diff options
-rw-r--r-- | chrome/browser/DEPS | 2 | ||||
-rw-r--r-- | chrome/browser/chrome_to_mobile_service.cc | 242 | ||||
-rw-r--r-- | chrome/browser/chrome_to_mobile_service.h | 52 | ||||
-rw-r--r-- | chrome/browser/chrome_to_mobile_service_factory.cc | 4 | ||||
-rw-r--r-- | chrome/browser/chrome_to_mobile_service_factory.h | 1 | ||||
-rw-r--r-- | chrome/browser/chrome_to_mobile_service_unittest.cc | 19 | ||||
-rw-r--r-- | chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller.mm | 5 | ||||
-rw-r--r-- | chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller_unittest.mm | 16 | ||||
-rw-r--r-- | chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm | 3 | ||||
-rw-r--r-- | chrome/browser/ui/gtk/chrome_to_mobile_bubble_gtk.cc | 8 | ||||
-rw-r--r-- | chrome/browser/ui/gtk/location_bar_view_gtk.cc | 5 | ||||
-rw-r--r-- | chrome/browser/ui/views/chrome_to_mobile_bubble_view.cc | 5 | ||||
-rw-r--r-- | chrome/browser/ui/views/location_bar/location_bar_view.cc | 8 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 3 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 1 |
15 files changed, 192 insertions, 182 deletions
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 775f092..e0a75e7 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS @@ -5,6 +5,7 @@ include_rules = [ "+chrome/tools/profiles", # For history unit tests. "+chromeos", "+content/public/browser", + "+google/cacheinvalidation", # Sync invalidation API protobuf files. "+google_update", "+grit", # For generated headers "+installer_util_strings", # For generated headers @@ -20,6 +21,7 @@ include_rules = [ "+skia/ext", "+skia/include", "+sync/api", # Sync API files. + "+sync/notifier", # Sync invalidation API files. "+sync/protocol", # Sync protobuf files. "+third_party/cros_system_api", "+webkit/database", diff --git a/chrome/browser/chrome_to_mobile_service.cc b/chrome/browser/chrome_to_mobile_service.cc index bc80c39..34afa32 100644 --- a/chrome/browser/chrome_to_mobile_service.cc +++ b/chrome/browser/chrome_to_mobile_service.cc @@ -11,15 +11,15 @@ #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/metrics/histogram.h" -#include "base/stringprintf.h" #include "base/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/content_settings/cookie_settings.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/printing/cloud_print/cloud_print_url.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/token_service.h" #include "chrome/browser/signin/token_service_factory.h" +#include "chrome/browser/sync/profile_sync_service.h" +#include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_command_controller.h" #include "chrome/browser/ui/browser_finder.h" @@ -38,10 +38,13 @@ #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/web_contents.h" +#include "google/cacheinvalidation/include/types.h" +#include "google/cacheinvalidation/types.pb.h" #include "net/base/escape.h" #include "net/base/load_flags.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_request_context_getter.h" +#include "sync/notifier/invalidation_util.h" namespace { @@ -59,19 +62,16 @@ const size_t kAuthRetryDelayHours = 6; // Note that this limitation does not hold across application restarts. const int kSearchRequestDelayHours = 24; +// The sync invalidation object ID for Chrome to Mobile's mobile device list. +// This corresponds with cloud print's server-side invalidation object ID. +// Meaning: "U" == "User", "CM" == "Chrome to Mobile", "MLST" == "Mobile LiST". +const char kSyncInvalidationObjectIdChromeToMobileDeviceList[] = "UCMMLST"; + // The cloud print OAuth2 scope and 'printer' type of compatible mobile devices. const char kCloudPrintAuth[] = "https://www.googleapis.com/auth/cloudprint"; const char kTypeAndroid[] = "ANDROID_CHROME_SNAPSHOT"; const char kTypeIOS[] = "IOS_CHROME_SNAPSHOT"; -// The account info URL pattern and strings to check for cloud print access. -// The 'key=' query parameter is used for caching; supply a random number. -// The 'rv=2' query parameter requests a JSON response; use 'rv=1' for XML. -const char kAccountInfoURL[] = - "https://clients1.google.com/tbproxy/getaccountinfo?key=%s&rv=2&%s"; -const char kAccountServicesKey[] = "services"; -const char kCloudPrintSerivceValue[] = "cprt"; - // The Chrome To Mobile requestor type; used by services for filtering. const char kChromeToMobileRequestor[] = "requestor=chrome-to-mobile"; @@ -125,8 +125,8 @@ void AddValue(const std::string& value_name, } // Get the URL for cloud print device search; appends a requestor query param. -GURL GetSearchURL(const GURL& service_url) { - GURL search_url = cloud_print::GetUrlForSearch(service_url); +GURL GetSearchURL(const GURL& cloud_print_url) { + GURL search_url = cloud_print::GetUrlForSearch(cloud_print_url); GURL::Replacements replacements; std::string query(kChromeToMobileRequestor); replacements.SetQueryStr(query); @@ -180,23 +180,26 @@ bool ChromeToMobileService::IsChromeToMobileEnabled() { void ChromeToMobileService::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterListPref(prefs::kChromeToMobileDeviceList, PrefService::UNSYNCABLE_PREF); - prefs->RegisterInt64Pref(prefs::kChromeToMobileTimestamp, 0, - PrefService::UNSYNCABLE_PREF); } ChromeToMobileService::ChromeToMobileService(Profile* profile) : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), profile_(profile), - cloud_print_url_(new CloudPrintURL(profile)), - cloud_print_accessible_(false) { - // TODO(msw): Fix GMock tests, which lack profiles (http://crbug.com/122183). - if (profile_) { - // Get an access token as soon as the Gaia login refresh token is available. - TokenService* service = TokenServiceFactory::GetForProfile(profile_); - registrar_.Add(this, chrome::NOTIFICATION_TOKEN_AVAILABLE, - content::Source<TokenService>(service)); - if (service->HasOAuthLoginToken()) - RequestAccessToken(); + sync_invalidation_enabled_(false) { + // TODO(msw): Unit tests do not provide profiles; see http://crbug.com/122183 + ProfileSyncService* profile_sync_service = + profile_ ? ProfileSyncServiceFactory::GetForProfile(profile_) : NULL; + if (profile_sync_service) { + CloudPrintURL cloud_print_url(profile_); + cloud_print_url_ = cloud_print_url.GetCloudPrintServiceURL(); + // Register for cloud print device list invalidation notifications. + // TODO(msw|akalin): Initialize |sync_invalidation_enabled_| properly. + profile_sync_service->RegisterInvalidationHandler(this); + syncer::ObjectIdSet ids; + ids.insert(invalidation::ObjectId( + ipc::invalidation::ObjectSource::CHROME_COMPONENTS, + kSyncInvalidationObjectIdChromeToMobileDeviceList)); + profile_sync_service->UpdateRegisteredInvalidationIds(this, ids); } } @@ -206,18 +209,13 @@ ChromeToMobileService::~ChromeToMobileService() { } bool ChromeToMobileService::HasMobiles() const { - return !GetMobiles()->empty(); + const base::ListValue* mobiles = GetMobiles(); + return mobiles && !mobiles->empty(); } const base::ListValue* ChromeToMobileService::GetMobiles() const { - return profile_->GetPrefs()->GetList(prefs::kChromeToMobileDeviceList); -} - -void ChromeToMobileService::RequestMobileListUpdate() { - if (access_token_.empty()) - RequestAccessToken(); - else if (cloud_print_accessible_) - RequestDeviceSearch(); + return sync_invalidation_enabled_ ? + profile_->GetPrefs()->GetList(prefs::kChromeToMobileDeviceList) : NULL; } void ChromeToMobileService::GenerateSnapshot(Browser* browser, @@ -234,19 +232,28 @@ void ChromeToMobileService::GenerateSnapshot(Browser* browser, } } -void ChromeToMobileService::SendToMobile(const base::DictionaryValue& mobile, +void ChromeToMobileService::SendToMobile(const base::DictionaryValue* mobile, const FilePath& snapshot, Browser* browser, base::WeakPtr<Observer> observer) { + if (access_token_.empty()) { + // Enqueue this task to perform after obtaining an access token. + task_queue_.push(base::Bind(&ChromeToMobileService::SendToMobile, + weak_ptr_factory_.GetWeakPtr(), base::Owned(mobile->DeepCopy()), + snapshot, browser, observer)); + RequestAccessToken(); + return; + } + LogMetric(SENDING_URL); JobData data; std::string mobile_os; - if (!mobile.GetString("type", &mobile_os)) + if (!mobile->GetString("type", &mobile_os)) NOTREACHED(); data.mobile_os = (mobile_os.compare(kTypeAndroid) == 0) ? ChromeToMobileService::ANDROID : ChromeToMobileService::IOS; - if (!mobile.GetString("id", &data.mobile_id)) + if (!mobile->GetString("id", &data.mobile_id)) NOTREACHED(); content::WebContents* web_contents = chrome::GetActiveWebContents(browser); data.url = web_contents->GetURL(); @@ -301,12 +308,18 @@ void ChromeToMobileService::LearnMore(Browser* browser) const { chrome::Navigate(¶ms); } -void ChromeToMobileService::OnURLFetchComplete( - const net::URLFetcher* source) { - if (source == account_info_request_.get()) - HandleAccountInfoResponse(); - else if (source == search_request_.get()) - HandleSearchResponse(); +void ChromeToMobileService::Shutdown() { + // TODO(msw): Unit tests do not provide profiles; see http://crbug.com/122183 + // Unregister for cloud print device list invalidation notifications. + ProfileSyncService* profile_sync_service = + profile_ ? ProfileSyncServiceFactory::GetForProfile(profile_) : NULL; + if (profile_sync_service) + profile_sync_service->UnregisterInvalidationHandler(this); +} + +void ChromeToMobileService::OnURLFetchComplete(const net::URLFetcher* source) { + if (source->GetURL() == GetSearchURL(cloud_print_url_)) + HandleSearchResponse(source); else HandleSubmitResponse(source); } @@ -318,8 +331,9 @@ void ChromeToMobileService::Observe( DCHECK_EQ(type, chrome::NOTIFICATION_TOKEN_AVAILABLE); TokenService::TokenAvailableDetails* token_details = content::Details<TokenService::TokenAvailableDetails>(details).ptr(); + // Invalidate the cloud print access token on Gaia login token updates. if (token_details->service() == GaiaConstants::kGaiaOAuth2LoginRefreshToken) - RequestAccessToken(); + access_token_.clear(); } void ChromeToMobileService::OnGetTokenSuccess( @@ -329,18 +343,57 @@ void ChromeToMobileService::OnGetTokenSuccess( access_token_fetcher_.reset(); auth_retry_timer_.Stop(); access_token_ = access_token; - RequestAccountInfo(); + + while (!task_queue_.empty()) { + // Post all tasks that were queued and waiting on a valid access token. + if (!content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + task_queue_.front())) { + NOTREACHED(); + } + task_queue_.pop(); + } } void ChromeToMobileService::OnGetTokenFailure( const GoogleServiceAuthError& error) { access_token_fetcher_.reset(); auth_retry_timer_.Stop(); + auth_retry_timer_.Start( FROM_HERE, base::TimeDelta::FromHours(kAuthRetryDelayHours), this, &ChromeToMobileService::RequestAccessToken); } +void ChromeToMobileService::OnNotificationsEnabled() { + sync_invalidation_enabled_ = true; + UpdateCommandState(); +} + +void ChromeToMobileService::OnNotificationsDisabled( + syncer::NotificationsDisabledReason reason) { + sync_invalidation_enabled_ = false; + UpdateCommandState(); +} + +void ChromeToMobileService::OnIncomingNotification( + const syncer::ObjectIdPayloadMap& id_payloads, + syncer::IncomingNotificationSource source) { + DCHECK_EQ(id_payloads.size(), 1U); + DCHECK_EQ(id_payloads.count(invalidation::ObjectId( + ipc::invalidation::ObjectSource::CHROME_COMPONENTS, + kSyncInvalidationObjectIdChromeToMobileDeviceList)), 1U); + RequestDeviceSearch(); +} + +const std::string& ChromeToMobileService::GetAccessTokenForTest() const { + return access_token_; +} + +void ChromeToMobileService::SetAccessTokenForTest( + const std::string& access_token) { + access_token_ = access_token; +} + void ChromeToMobileService::UpdateCommandState() const { // Ensure the feature is not disabled by commandline options. DCHECK(IsChromeToMobileEnabled()); @@ -374,9 +427,9 @@ void ChromeToMobileService::SnapshotFileCreated( } net::URLFetcher* ChromeToMobileService::CreateRequest(const JobData& data) { - const GURL service_url(cloud_print_url_->GetCloudPrintServiceURL()); net::URLFetcher* request = net::URLFetcher::Create( - cloud_print::GetUrlForSubmit(service_url), net::URLFetcher::POST, this); + cloud_print::GetUrlForSubmit(cloud_print_url_), + net::URLFetcher::POST, this); InitRequest(request); return request; } @@ -435,8 +488,13 @@ void ChromeToMobileService::SendRequest(net::URLFetcher* request, } void ChromeToMobileService::RequestAccessToken() { - // Deny concurrent requests and bail without a valid Gaia login refresh token. + // Register to observe Gaia login refresh token updates. TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); + if (registrar_.IsEmpty()) + registrar_.Add(this, chrome::NOTIFICATION_TOKEN_AVAILABLE, + content::Source<TokenService>(token_service)); + + // Deny concurrent requests and bail without a valid Gaia login refresh token. if (access_token_fetcher_.get() || !token_service->HasOAuthLoginToken()) return; @@ -450,86 +508,33 @@ void ChromeToMobileService::RequestAccessToken() { std::vector<std::string>(1, kCloudPrintAuth)); } -void ChromeToMobileService::RequestAccountInfo() { - // Deny concurrent requests. - if (account_info_request_.get()) - return; - - std::string url_string = StringPrintf(kAccountInfoURL, - base::GenerateGUID().c_str(), kChromeToMobileRequestor); - GURL url(url_string); - - // Account information is read from the profile's cookie. If cookies are - // blocked, access cloud print directly to list any potential devices. - scoped_refptr<CookieSettings> cookie_settings = - CookieSettings::Factory::GetForProfile(profile_); - if (cookie_settings && !cookie_settings->IsReadingCookieAllowed(url, url)) { - cloud_print_accessible_ = true; - RequestMobileListUpdate(); - return; - } - - account_info_request_.reset( - net::URLFetcher::Create(url, net::URLFetcher::GET, this)); - account_info_request_->SetRequestContext(profile_->GetRequestContext()); - account_info_request_->SetMaxRetries(kMaxRetries); - // This request sends the user's cookie to check the cloud print service flag. - account_info_request_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); - account_info_request_->Start(); -} - void ChromeToMobileService::RequestDeviceSearch() { - // Deny requests if cloud print is inaccessible, and deny concurrent requests. - if (!cloud_print_accessible_ || search_request_.get()) - return; - - PrefService* prefs = profile_->GetPrefs(); - base::TimeTicks previous_search_time = base::TimeTicks::FromInternalValue( - prefs->GetInt64(prefs::kChromeToMobileTimestamp)); - - // Deny requests before the delay period has passed since the last request. - base::TimeDelta elapsed_time = base::TimeTicks::Now() - previous_search_time; - if (!previous_search_time.is_null() && - elapsed_time.InHours() < kSearchRequestDelayHours) + DCHECK(sync_invalidation_enabled_); + if (access_token_.empty()) { + // Enqueue this task to perform after obtaining an access token. + task_queue_.push(base::Bind(&ChromeToMobileService::RequestDeviceSearch, + weak_ptr_factory_.GetWeakPtr())); + RequestAccessToken(); return; + } LogMetric(DEVICES_REQUESTED); - const GURL service_url(cloud_print_url_->GetCloudPrintServiceURL()); - search_request_.reset(net::URLFetcher::Create(GetSearchURL(service_url), - net::URLFetcher::GET, this)); - InitRequest(search_request_.get()); - search_request_->Start(); -} - -void ChromeToMobileService::HandleAccountInfoResponse() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - - std::string data; - account_info_request_->GetResponseAsString(&data); - account_info_request_.reset(); - - ListValue* services = NULL; - DictionaryValue* dictionary = NULL; - scoped_ptr<Value> json(base::JSONReader::Read(data)); - StringValue cloud_print_service(kCloudPrintSerivceValue); - if (json.get() && json->GetAsDictionary(&dictionary) && dictionary && - dictionary->GetList(kAccountServicesKey, &services) && services && - services->Find(cloud_print_service) != services->end()) { - cloud_print_accessible_ = true; - RequestMobileListUpdate(); - } + net::URLFetcher* search_request = net::URLFetcher::Create( + GetSearchURL(cloud_print_url_), net::URLFetcher::GET, this); + InitRequest(search_request); + search_request->Start(); } -void ChromeToMobileService::HandleSearchResponse() { +void ChromeToMobileService::HandleSearchResponse( + const net::URLFetcher* source) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_EQ(source->GetURL(), GetSearchURL(cloud_print_url_)); std::string data; - search_request_->GetResponseAsString(&data); - search_request_.reset(); - ListValue* list = NULL; DictionaryValue* dictionary = NULL; + source->GetResponseAsString(&data); scoped_ptr<Value> json(base::JSONReader::Read(data)); if (json.get() && json->GetAsDictionary(&dictionary) && dictionary && dictionary->GetList(cloud_print::kPrinterListValue, &list)) { @@ -555,11 +560,8 @@ void ChromeToMobileService::HandleSearchResponse() { } } - // Update the mobile list and timestamp in prefs. - PrefService* prefs = profile_->GetPrefs(); - prefs->Set(prefs::kChromeToMobileDeviceList, mobiles); - prefs->SetInt64(prefs::kChromeToMobileTimestamp, - base::TimeTicks::Now().ToInternalValue()); + // Update the cached mobile device list in profile prefs. + profile_->GetPrefs()->Set(prefs::kChromeToMobileDeviceList, mobiles); if (HasMobiles()) LogMetric(DEVICES_AVAILABLE); diff --git a/chrome/browser/chrome_to_mobile_service.h b/chrome/browser/chrome_to_mobile_service.h index 3613396..37a1b25 100644 --- a/chrome/browser/chrome_to_mobile_service.h +++ b/chrome/browser/chrome_to_mobile_service.h @@ -6,10 +6,12 @@ #define CHROME_BROWSER_CHROME_TO_MOBILE_SERVICE_H_ #include <map> +#include <queue> #include <set> #include <string> #include <vector> +#include "base/compiler_specific.h" #include "base/file_path.h" #include "base/memory/weak_ptr.h" #include "base/string16.h" @@ -22,6 +24,7 @@ #include "content/public/browser/notification_registrar.h" #include "googleurl/src/gurl.h" #include "net/url_request/url_fetcher_delegate.h" +#include "sync/notifier/sync_notifier_observer.h" class OAuth2AccessTokenFetcher; class Browser; @@ -39,7 +42,8 @@ class URLFetcher; class ChromeToMobileService : public ProfileKeyedService, public net::URLFetcherDelegate, public content::NotificationObserver, - public OAuth2AccessTokenConsumer { + public OAuth2AccessTokenConsumer, + public syncer::SyncNotifierObserver { public: class Observer { public: @@ -112,10 +116,6 @@ class ChromeToMobileService : public ProfileKeyedService, // Virtual for unit test mocking. virtual const base::ListValue* GetMobiles() const; - // Request an updated mobile device list, request auth first if needed. - // Virtual for unit test mocking. - virtual void RequestMobileListUpdate(); - // Callback with an MHTML snapshot of the browser's selected WebContents. // Virtual for unit test mocking. virtual void GenerateSnapshot(Browser* browser, @@ -123,7 +123,7 @@ class ChromeToMobileService : public ProfileKeyedService, // Send the browser's selected WebContents to the specified mobile device. // Virtual for unit test mocking. - virtual void SendToMobile(const base::DictionaryValue& mobile, + virtual void SendToMobile(const base::DictionaryValue* mobile, const FilePath& snapshot, Browser* browser, base::WeakPtr<Observer> observer); @@ -139,6 +139,9 @@ class ChromeToMobileService : public ProfileKeyedService, // Opens the "Learn More" help article link in the supplied |browser|. void LearnMore(Browser* browser) const; + // ProfileKeyedService method. + virtual void Shutdown() OVERRIDE; + // net::URLFetcherDelegate method. virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; @@ -152,6 +155,18 @@ class ChromeToMobileService : public ProfileKeyedService, const base::Time& expiration_time) OVERRIDE; virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE; + // syncer::SyncNotifierObserver implementation. + virtual void OnNotificationsEnabled() OVERRIDE; + virtual void OnNotificationsDisabled( + syncer::NotificationsDisabledReason reason) OVERRIDE; + virtual void OnIncomingNotification( + const syncer::ObjectIdPayloadMap& id_payloads, + syncer::IncomingNotificationSource source) OVERRIDE; + + // Expose access token accessors for test purposes. + const std::string& GetAccessTokenForTest() const; + void SetAccessTokenForTest(const std::string& access_token); + private: friend class MockChromeToMobileService; @@ -179,25 +194,26 @@ class ChromeToMobileService : public ProfileKeyedService, // Virtual for unit test mocking. virtual void RequestAccessToken(); - // Request account information to limit cloud print access to existing users. - void RequestAccountInfo(); - // Send the cloud print URLFetcher device search request. - void RequestDeviceSearch(); + // Virtual for unit test mocking. + virtual void RequestDeviceSearch(); - void HandleAccountInfoResponse(); - void HandleSearchResponse(); + void HandleSearchResponse(const net::URLFetcher* source); void HandleSubmitResponse(const net::URLFetcher* source); base::WeakPtrFactory<ChromeToMobileService> weak_ptr_factory_; Profile* profile_; + // Sync invalidation service state. Chrome To Mobile requires this service to + // to keep the mobile device list up to date and prevent page send failures. + bool sync_invalidation_enabled_; + // Used to recieve TokenService notifications for GaiaOAuth2LoginRefreshToken. content::NotificationRegistrar registrar_; - // Cloud print helper class and auth token. - scoped_ptr<CloudPrintURL> cloud_print_url_; + // The cloud print service URL and auth access token. + GURL cloud_print_url_; std::string access_token_; // The set of snapshots currently available. @@ -212,12 +228,8 @@ class ChromeToMobileService : public ProfileKeyedService, scoped_ptr<OAuth2AccessTokenFetcher> access_token_fetcher_; base::OneShotTimer<ChromeToMobileService> auth_retry_timer_; - // The pending account information request and the cloud print access flag. - scoped_ptr<net::URLFetcher> account_info_request_; - bool cloud_print_accessible_; - - // The pending mobile device search request. - scoped_ptr<net::URLFetcher> search_request_; + // A queue of tasks to perform after an access token is lazily initialized. + std::queue<base::Closure> task_queue_; DISALLOW_COPY_AND_ASSIGN(ChromeToMobileService); }; diff --git a/chrome/browser/chrome_to_mobile_service_factory.cc b/chrome/browser/chrome_to_mobile_service_factory.cc index 1058917..d2c6601 100644 --- a/chrome/browser/chrome_to_mobile_service_factory.cc +++ b/chrome/browser/chrome_to_mobile_service_factory.cc @@ -5,9 +5,9 @@ #include "chrome/browser/chrome_to_mobile_service_factory.h" #include "chrome/browser/chrome_to_mobile_service.h" -#include "chrome/browser/content_settings/cookie_settings.h" #include "chrome/browser/profiles/profile_dependency_manager.h" #include "chrome/browser/signin/token_service_factory.h" +#include "chrome/browser/sync/profile_sync_service_factory.h" // static ChromeToMobileServiceFactory* ChromeToMobileServiceFactory::GetInstance() { @@ -33,8 +33,8 @@ ProfileKeyedService* ChromeToMobileServiceFactory::BuildServiceInstanceFor( ChromeToMobileServiceFactory::ChromeToMobileServiceFactory() : ProfileKeyedServiceFactory("ChromeToMobileService", ProfileDependencyManager::GetInstance()) { + DependsOn(ProfileSyncServiceFactory::GetInstance()); DependsOn(TokenServiceFactory::GetInstance()); - DependsOn(CookieSettings::Factory::GetInstance()); // TODO(msw): Uncomment this once it exists. // DependsOn(PrefServiceFactory::GetInstance()); } diff --git a/chrome/browser/chrome_to_mobile_service_factory.h b/chrome/browser/chrome_to_mobile_service_factory.h index c3f62c6..5232a7f 100644 --- a/chrome/browser/chrome_to_mobile_service_factory.h +++ b/chrome/browser/chrome_to_mobile_service_factory.h @@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_CHROME_TO_MOBILE_SERVICE_FACTORY_H_ #define CHROME_BROWSER_CHROME_TO_MOBILE_SERVICE_FACTORY_H_ +#include "base/compiler_specific.h" #include "base/memory/singleton.h" #include "chrome/browser/profiles/profile_keyed_service_factory.h" diff --git a/chrome/browser/chrome_to_mobile_service_unittest.cc b/chrome/browser/chrome_to_mobile_service_unittest.cc index d1e6d41..8cff191 100644 --- a/chrome/browser/chrome_to_mobile_service_unittest.cc +++ b/chrome/browser/chrome_to_mobile_service_unittest.cc @@ -17,7 +17,6 @@ const char kDummyString[] = "dummy"; class DummyNotificationSource {}; -// A mock ChromeToMobileService with a mocked out RequestAccessToken method. class MockChromeToMobileService : public ChromeToMobileService { public: MockChromeToMobileService(); @@ -50,29 +49,37 @@ ChromeToMobileServiceTest::ChromeToMobileServiceTest() {} ChromeToMobileServiceTest::~ChromeToMobileServiceTest() {} -// Ensure that RequestAccessToken is not called for irrelevant notifications. +// Ensure that irrelevant notifications do not invalidate the access token. TEST_F(ChromeToMobileServiceTest, IgnoreIrrelevantNotifications) { EXPECT_CALL(service_, RequestAccessToken()).Times(0); - // Send dummy service/token details (should not refresh token). + service_.SetAccessTokenForTest(kDummyString); + ASSERT_FALSE(service_.GetAccessTokenForTest().empty()); + + // Send dummy service/token details (should not request token). DummyNotificationSource dummy_source; TokenService::TokenAvailableDetails dummy_details(kDummyString, kDummyString); service_.Observe(chrome::NOTIFICATION_TOKEN_AVAILABLE, content::Source<DummyNotificationSource>(&dummy_source), content::Details<TokenService::TokenAvailableDetails>(&dummy_details)); + EXPECT_FALSE(service_.GetAccessTokenForTest().empty()); } -// Ensure that RequestAccessToken is called on the proper notification. +// Ensure that proper notifications invalidate the access token. TEST_F(ChromeToMobileServiceTest, AuthenticateOnTokenAvailable) { - EXPECT_CALL(service_, RequestAccessToken()).Times(1); + EXPECT_CALL(service_, RequestAccessToken()).Times(0); + + service_.SetAccessTokenForTest(kDummyString); + ASSERT_FALSE(service_.GetAccessTokenForTest().empty()); - // Send a Gaia OAuth2 Login service dummy token (should refresh token). + // Send a Gaia OAuth2 Login service dummy token (should request token). DummyNotificationSource dummy_source; TokenService::TokenAvailableDetails login_details( GaiaConstants::kGaiaOAuth2LoginRefreshToken, kDummyString); service_.Observe(chrome::NOTIFICATION_TOKEN_AVAILABLE, content::Source<DummyNotificationSource>(&dummy_source), content::Details<TokenService::TokenAvailableDetails>(&login_details)); + EXPECT_TRUE(service_.GetAccessTokenForTest().empty()); } } // namespace diff --git a/chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller.mm b/chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller.mm index f8de658..61eb57a 100644 --- a/chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller.mm +++ b/chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller.mm @@ -165,9 +165,6 @@ void ChromeToMobileBubbleNotificationBridge::OnSendComplete(bool success) { // Generate the MHTML snapshot now to report its size in the bubble. service_->GenerateSnapshot(browser_, bridge_->AsWeakPtr()); - // Request a mobile device list update. - service_->RequestMobileListUpdate(); - [super showWindow:sender]; } @@ -187,7 +184,7 @@ void ChromeToMobileBubbleNotificationBridge::OnSendComplete(bool success) { const DictionaryValue* mobile = NULL; if (mobiles->GetDictionary(selected_index, &mobile)) { - service_->SendToMobile(*mobile, + service_->SendToMobile(mobile, ([sendCopy_ state] == NSOnState) ? snapshotPath_ : FilePath(), browser_, bridge_->AsWeakPtr()); } else { diff --git a/chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller_unittest.mm index c1efcb2..534a42f 100644 --- a/chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/chrome_to_mobile_bubble_controller_unittest.mm @@ -19,10 +19,9 @@ class MockChromeToMobileService : public ChromeToMobileService { // ChromeToMobileService overrides: virtual const base::ListValue* GetMobiles() const OVERRIDE; - MOCK_METHOD0(RequestMobileListUpdate, void()); MOCK_METHOD2(GenerateSnapshot, void(Browser* browser, base::WeakPtr<Observer> observer)); - MOCK_METHOD4(SendToMobile, void(const base::DictionaryValue& mobile, + MOCK_METHOD4(SendToMobile, void(const base::DictionaryValue* mobile, const FilePath& snapshot, Browser* browser, base::WeakPtr<Observer> observer)); @@ -36,7 +35,9 @@ class MockChromeToMobileService : public ChromeToMobileService { void MockChromeToMobileService::AddDevices(size_t count) { for(size_t i = 0; i < count; i++) { base::DictionaryValue* device = new base::DictionaryValue(); + device->SetString("type", "Device Type"); device->SetString("name", "Device Name"); + device->SetString("id", "Device ID"); mobiles_.Append(device); } } @@ -115,8 +116,9 @@ class ChromeToMobileBubbleControllerTest : public CocoaTest { }; TEST_F(ChromeToMobileBubbleControllerTest, OneDevice) { - EXPECT_CALL(service_, RequestMobileListUpdate()); EXPECT_CALL(service_, GenerateSnapshot(NULL, testing::_)); + EXPECT_CALL(service_, SendToMobile(testing::_, testing::_, + testing::_, testing::_)).Times(0); EXPECT_CALL(service_, DeleteSnapshot(testing::_)); EXPECT_CALL(service_, LogMetric(ChromeToMobileService::BUBBLE_SHOWN)); @@ -126,8 +128,9 @@ TEST_F(ChromeToMobileBubbleControllerTest, OneDevice) { } TEST_F(ChromeToMobileBubbleControllerTest, TwoDevices) { - EXPECT_CALL(service_, RequestMobileListUpdate()); EXPECT_CALL(service_, GenerateSnapshot(NULL, testing::_)); + EXPECT_CALL(service_, SendToMobile(testing::_, testing::_, + testing::_, testing::_)).Times(0); EXPECT_CALL(service_, DeleteSnapshot(testing::_)); EXPECT_CALL(service_, LogMetric(ChromeToMobileService::BUBBLE_SHOWN)); @@ -137,8 +140,9 @@ TEST_F(ChromeToMobileBubbleControllerTest, TwoDevices) { } TEST_F(ChromeToMobileBubbleControllerTest, ThreeDevices) { - EXPECT_CALL(service_, RequestMobileListUpdate()); EXPECT_CALL(service_, GenerateSnapshot(NULL, testing::_)); + EXPECT_CALL(service_, SendToMobile(testing::_, testing::_, + testing::_, testing::_)).Times(0); EXPECT_CALL(service_, DeleteSnapshot(testing::_)); EXPECT_CALL(service_, LogMetric(ChromeToMobileService::BUBBLE_SHOWN)); @@ -149,7 +153,6 @@ TEST_F(ChromeToMobileBubbleControllerTest, ThreeDevices) { TEST_F(ChromeToMobileBubbleControllerTest, SendWithoutSnapshot) { FilePath path; - EXPECT_CALL(service_, RequestMobileListUpdate()); EXPECT_CALL(service_, GenerateSnapshot(NULL, testing::_)); EXPECT_CALL(service_, SendToMobile(testing::_, path, NULL, testing::_)); EXPECT_CALL(service_, DeleteSnapshot(testing::_)); @@ -162,7 +165,6 @@ TEST_F(ChromeToMobileBubbleControllerTest, SendWithoutSnapshot) { TEST_F(ChromeToMobileBubbleControllerTest, SendWithSnapshot) { FilePath path("path.mht"); - EXPECT_CALL(service_, RequestMobileListUpdate()); EXPECT_CALL(service_, GenerateSnapshot(NULL, testing::_)); EXPECT_CALL(service_, SendToMobile(testing::_, path, NULL, testing::_)); EXPECT_CALL(service_, DeleteSnapshot(testing::_)); diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm index 54c85c5..e668251 100644 --- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm +++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm @@ -118,8 +118,7 @@ LocationBarViewMac::LocationBarViewMac( command_updater_->AddCommandObserver(IDC_CHROME_TO_MOBILE_PAGE, this); chrome_to_mobile_decoration_.reset( new ChromeToMobileDecoration(profile, command_updater)); - ChromeToMobileServiceFactory::GetForProfile(profile)-> - RequestMobileListUpdate(); + UpdateChromeToMobileEnabled(); } if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableActionBox)) { diff --git a/chrome/browser/ui/gtk/chrome_to_mobile_bubble_gtk.cc b/chrome/browser/ui/gtk/chrome_to_mobile_bubble_gtk.cc index 92a678b..ced3212 100644 --- a/chrome/browser/ui/gtk/chrome_to_mobile_bubble_gtk.cc +++ b/chrome/browser/ui/gtk/chrome_to_mobile_bubble_gtk.cc @@ -160,16 +160,12 @@ ChromeToMobileBubbleGtk::ChromeToMobileBubbleGtk(GtkImage* anchor_image, // Generate the MHTML snapshot now to report its size in the bubble. service_->GenerateSnapshot(browser_, weak_ptr_factory_.GetWeakPtr()); - // Request a mobile device list update. - service_->RequestMobileListUpdate(); - - const ListValue* mobiles = service_->GetMobiles(); - GtkWidget* content = gtk_vbox_new(FALSE, 5); gtk_container_set_border_width(GTK_CONTAINER(content), kContentBorder); // Create and pack the title label; init the selected mobile device. GtkWidget* title = NULL; + const ListValue* mobiles = service_->GetMobiles(); if (mobiles->GetSize() == 1) { string16 name; const DictionaryValue* mobile = NULL; @@ -324,7 +320,7 @@ void ChromeToMobileBubbleGtk::OnSendClicked(GtkWidget* widget) { const DictionaryValue* mobile = NULL; if (mobiles->GetDictionary(selected_index, &mobile)) { bool snapshot = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(send_copy_)); - service_->SendToMobile(*mobile, snapshot ? snapshot_path_ : FilePath(), + service_->SendToMobile(mobile, snapshot ? snapshot_path_ : FilePath(), browser_, weak_ptr_factory_.GetWeakPtr()); } else { NOTREACHED(); diff --git a/chrome/browser/ui/gtk/location_bar_view_gtk.cc b/chrome/browser/ui/gtk/location_bar_view_gtk.cc index 5522b9e..64add46 100644 --- a/chrome/browser/ui/gtk/location_bar_view_gtk.cc +++ b/chrome/browser/ui/gtk/location_bar_view_gtk.cc @@ -560,7 +560,7 @@ void LocationBarViewGtk::Init(bool popup_window_mode) { CreateStarButton(); gtk_box_pack_end(GTK_BOX(hbox_.get()), star_.get(), FALSE, FALSE, 0); - // Also disable Chrome To Mobile for off-the-record and non-synced profiles, + // Disable Chrome To Mobile for off-the-record and non-synced profiles, // or if the feature is disabled by a command line flag or chrome://flags. if (!profile->IsOffTheRecord() && profile->IsSyncAccessible() && ChromeToMobileService::IsChromeToMobileEnabled()) { @@ -568,8 +568,7 @@ void LocationBarViewGtk::Init(bool popup_window_mode) { gtk_box_pack_end(GTK_BOX(hbox_.get()), chrome_to_mobile_view_.get(), FALSE, FALSE, 0); command_updater_->AddCommandObserver(IDC_CHROME_TO_MOBILE_PAGE, this); - ChromeToMobileServiceFactory::GetForProfile(browser_->profile())-> - RequestMobileListUpdate(); + UpdateChromeToMobileIcon(); } } diff --git a/chrome/browser/ui/views/chrome_to_mobile_bubble_view.cc b/chrome/browser/ui/views/chrome_to_mobile_bubble_view.cc index 135c2c2..52aebb7 100644 --- a/chrome/browser/ui/views/chrome_to_mobile_bubble_view.cc +++ b/chrome/browser/ui/views/chrome_to_mobile_bubble_view.cc @@ -329,9 +329,6 @@ ChromeToMobileBubbleView::ChromeToMobileBubbleView(views::View* anchor_view, // Generate the MHTML snapshot now to report its size in the bubble. service_->GenerateSnapshot(browser_, weak_ptr_factory_.GetWeakPtr()); - - // Request a mobile device list update. - service_->RequestMobileListUpdate(); } void ChromeToMobileBubbleView::LinkClicked(views::Link* source, @@ -364,7 +361,7 @@ void ChromeToMobileBubbleView::Send() { const DictionaryValue* mobile = NULL; if (mobiles->GetDictionary(selected_index, &mobile)) { FilePath snapshot = send_copy_->checked() ? snapshot_path_ : FilePath(); - service_->SendToMobile(*mobile, snapshot, browser_, + service_->SendToMobile(mobile, snapshot, browser_, weak_ptr_factory_.GetWeakPtr()); } else { NOTREACHED(); diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index 9cc41ee..484c2e8 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc @@ -296,16 +296,14 @@ void LocationBarView::Init(views::View* popup_parent_view) { AddChildView(star_view_); star_view_->SetVisible(true); - // Also disable Chrome To Mobile for off-the-record and non-synced profiles, + // Disable Chrome To Mobile for off-the-record and non-synced profiles, // or if the feature is disabled by a command line flag or chrome://flags. if (!profile_->IsOffTheRecord() && profile_->IsSyncAccessible() && ChromeToMobileService::IsChromeToMobileEnabled()) { chrome_to_mobile_view_ = new ChromeToMobileView(this, command_updater_); AddChildView(chrome_to_mobile_view_); - ChromeToMobileService* service = - ChromeToMobileServiceFactory::GetForProfile(profile_); - service->RequestMobileListUpdate(); - chrome_to_mobile_view_->SetVisible(service->HasMobiles()); + chrome_to_mobile_view_->SetVisible( + ChromeToMobileServiceFactory::GetForProfile(profile_)->HasMobiles()); } } diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 92dc37a..ff25e2e 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -1745,9 +1745,8 @@ const char kCloudPrintSigninDialogHeight[] = "cloud_print.signin_dialog_size.height"; #if !defined(OS_ANDROID) -// The Chrome To Mobile service prefs; the device list and last update time. +// The Chrome To Mobile service mobile device list pref. const char kChromeToMobileDeviceList[] = "chrome_to_mobile.device_list"; -const char kChromeToMobileTimestamp[] = "chrome_to_mobile.timestamp"; #endif // The list of BackgroundContents that should be loaded when the browser diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index fa411c9..5d3731f 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -636,7 +636,6 @@ extern const char kCloudPrintSubmitEnabled[]; #if !defined(OS_ANDROID) extern const char kChromeToMobileDeviceList[]; -extern const char kChromeToMobileTimestamp[]; #endif extern const char kProxy[]; |