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#include "chrome/browser/extensions/extension_browser_event_router.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/json/json_writer.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h" 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_event_names.h" 10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/extensions/extension_event_router.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_page_actions_module_constants.h" 124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/extensions/extension_tabs_module_constants.h" 1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/tabs/tab_strip_model.h" 154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h" 1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/common/extensions/extension.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/extension_constants.h" 19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/navigation_entry.h" 20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace events = extension_event_names; 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace tab_keys = extension_tabs_module_constants; 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace page_action_keys = extension_page_actions_module_constants; 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochExtensionBrowserEventRouter::TabEntry::TabEntry() 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : complete_waiting_on_load_(false), 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_() { 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDictionaryValue* ExtensionBrowserEventRouter::TabEntry::UpdateLoadState( 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TabContents* contents) { 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tab may go in & out of loading (for instance if iframes navigate). 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We only want to respond to the first change from loading to !loading after 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the NAV_ENTRY_COMMITTED was fired. 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!complete_waiting_on_load_ || contents->is_loading()) 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Send "complete" state change. 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch complete_waiting_on_load_ = false; 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* changed_properties = new DictionaryValue(); 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch changed_properties->SetString(tab_keys::kStatusKey, 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_keys::kStatusValueComplete); 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return changed_properties; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDictionaryValue* ExtensionBrowserEventRouter::TabEntry::DidNavigate( 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TabContents* contents) { 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Send "loading" state change. 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch complete_waiting_on_load_ = true; 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* changed_properties = new DictionaryValue(); 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch changed_properties->SetString(tab_keys::kStatusKey, 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_keys::kStatusValueLoading); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (contents->GetURL() != url_) { 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_ = contents->GetURL(); 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch changed_properties->SetString(tab_keys::kUrlKey, url_.spec()); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return changed_properties; 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void DispatchEvent(Profile* profile, 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* event_name, 66731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& json_args) { 67731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (profile->GetExtensionEventRouter()) { 68731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick profile->GetExtensionEventRouter()->DispatchEventToRenderers( 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick event_name, json_args, profile, GURL()); 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 73731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstatic void DispatchEventToExtension(Profile* profile, 74731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& extension_id, 75731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const char* event_name, 76731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& json_args) { 77731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (profile->GetExtensionEventRouter()) { 78731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick profile->GetExtensionEventRouter()->DispatchEventToExtension( 79731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick extension_id, event_name, json_args, profile, GURL()); 80731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void DispatchEventWithTab(Profile* profile, 84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& extension_id, 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* event_name, 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TabContents* tab_contents) { 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args; 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(ExtensionTabUtil::CreateTabValue(tab_contents)); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string json_args; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::JSONWriter::Write(&args, false, &json_args); 91731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!extension_id.empty()) { 92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DispatchEventToExtension(profile, extension_id, event_name, json_args); 93731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 94731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DispatchEvent(profile, event_name, json_args); 95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void DispatchSimpleBrowserEvent(Profile* profile, 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int window_id, 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* event_name) { 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args; 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(Value::CreateIntegerValue(window_id)); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string json_args; 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::JSONWriter::Write(&args, false, &json_args); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DispatchEvent(profile, event_name, json_args); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ExtensionBrowserEventRouter::Init() { 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (initialized_) 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserList::AddObserver(this); 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(TOOLKIT_VIEWS) 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::FocusManager::GetWidgetFocusManager()->AddFocusChangeListener(this); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(TOOLKIT_GTK) 11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::ActiveWindowWatcherX::AddObserver(this); 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_MACOSX) 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Needed for when no suitable window can be passed to an extension as the 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // currently focused window. 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::NO_KEY_WINDOW, 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Init() can happen after the browser is running, so catch up with any 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // windows that already exist. 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BrowserList::const_iterator iter = BrowserList::begin(); 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iter != BrowserList::end(); ++iter) { 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RegisterForBrowserNotifications(*iter); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Also catch up our internal bookkeeping of tab entries. 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = *iter; 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser->tabstrip_model()) { 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < browser->tabstrip_model()->count(); ++i) { 135201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContents* contents = browser->GetTabContentsAt(i); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id = ExtensionTabUtil::GetTabId(contents); 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_entries_[tab_id] = TabEntry(); 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch initialized_ = true; 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenExtensionBrowserEventRouter::ExtensionBrowserEventRouter(Profile* profile) 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : initialized_(false), 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick focused_window_id_(extension_misc::kUnknownWindowId), 14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen profile_(profile) { 14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(!profile->IsOffTheRecord()); 15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenExtensionBrowserEventRouter::~ExtensionBrowserEventRouter() { 15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BrowserList::RemoveObserver(this); 15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(TOOLKIT_VIEWS) 15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen views::FocusManager::GetWidgetFocusManager()->RemoveFocusChangeListener(this); 15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#elif defined(TOOLKIT_GTK) 15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::ActiveWindowWatcherX::RemoveObserver(this); 15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif 15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::OnBrowserAdded(const Browser* browser) { 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RegisterForBrowserNotifications(browser); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::RegisterForBrowserNotifications( 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const Browser* browser) { 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Start listening to TabStripModel events for this browser. 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->tabstrip_model()->AddObserver(this); 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If this is a new window, it isn't ready at this point, so we register to be 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // notified when it is. If this is an existing window, this is a no-op that we 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // just do to reduce code complexity. 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::BROWSER_WINDOW_READY, 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<const Browser>(browser)); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser->tabstrip_model()) { 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < browser->tabstrip_model()->count(); ++i) 178201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch RegisterForTabNotifications(browser->GetTabContentsAt(i)); 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::RegisterForTabNotifications( 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents) { 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<NavigationController>(&contents->controller())); 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Observing TAB_CONTENTS_DESTROYED is necessary because it's 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // possible for tabs to be created, detached and then destroyed without 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ever having been re-attached and closed. This happens in the case of 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a devtools TabContents that is opened in window, docked, then closed. 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED, 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<TabContents>(contents)); 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid ExtensionBrowserEventRouter::UnregisterForTabNotifications( 1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TabContents* contents) { 1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.Remove(this, NotificationType::NAV_ENTRY_COMMITTED, 1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Source<NavigationController>(&contents->controller())); 1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED, 2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Source<TabContents>(contents)); 2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::OnBrowserWindowReady(const Browser* browser) { 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* window_dictionary = ExtensionTabUtil::CreateWindowValue( 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser, false); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(window_dictionary); 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string json_args; 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::JSONWriter::Write(&args, false, &json_args); 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DispatchEvent(browser->profile(), events::kOnWindowCreated, json_args); 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 216731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionBrowserEventRouter::OnBrowserRemoved(const Browser* browser) { 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Stop listening to TabStripModel events for this browser. 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->tabstrip_model()->RemoveObserver(this); 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Remove(this, NotificationType::BROWSER_WINDOW_READY, 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<const Browser>(browser)); 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DispatchSimpleBrowserEvent(browser->profile(), 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionTabUtil::GetWindowId(browser), 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch events::kOnWindowRemoved); 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(TOOLKIT_VIEWS) 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::NativeFocusWillChange( 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::NativeView focused_before, 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::NativeView focused_now) { 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!focused_now) 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBrowserSetLastActive(NULL); 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(TOOLKIT_GTK) 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::ActiveWindowChanged( 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkWindow* active_window) { 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!active_window) 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBrowserSetLastActive(NULL); 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::OnBrowserSetLastActive( 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const Browser* browser) { 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id = extension_misc::kUnknownWindowId; 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser) 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_id = ExtensionTabUtil::GetWindowId(browser); 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (focused_window_id_ == window_id) 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch focused_window_id_ = window_id; 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note: because we use the default profile when |browser| is NULL, it means 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that all extensions hear about the event regardless of whether the browser 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that lost focus was OTR or if the extension is OTR-enabled. 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See crbug.com/46610. 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DispatchSimpleBrowserEvent(browser ? browser->profile() : profile_, 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch focused_window_id_, 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch events::kOnWindowFocusedChanged); 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::TabCreatedAt(TabContents* contents, 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index, 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool foreground) { 265731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DispatchEventWithTab(contents->profile(), "", events::kOnTabCreated, 266731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick contents); 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RegisterForTabNotifications(contents); 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 271201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ExtensionBrowserEventRouter::TabInsertedAt(TabContentsWrapper* contents, 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index, 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool foreground) { 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If tab is new, send created event. 275201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int tab_id = ExtensionTabUtil::GetTabId(contents->tab_contents()); 276201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!GetTabEntry(contents->tab_contents())) { 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_entries_[tab_id] = TabEntry(); 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 279201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabCreatedAt(contents->tab_contents(), index, foreground); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args; 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(Value::CreateIntegerValue(tab_id)); 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* object_args = new DictionaryValue(); 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch object_args->Set(tab_keys::kNewWindowIdKey, Value::CreateIntegerValue( 288201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ExtensionTabUtil::GetWindowIdOfTab(contents->tab_contents()))); 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch object_args->Set(tab_keys::kNewPositionKey, Value::CreateIntegerValue( 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index)); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(object_args); 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string json_args; 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::JSONWriter::Write(&args, false, &json_args); 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DispatchEvent(contents->profile(), events::kOnTabAttached, json_args); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 299201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ExtensionBrowserEventRouter::TabDetachedAt(TabContentsWrapper* contents, 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 301201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!GetTabEntry(contents->tab_contents())) { 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tab was removed. Don't send detach event. 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args; 307201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch args.Append(Value::CreateIntegerValue( 308201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ExtensionTabUtil::GetTabId(contents->tab_contents()))); 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* object_args = new DictionaryValue(); 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch object_args->Set(tab_keys::kOldWindowIdKey, Value::CreateIntegerValue( 312201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ExtensionTabUtil::GetWindowIdOfTab(contents->tab_contents()))); 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch object_args->Set(tab_keys::kOldPositionKey, Value::CreateIntegerValue( 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index)); 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(object_args); 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string json_args; 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::JSONWriter::Write(&args, false, &json_args); 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DispatchEvent(contents->profile(), events::kOnTabDetached, json_args); 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 323731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionBrowserEventRouter::TabClosingAt(TabStripModel* tab_strip_model, 324201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* contents, 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 326201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int tab_id = ExtensionTabUtil::GetTabId(contents->tab_contents()); 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args; 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(Value::CreateIntegerValue(tab_id)); 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 331731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DictionaryValue* object_args = new DictionaryValue(); 332731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick object_args->SetBoolean(tab_keys::kWindowClosing, 333731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick tab_strip_model->closing_all()); 334731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick args.Append(object_args); 335731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string json_args; 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::JSONWriter::Write(&args, false, &json_args); 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DispatchEvent(contents->profile(), events::kOnTabRemoved, json_args); 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int removed_count = tab_entries_.erase(tab_id); 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_GT(removed_count, 0); 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 344201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch UnregisterForTabNotifications(contents->tab_contents()); 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 347201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ExtensionBrowserEventRouter::TabSelectedAt( 348201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* old_contents, 349201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* new_contents, 350201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int index, 351201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch bool user_gesture) { 352dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (old_contents == new_contents) 353dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 354dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args; 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(Value::CreateIntegerValue( 357201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ExtensionTabUtil::GetTabId(new_contents->tab_contents()))); 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* object_args = new DictionaryValue(); 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch object_args->Set(tab_keys::kWindowIdKey, Value::CreateIntegerValue( 361201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ExtensionTabUtil::GetWindowIdOfTab(new_contents->tab_contents()))); 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(object_args); 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string json_args; 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::JSONWriter::Write(&args, false, &json_args); 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DispatchEvent(new_contents->profile(), events::kOnTabSelectionChanged, 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch json_args); 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 371201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ExtensionBrowserEventRouter::TabMoved(TabContentsWrapper* contents, 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int from_index, 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int to_index) { 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args; 375201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch args.Append(Value::CreateIntegerValue( 376201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ExtensionTabUtil::GetTabId(contents->tab_contents()))); 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* object_args = new DictionaryValue(); 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch object_args->Set(tab_keys::kWindowIdKey, Value::CreateIntegerValue( 380201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ExtensionTabUtil::GetWindowIdOfTab(contents->tab_contents()))); 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch object_args->Set(tab_keys::kFromIndexKey, Value::CreateIntegerValue( 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch from_index)); 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch object_args->Set(tab_keys::kToIndexKey, Value::CreateIntegerValue( 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch to_index)); 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(object_args); 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string json_args; 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::JSONWriter::Write(&args, false, &json_args); 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DispatchEvent(contents->profile(), events::kOnTabMoved, json_args); 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::TabUpdated(TabContents* contents, 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool did_navigate) { 395513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch TabEntry* entry = GetTabEntry(contents); 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* changed_properties = NULL; 397513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 398513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(entry); 399513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (did_navigate) 401513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch changed_properties = entry->DidNavigate(contents); 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 403513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch changed_properties = entry->UpdateLoadState(contents); 404513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 405513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (changed_properties) 406513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DispatchTabUpdatedEvent(contents, changed_properties); 407513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 409513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ExtensionBrowserEventRouter::DispatchTabUpdatedEvent( 410513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch TabContents* contents, DictionaryValue* changed_properties) { 411513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(changed_properties); 412513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(contents); 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 414513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The state of the tab (as seen from the extension point of view) has 415513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // changed. Send a notification to the extension. 416513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ListValue args; 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 418513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // First arg: The id of the tab that changed. 419513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch args.Append(Value::CreateIntegerValue(ExtensionTabUtil::GetTabId(contents))); 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 421513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Second arg: An object containing the changes to the tab state. 422513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch args.Append(changed_properties); 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 424513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Third arg: An object containing the state of the tab. 425513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch args.Append(ExtensionTabUtil::CreateTabValue(contents)); 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 427513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string json_args; 428513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::JSONWriter::Write(&args, false, &json_args); 429513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 430513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DispatchEvent(contents->profile(), events::kOnTabUpdated, json_args); 431513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 432513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 433513209b27ff55e2841eac0e4120199c23acce758Ben MurdochExtensionBrowserEventRouter::TabEntry* ExtensionBrowserEventRouter::GetTabEntry( 434513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const TabContents* contents) { 435513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int tab_id = ExtensionTabUtil::GetTabId(contents); 436513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::map<int, TabEntry>::iterator i = tab_entries_.find(tab_id); 437513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (tab_entries_.end() == i) 438513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return NULL; 439513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return &i->second; 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::Observe(NotificationType type, 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type == NotificationType::NAV_ENTRY_COMMITTED) { 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationController* source_controller = 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<NavigationController>(source).ptr(); 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabUpdated(source_controller->tab_contents(), true); 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (type == NotificationType::TAB_CONTENTS_DESTROYED) { 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Tab was destroyed after being detached (without being re-attached). 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = Source<TabContents>(source).ptr(); 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Remove(this, NotificationType::NAV_ENTRY_COMMITTED, 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<NavigationController>(&contents->controller())); 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED, 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<TabContents>(contents)); 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (type == NotificationType::BROWSER_WINDOW_READY) { 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const Browser* browser = Source<const Browser>(source).ptr(); 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBrowserWindowReady(browser); 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX) 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (type == NotificationType::NO_KEY_WINDOW) { 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnBrowserSetLastActive(NULL); 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 468201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ExtensionBrowserEventRouter::TabChangedAt(TabContentsWrapper* contents, 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index, 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabChangeType change_type) { 471201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabUpdated(contents->tab_contents(), false); 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 474201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ExtensionBrowserEventRouter::TabReplacedAt( 47572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen TabStripModel* tab_strip_model, 476201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* old_contents, 477201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* new_contents, 478201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int index) { 47972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen TabClosingAt(tab_strip_model, old_contents, index); 480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabInsertedAt(new_contents, index, tab_strip_model->active_index() == index); 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 483201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid ExtensionBrowserEventRouter::TabPinnedStateChanged( 484201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* contents, 485201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int index) { 486513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch TabStripModel* tab_strip = NULL; 487513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int tab_index; 488513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 489201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (ExtensionTabUtil::GetTabStripModel( 490201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch contents->tab_contents(), &tab_strip, &tab_index)) { 491513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DictionaryValue* changed_properties = new DictionaryValue(); 492513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch changed_properties->SetBoolean(tab_keys::kPinnedKey, 493513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch tab_strip->IsTabPinned(tab_index)); 494201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DispatchTabUpdatedEvent(contents->tab_contents(), changed_properties); 495513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 496513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 497513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::TabStripEmpty() {} 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::DispatchOldPageActionEvent( 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile, 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& extension_id, 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& page_action_id, 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id, 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& url, 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int button) { 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue args; 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(Value::CreateStringValue(page_action_id)); 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* data = new DictionaryValue(); 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data->Set(tab_keys::kTabIdKey, Value::CreateIntegerValue(tab_id)); 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data->Set(tab_keys::kTabUrlKey, Value::CreateStringValue(url)); 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data->Set(page_action_keys::kButtonKey, Value::CreateIntegerValue(button)); 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch args.Append(data); 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string json_args; 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::JSONWriter::Write(&args, false, &json_args); 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 519731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DispatchEventToExtension(profile, extension_id, "pageActions", json_args); 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::PageActionExecuted( 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile, 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& extension_id, 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& page_action_id, 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id, 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& url, 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int button) { 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DispatchOldPageActionEvent(profile, extension_id, page_action_id, tab_id, url, 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch button); 531201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* tab_contents = NULL; 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ExtensionTabUtil::GetTabById(tab_id, profile, profile->IsOffTheRecord(), 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL, NULL, &tab_contents, NULL)) { 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 536731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DispatchEventWithTab(profile, extension_id, "pageAction.onClicked", 537201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch tab_contents->tab_contents()); 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionBrowserEventRouter::BrowserActionExecuted( 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile, const std::string& extension_id, Browser* browser) { 542201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* tab_contents = NULL; 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id = 0; 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ExtensionTabUtil::GetDefaultTab(browser, &tab_contents, &tab_id)) 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 546731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DispatchEventWithTab(profile, extension_id, "browserAction.onClicked", 547201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch tab_contents->tab_contents()); 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 549