blob: ba6526bf0f5b2e10fe0516e06c823d9214414060 [file] [log] [blame]
// Copyright 2019 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.
#ifndef CHROME_BROWSER_AUTOFILL_AUTOMATED_TESTS_CACHE_REPLAYER_H_
#define CHROME_BROWSER_AUTOFILL_AUTOMATED_TESTS_CACHE_REPLAYER_H_
#include <map>
#include <string>
#include <utility>
#include "base/files/file_path.h"
#include "components/autofill/core/browser/proto/api_v1.pb.h"
#include "components/autofill/core/browser/proto/server.pb.h"
#include "content/public/test/url_loader_interceptor.h"
#include "third_party/protobuf/src/google/protobuf/stubs/statusor.h"
namespace autofill {
namespace test {
using ServerCache = std::map<std::string, std::string>;
// Splits raw HTTP request text into a pair, where the first element represent
// the head with headers and the second element represents the body that
// contains the data payload.
std::pair<std::string, std::string> SplitHTTP(const std::string& http_text);
// Streams in text format. For consistency, taken from anonymous namespace in
// components/autofill/core/browser/autofill_download_manager.cc
std::ostream& operator<<(std::ostream& out,
const autofill::AutofillQueryContents& query);
std::ostream& operator<<(std::ostream& out,
const autofill::AutofillPageQueryRequest& query);
// Streams in text format. For consistency, taken from anonymous namespace in
// components/autofill/core/browser/form_structure.cc
std::ostream& operator<<(
std::ostream& out,
const autofill::AutofillQueryResponseContents& response);
std::ostream& operator<<(std::ostream& out,
const autofill::AutofillQueryResponse& response);
enum class RequestType {
kQueryProtoGET,
kQueryProtoPOST,
kNone,
};
class LegacyEnv {
public:
using Query = AutofillQueryContents;
using Response = AutofillQueryResponseContents;
};
class ApiEnv {
public:
using Query = AutofillPageQueryRequest;
using Response = AutofillQueryResponse;
};
// Gets a key from a given query request.
template <typename Env>
std::string GetKeyFromQuery(const typename Env::Query& query_request);
template <>
std::string GetKeyFromQuery<LegacyEnv>(const LegacyEnv::Query& query_request);
template <>
std::string GetKeyFromQuery<ApiEnv>(const ApiEnv::Query& query_request);
bool GetResponseForQuery(const ServerCache& cache,
const AutofillPageQueryRequest& query,
std::string* http_text);
// Conversion between different versions of queries.
template <typename ReadEnv>
AutofillPageQueryRequest ConvertQuery(const typename ReadEnv::Query& in);
template <>
AutofillPageQueryRequest ConvertQuery<LegacyEnv>(
const typename LegacyEnv::Query& in);
template <>
AutofillPageQueryRequest ConvertQuery<ApiEnv>(const typename ApiEnv::Query& in);
// Conversion between different versions of responses.
template <typename ReadEnv>
AutofillQueryResponse ConvertResponse(const typename ReadEnv::Response& in,
const typename ReadEnv::Query& query);
template <>
AutofillQueryResponse ConvertResponse<LegacyEnv>(
const typename LegacyEnv::Response& in,
const typename LegacyEnv::Query& query);
template <>
AutofillQueryResponse ConvertResponse<ApiEnv>(
const typename ApiEnv::Response& in,
const typename ApiEnv::Query& query);
// Switch `--autofill-server-type` is used to override the default behavior of
// using the cached responses from the wpr archive. The valid values match the
// enum AutofillServerBehaviorType below. Options are:
// SavedCache, ProductionServer, or OnlyLocalHeuristics.
constexpr char kAutofillServerBehaviorParam[] = "autofill-server-type";
enum class AutofillServerBehaviorType {
kSavedCache, // Uses cached responses. This is the Default.
kProductionServer, // Connects to live Autofill Server for recommendations.
kOnlyLocalHeuristics // Test with local heuristic recommendations only.
};
// Check for command line flags to determine Autofill Server Behavior type.
AutofillServerBehaviorType ParseAutofillServerBehaviorType();
// Replayer for Autofill Server cache. Can be used in concurrency.
class ServerCacheReplayer {
public:
enum Options {
kOptionNone = 0,
kOptionFailOnInvalidJsonRecord = 1 << 1,
kOptionFailOnEmpty = 1 << 2,
kOptionSplitRequestsByForm = 1 << 3,
};
// Container for status.
enum class StatusCode { kOk = 0, kEmpty = 1, kBadRead = 2, kBadNode = 3 };
struct Status {
StatusCode error_code;
std::string message;
bool Ok() { return error_code == StatusCode::kOk; }
};
// Populates the cache at construction time. File at |json_file_path| has to
// contain a textual json structured like this (same as WPR):
// {
// 'Requests': {
// 'clients1.google.com': {
// 'https://clients1.google.com/tbproxy/af/query?': [
// {'SerializedRequest': '1234', 'SerializedResponse': '1234'}
// ]
// }
// }
// }
// You can set the replayer's behavior by setting |options| with a mix of
// Options. Will crash if there is a failure when loading the cache.
ServerCacheReplayer(const base::FilePath& json_file_path, int options);
// Constructs the replayer from an already populated cache.
explicit ServerCacheReplayer(ServerCache server_cache,
bool split_requests_by_form = false);
~ServerCacheReplayer();
// Gets an uncompress HTTP textual response that is paired with |query| as
// key. Returns false if there was no match or the response could no be
// decompressed. Nothing will be assigned to |http_text| on error. Leaves a
// log when there is an error. Can be used in concurrency.
bool GetApiServerResponseForQuery(const AutofillPageQueryRequest& query,
std::string* http_text) const;
const ServerCache& cache() const { return cache_; }
bool split_requests_by_form() const { return split_requests_by_form_; }
private:
// Server's cache. Will only be modified during construction of
// ServerCacheReplayer.
ServerCache cache_;
// Controls the type of matching behavior. If False, will cache form signature
// groupings as they are recorded in the WPR archive. If True, will cache each
// form individually and attempt to stitch them together on retrieval, which
// allows a higher hit rate.
const bool split_requests_by_form_;
};
// Url loader that intercepts Autofill Server calls and serves back cached
// content.
class ServerUrlLoader {
public:
explicit ServerUrlLoader(std::unique_ptr<ServerCacheReplayer> cache_replayer);
~ServerUrlLoader();
private:
bool InterceptAutofillRequest(
content::URLLoaderInterceptor::RequestParams* params);
// Cache replayer component that is used to replay cached responses.
std::unique_ptr<ServerCacheReplayer> cache_replayer_;
// Describes what behavior we want from the autofill server requests
AutofillServerBehaviorType autofill_server_behavior_type_;
// Interceptor that intercepts Autofill Server calls.
content::URLLoaderInterceptor interceptor_;
};
} // namespace test
} // namespace autofill
#endif // CHROME_BROWSER_AUTOFILL_AUTOMATED_TESTS_CACHE_REPLAYER_H_