Home | History | Annotate | Download | only in extensions
      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