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)#ifndef CHROME_BROWSER_EXTENSIONS_API_PUSH_MESSAGING_PUSH_MESSAGING_API_H__
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_EXTENSIONS_API_PUSH_MESSAGING_PUSH_MESSAGING_API_H__
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/scoped_observer.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/push_messaging/obfuscated_gaia_id_fetcher.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_delegate.h"
171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/chrome_extension_function.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/signin/login_ui_service.h"
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/browser_context_keyed_api_factory.h"
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_registry_observer.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h"
22424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "google_apis/gaia/oauth2_token_service.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace content {
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class BrowserContext;
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class ExtensionRegistry;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PushMessagingInvalidationMapper;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Observes a single InvalidationHandler and generates onMessage events.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PushMessagingEventRouter
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public PushMessagingInvalidationHandlerDelegate {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  explicit PushMessagingEventRouter(content::BrowserContext* context);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~PushMessagingEventRouter();
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For testing purposes.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TriggerMessageForTest(const std::string& extension_id,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int subchannel,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const std::string& payload);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // InvalidationHandlerDelegate implementation.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnMessage(const std::string& extension_id,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int subchannel,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const std::string& payload) OVERRIDE;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  content::BrowserContext* const browser_context_;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PushMessagingEventRouter);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PushMessagingGetChannelIdFunction
561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    : public ChromeAsyncExtensionFunction,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public ObfuscatedGaiaIdFetcher::Delegate,
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      public OAuth2TokenService::Observer,
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      public OAuth2TokenService::Consumer {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PushMessagingGetChannelIdFunction();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~PushMessagingGetChannelIdFunction();
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ExtensionFunction:
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  virtual bool RunAsync() OVERRIDE;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DECLARE_EXTENSION_FUNCTION("pushMessaging.getChannelId",
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             PUSHMESSAGING_GETCHANNELID)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReportResult(const std::string& gaia_id,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& error_message);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BuildAndSendResult(const std::string& gaia_id,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const std::string& error_message);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Begin the async fetch of the Gaia ID.
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void StartGaiaIdFetch(const std::string& access_token);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Begin the async fetch of the access token for Gaia ID fetcher.
827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void StartAccessTokenFetch();
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // OAuth2TokenService::Observer implementation.
857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE;
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // OAuth2TokenService::Consumer implementation.
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void OnGetTokenSuccess(
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const OAuth2TokenService::Request* request,
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const std::string& access_token,
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const base::Time& expiration_time) OVERRIDE;
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void OnGetTokenFailure(
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const OAuth2TokenService::Request* request,
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const GoogleServiceAuthError& error) OVERRIDE;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ObfuscatedGiaiaIdFetcher::Delegate implementation.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnObfuscatedGaiaIdFetchSuccess(const std::string& gaia_id)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OVERRIDE;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnObfuscatedGaiaIdFetchFailure(
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GoogleServiceAuthError& error) OVERRIDE;
10123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ObfuscatedGaiaIdFetcher> fetcher_;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool interactive_;
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<OAuth2TokenService::Request> fetcher_access_token_request_;
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PushMessagingGetChannelIdFunction);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class PushMessagingAPI : public BrowserContextKeyedAPI,
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                         public ExtensionRegistryObserver {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  explicit PushMessagingAPI(content::BrowserContext* context);
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~PushMessagingAPI();
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Convenience method to get the PushMessagingAPI for a BrowserContext.
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static PushMessagingAPI* Get(content::BrowserContext* context);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // KeyedService implementation.
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Shutdown() OVERRIDE;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // BrowserContextKeyedAPI implementation.
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static BrowserContextKeyedAPIFactory<PushMessagingAPI>* GetFactoryInstance();
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For testing purposes.
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PushMessagingEventRouter* GetEventRouterForTest() const {
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return event_router_.get();
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PushMessagingInvalidationMapper* GetMapperForTest() const {
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return handler_.get();
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetMapperForTest(scoped_ptr<PushMessagingInvalidationMapper> mapper);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  friend class BrowserContextKeyedAPIFactory<PushMessagingAPI>;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // BrowserContextKeyedAPI implementation.
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const char* service_name() {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return "PushMessagingAPI";
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const bool kServiceIsNULLWhileTesting = true;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Overridden from ExtensionRegistryObserver.
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnExtensionLoaded(content::BrowserContext* browser_context,
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 const Extension* extension) OVERRIDE;
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnExtensionUnloaded(
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      content::BrowserContext* browser_context,
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      const Extension* extension,
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      UnloadedExtensionInfo::Reason reason) OVERRIDE;
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual void OnExtensionWillBeInstalled(
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      content::BrowserContext* browser_context,
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      const Extension* extension,
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      bool is_update,
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      bool from_ephemeral,
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      const std::string& old_name) OVERRIDE;
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Initialize |event_router_| and |handler_|.
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool InitEventRouterAndHandler();
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Created lazily when an app or extension with the push messaging permission
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // is loaded.
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<PushMessagingEventRouter> event_router_;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<PushMessagingInvalidationMapper> handler_;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      extension_registry_observer_;
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  content::BrowserContext* browser_context_;
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PushMessagingAPI);
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <>
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BrowserContextKeyedAPIFactory<
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PushMessagingAPI>::DeclareFactoryDependencies();
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace extensions
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // CHROME_BROWSER_EXTENSIONS_API_PUSH_MESSAGING_PUSH_MESSAGING_API_H__
179