158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/api/tabs/tabs_event_router.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/tabs/tabs_constants.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/tabs/tabs_windows_api.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/tabs/windows_event_router.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_iterator.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/favicon_status.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/navigation_entry.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using base::DictionaryValue; 2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using base::ListValue; 2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using base::FundamentalValue; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationController; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace { 3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace tabs = api::tabs; 383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WillDispatchTabUpdatedEvent( 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebContents* contents, 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue* changed_properties, 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserContext* context, 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Extension* extension, 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ListValue* event_args) { 4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Overwrite the second argument with the appropriate properties dictionary, 4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // depending on extension permissions. 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* properties_value = changed_properties->DeepCopy(); 4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExtensionTabUtil::ScrubTabValueForExtension(contents, 4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) extension, 5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) properties_value); 5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) event_args->Set(1, properties_value); 5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Overwrite the third arg with our tab value as seen by this extension. 5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) event_args->Set(2, ExtensionTabUtil::CreateTabValue(contents, extension)); 5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} // namespace 5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TabsEventRouter::TabEntry::TabEntry() : complete_waiting_on_load_(false), 6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) url_() { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::DictionaryValue* TabsEventRouter::TabEntry::UpdateLoadState( 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebContents* contents) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The tab may go in & out of loading (for instance if iframes navigate). 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only want to respond to the first change from loading to !loading after 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the NAV_ENTRY_COMMITTED was fired. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!complete_waiting_on_load_ || contents->IsLoading()) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send "complete" state change. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) complete_waiting_on_load_ = false; 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* changed_properties = new base::DictionaryValue(); 7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) changed_properties->SetString(tabs_constants::kStatusKey, 7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tabs_constants::kStatusValueComplete); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return changed_properties; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::DictionaryValue* TabsEventRouter::TabEntry::DidNavigate( 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebContents* contents) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send "loading" state change. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) complete_waiting_on_load_ = true; 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* changed_properties = new base::DictionaryValue(); 8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) changed_properties->SetString(tabs_constants::kStatusKey, 8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tabs_constants::kStatusValueLoading); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contents->GetURL() != url_) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_ = contents->GetURL(); 8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) changed_properties->SetString(tabs_constants::kUrlKey, url_.spec()); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return changed_properties; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TabsEventRouter::TabsEventRouter(Profile* profile) : profile_(profile) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!profile->IsOffTheRecord()); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserList::AddObserver(this); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Init() can happen after the browser is running, so catch up with any 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // windows that already exist. 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (chrome::BrowserIterator it; !it.done(); it.Next()) { 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RegisterForBrowserNotifications(*it); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Also catch up our internal bookkeeping of tab entries. 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Browser* browser = *it; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser->tab_strip_model()) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < browser->tab_strip_model()->count(); ++i) { 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(i); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_id = ExtensionTabUtil::GetTabId(contents); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_entries_[tab_id] = TabEntry(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TabsEventRouter::~TabsEventRouter() { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserList::RemoveObserver(this); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::OnBrowserAdded(Browser* browser) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegisterForBrowserNotifications(browser); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::RegisterForBrowserNotifications(Browser* browser) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!profile_->IsSameProfile(browser->profile())) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start listening to TabStripModel events for this browser. 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabStripModel* tab_strip = browser->tab_strip_model(); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab_strip->AddObserver(this); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < tab_strip->count(); ++i) { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RegisterForTabNotifications(tab_strip->GetWebContentsAt(i)); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::RegisterForTabNotifications(WebContents* contents) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add( 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<NavigationController>(&contents->GetController())); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Observing NOTIFICATION_WEB_CONTENTS_DESTROYED is necessary because it's 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // possible for tabs to be created, detached and then destroyed without 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ever having been re-attached and closed. This happens in the case of 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a devtools WebContents that is opened in window, docked, then closed. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<WebContents>(contents)); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_FAVICON_UPDATED, 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Source<WebContents>(contents)); 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ZoomController::FromWebContents(contents)->AddObserver(this); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::UnregisterForTabNotifications(WebContents* contents) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<NavigationController>(&contents->GetController())); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<WebContents>(contents)); 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registrar_.Remove(this, chrome::NOTIFICATION_FAVICON_UPDATED, 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Source<WebContents>(contents)); 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ZoomController::FromWebContents(contents)->RemoveObserver(this); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::OnBrowserRemoved(Browser* browser) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!profile_->IsSameProfile(browser->profile())) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stop listening to TabStripModel events for this browser. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser->tab_strip_model()->RemoveObserver(this); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::OnBrowserSetLastActive(Browser* browser) { 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabsWindowsAPI* tabs_window_api = TabsWindowsAPI::Get(profile_); 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (tabs_window_api) { 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tabs_window_api->windows_event_router()->OnActiveWindowChanged( 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser ? browser->extension_window_controller() : NULL); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void WillDispatchTabCreatedEvent(WebContents* contents, 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool active, 184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::BrowserContext* context, 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension, 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ListValue* event_args) { 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* tab_value = ExtensionTabUtil::CreateTabValue( 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents, extension); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_args->Clear(); 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_args->Append(tab_value); 19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tab_value->SetBoolean(tabs_constants::kSelectedKey, active); 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::TabCreatedAt(WebContents* contents, 19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int index, 19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool active) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> args(new base::ListValue); 1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<Event> event(new Event(tabs::OnCreated::kEventName, args.Pass())); 200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) event->restrict_to_browser_context = profile; 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->user_gesture = EventRouter::USER_GESTURE_NOT_ENABLED; 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->will_dispatch_callback = 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&WillDispatchTabCreatedEvent, contents, active); 2040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EventRouter::Get(profile)->BroadcastEvent(event.Pass()); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegisterForTabNotifications(contents); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::TabInsertedAt(WebContents* contents, 210010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int index, 211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool active) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If tab is new, send created event. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_id = ExtensionTabUtil::GetTabId(contents); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetTabEntry(contents)) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_entries_[tab_id] = TabEntry(); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabCreatedAt(contents, index, active); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> args(new base::ListValue); 22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args->Append(new FundamentalValue(tab_id)); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* object_args = new base::DictionaryValue(); 22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) object_args->Set(tabs_constants::kNewWindowIdKey, 22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new FundamentalValue( 22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExtensionTabUtil::GetWindowIdOfTab(contents))); 22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) object_args->Set(tabs_constants::kNewPositionKey, 22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new FundamentalValue(index)); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(object_args); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); 2333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DispatchEvent(profile, tabs::OnAttached::kEventName, args.Pass(), 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventRouter::USER_GESTURE_UNKNOWN); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::TabDetachedAt(WebContents* contents, int index) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetTabEntry(contents)) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The tab was removed. Don't send detach event. 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> args(new base::ListValue); 2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) args->Append( 24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new FundamentalValue(ExtensionTabUtil::GetTabId(contents))); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* object_args = new base::DictionaryValue(); 24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) object_args->Set(tabs_constants::kOldWindowIdKey, 24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new FundamentalValue( 25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExtensionTabUtil::GetWindowIdOfTab(contents))); 25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) object_args->Set(tabs_constants::kOldPositionKey, 25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new FundamentalValue(index)); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(object_args); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); 25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DispatchEvent(profile, 25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tabs::OnDetached::kEventName, 25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args.Pass(), 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventRouter::USER_GESTURE_UNKNOWN); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::TabClosingAt(TabStripModel* tab_strip_model, 26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebContents* contents, 26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int index) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_id = ExtensionTabUtil::GetTabId(contents); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> args(new base::ListValue); 26858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args->Append(new FundamentalValue(tab_id)); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* object_args = new base::DictionaryValue(); 27158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) object_args->SetInteger(tabs_constants::kWindowIdKey, 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionTabUtil::GetWindowIdOfTab(contents)); 27358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) object_args->SetBoolean(tabs_constants::kWindowClosing, 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip_model->closing_all()); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(object_args); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); 27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DispatchEvent(profile, 27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tabs::OnRemoved::kEventName, 28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args.Pass(), 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventRouter::USER_GESTURE_UNKNOWN); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int removed_count = tab_entries_.erase(tab_id); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(removed_count, 0); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnregisterForTabNotifications(contents); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::ActiveTabChanged(WebContents* old_contents, 29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebContents* new_contents, 29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int index, 29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int reason) { 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> args(new base::ListValue); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int tab_id = ExtensionTabUtil::GetTabId(new_contents); 29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args->Append(new FundamentalValue(tab_id)); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* object_args = new base::DictionaryValue(); 29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) object_args->Set(tabs_constants::kWindowIdKey, 29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new FundamentalValue( 30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExtensionTabUtil::GetWindowIdOfTab(new_contents))); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(object_args); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The onActivated event replaced onActiveChanged and onSelectionChanged. The 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deprecated events take two arguments: tabId, {windowId}. 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile = 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile::FromBrowserContext(new_contents->GetBrowserContext()); 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EventRouter::UserGestureState gesture = 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reason & CHANGE_REASON_USER_GESTURE 309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ? EventRouter::USER_GESTURE_ENABLED 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : EventRouter::USER_GESTURE_NOT_ENABLED; 31158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DispatchEvent(profile, 31258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tabs::OnSelectionChanged::kEventName, 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue>(args->DeepCopy()), 31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) gesture); 31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DispatchEvent(profile, 31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tabs::OnActiveChanged::kEventName, 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue>(args->DeepCopy()), 31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) gesture); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The onActivated event takes one argument: {windowId, tabId}. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Remove(0, NULL); 32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) object_args->Set(tabs_constants::kTabIdKey, 32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new FundamentalValue(tab_id)); 3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DispatchEvent(profile, tabs::OnActivated::kEventName, args.Pass(), gesture); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::TabSelectionChanged( 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* tab_strip_model, 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ui::ListSelectionModel& old_model) { 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ListSelectionModel::SelectedIndices new_selection = 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip_model->selection_model().selected_indices(); 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> all_tabs(new base::ListValue); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < new_selection.size(); ++i) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = new_selection[i]; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* contents = tab_strip_model->GetWebContentsAt(index); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!contents) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_id = ExtensionTabUtil::GetTabId(contents); 34058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) all_tabs->Append(new FundamentalValue(tab_id)); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> args(new base::ListValue); 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> select_info(new base::DictionaryValue); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) select_info->Set( 34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tabs_constants::kWindowIdKey, 34858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new FundamentalValue( 34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExtensionTabUtil::GetWindowIdOfTabStripModel(tab_strip_model))); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) select_info->Set(tabs_constants::kTabIdsKey, all_tabs.release()); 35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args->Append(select_info.release()); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The onHighlighted event replaced onHighlightChanged. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = tab_strip_model->profile(); 35658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DispatchEvent(profile, 35758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tabs::OnHighlightChanged::kEventName, 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue>(args->DeepCopy()), 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventRouter::USER_GESTURE_UNKNOWN); 36058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DispatchEvent(profile, 36158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tabs::OnHighlighted::kEventName, 36258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args.Pass(), 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventRouter::USER_GESTURE_UNKNOWN); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::TabMoved(WebContents* contents, 36758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int from_index, 36858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int to_index) { 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> args(new base::ListValue); 3703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) args->Append( 37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new FundamentalValue(ExtensionTabUtil::GetTabId(contents))); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* object_args = new base::DictionaryValue(); 37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) object_args->Set(tabs_constants::kWindowIdKey, 37558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new FundamentalValue( 37658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExtensionTabUtil::GetWindowIdOfTab(contents))); 37758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) object_args->Set(tabs_constants::kFromIndexKey, 37858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new FundamentalValue(from_index)); 37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) object_args->Set(tabs_constants::kToIndexKey, 38058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new FundamentalValue(to_index)); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(object_args); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); 38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DispatchEvent(profile, 38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tabs::OnMoved::kEventName, 38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args.Pass(), 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventRouter::USER_GESTURE_UNKNOWN); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::TabUpdated(WebContents* contents, bool did_navigate) { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabEntry* entry = GetTabEntry(contents); 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> changed_properties; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 39458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CHECK(entry); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (did_navigate) 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) changed_properties.reset(entry->DidNavigate(contents)); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) changed_properties.reset(entry->UpdateLoadState(contents)); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (changed_properties) 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DispatchTabUpdatedEvent(contents, changed_properties.Pass()); 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 40558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::FaviconUrlUpdated(WebContents* contents) { 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::NavigationEntry* entry = 4073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) contents->GetController().GetVisibleEntry(); 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!entry || !entry->GetFavicon().valid) 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> changed_properties( 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new base::DictionaryValue); 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) changed_properties->SetString( 41358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tabs_constants::kFaviconUrlKey, 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) entry->GetFavicon().url.possibly_invalid_spec()); 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DispatchTabUpdatedEvent(contents, changed_properties.Pass()); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 41858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::DispatchEvent( 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile, 4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& event_name, 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> args, 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventRouter::UserGestureState user_gesture) { 4230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EventRouter* event_router = EventRouter::Get(profile); 4240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!profile_->IsSameProfile(profile) || !event_router) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<Event> event(new Event(event_name, args.Pass())); 428f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) event->restrict_to_browser_context = profile; 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->user_gesture = user_gesture; 4300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch event_router->BroadcastEvent(event.Pass()); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 43358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::DispatchSimpleBrowserEvent( 4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Profile* profile, const int window_id, const std::string& event_name) { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!profile_->IsSameProfile(profile)) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> args(new base::ListValue); 43958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args->Append(new FundamentalValue(window_id)); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 44158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DispatchEvent(profile, 44258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) event_name, 44358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args.Pass(), 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventRouter::USER_GESTURE_UNKNOWN); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 44758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::DispatchTabUpdatedEvent( 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebContents* contents, 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> changed_properties) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(changed_properties); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(contents); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The state of the tab (as seen from the extension point of view) has 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // changed. Send a notification to the extension. 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> args_base(new base::ListValue); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First arg: The id of the tab that changed. 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args_base->AppendInteger(ExtensionTabUtil::GetTabId(contents)); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Second arg: An object containing the changes to the tab state. Filled in 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // by WillDispatchTabUpdatedEvent as a copy of changed_properties, if the 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // extension has the tabs permission. 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Third arg: An object containing the state of the tab. Filled in by 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // WillDispatchTabUpdatedEvent. 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 46858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_ptr<Event> event( 46958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new Event(tabs::OnUpdated::kEventName, args_base.Pass())); 470f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) event->restrict_to_browser_context = profile; 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->user_gesture = EventRouter::USER_GESTURE_NOT_ENABLED; 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->will_dispatch_callback = 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&WillDispatchTabUpdatedEvent, 47458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) contents, 47558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) changed_properties.get()); 4760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EventRouter::Get(profile)->BroadcastEvent(event.Pass()); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 479010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TabsEventRouter::TabEntry* TabsEventRouter::GetTabEntry(WebContents* contents) { 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_id = ExtensionTabUtil::GetTabId(contents); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<int, TabEntry>::iterator i = tab_entries_.find(tab_id); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_entries_.end() == i) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &i->second; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 48758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::Observe(int type, 48858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const content::NotificationSource& source, 48958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const content::NotificationDetails& details) { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) { 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NavigationController* source_controller = 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<NavigationController>(source).ptr(); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabUpdated(source_controller->GetWebContents(), true); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tab was destroyed after being detached (without being re-attached). 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* contents = content::Source<WebContents>(source).ptr(); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<NavigationController>(&contents->GetController())); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<WebContents>(contents)); 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registrar_.Remove(this, chrome::NOTIFICATION_FAVICON_UPDATED, 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Source<WebContents>(contents)); 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (type == chrome::NOTIFICATION_FAVICON_UPDATED) { 50458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool icon_url_changed = *content::Details<bool>(details).ptr(); 50558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (icon_url_changed) 50658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) FaviconUrlUpdated(content::Source<WebContents>(source).ptr()); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::TabChangedAt(WebContents* contents, 51358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int index, 51458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) TabChangeType change_type) { 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabUpdated(contents, false); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::TabReplacedAt(TabStripModel* tab_strip_model, 51958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebContents* old_contents, 52058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebContents* new_contents, 52158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int index) { 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Notify listeners that the next tabs closing or being added are due to 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // WebContents being swapped. 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int new_tab_id = ExtensionTabUtil::GetTabId(new_contents); 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int old_tab_id = ExtensionTabUtil::GetTabId(old_contents); 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> args(new base::ListValue); 52758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args->Append(new FundamentalValue(new_tab_id)); 52858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args->Append(new FundamentalValue(old_tab_id)); 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DispatchEvent(Profile::FromBrowserContext(new_contents->GetBrowserContext()), 5313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) tabs::OnReplaced::kEventName, 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) args.Pass(), 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EventRouter::USER_GESTURE_UNKNOWN); 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update tab_entries_. 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int removed_count = tab_entries_.erase(old_tab_id); 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_GT(removed_count, 0); 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UnregisterForTabNotifications(old_contents); 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetTabEntry(new_contents)) { 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab_entries_[new_tab_id] = TabEntry(); 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RegisterForTabNotifications(new_contents); 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 54658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TabsEventRouter::TabPinnedStateChanged(WebContents* contents, int index) { 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* tab_strip = NULL; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_index; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ExtensionTabUtil::GetTabStripModel(contents, &tab_strip, &tab_index)) { 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> changed_properties( 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new base::DictionaryValue()); 55358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) changed_properties->SetBoolean(tabs_constants::kPinnedKey, 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip->IsTabPinned(tab_index)); 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DispatchTabUpdatedEvent(contents, changed_properties.Pass()); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 559116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TabsEventRouter::OnZoomChanged( 560116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ZoomController::ZoomChangedEventData& data) { 561116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(data.web_contents); 562116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int tab_id = ExtensionTabUtil::GetTabId(data.web_contents); 563116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (tab_id < 0) 564116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 565116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Prepare the zoom change information. 567116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch api::tabs::OnZoomChange::ZoomChangeInfo zoom_change_info; 568116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch zoom_change_info.tab_id = tab_id; 569116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch zoom_change_info.old_zoom_factor = 570116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch content::ZoomLevelToZoomFactor(data.old_zoom_level); 571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch zoom_change_info.new_zoom_factor = 572116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch content::ZoomLevelToZoomFactor(data.new_zoom_level); 573116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ZoomModeToZoomSettings(data.zoom_mode, 574116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &zoom_change_info.zoom_settings); 575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 576116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Dispatch the |onZoomChange| event. 577116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Profile* profile = Profile::FromBrowserContext( 578116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch data.web_contents->GetBrowserContext()); 579116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DispatchEvent(profile, 580116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch tabs::OnZoomChange::kEventName, 581116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch api::tabs::OnZoomChange::Create(zoom_change_info), 582116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EventRouter::USER_GESTURE_UNKNOWN); 583116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 584116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 586