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