| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/extensions/browser_event_router.h" |
| |
| #include "base/json/json_writer.h" |
| #include "base/values.h" |
| #include "chrome/browser/extensions/api/extension_action/extension_page_actions_api_constants.h" |
| #include "chrome/browser/extensions/api/tabs/tabs_constants.h" |
| #include "chrome/browser/extensions/event_names.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/extensions/extension_system.h" |
| #include "chrome/browser/extensions/extension_tab_util.h" |
| #include "chrome/browser/extensions/window_controller.h" |
| #include "chrome/browser/extensions/window_event_router.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_list.h" |
| #include "chrome/browser/ui/browser_tabstrip.h" |
| #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/common/extensions/extension.h" |
| #include "chrome/common/extensions/extension_constants.h" |
| #include "content/public/browser/navigation_controller.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/notification_types.h" |
| #include "content/public/browser/web_contents.h" |
| |
| namespace events = extensions::event_names; |
| namespace tab_keys = extensions::tabs_constants; |
| namespace page_action_keys = extension_page_actions_api_constants; |
| |
| using content::NavigationController; |
| using content::WebContents; |
| |
| namespace extensions { |
| |
| BrowserEventRouter::TabEntry::TabEntry() |
| : complete_waiting_on_load_(false), |
| url_() { |
| } |
| |
| DictionaryValue* BrowserEventRouter::TabEntry::UpdateLoadState( |
| const WebContents* contents) { |
| // The tab may go in & out of loading (for instance if iframes navigate). |
| // We only want to respond to the first change from loading to !loading after |
| // the NAV_ENTRY_COMMITTED was fired. |
| if (!complete_waiting_on_load_ || contents->IsLoading()) |
| return NULL; |
| |
| // Send "complete" state change. |
| complete_waiting_on_load_ = false; |
| DictionaryValue* changed_properties = new DictionaryValue(); |
| changed_properties->SetString(tab_keys::kStatusKey, |
| tab_keys::kStatusValueComplete); |
| return changed_properties; |
| } |
| |
| DictionaryValue* BrowserEventRouter::TabEntry::DidNavigate( |
| const WebContents* contents) { |
| // Send "loading" state change. |
| complete_waiting_on_load_ = true; |
| DictionaryValue* changed_properties = new DictionaryValue(); |
| changed_properties->SetString(tab_keys::kStatusKey, |
| tab_keys::kStatusValueLoading); |
| |
| if (contents->GetURL() != url_) { |
| url_ = contents->GetURL(); |
| changed_properties->SetString(tab_keys::kUrlKey, url_.spec()); |
| } |
| |
| return changed_properties; |
| } |
| |
| void BrowserEventRouter::Init() { |
| if (initialized_) |
| return; |
| BrowserList::AddObserver(this); |
| |
| // Init() can happen after the browser is running, so catch up with any |
| // windows that already exist. |
| for (BrowserList::const_iterator iter = BrowserList::begin(); |
| iter != BrowserList::end(); ++iter) { |
| RegisterForBrowserNotifications(*iter); |
| |
| // Also catch up our internal bookkeeping of tab entries. |
| Browser* browser = *iter; |
| if (browser->tab_strip_model()) { |
| for (int i = 0; i < browser->tab_strip_model()->count(); ++i) { |
| WebContents* contents = |
| chrome::GetTabContentsAt(browser, i)->web_contents(); |
| int tab_id = ExtensionTabUtil::GetTabId(contents); |
| tab_entries_[tab_id] = TabEntry(); |
| } |
| } |
| } |
| |
| initialized_ = true; |
| } |
| |
| BrowserEventRouter::BrowserEventRouter(Profile* profile) |
| : initialized_(false), |
| profile_(profile) { |
| DCHECK(!profile->IsOffTheRecord()); |
| } |
| |
| BrowserEventRouter::~BrowserEventRouter() { |
| BrowserList::RemoveObserver(this); |
| } |
| |
| void BrowserEventRouter::OnBrowserAdded(Browser* browser) { |
| RegisterForBrowserNotifications(browser); |
| } |
| |
| void BrowserEventRouter::RegisterForBrowserNotifications(Browser* browser) { |
| if (!profile_->IsSameProfile(browser->profile())) |
| return; |
| // Start listening to TabStripModel events for this browser. |
| browser->tab_strip_model()->AddObserver(this); |
| |
| for (int i = 0; i < browser->tab_strip_model()->count(); ++i) { |
| RegisterForTabNotifications( |
| chrome::GetTabContentsAt(browser, i)->web_contents()); |
| } |
| } |
| |
| void BrowserEventRouter::RegisterForTabNotifications(WebContents* contents) { |
| registrar_.Add( |
| this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| content::Source<NavigationController>(&contents->GetController())); |
| |
| // Observing NOTIFICATION_WEB_CONTENTS_DESTROYED is necessary because it's |
| // possible for tabs to be created, detached and then destroyed without |
| // ever having been re-attached and closed. This happens in the case of |
| // a devtools WebContents that is opened in window, docked, then closed. |
| registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| content::Source<WebContents>(contents)); |
| } |
| |
| void BrowserEventRouter::UnregisterForTabNotifications(WebContents* contents) { |
| registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| content::Source<NavigationController>(&contents->GetController())); |
| registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| content::Source<WebContents>(contents)); |
| } |
| |
| void BrowserEventRouter::OnBrowserRemoved(Browser* browser) { |
| if (!profile_->IsSameProfile(browser->profile())) |
| return; |
| |
| // Stop listening to TabStripModel events for this browser. |
| browser->tab_strip_model()->RemoveObserver(this); |
| } |
| |
| void BrowserEventRouter::OnBrowserSetLastActive(Browser* browser) { |
| ExtensionService* service = |
| extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| if (service) { |
| service->window_event_router()->OnActiveWindowChanged( |
| browser ? browser->extension_window_controller() : NULL); |
| } |
| } |
| |
| void BrowserEventRouter::TabCreatedAt(WebContents* contents, |
| int index, |
| bool active) { |
| Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); |
| const EventListenerMap::ListenerList& listeners( |
| ExtensionSystem::Get(profile)->event_router()-> |
| listeners().GetEventListenersByName(events::kOnTabCreated)); |
| for (EventListenerMap::ListenerList::const_iterator it = listeners.begin(); |
| it != listeners.end(); |
| ++it) { |
| scoped_ptr<ListValue> args(new ListValue()); |
| DictionaryValue* tab_value = ExtensionTabUtil::CreateTabValue( |
| contents, |
| profile->GetExtensionService()->extensions()->GetByID( |
| (*it)->extension_id)); |
| args->Append(tab_value); |
| tab_value->SetBoolean(tab_keys::kSelectedKey, active); |
| DispatchEventToExtension(profile, (*it)->extension_id, |
| events::kOnTabCreated, args.Pass(), |
| EventRouter::USER_GESTURE_NOT_ENABLED); |
| } |
| |
| RegisterForTabNotifications(contents); |
| } |
| |
| void BrowserEventRouter::TabInsertedAt(TabContents* contents, |
| int index, |
| bool active) { |
| // If tab is new, send created event. |
| int tab_id = ExtensionTabUtil::GetTabId(contents->web_contents()); |
| if (!GetTabEntry(contents->web_contents())) { |
| tab_entries_[tab_id] = TabEntry(); |
| |
| TabCreatedAt(contents->web_contents(), index, active); |
| return; |
| } |
| |
| scoped_ptr<ListValue> args(new ListValue()); |
| args->Append(Value::CreateIntegerValue(tab_id)); |
| |
| DictionaryValue* object_args = new DictionaryValue(); |
| object_args->Set(tab_keys::kNewWindowIdKey, Value::CreateIntegerValue( |
| ExtensionTabUtil::GetWindowIdOfTab(contents->web_contents()))); |
| object_args->Set(tab_keys::kNewPositionKey, Value::CreateIntegerValue( |
| index)); |
| args->Append(object_args); |
| |
| DispatchEvent(contents->profile(), events::kOnTabAttached, args.Pass(), |
| EventRouter::USER_GESTURE_UNKNOWN); |
| } |
| |
| void BrowserEventRouter::TabDetachedAt(TabContents* contents, int index) { |
| if (!GetTabEntry(contents->web_contents())) { |
| // The tab was removed. Don't send detach event. |
| return; |
| } |
| |
| scoped_ptr<ListValue> args(new ListValue()); |
| args->Append(Value::CreateIntegerValue( |
| ExtensionTabUtil::GetTabId(contents->web_contents()))); |
| |
| DictionaryValue* object_args = new DictionaryValue(); |
| object_args->Set(tab_keys::kOldWindowIdKey, Value::CreateIntegerValue( |
| ExtensionTabUtil::GetWindowIdOfTab(contents->web_contents()))); |
| object_args->Set(tab_keys::kOldPositionKey, Value::CreateIntegerValue( |
| index)); |
| args->Append(object_args); |
| |
| DispatchEvent(contents->profile(), events::kOnTabDetached, args.Pass(), |
| EventRouter::USER_GESTURE_UNKNOWN); |
| } |
| |
| void BrowserEventRouter::TabClosingAt(TabStripModel* tab_strip_model, |
| TabContents* contents, |
| int index) { |
| int tab_id = ExtensionTabUtil::GetTabId(contents->web_contents()); |
| |
| scoped_ptr<ListValue> args(new ListValue()); |
| args->Append(Value::CreateIntegerValue(tab_id)); |
| |
| DictionaryValue* object_args = new DictionaryValue(); |
| object_args->SetBoolean(tab_keys::kWindowClosing, |
| tab_strip_model->closing_all()); |
| args->Append(object_args); |
| |
| DispatchEvent(contents->profile(), events::kOnTabRemoved, args.Pass(), |
| EventRouter::USER_GESTURE_UNKNOWN); |
| |
| int removed_count = tab_entries_.erase(tab_id); |
| DCHECK_GT(removed_count, 0); |
| |
| UnregisterForTabNotifications(contents->web_contents()); |
| } |
| |
| void BrowserEventRouter::ActiveTabChanged(TabContents* old_contents, |
| TabContents* new_contents, |
| int index, |
| bool user_gesture) { |
| scoped_ptr<ListValue> args(new ListValue()); |
| int tab_id = ExtensionTabUtil::GetTabId(new_contents->web_contents()); |
| args->Append(Value::CreateIntegerValue(tab_id)); |
| |
| DictionaryValue* object_args = new DictionaryValue(); |
| object_args->Set(tab_keys::kWindowIdKey, Value::CreateIntegerValue( |
| ExtensionTabUtil::GetWindowIdOfTab(new_contents->web_contents()))); |
| args->Append(object_args); |
| |
| // The onActivated event replaced onActiveChanged and onSelectionChanged. The |
| // deprecated events take two arguments: tabId, {windowId}. |
| Profile* profile = new_contents->profile(); |
| EventRouter::UserGestureState gesture = user_gesture ? |
| EventRouter::USER_GESTURE_ENABLED : EventRouter::USER_GESTURE_NOT_ENABLED; |
| DispatchEvent(profile, events::kOnTabSelectionChanged, |
| scoped_ptr<ListValue>(args->DeepCopy()), gesture); |
| DispatchEvent(profile, events::kOnTabActiveChanged, |
| scoped_ptr<ListValue>(args->DeepCopy()), gesture); |
| |
| // The onActivated event takes one argument: {windowId, tabId}. |
| args->Remove(0, NULL); |
| object_args->Set(tab_keys::kTabIdKey, Value::CreateIntegerValue(tab_id)); |
| DispatchEvent(profile, events::kOnTabActivated, args.Pass(), gesture); |
| } |
| |
| void BrowserEventRouter::TabSelectionChanged( |
| TabStripModel* tab_strip_model, |
| const TabStripSelectionModel& old_model) { |
| TabStripSelectionModel::SelectedIndices new_selection = |
| tab_strip_model->selection_model().selected_indices(); |
| ListValue* all = new ListValue(); |
| |
| for (size_t i = 0; i < new_selection.size(); ++i) { |
| int index = new_selection[i]; |
| TabContents* contents = tab_strip_model->GetTabContentsAt(index); |
| if (!contents) |
| break; |
| int tab_id = ExtensionTabUtil::GetTabId(contents->web_contents()); |
| all->Append(Value::CreateIntegerValue(tab_id)); |
| } |
| |
| scoped_ptr<ListValue> args(new ListValue()); |
| DictionaryValue* select_info = new DictionaryValue(); |
| |
| select_info->Set(tab_keys::kWindowIdKey, Value::CreateIntegerValue( |
| ExtensionTabUtil::GetWindowIdOfTabStripModel(tab_strip_model))); |
| |
| select_info->Set(tab_keys::kTabIdsKey, all); |
| args->Append(select_info); |
| |
| // The onHighlighted event replaced onHighlightChanged. |
| Profile* profile = tab_strip_model->profile(); |
| DispatchEvent(profile, events::kOnTabHighlightChanged, |
| scoped_ptr<ListValue>(args->DeepCopy()), |
| EventRouter::USER_GESTURE_UNKNOWN); |
| DispatchEvent(profile, events::kOnTabHighlighted, args.Pass(), |
| EventRouter::USER_GESTURE_UNKNOWN); |
| } |
| |
| void BrowserEventRouter::TabMoved(TabContents* contents, |
| int from_index, |
| int to_index) { |
| scoped_ptr<ListValue> args(new ListValue()); |
| args->Append(Value::CreateIntegerValue( |
| ExtensionTabUtil::GetTabId(contents->web_contents()))); |
| |
| DictionaryValue* object_args = new DictionaryValue(); |
| object_args->Set(tab_keys::kWindowIdKey, Value::CreateIntegerValue( |
| ExtensionTabUtil::GetWindowIdOfTab(contents->web_contents()))); |
| object_args->Set(tab_keys::kFromIndexKey, Value::CreateIntegerValue( |
| from_index)); |
| object_args->Set(tab_keys::kToIndexKey, Value::CreateIntegerValue( |
| to_index)); |
| args->Append(object_args); |
| |
| DispatchEvent(contents->profile(), events::kOnTabMoved, args.Pass(), |
| EventRouter::USER_GESTURE_UNKNOWN); |
| } |
| |
| void BrowserEventRouter::TabUpdated(WebContents* contents, bool did_navigate) { |
| TabEntry* entry = GetTabEntry(contents); |
| DictionaryValue* changed_properties = NULL; |
| |
| DCHECK(entry); |
| |
| if (did_navigate) |
| changed_properties = entry->DidNavigate(contents); |
| else |
| changed_properties = entry->UpdateLoadState(contents); |
| |
| if (changed_properties) |
| DispatchTabUpdatedEvent(contents, changed_properties); |
| } |
| |
| void BrowserEventRouter::DispatchEvent( |
| Profile* profile, |
| const char* event_name, |
| scoped_ptr<ListValue> args, |
| EventRouter::UserGestureState user_gesture) { |
| if (!profile_->IsSameProfile(profile) || !profile->GetExtensionEventRouter()) |
| return; |
| |
| profile->GetExtensionEventRouter()->DispatchEventToRenderers( |
| event_name, args.Pass(), profile, GURL(), user_gesture); |
| } |
| |
| void BrowserEventRouter::DispatchEventToExtension( |
| Profile* profile, |
| const std::string& extension_id, |
| const char* event_name, |
| scoped_ptr<ListValue> event_args, |
| EventRouter::UserGestureState user_gesture) { |
| if (!profile_->IsSameProfile(profile) || !profile->GetExtensionEventRouter()) |
| return; |
| |
| profile->GetExtensionEventRouter()->DispatchEventToExtension( |
| extension_id, event_name, event_args.Pass(), profile, GURL(), |
| user_gesture); |
| } |
| |
| void BrowserEventRouter::DispatchEventsAcrossIncognito( |
| Profile* profile, |
| const char* event_name, |
| scoped_ptr<ListValue> event_args, |
| scoped_ptr<ListValue> cross_incognito_args) { |
| if (!profile_->IsSameProfile(profile) || !profile->GetExtensionEventRouter()) |
| return; |
| |
| profile->GetExtensionEventRouter()->DispatchEventsToRenderersAcrossIncognito( |
| event_name, event_args.Pass(), profile, cross_incognito_args.Pass(), |
| GURL()); |
| } |
| |
| void BrowserEventRouter::DispatchSimpleBrowserEvent( |
| Profile* profile, const int window_id, const char* event_name) { |
| if (!profile_->IsSameProfile(profile)) |
| return; |
| |
| scoped_ptr<ListValue> args(new ListValue()); |
| args->Append(Value::CreateIntegerValue(window_id)); |
| |
| DispatchEvent(profile, event_name, args.Pass(), |
| EventRouter::USER_GESTURE_UNKNOWN); |
| } |
| |
| void BrowserEventRouter::DispatchTabUpdatedEvent( |
| WebContents* contents, DictionaryValue* changed_properties) { |
| DCHECK(changed_properties); |
| DCHECK(contents); |
| |
| // The state of the tab (as seen from the extension point of view) has |
| // changed. Send a notification to the extension. |
| scoped_ptr<ListValue> args_base(new ListValue()); |
| |
| // First arg: The id of the tab that changed. |
| args_base->AppendInteger(ExtensionTabUtil::GetTabId(contents)); |
| |
| // Second arg: An object containing the changes to the tab state. |
| args_base->Append(changed_properties); |
| |
| // Third arg: An object containing the state of the tab. |
| Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); |
| |
| const EventListenerMap::ListenerList& listeners( |
| ExtensionSystem::Get(profile)->event_router()-> |
| listeners().GetEventListenersByName(events::kOnTabUpdated)); |
| for (EventListenerMap::ListenerList::const_iterator it = listeners.begin(); |
| it != listeners.end(); |
| ++it) { |
| scoped_ptr<ListValue> args(args_base->DeepCopy()); |
| DictionaryValue* tab_value = ExtensionTabUtil::CreateTabValue( |
| contents, |
| profile->GetExtensionService()->extensions()->GetByID( |
| (*it)->extension_id)); |
| args->Append(tab_value); |
| DispatchEventToExtension(profile, (*it)->extension_id, |
| events::kOnTabUpdated, args.Pass(), |
| EventRouter::USER_GESTURE_UNKNOWN); |
| } |
| } |
| |
| BrowserEventRouter::TabEntry* BrowserEventRouter::GetTabEntry( |
| const WebContents* contents) { |
| int tab_id = ExtensionTabUtil::GetTabId(contents); |
| std::map<int, TabEntry>::iterator i = tab_entries_.find(tab_id); |
| if (tab_entries_.end() == i) |
| return NULL; |
| return &i->second; |
| } |
| |
| void BrowserEventRouter::Observe(int type, |
| const content::NotificationSource& source, |
| const content::NotificationDetails& details) { |
| if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) { |
| NavigationController* source_controller = |
| content::Source<NavigationController>(source).ptr(); |
| TabUpdated(source_controller->GetWebContents(), true); |
| } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { |
| // Tab was destroyed after being detached (without being re-attached). |
| WebContents* contents = content::Source<WebContents>(source).ptr(); |
| registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| content::Source<NavigationController>(&contents->GetController())); |
| registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| content::Source<WebContents>(contents)); |
| } else { |
| NOTREACHED(); |
| } |
| } |
| |
| void BrowserEventRouter::TabChangedAt(TabContents* contents, |
| int index, |
| TabChangeType change_type) { |
| TabUpdated(contents->web_contents(), false); |
| } |
| |
| void BrowserEventRouter::TabReplacedAt(TabStripModel* tab_strip_model, |
| TabContents* old_contents, |
| TabContents* new_contents, |
| int index) { |
| TabClosingAt(tab_strip_model, old_contents, index); |
| TabInsertedAt(new_contents, index, tab_strip_model->active_index() == index); |
| } |
| |
| void BrowserEventRouter::TabPinnedStateChanged(TabContents* contents, |
| int index) { |
| TabStripModel* tab_strip = NULL; |
| int tab_index; |
| |
| if (ExtensionTabUtil::GetTabStripModel( |
| contents->web_contents(), &tab_strip, &tab_index)) { |
| DictionaryValue* changed_properties = new DictionaryValue(); |
| changed_properties->SetBoolean(tab_keys::kPinnedKey, |
| tab_strip->IsTabPinned(tab_index)); |
| DispatchTabUpdatedEvent(contents->web_contents(), changed_properties); |
| } |
| } |
| |
| void BrowserEventRouter::TabStripEmpty() {} |
| |
| void BrowserEventRouter::DispatchOldPageActionEvent( |
| Profile* profile, |
| const std::string& extension_id, |
| const std::string& page_action_id, |
| int tab_id, |
| const std::string& url, |
| int button) { |
| scoped_ptr<ListValue> args(new ListValue()); |
| args->Append(Value::CreateStringValue(page_action_id)); |
| |
| DictionaryValue* data = new DictionaryValue(); |
| data->Set(tab_keys::kTabIdKey, Value::CreateIntegerValue(tab_id)); |
| data->Set(tab_keys::kTabUrlKey, Value::CreateStringValue(url)); |
| data->Set(page_action_keys::kButtonKey, Value::CreateIntegerValue(button)); |
| args->Append(data); |
| |
| DispatchEventToExtension(profile, extension_id, "pageActions", args.Pass(), |
| EventRouter::USER_GESTURE_ENABLED); |
| } |
| |
| void BrowserEventRouter::BrowserActionExecuted( |
| const ExtensionAction& browser_action, |
| Browser* browser) { |
| Profile* profile = browser->profile(); |
| TabContents* tab_contents = NULL; |
| int tab_id = 0; |
| if (!ExtensionTabUtil::GetDefaultTab(browser, &tab_contents, &tab_id)) |
| return; |
| ExtensionActionExecuted(profile, browser_action, tab_contents); |
| } |
| |
| void BrowserEventRouter::PageActionExecuted(Profile* profile, |
| const ExtensionAction& page_action, |
| int tab_id, |
| const std::string& url, |
| int button) { |
| DispatchOldPageActionEvent(profile, page_action.extension_id(), |
| page_action.id(), tab_id, url, button); |
| TabContents* tab_contents = NULL; |
| if (!ExtensionTabUtil::GetTabById(tab_id, profile, profile->IsOffTheRecord(), |
| NULL, NULL, &tab_contents, NULL)) { |
| return; |
| } |
| ExtensionActionExecuted(profile, page_action, tab_contents); |
| } |
| |
| void BrowserEventRouter::ScriptBadgeExecuted( |
| Profile* profile, |
| const ExtensionAction& script_badge, |
| int tab_id) { |
| TabContents* tab_contents = NULL; |
| if (!ExtensionTabUtil::GetTabById(tab_id, profile, profile->IsOffTheRecord(), |
| NULL, NULL, &tab_contents, NULL)) { |
| return; |
| } |
| ExtensionActionExecuted(profile, script_badge, tab_contents); |
| } |
| |
| void BrowserEventRouter::CommandExecuted(Profile* profile, |
| const std::string& extension_id, |
| const std::string& command) { |
| scoped_ptr<ListValue> args(new ListValue()); |
| args->Append(Value::CreateStringValue(command)); |
| |
| DispatchEventToExtension(profile, |
| extension_id, |
| "commands.onCommand", |
| args.Pass(), |
| EventRouter::USER_GESTURE_ENABLED); |
| } |
| |
| void BrowserEventRouter::ExtensionActionExecuted( |
| Profile* profile, |
| const ExtensionAction& extension_action, |
| TabContents* tab_contents) { |
| const char* event_name = NULL; |
| switch (extension_action.action_type()) { |
| case ExtensionAction::TYPE_BROWSER: |
| event_name = "browserAction.onClicked"; |
| break; |
| case ExtensionAction::TYPE_PAGE: |
| event_name = "pageAction.onClicked"; |
| break; |
| case ExtensionAction::TYPE_SCRIPT_BADGE: |
| event_name = "scriptBadge.onClicked"; |
| break; |
| } |
| |
| if (event_name) { |
| scoped_ptr<ListValue> args(new ListValue()); |
| DictionaryValue* tab_value = ExtensionTabUtil::CreateTabValue( |
| tab_contents->web_contents(), |
| ExtensionTabUtil::INCLUDE_PRIVACY_SENSITIVE_FIELDS); |
| args->Append(tab_value); |
| |
| DispatchEventToExtension(profile, |
| extension_action.extension_id(), |
| event_name, |
| args.Pass(), |
| EventRouter::USER_GESTURE_ENABLED); |
| } |
| } |
| |
| } // namespace extensions |