// Copyright 2014 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/location_bar_controller.h" #include #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" #include "chrome/browser/extensions/extension_action_manager.h" #include "chrome/browser/extensions/extension_action_runner.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/location_bar/location_bar.h" #include "chrome/common/extensions/manifest_handlers/ui_overrides_handler.h" #include "content/public/browser/web_contents.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/feature_switch.h" #include "extensions/common/permissions/api_permission.h" #include "extensions/common/permissions/permissions_data.h" namespace extensions { LocationBarController::LocationBarController( content::WebContents* web_contents) : web_contents_(web_contents), browser_context_(web_contents->GetBrowserContext()), action_manager_(ExtensionActionManager::Get(browser_context_)), should_show_page_actions_( !FeatureSwitch::extension_action_redesign()->IsEnabled()), extension_registry_observer_(this) { extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); } LocationBarController::~LocationBarController() { } std::vector LocationBarController::GetCurrentActions() { const ExtensionSet& extensions = ExtensionRegistry::Get(browser_context_)->enabled_extensions(); std::vector current_actions; if (!should_show_page_actions_) return current_actions; ExtensionActionRunner* action_executor = ExtensionActionRunner::GetForWebContents(web_contents_); for (const scoped_refptr& extension: extensions) { // Right now, we can consolidate these actions because we only want to show // one action per extension. If clicking on an active script action ever // has a response, then we will need to split the actions. ExtensionAction* action = action_manager_->GetPageAction(*extension); if (!action && action_executor->WantsToRun(extension.get())) { ExtensionActionMap::iterator existing = active_script_actions_.find(extension->id()); if (existing != active_script_actions_.end()) { action = existing->second.get(); } else { linked_ptr active_script_action( ExtensionActionManager::Get(browser_context_)-> GetBestFitAction(*extension, ActionInfo::TYPE_PAGE).release()); active_script_action->SetIsVisible( ExtensionAction::kDefaultTabId, true); active_script_actions_[extension->id()] = active_script_action; action = active_script_action.get(); } } if (action) current_actions.push_back(action); } // Sort by id to guarantee the extension actions are returned in the same // order every time this function is called. std::sort(current_actions.begin(), current_actions.end(), [](ExtensionAction* a, ExtensionAction* b) { return a->extension_id() < b->extension_id(); }); // Move extensions with BookmarkManagerPrivate permission to the start. This // is to ensure they will always end up rightmost on the location bar. std::stable_partition( current_actions.begin(), current_actions.end(), [&extensions](ExtensionAction* extension_action) { return extensions.GetByID(extension_action->extension_id()) ->permissions_data() ->HasAPIPermission( extensions::APIPermission::kBookmarkManagerPrivate); }); return current_actions; } void LocationBarController::OnExtensionLoaded( content::BrowserContext* browser_context, const Extension* extension) { if (should_show_page_actions_ && action_manager_->GetPageAction(*extension)) { ExtensionActionAPI::Get(browser_context)-> NotifyPageActionsChanged(web_contents_); } // We might also need to update the location bar if the extension can remove // the bookmark star. if (UIOverrides::RemovesBookmarkButton(extension)) { Browser* browser = chrome::FindBrowserWithWebContents(web_contents_); // In a perfect world, this can never be NULL. Unfortunately, since a // LocationBarController is attached to most WebContents, we can't make that // guarantee. if (!browser) return; // window() can be NULL if this is called before CreateBrowserWindow() // completes, and there won't be a location bar if the window has no toolbar // (e.g., and app window). LocationBar* location_bar = browser->window() ? browser->window()->GetLocationBar() : NULL; if (!location_bar) return; location_bar->UpdateBookmarkStarVisibility(); } } void LocationBarController::OnExtensionUnloaded( content::BrowserContext* browser_context, const Extension* extension, UnloadedExtensionInfo::Reason reason) { if (should_show_page_actions_ && action_manager_->GetPageAction(*extension)) { ExtensionActionAPI::Get(browser_context)-> NotifyPageActionsChanged(web_contents_); } } } // namespace extensions