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/weak_ptr.h" 14 #include "base/observer_list.h" 15 #include "chrome/browser/extensions/active_tab_permission_granter.h" 16 #include "chrome/browser/extensions/extension_function_dispatcher.h" 17 #include "chrome/common/web_application_info.h" 18 #include "content/public/browser/notification_observer.h" 19 #include "content/public/browser/notification_registrar.h" 20 #include "content/public/browser/web_contents_observer.h" 21 #include "content/public/browser/web_contents_user_data.h" 22 #include "third_party/skia/include/core/SkBitmap.h" 23 24 namespace content { 25 struct LoadCommittedDetails; 26 } 27 28 namespace gfx { 29 class Image; 30 } 31 32 namespace extensions { 33 class Extension; 34 class LocationBarController; 35 class ScriptBadgeController; 36 class ScriptBubbleController; 37 class ScriptExecutor; 38 39 // Per-tab extension helper. Also handles non-extension apps. 40 class TabHelper : public content::WebContentsObserver, 41 public ExtensionFunctionDispatcher::Delegate, 42 public base::SupportsWeakPtr<TabHelper>, 43 public content::NotificationObserver, 44 public content::WebContentsUserData<TabHelper> { 45 public: 46 // Different types of action when web app info is available. 47 // OnDidGetApplicationInfo uses this to dispatch calls. 48 enum WebAppAction { 49 NONE, // No action at all. 50 CREATE_SHORTCUT, // Bring up create application shortcut dialog. 51 UPDATE_SHORTCUT // Update icon for app shortcut. 52 }; 53 54 // Observer base class for classes that need to be notified when content 55 // scripts and/or tabs.executeScript calls run on a page. 56 class ScriptExecutionObserver { 57 public: 58 // Map of extensions IDs to the executing script paths. 59 typedef std::map<std::string, std::set<std::string> > ExecutingScriptsMap; 60 61 // Automatically observes and unobserves |tab_helper| on construction 62 // and destruction. |tab_helper| must outlive |this|. 63 explicit ScriptExecutionObserver(TabHelper* tab_helper); 64 ScriptExecutionObserver(); 65 66 // Called when script(s) have executed on a page. 67 // 68 // |executing_scripts_map| contains all extensions that are executing 69 // scripts, mapped to the paths for those scripts. This may be an empty set 70 // if the script has no path associated with it (e.g. in the case of 71 // tabs.executeScript). 72 virtual void OnScriptsExecuted( 73 const content::WebContents* web_contents, 74 const ExecutingScriptsMap& executing_scripts_map, 75 int32 on_page_id, 76 const GURL& on_url) = 0; 77 78 protected: 79 virtual ~ScriptExecutionObserver(); 80 81 TabHelper* tab_helper_; 82 }; 83 84 virtual ~TabHelper(); 85 86 void AddScriptExecutionObserver(ScriptExecutionObserver* observer) { 87 script_execution_observers_.AddObserver(observer); 88 } 89 90 void RemoveScriptExecutionObserver(ScriptExecutionObserver* observer) { 91 script_execution_observers_.RemoveObserver(observer); 92 } 93 94 void CreateApplicationShortcuts(); 95 bool CanCreateApplicationShortcuts() const; 96 97 void set_pending_web_app_action(WebAppAction action) { 98 pending_web_app_action_ = action; 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 ScriptBubbleController* script_bubble_controller() { 150 return script_bubble_controller_.get(); 151 } 152 153 // Sets a non-extension app icon associated with WebContents and fires an 154 // INVALIDATE_TYPE_TITLE navigation state change to trigger repaint of title. 155 void SetAppIcon(const SkBitmap& app_icon); 156 157 private: 158 explicit TabHelper(content::WebContents* web_contents); 159 friend class content::WebContentsUserData<TabHelper>; 160 161 // content::WebContentsObserver overrides. 162 virtual void RenderViewCreated( 163 content::RenderViewHost* render_view_host) OVERRIDE; 164 virtual void DidNavigateMainFrame( 165 const content::LoadCommittedDetails& details, 166 const content::FrameNavigateParams& params) OVERRIDE; 167 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 168 virtual void DidCloneToNewWebContents( 169 content::WebContents* old_web_contents, 170 content::WebContents* new_web_contents) OVERRIDE; 171 172 // ExtensionFunctionDispatcher::Delegate overrides. 173 virtual extensions::WindowController* GetExtensionWindowController() 174 const OVERRIDE; 175 virtual content::WebContents* GetAssociatedWebContents() const OVERRIDE; 176 177 // Message handlers. 178 void OnDidGetApplicationInfo(int32 page_id, const WebApplicationInfo& info); 179 void OnInlineWebstoreInstall(int install_id, 180 int return_route_id, 181 const std::string& webstore_item_id, 182 const GURL& requestor_url); 183 void OnGetAppInstallState(const GURL& requestor_url, 184 int return_route_id, 185 int callback_id); 186 void OnRequest(const ExtensionHostMsg_Request_Params& params); 187 void OnContentScriptsExecuting( 188 const ScriptExecutionObserver::ExecutingScriptsMap& extension_ids, 189 int32 page_id, 190 const GURL& on_url); 191 void OnWatchedPageChange(const std::vector<std::string>& css_selectors); 192 193 // App extensions related methods: 194 195 // Resets app_icon_ and if |extension| is non-null uses ImageLoader to load 196 // the extension's image asynchronously. 197 void UpdateExtensionAppIcon(const Extension* extension); 198 199 const Extension* GetExtension(const std::string& extension_app_id); 200 201 void OnImageLoaded(const gfx::Image& image); 202 203 // WebstoreStandaloneInstaller::Callback. 204 virtual void OnInlineInstallComplete(int install_id, 205 int return_route_id, 206 bool success, 207 const std::string& error); 208 209 // content::NotificationObserver. 210 virtual void Observe(int type, 211 const content::NotificationSource& source, 212 const content::NotificationDetails& details) OVERRIDE; 213 214 // Requests application info for the specified page. This is an asynchronous 215 // request. The delegate is notified by way of OnDidGetApplicationInfo when 216 // the data is available. 217 void GetApplicationInfo(int32 page_id); 218 219 // Sends our tab ID to |render_view_host|. 220 void SetTabId(content::RenderViewHost* render_view_host); 221 222 // Data for app extensions --------------------------------------------------- 223 224 // Our content script observers. Declare at top so that it will outlive all 225 // other members, since they might add themselves as observers. 226 ObserverList<ScriptExecutionObserver> script_execution_observers_; 227 228 // If non-null this tab is an app tab and this is the extension the tab was 229 // created for. 230 const Extension* extension_app_; 231 232 // Icon for extension_app_ (if non-null) or a manually-set icon for 233 // non-extension apps. 234 SkBitmap extension_app_icon_; 235 236 // Process any extension messages coming from the tab. 237 ExtensionFunctionDispatcher extension_function_dispatcher_; 238 239 // Cached web app info data. 240 WebApplicationInfo web_app_info_; 241 242 // Which deferred action to perform when OnDidGetApplicationInfo is notified 243 // from a WebContents. 244 WebAppAction pending_web_app_action_; 245 246 content::NotificationRegistrar registrar_; 247 248 scoped_ptr<ScriptExecutor> script_executor_; 249 250 scoped_ptr<LocationBarController> location_bar_controller_; 251 252 scoped_ptr<ActiveTabPermissionGranter> active_tab_permission_granter_; 253 254 scoped_ptr<ScriptBubbleController> script_bubble_controller_; 255 256 Profile* profile_; 257 258 // Vend weak pointers that can be invalidated to stop in-progress loads. 259 base::WeakPtrFactory<TabHelper> image_loader_ptr_factory_; 260 261 DISALLOW_COPY_AND_ASSIGN(TabHelper); 262 }; 263 264 } // namespace extensions 265 266 #endif // CHROME_BROWSER_EXTENSIONS_TAB_HELPER_H_ 267