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_TAB_HELPER_H_
6#define CHROME_BROWSER_EXTENSIONS_TAB_HELPER_H_
7
8#include <set>
9#include <string>
10#include <vector>
11
12#include "base/memory/ref_counted.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/memory/weak_ptr.h"
15#include "base/observer_list.h"
16#include "chrome/browser/extensions/active_tab_permission_granter.h"
17#include "chrome/common/extensions/webstore_install_result.h"
18#include "chrome/common/web_application_info.h"
19#include "content/public/browser/notification_observer.h"
20#include "content/public/browser/notification_registrar.h"
21#include "content/public/browser/web_contents_observer.h"
22#include "content/public/browser/web_contents_user_data.h"
23#include "extensions/browser/extension_function_dispatcher.h"
24#include "extensions/browser/script_execution_observer.h"
25#include "extensions/browser/script_executor.h"
26#include "extensions/common/stack_frame.h"
27#include "third_party/skia/include/core/SkBitmap.h"
28
29class FaviconDownloader;
30
31namespace content {
32struct LoadCommittedDetails;
33class RenderFrameHost;
34}
35
36namespace gfx {
37class Image;
38}
39
40namespace extensions {
41class ActiveScriptController;
42class BookmarkAppHelper;
43class Extension;
44class LocationBarController;
45class WebstoreInlineInstallerFactory;
46
47// Per-tab extension helper. Also handles non-extension apps.
48class TabHelper : public content::WebContentsObserver,
49                  public extensions::ExtensionFunctionDispatcher::Delegate,
50                  public base::SupportsWeakPtr<TabHelper>,
51                  public content::NotificationObserver,
52                  public content::WebContentsUserData<TabHelper> {
53 public:
54  virtual ~TabHelper();
55
56  void CreateApplicationShortcuts();
57  void CreateHostedAppFromWebContents();
58  bool CanCreateApplicationShortcuts() const;
59  bool CanCreateBookmarkApp() const;
60
61  void UpdateShortcutOnLoadComplete() {
62    update_shortcut_on_load_complete_ = true;
63  }
64
65  // ScriptExecutionObserver::Delegate
66  virtual void AddScriptExecutionObserver(ScriptExecutionObserver* observer);
67  virtual void RemoveScriptExecutionObserver(ScriptExecutionObserver* observer);
68
69  // App extensions ------------------------------------------------------------
70
71  // Sets the extension denoting this as an app. If |extension| is non-null this
72  // tab becomes an app-tab. WebContents does not listen for unload events for
73  // the extension. It's up to consumers of WebContents to do that.
74  //
75  // NOTE: this should only be manipulated before the tab is added to a browser.
76  // TODO(sky): resolve if this is the right way to identify an app tab. If it
77  // is, than this should be passed in the constructor.
78  void SetExtensionApp(const Extension* extension);
79
80  // Convenience for setting the app extension by id. This does nothing if
81  // |extension_app_id| is empty, or an extension can't be found given the
82  // specified id.
83  void SetExtensionAppById(const std::string& extension_app_id);
84
85  // Set just the app icon, used by panels created by an extension.
86  void SetExtensionAppIconById(const std::string& extension_app_id);
87
88  const Extension* extension_app() const { return extension_app_; }
89  bool is_app() const { return extension_app_ != NULL; }
90  const WebApplicationInfo& web_app_info() const {
91    return web_app_info_;
92  }
93
94  // If an app extension has been explicitly set for this WebContents its icon
95  // is returned.
96  //
97  // NOTE: the returned icon is larger than 16x16 (its size is
98  // extension_misc::EXTENSION_ICON_SMALLISH).
99  SkBitmap* GetExtensionAppIcon();
100
101  ScriptExecutor* script_executor() {
102    return script_executor_.get();
103  }
104
105  LocationBarController* location_bar_controller() {
106    return location_bar_controller_.get();
107  }
108
109  ActiveScriptController* active_script_controller() {
110    return active_script_controller_.get();
111  }
112
113  ActiveTabPermissionGranter* active_tab_permission_granter() {
114    return active_tab_permission_granter_.get();
115  }
116
117  // Sets a non-extension app icon associated with WebContents and fires an
118  // INVALIDATE_TYPE_TITLE navigation state change to trigger repaint of title.
119  void SetAppIcon(const SkBitmap& app_icon);
120
121  // Sets the factory used to create inline webstore item installers.
122  // Used for testing. Takes ownership of the factory instance.
123  void SetWebstoreInlineInstallerFactoryForTests(
124      WebstoreInlineInstallerFactory* factory);
125
126 private:
127  // Different types of action when web app info is available.
128  // OnDidGetApplicationInfo uses this to dispatch calls.
129  enum WebAppAction {
130    NONE,               // No action at all.
131    CREATE_SHORTCUT,    // Bring up create application shortcut dialog.
132    CREATE_HOSTED_APP,  // Create and install a hosted app.
133    UPDATE_SHORTCUT     // Update icon for app shortcut.
134  };
135
136  explicit TabHelper(content::WebContents* web_contents);
137  friend class content::WebContentsUserData<TabHelper>;
138
139  // Displays UI for completion of creating a bookmark hosted app.
140  void FinishCreateBookmarkApp(const extensions::Extension* extension,
141                               const WebApplicationInfo& web_app_info);
142
143  // content::WebContentsObserver overrides.
144  virtual void RenderViewCreated(
145      content::RenderViewHost* render_view_host) OVERRIDE;
146  virtual void DidNavigateMainFrame(
147      const content::LoadCommittedDetails& details,
148      const content::FrameNavigateParams& params) OVERRIDE;
149  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
150  virtual bool OnMessageReceived(
151      const IPC::Message& message,
152      content::RenderFrameHost* render_frame_host) OVERRIDE;
153  virtual void DidCloneToNewWebContents(
154      content::WebContents* old_web_contents,
155      content::WebContents* new_web_contents) OVERRIDE;
156
157  // extensions::ExtensionFunctionDispatcher::Delegate overrides.
158  virtual extensions::WindowController* GetExtensionWindowController()
159      const OVERRIDE;
160  virtual content::WebContents* GetAssociatedWebContents() const OVERRIDE;
161
162  // Message handlers.
163  void OnDidGetWebApplicationInfo(const WebApplicationInfo& info);
164  void OnInlineWebstoreInstall(int install_id,
165                               int return_route_id,
166                               const std::string& webstore_item_id,
167                               const GURL& requestor_url,
168                               int listeners_mask);
169  void OnGetAppInstallState(const GURL& requestor_url,
170                            int return_route_id,
171                            int callback_id);
172  void OnRequest(const ExtensionHostMsg_Request_Params& params);
173  void OnContentScriptsExecuting(
174      const ScriptExecutionObserver::ExecutingScriptsMap& extension_ids,
175      const GURL& on_url);
176  void OnWatchedPageChange(const std::vector<std::string>& css_selectors);
177  void OnDetailedConsoleMessageAdded(const base::string16& message,
178                                     const base::string16& source,
179                                     const StackTrace& stack_trace,
180                                     int32 severity_level);
181
182  // App extensions related methods:
183
184  // Resets app_icon_ and if |extension| is non-null uses ImageLoader to load
185  // the extension's image asynchronously.
186  void UpdateExtensionAppIcon(const Extension* extension);
187
188  const Extension* GetExtension(const std::string& extension_app_id);
189
190  void OnImageLoaded(const gfx::Image& image);
191
192  // WebstoreStandaloneInstaller::Callback.
193  virtual void OnInlineInstallComplete(int install_id,
194                                       int return_route_id,
195                                       bool success,
196                                       const std::string& error,
197                                       webstore_install::Result result);
198
199  // content::NotificationObserver.
200  virtual void Observe(int type,
201                       const content::NotificationSource& source,
202                       const content::NotificationDetails& details) OVERRIDE;
203
204  // Requests application info for the specified page. This is an asynchronous
205  // request. The delegate is notified by way of OnDidGetApplicationInfo when
206  // the data is available.
207  void GetApplicationInfo(WebAppAction action);
208
209  // Sends our tab ID to |render_view_host|.
210  void SetTabId(content::RenderViewHost* render_view_host);
211
212  // Data for app extensions ---------------------------------------------------
213
214  // Our content script observers. Declare at top so that it will outlive all
215  // other members, since they might add themselves as observers.
216  ObserverList<ScriptExecutionObserver> script_execution_observers_;
217
218  // If non-null this tab is an app tab and this is the extension the tab was
219  // created for.
220  const Extension* extension_app_;
221
222  // Icon for extension_app_ (if non-null) or a manually-set icon for
223  // non-extension apps.
224  SkBitmap extension_app_icon_;
225
226  // Process any extension messages coming from the tab.
227  extensions::ExtensionFunctionDispatcher extension_function_dispatcher_;
228
229  // Cached web app info data.
230  WebApplicationInfo web_app_info_;
231
232  // Which deferred action to perform when OnDidGetApplicationInfo is notified
233  // from a WebContents.
234  WebAppAction pending_web_app_action_;
235
236  // Which page id was active when the GetApplicationInfo request was sent, for
237  // verification when the reply returns.
238  int32 last_committed_page_id_;
239
240  // Whether to trigger an update when the page load completes.
241  bool update_shortcut_on_load_complete_;
242
243  content::NotificationRegistrar registrar_;
244
245  scoped_ptr<ScriptExecutor> script_executor_;
246
247  scoped_ptr<LocationBarController> location_bar_controller_;
248
249  scoped_ptr<ActiveScriptController> active_script_controller_;
250
251  scoped_ptr<ActiveTabPermissionGranter> active_tab_permission_granter_;
252
253  scoped_ptr<BookmarkAppHelper> bookmark_app_helper_;
254
255  Profile* profile_;
256
257  // Creates WebstoreInlineInstaller instances for inline install triggers.
258  scoped_ptr<WebstoreInlineInstallerFactory> webstore_inline_installer_factory_;
259
260  // Vend weak pointers that can be invalidated to stop in-progress loads.
261  base::WeakPtrFactory<TabHelper> image_loader_ptr_factory_;
262
263  DISALLOW_COPY_AND_ASSIGN(TabHelper);
264};
265
266}  // namespace extensions
267
268#endif  // CHROME_BROWSER_EXTENSIONS_TAB_HELPER_H_
269