Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(548)

Side by Side Diff: chrome/browser/chrome_to_mobile_service.cc

Issue 10861038: Revert 152609 - Integrate invalidation API into ChromeToMobileService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chrome_to_mobile_service.h" 5 #include "chrome/browser/chrome_to_mobile_service.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/guid.h" 10 #include "base/guid.h"
11 #include "base/json/json_reader.h" 11 #include "base/json/json_reader.h"
12 #include "base/json/json_writer.h" 12 #include "base/json/json_writer.h"
13 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
14 #include "base/stringprintf.h"
14 #include "base/utf_string_conversions.h" 15 #include "base/utf_string_conversions.h"
15 #include "chrome/app/chrome_command_ids.h" 16 #include "chrome/app/chrome_command_ids.h"
17 #include "chrome/browser/content_settings/cookie_settings.h"
16 #include "chrome/browser/prefs/pref_service.h" 18 #include "chrome/browser/prefs/pref_service.h"
17 #include "chrome/browser/printing/cloud_print/cloud_print_url.h" 19 #include "chrome/browser/printing/cloud_print/cloud_print_url.h"
18 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/signin/token_service.h" 21 #include "chrome/browser/signin/token_service.h"
20 #include "chrome/browser/signin/token_service_factory.h" 22 #include "chrome/browser/signin/token_service_factory.h"
21 #include "chrome/browser/sync/profile_sync_service.h"
22 #include "chrome/browser/sync/profile_sync_service_factory.h"
23 #include "chrome/browser/ui/browser.h" 23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_command_controller.h" 24 #include "chrome/browser/ui/browser_command_controller.h"
25 #include "chrome/browser/ui/browser_finder.h" 25 #include "chrome/browser/ui/browser_finder.h"
26 #include "chrome/browser/ui/browser_list.h" 26 #include "chrome/browser/ui/browser_list.h"
27 #include "chrome/browser/ui/browser_navigator.h" 27 #include "chrome/browser/ui/browser_navigator.h"
28 #include "chrome/browser/ui/browser_tabstrip.h" 28 #include "chrome/browser/ui/browser_tabstrip.h"
29 #include "chrome/common/chrome_notification_types.h" 29 #include "chrome/common/chrome_notification_types.h"
30 #include "chrome/common/chrome_switches.h" 30 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/cloud_print/cloud_print_helpers.h" 31 #include "chrome/common/cloud_print/cloud_print_helpers.h"
32 #include "chrome/common/net/gaia/gaia_constants.h" 32 #include "chrome/common/net/gaia/gaia_constants.h"
33 #include "chrome/common/net/gaia/gaia_urls.h" 33 #include "chrome/common/net/gaia/gaia_urls.h"
34 #include "chrome/common/net/gaia/oauth2_access_token_fetcher.h" 34 #include "chrome/common/net/gaia/oauth2_access_token_fetcher.h"
35 #include "chrome/common/pref_names.h" 35 #include "chrome/common/pref_names.h"
36 #include "chrome/common/url_constants.h" 36 #include "chrome/common/url_constants.h"
37 #include "content/public/browser/browser_thread.h" 37 #include "content/public/browser/browser_thread.h"
38 #include "content/public/browser/notification_details.h" 38 #include "content/public/browser/notification_details.h"
39 #include "content/public/browser/notification_source.h" 39 #include "content/public/browser/notification_source.h"
40 #include "content/public/browser/web_contents.h" 40 #include "content/public/browser/web_contents.h"
41 #include "google/cacheinvalidation/include/types.h"
42 #include "google/cacheinvalidation/types.pb.h"
43 #include "net/base/escape.h" 41 #include "net/base/escape.h"
44 #include "net/base/load_flags.h" 42 #include "net/base/load_flags.h"
45 #include "net/url_request/url_fetcher.h" 43 #include "net/url_request/url_fetcher.h"
46 #include "net/url_request/url_request_context_getter.h" 44 #include "net/url_request/url_request_context_getter.h"
47 #include "sync/notifier/invalidation_util.h"
48 45
49 namespace { 46 namespace {
50 47
51 // The default enabled/disabled state of the Chrome To Mobile feature. 48 // The default enabled/disabled state of the Chrome To Mobile feature.
52 const bool kChromeToMobileEnabled = true; 49 const bool kChromeToMobileEnabled = true;
53 50
54 // The maximum number of retries for the URLFetcher requests. 51 // The maximum number of retries for the URLFetcher requests.
55 const size_t kMaxRetries = 1; 52 const size_t kMaxRetries = 1;
56 53
57 // The number of hours to delay before retrying authentication on failure. 54 // The number of hours to delay before retrying authentication on failure.
58 const size_t kAuthRetryDelayHours = 6; 55 const size_t kAuthRetryDelayHours = 6;
59 56
60 // The number of hours before subsequent search requests are allowed. 57 // The number of hours before subsequent search requests are allowed.
61 // This value is used to throttle expensive cloud print search requests. 58 // This value is used to throttle expensive cloud print search requests.
62 // Note that this limitation does not hold across application restarts. 59 // Note that this limitation does not hold across application restarts.
63 const int kSearchRequestDelayHours = 24; 60 const int kSearchRequestDelayHours = 24;
64 61
65 // The sync invalidation object ID for Chrome to Mobile's mobile device list.
66 // This corresponds with cloud print's server-side invalidation object ID.
67 // Meaning: "U" == "User", "CM" == "Chrome to Mobile", "MLST" == "Mobile LiST".
68 const char kSyncInvalidationObjectIdChromeToMobileDeviceList[] = "UCMMLST";
69
70 // The cloud print OAuth2 scope and 'printer' type of compatible mobile devices. 62 // The cloud print OAuth2 scope and 'printer' type of compatible mobile devices.
71 const char kCloudPrintAuth[] = "https://www.googleapis.com/auth/cloudprint"; 63 const char kCloudPrintAuth[] = "https://www.googleapis.com/auth/cloudprint";
72 const char kTypeAndroid[] = "ANDROID_CHROME_SNAPSHOT"; 64 const char kTypeAndroid[] = "ANDROID_CHROME_SNAPSHOT";
73 const char kTypeIOS[] = "IOS_CHROME_SNAPSHOT"; 65 const char kTypeIOS[] = "IOS_CHROME_SNAPSHOT";
74 66
67 // The account info URL pattern and strings to check for cloud print access.
68 // The 'key=' query parameter is used for caching; supply a random number.
69 // The 'rv=2' query parameter requests a JSON response; use 'rv=1' for XML.
70 const char kAccountInfoURL[] =
71 "https://clients1.google.com/tbproxy/getaccountinfo?key=%s&rv=2&%s";
72 const char kAccountServicesKey[] = "services";
73 const char kCloudPrintSerivceValue[] = "cprt";
74
75 // The Chrome To Mobile requestor type; used by services for filtering. 75 // The Chrome To Mobile requestor type; used by services for filtering.
76 const char kChromeToMobileRequestor[] = "requestor=chrome-to-mobile"; 76 const char kChromeToMobileRequestor[] = "requestor=chrome-to-mobile";
77 77
78 // Get the job type string for a cloud print job submission. 78 // Get the job type string for a cloud print job submission.
79 std::string GetType(const ChromeToMobileService::JobData& data) { 79 std::string GetType(const ChromeToMobileService::JobData& data) {
80 if (data.type == ChromeToMobileService::URL) 80 if (data.type == ChromeToMobileService::URL)
81 return "url"; 81 return "url";
82 if (data.type == ChromeToMobileService::DELAYED_SNAPSHOT) 82 if (data.type == ChromeToMobileService::DELAYED_SNAPSHOT)
83 return "url_with_delayed_snapshot"; 83 return "url_with_delayed_snapshot";
84 DCHECK_EQ(data.type, ChromeToMobileService::SNAPSHOT); 84 DCHECK_EQ(data.type, ChromeToMobileService::SNAPSHOT);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 // Utility function to call cloud_print::AddMultipartValueForUpload. 118 // Utility function to call cloud_print::AddMultipartValueForUpload.
119 void AddValue(const std::string& value_name, 119 void AddValue(const std::string& value_name,
120 const std::string& value, 120 const std::string& value,
121 const std::string& mime_boundary, 121 const std::string& mime_boundary,
122 std::string* post_data) { 122 std::string* post_data) {
123 cloud_print::AddMultipartValueForUpload(value_name, value, mime_boundary, 123 cloud_print::AddMultipartValueForUpload(value_name, value, mime_boundary,
124 std::string(), post_data); 124 std::string(), post_data);
125 } 125 }
126 126
127 // Get the URL for cloud print device search; appends a requestor query param. 127 // Get the URL for cloud print device search; appends a requestor query param.
128 GURL GetSearchURL(const GURL& cloud_print_url) { 128 GURL GetSearchURL(const GURL& service_url) {
129 GURL search_url = cloud_print::GetUrlForSearch(cloud_print_url); 129 GURL search_url = cloud_print::GetUrlForSearch(service_url);
130 GURL::Replacements replacements; 130 GURL::Replacements replacements;
131 std::string query(kChromeToMobileRequestor); 131 std::string query(kChromeToMobileRequestor);
132 replacements.SetQueryStr(query); 132 replacements.SetQueryStr(query);
133 return search_url.ReplaceComponents(replacements); 133 return search_url.ReplaceComponents(replacements);
134 } 134 }
135 135
136 // A callback to continue snapshot generation after creating the temp file. 136 // A callback to continue snapshot generation after creating the temp file.
137 typedef base::Callback<void(const FilePath& path, bool success)> 137 typedef base::Callback<void(const FilePath& path, bool success)>
138 CreateSnapshotFileCallback; 138 CreateSnapshotFileCallback;
139 139
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 if (command_line->HasSwitch(switches::kEnableChromeToMobile)) 173 if (command_line->HasSwitch(switches::kEnableChromeToMobile))
174 return true; 174 return true;
175 175
176 return kChromeToMobileEnabled; 176 return kChromeToMobileEnabled;
177 } 177 }
178 178
179 // static 179 // static
180 void ChromeToMobileService::RegisterUserPrefs(PrefService* prefs) { 180 void ChromeToMobileService::RegisterUserPrefs(PrefService* prefs) {
181 prefs->RegisterListPref(prefs::kChromeToMobileDeviceList, 181 prefs->RegisterListPref(prefs::kChromeToMobileDeviceList,
182 PrefService::UNSYNCABLE_PREF); 182 PrefService::UNSYNCABLE_PREF);
183 prefs->RegisterInt64Pref(prefs::kChromeToMobileTimestamp, 0,
184 PrefService::UNSYNCABLE_PREF);
183 } 185 }
184 186
185 ChromeToMobileService::ChromeToMobileService(Profile* profile) 187 ChromeToMobileService::ChromeToMobileService(Profile* profile)
186 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), 188 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
187 profile_(profile), 189 profile_(profile),
188 sync_invalidation_enabled_(false) { 190 cloud_print_url_(new CloudPrintURL(profile)),
189 // TODO(msw): Unit tests do not provide profiles; see http://crbug.com/122183 191 cloud_print_accessible_(false) {
190 ProfileSyncService* profile_sync_service = 192 // TODO(msw): Fix GMock tests, which lack profiles (http://crbug.com/122183).
191 profile_ ? ProfileSyncServiceFactory::GetForProfile(profile_) : NULL; 193 if (profile_) {
192 if (profile_sync_service) { 194 // Get an access token as soon as the Gaia login refresh token is available.
193 CloudPrintURL cloud_print_url(profile_); 195 TokenService* service = TokenServiceFactory::GetForProfile(profile_);
194 cloud_print_url_ = cloud_print_url.GetCloudPrintServiceURL(); 196 registrar_.Add(this, chrome::NOTIFICATION_TOKEN_AVAILABLE,
195 // Register for cloud print device list invalidation notifications. 197 content::Source<TokenService>(service));
196 // TODO(msw|akalin): Initialize |sync_invalidation_enabled_| properly. 198 if (service->HasOAuthLoginToken())
197 profile_sync_service->RegisterInvalidationHandler(this); 199 RequestAccessToken();
198 syncer::ObjectIdSet ids;
199 ids.insert(invalidation::ObjectId(
200 ipc::invalidation::ObjectSource::CHROME_COMPONENTS,
201 kSyncInvalidationObjectIdChromeToMobileDeviceList));
202 profile_sync_service->UpdateRegisteredInvalidationIds(this, ids);
203 } 200 }
204 } 201 }
205 202
206 ChromeToMobileService::~ChromeToMobileService() { 203 ChromeToMobileService::~ChromeToMobileService() {
207 while (!snapshots_.empty()) 204 while (!snapshots_.empty())
208 DeleteSnapshot(*snapshots_.begin()); 205 DeleteSnapshot(*snapshots_.begin());
209 // TODO(msw): Unit tests do not provide profiles; see http://crbug.com/122183
210 // Unregister for cloud print device list invalidation notifications.
211 ProfileSyncService* profile_sync_service =
212 profile_ ? ProfileSyncServiceFactory::GetForProfile(profile_) : NULL;
213 if (profile_sync_service)
214 profile_sync_service->UnregisterInvalidationHandler(this);
215 } 206 }
216 207
217 bool ChromeToMobileService::HasMobiles() const { 208 bool ChromeToMobileService::HasMobiles() const {
218 const base::ListValue* mobiles = GetMobiles(); 209 return !GetMobiles()->empty();
219 return mobiles && !mobiles->empty();
220 } 210 }
221 211
222 const base::ListValue* ChromeToMobileService::GetMobiles() const { 212 const base::ListValue* ChromeToMobileService::GetMobiles() const {
223 return sync_invalidation_enabled_ ? 213 return profile_->GetPrefs()->GetList(prefs::kChromeToMobileDeviceList);
224 profile_->GetPrefs()->GetList(prefs::kChromeToMobileDeviceList) : NULL; 214 }
215
216 void ChromeToMobileService::RequestMobileListUpdate() {
217 if (access_token_.empty())
218 RequestAccessToken();
219 else if (cloud_print_accessible_)
220 RequestDeviceSearch();
225 } 221 }
226 222
227 void ChromeToMobileService::GenerateSnapshot(Browser* browser, 223 void ChromeToMobileService::GenerateSnapshot(Browser* browser,
228 base::WeakPtr<Observer> observer) { 224 base::WeakPtr<Observer> observer) {
229 // Callback SnapshotFileCreated from CreateSnapshotFile to continue. 225 // Callback SnapshotFileCreated from CreateSnapshotFile to continue.
230 CreateSnapshotFileCallback callback = 226 CreateSnapshotFileCallback callback =
231 base::Bind(&ChromeToMobileService::SnapshotFileCreated, 227 base::Bind(&ChromeToMobileService::SnapshotFileCreated,
232 weak_ptr_factory_.GetWeakPtr(), observer, 228 weak_ptr_factory_.GetWeakPtr(), observer,
233 browser->session_id().id()); 229 browser->session_id().id());
234 // Create a temporary file via the blocking pool for snapshot storage. 230 // Create a temporary file via the blocking pool for snapshot storage.
235 if (!content::BrowserThread::PostBlockingPoolTask(FROM_HERE, 231 if (!content::BrowserThread::PostBlockingPoolTask(FROM_HERE,
236 base::Bind(&CreateSnapshotFile, callback))) { 232 base::Bind(&CreateSnapshotFile, callback))) {
237 NOTREACHED(); 233 NOTREACHED();
238 } 234 }
239 } 235 }
240 236
241 void ChromeToMobileService::SendToMobile(const base::DictionaryValue* mobile, 237 void ChromeToMobileService::SendToMobile(const base::DictionaryValue& mobile,
242 const FilePath& snapshot, 238 const FilePath& snapshot,
243 Browser* browser, 239 Browser* browser,
244 base::WeakPtr<Observer> observer) { 240 base::WeakPtr<Observer> observer) {
245 if (access_token_.empty()) {
246 // Enqueue this task to perform after obtaining an access token.
247 task_queue_.push(base::Bind(&ChromeToMobileService::SendToMobile,
248 weak_ptr_factory_.GetWeakPtr(), base::Owned(mobile->DeepCopy()),
249 snapshot, browser, observer));
250 RequestAccessToken();
251 return;
252 }
253
254 LogMetric(SENDING_URL); 241 LogMetric(SENDING_URL);
255 242
256 JobData data; 243 JobData data;
257 std::string mobile_os; 244 std::string mobile_os;
258 if (!mobile->GetString("type", &mobile_os)) 245 if (!mobile.GetString("type", &mobile_os))
259 NOTREACHED(); 246 NOTREACHED();
260 data.mobile_os = (mobile_os.compare(kTypeAndroid) == 0) ? 247 data.mobile_os = (mobile_os.compare(kTypeAndroid) == 0) ?
261 ChromeToMobileService::ANDROID : ChromeToMobileService::IOS; 248 ChromeToMobileService::ANDROID : ChromeToMobileService::IOS;
262 if (!mobile->GetString("id", &data.mobile_id)) 249 if (!mobile.GetString("id", &data.mobile_id))
263 NOTREACHED(); 250 NOTREACHED();
264 content::WebContents* web_contents = chrome::GetActiveWebContents(browser); 251 content::WebContents* web_contents = chrome::GetActiveWebContents(browser);
265 data.url = web_contents->GetURL(); 252 data.url = web_contents->GetURL();
266 data.title = web_contents->GetTitle(); 253 data.title = web_contents->GetTitle();
267 data.snapshot = snapshot; 254 data.snapshot = snapshot;
268 data.snapshot_id = base::GenerateGUID(); 255 data.snapshot_id = base::GenerateGUID();
269 data.type = !snapshot.empty() ? DELAYED_SNAPSHOT : URL; 256 data.type = !snapshot.empty() ? DELAYED_SNAPSHOT : URL;
270 257
271 net::URLFetcher* submit_url = CreateRequest(data); 258 net::URLFetcher* submit_url = CreateRequest(data);
272 request_observer_map_[submit_url] = observer; 259 request_observer_map_[submit_url] = observer;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 } 294 }
308 295
309 void ChromeToMobileService::LearnMore(Browser* browser) const { 296 void ChromeToMobileService::LearnMore(Browser* browser) const {
310 LogMetric(LEARN_MORE_CLICKED); 297 LogMetric(LEARN_MORE_CLICKED);
311 chrome::NavigateParams params(browser, 298 chrome::NavigateParams params(browser,
312 GURL(chrome::kChromeToMobileLearnMoreURL), content::PAGE_TRANSITION_LINK); 299 GURL(chrome::kChromeToMobileLearnMoreURL), content::PAGE_TRANSITION_LINK);
313 params.disposition = NEW_FOREGROUND_TAB; 300 params.disposition = NEW_FOREGROUND_TAB;
314 chrome::Navigate(&params); 301 chrome::Navigate(&params);
315 } 302 }
316 303
317 void ChromeToMobileService::OnURLFetchComplete(const net::URLFetcher* source) { 304 void ChromeToMobileService::OnURLFetchComplete(
318 if (source->GetURL() == GetSearchURL(cloud_print_url_)) 305 const net::URLFetcher* source) {
319 HandleSearchResponse(source); 306 if (source == account_info_request_.get())
307 HandleAccountInfoResponse();
308 else if (source == search_request_.get())
309 HandleSearchResponse();
320 else 310 else
321 HandleSubmitResponse(source); 311 HandleSubmitResponse(source);
322 } 312 }
323 313
324 void ChromeToMobileService::Observe( 314 void ChromeToMobileService::Observe(
325 int type, 315 int type,
326 const content::NotificationSource& source, 316 const content::NotificationSource& source,
327 const content::NotificationDetails& details) { 317 const content::NotificationDetails& details) {
328 DCHECK_EQ(type, chrome::NOTIFICATION_TOKEN_AVAILABLE); 318 DCHECK_EQ(type, chrome::NOTIFICATION_TOKEN_AVAILABLE);
329 TokenService::TokenAvailableDetails* token_details = 319 TokenService::TokenAvailableDetails* token_details =
330 content::Details<TokenService::TokenAvailableDetails>(details).ptr(); 320 content::Details<TokenService::TokenAvailableDetails>(details).ptr();
331 // Invalidate the cloud print access token on Gaia login token updates.
332 if (token_details->service() == GaiaConstants::kGaiaOAuth2LoginRefreshToken) 321 if (token_details->service() == GaiaConstants::kGaiaOAuth2LoginRefreshToken)
333 access_token_.clear(); 322 RequestAccessToken();
334 } 323 }
335 324
336 void ChromeToMobileService::OnGetTokenSuccess( 325 void ChromeToMobileService::OnGetTokenSuccess(
337 const std::string& access_token, 326 const std::string& access_token,
338 const base::Time& expiration_time) { 327 const base::Time& expiration_time) {
339 DCHECK(!access_token.empty()); 328 DCHECK(!access_token.empty());
340 access_token_fetcher_.reset(); 329 access_token_fetcher_.reset();
341 auth_retry_timer_.Stop(); 330 auth_retry_timer_.Stop();
342 access_token_ = access_token; 331 access_token_ = access_token;
343 332 RequestAccountInfo();
344 while (!task_queue_.empty()) {
345 // Post all tasks that were queued and waiting on a valid access token.
346 if (!content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
347 task_queue_.front())) {
348 NOTREACHED();
349 }
350 task_queue_.pop();
351 }
352 } 333 }
353 334
354 void ChromeToMobileService::OnGetTokenFailure( 335 void ChromeToMobileService::OnGetTokenFailure(
355 const GoogleServiceAuthError& error) { 336 const GoogleServiceAuthError& error) {
356 access_token_fetcher_.reset(); 337 access_token_fetcher_.reset();
357 auth_retry_timer_.Stop(); 338 auth_retry_timer_.Stop();
358
359 auth_retry_timer_.Start( 339 auth_retry_timer_.Start(
360 FROM_HERE, base::TimeDelta::FromHours(kAuthRetryDelayHours), 340 FROM_HERE, base::TimeDelta::FromHours(kAuthRetryDelayHours),
361 this, &ChromeToMobileService::RequestAccessToken); 341 this, &ChromeToMobileService::RequestAccessToken);
362 } 342 }
363 343
364 void ChromeToMobileService::OnNotificationsEnabled() {
365 sync_invalidation_enabled_ = true;
366 UpdateCommandState();
367 }
368
369 void ChromeToMobileService::OnNotificationsDisabled(
370 syncer::NotificationsDisabledReason reason) {
371 sync_invalidation_enabled_ = false;
372 UpdateCommandState();
373 }
374
375 void ChromeToMobileService::OnIncomingNotification(
376 const syncer::ObjectIdPayloadMap& id_payloads,
377 syncer::IncomingNotificationSource source) {
378 DCHECK_EQ(id_payloads.size(), 1U);
379 DCHECK_EQ(id_payloads.count(invalidation::ObjectId(
380 ipc::invalidation::ObjectSource::CHROME_COMPONENTS,
381 kSyncInvalidationObjectIdChromeToMobileDeviceList)), 1U);
382 RequestDeviceSearch();
383 }
384
385 const std::string& ChromeToMobileService::GetAccessTokenForTest() const {
386 return access_token_;
387 }
388
389 void ChromeToMobileService::SetAccessTokenForTest(
390 const std::string& access_token) {
391 access_token_ = access_token;
392 }
393
394 void ChromeToMobileService::UpdateCommandState() const { 344 void ChromeToMobileService::UpdateCommandState() const {
395 // Ensure the feature is not disabled by commandline options. 345 // Ensure the feature is not disabled by commandline options.
396 DCHECK(IsChromeToMobileEnabled()); 346 DCHECK(IsChromeToMobileEnabled());
397 const bool has_mobiles = HasMobiles(); 347 const bool has_mobiles = HasMobiles();
398 for (BrowserList::const_iterator i = BrowserList::begin(); 348 for (BrowserList::const_iterator i = BrowserList::begin();
399 i != BrowserList::end(); ++i) { 349 i != BrowserList::end(); ++i) {
400 Browser* browser = *i; 350 Browser* browser = *i;
401 if (browser->profile() == profile_) 351 if (browser->profile() == profile_)
402 browser->command_controller()->SendToMobileStateChanged(has_mobiles); 352 browser->command_controller()->SendToMobileStateChanged(has_mobiles);
403 } 353 }
(...skipping 13 matching lines...) Expand all
417 // Generate the snapshot and have the observer be called back on completion. 367 // Generate the snapshot and have the observer be called back on completion.
418 chrome::GetActiveWebContents(browser)->GenerateMHTML(path, 368 chrome::GetActiveWebContents(browser)->GenerateMHTML(path,
419 base::Bind(&Observer::SnapshotGenerated, observer)); 369 base::Bind(&Observer::SnapshotGenerated, observer));
420 } else if (observer.get()) { 370 } else if (observer.get()) {
421 // Signal snapshot generation failure. 371 // Signal snapshot generation failure.
422 observer->SnapshotGenerated(FilePath(), 0); 372 observer->SnapshotGenerated(FilePath(), 0);
423 } 373 }
424 } 374 }
425 375
426 net::URLFetcher* ChromeToMobileService::CreateRequest(const JobData& data) { 376 net::URLFetcher* ChromeToMobileService::CreateRequest(const JobData& data) {
377 const GURL service_url(cloud_print_url_->GetCloudPrintServiceURL());
427 net::URLFetcher* request = net::URLFetcher::Create( 378 net::URLFetcher* request = net::URLFetcher::Create(
428 cloud_print::GetUrlForSubmit(cloud_print_url_), 379 cloud_print::GetUrlForSubmit(service_url), net::URLFetcher::POST, this);
429 net::URLFetcher::POST, this);
430 InitRequest(request); 380 InitRequest(request);
431 return request; 381 return request;
432 } 382 }
433 383
434 void ChromeToMobileService::InitRequest(net::URLFetcher* request) { 384 void ChromeToMobileService::InitRequest(net::URLFetcher* request) {
435 request->SetRequestContext(profile_->GetRequestContext()); 385 request->SetRequestContext(profile_->GetRequestContext());
436 request->SetMaxRetries(kMaxRetries); 386 request->SetMaxRetries(kMaxRetries);
437 DCHECK(!access_token_.empty()); 387 DCHECK(!access_token_.empty());
438 request->SetExtraRequestHeaders("Authorization: OAuth " + 388 request->SetExtraRequestHeaders("Authorization: OAuth " +
439 access_token_ + "\r\n" + cloud_print::kChromeCloudPrintProxyHeader); 389 access_token_ + "\r\n" + cloud_print::kChromeCloudPrintProxyHeader);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 } 428 }
479 cloud_print::AddMultipartValueForUpload("content", file, bound, 429 cloud_print::AddMultipartValueForUpload("content", file, bound,
480 "text/mhtml", &post); 430 "text/mhtml", &post);
481 431
482 post.append("--" + bound + "--\r\n"); 432 post.append("--" + bound + "--\r\n");
483 request->SetUploadData("multipart/form-data; boundary=" + bound, post); 433 request->SetUploadData("multipart/form-data; boundary=" + bound, post);
484 request->Start(); 434 request->Start();
485 } 435 }
486 436
487 void ChromeToMobileService::RequestAccessToken() { 437 void ChromeToMobileService::RequestAccessToken() {
488 // Register to observe Gaia login refresh token updates. 438 // Deny concurrent requests and bail without a valid Gaia login refresh token.
489 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 439 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
490 if (registrar_.IsEmpty())
491 registrar_.Add(this, chrome::NOTIFICATION_TOKEN_AVAILABLE,
492 content::Source<TokenService>(token_service));
493
494 // Deny concurrent requests and bail without a valid Gaia login refresh token.
495 if (access_token_fetcher_.get() || !token_service->HasOAuthLoginToken()) 440 if (access_token_fetcher_.get() || !token_service->HasOAuthLoginToken())
496 return; 441 return;
497 442
498 auth_retry_timer_.Stop(); 443 auth_retry_timer_.Stop();
499 access_token_fetcher_.reset( 444 access_token_fetcher_.reset(
500 new OAuth2AccessTokenFetcher(this, profile_->GetRequestContext())); 445 new OAuth2AccessTokenFetcher(this, profile_->GetRequestContext()));
501 GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); 446 GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
502 access_token_fetcher_->Start(gaia_urls->oauth2_chrome_client_id(), 447 access_token_fetcher_->Start(gaia_urls->oauth2_chrome_client_id(),
503 gaia_urls->oauth2_chrome_client_secret(), 448 gaia_urls->oauth2_chrome_client_secret(),
504 token_service->GetOAuth2LoginRefreshToken(), 449 token_service->GetOAuth2LoginRefreshToken(),
505 std::vector<std::string>(1, kCloudPrintAuth)); 450 std::vector<std::string>(1, kCloudPrintAuth));
506 } 451 }
507 452
508 void ChromeToMobileService::RequestDeviceSearch() { 453 void ChromeToMobileService::RequestAccountInfo() {
509 DCHECK(sync_invalidation_enabled_); 454 // Deny concurrent requests.
510 if (access_token_.empty()) { 455 if (account_info_request_.get())
511 // Enqueue this task to perform after obtaining an access token. 456 return;
512 task_queue_.push(base::Bind(&ChromeToMobileService::RequestDeviceSearch, 457
513 weak_ptr_factory_.GetWeakPtr())); 458 std::string url_string = StringPrintf(kAccountInfoURL,
514 RequestAccessToken(); 459 base::GenerateGUID().c_str(), kChromeToMobileRequestor);
460 GURL url(url_string);
461
462 // Account information is read from the profile's cookie. If cookies are
463 // blocked, access cloud print directly to list any potential devices.
464 scoped_refptr<CookieSettings> cookie_settings =
465 CookieSettings::Factory::GetForProfile(profile_);
466 if (cookie_settings && !cookie_settings->IsReadingCookieAllowed(url, url)) {
467 cloud_print_accessible_ = true;
468 RequestMobileListUpdate();
515 return; 469 return;
516 } 470 }
517 471
472 account_info_request_.reset(
473 net::URLFetcher::Create(url, net::URLFetcher::GET, this));
474 account_info_request_->SetRequestContext(profile_->GetRequestContext());
475 account_info_request_->SetMaxRetries(kMaxRetries);
476 // This request sends the user's cookie to check the cloud print service flag.
477 account_info_request_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
478 account_info_request_->Start();
479 }
480
481 void ChromeToMobileService::RequestDeviceSearch() {
482 // Deny requests if cloud print is inaccessible, and deny concurrent requests.
483 if (!cloud_print_accessible_ || search_request_.get())
484 return;
485
486 PrefService* prefs = profile_->GetPrefs();
487 base::TimeTicks previous_search_time = base::TimeTicks::FromInternalValue(
488 prefs->GetInt64(prefs::kChromeToMobileTimestamp));
489
490 // Deny requests before the delay period has passed since the last request.
491 base::TimeDelta elapsed_time = base::TimeTicks::Now() - previous_search_time;
492 if (!previous_search_time.is_null() &&
493 elapsed_time.InHours() < kSearchRequestDelayHours)
494 return;
495
518 LogMetric(DEVICES_REQUESTED); 496 LogMetric(DEVICES_REQUESTED);
519 497
520 net::URLFetcher* search_request = net::URLFetcher::Create( 498 const GURL service_url(cloud_print_url_->GetCloudPrintServiceURL());
521 GetSearchURL(cloud_print_url_), net::URLFetcher::GET, this); 499 search_request_.reset(net::URLFetcher::Create(GetSearchURL(service_url),
522 InitRequest(search_request); 500 net::URLFetcher::GET, this));
523 search_request->Start(); 501 InitRequest(search_request_.get());
502 search_request_->Start();
524 } 503 }
525 504
526 void ChromeToMobileService::HandleSearchResponse( 505 void ChromeToMobileService::HandleAccountInfoResponse() {
527 const net::URLFetcher* source) {
528 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 506 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
529 DCHECK_EQ(source->GetURL(), GetSearchURL(cloud_print_url_));
530 507
531 std::string data; 508 std::string data;
509 account_info_request_->GetResponseAsString(&data);
510 account_info_request_.reset();
511
512 ListValue* services = NULL;
513 DictionaryValue* dictionary = NULL;
514 scoped_ptr<Value> json(base::JSONReader::Read(data));
515 StringValue cloud_print_service(kCloudPrintSerivceValue);
516 if (json.get() && json->GetAsDictionary(&dictionary) && dictionary &&
517 dictionary->GetList(kAccountServicesKey, &services) && services &&
518 services->Find(cloud_print_service) != services->end()) {
519 cloud_print_accessible_ = true;
520 RequestMobileListUpdate();
521 }
522 }
523
524 void ChromeToMobileService::HandleSearchResponse() {
525 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
526
527 std::string data;
528 search_request_->GetResponseAsString(&data);
529 search_request_.reset();
530
532 ListValue* list = NULL; 531 ListValue* list = NULL;
533 DictionaryValue* dictionary = NULL; 532 DictionaryValue* dictionary = NULL;
534 source->GetResponseAsString(&data);
535 scoped_ptr<Value> json(base::JSONReader::Read(data)); 533 scoped_ptr<Value> json(base::JSONReader::Read(data));
536 if (json.get() && json->GetAsDictionary(&dictionary) && dictionary && 534 if (json.get() && json->GetAsDictionary(&dictionary) && dictionary &&
537 dictionary->GetList(cloud_print::kPrinterListValue, &list)) { 535 dictionary->GetList(cloud_print::kPrinterListValue, &list)) {
538 ListValue mobiles; 536 ListValue mobiles;
539 std::string type, name, id; 537 std::string type, name, id;
540 DictionaryValue* printer = NULL; 538 DictionaryValue* printer = NULL;
541 DictionaryValue* mobile = NULL; 539 DictionaryValue* mobile = NULL;
542 for (size_t index = 0; index < list->GetSize(); ++index) { 540 for (size_t index = 0; index < list->GetSize(); ++index) {
543 if (list->GetDictionary(index, &printer) && 541 if (list->GetDictionary(index, &printer) &&
544 printer->GetString("type", &type) && 542 printer->GetString("type", &type) &&
545 (type.compare(kTypeAndroid) == 0 || type.compare(kTypeIOS) == 0)) { 543 (type.compare(kTypeAndroid) == 0 || type.compare(kTypeIOS) == 0)) {
546 // Copy just the requisite values from the full |printer| definition. 544 // Copy just the requisite values from the full |printer| definition.
547 if (printer->GetString("displayName", &name) && 545 if (printer->GetString("displayName", &name) &&
548 printer->GetString("id", &id)) { 546 printer->GetString("id", &id)) {
549 mobile = new DictionaryValue(); 547 mobile = new DictionaryValue();
550 mobile->SetString("type", type); 548 mobile->SetString("type", type);
551 mobile->SetString("name", name); 549 mobile->SetString("name", name);
552 mobile->SetString("id", id); 550 mobile->SetString("id", id);
553 mobiles.Append(mobile); 551 mobiles.Append(mobile);
554 } else { 552 } else {
555 NOTREACHED(); 553 NOTREACHED();
556 } 554 }
557 } 555 }
558 } 556 }
559 557
560 // Update the cached mobile device list in profile prefs. 558 // Update the mobile list and timestamp in prefs.
561 profile_->GetPrefs()->Set(prefs::kChromeToMobileDeviceList, mobiles); 559 PrefService* prefs = profile_->GetPrefs();
560 prefs->Set(prefs::kChromeToMobileDeviceList, mobiles);
561 prefs->SetInt64(prefs::kChromeToMobileTimestamp,
562 base::TimeTicks::Now().ToInternalValue());
562 563
563 if (HasMobiles()) 564 if (HasMobiles())
564 LogMetric(DEVICES_AVAILABLE); 565 LogMetric(DEVICES_AVAILABLE);
565 UpdateCommandState(); 566 UpdateCommandState();
566 } 567 }
567 } 568 }
568 569
569 void ChromeToMobileService::HandleSubmitResponse( 570 void ChromeToMobileService::HandleSubmitResponse(
570 const net::URLFetcher* source) { 571 const net::URLFetcher* source) {
571 // Get the observer for this response; bail if there is none or it is NULL. 572 // Get the observer for this response; bail if there is none or it is NULL.
(...skipping 24 matching lines...) Expand all
596 597
597 // Ensure a second response is not sent after reporting failure below. 598 // Ensure a second response is not sent after reporting failure below.
598 request_observer_map_.erase(other); 599 request_observer_map_.erase(other);
599 break; 600 break;
600 } 601 }
601 } 602 }
602 603
603 LogMetric(success ? SEND_SUCCESS : SEND_ERROR); 604 LogMetric(success ? SEND_SUCCESS : SEND_ERROR);
604 observer->OnSendComplete(success); 605 observer->OnSendComplete(success);
605 } 606 }
OLDNEW
« no previous file with comments | « chrome/browser/chrome_to_mobile_service.h ('k') | chrome/browser/chrome_to_mobile_service_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698