diff --git a/components/BUILD.gn b/components/BUILD.gn index ebc1e63614b5..80379139c4e1 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn @@ -159,6 +159,7 @@ group("all_components") { if (!is_ios && !is_android) { deps += [ + "//components/copresence", "//components/storage_monitor", ] } diff --git a/components/OWNERS b/components/OWNERS index e721131b6a81..62a4be48cb61 100644 --- a/components/OWNERS +++ b/components/OWNERS @@ -30,6 +30,11 @@ per-file cloud_devices*=gene@chromium.org per-file cloud_devices*=noamsml@chromium.org per-file cloud_devices*=vitalybuka@chromium.org +per-file copresence.gypi=rkc@chromium.org +per-file copresence.gypi=ckehoe@chromium.org +per-file copresence.gypi=xiyuan@chromium.org +per-file copresence.gypi=derat@chromium.org + per-file cronet*=mef@chromium.org per-file cronet*=mmenke@chromium.org diff --git a/components/components.gyp b/components/components.gyp index 85a1137aaf75..65e7ecd0795b 100644 --- a/components/components.gyp +++ b/components/components.gyp @@ -76,6 +76,7 @@ }], ['OS != "ios" and OS != "android"', { 'includes': [ + 'copresence.gypi', 'storage_monitor.gypi', 'usb_service.gypi', ] diff --git a/components/copresence.gypi b/components/copresence.gypi new file mode 100644 index 000000000000..98b2dc1bb96f --- /dev/null +++ b/components/copresence.gypi @@ -0,0 +1,52 @@ +# 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. + +{ + 'targets': [ + { + 'target_name': 'copresence', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + '../net/net.gyp:net', + 'copresence_proto', + ], + 'include_dirs': [ + '..', + ], + 'sources': [ + 'copresence/copresence_client.cc', + 'copresence/public/copresence_client_delegate.h', + 'copresence/public/copresence_client.h', + 'copresence/public/whispernet_client.h', + 'copresence/rpc/rpc_handler.cc', + 'copresence/rpc/rpc_handler.h', + ], + 'export_dependent_settings': [ + 'copresence_proto', + ], + }, + { + # Protobuf compiler / generate rule for copresence. + # GN version: //components/copresence/proto + # Note: These protos are auto-generated from the protos of the + # Copresence server. Currently this strips all formatting and comments + # but makes sure that we are always using up to date protos. + 'target_name': 'copresence_proto', + 'type': 'static_library', + 'sources': [ + 'copresence/proto/codes.proto', + 'copresence/proto/data.proto', + 'copresence/proto/enums.proto', + 'copresence/proto/identity.proto', + 'copresence/proto/rpcs.proto', + ], + 'variables': { + 'proto_in_dir': 'copresence/proto', + 'proto_out_dir': 'components/copresence/proto', + }, + 'includes': [ '../build/protoc.gypi' ] + }, + ], +} diff --git a/components/copresence/BUILD.gn b/components/copresence/BUILD.gn new file mode 100644 index 000000000000..cb0a5f32f6f1 --- /dev/null +++ b/components/copresence/BUILD.gn @@ -0,0 +1,20 @@ +# 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. + +static_library("copresence") { + sources = [ + "copresence_client.cc", + "public/copresence_client_delegate.h", + "public/copresence_client.h", + "public/whispernet_client.h", + "rpc/rpc_handler.cc", + "rpc/rpc_handler.h", + ] + + deps = [ + "//base", + "//components/copresence/proto", + "//net", + ] +} diff --git a/components/copresence/DEPS b/components/copresence/DEPS new file mode 100644 index 000000000000..5cd0867c848d --- /dev/null +++ b/components/copresence/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+base", +] diff --git a/components/copresence/OWNERS b/components/copresence/OWNERS new file mode 100644 index 000000000000..38d2b19b7c74 --- /dev/null +++ b/components/copresence/OWNERS @@ -0,0 +1,4 @@ +rkc@chromium.org +ckehoe@chromium.org +xiyuan@chromium.org +derat@chromium.org diff --git a/components/copresence/copresence_client.cc b/components/copresence/copresence_client.cc new file mode 100644 index 000000000000..60e45e15d215 --- /dev/null +++ b/components/copresence/copresence_client.cc @@ -0,0 +1,108 @@ +// 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/public/copresence_client.h" + +#include "base/bind.h" +#include "components/copresence/public/copresence_client_delegate.h" +#include "components/copresence/public/whispernet_client.h" +#include "components/copresence/rpc/rpc_handler.h" + +namespace copresence { + +PendingRequest::PendingRequest(const copresence::ReportRequest& report, + const std::string app_id, + const StatusCallback& callback) + : report(report), app_id(app_id), callback(callback) { +} + +PendingRequest::~PendingRequest() { +} + +// Public methods + +CopresenceClient::CopresenceClient(CopresenceClientDelegate* delegate) + : delegate_(delegate), init_failed_(false), pending_init_operations_(0) { + DVLOG(3) << "Initializing client."; + pending_init_operations_++; + rpc_handler_.reset( + new RpcHandler(delegate, + base::Bind(&CopresenceClient::InitStepComplete, + AsWeakPtr(), + "Copresence device registration"))); + + pending_init_operations_++; + delegate_->GetWhispernetClient()->Initialize( + base::Bind(&CopresenceClient::InitStepComplete, + AsWeakPtr(), + "Whispernet proxy initialization")); +} + +CopresenceClient::~CopresenceClient() { +} + +void CopresenceClient::Shutdown() { + DVLOG(3) << "Shutting down client."; + delegate_->GetWhispernetClient()->Shutdown(); + rpc_handler_->DisconnectFromWhispernet(); +} + +// Returns false if any operations were malformed. +void CopresenceClient::ExecuteReportRequest(copresence::ReportRequest request, + const std::string& app_id, + const StatusCallback& callback) { + // Don't take on any more requests, we can't execute any, init failed. + if (init_failed_) { + callback.Run(FAIL); + return; + } + + if (pending_init_operations_) { + pending_requests_queue_.push_back( + PendingRequest(request, app_id, callback)); + } else { + rpc_handler_->SendReportRequest( + make_scoped_ptr(new copresence::ReportRequest(request)), + app_id, + callback); + } +} + +// Private methods + +void CopresenceClient::CompleteInitialization() { + if (pending_init_operations_) + return; + + if (!init_failed_) + rpc_handler_->ConnectToWhispernet(delegate_->GetWhispernetClient()); + + for (std::vector::iterator request = + pending_requests_queue_.begin(); + request != pending_requests_queue_.end(); + ++request) { + if (init_failed_) { + request->callback.Run(FAIL); + } else { + rpc_handler_->SendReportRequest( + make_scoped_ptr(new copresence::ReportRequest(request->report)), + request->app_id, + request->callback); + } + } + pending_requests_queue_.clear(); +} + +void CopresenceClient::InitStepComplete(const std::string& step, bool success) { + if (!success) { + LOG(ERROR) << step << " failed!"; + init_failed_ = true; + } + + DVLOG(3) << "Init step: " << step << " complete."; + pending_init_operations_--; + CompleteInitialization(); +} + +} // namespace copresence diff --git a/components/copresence/proto/BUILD.gn b/components/copresence/proto/BUILD.gn new file mode 100644 index 000000000000..87812ddeeedd --- /dev/null +++ b/components/copresence/proto/BUILD.gn @@ -0,0 +1,16 @@ +# 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. + +import("//third_party/protobuf/proto_library.gni") + +# GYP version: components/copresence.gypi:copresence_proto +proto_library("proto") { + sources = [ + "codes.proto", + "data.proto", + "enums.proto", + "identity.proto", + "rpcs.proto", + ] +} diff --git a/components/copresence/proto/codes.proto b/components/copresence/proto/codes.proto new file mode 100644 index 000000000000..3459f2693955 --- /dev/null +++ b/components/copresence/proto/codes.proto @@ -0,0 +1,23 @@ +syntax = "proto2"; +package util.error; +option optimize_for = LITE_RUNTIME; +enum Code { + OK = 0; + CANCELLED = 1; + UNKNOWN = 2; + INVALID_ARGUMENT = 3; + DEADLINE_EXCEEDED = 4; + NOT_FOUND = 5; + ALREADY_EXISTS = 6; + PERMISSION_DENIED = 7; + UNAUTHENTICATED = 16; + RESOURCE_EXHAUSTED = 8; + FAILED_PRECONDITION = 9; + ABORTED = 10; + OUT_OF_RANGE = 11; + UNIMPLEMENTED = 12; + INTERNAL = 13; + UNAVAILABLE = 14; + DATA_LOSS = 15; + DO_NOT_USE_RESERVED_FOR_FUTURE_EXPANSION_USE_DEFAULT_IN_SWITCH_INSTEAD_ = 20; +} diff --git a/components/copresence/proto/data.proto b/components/copresence/proto/data.proto new file mode 100644 index 000000000000..a03df3c7d910 --- /dev/null +++ b/components/copresence/proto/data.proto @@ -0,0 +1,147 @@ +syntax = "proto2"; +package copresence; +option optimize_for = LITE_RUNTIME; +import "enums.proto"; +import "identity.proto"; +message ClientVersion { + optional string client = 1; + optional string version_name = 2; + optional int64 version_code = 3; + optional string certificate_fingerprint = 4; +} +message Status { + optional StatusCode code = 1; + optional string message = 2; +} +message DeviceRegistration { + optional PushService service = 1 [deprecated = true]; + optional string device_token = 2 [deprecated = true]; + optional DeviceIdentity device_identity = 3 [deprecated = true]; + optional string app_name = 4 [deprecated = true]; + optional bytes device_token_binary = 5 [deprecated = true]; + optional string registered_device_id = 6 [deprecated = true]; + optional int32 ulr_device_id = 7 [deprecated = true]; + optional Identity registrant = 8 [deprecated = true]; +} +message PushServiceRegistration { + optional PushService service = 1; +} +message DeviceIdentifiers { + optional int32 ulr_device_id = 1; + optional DeviceIdentity device_identity = 2; + optional Identity registrant = 3; +} +message Token { + message Debug { + repeated string email = 2; + extensions 1 to 1; + } + optional string id = 1; + optional uint32 ttl_millis_deprecated = 2 [deprecated = true]; + optional TokenStatus status = 3; + optional Debug debug = 4; +} +message TokenTechnology { + optional TokenMedium medium = 1; + repeated TokenInstructionType instruction_type = 2; +} +message DeviceCapabilities { + repeated TokenTechnology token_technology = 2; +} +message TokenInstruction { + optional TokenInstructionType token_instruction_type = 1; + optional TokenMedium medium = 2; + optional string token_id = 4; +} +message Directive { + optional InstructionType instruction_type = 1; + optional TokenInstruction token_instruction = 2; + optional int64 delay_millis = 3; + optional int64 ttl_millis = 4; + optional string published_message_id = 5; + optional string subscription_id = 6; +} +message DeviceState { + optional DeviceCapabilities capabilities = 1; + repeated Directive active_directive = 2; +} +message DebugInfo { + optional string served_by_task = 1; + optional bool listen_initiated_by_location_deprecated = 2 [deprecated = true]; + repeated string token_id = 3; + optional int64 request_time_millis = 4; +} +message TokenObservation { + optional string token_id = 1; + repeated TokenSignals signals = 2; +} +message TokenSignals { + optional TokenMedium medium = 1; + optional int32 rssi = 2; + optional int64 observed_time_millis = 3; +} +message AccessPolicy { + optional int64 ttl_millis = 1; + optional Acl acl = 2; + extensions 4 to 4; +} +message Acl { + optional AclType acl_type = 1; + optional string named_acl_name = 2; + optional bytes referenced_acl_consistency_token = 5; +} +message PublishedMessage { + optional string id = 1; + optional AccessPolicy access_policy = 2; + optional Message message = 3; + optional TransmissionStrategy strategy = 4; + optional TokenExchangeStrategy token_exchange_strategy = 5; + optional OptInStateFilter opt_in_state_filter = 6; +} +message TokenExchangeStrategy { + optional AudioConfiguration audio_configuration = 1; + optional BroadcastScanConfiguration broadcast_scan_configuration = 2; +} +message SubscribedMessage { + message Debug { + optional string published_message_id = 1; + optional string publisher_identity_id = 2; + optional string publisher_device_id = 3; + optional int64 creation_timestamp_millis = 4; + optional int64 ttl_millis = 5; + optional TransmissionStrategy strategy = 6; + optional TokenExchangeStrategy token_exchange_strategy = 7; + } + repeated string subscription_id = 1; + optional Message published_message = 2; + optional Debug debug = 3; +} +message Message { + optional MessageType type = 2; + optional bytes payload = 3; +} +message MessageType { + optional string namespace_deprecated = 1 [deprecated = true]; + optional string type = 2; +} +message Subscription { + optional string id = 1; + optional TransmissionStrategy strategy = 2; + optional int64 ttl_millis = 3; + optional MessageType message_type = 4; + optional TokenExchangeStrategy token_exchange_strategy = 7; + optional OptInStateFilter opt_in_state_filter = 8; +} +message DeleteAll { + optional DeleteAllType type = 1; + repeated string namespace = 2; +} +message MessageResult { + optional string published_message_id = 1; +} +message SubscriptionResult { + optional string subscription_id = 1; +} +message OptInStateFilter { + repeated OptInState allowed_opt_in_state = 1; +} diff --git a/components/copresence/proto/enums.proto b/components/copresence/proto/enums.proto new file mode 100644 index 000000000000..9356cab0439d --- /dev/null +++ b/components/copresence/proto/enums.proto @@ -0,0 +1,97 @@ +syntax = "proto2"; +package copresence; +option optimize_for = LITE_RUNTIME; +enum IdentityType { + IDENTITY_TYPE_UNKNOWN = 0; + GAIA_USER = 1; + CHROMECAST = 2; + ANDROID = 3; + CHROME = 4; + UNREGISTERED = 5; +} +enum PushService { + PUSH_SERVICE_UNKNOWN = 0; + GCM = 1; + APNS = 2; + PUSH_SERVICE_NONE = 3; +} +enum ErrorType { + ERROR_TYPE_UNKNOWN = 0; + TOKEN_EXPIRED = 1; + MAC_ADDRESS_UNAVAILABLE = 2; + MAC_ADDRESS_NEEDS_PERMISSION = 3; +} +enum TokenStatus { + TOKEN_STATUS_UNKNOWN = 0; + VALID = 1; + INVALID = 2; + TRANSITIVE = 3; +} +enum TokenMedium { + TOKEN_MEDIUM_UNKNOWN = 0; + AUDIO_ULTRASOUND_PASSBAND = 1; + BLUETOOTH_CLASSIC_NAME = 2; + BLE_ADVERTISING_PACKET = 3; + WIFI_DIRECT_SSID = 4; + LOCAL_DEVICE = 5; + BLE_GATT_SERVICE = 6; + WIFI_AP_SSID = 7; + AUDIO_AUDIBLE_DTMF = 8; +} +enum AclType { + UNKNOWN_ACL_TYPE = 0; + NO_ACL_CHECK = 1; + OWNER_ONLY = 2; + NAMED_ACL = 4; + MESSAGE_ACL = 5; + REFERENCED_ACL = 6; + OPTED_OUT_MESSAGE_ACL = 7; +} +enum TokenInstructionType { + UNKNOWN_TOKEN_INSTRUCTION_TYPE = 0; + TRANSMIT = 1; + RECEIVE = 2; +} +enum InstructionType { + UNKNOWN_INSTRUCTION_TYPE = 0; + TOKEN = 1; + SCAN_WIFI = 2; + SCAN_BLE = 3; +} +enum TransmissionStrategy { + UNKNOWN_STRATEGY = 0; + AGGRESSIVE = 1; + OPPORTUNISTIC = 2; + PASSIVE = 3; +} +enum DeleteAllType { + UNKNOWN_DELETE_ALL_TYPE = 0; + DELETE_NONE = 1; + DELETE_ALL_FOR_IDENTITY_DEVICE = 2; + DELETE_ALL_FOR_IDENTITY = 3; + DELETE_ALL_FOR_DEVICE_APP = 4; +} +enum StatusCode { + STATUS_CODE_UNKNOWN = -1; + OK = 0; + COPRESENCE_DISABLED = 201; + LOCATION_HISTORY_DISABLED = 202; + UNDERAGED = 203; + DEVICE_RE_REGISTRATION_REQUIRED = 204; + RATE_LIMITED = 301; +} +enum OptInState { + UNKNOWN_OPT_IN_STATE = 0; + OPTED_IN = 1; + OPTED_OUT = 2; +} +enum AudioConfiguration { + AUDIO_CONFIGURATION_UNKNOWN = 0; + AUDIBLE = 1; +} +enum BroadcastScanConfiguration { + BROADCAST_SCAN_CONFIGURATION_UNKNOWN = 0; + BROADCAST_AND_SCAN = 1; + BROADCAST_ONLY = 2; + SCAN_ONLY = 3; +} diff --git a/components/copresence/proto/identity.proto b/components/copresence/proto/identity.proto new file mode 100644 index 000000000000..c89f6619f830 --- /dev/null +++ b/components/copresence/proto/identity.proto @@ -0,0 +1,21 @@ +syntax = "proto2"; +package copresence; +option optimize_for = LITE_RUNTIME; +import "enums.proto"; +message Identity { + optional IdentityType type = 1; + optional string obfuscated_gaia_id = 2 [deprecated = true]; + optional string chromecast_id = 3; + optional string android_id = 4; + optional string chrome_id = 5; + optional int64 gaia_id = 6; +} +message DeviceIdentity { + optional Identity identity = 1; + optional DeviceVersion version = 2; +} +message DeviceVersion { + optional string brand = 1; + optional string product = 2; + optional string version = 3; +} diff --git a/components/copresence/proto/rpcs.proto b/components/copresence/proto/rpcs.proto new file mode 100644 index 000000000000..bdbed2ec9cb2 --- /dev/null +++ b/components/copresence/proto/rpcs.proto @@ -0,0 +1,74 @@ +syntax = "proto2"; +package copresence; +option optimize_for = LITE_RUNTIME; +import "codes.proto"; +import "enums.proto"; +import "data.proto"; +message RequestHeader { + optional DeviceRegistration device_id = 3 [deprecated = true]; + optional ClientVersion client_version = 4; + optional ClientVersion framework_version = 5; + optional int64 current_time_millis = 6; + optional string registered_device_id = 7; + repeated string experiment_override = 8; + optional string configuration_etag = 11; + extensions 9 to 9; +} +message ResponseHeader { + optional ErrorType error_type = 1 [deprecated = true]; + optional DebugInfo debug_info = 2; + optional Status status = 3; +} +message RegisterDeviceRequest { + optional RequestHeader header = 1; + optional DeviceRegistration old_registration = 2 [deprecated = true]; + optional DeviceRegistration new_registration = 3 [deprecated = true]; + optional PushServiceRegistration push_service = 5; + optional DeviceIdentifiers device_identifiers = 6; +} +message RegisterDeviceResponse { + optional ResponseHeader header = 1; + optional string registered_device_id = 2; +} +message ReportRequest { + optional RequestHeader header = 1; + optional ManageMessagesRequest manage_messages_request = 2; + optional ManageSubscriptionsRequest manage_subscriptions_request = 3; + optional UpdateSignalsRequest update_signals_request = 4; +} +message UpdateSignalsRequest { + repeated TokenObservation token_observation = 1; + optional DeviceState state = 3; +} +message ManageMessagesRequest { + repeated PublishedMessage message_to_publish = 1; + repeated string id_to_unpublish = 2; + optional DeleteAll delete_all = 3; +} +message ManageSubscriptionsRequest { + repeated Subscription subscription = 1; + repeated string id_to_unsubscribe = 2; + optional DeleteAll delete_all = 3; +} +message ReportResponse { + optional ResponseHeader header = 1; + optional ManageMessagesResponse manage_messages_response = 2; + optional ManageSubscriptionsResponse manage_subscriptions_response = 3; + optional UpdateSignalsResponse update_signals_response = 4; +} +message UpdateSignalsResponse { + optional util.error.Code status = 1; + repeated Token token = 2; + repeated SubscribedMessage message = 3; + repeated Directive directive = 4; +} +message ManageMessagesResponse { + optional util.error.Code status = 1; + repeated MessageResult published_message_result = 3; + extensions 2 to 2; +} +message ManageSubscriptionsResponse { + optional util.error.Code status = 1; + repeated SubscriptionResult subscription_result = 3; + extensions 2 to 2; +} diff --git a/components/copresence/public/copresence_client.h b/components/copresence/public/copresence_client.h new file mode 100644 index 000000000000..40b8bf97bfe4 --- /dev/null +++ b/components/copresence/public/copresence_client.h @@ -0,0 +1,81 @@ +// 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_PUBLIC_COPRESENCE_CLIENT_H_ +#define COMPONENTS_COPRESENCE_PUBLIC_COPRESENCE_CLIENT_H_ + +#include +#include + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "components/copresence/proto/rpcs.pb.h" +#include "components/copresence/public/copresence_client_delegate.h" + +namespace net { +class URLContextGetter; +} + +namespace copresence { + +class CopresenceClientDelegate; +class RpcHandler; + +struct PendingRequest { + PendingRequest(const copresence::ReportRequest& report, + const std::string app_id, + const StatusCallback& callback); + ~PendingRequest(); + + copresence::ReportRequest report; + std::string app_id; + StatusCallback callback; +}; + +// The CopresenceClient class is the central interface for Copresence +// functionality. This class handles all the initialization and delegation of +// copresence tasks. Any user of copresence only needs to interact with this +// client. +class CopresenceClient : public base::SupportsWeakPtr { + public: + // The delegate must outlive us. + explicit CopresenceClient(CopresenceClientDelegate* delegate); + virtual ~CopresenceClient(); + + // This method will execute a report request. Each report request can have + // multiple (un)publishes, (un)subscribes. This will ensure that once the + // client is initialized, it sends all request to the server and handles + // the response. If an error is encountered, the status callback is used + // to relay it to the requester. + void ExecuteReportRequest(copresence::ReportRequest request, + const std::string& app_id, + const StatusCallback& callback); + + // Called before the API (and thus the Client) is destructed. + void Shutdown(); + + private: + void CompleteInitialization(); + void InitStepComplete(const std::string& step, bool success); + + CopresenceClientDelegate* delegate_; + bool init_failed_; + std::vector pending_requests_queue_; + + // TODO(rkc): This code is almost identical to what we use in feedback to + // perform multiple blocking tasks and then run a post process method. Look + // into refactoring it all out to a common construct, like maybe a + // PostMultipleTasksAndReply? + size_t pending_init_operations_; + + scoped_ptr rpc_handler_; + + DISALLOW_COPY_AND_ASSIGN(CopresenceClient); +}; + +} // namespace copresence + +#endif // COMPONENTS_COPRESENCE_PUBLIC_COPRESENCE_CLIENT_H_ diff --git a/components/copresence/public/copresence_client_delegate.h b/components/copresence/public/copresence_client_delegate.h new file mode 100644 index 000000000000..374eb96561a7 --- /dev/null +++ b/components/copresence/public/copresence_client_delegate.h @@ -0,0 +1,51 @@ +// 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_PUBLIC_COPRESENCE_DELEGATE_H_ +#define COMPONENTS_COPRESENCE_PUBLIC_COPRESENCE_DELEGATE_H_ + +#include + +#include "base/callback_forward.h" +#include "components/copresence/proto/rpcs.pb.h" + +namespace net { +class URLRequestContextGetter; +} + +namespace copresence { + +class WhispernetClient; + +enum CopresenceStatus { SUCCESS, FAIL }; + +// Callback type to send a status. +typedef base::Callback StatusCallback; + +// A delegate interface for users of Copresence. +class CopresenceClientDelegate { + public: + // This method will be called when we have subscribed messages that need to + // be sent to their respective apps. + virtual void HandleMessages( + const std::string& app_id, + const std::string& subscription_id, + const std::vector& message) = 0; + + virtual net::URLRequestContextGetter* GetRequestContext() const = 0; + + virtual const std::string GetPlatformVersionString() const = 0; + + // Methods to set and and get our device ID. This needs to be saved to + // persistent storage to avoid flooding the Copresence server with generate + // id requests. + virtual const std::string GetDeviceId() const = 0; + virtual void SaveDeviceId(const std::string& device_id) = 0; + + virtual WhispernetClient* GetWhispernetClient() = 0; +}; + +} // namespace copresence + +#endif // COMPONENTS_COPRESENCE_PUBLIC_COPRESENCE_DELEGATE_H_ diff --git a/components/copresence/public/whispernet_client.h b/components/copresence/public/whispernet_client.h new file mode 100644 index 000000000000..afec22b2f468 --- /dev/null +++ b/components/copresence/public/whispernet_client.h @@ -0,0 +1,70 @@ +// 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_INTERFACE_WHISPERNET_CLIENT_H_ +#define COMPONENTS_COPRESENCE_INTERFACE_WHISPERNET_CLIENT_H_ + +#include +#include + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" + +namespace media { +class AudioBusRefCounted; +} + +namespace copresence { + +// The interface that the whispernet client needs to implement. These methods +// provide us the ability to use the audio medium in copresence. Currently since +// the only medium that copresence uses is audio, the implementation of this +// interface is required. +class WhispernetClient { + public: + // Generic callback to indicate a boolean success or failure. + typedef base::Callback SuccessCallback; + // Callback that returns detected tokens. + typedef base::Callback&)> TokensCallback; + // Callback that returns encoded samples for a given token. + typedef base::Callback< + void(const std::string&, const scoped_refptr&)> + SamplesCallback; + + // Initialize the whispernet client and call the callback when done. The + // parameter indicates whether we succeeded or failed. + virtual void Initialize(const SuccessCallback& init_callback) = 0; + // Copresence will call this before making any calls to its destructors. + virtual void Shutdown() = 0; + + // Fires an event to request a token encode. + virtual void EncodeToken(const std::string& token) = 0; + // Fires an event to request a decode for the given samples. + virtual void DecodeSamples(const std::string& samples) = 0; + // Fires an event to request detection of a whispernet broadcast. + virtual void DetectBroadcast() = 0; + + // Callback registreation methods. These are the callbacks that will be + // registered by Copresence to receive data. + virtual void RegisterTokensCallback( + const TokensCallback& tokens_callback) = 0; + virtual void RegisterSamplesCallback( + const SamplesCallback& samples_callback) = 0; + virtual void RegisterDetectBroadcastCallback( + const SuccessCallback& db_callback) = 0; + + // Don't cache these callbacks, as they may become invalid at any time. + // Always invoke callbacks directly through these accessors. + virtual TokensCallback GetTokensCallback() = 0; + virtual SamplesCallback GetSamplesCallback() = 0; + virtual SuccessCallback GetDetectBroadcastCallback() = 0; + virtual SuccessCallback GetInitializedCallback() = 0; + + virtual ~WhispernetClient() {}; +}; + +} // namespace copresence + +#endif // COMPONENTS_COPRESENCE_INTERFACE_WHISPERNET_CLIENT_H_ diff --git a/components/copresence/rpc/rpc_handler.cc b/components/copresence/rpc/rpc_handler.cc new file mode 100644 index 000000000000..e5f12d0c4d96 --- /dev/null +++ b/components/copresence/rpc/rpc_handler.cc @@ -0,0 +1,42 @@ +// 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/rpc_handler.h" + +#include "base/bind.h" +#include "components/copresence/proto/data.pb.h" +#include "components/copresence/proto/rpcs.pb.h" +#include "components/copresence/public/copresence_client_delegate.h" +#include "components/copresence/public/whispernet_client.h" + +namespace copresence { + +RpcHandler::RpcHandler(CopresenceClientDelegate* delegate, + SuccessCallback init_done_callback) { +} + +RpcHandler::~RpcHandler() { +} + +void RpcHandler::SendReportRequest( + scoped_ptr request) { +} + +void RpcHandler::SendReportRequest( + scoped_ptr request, + const std::string& app_id, + const StatusCallback& status_callback) { +} + +void RpcHandler::ReportTokens(copresence::TokenMedium medium, + const std::vector& tokens) { +} + +void RpcHandler::ConnectToWhispernet(WhispernetClient* whispernet_client) { +} + +void RpcHandler::DisconnectFromWhispernet() { +} + +} // namespace copresence diff --git a/components/copresence/rpc/rpc_handler.h b/components/copresence/rpc/rpc_handler.h new file mode 100644 index 000000000000..dee7220ac780 --- /dev/null +++ b/components/copresence/rpc/rpc_handler.h @@ -0,0 +1,57 @@ +// 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_RPC_HANDLER_H_ +#define COMPONENTS_COPRESENCE_RPC_RPC_HANDLER_H_ + +#include +#include + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "components/copresence/public/copresence_client_delegate.h" + +namespace copresence { + +class ReportRequest; +class WhispernetClient; + +// This class currently handles all communication with the copresence server. +// NOTE: This class is a stub. +class RpcHandler { + public: + // A callback to indicate whether handler initialization succeeded. + typedef base::Callback SuccessCallback; + + // Constructor. May call the server to register a device, + // so completion status is indicated by the SuccessCallback. + RpcHandler(CopresenceClientDelegate* delegate, + SuccessCallback init_done_callback); + + virtual ~RpcHandler(); + + // Send a report request + void SendReportRequest(scoped_ptr request); + void SendReportRequest(scoped_ptr request, + const std::string& app_id, + const StatusCallback& callback); + + // Report a set of tokens to the server for a given medium. + void ReportTokens(copresence::TokenMedium medium, + const std::vector& tokens); + + // Create the directive handler and connect it to the whispernet client. + void ConnectToWhispernet(WhispernetClient* whispernet_client); + + // Disconnect the directive handler from the whispernet client. + void DisconnectFromWhispernet(); + + private: + DISALLOW_COPY_AND_ASSIGN(RpcHandler); +}; + +} // namespace copresence + +#endif // COMPONENTS_COPRESENCE_RPC_RPC_HANDLER_H_