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