Home | History | Annotate | Download | only in tabs
      1 // Copyright 2013 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_API_TABS_TABS_EVENT_ROUTER_H_
      6 #define CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_EVENT_ROUTER_H_
      7 
      8 #include <map>
      9 #include <string>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/compiler_specific.h"
     13 #include "chrome/browser/extensions/api/tabs/tabs_api.h"
     14 #include "chrome/browser/ui/browser_list_observer.h"
     15 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
     16 #include "chrome/browser/ui/zoom/zoom_observer.h"
     17 #include "content/public/browser/notification_registrar.h"
     18 #include "extensions/browser/event_router.h"
     19 
     20 namespace content {
     21 class WebContents;
     22 }
     23 
     24 namespace extensions {
     25 
     26 // The TabsEventRouter listens to tab events and routes them to listeners inside
     27 // extension process renderers.
     28 // TabsEventRouter will only route events from windows/tabs within a profile to
     29 // extension processes in the same profile.
     30 class TabsEventRouter : public TabStripModelObserver,
     31                         public chrome::BrowserListObserver,
     32                         public content::NotificationObserver,
     33                         public ZoomObserver {
     34  public:
     35   explicit TabsEventRouter(Profile* profile);
     36   virtual ~TabsEventRouter();
     37 
     38   // chrome::BrowserListObserver
     39   virtual void OnBrowserAdded(Browser* browser) OVERRIDE;
     40   virtual void OnBrowserRemoved(Browser* browser) OVERRIDE;
     41   virtual void OnBrowserSetLastActive(Browser* browser) OVERRIDE;
     42 
     43   // TabStripModelObserver
     44   virtual void TabInsertedAt(content::WebContents* contents, int index,
     45                              bool active) OVERRIDE;
     46   virtual void TabClosingAt(TabStripModel* tab_strip_model,
     47                             content::WebContents* contents,
     48                             int index) OVERRIDE;
     49   virtual void TabDetachedAt(content::WebContents* contents,
     50                              int index) OVERRIDE;
     51   virtual void ActiveTabChanged(content::WebContents* old_contents,
     52                                 content::WebContents* new_contents,
     53                                 int index,
     54                                 int reason) OVERRIDE;
     55   virtual void TabSelectionChanged(
     56       TabStripModel* tab_strip_model,
     57       const ui::ListSelectionModel& old_model) OVERRIDE;
     58   virtual void TabMoved(content::WebContents* contents,
     59                         int from_index,
     60                         int to_index) OVERRIDE;
     61   virtual void TabChangedAt(content::WebContents* contents,
     62                             int index,
     63                             TabChangeType change_type) OVERRIDE;
     64   virtual void TabReplacedAt(TabStripModel* tab_strip_model,
     65                              content::WebContents* old_contents,
     66                              content::WebContents* new_contents,
     67                              int index) OVERRIDE;
     68   virtual void TabPinnedStateChanged(content::WebContents* contents,
     69                                      int index) OVERRIDE;
     70 
     71   // content::NotificationObserver.
     72   virtual void Observe(int type,
     73                        const content::NotificationSource& source,
     74                        const content::NotificationDetails& details) OVERRIDE;
     75 
     76   // ZoomObserver.
     77   virtual void OnZoomChanged(
     78       const ZoomController::ZoomChangedEventData& data) OVERRIDE;
     79 
     80  private:
     81   // "Synthetic" event. Called from TabInsertedAt if new tab is detected.
     82   void TabCreatedAt(content::WebContents* contents, int index, bool active);
     83 
     84   // Internal processing of tab updated events. Is called by both TabChangedAt
     85   // and Observe/NAV_ENTRY_COMMITTED.
     86   void TabUpdated(content::WebContents* contents, bool did_navigate);
     87 
     88   // Triggers a tab updated event if the favicon URL changes.
     89   void FaviconUrlUpdated(content::WebContents* contents);
     90 
     91   // The DispatchEvent methods forward events to the |profile|'s event router.
     92   // The TabsEventRouter listens to events for all profiles,
     93   // so we avoid duplication by dropping events destined for other profiles.
     94   void DispatchEvent(Profile* profile,
     95                      const std::string& event_name,
     96                      scoped_ptr<base::ListValue> args,
     97                      EventRouter::UserGestureState user_gesture);
     98 
     99   void DispatchEventsAcrossIncognito(
    100       Profile* profile,
    101       const std::string& event_name,
    102       scoped_ptr<base::ListValue> event_args,
    103       scoped_ptr<base::ListValue> cross_incognito_args);
    104 
    105   void DispatchSimpleBrowserEvent(Profile* profile,
    106                                   const int window_id,
    107                                   const std::string& event_name);
    108 
    109   // Packages |changed_properties| as a tab updated event for the tab |contents|
    110   // and dispatches the event to the extension.
    111   void DispatchTabUpdatedEvent(
    112       content::WebContents* contents,
    113       scoped_ptr<base::DictionaryValue> changed_properties);
    114 
    115   // Register ourselves to receive the various notifications we are interested
    116   // in for a browser.
    117   void RegisterForBrowserNotifications(Browser* browser);
    118 
    119   // Register ourselves to receive the various notifications we are interested
    120   // in for a tab.
    121   void RegisterForTabNotifications(content::WebContents* contents);
    122 
    123   // Removes notifications added in RegisterForTabNotifications.
    124   void UnregisterForTabNotifications(content::WebContents* contents);
    125 
    126   content::NotificationRegistrar registrar_;
    127 
    128   // Maintain some information about known tabs, so we can:
    129   //
    130   //  - distinguish between tab creation and tab insertion
    131   //  - not send tab-detached after tab-removed
    132   //  - reduce the "noise" of TabChangedAt() when sending events to extensions
    133   class TabEntry {
    134    public:
    135     // Create a new tab entry whose initial state is TAB_COMPLETE.  This
    136     // constructor is required because TabEntry objects placed inside an
    137     // std::map<> by value.
    138     TabEntry();
    139 
    140     // Update the load state of the tab based on its WebContents.  Returns true
    141     // if the state changed, false otherwise.  Whether the state has changed or
    142     // not is used to determine if events needs to be sent to extensions during
    143     // processing of TabChangedAt(). This method will "hold" a state-change
    144     // to "loading", until the DidNavigate() method which should always follow
    145     // it. Returns NULL if no updates should be sent.
    146     base::DictionaryValue* UpdateLoadState(
    147         const content::WebContents* contents);
    148 
    149     // Indicates that a tab load has resulted in a navigation and the
    150     // destination url is available for inspection. Returns NULL if no updates
    151     // should be sent.
    152     base::DictionaryValue* DidNavigate(const content::WebContents* contents);
    153 
    154    private:
    155     // Whether we are waiting to fire the 'complete' status change. This will
    156     // occur the first time the WebContents stops loading after the
    157     // NAV_ENTRY_COMMITTED was fired. The tab may go back into and out of the
    158     // loading state subsequently, but we will ignore those changes.
    159     bool complete_waiting_on_load_;
    160 
    161     GURL url_;
    162   };
    163 
    164   // Gets the TabEntry for the given |contents|. Returns TabEntry* if
    165   // found, NULL if not.
    166   TabEntry* GetTabEntry(content::WebContents* contents);
    167 
    168   std::map<int, TabEntry> tab_entries_;
    169 
    170   // The main profile that owns this event router.
    171   Profile* profile_;
    172 
    173   DISALLOW_COPY_AND_ASSIGN(TabsEventRouter);
    174 };
    175 
    176 }  // namespace extensions
    177 
    178 #endif  // CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_EVENT_ROUTER_H_
    179