push_messaging_api.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/token_cache/token_cache_service.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/token_cache/token_cache_service_factory.h" 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/api/push_messaging.h" 230de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "components/invalidation/invalidation_service.h" 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/invalidation/profile_invalidation_provider.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" 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h" 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_registry.h" 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "extensions/browser/extension_registry_factory.h" 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system_provider.h" 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extensions_browser_client.h" 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "extensions/common/permissions/api_permission.h" 3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.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) 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace extensions { 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kChannelIdSeparator[] = "/"; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kUserNotSignedIn[] = "The user is not signed in."; 467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kUserAccessTokenFailure[] = 477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch "Cannot obtain access token for the user."; 48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kAPINotAvailableForUser[] = 49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "The API is not available for this user."; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kObfuscatedGaiaIdTimeoutInDays = 30; 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace glue = api::push_messaging; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)PushMessagingEventRouter::PushMessagingEventRouter( 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) content::BrowserContext* context) 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : browser_context_(context) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PushMessagingEventRouter::~PushMessagingEventRouter() {} 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingEventRouter::TriggerMessageForTest( 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int subchannel, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& payload) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnMessage(extension_id, subchannel, payload); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingEventRouter::OnMessage(const std::string& extension_id, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int subchannel, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& payload) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glue::Message message; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message.subchannel_id = subchannel; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message.payload = payload; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(2) << "PushMessagingEventRouter::OnMessage" 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " payload = '" << payload 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "' subchannel = '" << subchannel 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "' extension = '" << extension_id << "'"; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::ListValue> args(glue::OnMessage::Create(message)); 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<Event> event(new Event(glue::OnMessage::kEventName, args.Pass())); 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) event->restrict_to_browser_context = browser_context_; 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EventRouter::Get(browser_context_) 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ->DispatchEventToExtension(extension_id, event.Pass()); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GetChannelId class functions 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PushMessagingGetChannelIdFunction::PushMessagingGetChannelIdFunction() 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : OAuth2TokenService::Consumer("push_messaging"), 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interactive_(false) {} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PushMessagingGetChannelIdFunction::~PushMessagingGetChannelIdFunction() {} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool PushMessagingGetChannelIdFunction::RunAsync() { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fetch the function arguments. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<glue::GetChannelId::Params> params( 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glue::GetChannelId::Params::Create(*args_)); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params.get()); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params && params->interactive) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interactive_ = *params->interactive; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Balanced in ReportResult() 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddRef(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation::ProfileInvalidationProvider* invalidation_provider = 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation::ProfileInvalidationProviderFactory::GetForProfile( 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetProfile()); 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!invalidation_provider) { 113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch error_ = kAPINotAvailableForUser; 114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ReportResult(std::string(), error_); 115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return false; 116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch IdentityProvider* identity_provider = 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation_provider->GetInvalidationService()->GetIdentityProvider(); 1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!identity_provider->GetTokenService()->RefreshTokenIsAvailable( 1210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch identity_provider->GetActiveAccountId())) { 1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (interactive_ && identity_provider->RequestLogin()) { 1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch identity_provider->AddActiveAccountRefreshTokenObserver(this); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = kUserNotSignedIn; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(std::string(), error_); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DVLOG(2) << "Logged in profile name: " << GetProfile()->GetProfileName(); 1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch StartAccessTokenFetch(); 1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return true; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PushMessagingGetChannelIdFunction::StartAccessTokenFetch() { 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation::ProfileInvalidationProvider* invalidation_provider = 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation::ProfileInvalidationProviderFactory::GetForProfile( 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetProfile()); 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK(invalidation_provider); 1430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch IdentityProvider* identity_provider = 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation_provider->GetInvalidationService()->GetIdentityProvider(); 145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<std::string> scope_vector = ObfuscatedGaiaIdFetcher::GetScopes(); 1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch OAuth2TokenService::ScopeSet scopes(scope_vector.begin(), scope_vector.end()); 14823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) fetcher_access_token_request_ = 1490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch identity_provider->GetTokenService()->StartRequest( 1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch identity_provider->GetActiveAccountId(), scopes, this); 1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PushMessagingGetChannelIdFunction::OnRefreshTokenAvailable( 1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& account_id) { 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation::ProfileInvalidationProvider* invalidation_provider = 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation::ProfileInvalidationProviderFactory::GetForProfile( 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetProfile()); 158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK(invalidation_provider); 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation_provider->GetInvalidationService()->GetIdentityProvider()-> 1600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RemoveActiveAccountRefreshTokenObserver(this); 1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DVLOG(2) << "Newly logged in: " << GetProfile()->GetProfileName(); 1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch StartAccessTokenFetch(); 1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PushMessagingGetChannelIdFunction::OnGetTokenSuccess( 1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const OAuth2TokenService::Request* request, 1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& access_token, 1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const base::Time& expiration_time) { 1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_EQ(fetcher_access_token_request_.get(), request); 1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch fetcher_access_token_request_.reset(); 1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch StartGaiaIdFetch(access_token); 1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PushMessagingGetChannelIdFunction::OnGetTokenFailure( 1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const OAuth2TokenService::Request* request, 1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const GoogleServiceAuthError& error) { 1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_EQ(fetcher_access_token_request_.get(), request); 1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch fetcher_access_token_request_.reset(); 1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // TODO(fgorski): We are currently ignoring the error passed in upon failure. 1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // It should be revisited when we are working on improving general error 1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // handling for the identity related code. 1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DVLOG(1) << "Cannot obtain access token for this user " 1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) << error.error_message() << " " << error.state(); 1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch error_ = kUserAccessTokenFailure; 1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ReportResult(std::string(), error_); 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PushMessagingGetChannelIdFunction::StartGaiaIdFetch( 1917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& access_token) { 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Start the async fetch of the Gaia Id. 193effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) net::URLRequestContextGetter* context = GetProfile()->GetRequestContext(); 1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch fetcher_.reset(new ObfuscatedGaiaIdFetcher(context, this, access_token)); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get the token cache and see if we have already cached a Gaia Id. 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TokenCacheService* token_cache = 1991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TokenCacheServiceFactory::GetForProfile(GetProfile()); 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check the cache, if we already have a Gaia ID, use it instead of 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fetching the ID over the network. 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& gaia_id = 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) token_cache->RetrieveToken(GaiaConstants::kObfuscatedGaiaId); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gaia_id.empty()) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(gaia_id, std::string()); 2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::ReportResult( 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& gaia_id, const std::string& error_string) { 215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildAndSendResult(gaia_id, error_string); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cache the obfuscated ID locally. It never changes for this user, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and if we call the web API too often, we get errors due to rate limiting. 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gaia_id.empty()) { 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta timeout = 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta::FromDays(kObfuscatedGaiaIdTimeoutInDays); 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TokenCacheService* token_cache = 2251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TokenCacheServiceFactory::GetForProfile(GetProfile()); 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) token_cache->StoreToken(GaiaConstants::kObfuscatedGaiaId, gaia_id, 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timeout); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 230010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Balanced in RunAsync. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::BuildAndSendResult( 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& gaia_id, const std::string& error_message) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string channel_id; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gaia_id.empty()) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_id = gaia_id; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_id += kChannelIdSeparator; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_id += extension_id(); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(petewil): It may be a good idea to further 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // obfuscate the channel ID to prevent the user's obfuscated Gaia Id 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from being readily obtained. Security review will tell us if we need to. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a ChannelId results object and set the fields. 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glue::ChannelIdResult result; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.channel_id = channel_id; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetError(error_message); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_ = glue::GetChannelId::Results::Create(result); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = error_message.empty() && !gaia_id.empty(); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendResponse(success); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::OnObfuscatedGaiaIdFetchSuccess( 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& gaia_id) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportResult(gaia_id, std::string()); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushMessagingGetChannelIdFunction::OnObfuscatedGaiaIdFetchFailure( 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GoogleServiceAuthError& error) { 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error_text = error.error_message(); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the error message is blank, see if we can set it from the state. 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_text.empty() && 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (0 != error.state())) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_text = base::IntToString(error.state()); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "GetChannelId status: '" << error_text << "'"; 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If we had bad credentials, try the logon again. 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (error.state()) { 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case GoogleServiceAuthError::ACCOUNT_DELETED: 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case GoogleServiceAuthError::ACCOUNT_DISABLED: { 278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation::ProfileInvalidationProvider* invalidation_provider = 279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation::ProfileInvalidationProviderFactory::GetForProfile( 280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetProfile()); 281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CHECK(invalidation_provider); 282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!interactive_ || !invalidation_provider->GetInvalidationService()-> 283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetIdentityProvider()->RequestLogin()) { 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ReportResult(std::string(), error_text); 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) default: 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Return error to caller. 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ReportResult(std::string(), error_text); 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)PushMessagingAPI::PushMessagingAPI(content::BrowserContext* context) 296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : extension_registry_observer_(this), browser_context_(context) { 297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PushMessagingAPI::~PushMessagingAPI() { 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)PushMessagingAPI* PushMessagingAPI::Get(content::BrowserContext* context) { 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return BrowserContextKeyedAPIFactory<PushMessagingAPI>::Get(context); 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PushMessagingAPI::Shutdown() { 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_router_.reset(); 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) handler_.reset(); 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance<BrowserContextKeyedAPIFactory<PushMessagingAPI> > 314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) g_factory = LAZY_INSTANCE_INITIALIZER; 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<PushMessagingAPI>* 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PushMessagingAPI::GetFactoryInstance() { 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return g_factory.Pointer(); 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool PushMessagingAPI::InitEventRouterAndHandler() { 323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation::ProfileInvalidationProvider* invalidation_provider = 324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation::ProfileInvalidationProviderFactory::GetForProfile( 325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Profile::FromBrowserContext(browser_context_)); 326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!invalidation_provider) 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!event_router_) 330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) event_router_.reset(new PushMessagingEventRouter(browser_context_)); 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!handler_) { 332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) handler_.reset(new PushMessagingInvalidationHandler( 333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) invalidation_provider->GetInvalidationService(), 334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) event_router_.get())); 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PushMessagingAPI::OnExtensionLoaded( 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::BrowserContext* browser_context, 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension) { 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!InitEventRouterAndHandler()) 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 34646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (extension->permissions_data()->HasAPIPermission( 34746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) APIPermission::kPushMessaging)) { 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) handler_->RegisterExtension(extension->id()); 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PushMessagingAPI::OnExtensionUnloaded( 353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::BrowserContext* browser_context, 354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension, 355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UnloadedExtensionInfo::Reason reason) { 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!InitEventRouterAndHandler()) 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (extension->permissions_data()->HasAPIPermission( 36046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) APIPermission::kPushMessaging)) { 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) handler_->UnregisterExtension(extension->id()); 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void PushMessagingAPI::OnExtensionWillBeInstalled( 366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) content::BrowserContext* browser_context, 367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const Extension* extension, 368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool is_update, 369f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool from_ephemeral, 370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& old_name) { 371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (InitEventRouterAndHandler() && 372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) extension->permissions_data()->HasAPIPermission( 37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) APIPermission::kPushMessaging)) { 374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) handler_->SuppressInitialInvalidationsForExtension(extension->id()); 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PushMessagingAPI::SetMapperForTest( 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<PushMessagingInvalidationMapper> mapper) { 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) handler_ = mapper.Pass(); 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <> 384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void 385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<PushMessagingAPI>::DeclareFactoryDependencies() { 386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DependsOn(ExtensionRegistryFactory::GetInstance()); 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); 388f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DependsOn(invalidation::ProfileInvalidationProviderFactory::GetInstance()); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 392