Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / extensions / api / copresence / copresence_translations.cc
blob492e6c2b5b32d9f9540346556cd0561062fb2929
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/copresence/copresence_translations.h"
7 #include "base/stl_util.h"
8 #include "chrome/common/extensions/api/copresence.h"
9 #include "components/copresence/proto/data.pb.h"
10 #include "components/copresence/proto/enums.pb.h"
11 #include "components/copresence/proto/rpcs.pb.h"
13 using copresence::AUDIO_CONFIGURATION_AUDIBLE;
14 using copresence::AUDIO_CONFIGURATION_UNKNOWN;
15 using copresence::BROADCAST_AND_SCAN;
16 using copresence::BROADCAST_ONLY;
17 using copresence::BROADCAST_SCAN_CONFIGURATION_UNKNOWN;
18 using copresence::BroadcastScanConfiguration;
19 using copresence::ReportRequest;
20 using copresence::SCAN_ONLY;
21 using copresence::TokenExchangeStrategy;
23 using extensions::api::copresence::Strategy;
25 namespace {
27 const int kDefaultTimeToLiveMs = 5 * 60 * 1000; // 5 minutes.
28 const int kMaxTimeToLiveMs = 24 * 60 * 60 * 1000; // 24 hours.
30 // Checks and returns the ttl provided by the user. If invalid, returns -1.
31 int SanitizeTtl(int* user_ttl) {
32 return !user_ttl
33 ? kDefaultTimeToLiveMs
34 : (*user_ttl <= 0 || *user_ttl > kMaxTimeToLiveMs ? -1 : *user_ttl);
37 BroadcastScanConfiguration TranslateStrategy(const Strategy& strategy) {
38 bool only_broadcast = strategy.only_broadcast && *strategy.only_broadcast;
39 bool only_scan = strategy.only_scan && *strategy.only_scan;
41 if (only_broadcast && only_scan)
42 return BROADCAST_AND_SCAN;
43 if (only_broadcast)
44 return BROADCAST_ONLY;
45 if (only_scan)
46 return SCAN_ONLY;
48 return BROADCAST_SCAN_CONFIGURATION_UNKNOWN;
51 // The strategy may be null (unspecified), so we pass it as a pointer.
52 void SetTokenExchangeStrategy(const Strategy* strategy,
53 BroadcastScanConfiguration default_config,
54 TokenExchangeStrategy* strategy_proto) {
55 if (strategy) {
56 BroadcastScanConfiguration config;
57 if (strategy->low_power && *(strategy->low_power)) {
58 config = BROADCAST_SCAN_CONFIGURATION_UNKNOWN;
59 } else {
60 config = TranslateStrategy(*strategy);
61 if (config == BROADCAST_SCAN_CONFIGURATION_UNKNOWN)
62 config = default_config;
65 strategy_proto->set_broadcast_scan_configuration(config);
66 strategy_proto->set_audio_configuration(
67 strategy->audible && *strategy->audible ? AUDIO_CONFIGURATION_AUDIBLE
68 : AUDIO_CONFIGURATION_UNKNOWN);
69 } else {
70 strategy_proto->set_broadcast_scan_configuration(default_config);
71 strategy_proto->set_audio_configuration(AUDIO_CONFIGURATION_UNKNOWN);
75 } // namespace
77 namespace extensions {
79 using api::copresence::Operation;
81 // Adds a publish operation to the report request. Returns false if the
82 // publish operation was invalid.
83 bool AddPublishToRequest(const std::string& app_id,
84 const api::copresence::PublishOperation& publish,
85 ReportRequest* request) {
86 copresence::PublishedMessage* publish_proto =
87 request->mutable_manage_messages_request()->add_message_to_publish();
88 publish_proto->mutable_access_policy()->mutable_acl()->set_acl_type(
89 copresence::NO_ACL_CHECK);
90 publish_proto->set_id(publish.id);
91 publish_proto->mutable_message()->mutable_type()->set_type(
92 publish.message.type);
93 publish_proto->mutable_message()->set_payload(
94 vector_as_array(&publish.message.payload),
95 publish.message.payload.size());
97 int ttl = SanitizeTtl(publish.time_to_live_millis.get());
98 if (ttl < 0)
99 return false;
100 publish_proto->mutable_access_policy()->set_ttl_millis(ttl);
102 SetTokenExchangeStrategy(publish.strategies.get(),
103 BROADCAST_ONLY,
104 publish_proto->mutable_token_exchange_strategy());
106 DVLOG(2) << "Publishing message of type " << publish.message.type << ":\n"
107 << std::string(publish.message.payload.begin(),
108 publish.message.payload.end());
109 // TODO(ckehoe): Validate that required fields are non-empty, etc.
110 return true;
113 // Adds an unpublish operation to the report request. Returns false if the
114 // publish id was invalid.
115 bool AddUnpublishToRequest(const std::string& publish_id,
116 ReportRequest* request) {
117 if (publish_id.empty())
118 return false;
120 request->mutable_manage_messages_request()->add_id_to_unpublish(publish_id);
121 DVLOG(2) << "Unpublishing message \"" << publish_id << "\"";
122 return true;
125 // Adds a subscribe operation to the report request. Returns false if the
126 // subscription operation was invalid.
127 bool AddSubscribeToRequest(
128 const std::string& app_id,
129 const api::copresence::SubscribeOperation& subscription,
130 SubscriptionToAppMap* apps_by_subscription_id,
131 ReportRequest* request) {
132 // Associate the subscription id with the app id.
133 SubscriptionToAppMap::iterator previous_subscription =
134 apps_by_subscription_id->find(subscription.id);
135 if (previous_subscription == apps_by_subscription_id->end()) {
136 (*apps_by_subscription_id)[subscription.id] = app_id;
137 } else if (previous_subscription->second == app_id) {
138 VLOG(2) << "Overwriting subscription id \"" << subscription.id
139 << "\" for app \"" << app_id << "\"";
140 } else {
141 // A conflicting association exists already.
142 VLOG(1) << "Subscription id \"" << subscription.id
143 << "\" used by two apps: \"" << previous_subscription->second
144 << "\" and \"" << app_id << "\"";
145 return false;
148 // Convert from IDL to server subscription format.
149 copresence::Subscription* subscription_proto =
150 request->mutable_manage_subscriptions_request()->add_subscription();
151 subscription_proto->set_id(subscription.id);
152 int ttl = SanitizeTtl(subscription.time_to_live_millis.get());
153 if (ttl < 0)
154 return false;
155 subscription_proto->set_ttl_millis(ttl);
157 subscription_proto->mutable_message_type()->set_type(
158 subscription.filter.type);
160 SetTokenExchangeStrategy(
161 subscription.strategies.get(),
162 SCAN_ONLY,
163 subscription_proto->mutable_token_exchange_strategy());
165 DVLOG(2) << "Subscribing for messages of type " << subscription.filter.type;
166 // TODO(ckehoe): Validate that required fields are non-empty, etc.
167 return true;
170 // Adds an unpublish operation to the report request. Returns false if the
171 // subscription id was invalid.
172 bool AddUnsubscribeToRequest(const std::string& app_id,
173 const std::string& subscription_id,
174 SubscriptionToAppMap* apps_by_subscription_id,
175 ReportRequest* request) {
176 if (subscription_id.empty())
177 return false;
179 // Check that this subscription id belongs to this app.
180 SubscriptionToAppMap::iterator subscription =
181 apps_by_subscription_id->find(subscription_id);
182 if (subscription == apps_by_subscription_id->end()) {
183 LOG(ERROR) << "No such subscription \"" << subscription_id
184 << "\". Cannot unsubscribe.";
185 return false;
186 } else if (subscription->second != app_id) {
187 LOG(ERROR) << "Subscription \"" << subscription_id
188 << "\" does not belong to app \"" << app_id
189 << "\". Cannot unsubscribe.";
190 return false;
191 } else {
192 apps_by_subscription_id->erase(subscription);
195 request->mutable_manage_subscriptions_request()->add_id_to_unsubscribe(
196 subscription_id);
197 DVLOG(2) << "Cancelling subscription \"" << subscription_id << "\" for app \""
198 << app_id << "\"";
199 return true;
202 bool PrepareReportRequestProto(
203 const std::vector<linked_ptr<Operation>>& operations,
204 const std::string& app_id,
205 SubscriptionToAppMap* apps_by_subscription_id,
206 ReportRequest* request) {
207 for (const linked_ptr<Operation>& op : operations) {
208 DCHECK(op.get());
210 // Verify our object has exactly one operation.
211 if (static_cast<int>(op->publish != nullptr) +
212 static_cast<int>(op->subscribe != nullptr) +
213 static_cast<int>(op->unpublish != nullptr) +
214 static_cast<int>(op->unsubscribe != nullptr) != 1) {
215 return false;
218 if (op->publish) {
219 if (!AddPublishToRequest(app_id, *(op->publish), request))
220 return false;
221 } else if (op->subscribe) {
222 if (!AddSubscribeToRequest(
223 app_id, *(op->subscribe), apps_by_subscription_id, request))
224 return false;
225 } else if (op->unpublish) {
226 if (!AddUnpublishToRequest(op->unpublish->unpublish_id, request))
227 return false;
228 } else { // if (op->unsubscribe)
229 if (!AddUnsubscribeToRequest(app_id,
230 op->unsubscribe->unsubscribe_id,
231 apps_by_subscription_id,
232 request))
233 return false;
237 return true;
240 } // namespace extensions