summaryrefslogtreecommitdiff
path: root/chromium/components/copresence/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/copresence/rpc')
-rw-r--r--chromium/components/copresence/rpc/http_post.cc110
-rw-r--r--chromium/components/copresence/rpc/http_post.h75
-rw-r--r--chromium/components/copresence/rpc/http_post_unittest.cc143
-rw-r--r--chromium/components/copresence/rpc/rpc_handler.cc620
-rw-r--r--chromium/components/copresence/rpc/rpc_handler.h213
-rw-r--r--chromium/components/copresence/rpc/rpc_handler_unittest.cc348
6 files changed, 0 insertions, 1509 deletions
diff --git a/chromium/components/copresence/rpc/http_post.cc b/chromium/components/copresence/rpc/http_post.cc
deleted file mode 100644
index 63ea7e74d29..00000000000
--- a/chromium/components/copresence/rpc/http_post.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2014 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 "components/copresence/rpc/http_post.h"
-
-// TODO(ckehoe): Support third-party protobufs too.
-#include <google/protobuf/message_lite.h>
-
-#include "base/bind.h"
-#include "google_apis/google_api_keys.h"
-#include "net/base/load_flags.h"
-#include "net/base/net_errors.h"
-#include "net/base/url_util.h"
-#include "net/http/http_status_code.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "url/gurl.h"
-
-namespace copresence {
-
-const char HttpPost::kApiKeyField[] = "key";
-const char HttpPost::kTracingField[] = "trace";
-
-HttpPost::HttpPost(net::URLRequestContextGetter* url_context_getter,
- const std::string& server_host,
- const std::string& rpc_name,
- std::string api_key,
- const std::string& auth_token,
- const std::string& tracing_token,
- const google::protobuf::MessageLite& request_proto) {
- // Create the base URL to call.
- GURL url(server_host + "/" + rpc_name);
-
- // Add the tracing token, if specified.
- if (!tracing_token.empty()) {
- url = net::AppendQueryParameter(
- url, kTracingField, "token:" + tracing_token);
- }
-
- // If we have no auth token, authenticate using the API key.
- // If no API key is specified, use the Chrome API key.
- if (auth_token.empty()) {
- if (api_key.empty()) {
-#ifdef GOOGLE_CHROME_BUILD
- DCHECK(google_apis::HasKeysConfigured());
- api_key = google_apis::GetAPIKey();
-#else
- LOG(ERROR) << "No Copresence API key provided";
-#endif
- }
- url = net::AppendQueryParameter(url, kApiKeyField, api_key);
- }
-
- // Serialize the proto for transmission.
- std::string request_data;
- bool serialize_success = request_proto.SerializeToString(&request_data);
- DCHECK(serialize_success);
-
- // Configure and send the request.
- url_fetcher_ =
- net::URLFetcher::Create(kUrlFetcherId, url, net::URLFetcher::POST, this);
- url_fetcher_->SetRequestContext(url_context_getter);
- url_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE |
- net::LOAD_DISABLE_CACHE |
- net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES |
- net::LOAD_DO_NOT_SEND_AUTH_DATA);
- url_fetcher_->SetUploadData("application/x-protobuf", request_data);
- if (!auth_token.empty()) {
- url_fetcher_->AddExtraRequestHeader("Authorization: Bearer " + auth_token);
- }
-}
-
-HttpPost::~HttpPost() {}
-
-void HttpPost::Start(const ResponseCallback& response_callback) {
- response_callback_ = response_callback;
- DVLOG(3) << "Sending Copresence request to "
- << url_fetcher_->GetOriginalURL().spec();
- url_fetcher_->Start();
-}
-
-void HttpPost::OnURLFetchComplete(const net::URLFetcher* source) {
- DCHECK_EQ(url_fetcher_.get(), source);
-
- // Gather response info.
- std::string response;
- source->GetResponseAsString(&response);
- int response_code = source->GetResponseCode();
-
- // Log any errors.
- if (response_code < 0) {
- net::URLRequestStatus status = source->GetStatus();
- LOG(WARNING) << "Couldn't contact the Copresence server at "
- << source->GetURL() << ". Status code " << status.status();
- LOG_IF(WARNING, status.error())
- << "Network error: " << net::ErrorToString(status.error());
- LOG_IF(WARNING, !response.empty()) << "HTTP response: " << response;
- } else if (response_code != net::HTTP_OK) {
- LOG(WARNING) << "Copresence request got HTTP response code "
- << response_code << ". Response:\n" << response;
- }
-
- // Return the response.
- response_callback_.Run(response_code, response);
- delete this;
-}
-
-} // namespace copresence
diff --git a/chromium/components/copresence/rpc/http_post.h b/chromium/components/copresence/rpc/http_post.h
deleted file mode 100644
index 911bc5f03a3..00000000000
--- a/chromium/components/copresence/rpc/http_post.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 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 COMPONENTS_COPRESENCE_RPC_HTTP_POST_H_
-#define COMPONENTS_COPRESENCE_RPC_HTTP_POST_H_
-
-#include <memory>
-#include <string>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "net/url_request/url_fetcher_delegate.h"
-
-namespace google {
-namespace protobuf {
-class MessageLite;
-}
-}
-
-namespace net {
-class URLRequestContextGetter;
-}
-
-namespace copresence {
-
-// This class handles all Apiary calls to the Copresence server.
-// It configures the HTTP request appropriately and reports any errors.
-// If deleted, the HTTP request is cancelled.
-//
-// TODO(ckehoe): Add retry logic.
-class HttpPost : public net::URLFetcherDelegate {
- public:
- // Callback to receive the HTTP status code and body of the response
- // (if any). A pointer to this HttpPost object is also passed along.
- using ResponseCallback = base::Callback<void(int, const std::string&)>;
-
- // Create a request to the Copresence server.
- // |url_context_getter| is owned by the caller,
- // and the context it provides must be available until the request completes.
- HttpPost(net::URLRequestContextGetter* url_context_getter,
- const std::string& server_host,
- // TODO(ckehoe): Condense some of these into a struct.
- const std::string& rpc_name,
- std::string api_key, // If blank, we overwrite with a default.
- const std::string& auth_token,
- const std::string& tracing_token,
- const google::protobuf::MessageLite& request_proto);
-
- // HTTP requests are cancelled on delete.
- ~HttpPost() override;
-
- // Send an HttpPost request.
- void Start(const ResponseCallback& response_callback);
-
- private:
- static const int kUrlFetcherId = 1;
- static const char kApiKeyField[];
- static const char kTracingField[];
-
- friend class HttpPostTest;
-
- // Overridden from net::URLFetcherDelegate.
- void OnURLFetchComplete(const net::URLFetcher* source) override;
-
- ResponseCallback response_callback_;
-
- std::unique_ptr<net::URLFetcher> url_fetcher_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpPost);
-};
-
-} // namespace copresence
-
-#endif // COMPONENTS_COPRESENCE_RPC_HTTP_POST_H_
diff --git a/chromium/components/copresence/rpc/http_post_unittest.cc b/chromium/components/copresence/rpc/http_post_unittest.cc
deleted file mode 100644
index 92bc5808ffa..00000000000
--- a/chromium/components/copresence/rpc/http_post_unittest.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2014 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 "components/copresence/rpc/http_post.h"
-
-#include "base/test/test_simple_task_runner.h"
-#include "components/copresence/proto/data.pb.h"
-#include "net/base/url_util.h"
-#include "net/http/http_status_code.h"
-#include "net/url_request/test_url_fetcher_factory.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace {
-
-const char kFakeServerHost[] = "test.server.google.com";
-const char kRPCName[] = "testRpc";
-const char kTracingToken[] = "trace me!";
-const char kApiKey[] = "unlock ALL the APIz";
-const char kAuthToken[] = "oogabooga";
-
-} // namespace
-
-using google::protobuf::MessageLite;
-
-namespace copresence {
-
-class HttpPostTest : public testing::Test {
- public:
- HttpPostTest() {
- context_getter_ = new net::TestURLRequestContextGetter(
- make_scoped_refptr(new base::TestSimpleTaskRunner));
- proto_.set_client("test_client");
- proto_.set_version_code(123);
- }
- ~HttpPostTest() override {}
-
- // Check that the correct response was sent.
- void TestResponseCallback(int expected_response_code,
- const std::string& expected_response,
- int actual_response_code,
- const std::string& actual_response) {
- CHECK_EQ(expected_response_code, actual_response_code);
- CHECK_EQ(expected_response, actual_response);
- }
-
- protected:
- void CheckPassthrough(int response_code, const std::string& response) {
- HttpPost* post = new HttpPost(
- context_getter_.get(), std::string("http://") + kFakeServerHost,
- kRPCName, kApiKey,
- "", // auth token
- "", // tracing token
- proto_);
- post->Start(base::Bind(&HttpPostTest::TestResponseCallback,
- base::Unretained(this),
- response_code,
- response));
-
- net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(
- HttpPost::kUrlFetcherId);
- fetcher->set_response_code(response_code);
- fetcher->SetResponseString(response);
- fetcher->delegate()->OnURLFetchComplete(fetcher);
- }
-
- net::TestURLFetcher* GetFetcher() {
- return fetcher_factory_.GetFetcherByID(HttpPost::kUrlFetcherId);
- }
-
- const std::string GetApiKeySent() {
- std::string api_key_sent;
- net::GetValueForKeyInQuery(GetFetcher()->GetOriginalURL(),
- HttpPost::kApiKeyField,
- &api_key_sent);
- return api_key_sent;
- }
-
- const std::string GetAuthHeaderSent() {
- net::HttpRequestHeaders headers;
- std::string header;
- GetFetcher()->GetExtraRequestHeaders(&headers);
- return headers.GetHeader("Authorization", &header) ? header : "";
- }
-
- const std::string GetTracingTokenSent() {
- std::string tracing_token_sent;
- net::GetValueForKeyInQuery(GetFetcher()->GetOriginalURL(),
- HttpPost::kTracingField,
- &tracing_token_sent);
- return tracing_token_sent;
- }
-
- net::TestURLFetcherFactory fetcher_factory_;
- scoped_refptr<net::TestURLRequestContextGetter> context_getter_;
-
- ClientVersion proto_;
-};
-
-TEST_F(HttpPostTest, OKResponse) {
- // "Send" the proto to the "server".
- HttpPost* post = new HttpPost(context_getter_.get(),
- std::string("http://") + kFakeServerHost,
- kRPCName,
- kApiKey,
- kAuthToken,
- kTracingToken,
- proto_);
- post->Start(base::Bind(&HttpPostTest::TestResponseCallback,
- base::Unretained(this),
- net::HTTP_OK,
- "Hello World!"));
-
- // Verify that the data was sent to the right place.
- GURL requested_url = GetFetcher()->GetOriginalURL();
- EXPECT_EQ(kFakeServerHost, requested_url.host());
- EXPECT_EQ(std::string("/") + kRPCName, requested_url.path());
-
- // Check parameters.
- EXPECT_EQ("", GetApiKeySent()); // No API key when using an auth token.
- EXPECT_EQ(std::string("Bearer ") + kAuthToken, GetAuthHeaderSent());
- EXPECT_EQ(std::string("token:") + kTracingToken, GetTracingTokenSent());
-
- // Verify that the right data was sent.
- std::string upload_data;
- ASSERT_TRUE(proto_.SerializeToString(&upload_data));
- EXPECT_EQ(upload_data, GetFetcher()->upload_data());
-
- // Send a response and check that it's passed along correctly.
- GetFetcher()->set_response_code(net::HTTP_OK);
- GetFetcher()->SetResponseString("Hello World!");
- GetFetcher()->delegate()->OnURLFetchComplete(GetFetcher());
-}
-
-TEST_F(HttpPostTest, ErrorResponse) {
- CheckPassthrough(net::HTTP_BAD_REQUEST, "Bad client. Shame on you.");
- CheckPassthrough(net::HTTP_INTERNAL_SERVER_ERROR, "I'm dying. Forgive me.");
- CheckPassthrough(-1, "");
-}
-
-} // namespace copresence
diff --git a/chromium/components/copresence/rpc/rpc_handler.cc b/chromium/components/copresence/rpc/rpc_handler.cc
deleted file mode 100644
index 58eec73d316..00000000000
--- a/chromium/components/copresence/rpc/rpc_handler.cc
+++ /dev/null
@@ -1,620 +0,0 @@
-// Copyright 2015 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 "components/copresence/rpc/rpc_handler.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-// TODO(ckehoe): time.h includes windows.h, which #defines DeviceCapabilities
-// to DeviceCapabilitiesW. This breaks the pb.h headers below. For now,
-// we fix this with an #undef.
-#include "base/time/time.h"
-#include "build/build_config.h"
-#if defined(OS_WIN)
-#undef DeviceCapabilities
-#endif
-
-#include "components/audio_modem/public/audio_modem_types.h"
-#include "components/copresence/copresence_state_impl.h"
-#include "components/copresence/copresence_switches.h"
-#include "components/copresence/handlers/directive_handler.h"
-#include "components/copresence/handlers/gcm_handler.h"
-#include "components/copresence/proto/codes.pb.h"
-#include "components/copresence/proto/data.pb.h"
-#include "components/copresence/proto/rpcs.pb.h"
-#include "components/copresence/public/copresence_constants.h"
-#include "components/copresence/public/copresence_delegate.h"
-#include "components/copresence/rpc/http_post.h"
-#include "net/http/http_status_code.h"
-
-using google::protobuf::MessageLite;
-
-using audio_modem::AUDIBLE;
-using audio_modem::AudioToken;
-using audio_modem::INAUDIBLE;
-
-// TODO(ckehoe): Return error messages for bad requests.
-
-namespace copresence {
-
-const char RpcHandler::kReportRequestRpcName[] = "report";
-
-namespace {
-
-const int kTokenLoggingSuffix = 5;
-const int kInvalidTokenExpiryTimeMinutes = 10;
-const int kMaxInvalidTokens = 10000;
-const char kRegisterDeviceRpcName[] = "registerdevice";
-const char kDefaultCopresenceServer[] =
- "https://www.googleapis.com/copresence/v2/copresence";
-
-// UrlSafe is defined as:
-// '/' represented by a '_' and '+' represented by a '-'
-// TODO(rkc): Move this to the wrapper.
-std::string ToUrlSafe(std::string token) {
- base::ReplaceChars(token, "+", "-", &token);
- base::ReplaceChars(token, "/", "_", &token);
- return token;
-}
-
-// Logging
-
-// Checks for a copresence error. If there is one, logs it and returns true.
-bool IsErrorStatus(const Status& status) {
- if (status.code() != OK) {
- LOG(ERROR) << "Copresence error code " << status.code()
- << (status.message().empty() ? "" : ": " + status.message());
- }
- return status.code() != OK;
-}
-
-void LogIfErrorStatus(const util::error::Code& code,
- const std::string& context) {
- LOG_IF(ERROR, code != util::error::OK)
- << context << " error " << code << ". See "
- << "cs/google3/util/task/codes.proto for more info.";
-}
-
-// If any errors occurred, logs them and returns true.
-bool ReportErrorLogged(const ReportResponse& response) {
- bool result = IsErrorStatus(response.header().status());
-
- // The Report fails or succeeds as a unit. If any responses had errors,
- // the header will too. Thus we don't need to propagate individual errors.
- if (response.has_update_signals_response())
- LogIfErrorStatus(response.update_signals_response().status(), "Update");
- if (response.has_manage_messages_response())
- LogIfErrorStatus(response.manage_messages_response().status(), "Publish");
- if (response.has_manage_subscriptions_response()) {
- LogIfErrorStatus(response.manage_subscriptions_response().status(),
- "Subscribe");
- }
-
- return result;
-}
-
-const std::string LoggingStrForToken(const std::string& auth_token) {
- if (auth_token.empty())
- return "anonymous";
-
- std::string token_suffix = auth_token.substr(
- auth_token.length() - kTokenLoggingSuffix, kTokenLoggingSuffix);
- return "token ..." + token_suffix;
-}
-
-
-// Request construction
-
-template <typename T>
-BroadcastScanConfiguration GetBroadcastScanConfig(const T& msg) {
- if (msg.has_token_exchange_strategy() &&
- msg.token_exchange_strategy().has_broadcast_scan_configuration()) {
- return msg.token_exchange_strategy().broadcast_scan_configuration();
- }
- return BROADCAST_SCAN_CONFIGURATION_UNKNOWN;
-}
-
-std::unique_ptr<DeviceState> GetDeviceCapabilities(
- const ReportRequest& request) {
- std::unique_ptr<DeviceState> state(new DeviceState);
-
- TokenTechnology* ultrasound =
- state->mutable_capabilities()->add_token_technology();
- ultrasound->set_medium(AUDIO_ULTRASOUND_PASSBAND);
- ultrasound->add_instruction_type(TRANSMIT);
- ultrasound->add_instruction_type(RECEIVE);
-
- TokenTechnology* audible =
- state->mutable_capabilities()->add_token_technology();
- audible->set_medium(AUDIO_AUDIBLE_DTMF);
- audible->add_instruction_type(TRANSMIT);
- audible->add_instruction_type(RECEIVE);
-
- return state;
-}
-
-// TODO(ckehoe): We're keeping this code in a separate function for now
-// because we get a version string from Chrome, but the proto expects
-// an int64_t version. We should probably change the version proto
-// to handle a more detailed version.
-ClientVersion* CreateVersion(const std::string& client,
- const std::string& version_name) {
- ClientVersion* version = new ClientVersion;
- version->set_client(client);
- version->set_version_name(version_name);
- return version;
-}
-
-void AddTokenToRequest(const AudioToken& token, ReportRequest* request) {
- TokenObservation* token_observation =
- request->mutable_update_signals_request()->add_token_observation();
- token_observation->set_token_id(ToUrlSafe(token.token));
-
- TokenSignals* signals = token_observation->add_signals();
- signals->set_medium(token.audible ? AUDIO_AUDIBLE_DTMF
- : AUDIO_ULTRASOUND_PASSBAND);
- signals->set_observed_time_millis(base::Time::Now().ToJsTime());
-}
-
-} // namespace
-
-
-// Public functions.
-
-RpcHandler::RpcHandler(CopresenceDelegate* delegate,
- DirectiveHandler* directive_handler,
- CopresenceStateImpl* state,
- GCMHandler* gcm_handler,
- const MessagesCallback& new_messages_callback,
- const PostCallback& server_post_callback)
- : delegate_(delegate),
- directive_handler_(directive_handler),
- state_(state),
- gcm_handler_(gcm_handler),
- new_messages_callback_(new_messages_callback),
- server_post_callback_(server_post_callback),
- invalid_audio_token_cache_(
- base::TimeDelta::FromMinutes(kInvalidTokenExpiryTimeMinutes),
- kMaxInvalidTokens) {
- DCHECK(delegate_);
- DCHECK(directive_handler_);
- // |gcm_handler_| is optional.
-
- if (server_post_callback_.is_null()) {
- server_post_callback_ =
- base::Bind(&RpcHandler::SendHttpPost, base::Unretained(this));
- }
-
- if (gcm_handler_) {
- gcm_handler_->GetGcmId(
- base::Bind(&RpcHandler::RegisterGcmId, base::Unretained(this)));
- }
- }
-
-RpcHandler::~RpcHandler() {
- // TODO(ckehoe): Cancel the GCM callback?
- for (HttpPost* post : pending_posts_)
- delete post;
-}
-
-void RpcHandler::SendReportRequest(std::unique_ptr<ReportRequest> request,
- const std::string& app_id,
- const std::string& auth_token,
- const StatusCallback& status_callback) {
- DCHECK(request.get());
-
- // Check that the app, if any, has some kind of authentication token.
- // Don't allow it to piggyback on Chrome's credentials.
- if (!app_id.empty() && delegate_->GetAPIKey(app_id).empty() &&
- auth_token.empty()) {
- LOG(ERROR) << "App " << app_id << " has no API key or auth token";
- status_callback.Run(FAIL);
- return;
- }
-
- // Store just one auth token since we should have only one account
- // per instance of the copresence component.
- // TODO(ckehoe): We may eventually need to support multiple auth tokens.
- const bool authenticated = !auth_token.empty();
- if (authenticated && auth_token != auth_token_) {
- LOG_IF(ERROR, !auth_token_.empty())
- << "Overwriting old auth token: " << LoggingStrForToken(auth_token);
- auth_token_ = auth_token;
- }
-
- // Check that we have a "device" registered for this authentication state.
- bool queue_request;
- const std::string device_id = delegate_->GetDeviceId(authenticated);
- if (device_id.empty()) {
- queue_request = true;
- if (pending_registrations_.count(authenticated) == 0)
- RegisterDevice(authenticated);
- // else, registration is already in progress.
- } else {
- queue_request = false;
- }
-
- // We're not registered, or registration is in progress.
- if (queue_request) {
- pending_requests_queue_.push_back(new PendingRequest(
- std::move(request), app_id, authenticated, status_callback));
- return;
- }
-
- DVLOG(3) << "Sending ReportRequest to server.";
-
- // If we are unpublishing or unsubscribing, we need to stop those publish or
- // subscribes right away, we don't need to wait for the server to tell us.
- ProcessRemovedOperations(*request);
-
- request->mutable_update_signals_request()->set_allocated_state(
- GetDeviceCapabilities(*request).release());
-
- AddPlayingTokens(request.get());
-
- request->set_allocated_header(CreateRequestHeader(app_id, device_id));
- server_post_callback_.Run(
- delegate_->GetRequestContext(), kReportRequestRpcName,
- delegate_->GetAPIKey(app_id), auth_token,
- base::WrapUnique<MessageLite>(request.release()),
- // On destruction, this request will be cancelled.
- base::Bind(&RpcHandler::ReportResponseHandler, base::Unretained(this),
- status_callback));
-}
-
-void RpcHandler::ReportTokens(const std::vector<AudioToken>& tokens) {
- DCHECK(!tokens.empty());
-
- std::unique_ptr<ReportRequest> request(new ReportRequest);
- for (const AudioToken& token : tokens) {
- if (invalid_audio_token_cache_.HasKey(ToUrlSafe(token.token)))
- continue;
- DVLOG(3) << "Sending token " << token.token << " to server";
- AddTokenToRequest(token, request.get());
- }
-
- ReportOnAllDevices(std::move(request));
-}
-
-
-// Private functions.
-
-RpcHandler::PendingRequest::PendingRequest(
- std::unique_ptr<ReportRequest> report,
- const std::string& app_id,
- bool authenticated,
- const StatusCallback& callback)
- : report(std::move(report)),
- app_id(app_id),
- authenticated(authenticated),
- callback(callback) {}
-
-RpcHandler::PendingRequest::~PendingRequest() {}
-
-void RpcHandler::RegisterDevice(const bool authenticated) {
- DVLOG(2) << "Sending " << (authenticated ? "authenticated" : "anonymous")
- << " registration to server.";
-
- std::unique_ptr<RegisterDeviceRequest> request(new RegisterDeviceRequest);
-
- // Add a GCM ID for authenticated registration, if we have one.
- if (!authenticated || gcm_id_.empty()) {
- request->mutable_push_service()->set_service(PUSH_SERVICE_NONE);
- } else {
- DVLOG(2) << "Registering GCM ID with " << LoggingStrForToken(auth_token_);
- request->mutable_push_service()->set_service(GCM);
- request->mutable_push_service()->mutable_gcm_registration()
- ->set_device_token(gcm_id_);
- }
-
- // Only identify as a Chrome device if we're in anonymous mode.
- // Authenticated calls come from a "GAIA device".
- if (!authenticated) {
- // Make sure this isn't a duplicate anonymous registration.
- // Duplicate authenticated registrations are allowed, to update the GCM ID.
- DCHECK(delegate_->GetDeviceId(false).empty())
- << "Attempted anonymous re-registration";
-
- Identity* identity =
- request->mutable_device_identifiers()->mutable_registrant();
- identity->set_type(CHROME);
- }
-
- bool gcm_pending = authenticated && gcm_handler_ && gcm_id_.empty();
- pending_registrations_.insert(authenticated);
- request->set_allocated_header(CreateRequestHeader(
- // The device is empty on first registration.
- // When re-registering to pass on the GCM ID, it will be present.
- std::string(), delegate_->GetDeviceId(authenticated)));
- if (authenticated)
- DCHECK(!auth_token_.empty());
- server_post_callback_.Run(
- delegate_->GetRequestContext(), kRegisterDeviceRpcName, std::string(),
- authenticated ? auth_token_ : std::string(),
- base::WrapUnique<MessageLite>(request.release()),
- // On destruction, this request will be cancelled.
- base::Bind(&RpcHandler::RegisterResponseHandler, base::Unretained(this),
- authenticated, gcm_pending));
-}
-
-void RpcHandler::ProcessQueuedRequests(const bool authenticated) {
- // If there is no device ID for this auth state, registration failed.
- bool registration_failed = delegate_->GetDeviceId(authenticated).empty();
-
- // We momentarily take ownership of all the pointers in the queue.
- // They are either deleted here or passed on to a new queue.
- ScopedVector<PendingRequest> requests_being_processed;
- std::swap(requests_being_processed, pending_requests_queue_);
- for (PendingRequest* request : requests_being_processed) {
- if (request->authenticated == authenticated) {
- if (registration_failed) {
- request->callback.Run(FAIL);
- } else {
- if (request->authenticated)
- DCHECK(!auth_token_.empty());
- SendReportRequest(std::move(request->report), request->app_id,
- request->authenticated ? auth_token_ : std::string(),
- request->callback);
- }
- delete request;
- } else {
- // The request is in a different auth state.
- pending_requests_queue_.push_back(request);
- }
- }
-
- // Only keep the requests that weren't processed.
- // All the pointers in the queue are now spoken for.
- requests_being_processed.weak_clear();
-}
-
-void RpcHandler::ReportOnAllDevices(std::unique_ptr<ReportRequest> request) {
- std::vector<bool> auth_states;
- if (!auth_token_.empty() && !delegate_->GetDeviceId(true).empty())
- auth_states.push_back(true);
- if (!delegate_->GetDeviceId(false).empty())
- auth_states.push_back(false);
- if (auth_states.empty()) {
- VLOG(2) << "Skipping reporting because no device IDs are registered";
- return;
- }
-
- for (bool authenticated : auth_states) {
- SendReportRequest(
- base::WrapUnique(new ReportRequest(*request)), std::string(),
- authenticated ? auth_token_ : std::string(), StatusCallback());
- }
-}
-
-// Store a GCM ID and send it to the server if needed. The constructor passes
-// this callback to the GCMHandler to receive the ID whenever it's ready.
-// It may be returned immediately, if the ID is cached, or require a server
-// round-trip. This ID must then be passed along to the copresence server.
-// There are a few ways this can happen:
-//
-// 1. The GCM ID is available when we first register, and is passed along
-// with the RegisterDeviceRequest.
-//
-// 2. The GCM ID becomes available after the RegisterDeviceRequest has
-// completed. Then this function will invoke RegisterDevice()
-// again to pass on the ID.
-//
-// 3. The GCM ID becomes available after the RegisterDeviceRequest is sent,
-// but before it completes. In this case, the gcm_pending flag is passed
-// through to the RegisterResponseHandler, which invokes RegisterDevice()
-// again to pass on the ID. This function must skip pending registrations,
-// as the device ID will be empty.
-//
-// TODO(ckehoe): Add tests for these scenarios.
-void RpcHandler::RegisterGcmId(const std::string& gcm_id) {
- gcm_id_ = gcm_id;
- if (!gcm_id.empty()) {
- const std::string& device_id = delegate_->GetDeviceId(true);
- if (!auth_token_.empty() && !device_id.empty())
- RegisterDevice(true);
- }
-}
-
-void RpcHandler::RegisterResponseHandler(
- bool authenticated,
- bool gcm_pending,
- HttpPost* completed_post,
- int http_status_code,
- const std::string& response_data) {
- if (completed_post) {
- size_t elements_erased = pending_posts_.erase(completed_post);
- DCHECK_GT(elements_erased, 0u);
- }
-
- size_t registrations_completed = pending_registrations_.erase(authenticated);
- DCHECK_GT(registrations_completed, 0u);
-
- RegisterDeviceResponse response;
- const std::string token_str =
- LoggingStrForToken(authenticated ? auth_token_ : std::string());
- if (http_status_code != net::HTTP_OK) {
- // TODO(ckehoe): Retry registration if appropriate.
- LOG(ERROR) << token_str << " device registration failed";
- } else if (!response.ParseFromString(response_data)) {
- LOG(ERROR) << "Invalid RegisterDeviceResponse:\n" << response_data;
- } else if (!IsErrorStatus(response.header().status())) {
- const std::string& device_id = response.registered_device_id();
- DCHECK(!device_id.empty());
- delegate_->SaveDeviceId(authenticated, device_id);
- DVLOG(2) << token_str << " device registration successful. Id: "
- << device_id;
-
- // If we have a GCM ID now, and didn't before, pass it on to the server.
- if (gcm_pending && !gcm_id_.empty())
- RegisterDevice(authenticated);
- }
-
- // Send or fail requests on this auth token.
- ProcessQueuedRequests(authenticated);
-}
-
-void RpcHandler::ReportResponseHandler(const StatusCallback& status_callback,
- HttpPost* completed_post,
- int http_status_code,
- const std::string& response_data) {
- if (completed_post) {
- size_t elements_erased = pending_posts_.erase(completed_post);
- DCHECK_GT(elements_erased, 0u);
- }
-
- if (http_status_code != net::HTTP_OK) {
- if (!status_callback.is_null())
- status_callback.Run(FAIL);
- return;
- }
-
- DVLOG(3) << "Received ReportResponse.";
- ReportResponse response;
- if (!response.ParseFromString(response_data)) {
- LOG(ERROR) << "Invalid ReportResponse";
- if (!status_callback.is_null())
- status_callback.Run(FAIL);
- return;
- }
-
- if (ReportErrorLogged(response)) {
- if (!status_callback.is_null())
- status_callback.Run(FAIL);
- return;
- }
-
- for (const MessageResult& result :
- response.manage_messages_response().published_message_result()) {
- DVLOG(2) << "Published message with id " << result.published_message_id();
- }
-
- for (const SubscriptionResult& result :
- response.manage_subscriptions_response().subscription_result()) {
- DVLOG(2) << "Created subscription with id " << result.subscription_id();
- }
-
- if (response.has_update_signals_response()) {
- const UpdateSignalsResponse& update_response =
- response.update_signals_response();
- new_messages_callback_.Run(update_response.message());
-
- for (const Directive& directive : update_response.directive())
- directive_handler_->AddDirective(directive);
-
- for (const Token& token : update_response.token()) {
- if (state_)
- state_->UpdateTokenStatus(token.id(), token.status());
- switch (token.status()) {
- case VALID:
- // TODO(rkc/ckehoe): Store the token in a |valid_token_cache_| with a
- // short TTL (like 10s) and send it up with every report request.
- // Then we'll still get messages while we're waiting to hear it again.
- VLOG(1) << "Got valid token " << token.id();
- break;
- case INVALID:
- DVLOG(3) << "Discarding invalid token " << token.id();
- invalid_audio_token_cache_.Add(token.id(), true);
- break;
- default:
- DVLOG(2) << "Token " << token.id() << " has status code "
- << token.status();
- }
- }
- }
-
- // TODO(ckehoe): Return a more detailed status response.
- if (!status_callback.is_null())
- status_callback.Run(SUCCESS);
-}
-
-void RpcHandler::ProcessRemovedOperations(const ReportRequest& request) {
- // Remove unpublishes.
- if (request.has_manage_messages_request()) {
- for (const std::string& unpublish :
- request.manage_messages_request().id_to_unpublish()) {
- directive_handler_->RemoveDirectives(unpublish);
- }
- }
-
- // Remove unsubscribes.
- if (request.has_manage_subscriptions_request()) {
- for (const std::string& unsubscribe :
- request.manage_subscriptions_request().id_to_unsubscribe()) {
- directive_handler_->RemoveDirectives(unsubscribe);
- }
- }
-}
-
-void RpcHandler::AddPlayingTokens(ReportRequest* request) {
- const std::string& audible_token =
- directive_handler_->GetCurrentAudioToken(AUDIBLE);
- const std::string& inaudible_token =
- directive_handler_->GetCurrentAudioToken(INAUDIBLE);
-
- if (!audible_token.empty())
- AddTokenToRequest(AudioToken(audible_token, true), request);
- if (!inaudible_token.empty())
- AddTokenToRequest(AudioToken(inaudible_token, false), request);
-}
-
-// TODO(ckehoe): Pass in the version string and
-// group this with the local functions up top.
-RequestHeader* RpcHandler::CreateRequestHeader(
- const std::string& app_id,
- const std::string& device_id) const {
- RequestHeader* header = new RequestHeader;
-
- header->set_allocated_framework_version(CreateVersion(
- "Chrome", delegate_->GetPlatformVersionString()));
- if (!app_id.empty())
- header->set_allocated_client_version(CreateVersion(app_id, std::string()));
- header->set_current_time_millis(base::Time::Now().ToJsTime());
- if (!device_id.empty())
- header->set_registered_device_id(device_id);
-
- DeviceFingerprint* fingerprint = new DeviceFingerprint;
- fingerprint->set_platform_version(delegate_->GetPlatformVersionString());
- fingerprint->set_type(CHROME_PLATFORM_TYPE);
- header->set_allocated_device_fingerprint(fingerprint);
-
- return header;
-}
-
-void RpcHandler::SendHttpPost(net::URLRequestContextGetter* url_context_getter,
- const std::string& rpc_name,
- const std::string& api_key,
- const std::string& auth_token,
- std::unique_ptr<MessageLite> request_proto,
- const PostCleanupCallback& callback) {
- // Create the base URL to call.
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- const std::string copresence_server_host =
- command_line->HasSwitch(switches::kCopresenceServer) ?
- command_line->GetSwitchValueASCII(switches::kCopresenceServer) :
- kDefaultCopresenceServer;
-
- // Create the request and keep a pointer until it completes.
- HttpPost* http_post = new HttpPost(
- url_context_getter,
- copresence_server_host,
- rpc_name,
- api_key,
- auth_token,
- command_line->GetSwitchValueASCII(switches::kCopresenceTracingToken),
- *request_proto);
-
- http_post->Start(base::Bind(callback, http_post));
- pending_posts_.insert(http_post);
-}
-
-} // namespace copresence
diff --git a/chromium/components/copresence/rpc/rpc_handler.h b/chromium/components/copresence/rpc/rpc_handler.h
deleted file mode 100644
index 16fd1184051..00000000000
--- a/chromium/components/copresence/rpc/rpc_handler.h
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright 2015 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 COMPONENTS_COPRESENCE_RPC_RPC_HANDLER_H_
-#define COMPONENTS_COPRESENCE_RPC_RPC_HANDLER_H_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/callback_forward.h"
-#include "base/memory/scoped_vector.h"
-#include "components/audio_modem/public/audio_modem_types.h"
-#include "components/copresence/proto/enums.pb.h"
-#include "components/copresence/public/copresence_constants.h"
-#include "components/copresence/public/copresence_delegate.h"
-#include "components/copresence/timed_map.h"
-
-namespace copresence {
-
-class CopresenceDelegate;
-class CopresenceStateImpl;
-class DirectiveHandler;
-class GCMHandler;
-class HttpPost;
-class ReportRequest;
-class RequestHeader;
-class SubscribedMessage;
-
-// This class handles all communication with the copresence server.
-// Clients provide a ReportRequest proto containing publishes, subscribes,
-// and token observations they want to send to the server. The RpcHandler
-// will fill in details like the RequestHeader and DeviceCapabilities,
-// and dispatch the results of the server call to the appropriate parts
-// of the system.
-//
-// To create an RpcHandler, clients will need to provide a few other classes
-// that support its functionality. Notable among them is the CopresenceDelegate,
-// an interface clients must implement to provide settings and functionality
-// that may depend on the environment. See the definition in
-// //components/copresence/public/copresence_delegate.h.
-//
-// Here is an example of creating and using an RpcHandler.
-// The GCMHandler and CopresenceStateImpl are optional.
-//
-// MyDelegate delegate(...);
-// copresence::DirectiveHandlerImpl directive_handler;
-//
-// RpcHandler handler(&delegate,
-// &directive_handler,
-// nullptr,
-// nullptr,
-// base::Bind(&HandleMessages));
-//
-// std::unique_ptr<ReportRequest> request(new ReportRequest);
-// (Fill in ReportRequest.)
-//
-// handler.SendReportRequest(std::move(request),
-// "my_app_id",
-// "",
-// base::Bind(&HandleStatus));
-//
-// The server will respond with directives, which get passed to the
-// DirectiveHandlerImpl.
-//
-// Tokens from the audio modem should also be forwarded
-// via ReportTokens() so that messages get delivered properly.
-class RpcHandler final {
- public:
- // An HttpPost::ResponseCallback along with an HttpPost object to be deleted.
- // Arguments:
- // HttpPost*: The handler should take ownership of (i.e. delete) this object.
- // int: The HTTP status code of the response.
- // string: The contents of the response.
- using PostCleanupCallback = base::Callback<void(HttpPost*,
- int,
- const std::string&)>;
-
- // Callback to allow tests to stub out HTTP POST behavior.
- // Arguments:
- // URLRequestContextGetter: Context for the HTTP POST request.
- // string: Name of the rpc to invoke. URL format: server.google.com/rpc_name
- // string: The API key to pass in the request.
- // string: The auth token to pass with the request.
- // MessageLite: Contents of POST request to be sent. This needs to be
- // a (scoped) pointer to ease handling of the abstract MessageLite class.
- // PostCleanupCallback: Receives the response to the request.
- using PostCallback =
- base::Callback<void(net::URLRequestContextGetter*,
- const std::string&,
- const std::string&,
- const std::string&,
- std::unique_ptr<google::protobuf::MessageLite>,
- const PostCleanupCallback&)>;
-
- // Report rpc name to send to Apiary.
- static const char kReportRequestRpcName[];
-
- // Constructor. The CopresenceStateImpl and GCMHandler may be null.
- // The first four parameters are owned by the caller and (if not null)
- // must outlive the RpcHandler.
- RpcHandler(CopresenceDelegate* delegate,
- DirectiveHandler* directive_handler,
- CopresenceStateImpl* state,
- GCMHandler* gcm_handler,
- const MessagesCallback& new_messages_callback,
- const PostCallback& server_post_callback = PostCallback());
-
- // Not copyable.
- RpcHandler(const RpcHandler&) = delete;
- void operator=(const RpcHandler&) = delete;
-
- ~RpcHandler();
-
- // Sends a ReportRequest from a specific app, and get notified of completion.
- void SendReportRequest(std::unique_ptr<ReportRequest> request,
- const std::string& app_id,
- const std::string& auth_token,
- const StatusCallback& callback);
-
- // Reports a set of tokens to the server for a given medium.
- // Uses all active auth tokens (if any).
- void ReportTokens(const std::vector<audio_modem::AudioToken>& tokens);
-
- private:
- // A queued ReportRequest along with its metadata.
- struct PendingRequest {
- PendingRequest(std::unique_ptr<ReportRequest> report,
- const std::string& app_id,
- bool authenticated,
- const StatusCallback& callback);
- ~PendingRequest();
-
- std::unique_ptr<ReportRequest> report;
- const std::string app_id;
- const bool authenticated;
- const StatusCallback callback;
- };
-
- friend class RpcHandlerTest;
-
- // Before accepting any other calls, the server requires registration,
- // which is tied to the auth token (or lack thereof) used to call Report.
- void RegisterDevice(bool authenticated);
-
- // Device registration has completed. Send the requests that it was blocking.
- void ProcessQueuedRequests(bool authenticated);
-
- // Sends a ReportRequest from Chrome itself, i.e. no app id.
- void ReportOnAllDevices(std::unique_ptr<ReportRequest> request);
-
- // Stores a GCM ID and send it to the server if needed.
- void RegisterGcmId(const std::string& gcm_id);
-
- // Server call response handlers.
- void RegisterResponseHandler(bool authenticated,
- bool gcm_pending,
- HttpPost* completed_post,
- int http_status_code,
- const std::string& response_data);
- void ReportResponseHandler(const StatusCallback& status_callback,
- HttpPost* completed_post,
- int http_status_code,
- const std::string& response_data);
-
- // Removes unpublished or unsubscribed operations from the directive handlers.
- void ProcessRemovedOperations(const ReportRequest& request);
-
- // Adds all currently playing tokens to the update signals in this report
- // request. This ensures that the server doesn't keep issueing new tokens to
- // us when we're already playing valid tokens.
- void AddPlayingTokens(ReportRequest* request);
-
- void DispatchMessages(
- const google::protobuf::RepeatedPtrField<SubscribedMessage>&
- subscribed_messages);
-
- RequestHeader* CreateRequestHeader(const std::string& app_id,
- const std::string& device_id) const;
-
- // Wrapper for the http post constructor. This is the default way
- // to contact the server, but it can be overridden for testing.
- void SendHttpPost(
- net::URLRequestContextGetter* url_context_getter,
- const std::string& rpc_name,
- const std::string& api_key,
- const std::string& auth_token,
- std::unique_ptr<google::protobuf::MessageLite> request_proto,
- const PostCleanupCallback& callback);
-
- // These belong to the caller.
- CopresenceDelegate* const delegate_;
- DirectiveHandler* const directive_handler_;
- CopresenceStateImpl* state_;
- GCMHandler* const gcm_handler_;
-
- MessagesCallback new_messages_callback_;
- PostCallback server_post_callback_;
-
- ScopedVector<PendingRequest> pending_requests_queue_;
- TimedMap<std::string, bool> invalid_audio_token_cache_;
- std::set<HttpPost*> pending_posts_;
- std::set<bool> pending_registrations_;
- std::string auth_token_;
- std::string gcm_id_;
-};
-
-} // namespace copresence
-
-#endif // COMPONENTS_COPRESENCE_RPC_RPC_HANDLER_H_
diff --git a/chromium/components/copresence/rpc/rpc_handler_unittest.cc b/chromium/components/copresence/rpc/rpc_handler_unittest.cc
deleted file mode 100644
index ea4baab8f6b..00000000000
--- a/chromium/components/copresence/rpc/rpc_handler_unittest.cc
+++ /dev/null
@@ -1,348 +0,0 @@
-// Copyright 2015 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 "components/copresence/rpc/rpc_handler.h"
-
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/scoped_vector.h"
-#include "base/message_loop/message_loop.h"
-#include "components/audio_modem/public/modem.h"
-#include "components/audio_modem/test/stub_whispernet_client.h"
-#include "components/copresence/copresence_state_impl.h"
-#include "components/copresence/handlers/directive_handler.h"
-#include "components/copresence/proto/data.pb.h"
-#include "components/copresence/proto/enums.pb.h"
-#include "components/copresence/proto/rpcs.pb.h"
-#include "components/copresence/test/fake_directive_handler.h"
-#include "net/http/http_status_code.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-using google::protobuf::MessageLite;
-using google::protobuf::RepeatedPtrField;
-
-using testing::ElementsAre;
-using testing::Property;
-using testing::SizeIs;
-
-using audio_modem::AudioToken;
-using audio_modem::WhispernetClient;
-
-namespace copresence {
-
-namespace {
-
-const char kChromeVersion[] = "Chrome Version String";
-
-void IgnoreMessages(
- const RepeatedPtrField<SubscribedMessage>& /* messages */) {}
-
-} // namespace
-
-class RpcHandlerTest : public testing::Test, public CopresenceDelegate {
- public:
- RpcHandlerTest()
- : whispernet_client_(new audio_modem::StubWhispernetClient),
- // TODO(ckehoe): Use a FakeCopresenceState here
- // and test that it gets called correctly.
- rpc_handler_(this,
- &directive_handler_,
- nullptr,
- nullptr,
- base::Bind(&IgnoreMessages),
- base::Bind(&RpcHandlerTest::CaptureHttpPost,
- base::Unretained(this))),
- status_(SUCCESS) {}
-
- // CopresenceDelegate implementation
-
- void HandleMessages(const std::string& /* app_id */,
- const std::string& subscription_id,
- const std::vector<Message>& messages) override {
- NOTREACHED();
- }
-
- void HandleStatusUpdate(CopresenceStatus /* status */) override {
- NOTREACHED();
- }
-
- net::URLRequestContextGetter* GetRequestContext() const override {
- return nullptr;
- }
-
- std::string GetPlatformVersionString() const override {
- return kChromeVersion;
- }
-
- std::string GetAPIKey(const std::string& app_id) const override {
- return app_id + " API Key";
- }
-
- WhispernetClient* GetWhispernetClient() override {
- return whispernet_client_.get();
- }
-
- // TODO(ckehoe): Add GCM tests.
- gcm::GCMDriver* GetGCMDriver() override {
- return nullptr;
- }
-
- std::string GetDeviceId(bool authenticated) override {
- return device_id_by_auth_state_[authenticated];
- }
-
- void SaveDeviceId(bool authenticated, const std::string& device_id) override {
- device_id_by_auth_state_[authenticated] = device_id;
- }
-
- protected:
-
- // Send test input to RpcHandler
-
- void RegisterDevice(bool authenticated) {
- rpc_handler_.RegisterDevice(authenticated);
- }
-
- void SendRegisterResponse(bool authenticated,
- const std::string& device_id) {
- RegisterDeviceResponse response;
- response.set_registered_device_id(device_id);
- response.mutable_header()->mutable_status()->set_code(OK);
-
- std::string serialized_response;
- response.SerializeToString(&serialized_response);
- rpc_handler_.RegisterResponseHandler(
- authenticated, false, nullptr, net::HTTP_OK, serialized_response);
- }
-
- void SendReport(std::unique_ptr<ReportRequest> request,
- const std::string& app_id,
- const std::string& auth_token) {
- rpc_handler_.SendReportRequest(std::move(request), app_id, auth_token,
- StatusCallback());
- }
-
- void SendReportResponse(int status_code,
- std::unique_ptr<ReportResponse> response) {
- response->mutable_header()->mutable_status()->set_code(OK);
-
- std::string serialized_response;
- response->SerializeToString(&serialized_response);
- rpc_handler_.ReportResponseHandler(
- base::Bind(&RpcHandlerTest::CaptureStatus, base::Unretained(this)),
- nullptr,
- status_code,
- serialized_response);
- }
-
- // Read and modify RpcHandler state
-
- void SetAuthToken(const std::string& auth_token) {
- rpc_handler_.auth_token_ = auth_token;
- }
-
- const ScopedVector<RpcHandler::PendingRequest>& request_queue() const {
- return rpc_handler_.pending_requests_queue_;
- }
-
- void AddInvalidToken(const std::string& token) {
- rpc_handler_.invalid_audio_token_cache_.Add(token, true);
- }
-
- bool TokenIsInvalid(const std::string& token) {
- return rpc_handler_.invalid_audio_token_cache_.HasKey(token);
- }
-
- // For rpc_handler_.invalid_audio_token_cache_
- base::MessageLoop message_loop_;
-
- std::unique_ptr<WhispernetClient> whispernet_client_;
- FakeDirectiveHandler directive_handler_;
- RpcHandler rpc_handler_;
-
- std::map<bool, std::string> device_id_by_auth_state_;
-
- CopresenceStatus status_;
- std::string rpc_name_;
- std::string api_key_;
- std::string auth_token_;
- ScopedVector<MessageLite> request_protos_;
-
- private:
- void CaptureHttpPost(
- net::URLRequestContextGetter* url_context_getter,
- const std::string& rpc_name,
- const std::string& api_key,
- const std::string& auth_token,
- std::unique_ptr<MessageLite> request_proto,
- const RpcHandler::PostCleanupCallback& response_callback) {
- rpc_name_ = rpc_name;
- api_key_ = api_key;
- auth_token_ = auth_token;
- request_protos_.push_back(request_proto.release());
- }
-
- void CaptureStatus(CopresenceStatus status) {
- status_ = status;
- }
-};
-
-TEST_F(RpcHandlerTest, RegisterDevice) {
- RegisterDevice(false);
- EXPECT_THAT(request_protos_, SizeIs(1));
- const RegisterDeviceRequest* registration =
- static_cast<RegisterDeviceRequest*>(request_protos_[0]);
- EXPECT_EQ(CHROME, registration->device_identifiers().registrant().type());
-
- SetAuthToken("Register auth");
- RegisterDevice(true);
- EXPECT_THAT(request_protos_, SizeIs(2));
- registration = static_cast<RegisterDeviceRequest*>(request_protos_[1]);
- EXPECT_FALSE(registration->has_device_identifiers());
-}
-
-TEST_F(RpcHandlerTest, RequestQueuing) {
- // Send a report.
- ReportRequest* report = new ReportRequest;
- report->mutable_manage_messages_request()->add_id_to_unpublish("unpublish");
- SendReport(base::WrapUnique(report), "Q App ID", "Q Auth Token");
- EXPECT_THAT(request_queue(), SizeIs(1));
- EXPECT_TRUE(request_queue()[0]->authenticated);
-
- // Check for registration request.
- EXPECT_THAT(request_protos_, SizeIs(1));
- const RegisterDeviceRequest* registration =
- static_cast<RegisterDeviceRequest*>(request_protos_[0]);
- EXPECT_FALSE(registration->device_identifiers().has_registrant());
- EXPECT_EQ("Q Auth Token", auth_token_);
-
- // Send a second report.
- report = new ReportRequest;
- report->mutable_manage_subscriptions_request()->add_id_to_unsubscribe(
- "unsubscribe");
- SendReport(base::WrapUnique(report), "Q App ID", "Q Auth Token");
- EXPECT_THAT(request_protos_, SizeIs(1));
- EXPECT_THAT(request_queue(), SizeIs(2));
- EXPECT_TRUE(request_queue()[1]->authenticated);
-
- // Send an anonymous report.
- report = new ReportRequest;
- report->mutable_update_signals_request()->add_token_observation()
- ->set_token_id("Q Audio Token");
- SendReport(base::WrapUnique(report), "Q App ID", "");
- EXPECT_THAT(request_queue(), SizeIs(3));
- EXPECT_FALSE(request_queue()[2]->authenticated);
-
- // Check for another registration request.
- EXPECT_THAT(request_protos_, SizeIs(2));
- registration = static_cast<RegisterDeviceRequest*>(request_protos_[1]);
- EXPECT_TRUE(registration->device_identifiers().has_registrant());
- EXPECT_EQ("", auth_token_);
-
- // Respond to the first registration.
- SendRegisterResponse(true, "Q Auth Device ID");
- EXPECT_EQ("Q Auth Device ID", device_id_by_auth_state_[true]);
-
- // Check that queued reports are sent.
- EXPECT_THAT(request_protos_, SizeIs(4));
- EXPECT_THAT(request_queue(), SizeIs(1));
- EXPECT_THAT(directive_handler_.removed_directives(),
- ElementsAre("unpublish", "unsubscribe"));
- report = static_cast<ReportRequest*>(request_protos_[2]);
- EXPECT_EQ("unpublish", report->manage_messages_request().id_to_unpublish(0));
- report = static_cast<ReportRequest*>(request_protos_[3]);
- EXPECT_EQ("unsubscribe",
- report->manage_subscriptions_request().id_to_unsubscribe(0));
-
- // Respond to the second registration.
- SendRegisterResponse(false, "Q Anonymous Device ID");
- EXPECT_EQ("Q Anonymous Device ID", device_id_by_auth_state_[false]);
-
- // Check for last report.
- EXPECT_THAT(request_protos_, SizeIs(5));
- EXPECT_TRUE(request_queue().empty());
- report = static_cast<ReportRequest*>(request_protos_[4]);
- EXPECT_EQ("Q Audio Token",
- report->update_signals_request().token_observation(0).token_id());
-}
-
-TEST_F(RpcHandlerTest, CreateRequestHeader) {
- device_id_by_auth_state_[true] = "CreateRequestHeader Device ID";
- SendReport(base::WrapUnique(new ReportRequest), "CreateRequestHeader App",
- "CreateRequestHeader Auth Token");
-
- EXPECT_EQ(RpcHandler::kReportRequestRpcName, rpc_name_);
- EXPECT_EQ("CreateRequestHeader App API Key", api_key_);
- EXPECT_EQ("CreateRequestHeader Auth Token", auth_token_);
- const ReportRequest* report = static_cast<ReportRequest*>(request_protos_[0]);
- EXPECT_EQ(kChromeVersion,
- report->header().framework_version().version_name());
- EXPECT_EQ("CreateRequestHeader App",
- report->header().client_version().client());
- EXPECT_EQ("CreateRequestHeader Device ID",
- report->header().registered_device_id());
- EXPECT_EQ(CHROME_PLATFORM_TYPE,
- report->header().device_fingerprint().type());
-}
-
-TEST_F(RpcHandlerTest, ReportTokens) {
- std::vector<AudioToken> test_tokens;
- test_tokens.push_back(AudioToken("token 1", false));
- test_tokens.push_back(AudioToken("token 2", false));
- test_tokens.push_back(AudioToken("token 3", true));
- AddInvalidToken("token 2");
-
- device_id_by_auth_state_[false] = "ReportTokens Anonymous Device";
- device_id_by_auth_state_[true] = "ReportTokens Auth Device";
- SetAuthToken("ReportTokens Auth");
-
- rpc_handler_.ReportTokens(test_tokens);
- EXPECT_EQ(RpcHandler::kReportRequestRpcName, rpc_name_);
- EXPECT_EQ(" API Key", api_key_);
- EXPECT_THAT(request_protos_, SizeIs(2));
- const ReportRequest* report = static_cast<ReportRequest*>(request_protos_[0]);
- RepeatedPtrField<TokenObservation> tokens_sent =
- report->update_signals_request().token_observation();
- EXPECT_THAT(tokens_sent, ElementsAre(
- Property(&TokenObservation::token_id, "token 1"),
- Property(&TokenObservation::token_id, "token 3"),
- Property(&TokenObservation::token_id, "current audible"),
- Property(&TokenObservation::token_id, "current inaudible")));
-}
-
-TEST_F(RpcHandlerTest, ReportResponseHandler) {
- // Fail on HTTP status != 200.
- std::unique_ptr<ReportResponse> response(new ReportResponse);
- status_ = SUCCESS;
- SendReportResponse(net::HTTP_BAD_REQUEST, std::move(response));
- EXPECT_EQ(FAIL, status_);
-
- // Construct a test ReportResponse.
- response.reset(new ReportResponse);
- response->mutable_header()->mutable_status()->set_code(OK);
- UpdateSignalsResponse* update_response =
- response->mutable_update_signals_response();
- update_response->set_status(util::error::OK);
- Token* invalid_token = update_response->add_token();
- invalid_token->set_id("bad token");
- invalid_token->set_status(INVALID);
- update_response->add_directive()->set_subscription_id("Subscription 1");
- update_response->add_directive()->set_subscription_id("Subscription 2");
-
- // Check processing.
- status_ = FAIL;
- SendReportResponse(net::HTTP_OK, std::move(response));
- EXPECT_EQ(SUCCESS, status_);
- EXPECT_TRUE(TokenIsInvalid("bad token"));
- EXPECT_THAT(directive_handler_.added_directives(),
- ElementsAre("Subscription 1", "Subscription 2"));
-}
-
-} // namespace copresence