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