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