push_messaging_api.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/push_messaging/push_messaging_api.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/token_cache/token_cache_service.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/token_cache/token_cache_service_factory.h" 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/invalidation/invalidation_service_factory.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/api/push_messaging.h" 240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "components/invalidation/invalidation_service.h" 25effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/profile_oauth2_token_service.h" 26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_manager.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h" 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_registry.h" 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system_provider.h" 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extensions_browser_client.h" 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "extensions/common/permissions/api_permission.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_constants.h" 370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "google_apis/gaia/identity_provider.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kChannelIdSeparator[] = "/"; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kUserNotSignedIn[] = "The user is not signed in."; 437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kUserAccessTokenFailure[] = 447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch "Cannot obtain access token for the user."; 45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kAPINotAvailableForUser[] = 46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "The API is not available for this user."; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kObfuscatedGaiaIdTimeoutInDays = 30; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace glue = api::push_messaging; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PushMessagingEventRouter::PushMessagingEventRouter(Profile* profile) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : profile_(profile) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PushMessagingEventRouter::~PushMessagingEventRouter() {} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingEventRouter::TriggerMessageForTest( 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int subchannel, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& payload) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnMessage(extension_id, subchannel, payload); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingEventRouter::OnMessage(const std::string& extension_id, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int subchannel, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& payload) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glue::Message message; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message.subchannel_id = subchannel; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message.payload = payload; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(2) << "PushMessagingEventRouter::OnMessage" 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " payload = '" << payload 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "' subchannel = '" << subchannel 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "' extension = '" << extension_id << "'"; 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::ListValue> args(glue::OnMessage::Create(message)); 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<Event> event(new Event(glue::OnMessage::kEventName, args.Pass())); 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) event->restrict_to_browser_context = profile_; 810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EventRouter::Get(profile_)->DispatchEventToExtension( 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension_id, event.Pass()); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GetChannelId class functions 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PushMessagingGetChannelIdFunction::PushMessagingGetChannelIdFunction() 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : OAuth2TokenService::Consumer("push_messaging"), 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interactive_(false) {} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PushMessagingGetChannelIdFunction::~PushMessagingGetChannelIdFunction() {} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool PushMessagingGetChannelIdFunction::RunAsync() { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fetch the function arguments. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<glue::GetChannelId::Params> params( 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glue::GetChannelId::Params::Create(*args_)); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params.get()); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params && params->interactive) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interactive_ = *params->interactive; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Balanced in ReportResult() 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddRef(); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch invalidation::InvalidationService* invalidation_service = 107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch invalidation::InvalidationServiceFactory::GetForProfile(GetProfile()); 108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!invalidation_service) { 109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch error_ = kAPINotAvailableForUser; 110c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ReportResult(std::string(), error_); 111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return false; 112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch IdentityProvider* identity_provider = 1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch invalidation_service->GetIdentityProvider(); 1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!identity_provider->GetTokenService()->RefreshTokenIsAvailable( 1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch identity_provider->GetActiveAccountId())) { 1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (interactive_ && identity_provider->RequestLogin()) { 1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch identity_provider->AddActiveAccountRefreshTokenObserver(this); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = kUserNotSignedIn; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(std::string(), error_); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DVLOG(2) << "Logged in profile name: " << GetProfile()->GetProfileName(); 1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch StartAccessTokenFetch(); 1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return true; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PushMessagingGetChannelIdFunction::StartAccessTokenFetch() { 135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch invalidation::InvalidationService* invalidation_service = 136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch invalidation::InvalidationServiceFactory::GetForProfile(GetProfile()); 137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch CHECK(invalidation_service); 1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch IdentityProvider* identity_provider = 1390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch invalidation_service->GetIdentityProvider(); 140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::vector<std::string> scope_vector = 1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch extensions::ObfuscatedGaiaIdFetcher::GetScopes(); 1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch OAuth2TokenService::ScopeSet scopes(scope_vector.begin(), scope_vector.end()); 14423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) fetcher_access_token_request_ = 1450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch identity_provider->GetTokenService()->StartRequest( 1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch identity_provider->GetActiveAccountId(), scopes, this); 1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PushMessagingGetChannelIdFunction::OnRefreshTokenAvailable( 1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& account_id) { 151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch invalidation::InvalidationService* invalidation_service = 152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch invalidation::InvalidationServiceFactory::GetForProfile(GetProfile()); 153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch CHECK(invalidation_service); 1540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch invalidation_service->GetIdentityProvider()-> 1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RemoveActiveAccountRefreshTokenObserver(this); 1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DVLOG(2) << "Newly logged in: " << GetProfile()->GetProfileName(); 1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch StartAccessTokenFetch(); 1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PushMessagingGetChannelIdFunction::OnGetTokenSuccess( 1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const OAuth2TokenService::Request* request, 1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& access_token, 1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const base::Time& expiration_time) { 1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_EQ(fetcher_access_token_request_.get(), request); 1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch fetcher_access_token_request_.reset(); 1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch StartGaiaIdFetch(access_token); 1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PushMessagingGetChannelIdFunction::OnGetTokenFailure( 1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const OAuth2TokenService::Request* request, 1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const GoogleServiceAuthError& error) { 1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_EQ(fetcher_access_token_request_.get(), request); 1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch fetcher_access_token_request_.reset(); 1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // TODO(fgorski): We are currently ignoring the error passed in upon failure. 1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // It should be revisited when we are working on improving general error 1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // handling for the identity related code. 1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DVLOG(1) << "Cannot obtain access token for this user " 1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) << error.error_message() << " " << error.state(); 1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch error_ = kUserAccessTokenFailure; 1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ReportResult(std::string(), error_); 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PushMessagingGetChannelIdFunction::StartGaiaIdFetch( 1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& access_token) { 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Start the async fetch of the Gaia Id. 188effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) net::URLRequestContextGetter* context = GetProfile()->GetRequestContext(); 1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch fetcher_.reset(new ObfuscatedGaiaIdFetcher(context, this, access_token)); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get the token cache and see if we have already cached a Gaia Id. 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TokenCacheService* token_cache = 1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TokenCacheServiceFactory::GetForProfile(GetProfile()); 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check the cache, if we already have a Gaia ID, use it instead of 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fetching the ID over the network. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& gaia_id = 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) token_cache->RetrieveToken(GaiaConstants::kObfuscatedGaiaId); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gaia_id.empty()) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(gaia_id, std::string()); 2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::ReportResult( 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& gaia_id, const std::string& error_string) { 210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildAndSendResult(gaia_id, error_string); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cache the obfuscated ID locally. It never changes for this user, 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and if we call the web API too often, we get errors due to rate limiting. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gaia_id.empty()) { 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta timeout = 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta::FromDays(kObfuscatedGaiaIdTimeoutInDays); 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TokenCacheService* token_cache = 2201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TokenCacheServiceFactory::GetForProfile(GetProfile()); 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) token_cache->StoreToken(GaiaConstants::kObfuscatedGaiaId, gaia_id, 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timeout); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Balanced in RunAsync. 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::BuildAndSendResult( 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& gaia_id, const std::string& error_message) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string channel_id; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gaia_id.empty()) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_id = gaia_id; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_id += kChannelIdSeparator; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_id += extension_id(); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(petewil): It may be a good idea to further 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // obfuscate the channel ID to prevent the user's obfuscated Gaia Id 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from being readily obtained. Security review will tell us if we need to. 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a ChannelId results object and set the fields. 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glue::ChannelIdResult result; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.channel_id = channel_id; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetError(error_message); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_ = glue::GetChannelId::Results::Create(result); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = error_message.empty() && !gaia_id.empty(); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendResponse(success); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::OnObfuscatedGaiaIdFetchSuccess( 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& gaia_id) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(gaia_id, std::string()); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::OnObfuscatedGaiaIdFetchFailure( 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GoogleServiceAuthError& error) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error_text = error.error_message(); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the error message is blank, see if we can set it from the state. 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_text.empty() && 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (0 != error.state())) { 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_text = base::IntToString(error.state()); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "GetChannelId status: '" << error_text << "'"; 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If we had bad credentials, try the logon again. 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (error.state()) { 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case GoogleServiceAuthError::ACCOUNT_DELETED: 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case GoogleServiceAuthError::ACCOUNT_DISABLED: { 273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch invalidation::InvalidationService* invalidation_service = 274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch invalidation::InvalidationServiceFactory::GetForProfile(GetProfile()); 275c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch CHECK(invalidation_service); 276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!interactive_ || 2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch !invalidation_service->GetIdentityProvider()->RequestLogin()) { 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ReportResult(std::string(), error_text); 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) default: 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Return error to caller. 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ReportResult(std::string(), error_text); 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)PushMessagingAPI::PushMessagingAPI(content::BrowserContext* context) 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : extension_registry_observer_(this), 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) profile_(Profile::FromBrowserContext(context)) { 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); 2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registrar_.Add(this, 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED, 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Source<Profile>(profile_->GetOriginalProfile())); 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PushMessagingAPI::~PushMessagingAPI() { 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)PushMessagingAPI* PushMessagingAPI::Get(content::BrowserContext* context) { 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return BrowserContextKeyedAPIFactory<PushMessagingAPI>::Get(context); 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PushMessagingAPI::Shutdown() { 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_router_.reset(); 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) handler_.reset(); 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance<BrowserContextKeyedAPIFactory<PushMessagingAPI> > 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) g_factory = LAZY_INSTANCE_INITIALIZER; 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<PushMessagingAPI>* 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PushMessagingAPI::GetFactoryInstance() { 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return g_factory.Pointer(); 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool PushMessagingAPI::InitEventRouterAndHandler() { 321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch invalidation::InvalidationService* invalidation_service = 322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch invalidation::InvalidationServiceFactory::GetForProfile(profile_); 323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!invalidation_service) 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!event_router_) 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_router_.reset(new PushMessagingEventRouter(profile_)); 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!handler_) { 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) handler_.reset(new PushMessagingInvalidationHandler(invalidation_service, 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) event_router_.get())); 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PushMessagingAPI::OnExtensionLoaded( 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::BrowserContext* browser_context, 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension) { 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!InitEventRouterAndHandler()) 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (extension->HasAPIPermission(APIPermission::kPushMessaging)) { 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) handler_->RegisterExtension(extension->id()); 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PushMessagingAPI::OnExtensionUnloaded( 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::BrowserContext* browser_context, 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension, 350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UnloadedExtensionInfo::Reason reason) { 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!InitEventRouterAndHandler()) 352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (extension->HasAPIPermission(APIPermission::kPushMessaging)) { 355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) handler_->UnregisterExtension(extension->id()); 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PushMessagingAPI::Observe(int type, 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const content::NotificationSource& source, 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const content::NotificationDetails& details) { 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_EQ(type, chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED); 363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!InitEventRouterAndHandler()) 364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension = 367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::Details<const InstalledExtensionInfo>(details)->extension; 368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (extension->HasAPIPermission(APIPermission::kPushMessaging)) { 369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) handler_->SuppressInitialInvalidationsForExtension(extension->id()); 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PushMessagingAPI::SetMapperForTest( 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<PushMessagingInvalidationMapper> mapper) { 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) handler_ = mapper.Pass(); 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <> 379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void 380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<PushMessagingAPI>::DeclareFactoryDependencies() { 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); 382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DependsOn(invalidation::InvalidationServiceFactory::GetInstance()); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 386