1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_EXTENSIONS_API_PUSH_MESSAGING_PUSH_MESSAGING_API_H__
6#define CHROME_BROWSER_EXTENSIONS_API_PUSH_MESSAGING_PUSH_MESSAGING_API_H__
7
8#include <string>
9
10#include "base/basictypes.h"
11#include "base/compiler_specific.h"
12#include "base/gtest_prod_util.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/scoped_observer.h"
15#include "chrome/browser/extensions/api/push_messaging/obfuscated_gaia_id_fetcher.h"
16#include "chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_delegate.h"
17#include "chrome/browser/extensions/chrome_extension_function.h"
18#include "chrome/browser/ui/webui/signin/login_ui_service.h"
19#include "extensions/browser/browser_context_keyed_api_factory.h"
20#include "extensions/browser/extension_registry_observer.h"
21#include "google_apis/gaia/google_service_auth_error.h"
22#include "google_apis/gaia/oauth2_token_service.h"
23
24namespace content {
25class BrowserContext;
26}
27
28namespace extensions {
29class ExtensionRegistry;
30class PushMessagingInvalidationMapper;
31
32// Observes a single InvalidationHandler and generates onMessage events.
33class PushMessagingEventRouter
34    : public PushMessagingInvalidationHandlerDelegate {
35 public:
36  explicit PushMessagingEventRouter(content::BrowserContext* context);
37  virtual ~PushMessagingEventRouter();
38
39  // For testing purposes.
40  void TriggerMessageForTest(const std::string& extension_id,
41                             int subchannel,
42                             const std::string& payload);
43
44 private:
45  // InvalidationHandlerDelegate implementation.
46  virtual void OnMessage(const std::string& extension_id,
47                         int subchannel,
48                         const std::string& payload) OVERRIDE;
49
50  content::BrowserContext* const browser_context_;
51
52  DISALLOW_COPY_AND_ASSIGN(PushMessagingEventRouter);
53};
54
55class PushMessagingGetChannelIdFunction
56    : public ChromeAsyncExtensionFunction,
57      public ObfuscatedGaiaIdFetcher::Delegate,
58      public OAuth2TokenService::Observer,
59      public OAuth2TokenService::Consumer {
60 public:
61  PushMessagingGetChannelIdFunction();
62
63 protected:
64  virtual ~PushMessagingGetChannelIdFunction();
65
66  // ExtensionFunction:
67  virtual bool RunAsync() OVERRIDE;
68  DECLARE_EXTENSION_FUNCTION("pushMessaging.getChannelId",
69                             PUSHMESSAGING_GETCHANNELID)
70
71 private:
72  void ReportResult(const std::string& gaia_id,
73                    const std::string& error_message);
74
75  void BuildAndSendResult(const std::string& gaia_id,
76                          const std::string& error_message);
77
78  // Begin the async fetch of the Gaia ID.
79  void StartGaiaIdFetch(const std::string& access_token);
80
81  // Begin the async fetch of the access token for Gaia ID fetcher.
82  void StartAccessTokenFetch();
83
84  // OAuth2TokenService::Observer implementation.
85  virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE;
86
87  // OAuth2TokenService::Consumer implementation.
88  virtual void OnGetTokenSuccess(
89      const OAuth2TokenService::Request* request,
90      const std::string& access_token,
91      const base::Time& expiration_time) OVERRIDE;
92  virtual void OnGetTokenFailure(
93      const OAuth2TokenService::Request* request,
94      const GoogleServiceAuthError& error) OVERRIDE;
95
96  // ObfuscatedGiaiaIdFetcher::Delegate implementation.
97  virtual void OnObfuscatedGaiaIdFetchSuccess(const std::string& gaia_id)
98      OVERRIDE;
99  virtual void OnObfuscatedGaiaIdFetchFailure(
100      const GoogleServiceAuthError& error) OVERRIDE;
101
102  scoped_ptr<ObfuscatedGaiaIdFetcher> fetcher_;
103  bool interactive_;
104  scoped_ptr<OAuth2TokenService::Request> fetcher_access_token_request_;
105
106  DISALLOW_COPY_AND_ASSIGN(PushMessagingGetChannelIdFunction);
107};
108
109class PushMessagingAPI : public BrowserContextKeyedAPI,
110                         public ExtensionRegistryObserver {
111 public:
112  explicit PushMessagingAPI(content::BrowserContext* context);
113  virtual ~PushMessagingAPI();
114
115  // Convenience method to get the PushMessagingAPI for a BrowserContext.
116  static PushMessagingAPI* Get(content::BrowserContext* context);
117
118  // KeyedService implementation.
119  virtual void Shutdown() OVERRIDE;
120
121  // BrowserContextKeyedAPI implementation.
122  static BrowserContextKeyedAPIFactory<PushMessagingAPI>* GetFactoryInstance();
123
124  // For testing purposes.
125  PushMessagingEventRouter* GetEventRouterForTest() const {
126    return event_router_.get();
127  }
128  PushMessagingInvalidationMapper* GetMapperForTest() const {
129    return handler_.get();
130  }
131  void SetMapperForTest(scoped_ptr<PushMessagingInvalidationMapper> mapper);
132
133 private:
134  friend class BrowserContextKeyedAPIFactory<PushMessagingAPI>;
135
136  // BrowserContextKeyedAPI implementation.
137  static const char* service_name() {
138    return "PushMessagingAPI";
139  }
140  static const bool kServiceIsNULLWhileTesting = true;
141
142  // Overridden from ExtensionRegistryObserver.
143  virtual void OnExtensionLoaded(content::BrowserContext* browser_context,
144                                 const Extension* extension) OVERRIDE;
145  virtual void OnExtensionUnloaded(
146      content::BrowserContext* browser_context,
147      const Extension* extension,
148      UnloadedExtensionInfo::Reason reason) OVERRIDE;
149  virtual void OnExtensionWillBeInstalled(
150      content::BrowserContext* browser_context,
151      const Extension* extension,
152      bool is_update,
153      bool from_ephemeral,
154      const std::string& old_name) OVERRIDE;
155
156  // Initialize |event_router_| and |handler_|.
157  bool InitEventRouterAndHandler();
158
159  // Created lazily when an app or extension with the push messaging permission
160  // is loaded.
161  scoped_ptr<PushMessagingEventRouter> event_router_;
162  scoped_ptr<PushMessagingInvalidationMapper> handler_;
163
164  ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
165      extension_registry_observer_;
166
167  content::BrowserContext* browser_context_;
168
169  DISALLOW_COPY_AND_ASSIGN(PushMessagingAPI);
170};
171
172template <>
173void BrowserContextKeyedAPIFactory<
174    PushMessagingAPI>::DeclareFactoryDependencies();
175
176}  // namespace extensions
177
178#endif  // CHROME_BROWSER_EXTENSIONS_API_PUSH_MESSAGING_PUSH_MESSAGING_API_H__
179