1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSER_EVENT_ROUTER_H_
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSER_EVENT_ROUTER_H_
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <map>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_tabs_module.h"
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/tabs/tab_strip_model_observer.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_registrar.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(TOOLKIT_VIEWS)
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/focus/focus_manager.h"
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "views/view.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(TOOLKIT_GTK)
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/x/active_window_watcher_x.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The ExtensionBrowserEventRouter listens to Browser window & tab events
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// and routes them to listeners inside extension process renderers.
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ExtensionBrowserEventRouter listens to *all* events, but will only route
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// events from windows/tabs within a profile to extension processes in the same
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// profile.
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ExtensionBrowserEventRouter : public TabStripModelObserver,
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(TOOLKIT_VIEWS)
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    public views::WidgetFocusChangeListener,
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(TOOLKIT_GTK)
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                    public ui::ActiveWindowWatcherX::Observer,
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    public BrowserList::Observer,
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    public NotificationObserver {
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  explicit ExtensionBrowserEventRouter(Profile* profile);
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ~ExtensionBrowserEventRouter();
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Must be called once. Subsequent calls have no effect.
4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void Init();
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // BrowserList::Observer
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnBrowserAdded(const Browser* browser);
46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  virtual void OnBrowserRemoved(const Browser* browser);
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnBrowserSetLastActive(const Browser* browser);
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(TOOLKIT_VIEWS)
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void NativeFocusWillChange(gfx::NativeView focused_before,
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     gfx::NativeView focused_now);
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(TOOLKIT_GTK)
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void ActiveWindowChanged(GdkWindow* active_window);
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Called from Observe() on BROWSER_WINDOW_READY (not a part of
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // BrowserList::Observer).
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OnBrowserWindowReady(const Browser* browser);
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TabStripModelObserver
61201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void TabInsertedAt(TabContentsWrapper* contents, int index,
62201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                             bool foreground);
63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  virtual void TabClosingAt(TabStripModel* tab_strip_model,
64201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                            TabContentsWrapper* contents,
65731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                            int index);
66201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void TabDetachedAt(TabContentsWrapper* contents, int index);
67201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void TabSelectedAt(TabContentsWrapper* old_contents,
68201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                             TabContentsWrapper* new_contents,
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             int index,
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             bool user_gesture);
71201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void TabMoved(TabContentsWrapper* contents, int from_index,
72201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        int to_index);
73201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void TabChangedAt(TabContentsWrapper* contents, int index,
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            TabChangeType change_type);
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                             TabContentsWrapper* old_contents,
77201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                             TabContentsWrapper* new_contents,
78731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                             int index);
79201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void TabPinnedStateChanged(TabContentsWrapper* contents, int index);
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void TabStripEmpty();
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Page Action execute event.
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void PageActionExecuted(Profile* profile,
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          const std::string& extension_id,
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          const std::string& page_action_id,
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          int tab_id,
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          const std::string& url,
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          int button);
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Browser Actions execute event.
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void BrowserActionExecuted(Profile* profile,
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             const std::string& extension_id,
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             Browser* browser);
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // NotificationObserver.
9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  virtual void Observe(NotificationType type,
9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                       const NotificationSource& source,
9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                       const NotificationDetails& details);
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // "Synthetic" event. Called from TabInsertedAt if new tab is detected.
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void TabCreatedAt(TabContents* contents, int index, bool foreground);
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Internal processing of tab updated events. Is called by both TabChangedAt
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // and Observe/NAV_ENTRY_COMMITTED.
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void TabUpdated(TabContents* contents, bool did_navigate);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Packages |changed_properties| as a tab updated event for the tab |contents|
107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // and dispatches the event to the extension.
108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  void DispatchTabUpdatedEvent(TabContents* contents,
109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                               DictionaryValue* changed_properties);
110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Called to dispatch a deprecated style page action click event that was
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // registered like:
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //   chrome.pageActions["name"].addListener(function(actionId, info){})
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void DispatchOldPageActionEvent(Profile* profile,
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& extension_id,
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& page_action_id,
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int tab_id,
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& url,
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int button);
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Register ourselves to receive the various notifications we are interested
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // in for a browser.
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void RegisterForBrowserNotifications(const Browser* browser);
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Register ourselves to receive the various notifications we are interested
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // in for a tab.
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void RegisterForTabNotifications(TabContents* contents);
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Removes notifications added in RegisterForTabNotifications.
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void UnregisterForTabNotifications(TabContents* contents);
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotificationRegistrar registrar_;
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool initialized_;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Maintain some information about known tabs, so we can:
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //  - distinguish between tab creation and tab insertion
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //  - not send tab-detached after tab-removed
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //  - reduce the "noise" of TabChangedAt() when sending events to extensions
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  class TabEntry {
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   public:
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Create a new tab entry whose initial state is TAB_COMPLETE.  This
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // constructor is required because TabEntry objects placed inside an
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // std::map<> by value.
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TabEntry();
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Update the load state of the tab based on its TabContents.  Returns true
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // if the state changed, false otherwise.  Whether the state has changed or
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // not is used to determine if events needs to be sent to extensions during
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // processing of TabChangedAt(). This method will "hold" a state-change
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // to "loading", until the DidNavigate() method which should always follow
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // it. Returns NULL if no updates should be sent.
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DictionaryValue* UpdateLoadState(const TabContents* contents);
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Indicates that a tab load has resulted in a navigation and the
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // destination url is available for inspection. Returns NULL if no updates
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // should be sent.
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DictionaryValue* DidNavigate(const TabContents* contents);
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   private:
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Whether we are waiting to fire the 'complete' status change. This will
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // occur the first time the TabContents stops loading after the
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // NAV_ENTRY_COMMITTED was fired. The tab may go back into and out of the
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // loading state subsequently, but we will ignore those changes.
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool complete_waiting_on_load_;
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GURL url_;
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
171513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Gets the TabEntry for the given |contents|. Returns TabEntry* if
172513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // found, NULL if not.
173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  TabEntry* GetTabEntry(const TabContents* contents);
174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::map<int, TabEntry> tab_entries_;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The currently focused window. We keep this so as to avoid sending multiple
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // windows.onFocusChanged events with the same windowId.
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int focused_window_id_;
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The main profile (non-OTR) profile which will be used to send events not
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // associated with any browser.
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Profile* profile_;
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ExtensionBrowserEventRouter);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSER_EVENT_ROUTER_H_
189