<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: Sebastian Schaffert <schaffert@google.com>

#include "SourcesToolService.h"

#include <booster/log.h>
#include <cppcms/service.h>
#include <cppcms/http_response.h>
#include <cppcms/http_request.h>
#include <cppcms/url_dispatcher.h>
#include <cppcms/url_mapper.h>
#include <fstream>

#include "SerializerTSV.h"
#include "SerializerJSON.h"
#include "Persistence.h"
#include "Membuf.h"
#include "Version.h"

#define TIMING(message, begin, end) \
    BOOSTER_NOTICE("sourcestool") \
        << request().remote_addr() << ": " \
        << (message) << " time: " \
        << 1000 * (static_cast<double>(end - begin) / CLOCKS_PER_SEC) \
        << "ms" << std::endl;

// initialise static counters for status reports
time_t SourcesToolService::startupTime = std::time(NULL);
int64_t SourcesToolService::reqGetEntityCount = 0;
int64_t SourcesToolService::reqGetRandomCount = 0;
int64_t SourcesToolService::reqGetStatementCount = 0;
int64_t SourcesToolService::reqUpdateStatementCount = 0;
int64_t SourcesToolService::reqStatusCount = 0;

// format a time_t using ISO8601 GMT time
inline std::string formatGMT(time_t* time) {
    char result[128];
    std::strftime(result, 128, "%Y-%m-%dT%H:%M:%SZ", gmtime(time));
    return std::string(result);
}

// represent memory statistics (used for status)
struct memstat {
    double rss, shared_mem, private_mem;
};

// read memory statistics from /proc (used for status)
inline memstat getMemStat() {
    int tSize = 0, resident = 0, share = 0;
    std::ifstream buffer("/proc/self/statm");
    buffer >> tSize >> resident >> share;
    buffer.close();

    struct memstat result;

    long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
    result.rss = resident * page_size_kb;
    result.shared_mem = share * page_size_kb;
    result.private_mem = result.rss - result.shared_mem;

    return result;
}

// initialise service mappings from URLs to methods
SourcesToolService::SourcesToolService(cppcms::service &srv)
        : cppcms::application(srv), backend(settings()["database"]) {

    dispatcher().assign("/entities/(Q\\d+)",
            &SourcesToolService::getEntityByQID, this, 1);
    mapper().assign("entity_by_qid", "/entities/{1}");

    // map request to random entity selector
    dispatcher().assign("/entities/any",
            &SourcesToolService::getRandomEntity, this);
    mapper().assign("entity_by_topic_user", "/entities/any");

    // map GET and POST requests to /entities/<QID> to the respective handlers
    // we use a helper function to distinguish both cases, since cppcms
    // currently does not really support REST
    dispatcher().assign("/statements/(\\d+)",
            &SourcesToolService::handleGetPostStatement, this, 1);
    mapper().assign("stmt_by_id", "/statements/{1}");

    dispatcher().assign("/statements/any",
            &SourcesToolService::getRandomStatements, this);
    mapper().assign("stmt_by_random", "/statements/any");

    dispatcher().assign("/import",
            &SourcesToolService::importStatements, this);
    mapper().assign("import", "/import");

    dispatcher().assign("/delete",
                        &SourcesToolService::deleteStatements, this);
    mapper().assign("delete", "/delete");

    dispatcher().assign("/datasets/all",
                            &SourcesToolService::getAllDatasets, this);
        mapper().assign("datasets_all", "/datasets/all");

    dispatcher().assign("/status",
                        &SourcesToolService::getStatus, this);
    mapper().assign("status", "/status");

    dispatcher().assign("/dashboard/activitylog",
                        &SourcesToolService::getActivityLog, this);
    mapper().assign("activitylog", "/dashboard/activitylog");
}

void SourcesToolService::handleGetPostStatement(std::string stid) {
    if (request().request_method() == "POST") {
        approveStatement(std::stoll(stid));
    } else {
        getStatement(std::stoll(stid));
    }
}

void SourcesToolService::getEntityByQID(std::string qid) {
    clock_t begin = std::clock();

    std::vector<Statement> statements = backend.getStatementsByQID(cache(), qid, true, request().get("dataset"));

    addCORSHeaders();
    addVersionHeaders();

    if (statements.size() > 0) {
        serializeStatements(statements);
    } else {
        response().status(404, "no statements found for entity "+qid);
    }

    reqGetEntityCount++;

    clock_t end = std::clock();
    TIMING("GET /entities/" + qid, begin, end);
}

void SourcesToolService::getRandomEntity() {
    clock_t begin = std::clock();

    addCORSHeaders();
    addVersionHeaders();

    try {
        std::vector<Statement> statements = backend.getStatementsByRandomQID(cache(), true, request().get("dataset"));
        serializeStatements(statements);
    } catch(PersistenceException const &e) {
        response().status(404, "no random unapproved entity found");
    }

    reqGetRandomCount++;

    clock_t end = std::clock();
    TIMING("GET /entities/any", begin, end);
}

void SourcesToolService::approveStatement(int64_t stid) {
    clock_t begin = std::clock();

    ApprovalState state;

    addCORSHeaders();
    addVersionHeaders();

    // return 403 forbidden when there is no user given or the username is too
    // long for the database
    if (request().get("user") == "" || request().get("user").length() > 64) {
        response().status(403, "Forbidden: invalid or missing user");
        return;
    }

    // check if statement exists and update it with new state
    try {
        backend.updateStatement(cache(), stid, stateFromString(request().get("state")), request().get("user"));
    } catch(PersistenceException const &e) {
        response().status(404, "Statement not found");
    } catch(InvalidApprovalState const &e) {
        response().status(400, "Bad Request: invalid or missing state parameter");
    }

    reqUpdateStatementCount++;

    clock_t end = std::clock();
    TIMING("POST /statements/" + std::to_string(stid), begin, end);
}

void SourcesToolService::getStatement(int64_t stid) {
    clock_t begin = std::clock();

    addCORSHeaders();
    addVersionHeaders();

    // query for statement, wrap it in a vector and return it
    try {
        std::vector<Statement> statements = { backend.getStatementByID(cache(), stid) };
        serializeStatements(statements);
    } catch(PersistenceException const &e) {
        std::cerr << "error: " << e.what() << std::endl;
        response().status(404, "Statement not found");
    }

    reqGetStatementCount++;

    clock_t end = std::clock();
    TIMING("GET /statements/" + std::to_string(stid), begin, end);
}

void SourcesToolService::getRandomStatements() {
    clock_t begin = std::clock();

    int count = 10;
    if (request().get("count") != "") {
        count = std::stoi(request().get("count"));
    }

    addCORSHeaders();
    addVersionHeaders();

    serializeStatements(backend.getRandomStatements(cache(), count, true));

    clock_t end = std::clock();
    TIMING("GET /statements/any", begin, end);
}

void SourcesToolService::getStatus() {
    clock_t begin = std::clock();

    addCORSHeaders();
    addVersionHeaders();

    cppcms::json::value result;

    Status status = backend.getStatus(cache());

    result["statements"]["total"] = status.getStatements();
    result["statements"]["approved"] = status.getApproved();
    result["statements"]["unapproved"] = status.getUnapproved();
    result["statements"]["blacklisted"] = status.getBlacklisted();
    result["statements"]["duplicate"] = status.getDuplicate();
    result["statements"]["wrong"] = status.getWrong();

    cppcms::json::array topusers;
    for (auto entry : status.getTopUsers()) {
        cppcms::json::value v;
        v["name"] = entry.first;
        v["activities"] = entry.second;
        topusers.push_back(v);
    }
    result["topusers"] = topusers;

    // system information
    result["system"]["startup"] = formatGMT(&SourcesToolService::startupTime);
    result["system"]["version"] = std::string(GIT_SHA1);
    result["system"]["cache_hits"] = backend.getCacheHits();
    result["system"]["cache_misses"] = backend.getCacheMisses();

    struct memstat meminfo = getMemStat();
    result["system"]["shared_mem"] = meminfo.shared_mem;
    result["system"]["private_mem"] = meminfo.private_mem;
    result["system"]["rss"] = meminfo.rss;

    // request statistics
    result["requests"]["getentity"] = reqGetEntityCount;
    result["requests"]["getrandom"] = reqGetRandomCount;
    result["requests"]["getstatement"] = reqGetStatementCount;
    result["requests"]["updatestatement"] = reqUpdateStatementCount;
    result["requests"]["getstatus"] = reqStatusCount;

    response().content_type("application/json");
    result.save(response().out(), cppcms::json::readable);

    reqStatusCount++;

    clock_t end = std::clock();
    TIMING("GET /status", begin, end);
}

void SourcesToolService::serializeStatements(const std::vector<Statement> &statements) {
    if(request().http_accept() == "text/vnd.wikidata+tsv"
            || request().http_accept() == "text/tsv") {
        response().content_type("text/vnd.wikidata+tsv");

        Serializer::writeTSV(statements.cbegin(), statements.cend(), &response().out());
    } else if(request().http_accept() == "application/vnd.wikidata+json") {
        response().content_type("application/vnd.wikidata+json");

        Serializer::writeWikidataJSON(statements.cbegin(), statements.cend(), &response().out());
    } else {
        response().content_type("application/vnd.wikidata.envelope+json");

        Serializer::writeEnvelopeJSON(statements.cbegin(), statements.cend(), &response().out());
    }
}

void SourcesToolService::importStatements() {
    addVersionHeaders();

    if (request().request_method() == "POST") {
        clock_t begin = std::clock();

        // check if token matches
        if (request().get("token") != settings()["token"].str()) {
            response().status(401, "Invalid authorization token");
            return;
        }

        if (request().get("dataset") == "") {
            response().status(400, "Missing argument: dataset");
            return;
        }

        // check if content is gzipped
        bool gzip = false;
        if (request().get("gzip") == "true") {
            gzip = true;
        }

        bool dedup = true;
        if (request().get("deduplicate") == "false") {
            dedup = false;
        }

        // wrap raw post data into a memory stream
        Membuf body(request().raw_post_data());
        std::istream in(&body);

        // import statements
        int64_t count = backend.importStatements(
                cache(), in, request().get("dataset"), gzip, dedup);

        clock_t end = std::clock();

        cppcms::json::value result;
        result["count"] = count;
        result["time"] = 1000 * (static_cast<double>(end - begin) / CLOCKS_PER_SEC);

        response().content_type("application/json");
        result.save(response().out(), cppcms::json::readable);

        TIMING("POST /import", begin, end);
    } else {
        response().status(405, "Method not allowed");
        response().set_header("Allow", "POST");
    }
}

void SourcesToolService::getAllDatasets() {
	addCORSHeaders();
	addVersionHeaders();

	std::vector<std::string> datasets = backend.getDatasets(cache());

	cppcms::json::value result;
	for(std::string id : datasets) {
        result[id]["id"] = id;
	}

    response().content_type("application/json");
    result.save(response().out(), cppcms::json::readable);
}

void SourcesToolService::deleteStatements() {
    addVersionHeaders();

    if (request().request_method() == "POST") {

        // check if token matches
        if (request().get("token") != settings()["token"].str()) {
            response().status(401, "Invalid authorization token");
            return;
        }

        clock_t begin = std::clock();

        // check if statement exists and update it with new state
        try {
            backend.deleteStatements(cache(), stateFromString(request().get("state")));
        } catch(PersistenceException const &e) {
            response().status(404, "Could not delete statements");
        } catch(InvalidApprovalState const &e) {
            response().status(400, "Bad Request: invalid or missing state parameter");
        }

        clock_t end = std::clock();

        TIMING("POST /delete", begin, end);
    } else {
        response().status(405, "Method not allowed");
        response().set_header("Allow", "POST");
    }
}

void SourcesToolService::addCORSHeaders() {
    response().set_header("Access-Control-Allow-Origin", "*");
}

void SourcesToolService::addVersionHeaders() {
    response().set_header("X-Powered-By", std::string("Wikidata Sources Tool/") + GIT_SHA1);
}

void SourcesToolService::getActivityLog() {
    clock_t begin = std::clock();

    addCORSHeaders();
    addVersionHeaders();

    cppcms::json::value result;

    Dashboard::ActivityLog activities = backend.getActivityLog(cache());

    std::vector<std::string> users(activities.getUsers().begin(), activities.getUsers().end());

    result["users"] = users;
    for(int i=0; i< activities.getActivities().size(); i++) {
        Dashboard::ActivityEntry entry = activities.getActivities()[i];

        if (entry.date != "") {
            result["approved"][i][0] = entry.date;
            for (int j = 0; j < users.size(); j++) {
                if (entry.approved.find(users[j]) != entry.approved.end()) {
                    result["approved"][i][j + 1] = entry.approved[users[j]];
                } else {
                    result["approved"][i][j + 1] = 0;
                }
            }

            result["rejected"][i][0] = entry.date;
            for (int j = 0; j < users.size(); j++) {
                if (entry.rejected.find(users[j]) != entry.rejected.end()) {
                    result["rejected"][i][j + 1] = entry.rejected[users[j]];
                } else {
                    result["rejected"][i][j + 1] = 0;
                }
            }
        }

    }

    response().content_type("application/json");
    result.save(response().out(), cppcms::json::readable);

    reqStatusCount++;

    clock_t end = std::clock();
    TIMING("GET /dashboard/activitylog", begin, end);
}
<commit_msg>Adds dataset to the import response<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: Sebastian Schaffert <schaffert@google.com>

#include "SourcesToolService.h"

#include <booster/log.h>
#include <cppcms/service.h>
#include <cppcms/http_response.h>
#include <cppcms/http_request.h>
#include <cppcms/url_dispatcher.h>
#include <cppcms/url_mapper.h>
#include <fstream>

#include "SerializerTSV.h"
#include "SerializerJSON.h"
#include "Persistence.h"
#include "Membuf.h"
#include "Version.h"

#define TIMING(message, begin, end) \
    BOOSTER_NOTICE("sourcestool") \
        << request().remote_addr() << ": " \
        << (message) << " time: " \
        << 1000 * (static_cast<double>(end - begin) / CLOCKS_PER_SEC) \
        << "ms" << std::endl;

// initialise static counters for status reports
time_t SourcesToolService::startupTime = std::time(NULL);
int64_t SourcesToolService::reqGetEntityCount = 0;
int64_t SourcesToolService::reqGetRandomCount = 0;
int64_t SourcesToolService::reqGetStatementCount = 0;
int64_t SourcesToolService::reqUpdateStatementCount = 0;
int64_t SourcesToolService::reqStatusCount = 0;

// format a time_t using ISO8601 GMT time
inline std::string formatGMT(time_t* time) {
    char result[128];
    std::strftime(result, 128, "%Y-%m-%dT%H:%M:%SZ", gmtime(time));
    return std::string(result);
}

// represent memory statistics (used for status)
struct memstat {
    double rss, shared_mem, private_mem;
};

// read memory statistics from /proc (used for status)
inline memstat getMemStat() {
    int tSize = 0, resident = 0, share = 0;
    std::ifstream buffer("/proc/self/statm");
    buffer >> tSize >> resident >> share;
    buffer.close();

    struct memstat result;

    long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
    result.rss = resident * page_size_kb;
    result.shared_mem = share * page_size_kb;
    result.private_mem = result.rss - result.shared_mem;

    return result;
}

// initialise service mappings from URLs to methods
SourcesToolService::SourcesToolService(cppcms::service &srv)
        : cppcms::application(srv), backend(settings()["database"]) {

    dispatcher().assign("/entities/(Q\\d+)",
            &SourcesToolService::getEntityByQID, this, 1);
    mapper().assign("entity_by_qid", "/entities/{1}");

    // map request to random entity selector
    dispatcher().assign("/entities/any",
            &SourcesToolService::getRandomEntity, this);
    mapper().assign("entity_by_topic_user", "/entities/any");

    // map GET and POST requests to /entities/<QID> to the respective handlers
    // we use a helper function to distinguish both cases, since cppcms
    // currently does not really support REST
    dispatcher().assign("/statements/(\\d+)",
            &SourcesToolService::handleGetPostStatement, this, 1);
    mapper().assign("stmt_by_id", "/statements/{1}");

    dispatcher().assign("/statements/any",
            &SourcesToolService::getRandomStatements, this);
    mapper().assign("stmt_by_random", "/statements/any");

    dispatcher().assign("/import",
            &SourcesToolService::importStatements, this);
    mapper().assign("import", "/import");

    dispatcher().assign("/delete",
                        &SourcesToolService::deleteStatements, this);
    mapper().assign("delete", "/delete");

    dispatcher().assign("/datasets/all",
                            &SourcesToolService::getAllDatasets, this);
        mapper().assign("datasets_all", "/datasets/all");

    dispatcher().assign("/status",
                        &SourcesToolService::getStatus, this);
    mapper().assign("status", "/status");

    dispatcher().assign("/dashboard/activitylog",
                        &SourcesToolService::getActivityLog, this);
    mapper().assign("activitylog", "/dashboard/activitylog");
}

void SourcesToolService::handleGetPostStatement(std::string stid) {
    if (request().request_method() == "POST") {
        approveStatement(std::stoll(stid));
    } else {
        getStatement(std::stoll(stid));
    }
}

void SourcesToolService::getEntityByQID(std::string qid) {
    clock_t begin = std::clock();

    std::vector<Statement> statements = backend.getStatementsByQID(cache(), qid, true, request().get("dataset"));

    addCORSHeaders();
    addVersionHeaders();

    if (statements.size() > 0) {
        serializeStatements(statements);
    } else {
        response().status(404, "no statements found for entity "+qid);
    }

    reqGetEntityCount++;

    clock_t end = std::clock();
    TIMING("GET /entities/" + qid, begin, end);
}

void SourcesToolService::getRandomEntity() {
    clock_t begin = std::clock();

    addCORSHeaders();
    addVersionHeaders();

    try {
        std::vector<Statement> statements = backend.getStatementsByRandomQID(cache(), true, request().get("dataset"));
        serializeStatements(statements);
    } catch(PersistenceException const &e) {
        response().status(404, "no random unapproved entity found");
    }

    reqGetRandomCount++;

    clock_t end = std::clock();
    TIMING("GET /entities/any", begin, end);
}

void SourcesToolService::approveStatement(int64_t stid) {
    clock_t begin = std::clock();

    ApprovalState state;

    addCORSHeaders();
    addVersionHeaders();

    // return 403 forbidden when there is no user given or the username is too
    // long for the database
    if (request().get("user") == "" || request().get("user").length() > 64) {
        response().status(403, "Forbidden: invalid or missing user");
        return;
    }

    // check if statement exists and update it with new state
    try {
        backend.updateStatement(cache(), stid, stateFromString(request().get("state")), request().get("user"));
    } catch(PersistenceException const &e) {
        response().status(404, "Statement not found");
    } catch(InvalidApprovalState const &e) {
        response().status(400, "Bad Request: invalid or missing state parameter");
    }

    reqUpdateStatementCount++;

    clock_t end = std::clock();
    TIMING("POST /statements/" + std::to_string(stid), begin, end);
}

void SourcesToolService::getStatement(int64_t stid) {
    clock_t begin = std::clock();

    addCORSHeaders();
    addVersionHeaders();

    // query for statement, wrap it in a vector and return it
    try {
        std::vector<Statement> statements = { backend.getStatementByID(cache(), stid) };
        serializeStatements(statements);
    } catch(PersistenceException const &e) {
        std::cerr << "error: " << e.what() << std::endl;
        response().status(404, "Statement not found");
    }

    reqGetStatementCount++;

    clock_t end = std::clock();
    TIMING("GET /statements/" + std::to_string(stid), begin, end);
}

void SourcesToolService::getRandomStatements() {
    clock_t begin = std::clock();

    int count = 10;
    if (request().get("count") != "") {
        count = std::stoi(request().get("count"));
    }

    addCORSHeaders();
    addVersionHeaders();

    serializeStatements(backend.getRandomStatements(cache(), count, true));

    clock_t end = std::clock();
    TIMING("GET /statements/any", begin, end);
}

void SourcesToolService::getStatus() {
    clock_t begin = std::clock();

    addCORSHeaders();
    addVersionHeaders();

    cppcms::json::value result;

    Status status = backend.getStatus(cache());

    result["statements"]["total"] = status.getStatements();
    result["statements"]["approved"] = status.getApproved();
    result["statements"]["unapproved"] = status.getUnapproved();
    result["statements"]["blacklisted"] = status.getBlacklisted();
    result["statements"]["duplicate"] = status.getDuplicate();
    result["statements"]["wrong"] = status.getWrong();

    cppcms::json::array topusers;
    for (auto entry : status.getTopUsers()) {
        cppcms::json::value v;
        v["name"] = entry.first;
        v["activities"] = entry.second;
        topusers.push_back(v);
    }
    result["topusers"] = topusers;

    // system information
    result["system"]["startup"] = formatGMT(&SourcesToolService::startupTime);
    result["system"]["version"] = std::string(GIT_SHA1);
    result["system"]["cache_hits"] = backend.getCacheHits();
    result["system"]["cache_misses"] = backend.getCacheMisses();

    struct memstat meminfo = getMemStat();
    result["system"]["shared_mem"] = meminfo.shared_mem;
    result["system"]["private_mem"] = meminfo.private_mem;
    result["system"]["rss"] = meminfo.rss;

    // request statistics
    result["requests"]["getentity"] = reqGetEntityCount;
    result["requests"]["getrandom"] = reqGetRandomCount;
    result["requests"]["getstatement"] = reqGetStatementCount;
    result["requests"]["updatestatement"] = reqUpdateStatementCount;
    result["requests"]["getstatus"] = reqStatusCount;

    response().content_type("application/json");
    result.save(response().out(), cppcms::json::readable);

    reqStatusCount++;

    clock_t end = std::clock();
    TIMING("GET /status", begin, end);
}

void SourcesToolService::serializeStatements(const std::vector<Statement> &statements) {
    if(request().http_accept() == "text/vnd.wikidata+tsv"
            || request().http_accept() == "text/tsv") {
        response().content_type("text/vnd.wikidata+tsv");

        Serializer::writeTSV(statements.cbegin(), statements.cend(), &response().out());
    } else if(request().http_accept() == "application/vnd.wikidata+json") {
        response().content_type("application/vnd.wikidata+json");

        Serializer::writeWikidataJSON(statements.cbegin(), statements.cend(), &response().out());
    } else {
        response().content_type("application/vnd.wikidata.envelope+json");

        Serializer::writeEnvelopeJSON(statements.cbegin(), statements.cend(), &response().out());
    }
}

void SourcesToolService::importStatements() {
    addVersionHeaders();

    if (request().request_method() == "POST") {
        clock_t begin = std::clock();

        // check if token matches
        if (request().get("token") != settings()["token"].str()) {
            response().status(401, "Invalid authorization token");
            return;
        }

        std::string dataset = request().get("dataset");
        if (dataset == "") {
            response().status(400, "Missing argument: dataset");
            return;
        }

        // check if content is gzipped
        bool gzip = false;
        if (request().get("gzip") == "true") {
            gzip = true;
        }

        bool dedup = true;
        if (request().get("deduplicate") == "false") {
            dedup = false;
        }

        // wrap raw post data into a memory stream
        Membuf body(request().raw_post_data());
        std::istream in(&body);

        // import statements
        int64_t count = backend.importStatements(
                cache(), in, dataset, gzip, dedup);

        clock_t end = std::clock();

        cppcms::json::value result;
        result["count"] = count;
        result["time"] = 1000 * (static_cast<double>(end - begin) / CLOCKS_PER_SEC);
        result["dataset"] = dataset;

        response().content_type("application/json");
        result.save(response().out(), cppcms::json::readable);

        TIMING("POST /import", begin, end);
    } else {
        response().status(405, "Method not allowed");
        response().set_header("Allow", "POST");
    }
}

void SourcesToolService::getAllDatasets() {
	addCORSHeaders();
	addVersionHeaders();

	std::vector<std::string> datasets = backend.getDatasets(cache());

	cppcms::json::value result;
	for(std::string id : datasets) {
        result[id]["id"] = id;
	}

    response().content_type("application/json");
    result.save(response().out(), cppcms::json::readable);
}

void SourcesToolService::deleteStatements() {
    addVersionHeaders();

    if (request().request_method() == "POST") {

        // check if token matches
        if (request().get("token") != settings()["token"].str()) {
            response().status(401, "Invalid authorization token");
            return;
        }

        clock_t begin = std::clock();

        // check if statement exists and update it with new state
        try {
            backend.deleteStatements(cache(), stateFromString(request().get("state")));
        } catch(PersistenceException const &e) {
            response().status(404, "Could not delete statements");
        } catch(InvalidApprovalState const &e) {
            response().status(400, "Bad Request: invalid or missing state parameter");
        }

        clock_t end = std::clock();

        TIMING("POST /delete", begin, end);
    } else {
        response().status(405, "Method not allowed");
        response().set_header("Allow", "POST");
    }
}

void SourcesToolService::addCORSHeaders() {
    response().set_header("Access-Control-Allow-Origin", "*");
}

void SourcesToolService::addVersionHeaders() {
    response().set_header("X-Powered-By", std::string("Wikidata Sources Tool/") + GIT_SHA1);
}

void SourcesToolService::getActivityLog() {
    clock_t begin = std::clock();

    addCORSHeaders();
    addVersionHeaders();

    cppcms::json::value result;

    Dashboard::ActivityLog activities = backend.getActivityLog(cache());

    std::vector<std::string> users(activities.getUsers().begin(), activities.getUsers().end());

    result["users"] = users;
    for(int i=0; i< activities.getActivities().size(); i++) {
        Dashboard::ActivityEntry entry = activities.getActivities()[i];

        if (entry.date != "") {
            result["approved"][i][0] = entry.date;
            for (int j = 0; j < users.size(); j++) {
                if (entry.approved.find(users[j]) != entry.approved.end()) {
                    result["approved"][i][j + 1] = entry.approved[users[j]];
                } else {
                    result["approved"][i][j + 1] = 0;
                }
            }

            result["rejected"][i][0] = entry.date;
            for (int j = 0; j < users.size(); j++) {
                if (entry.rejected.find(users[j]) != entry.rejected.end()) {
                    result["rejected"][i][j + 1] = entry.rejected[users[j]];
                } else {
                    result["rejected"][i][j + 1] = 0;
                }
            }
        }

    }

    response().content_type("application/json");
    result.save(response().out(), cppcms::json::readable);

    reqStatusCount++;

    clock_t end = std::clock();
    TIMING("GET /dashboard/activitylog", begin, end);
}
<|endoftext|>


<commit_before>
#include "config.h"

#include "ambdec.h"

#include <cstring>
#include <cctype>

#include <limits>
#include <string>
#include <fstream>
#include <sstream>

#include "compat.h"

namespace {

int readline(std::istream &f, std::string &output)
{
    while(f.good() && f.peek() == '\n')
        f.ignore();

    std::getline(f, output);
    return !output.empty();
}

bool read_clipped_line(std::istream &f, std::string &buffer)
{
    while(readline(f, buffer))
    {
        std::size_t pos{0};
        while(pos < buffer.length() && std::isspace(buffer[pos]))
            pos++;
        buffer.erase(0, pos);

        std::size_t cmtpos{buffer.find_first_of('#')};
        if(cmtpos < buffer.length())
            buffer.resize(cmtpos);
        while(!buffer.empty() && std::isspace(buffer.back()))
            buffer.pop_back();

        if(!buffer.empty())
            return true;
    }
    return false;
}

std::string read_word(std::istream &f)
{
    std::string ret;
    f >> ret;
    return ret;
}

bool is_at_end(const std::string &buffer, std::size_t endpos)
{
    while(endpos < buffer.length() && std::isspace(buffer[endpos]))
        ++endpos;
    if(endpos < buffer.length())
        return false;
    return true;
}

bool load_ambdec_speakers(AmbDecConf *conf, std::istream &f, std::string &buffer)
{
    ALsizei cur = 0;
    while(cur < conf->NumSpeakers)
    {
        std::istringstream istr{buffer};

        std::string cmd = read_word(istr);
        if(cmd.empty())
        {
            if(!read_clipped_line(f, buffer))
            {
                ERR("Unexpected end of file\n");
                return false;
            }
            istr = std::istringstream{buffer};
            cmd = read_word(istr);
        }

        if(cmd == "add_spkr")
        {
            istr >> conf->Speakers[cur].Name;
            if(istr.fail()) WARN("Name not specified for speaker %u\n", cur+1);
            istr >> conf->Speakers[cur].Distance;
            if(istr.fail()) WARN("Distance not specified for speaker %u\n", cur+1);
            istr >> conf->Speakers[cur].Azimuth;
            if(istr.fail()) WARN("Azimuth not specified for speaker %u\n", cur+1);
            istr >> conf->Speakers[cur].Elevation;
            if(istr.fail()) WARN("Elevation not specified for speaker %u\n", cur+1);
            istr >> conf->Speakers[cur].Connection;
            if(istr.fail()) TRACE("Connection not specified for speaker %u\n", cur+1);

            cur++;
        }
        else
        {
            ERR("Unexpected speakers command: %s\n", cmd.c_str());
            return false;
        }

        istr.clear();
        std::streamsize endpos{istr.tellg()};
        if(!is_at_end(buffer, endpos))
        {
            ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
            return false;
        }
        buffer.clear();
    }

    return true;
}

bool load_ambdec_matrix(ALfloat *gains, ALfloat (*matrix)[MAX_AMBI_COEFFS], ALsizei maxrow, std::istream &f, std::string &buffer)
{
    bool gotgains = false;
    ALsizei cur = 0;
    while(cur < maxrow)
    {
        std::istringstream istr{buffer};
        std::string cmd;

        istr >> cmd;
        if(cmd.empty())
        {
            if(!read_clipped_line(f, buffer))
            {
                ERR("Unexpected end of file\n");
                return false;
            }
            istr = std::istringstream{buffer};
            istr >> cmd;
        }

        if(cmd == "order_gain")
        {
            ALuint curgain = 0;
            float value;
            while(istr.good())
            {
                istr >> value;
                if(istr.fail()) break;
                if(!istr.eof() && !std::isspace(istr.peek()))
                {
                    ERR("Extra junk on gain %u: %s\n", curgain+1, buffer.c_str()+istr.tellg());
                    return false;
                }
                if(curgain < MAX_AMBI_ORDER+1)
                    gains[curgain++] = value;
            }
            while(curgain < MAX_AMBI_ORDER+1)
                gains[curgain++] = 0.0f;
            gotgains = true;
        }
        else if(cmd == "add_row")
        {
            ALuint curidx = 0;
            float value;
            while(istr.good())
            {
                istr >> value;
                if(istr.fail()) break;
                if(!istr.eof() && !std::isspace(istr.peek()))
                {
                    ERR("Extra junk on matrix element %ux%u: %s\n", cur, curidx,
                        buffer.c_str()+istr.tellg());
                    return false;
                }
                if(curidx < MAX_AMBI_COEFFS)
                    matrix[cur][curidx++] = value;
            }
            while(curidx < MAX_AMBI_COEFFS)
                matrix[cur][curidx++] = 0.0f;
            cur++;
        }
        else
        {
            ERR("Unexpected matrix command: %s\n", cmd.c_str());
            return false;
        }

        istr.clear();
        std::streamsize endpos{istr.tellg()};
        if(!is_at_end(buffer, endpos))
        {
            ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
            return false;
        }
        buffer.clear();
    }

    if(!gotgains)
    {
        ERR("Matrix order_gain not specified\n");
        return false;
    }

    return true;
}

} // namespace

int AmbDecConf::load(const char *fname)
{
    al::ifstream f{fname};
    if(!f.is_open())
    {
        ERR("Failed to open: %s\n", fname);
        return 0;
    }

    std::string buffer;
    while(read_clipped_line(f, buffer))
    {
        std::istringstream istr{buffer};
        std::string command;

        istr >> command;
        if(command.empty())
        {
            ERR("Malformed line: %s\n", buffer.c_str());
            return 0;
        }

        if(command == "/description")
            istr >> Description;
        else if(command == "/version")
        {
            istr >> Version;
            if(!istr.eof() && !std::isspace(istr.peek()))
            {
                ERR("Extra junk after version: %s\n", buffer.c_str()+istr.tellg());
                return 0;
            }
            if(Version != 3)
            {
                ERR("Unsupported version: %u\n", Version);
                return 0;
            }
        }
        else if(command == "/dec/chan_mask")
        {
            istr >> std::hex >> ChanMask >> std::dec;
            if(!istr.eof() && !std::isspace(istr.peek()))
            {
                ERR("Extra junk after mask: %s\n", buffer.c_str()+istr.tellg());
                return 0;
            }
        }
        else if(command == "/dec/freq_bands")
        {
            istr >> FreqBands;
            if(!istr.eof() && !std::isspace(istr.peek()))
            {
                ERR("Extra junk after freq_bands: %s\n", buffer.c_str()+istr.tellg());
                return 0;
            }
            if(FreqBands != 1 && FreqBands != 2)
            {
                ERR("Invalid freq_bands value: %u\n", FreqBands);
                return 0;
            }
        }
        else if(command == "/dec/speakers")
        {
            istr >> NumSpeakers;
            if(!istr.eof() && !std::isspace(istr.peek()))
            {
                ERR("Extra junk after speakers: %s\n", buffer.c_str()+istr.tellg());
                return 0;
            }
            if(NumSpeakers > MAX_OUTPUT_CHANNELS)
            {
                ERR("Unsupported speaker count: %u\n", NumSpeakers);
                return 0;
            }
        }
        else if(command == "/dec/coeff_scale")
        {
            std::string scale = read_word(istr);
            if(scale == "n3d") CoeffScale = AmbDecScale::N3D;
            else if(scale == "sn3d") CoeffScale = AmbDecScale::SN3D;
            else if(scale == "fuma") CoeffScale = AmbDecScale::FuMa;
            else
            {
                ERR("Unsupported coeff scale: %s\n", scale.c_str());
                return 0;
            }
        }
        else if(command == "/opt/xover_freq")
        {
            istr >> XOverFreq;
            if(!istr.eof() && !std::isspace(istr.peek()))
            {
                ERR("Extra junk after xover_freq: %s\n", buffer.c_str()+istr.tellg());
                return 0;
            }
        }
        else if(command == "/opt/xover_ratio")
        {
            istr >> XOverRatio;
            if(!istr.eof() && !std::isspace(istr.peek()))
            {
                ERR("Extra junk after xover_ratio: %s\n", buffer.c_str()+istr.tellg());
                return 0;
            }
        }
        else if(command == "/opt/input_scale" || command == "/opt/nfeff_comp" ||
                command == "/opt/delay_comp" || command == "/opt/level_comp")
        {
            /* Unused */
            read_word(istr);
        }
        else if(command == "/speakers/{")
        {
            std::streamsize endpos{istr.tellg()};
            if(!is_at_end(buffer, endpos))
            {
                ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
                return 0;
            }
            buffer.clear();

            if(!load_ambdec_speakers(this, f, buffer))
                return 0;

            if(!read_clipped_line(f, buffer))
            {
                ERR("Unexpected end of file\n");
                return 0;
            }
            istr = std::istringstream{buffer};
            std::string endmark = read_word(istr);
            if(endmark != "/}")
            {
                ERR("Expected /} after speaker definitions, got %s\n", endmark.c_str());
                return 0;
            }
        }
        else if(command == "/lfmatrix/{" || command == "/hfmatrix/{" || command == "/matrix/{")
        {
            std::streamsize endpos{istr.tellg()};
            if(!is_at_end(buffer, endpos))
            {
                ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
                return 0;
            }
            buffer.clear();

            if(FreqBands == 1)
            {
                if(command != "/matrix/{")
                {
                    ERR("Unexpected \"%s\" type for a single-band decoder\n", command.c_str());
                    return 0;
                }
                if(!load_ambdec_matrix(HFOrderGain, HFMatrix, NumSpeakers, f, buffer))
                    return 0;
            }
            else
            {
                if(command == "/lfmatrix/{")
                {
                    if(!load_ambdec_matrix(LFOrderGain, LFMatrix, NumSpeakers, f, buffer))
                        return 0;
                }
                else if(command == "/hfmatrix/{")
                {
                    if(!load_ambdec_matrix(HFOrderGain, HFMatrix, NumSpeakers, f, buffer))
                        return 0;
                }
                else
                {
                    ERR("Unexpected \"%s\" type for a dual-band decoder\n", command.c_str());
                    return 0;
                }
            }

            if(!read_clipped_line(f, buffer))
            {
                ERR("Unexpected end of file\n");
                return 0;
            }
            istr = std::istringstream{buffer};
            std::string endmark = read_word(istr);
            if(endmark != "/}")
            {
                ERR("Expected /} after matrix definitions, got %s\n", endmark.c_str());
                return 0;
            }
        }
        else if(command == "/end")
        {
            std::streamsize endpos{istr.tellg()};
            if(!is_at_end(buffer, endpos))
            {
                ERR("Unexpected junk on end: %s\n", buffer.c_str()+endpos);
                return 0;
            }

            return 1;
        }
        else
        {
            ERR("Unexpected command: %s\n", command.c_str());
            return 0;
        }

        istr.clear();
        std::streamsize endpos{istr.tellg()};
        if(!is_at_end(buffer, endpos))
        {
            ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
            return 0;
        }
        buffer.clear();
    }
    ERR("Unexpected end of file\n");

    return 0;
}
<commit_msg>Avoid moving istringstreams<commit_after>
#include "config.h"

#include "ambdec.h"

#include <cstring>
#include <cctype>

#include <limits>
#include <string>
#include <fstream>
#include <sstream>

#include "compat.h"

namespace {

int readline(std::istream &f, std::string &output)
{
    while(f.good() && f.peek() == '\n')
        f.ignore();

    std::getline(f, output);
    return !output.empty();
}

bool read_clipped_line(std::istream &f, std::string &buffer)
{
    while(readline(f, buffer))
    {
        std::size_t pos{0};
        while(pos < buffer.length() && std::isspace(buffer[pos]))
            pos++;
        buffer.erase(0, pos);

        std::size_t cmtpos{buffer.find_first_of('#')};
        if(cmtpos < buffer.length())
            buffer.resize(cmtpos);
        while(!buffer.empty() && std::isspace(buffer.back()))
            buffer.pop_back();

        if(!buffer.empty())
            return true;
    }
    return false;
}

std::string read_word(std::istream &f)
{
    std::string ret;
    f >> ret;
    return ret;
}

bool is_at_end(const std::string &buffer, std::size_t endpos)
{
    while(endpos < buffer.length() && std::isspace(buffer[endpos]))
        ++endpos;
    if(endpos < buffer.length())
        return false;
    return true;
}

bool load_ambdec_speakers(AmbDecConf *conf, std::istream &f, std::string &buffer)
{
    ALsizei cur = 0;
    while(cur < conf->NumSpeakers)
    {
        std::istringstream istr{buffer};

        std::string cmd{read_word(istr)};
        if(cmd.empty())
        {
            if(!read_clipped_line(f, buffer))
            {
                ERR("Unexpected end of file\n");
                return false;
            }
            continue;
        }

        if(cmd == "add_spkr")
        {
            istr >> conf->Speakers[cur].Name;
            if(istr.fail()) WARN("Name not specified for speaker %u\n", cur+1);
            istr >> conf->Speakers[cur].Distance;
            if(istr.fail()) WARN("Distance not specified for speaker %u\n", cur+1);
            istr >> conf->Speakers[cur].Azimuth;
            if(istr.fail()) WARN("Azimuth not specified for speaker %u\n", cur+1);
            istr >> conf->Speakers[cur].Elevation;
            if(istr.fail()) WARN("Elevation not specified for speaker %u\n", cur+1);
            istr >> conf->Speakers[cur].Connection;
            if(istr.fail()) TRACE("Connection not specified for speaker %u\n", cur+1);

            cur++;
        }
        else
        {
            ERR("Unexpected speakers command: %s\n", cmd.c_str());
            return false;
        }

        istr.clear();
        std::streamsize endpos{istr.tellg()};
        if(!is_at_end(buffer, endpos))
        {
            ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
            return false;
        }
        buffer.clear();
    }

    return true;
}

bool load_ambdec_matrix(ALfloat *gains, ALfloat (*matrix)[MAX_AMBI_COEFFS], ALsizei maxrow, std::istream &f, std::string &buffer)
{
    bool gotgains = false;
    ALsizei cur = 0;
    while(cur < maxrow)
    {
        std::istringstream istr{buffer};

        std::string cmd{read_word(istr)};
        if(cmd.empty())
        {
            if(!read_clipped_line(f, buffer))
            {
                ERR("Unexpected end of file\n");
                return false;
            }
            continue;
        }

        if(cmd == "order_gain")
        {
            ALuint curgain = 0;
            float value;
            while(istr.good())
            {
                istr >> value;
                if(istr.fail()) break;
                if(!istr.eof() && !std::isspace(istr.peek()))
                {
                    ERR("Extra junk on gain %u: %s\n", curgain+1, buffer.c_str()+istr.tellg());
                    return false;
                }
                if(curgain < MAX_AMBI_ORDER+1)
                    gains[curgain++] = value;
            }
            while(curgain < MAX_AMBI_ORDER+1)
                gains[curgain++] = 0.0f;
            gotgains = true;
        }
        else if(cmd == "add_row")
        {
            ALuint curidx = 0;
            float value;
            while(istr.good())
            {
                istr >> value;
                if(istr.fail()) break;
                if(!istr.eof() && !std::isspace(istr.peek()))
                {
                    ERR("Extra junk on matrix element %ux%u: %s\n", cur, curidx,
                        buffer.c_str()+istr.tellg());
                    return false;
                }
                if(curidx < MAX_AMBI_COEFFS)
                    matrix[cur][curidx++] = value;
            }
            while(curidx < MAX_AMBI_COEFFS)
                matrix[cur][curidx++] = 0.0f;
            cur++;
        }
        else
        {
            ERR("Unexpected matrix command: %s\n", cmd.c_str());
            return false;
        }

        istr.clear();
        std::streamsize endpos{istr.tellg()};
        if(!is_at_end(buffer, endpos))
        {
            ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
            return false;
        }
        buffer.clear();
    }

    if(!gotgains)
    {
        ERR("Matrix order_gain not specified\n");
        return false;
    }

    return true;
}

} // namespace

int AmbDecConf::load(const char *fname)
{
    al::ifstream f{fname};
    if(!f.is_open())
    {
        ERR("Failed to open: %s\n", fname);
        return 0;
    }

    std::string buffer;
    while(read_clipped_line(f, buffer))
    {
        std::istringstream istr{buffer};

        std::string command{read_word(istr)};
        if(command.empty())
        {
            ERR("Malformed line: %s\n", buffer.c_str());
            return 0;
        }

        if(command == "/description")
            istr >> Description;
        else if(command == "/version")
        {
            istr >> Version;
            if(!istr.eof() && !std::isspace(istr.peek()))
            {
                ERR("Extra junk after version: %s\n", buffer.c_str()+istr.tellg());
                return 0;
            }
            if(Version != 3)
            {
                ERR("Unsupported version: %u\n", Version);
                return 0;
            }
        }
        else if(command == "/dec/chan_mask")
        {
            istr >> std::hex >> ChanMask >> std::dec;
            if(!istr.eof() && !std::isspace(istr.peek()))
            {
                ERR("Extra junk after mask: %s\n", buffer.c_str()+istr.tellg());
                return 0;
            }
        }
        else if(command == "/dec/freq_bands")
        {
            istr >> FreqBands;
            if(!istr.eof() && !std::isspace(istr.peek()))
            {
                ERR("Extra junk after freq_bands: %s\n", buffer.c_str()+istr.tellg());
                return 0;
            }
            if(FreqBands != 1 && FreqBands != 2)
            {
                ERR("Invalid freq_bands value: %u\n", FreqBands);
                return 0;
            }
        }
        else if(command == "/dec/speakers")
        {
            istr >> NumSpeakers;
            if(!istr.eof() && !std::isspace(istr.peek()))
            {
                ERR("Extra junk after speakers: %s\n", buffer.c_str()+istr.tellg());
                return 0;
            }
            if(NumSpeakers > MAX_OUTPUT_CHANNELS)
            {
                ERR("Unsupported speaker count: %u\n", NumSpeakers);
                return 0;
            }
        }
        else if(command == "/dec/coeff_scale")
        {
            std::string scale = read_word(istr);
            if(scale == "n3d") CoeffScale = AmbDecScale::N3D;
            else if(scale == "sn3d") CoeffScale = AmbDecScale::SN3D;
            else if(scale == "fuma") CoeffScale = AmbDecScale::FuMa;
            else
            {
                ERR("Unsupported coeff scale: %s\n", scale.c_str());
                return 0;
            }
        }
        else if(command == "/opt/xover_freq")
        {
            istr >> XOverFreq;
            if(!istr.eof() && !std::isspace(istr.peek()))
            {
                ERR("Extra junk after xover_freq: %s\n", buffer.c_str()+istr.tellg());
                return 0;
            }
        }
        else if(command == "/opt/xover_ratio")
        {
            istr >> XOverRatio;
            if(!istr.eof() && !std::isspace(istr.peek()))
            {
                ERR("Extra junk after xover_ratio: %s\n", buffer.c_str()+istr.tellg());
                return 0;
            }
        }
        else if(command == "/opt/input_scale" || command == "/opt/nfeff_comp" ||
                command == "/opt/delay_comp" || command == "/opt/level_comp")
        {
            /* Unused */
            read_word(istr);
        }
        else if(command == "/speakers/{")
        {
            std::streamsize endpos{istr.tellg()};
            if(!is_at_end(buffer, endpos))
            {
                ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
                return 0;
            }
            buffer.clear();

            if(!load_ambdec_speakers(this, f, buffer))
                return 0;

            if(!read_clipped_line(f, buffer))
            {
                ERR("Unexpected end of file\n");
                return 0;
            }
            std::istringstream istr2{buffer};
            std::string endmark{read_word(istr2)};
            if(endmark != "/}")
            {
                ERR("Expected /} after speaker definitions, got %s\n", endmark.c_str());
                return 0;
            }
            istr.swap(istr2);
        }
        else if(command == "/lfmatrix/{" || command == "/hfmatrix/{" || command == "/matrix/{")
        {
            std::streamsize endpos{istr.tellg()};
            if(!is_at_end(buffer, endpos))
            {
                ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
                return 0;
            }
            buffer.clear();

            if(FreqBands == 1)
            {
                if(command != "/matrix/{")
                {
                    ERR("Unexpected \"%s\" type for a single-band decoder\n", command.c_str());
                    return 0;
                }
                if(!load_ambdec_matrix(HFOrderGain, HFMatrix, NumSpeakers, f, buffer))
                    return 0;
            }
            else
            {
                if(command == "/lfmatrix/{")
                {
                    if(!load_ambdec_matrix(LFOrderGain, LFMatrix, NumSpeakers, f, buffer))
                        return 0;
                }
                else if(command == "/hfmatrix/{")
                {
                    if(!load_ambdec_matrix(HFOrderGain, HFMatrix, NumSpeakers, f, buffer))
                        return 0;
                }
                else
                {
                    ERR("Unexpected \"%s\" type for a dual-band decoder\n", command.c_str());
                    return 0;
                }
            }

            if(!read_clipped_line(f, buffer))
            {
                ERR("Unexpected end of file\n");
                return 0;
            }
            std::istringstream istr2{buffer};
            std::string endmark{read_word(istr2)};
            if(endmark != "/}")
            {
                ERR("Expected /} after matrix definitions, got %s\n", endmark.c_str());
                return 0;
            }
            istr.swap(istr2);
        }
        else if(command == "/end")
        {
            std::streamsize endpos{istr.tellg()};
            if(!is_at_end(buffer, endpos))
            {
                ERR("Unexpected junk on end: %s\n", buffer.c_str()+endpos);
                return 0;
            }

            return 1;
        }
        else
        {
            ERR("Unexpected command: %s\n", command.c_str());
            return 0;
        }

        istr.clear();
        std::streamsize endpos{istr.tellg()};
        if(!is_at_end(buffer, endpos))
        {
            ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
            return 0;
        }
        buffer.clear();
    }
    ERR("Unexpected end of file\n");

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "app/l10n_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/account_screen.h"
#include "chrome/browser/chromeos/login/eula_view.h"
#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "chrome/browser/chromeos/login/login_screen.h"
#include "chrome/browser/chromeos/login/mock_update_screen.h"
#include "chrome/browser/chromeos/login/network_screen.h"
#include "chrome/browser/chromeos/login/network_selection_view.h"
#include "chrome/browser/chromeos/login/user_image_screen.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/test/ui_test_utils.h"
#include "grit/generated_resources.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "unicode/locid.h"
#include "views/accelerator.h"

namespace {

template <class T>
class MockOutShowHide : public T {
 public:
  template <class P> MockOutShowHide(P p) : T(p) {}
  template <class P1, class P2> MockOutShowHide(P1 p1, P2 p2) : T(p1, p2) {}
  MOCK_METHOD0(Show, void());
  MOCK_METHOD0(Hide, void());
};

template <class T>
struct CreateMockWizardScreenHelper {
  static MockOutShowHide<T>* Create(WizardController* wizard);
};

template <class T> MockOutShowHide<T>*
CreateMockWizardScreenHelper<T>::Create(WizardController* wizard) {
  return new MockOutShowHide<T>(wizard);
}

template <> MockOutShowHide<chromeos::NetworkScreen>*
CreateMockWizardScreenHelper<chromeos::NetworkScreen>::Create(
    WizardController* wizard) {
  return new MockOutShowHide<chromeos::NetworkScreen>(wizard);
}

#define MOCK(mock_var, screen_name, mocked_class)                              \
  mock_var = CreateMockWizardScreenHelper<mocked_class>::Create(controller()); \
  controller()->screen_name.reset(mock_var);                                   \
  EXPECT_CALL(*mock_var, Show()).Times(0);                                     \
  EXPECT_CALL(*mock_var, Hide()).Times(0);

}  // namespace

class WizardControllerTest : public chromeos::WizardInProcessBrowserTest {
 protected:
  WizardControllerTest() : chromeos::WizardInProcessBrowserTest(
      WizardController::kTestNoScreenName) {}
  virtual ~WizardControllerTest() {}

 private:
  DISALLOW_COPY_AND_ASSIGN(WizardControllerTest);
};

IN_PROC_BROWSER_TEST_F(WizardControllerTest, SwitchLanguage) {
  WizardController* const wizard = controller();
  ASSERT_TRUE(wizard != NULL);
  wizard->ShowFirstScreen(WizardController::kNetworkScreenName);
  views::View* current_screen = wizard->contents();
  ASSERT_TRUE(current_screen != NULL);

  // Checking the default locale. Provided that the profile is cleared in SetUp.
  EXPECT_EQ("en-US", g_browser_process->GetApplicationLocale());
  EXPECT_STREQ("en", icu::Locale::getDefault().getLanguage());
  EXPECT_FALSE(base::i18n::IsRTL());
  const std::wstring en_str = l10n_util::GetString(IDS_NETWORK_SELECTION_TITLE);

  chromeos::LanguageSwitchMenu::SwitchLanguage("fr");
  EXPECT_EQ("fr", g_browser_process->GetApplicationLocale());
  EXPECT_STREQ("fr", icu::Locale::getDefault().getLanguage());
  EXPECT_FALSE(base::i18n::IsRTL());
  const std::wstring fr_str = l10n_util::GetString(IDS_NETWORK_SELECTION_TITLE);

  EXPECT_NE(en_str, fr_str);

  chromeos::LanguageSwitchMenu::SwitchLanguage("ar");
  EXPECT_EQ("ar", g_browser_process->GetApplicationLocale());
  EXPECT_STREQ("ar", icu::Locale::getDefault().getLanguage());
  EXPECT_TRUE(base::i18n::IsRTL());
  const std::wstring ar_str = l10n_util::GetString(IDS_NETWORK_SELECTION_TITLE);

  EXPECT_NE(fr_str, ar_str);
}

class WizardControllerFlowTest : public WizardControllerTest {
 protected:
  WizardControllerFlowTest() {}
  // Overriden from InProcessBrowserTest:
  virtual Browser* CreateBrowser(Profile* profile) {
    Browser* ret = WizardControllerTest::CreateBrowser(profile);

    // Make sure that OOBE is run as an "official" build.
    WizardController::default_controller()->is_official_build_ = true;

    // Set up the mocks for all screens.
    MOCK(mock_account_screen_, account_screen_, chromeos::AccountScreen);
    MOCK(mock_login_screen_, login_screen_, chromeos::LoginScreen);
    MOCK(mock_network_screen_, network_screen_, chromeos::NetworkScreen);
    MOCK(mock_update_screen_, update_screen_, MockUpdateScreen);
    MOCK(mock_eula_screen_, eula_screen_, chromeos::EulaScreen);

    // Switch to the initial screen.
    EXPECT_EQ(NULL, controller()->current_screen());
    EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
    controller()->ShowFirstScreen(WizardController::kNetworkScreenName);

    return ret;
  }

  MockOutShowHide<chromeos::AccountScreen>* mock_account_screen_;
  MockOutShowHide<chromeos::LoginScreen>* mock_login_screen_;
  MockOutShowHide<chromeos::NetworkScreen>* mock_network_screen_;
  MockOutShowHide<MockUpdateScreen>* mock_update_screen_;
  MockOutShowHide<chromeos::EulaScreen>* mock_eula_screen_;

 private:
  DISALLOW_COPY_AND_ASSIGN(WizardControllerFlowTest);
};

IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowMain) {
  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::NETWORK_CONNECTED);

  EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_update_screen_, StartUpdate()).Times(1);
  EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::EULA_ACCEPTED);

  EXPECT_EQ(controller()->GetUpdateScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_eula_screen_, Show()).Times(0);
  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::UPDATE_INSTALLED);

  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_login_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_account_screen_, Show()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::LOGIN_CREATE_ACCOUNT);

  EXPECT_EQ(controller()->GetAccountScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_account_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
  EXPECT_CALL(*mock_login_screen_, Hide()).Times(0);  // last transition
  controller()->OnExit(chromeos::ScreenObserver::ACCOUNT_CREATED);

  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
}

IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowErrorUpdate) {
  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_update_screen_, StartUpdate()).Times(0);
  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
  EXPECT_CALL(*mock_update_screen_, Show()).Times(0);
  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::NETWORK_CONNECTED);

  EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_update_screen_, StartUpdate()).Times(1);
  EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::EULA_ACCEPTED);

  EXPECT_EQ(controller()->GetUpdateScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_eula_screen_, Show()).Times(0);
  EXPECT_CALL(*mock_eula_screen_, Hide()).Times(0);  // last transition
  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
  controller()->OnExit(
      chromeos::ScreenObserver::UPDATE_ERROR_UPDATING);

  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
}

IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowEulaDeclined) {
  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_update_screen_, StartUpdate()).Times(0);
  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::NETWORK_CONNECTED);

  EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
  EXPECT_CALL(*mock_network_screen_, Hide()).Times(0);  // last transition
  controller()->OnExit(chromeos::ScreenObserver::EULA_BACK);

  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
}

IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowErrorNetwork) {
  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::NETWORK_OFFLINE);
  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
}

#if defined(OFFICIAL_BUILD)
// This test is supposed to fail on official test.
#define MAYBE_Accelerators DISABLED_Accelerators
#else
#define MAYBE_Accelerators Accelerators
#endif

IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, MAYBE_Accelerators) {
  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());

  views::FocusManager* focus_manager =
      controller()->contents()->GetFocusManager();
  views::Accelerator accel_account_screen(app::VKEY_A, false, true, true);
  views::Accelerator accel_login_screen(app::VKEY_L, false, true, true);
  views::Accelerator accel_network_screen(app::VKEY_N, false, true, true);
  views::Accelerator accel_update_screen(app::VKEY_U, false, true, true);
  views::Accelerator accel_image_screen(app::VKEY_I, false, true, true);
  views::Accelerator accel_eula_screen(app::VKEY_E, false, true, true);

  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_account_screen_, Show()).Times(1);
  EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_account_screen));
  EXPECT_EQ(controller()->GetAccountScreen(), controller()->current_screen());

  focus_manager = controller()->contents()->GetFocusManager();
  EXPECT_CALL(*mock_account_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
  EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_login_screen));
  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());

  focus_manager = controller()->contents()->GetFocusManager();
  EXPECT_CALL(*mock_login_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
  EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_network_screen));
  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());

  focus_manager = controller()->contents()->GetFocusManager();
  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
  EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_update_screen));
  EXPECT_EQ(controller()->GetUpdateScreen(), controller()->current_screen());

  focus_manager = controller()->contents()->GetFocusManager();
  EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
  EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_image_screen));
  EXPECT_EQ(controller()->GetUserImageScreen(), controller()->current_screen());

  focus_manager = controller()->contents()->GetFocusManager();
  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
  EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_eula_screen));
  EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
}

COMPILE_ASSERT(chromeos::ScreenObserver::EXIT_CODES_COUNT == 18,
               add_tests_for_new_control_flow_you_just_introduced);
<commit_msg>Mark failing unittest to FAILS.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "app/l10n_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/account_screen.h"
#include "chrome/browser/chromeos/login/eula_view.h"
#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "chrome/browser/chromeos/login/login_screen.h"
#include "chrome/browser/chromeos/login/mock_update_screen.h"
#include "chrome/browser/chromeos/login/network_screen.h"
#include "chrome/browser/chromeos/login/network_selection_view.h"
#include "chrome/browser/chromeos/login/user_image_screen.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/test/ui_test_utils.h"
#include "grit/generated_resources.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "unicode/locid.h"
#include "views/accelerator.h"

namespace {

template <class T>
class MockOutShowHide : public T {
 public:
  template <class P> MockOutShowHide(P p) : T(p) {}
  template <class P1, class P2> MockOutShowHide(P1 p1, P2 p2) : T(p1, p2) {}
  MOCK_METHOD0(Show, void());
  MOCK_METHOD0(Hide, void());
};

template <class T>
struct CreateMockWizardScreenHelper {
  static MockOutShowHide<T>* Create(WizardController* wizard);
};

template <class T> MockOutShowHide<T>*
CreateMockWizardScreenHelper<T>::Create(WizardController* wizard) {
  return new MockOutShowHide<T>(wizard);
}

template <> MockOutShowHide<chromeos::NetworkScreen>*
CreateMockWizardScreenHelper<chromeos::NetworkScreen>::Create(
    WizardController* wizard) {
  return new MockOutShowHide<chromeos::NetworkScreen>(wizard);
}

#define MOCK(mock_var, screen_name, mocked_class)                              \
  mock_var = CreateMockWizardScreenHelper<mocked_class>::Create(controller()); \
  controller()->screen_name.reset(mock_var);                                   \
  EXPECT_CALL(*mock_var, Show()).Times(0);                                     \
  EXPECT_CALL(*mock_var, Hide()).Times(0);

}  // namespace

class WizardControllerTest : public chromeos::WizardInProcessBrowserTest {
 protected:
  WizardControllerTest() : chromeos::WizardInProcessBrowserTest(
      WizardController::kTestNoScreenName) {}
  virtual ~WizardControllerTest() {}

 private:
  DISALLOW_COPY_AND_ASSIGN(WizardControllerTest);
};

// TODO(zelidrag): Need to revisit this once translation for fr and ar is
// complete.  See http://crosbug.com/8974
IN_PROC_BROWSER_TEST_F(WizardControllerTest, FAILS_SwitchLanguage) {
  WizardController* const wizard = controller();
  ASSERT_TRUE(wizard != NULL);
  wizard->ShowFirstScreen(WizardController::kNetworkScreenName);
  views::View* current_screen = wizard->contents();
  ASSERT_TRUE(current_screen != NULL);

  // Checking the default locale. Provided that the profile is cleared in SetUp.
  EXPECT_EQ("en-US", g_browser_process->GetApplicationLocale());
  EXPECT_STREQ("en", icu::Locale::getDefault().getLanguage());
  EXPECT_FALSE(base::i18n::IsRTL());
  const std::wstring en_str = l10n_util::GetString(IDS_NETWORK_SELECTION_TITLE);

  chromeos::LanguageSwitchMenu::SwitchLanguage("fr");
  EXPECT_EQ("fr", g_browser_process->GetApplicationLocale());
  EXPECT_STREQ("fr", icu::Locale::getDefault().getLanguage());
  EXPECT_FALSE(base::i18n::IsRTL());
  const std::wstring fr_str = l10n_util::GetString(IDS_NETWORK_SELECTION_TITLE);

  EXPECT_NE(en_str, fr_str);

  chromeos::LanguageSwitchMenu::SwitchLanguage("ar");
  EXPECT_EQ("ar", g_browser_process->GetApplicationLocale());
  EXPECT_STREQ("ar", icu::Locale::getDefault().getLanguage());
  EXPECT_TRUE(base::i18n::IsRTL());
  const std::wstring ar_str = l10n_util::GetString(IDS_NETWORK_SELECTION_TITLE);

  EXPECT_NE(fr_str, ar_str);
}

class WizardControllerFlowTest : public WizardControllerTest {
 protected:
  WizardControllerFlowTest() {}
  // Overriden from InProcessBrowserTest:
  virtual Browser* CreateBrowser(Profile* profile) {
    Browser* ret = WizardControllerTest::CreateBrowser(profile);

    // Make sure that OOBE is run as an "official" build.
    WizardController::default_controller()->is_official_build_ = true;

    // Set up the mocks for all screens.
    MOCK(mock_account_screen_, account_screen_, chromeos::AccountScreen);
    MOCK(mock_login_screen_, login_screen_, chromeos::LoginScreen);
    MOCK(mock_network_screen_, network_screen_, chromeos::NetworkScreen);
    MOCK(mock_update_screen_, update_screen_, MockUpdateScreen);
    MOCK(mock_eula_screen_, eula_screen_, chromeos::EulaScreen);

    // Switch to the initial screen.
    EXPECT_EQ(NULL, controller()->current_screen());
    EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
    controller()->ShowFirstScreen(WizardController::kNetworkScreenName);

    return ret;
  }

  MockOutShowHide<chromeos::AccountScreen>* mock_account_screen_;
  MockOutShowHide<chromeos::LoginScreen>* mock_login_screen_;
  MockOutShowHide<chromeos::NetworkScreen>* mock_network_screen_;
  MockOutShowHide<MockUpdateScreen>* mock_update_screen_;
  MockOutShowHide<chromeos::EulaScreen>* mock_eula_screen_;

 private:
  DISALLOW_COPY_AND_ASSIGN(WizardControllerFlowTest);
};

IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowMain) {
  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::NETWORK_CONNECTED);

  EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_update_screen_, StartUpdate()).Times(1);
  EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::EULA_ACCEPTED);

  EXPECT_EQ(controller()->GetUpdateScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_eula_screen_, Show()).Times(0);
  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::UPDATE_INSTALLED);

  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_login_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_account_screen_, Show()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::LOGIN_CREATE_ACCOUNT);

  EXPECT_EQ(controller()->GetAccountScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_account_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
  EXPECT_CALL(*mock_login_screen_, Hide()).Times(0);  // last transition
  controller()->OnExit(chromeos::ScreenObserver::ACCOUNT_CREATED);

  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
}

IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowErrorUpdate) {
  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_update_screen_, StartUpdate()).Times(0);
  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
  EXPECT_CALL(*mock_update_screen_, Show()).Times(0);
  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::NETWORK_CONNECTED);

  EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_update_screen_, StartUpdate()).Times(1);
  EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::EULA_ACCEPTED);

  EXPECT_EQ(controller()->GetUpdateScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_eula_screen_, Show()).Times(0);
  EXPECT_CALL(*mock_eula_screen_, Hide()).Times(0);  // last transition
  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
  controller()->OnExit(
      chromeos::ScreenObserver::UPDATE_ERROR_UPDATING);

  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
}

IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowEulaDeclined) {
  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_update_screen_, StartUpdate()).Times(0);
  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::NETWORK_CONNECTED);

  EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
  EXPECT_CALL(*mock_network_screen_, Hide()).Times(0);  // last transition
  controller()->OnExit(chromeos::ScreenObserver::EULA_BACK);

  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
}

IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, ControlFlowErrorNetwork) {
  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());
  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
  controller()->OnExit(chromeos::ScreenObserver::NETWORK_OFFLINE);
  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());
}

#if defined(OFFICIAL_BUILD)
// This test is supposed to fail on official test.
#define MAYBE_Accelerators DISABLED_Accelerators
#else
#define MAYBE_Accelerators Accelerators
#endif

IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest, MAYBE_Accelerators) {
  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());

  views::FocusManager* focus_manager =
      controller()->contents()->GetFocusManager();
  views::Accelerator accel_account_screen(app::VKEY_A, false, true, true);
  views::Accelerator accel_login_screen(app::VKEY_L, false, true, true);
  views::Accelerator accel_network_screen(app::VKEY_N, false, true, true);
  views::Accelerator accel_update_screen(app::VKEY_U, false, true, true);
  views::Accelerator accel_image_screen(app::VKEY_I, false, true, true);
  views::Accelerator accel_eula_screen(app::VKEY_E, false, true, true);

  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_account_screen_, Show()).Times(1);
  EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_account_screen));
  EXPECT_EQ(controller()->GetAccountScreen(), controller()->current_screen());

  focus_manager = controller()->contents()->GetFocusManager();
  EXPECT_CALL(*mock_account_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_login_screen_, Show()).Times(1);
  EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_login_screen));
  EXPECT_EQ(controller()->GetLoginScreen(), controller()->current_screen());

  focus_manager = controller()->contents()->GetFocusManager();
  EXPECT_CALL(*mock_login_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
  EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_network_screen));
  EXPECT_EQ(controller()->GetNetworkScreen(), controller()->current_screen());

  focus_manager = controller()->contents()->GetFocusManager();
  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
  EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
  EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_update_screen));
  EXPECT_EQ(controller()->GetUpdateScreen(), controller()->current_screen());

  focus_manager = controller()->contents()->GetFocusManager();
  EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
  EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_image_screen));
  EXPECT_EQ(controller()->GetUserImageScreen(), controller()->current_screen());

  focus_manager = controller()->contents()->GetFocusManager();
  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
  EXPECT_TRUE(focus_manager->ProcessAccelerator(accel_eula_screen));
  EXPECT_EQ(controller()->GetEulaScreen(), controller()->current_screen());
}

COMPILE_ASSERT(chromeos::ScreenObserver::EXIT_CODES_COUNT == 18,
               add_tests_for_new_control_flow_you_just_introduced);
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/process_util.h"
#include "base/sys_string_conversions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/component_loader.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/omnibox/location_bar.h"
#include "chrome/browser/ui/omnibox/omnibox_view.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "extensions/common/constants.h"
#include "googleurl/src/gurl.h"

using content::NavigationEntry;

class ExtensionURLRewriteBrowserTest : public ExtensionBrowserTest {
 public:
  virtual void SetUp() OVERRIDE {
    extensions::ComponentLoader::EnableBackgroundExtensionsForTesting();
    ExtensionBrowserTest::SetUp();
  }

 protected:
  std::string GetLocationBarText() const {
    return UTF16ToUTF8(
        browser()->window()->GetLocationBar()->GetLocationEntry()->GetText());
  }

  GURL GetLocationBarTextAsURL() const {
    return GURL(GetLocationBarText());
  }

  content::NavigationController* GetNavigationController() const {
    return &browser()->tab_strip_model()->GetActiveWebContents()->
        GetController();
  }

  NavigationEntry* GetNavigationEntry() const {
    return GetNavigationController()->GetActiveEntry();
  }

  base::FilePath GetTestExtensionPath(const char* extension_name) const {
    return test_data_dir_.AppendASCII("browsertest/url_rewrite/").
        AppendASCII(extension_name);
  }

  // Navigates to |url| and tests that the location bar and the |virtual_url|
  // correspond to |url|, while the real URL of the navigation entry uses the
  // chrome-extension:// scheme.
  void TestExtensionURLOverride(const GURL& url) {
    ui_test_utils::NavigateToURL(browser(), url);
    EXPECT_EQ(url, GetLocationBarTextAsURL());
    EXPECT_EQ(url, GetNavigationEntry()->GetVirtualURL());
    EXPECT_TRUE(
        GetNavigationEntry()->GetURL().SchemeIs(extensions::kExtensionScheme));
  }

  // Navigates to |url| and tests that the location bar is empty while the
  // |virtual_url| is the same as |url|.
  void TestURLNotShown(const GURL& url) {
    ui_test_utils::NavigateToURL(browser(), url);
    EXPECT_EQ("", GetLocationBarText());
    EXPECT_EQ(url, GetNavigationEntry()->GetVirtualURL());
  }
};

IN_PROC_BROWSER_TEST_F(ExtensionURLRewriteBrowserTest, NewTabPageURL) {
  // Navigate to chrome://newtab and check that the location bar text is blank.
  GURL url(chrome::kChromeUINewTabURL);
  TestURLNotShown(url);
  // Check that the actual URL corresponds to chrome://newtab.
  EXPECT_EQ(url, GetNavigationEntry()->GetURL());
}

IN_PROC_BROWSER_TEST_F(ExtensionURLRewriteBrowserTest, NewTabPageURLOverride) {
  // Load an extension to override the NTP and check that the location bar text
  // is blank after navigating to chrome://newtab.
  LoadExtension(GetTestExtensionPath("newtab"));
  TestURLNotShown(GURL(chrome::kChromeUINewTabURL));
  // Check that the internal URL uses the chrome-extension:// scheme.
  EXPECT_TRUE(GetNavigationEntry()->GetURL().SchemeIs(
      extensions::kExtensionScheme));
}

// TODO(linux_aura) http://crbug.com/163931
#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
#define MAYBE_BookmarksURL DISABLED_BookmarksURL
#else
#define MAYBE_BookmarksURL BookmarksURL
#endif
IN_PROC_BROWSER_TEST_F(ExtensionURLRewriteBrowserTest, MAYBE_BookmarksURL) {
  // Navigate to chrome://bookmarks and check that the location bar URL is
  // what was entered and the internal URL uses the chrome-extension:// scheme.
  TestExtensionURLOverride(GURL(chrome::kChromeUIBookmarksURL));
}

#if defined(FILE_MANAGER_EXTENSION)
IN_PROC_BROWSER_TEST_F(ExtensionURLRewriteBrowserTest, FileManagerURL) {
  // Navigate to chrome://files and check that the location bar URL is
  // what was entered and the internal URL uses the chrome-extension:// scheme.
  TestExtensionURLOverride(GURL(chrome::kChromeUIFileManagerURL));
}
#endif

IN_PROC_BROWSER_TEST_F(ExtensionURLRewriteBrowserTest, BookmarksURLWithRef) {
  // Navigate to chrome://bookmarks/#1 and check that the location bar URL is
  // what was entered and the internal URL uses the chrome-extension:// scheme.
  GURL url_with_ref(chrome::kChromeUIBookmarksURL + std::string("#1"));
  TestExtensionURLOverride(url_with_ref);
}

// Disabled for flakiness: crbug.com/176332
IN_PROC_BROWSER_TEST_F(ExtensionURLRewriteBrowserTest,
                       DISABLED_BookmarksURLOverride) {
  // Load an extension that overrides chrome://bookmarks.
  LoadExtension(GetTestExtensionPath("bookmarks"));
  // Navigate to chrome://bookmarks and check that the location bar URL is what
  // was entered and the internal URL uses the chrome-extension:// scheme.
  TestExtensionURLOverride(GURL(chrome::kChromeUIBookmarksURL));
}
<commit_msg>Attempt to fix flakyness of ExtensionURLRewriteBrowserTest.BookmarksURL.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/process_util.h"
#include "base/sys_string_conversions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/component_loader.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/omnibox/location_bar.h"
#include "chrome/browser/ui/omnibox/omnibox_view.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "extensions/common/constants.h"
#include "googleurl/src/gurl.h"

using content::NavigationEntry;

class ExtensionURLRewriteBrowserTest : public ExtensionBrowserTest {
 public:
  virtual void SetUp() OVERRIDE {
    extensions::ComponentLoader::EnableBackgroundExtensionsForTesting();
    ExtensionBrowserTest::SetUp();
  }

 protected:
  std::string GetLocationBarText() const {
    return UTF16ToUTF8(
        browser()->window()->GetLocationBar()->GetLocationEntry()->GetText());
  }

  GURL GetLocationBarTextAsURL() const {
    return GURL(GetLocationBarText());
  }

  content::NavigationController* GetNavigationController() const {
    return &browser()->tab_strip_model()->GetActiveWebContents()->
        GetController();
  }

  NavigationEntry* GetNavigationEntry() const {
    return GetNavigationController()->GetActiveEntry();
  }

  base::FilePath GetTestExtensionPath(const char* extension_name) const {
    return test_data_dir_.AppendASCII("browsertest/url_rewrite/").
        AppendASCII(extension_name);
  }

  // Navigates to |url| and tests that the location bar and the |virtual_url|
  // correspond to |url|, while the real URL of the navigation entry uses the
  // chrome-extension:// scheme.
  void TestExtensionURLOverride(const GURL& url) {
    ui_test_utils::NavigateToURL(browser(), url);
    EXPECT_EQ(url, GetLocationBarTextAsURL());
    EXPECT_EQ(url, GetNavigationEntry()->GetVirtualURL());
    EXPECT_TRUE(
        GetNavigationEntry()->GetURL().SchemeIs(extensions::kExtensionScheme));
  }

  // Navigates to |url| and tests that the location bar is empty while the
  // |virtual_url| is the same as |url|.
  void TestURLNotShown(const GURL& url) {
    ui_test_utils::NavigateToURL(browser(), url);
    EXPECT_EQ("", GetLocationBarText());
    EXPECT_EQ(url, GetNavigationEntry()->GetVirtualURL());
  }
};

IN_PROC_BROWSER_TEST_F(ExtensionURLRewriteBrowserTest, NewTabPageURL) {
  // Navigate to chrome://newtab and check that the location bar text is blank.
  GURL url(chrome::kChromeUINewTabURL);
  TestURLNotShown(url);
  // Check that the actual URL corresponds to chrome://newtab.
  EXPECT_EQ(url, GetNavigationEntry()->GetURL());
}

IN_PROC_BROWSER_TEST_F(ExtensionURLRewriteBrowserTest, NewTabPageURLOverride) {
  // Load an extension to override the NTP and check that the location bar text
  // is blank after navigating to chrome://newtab.
  ASSERT_TRUE(LoadExtension(GetTestExtensionPath("newtab")));
  TestURLNotShown(GURL(chrome::kChromeUINewTabURL));
  // Check that the internal URL uses the chrome-extension:// scheme.
  EXPECT_TRUE(GetNavigationEntry()->GetURL().SchemeIs(
      extensions::kExtensionScheme));
}

// TODO(linux_aura) http://crbug.com/163931
#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
#define MAYBE_BookmarksURL DISABLED_BookmarksURL
#else
#define MAYBE_BookmarksURL BookmarksURL
#endif
IN_PROC_BROWSER_TEST_F(ExtensionURLRewriteBrowserTest, MAYBE_BookmarksURL) {
  // Navigate to chrome://bookmarks and check that the location bar URL is
  // what was entered and the internal URL uses the chrome-extension:// scheme.
  const GURL bookmarks_url(chrome::kChromeUIBookmarksURL);
  ui_test_utils::NavigateToURL(browser(), bookmarks_url);
  // The default chrome://bookmarks implementation will append /#1 to the URL
  // once loaded. Use |GetWithEmptyPath()| to avoid flakyness.
  EXPECT_EQ(bookmarks_url, GetLocationBarTextAsURL().GetWithEmptyPath());
  NavigationEntry* navigation = GetNavigationEntry();
  EXPECT_EQ(bookmarks_url, navigation->GetVirtualURL().GetWithEmptyPath());
  EXPECT_TRUE(navigation->GetURL().SchemeIs(extensions::kExtensionScheme));
}

#if defined(FILE_MANAGER_EXTENSION)
IN_PROC_BROWSER_TEST_F(ExtensionURLRewriteBrowserTest, FileManagerURL) {
  // Navigate to chrome://files and check that the location bar URL is
  // what was entered and the internal URL uses the chrome-extension:// scheme.
  TestExtensionURLOverride(GURL(chrome::kChromeUIFileManagerURL));
}
#endif

IN_PROC_BROWSER_TEST_F(ExtensionURLRewriteBrowserTest, BookmarksURLWithRef) {
  // Navigate to chrome://bookmarks/#1 and check that the location bar URL is
  // what was entered and the internal URL uses the chrome-extension:// scheme.
  GURL url_with_ref(chrome::kChromeUIBookmarksURL + std::string("#1"));
  TestExtensionURLOverride(url_with_ref);
}

IN_PROC_BROWSER_TEST_F(ExtensionURLRewriteBrowserTest, BookmarksURLOverride) {
  // Load an extension that overrides chrome://bookmarks.
  ASSERT_TRUE(LoadExtension(GetTestExtensionPath("bookmarks")));
  // Navigate to chrome://bookmarks and check that the location bar URL is what
  // was entered and the internal URL uses the chrome-extension:// scheme.
  TestExtensionURLOverride(GURL(chrome::kChromeUIBookmarksURL));
}
<|endoftext|>


<commit_before>#include <boost/any.hpp>
#include <iostream>
#include <vector>
#include <string>

int main(int argc, char** argv) {
	std::vector<boost::any> some_values;

	some_values.push_back(10);
	const char* c_str = "Hello there!";
	some_values.push_back(c_str);
	some_values.push_back(std::string("Wow!"));
	std::string& s = boost::any_cast<std::string&>(some_values.back());
	s += " That is great!\n";
	std::cout << s;
	return 0;
}<commit_msg>'Any' example updated.<commit_after>#include <boost/any.hpp>
#include <iostream>
#include <vector>
#include <string>
#include <cassert>

int main(int argc, char** argv) {

	{
		boost::any any_value = 10;
		std::cout << boost::any_cast<int>(any_value) << std::endl;
		int *pointer = boost::any_cast<int>(&any_value);
		std::cout << *pointer << std::endl;

		any_value = 2.34;
		std::cout << boost::any_cast<double>(any_value) << std::endl;

		any_value = false;
		std::cout << std::boolalpha << boost::any_cast<bool>(any_value) << std::endl;
	}

	{
		boost::any any_value = 10;
		assert(any_value.type() == typeid(int));

		boost::any empty_value;
		assert(empty_value.empty());
	}

	return 0;
}<|endoftext|>