diff options
author | rdevlin.cronin@chromium.org <rdevlin.cronin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-18 19:24:47 +0000 |
---|---|---|
committer | rdevlin.cronin@chromium.org <rdevlin.cronin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-18 19:26:03 +0000 |
commit | 8a188eee9d8bccc5345fe52254437412b94a3ea9 (patch) | |
tree | a812681b3bbe9c86eaf2ee7f36d7bb91dfa3d0f0 | |
parent | ee7a5fd630f228f0b4e818d8184c354f20edbb75 (diff) | |
download | chromium_src-8a188eee9d8bccc5345fe52254437412b94a3ea9.zip chromium_src-8a188eee9d8bccc5345fe52254437412b94a3ea9.tar.gz chromium_src-8a188eee9d8bccc5345fe52254437412b94a3ea9.tar.bz2 |
Have ExtensionToolbarModel include page action extensions
BUG=397259
Review URL: https://codereview.chromium.org/464623002
Cr-Commit-Position: refs/heads/master@{#290325}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@290325 0039d316-1c4b-4281-b951-d872f2087c98
14 files changed, 305 insertions, 104 deletions
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc index 61e647c..ba86982 100644 --- a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc +++ b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc @@ -552,7 +552,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoDragging) { // ABC -> CAB ExtensionToolbarModel* toolbar_model = ExtensionToolbarModel::Get( browser()->profile()); - toolbar_model->MoveBrowserAction(extension_c, 0); + toolbar_model->MoveExtensionIcon(extension_c, 0); EXPECT_EQ(kTooltipC, GetBrowserActionsBar().GetTooltip(0)); EXPECT_EQ(kTooltipA, GetBrowserActionsBar().GetTooltip(1)); @@ -562,7 +562,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoDragging) { EXPECT_EQ(kTooltipA, incognito_bar.GetTooltip(1)); // CAB -> CBA - toolbar_model->MoveBrowserAction(extension_b, 1); + toolbar_model->MoveExtensionIcon(extension_b, 1); EXPECT_EQ(kTooltipC, GetBrowserActionsBar().GetTooltip(0)); EXPECT_EQ(kTooltipB, GetBrowserActionsBar().GetTooltip(1)); diff --git a/chrome/browser/extensions/extension_toolbar_model.cc b/chrome/browser/extensions/extension_toolbar_model.cc index 7dea3ac..a87656b 100644 --- a/chrome/browser/extensions/extension_toolbar_model.cc +++ b/chrome/browser/extensions/extension_toolbar_model.cc @@ -34,17 +34,14 @@ namespace extensions { -bool ExtensionToolbarModel::Observer::BrowserActionShowPopup( - const Extension* extension) { - return false; -} - ExtensionToolbarModel::ExtensionToolbarModel(Profile* profile, ExtensionPrefs* extension_prefs) : profile_(profile), extension_prefs_(extension_prefs), prefs_(profile_->GetPrefs()), extensions_initialized_(false), + include_all_extensions_( + FeatureSwitch::extension_action_redesign()->IsEnabled()), is_highlighting_(false), extension_registry_observer_(this), weak_ptr_factory_(this) { @@ -76,7 +73,7 @@ void ExtensionToolbarModel::RemoveObserver(Observer* observer) { observers_.RemoveObserver(observer); } -void ExtensionToolbarModel::MoveBrowserAction(const Extension* extension, +void ExtensionToolbarModel::MoveExtensionIcon(const Extension* extension, int index) { ExtensionList::iterator pos = std::find(toolbar_items_.begin(), toolbar_items_.end(), extension); @@ -116,7 +113,8 @@ void ExtensionToolbarModel::MoveBrowserAction(const Extension* extension, last_known_positions_.push_back(extension->id()); } - FOR_EACH_OBSERVER(Observer, observers_, BrowserActionMoved(extension, index)); + FOR_EACH_OBSERVER( + Observer, observers_, ToolbarExtensionMoved(extension, index)); UpdatePrefs(); } @@ -175,10 +173,8 @@ void ExtensionToolbarModel::OnExtensionLoaded( if (toolbar_items_[i].get() == extension) return; } - if (ExtensionActionAPI::GetBrowserActionVisibility(extension_prefs_, - extension->id())) { - AddExtension(extension); - } + + AddExtension(extension); } void ExtensionToolbarModel::OnExtensionUnloaded( @@ -240,7 +236,7 @@ size_t ExtensionToolbarModel::FindNewPositionFromLastKnownGood( // See if we have last known good position for this extension. size_t new_index = 0; // Loop through the ID list of known positions, to count the number of visible - // browser action icons preceding |extension|. + // extension icons preceding |extension|. for (ExtensionIdList::const_iterator iter_id = last_known_positions_.begin(); iter_id < last_known_positions_.end(); ++iter_id) { if ((*iter_id) == extension->id()) @@ -260,9 +256,25 @@ size_t ExtensionToolbarModel::FindNewPositionFromLastKnownGood( return toolbar_items_.size(); } +bool ExtensionToolbarModel::ShouldAddExtension(const Extension* extension) { + ExtensionActionManager* action_manager = + ExtensionActionManager::Get(profile_); + if (include_all_extensions_) { + // In this case, we don't care about the browser action visibility, because + // we want to show each extension regardless. + // TODO(devlin): Extension actions which are not visible should be moved to + // the overflow menu by default. + return action_manager->GetBrowserAction(*extension) || + action_manager->GetPageAction(*extension); + } + + return action_manager->GetBrowserAction(*extension) && + ExtensionActionAPI::GetBrowserActionVisibility( + extension_prefs_, extension->id()); +} + void ExtensionToolbarModel::AddExtension(const Extension* extension) { - // We only care about extensions with browser actions. - if (!ExtensionActionManager::Get(profile_)->GetBrowserAction(*extension)) + if (!ShouldAddExtension(extension)) return; size_t new_index = toolbar_items_.size(); @@ -291,8 +303,8 @@ void ExtensionToolbarModel::AddExtension(const Extension* extension) { // to the full list (|toolbar_items_|, there won't be another *visible* // browser action, which was what the observers care about. if (!is_highlighting_) { - FOR_EACH_OBSERVER(Observer, observers_, - BrowserActionAdded(extension, new_index)); + FOR_EACH_OBSERVER( + Observer, observers_, ToolbarExtensionAdded(extension, new_index)); } } @@ -312,13 +324,14 @@ void ExtensionToolbarModel::RemoveExtension(const Extension* extension) { extension); if (pos != highlighted_items_.end()) { highlighted_items_.erase(pos); - FOR_EACH_OBSERVER(Observer, observers_, BrowserActionRemoved(extension)); + FOR_EACH_OBSERVER( + Observer, observers_, ToolbarExtensionRemoved(extension)); // If the highlighted list is now empty, we stop highlighting. if (highlighted_items_.empty()) StopHighlighting(); } } else { - FOR_EACH_OBSERVER(Observer, observers_, BrowserActionRemoved(extension)); + FOR_EACH_OBSERVER(Observer, observers_, ToolbarExtensionRemoved(extension)); } UpdatePrefs(); @@ -337,7 +350,7 @@ void ExtensionToolbarModel::InitializeExtensionList( Populate(last_known_positions_, extensions); extensions_initialized_ = true; - FOR_EACH_OBSERVER(Observer, observers_, VisibleCountChanged()); + FOR_EACH_OBSERVER(Observer, observers_, ToolbarVisibleCountChanged()); } void ExtensionToolbarModel::Populate(const ExtensionIdList& positions, @@ -357,11 +370,9 @@ void ExtensionToolbarModel::Populate(const ExtensionIdList& positions, it != extensions.end(); ++it) { const Extension* extension = it->get(); - if (!extension_action_manager->GetBrowserAction(*extension)) - continue; - if (!ExtensionActionAPI::GetBrowserActionVisibility( - extension_prefs_, extension->id())) { - ++hidden; + if (!ShouldAddExtension(extension)) { + if (extension_action_manager->GetBrowserAction(*extension)) + ++hidden; continue; } @@ -381,7 +392,7 @@ void ExtensionToolbarModel::Populate(const ExtensionIdList& positions, // calls SetVisibleCount. toolbar_items_.pop_back(); FOR_EACH_OBSERVER( - Observer, observers_, BrowserActionRemoved(extension)); + Observer, observers_, ToolbarExtensionRemoved(extension)); } DCHECK(toolbar_items_.empty()); @@ -399,7 +410,7 @@ void ExtensionToolbarModel::Populate(const ExtensionIdList& positions, if (iter->get() != NULL) { toolbar_items_.push_back(*iter); FOR_EACH_OBSERVER( - Observer, observers_, BrowserActionAdded( + Observer, observers_, ToolbarExtensionAdded( *iter, toolbar_items_.size() - 1)); } } @@ -408,7 +419,7 @@ void ExtensionToolbarModel::Populate(const ExtensionIdList& positions, if (iter->get() != NULL) { toolbar_items_.push_back(*iter); FOR_EACH_OBSERVER( - Observer, observers_, BrowserActionAdded( + Observer, observers_, ToolbarExtensionAdded( *iter, toolbar_items_.size() - 1)); } } @@ -502,7 +513,7 @@ bool ExtensionToolbarModel::ShowBrowserActionPopup(const Extension* extension) { Observer* obs = NULL; while ((obs = it.GetNext()) != NULL) { // Stop after first popup since it should only show in the active window. - if (obs->BrowserActionShowPopup(extension)) + if (obs->ShowExtensionActionPopup(extension)) return true; } return false; @@ -519,7 +530,7 @@ void ExtensionToolbarModel::EnsureVisibility( SetVisibleIconCount(extension_ids.size()); // Inform observers. - FOR_EACH_OBSERVER(Observer, observers_, VisibleCountChanged()); + FOR_EACH_OBSERVER(Observer, observers_, ToolbarVisibleCountChanged()); } if (visible_icon_count_ == -1) @@ -532,7 +543,7 @@ void ExtensionToolbarModel::EnsureVisibility( extension != toolbar_items_.end(); ++extension) { if ((*extension)->id() == (*it)) { if (extension - toolbar_items_.begin() >= visible_icon_count_) - MoveBrowserAction(*extension, 0); + MoveExtensionIcon(*extension, 0); break; } } @@ -562,10 +573,10 @@ bool ExtensionToolbarModel::HighlightExtensions( if (visible_icon_count_ != -1 && visible_icon_count_ < static_cast<int>(extension_ids.size())) { SetVisibleIconCount(extension_ids.size()); - FOR_EACH_OBSERVER(Observer, observers_, VisibleCountChanged()); + FOR_EACH_OBSERVER(Observer, observers_, ToolbarVisibleCountChanged()); } - FOR_EACH_OBSERVER(Observer, observers_, HighlightModeChanged(true)); + FOR_EACH_OBSERVER(Observer, observers_, ToolbarHighlightModeChanged(true)); return true; } @@ -582,9 +593,9 @@ void ExtensionToolbarModel::StopHighlighting() { is_highlighting_ = false; if (old_visible_icon_count_ != visible_icon_count_) { SetVisibleIconCount(old_visible_icon_count_); - FOR_EACH_OBSERVER(Observer, observers_, VisibleCountChanged()); + FOR_EACH_OBSERVER(Observer, observers_, ToolbarVisibleCountChanged()); } - FOR_EACH_OBSERVER(Observer, observers_, HighlightModeChanged(false)); + FOR_EACH_OBSERVER(Observer, observers_, ToolbarHighlightModeChanged(false)); } } diff --git a/chrome/browser/extensions/extension_toolbar_model.h b/chrome/browser/extensions/extension_toolbar_model.h index 0068b8b..457311d 100644 --- a/chrome/browser/extensions/extension_toolbar_model.h +++ b/chrome/browser/extensions/extension_toolbar_model.h @@ -35,25 +35,28 @@ class ExtensionToolbarModel : public content::NotificationObserver, // A class which is informed of changes to the model; represents the view of // MVC. Also used for signaling view changes such as showing extension popups. + // TODO(devlin): Should this really be an observer? There should probably be + // only one (aka a Delegate)... class Observer { public: - // An extension with a browser action button has been added, and should go - // in the toolbar at |index|. - virtual void BrowserActionAdded(const Extension* extension, int index) {} + // An extension has been added to the toolbar and should go at |index|. + virtual void ToolbarExtensionAdded(const Extension* extension, + int index) = 0; - // The browser action button for |extension| should no longer show. - virtual void BrowserActionRemoved(const Extension* extension) {} + // The given |extension| should be removed from the toolbar. + virtual void ToolbarExtensionRemoved(const Extension* extension) = 0; - // The browser action button for |extension| has been moved to |index|. - virtual void BrowserActionMoved(const Extension* extension, int index) {} + // The given |extension| has been moved to |index|. + virtual void ToolbarExtensionMoved(const Extension* extension, + int index) = 0; // Signal the |extension| to show the popup now in the active window. // Returns true if a popup was slated to be shown. - virtual bool BrowserActionShowPopup(const Extension* extension); + virtual bool ShowExtensionActionPopup(const Extension* extension) = 0; // Signal when the container needs to be redrawn because of a size change, // and when the model has finished loading. - virtual void VisibleCountChanged() {} + virtual void ToolbarVisibleCountChanged() = 0; // Signal that the model has entered or exited highlighting mode, or that // the extensions being highlighted have (probably*) changed. Highlighting @@ -62,7 +65,7 @@ class ExtensionToolbarModel : public content::NotificationObserver, // * probably, because if we are in highlight mode and receive a call to // highlight a new set of extensions, we do not compare the current set // with the new set (and just assume the new set is different). - virtual void HighlightModeChanged(bool is_highlighting) {} + virtual void ToolbarHighlightModeChanged(bool is_highlighting) = 0; protected: virtual ~Observer() {} @@ -71,10 +74,13 @@ class ExtensionToolbarModel : public content::NotificationObserver, // Convenience function to get the ExtensionToolbarModel for a Profile. static ExtensionToolbarModel* Get(Profile* profile); - // Functions called by the view. + // Add or remove an observer. void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); - void MoveBrowserAction(const Extension* extension, int index); + + // Moves the given |extension|'s icon to the given |index|. + void MoveExtensionIcon(const Extension* extension, int index); + // Executes the browser action for an extension and returns the action that // the UI should perform in response. // |popup_url_out| will be set if the extension should show a popup, with @@ -86,9 +92,12 @@ class ExtensionToolbarModel : public content::NotificationObserver, Browser* browser, GURL* popup_url_out, bool should_grant); + + // Sets the number of extension icons that should be visible. // If count == size(), this will set the visible icon count to -1, meaning // "show all actions". void SetVisibleIconCount(int count); + // As above, a return value of -1 represents "show all actions". int GetVisibleIconCount() const { return visible_icon_count_; } @@ -162,12 +171,16 @@ class ExtensionToolbarModel : public content::NotificationObserver, // value returned is a zero-based index into the vector of visible items. size_t FindNewPositionFromLastKnownGood(const Extension* extension); - // Our observers. - ObserverList<Observer> observers_; + // Returns true if the given |extension| should be added to the toolbar. + bool ShouldAddExtension(const Extension* extension); + // Adds or removes the given |extension| from the toolbar model. void AddExtension(const Extension* extension); void RemoveExtension(const Extension* extension); + // Our observers. + ObserverList<Observer> observers_; + // The Profile this toolbar model is for. Profile* profile_; @@ -177,6 +190,10 @@ class ExtensionToolbarModel : public content::NotificationObserver, // True if we've handled the initial EXTENSIONS_READY notification. bool extensions_initialized_; + // If true, we include all extensions in the toolbar model. If false, we only + // include browser actions. + bool include_all_extensions_; + // Ordered list of browser action buttons. ExtensionList toolbar_items_; diff --git a/chrome/browser/extensions/extension_toolbar_model_browsertest.cc b/chrome/browser/extensions/extension_toolbar_model_browsertest.cc index a34b89e..b5bac5b 100644 --- a/chrome/browser/extensions/extension_toolbar_model_browsertest.cc +++ b/chrome/browser/extensions/extension_toolbar_model_browsertest.cc @@ -36,21 +36,28 @@ class ExtensionToolbarModelTest : public ExtensionBrowserTest, model_->RemoveObserver(this); } - virtual void BrowserActionAdded(const Extension* extension, - int index) OVERRIDE { + virtual void ToolbarExtensionAdded(const Extension* extension, + int index) OVERRIDE { inserted_count_++; } - virtual void BrowserActionRemoved(const Extension* extension) OVERRIDE { + virtual void ToolbarExtensionRemoved(const Extension* extension) OVERRIDE { removed_count_++; } - virtual void BrowserActionMoved(const Extension* extension, - int index) OVERRIDE { + virtual void ToolbarExtensionMoved(const Extension* extension, + int index) OVERRIDE { moved_count_++; } - virtual void HighlightModeChanged(bool is_highlighting) OVERRIDE { + virtual bool ShowExtensionActionPopup(const Extension* extension) OVERRIDE { + return false; + } + + virtual void ToolbarVisibleCountChanged() OVERRIDE { + } + + virtual void ToolbarHighlightModeChanged(bool is_highlighting) OVERRIDE { // Add one if highlighting, subtract one if not. highlight_mode_count_ += is_highlighting ? 1 : -1; } @@ -99,7 +106,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, Basic) { extension->name().c_str()); // Should be a no-op, but still fires the events. - model_->MoveBrowserAction(extension, 0); + model_->MoveExtensionIcon(extension, 0); EXPECT_EQ(1, moved_count_); EXPECT_EQ(1u, model_->toolbar_items().size()); const Extension* extension2 = ExtensionAt(0); @@ -160,7 +167,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, MAYBE_ReorderAndReinsert) { extensionC->name().c_str()); // Order is now A, B, C. Let's put C first. - model_->MoveBrowserAction(extensionC, 0); + model_->MoveExtensionIcon(extensionC, 0); EXPECT_EQ(1, moved_count_); EXPECT_EQ(3u, model_->toolbar_items().size()); EXPECT_EQ(extensionC, ExtensionAt(0)); @@ -169,7 +176,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, MAYBE_ReorderAndReinsert) { EXPECT_EQ(NULL, ExtensionAt(3)); // Order is now C, A, B. Let's put A last. - model_->MoveBrowserAction(extensionA, 2); + model_->MoveExtensionIcon(extensionA, 2); EXPECT_EQ(2, moved_count_); EXPECT_EQ(3u, model_->toolbar_items().size()); EXPECT_EQ(extensionC, ExtensionAt(0)); @@ -205,7 +212,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, MAYBE_ReorderAndReinsert) { EXPECT_EQ(NULL, ExtensionAt(2)); // Order is now C, A. Flip it. - model_->MoveBrowserAction(extensionA, 0); + model_->MoveExtensionIcon(extensionA, 0); EXPECT_EQ(3, moved_count_); EXPECT_EQ(2u, model_->toolbar_items().size()); EXPECT_EQ(extensionA, ExtensionAt(0)); @@ -213,7 +220,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, MAYBE_ReorderAndReinsert) { EXPECT_EQ(NULL, ExtensionAt(2)); // Move A to the location it already occupies. - model_->MoveBrowserAction(extensionA, 0); + model_->MoveExtensionIcon(extensionA, 0); EXPECT_EQ(4, moved_count_); EXPECT_EQ(2u, model_->toolbar_items().size()); EXPECT_EQ(extensionA, ExtensionAt(0)); @@ -287,8 +294,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, UnloadAndDisableMultiple) { EXPECT_STREQ(idC.c_str(), extensionC->id().c_str()); // Put C in the middle and A to the end. - model_->MoveBrowserAction(extensionC, 1); - model_->MoveBrowserAction(extensionA, 2); + model_->MoveExtensionIcon(extensionC, 1); + model_->MoveExtensionIcon(extensionA, 2); // Make sure we get this order (C, B, A). EXPECT_STREQ(idC.c_str(), ExtensionAt(0)->id().c_str()); @@ -332,7 +339,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, Uninstall) { EXPECT_STREQ("Popup tester", extensionB->name().c_str()); // Order is now A, B. Make B first. - model_->MoveBrowserAction(extensionB, 0); + model_->MoveExtensionIcon(extensionB, 0); // Order is now B, A. Uninstall Extension B. UninstallExtension(idB); diff --git a/chrome/browser/extensions/extension_toolbar_model_unittest.cc b/chrome/browser/extensions/extension_toolbar_model_unittest.cc new file mode 100644 index 0000000..50d0446 --- /dev/null +++ b/chrome/browser/extensions/extension_toolbar_model_unittest.cc @@ -0,0 +1,139 @@ +// 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 "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_service_test_base.h" +#include "chrome/browser/extensions/extension_toolbar_model.h" +#include "chrome/browser/extensions/test_extension_system.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/extensions/api/extension_action/action_info.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/browser/extension_system.h" +#include "extensions/common/extension.h" +#include "extensions/common/extension_builder.h" +#include "extensions/common/feature_switch.h" +#include "extensions/common/id_util.h" +#include "extensions/common/manifest_constants.h" +#include "extensions/common/value_builder.h" + +namespace extensions { + +namespace { + +// Create an extension. If |action_key| is non-NULL, it should point to either +// kBrowserAction or kPageAction, and the extension will have the associated +// action. +scoped_refptr<const Extension> GetActionExtension(const std::string& name, + const char* action_key) { + DictionaryBuilder manifest; + manifest.Set("name", name) + .Set("description", "An extension") + .Set("manifest_version", 2) + .Set("version", "1.0.0"); + if (action_key) + manifest.Set(action_key, DictionaryBuilder().Pass()); + + return ExtensionBuilder().SetManifest(manifest.Pass()) + .SetID(id_util::GenerateId(name)) + .Build(); +} + +} // namespace + +// TODO(devlin): Experiment with moving (some of the) +// ExtensionToolbarModelBrowserTests into here? +class ExtensionToolbarModelUnitTest : public ExtensionServiceTestBase { + protected: + // Initialize the ExtensionService, ExtensionToolbarModel, and + // ExtensionSystem. + void Init(); + + // Add three extensions, one each for browser action, page action, and no + // action. + testing::AssertionResult AddActionExtensions() WARN_UNUSED_RESULT; + + ExtensionToolbarModel* toolbar_model() { return toolbar_model_.get(); } + const Extension* browser_action() { return browser_action_extension_.get(); } + const Extension* page_action() { return page_action_extension_.get(); } + const Extension* no_action() { return no_action_extension_.get(); } + + private: + // The associated (and owned) toolbar model. + scoped_ptr<ExtensionToolbarModel> toolbar_model_; + + // Three sample extensions. + scoped_refptr<const Extension> browser_action_extension_; + scoped_refptr<const Extension> page_action_extension_; + scoped_refptr<const Extension> no_action_extension_; +}; + +void ExtensionToolbarModelUnitTest::Init() { + InitializeEmptyExtensionService(); + toolbar_model_.reset( + new ExtensionToolbarModel(profile(), ExtensionPrefs::Get(profile()))); + static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()))-> + SetReady(); + // Run tasks posted to TestExtensionSystem. + base::RunLoop().RunUntilIdle(); +} + +testing::AssertionResult ExtensionToolbarModelUnitTest::AddActionExtensions() { + browser_action_extension_ = + GetActionExtension("browser_action", manifest_keys::kBrowserAction); + page_action_extension_ = + GetActionExtension("page_action", manifest_keys::kPageAction); + no_action_extension_ = GetActionExtension("no_action", NULL); + + ExtensionList extensions; + extensions.push_back(browser_action_extension_); + extensions.push_back(page_action_extension_); + extensions.push_back(no_action_extension_); + + // Add and verify each extension. + ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); + for (ExtensionList::const_iterator iter = extensions.begin(); + iter != extensions.end(); ++iter) { + service()->AddExtension(iter->get()); + if (!registry->enabled_extensions().GetByID((*iter)->id())) { + return testing::AssertionFailure() << "Failed to install extension: " << + (*iter)->name(); + } + } + + return testing::AssertionSuccess(); +} + +// Test that, in the absence of the extension-action-redesign switch, the +// model only contains extensions with browser actions. +TEST_F(ExtensionToolbarModelUnitTest, TestToolbarExtensionTypesNoSwitch) { + Init(); + ASSERT_TRUE(AddActionExtensions()); + + const ExtensionList& extensions = toolbar_model()->toolbar_items(); + ASSERT_EQ(1u, extensions.size()); + EXPECT_EQ(browser_action(), extensions[0]); +} + +// Test that, with the extension-action-redesign switch, the model contains +// all types of extensions, except those which should not be displayed on the +// toolbar (like component extensions). +TEST_F(ExtensionToolbarModelUnitTest, TestToolbarExtensionTypesSwitch) { + FeatureSwitch::ScopedOverride enable_redesign( + FeatureSwitch::extension_action_redesign(), true); + Init(); + ASSERT_TRUE(AddActionExtensions()); + + // With the switch on, extensions with page actions and no action should also + // be displayed in the toolbar. + const ExtensionList& extensions = toolbar_model()->toolbar_items(); + ASSERT_EQ(3u, extensions.size()); + EXPECT_EQ(browser_action(), extensions[0]); + EXPECT_EQ(page_action(), extensions[1]); + EXPECT_EQ(no_action(), extensions[2]); +} + +} // namespace extensions diff --git a/chrome/browser/extensions/test_extension_system.h b/chrome/browser/extensions/test_extension_system.h index f436c9f..fb88ef3 100644 --- a/chrome/browser/extensions/test_extension_system.h +++ b/chrome/browser/extensions/test_extension_system.h @@ -86,10 +86,9 @@ class TestExtensionSystem : public ExtensionSystem { GetDeclarativeUserScriptMasterByExtension( const ExtensionId& extension_id) OVERRIDE; - void SetReady() { - LOG(INFO) << "SetReady()"; - ready_.Signal(); - } + // Note that you probably want to use base::RunLoop().RunUntilIdle() right + // after this to run all the accumulated tasks. + void SetReady() { ready_.Signal(); } // Factory method for tests to use with SetTestingProfile. static KeyedService* Build(content::BrowserContext* profile); diff --git a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm index 504809d..04da4d0 100644 --- a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm @@ -220,19 +220,23 @@ class ExtensionServiceObserverBridge } // extensions::ExtensionToolbarModel::Observer implementation. - virtual void BrowserActionAdded( + virtual void ToolbarExtensionAdded( const Extension* extension, int index) OVERRIDE { [owner_ createActionButtonForExtension:extension withIndex:index]; [owner_ resizeContainerAndAnimate:NO]; } - virtual void BrowserActionRemoved(const Extension* extension) OVERRIDE { + virtual void ToolbarExtensionRemoved(const Extension* extension) OVERRIDE { [owner_ removeActionButtonForExtension:extension]; [owner_ resizeContainerAndAnimate:NO]; } - virtual bool BrowserActionShowPopup(const Extension* extension) OVERRIDE { + virtual void ToolbarExtensionMoved(const Extension* extension, + int index) OVERRIDE { + } + + virtual bool ShowExtensionActionPopup(const Extension* extension) OVERRIDE { // Do not override other popups and only show in active window. ExtensionPopupController* popup = [ExtensionPopupController popup]; if (popup || !browser_->window()->IsActive()) @@ -243,6 +247,12 @@ class ExtensionServiceObserverBridge shouldGrant:NO]; } + virtual void ToolbarVisibleCountChanged() OVERRIDE { + } + + virtual void ToolbarHighlightModeChanged(bool is_highlighting) OVERRIDE { + } + private: // The object we need to inform when we get a notification. Weak. Owns us. BrowserActionsController* owner_; @@ -704,7 +714,7 @@ class ExtensionServiceObserverBridge if (intersectionWidth > dragThreshold && button != draggedButton && ![button isAnimating] && index < [self visibleButtonCount]) { - toolbarModel_->MoveBrowserAction([draggedButton extension], index); + toolbarModel_->MoveExtensionIcon([draggedButton extension], index); [self positionActionButtonsAndAnimate:YES]; return; } diff --git a/chrome/browser/ui/views/extensions/extension_action_view_controller.cc b/chrome/browser/ui/views/extensions/extension_action_view_controller.cc index c5bbe63..56bf76f 100644 --- a/chrome/browser/ui/views/extensions/extension_action_view_controller.cc +++ b/chrome/browser/ui/views/extensions/extension_action_view_controller.cc @@ -48,10 +48,10 @@ ExtensionActionViewController::ExtensionActionViewController( icon_factory_(browser->profile(), extension, extension_action, this), popup_(NULL), weak_factory_(this) { + DCHECK(extension_action); DCHECK(extension_action->action_type() == ActionInfo::TYPE_PAGE || extension_action->action_type() == ActionInfo::TYPE_BROWSER); DCHECK(extension); - } ExtensionActionViewController::~ExtensionActionViewController() { diff --git a/chrome/browser/ui/views/toolbar/browser_action_view.cc b/chrome/browser/ui/views/toolbar/browser_action_view.cc index 1519518..6ddc7ed 100644 --- a/chrome/browser/ui/views/toolbar/browser_action_view.cc +++ b/chrome/browser/ui/views/toolbar/browser_action_view.cc @@ -9,7 +9,6 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/extension_action.h" -#include "chrome/browser/extensions/extension_action_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/themes/theme_service_factory.h" @@ -46,14 +45,14 @@ const int kBorderInset = 4; // BrowserActionView BrowserActionView::BrowserActionView(const Extension* extension, + ExtensionAction* extension_action, Browser* browser, BrowserActionView::Delegate* delegate) : MenuButton(this, base::string16(), NULL, false), view_controller_(new ExtensionActionViewController( extension, browser, - extensions::ExtensionActionManager::Get(browser->profile())-> - GetBrowserAction(*extension), + extension_action, this)), delegate_(delegate), called_registered_extension_command_(false), @@ -67,7 +66,7 @@ BrowserActionView::BrowserActionView(const Extension* extension, content::Source<Profile>(browser->profile()->GetOriginalProfile()); registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED, - content::Source<ExtensionAction>(extension_action())); + content::Source<ExtensionAction>(extension_action)); registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_COMMAND_ADDED, notification_source); diff --git a/chrome/browser/ui/views/toolbar/browser_action_view.h b/chrome/browser/ui/views/toolbar/browser_action_view.h index 4d0af0c..6d3c26a 100644 --- a/chrome/browser/ui/views/toolbar/browser_action_view.h +++ b/chrome/browser/ui/views/toolbar/browser_action_view.h @@ -82,8 +82,9 @@ class BrowserActionView : public views::MenuButton, }; BrowserActionView(const extensions::Extension* extension, - Browser* browser, - BrowserActionView::Delegate* delegate); + ExtensionAction* extension_action, + Browser* browser, + BrowserActionView::Delegate* delegate); virtual ~BrowserActionView(); const extensions::Extension* extension() const { diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container.cc b/chrome/browser/ui/views/toolbar/browser_actions_container.cc index 491d85c..fce979e 100644 --- a/chrome/browser/ui/views/toolbar/browser_actions_container.cc +++ b/chrome/browser/ui/views/toolbar/browser_actions_container.cc @@ -6,6 +6,7 @@ #include "base/compiler_specific.h" #include "base/stl_util.h" +#include "chrome/browser/extensions/extension_action_manager.h" #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/extension_view_host.h" #include "chrome/browser/extensions/tab_helper.h" @@ -65,6 +66,15 @@ const int kIconsPerMenuRow = 8; // The menu on Linux is wider. const int kIconsPerMenuRow = 7; #endif +// Returns the ExtensionAction for the given |extension|. +ExtensionAction* GetExtensionAction(const Extension& extension, + Profile* profile) { + extensions::ExtensionActionManager* action_manager = + extensions::ExtensionActionManager::Get(profile); + ExtensionAction* action = action_manager->GetBrowserAction(extension); + return action ? action : action_manager->GetPageAction(extension); +} + // A version of MenuButton with almost empty insets to fit properly on the // toolbar. class ChevronMenuButton : public views::MenuButton { @@ -223,7 +233,11 @@ void BrowserActionsContainer::CreateBrowserActionViews() { if (!ShouldDisplayBrowserAction(i->get())) continue; - BrowserActionView* view = new BrowserActionView(i->get(), browser_, this); + BrowserActionView* view = + new BrowserActionView(i->get(), + GetExtensionAction(*i->get(), profile_), + browser_, + this); browser_action_views_.push_back(view); AddChildView(view); } @@ -532,7 +546,7 @@ int BrowserActionsContainer::OnPerformDrop( if (profile_->IsOffTheRecord()) i = model_->IncognitoIndexToOriginal(i); - model_->MoveBrowserAction( + model_->MoveExtensionIcon( browser_action_views_[data.index()]->extension(), i); OnDragExited(); // Perform clean up after dragging. @@ -666,7 +680,7 @@ void BrowserActionsContainer::MoveBrowserAction(const std::string& extension_id, size_t new_index) { const Extension* extension = extensions::ExtensionRegistry::Get(profile_)-> enabled_extensions().GetByID(extension_id); - model_->MoveBrowserAction(extension, new_index); + model_->MoveExtensionIcon(extension, new_index); SchedulePaint(); } @@ -776,8 +790,8 @@ int BrowserActionsContainer::IconHeight() { return icon_height; } -void BrowserActionsContainer::BrowserActionAdded(const Extension* extension, - int index) { +void BrowserActionsContainer::ToolbarExtensionAdded(const Extension* extension, + int index) { #if defined(DEBUG) for (size_t i = 0; i < browser_action_views_.size(); ++i) { DCHECK(browser_action_views_[i]->extension() != extension) << @@ -795,7 +809,11 @@ void BrowserActionsContainer::BrowserActionAdded(const Extension* extension, // Add the new browser action to the vector and the view hierarchy. if (profile_->IsOffTheRecord()) index = model_->OriginalIndexToIncognito(index); - BrowserActionView* view = new BrowserActionView(extension, browser_, this); + BrowserActionView* view = + new BrowserActionView(extension, + GetExtensionAction(*extension, profile_), + browser_, + this); browser_action_views_.insert(browser_action_views_.begin() + index, view); AddChildViewAt(view, index); @@ -816,7 +834,8 @@ void BrowserActionsContainer::BrowserActionAdded(const Extension* extension, } } -void BrowserActionsContainer::BrowserActionRemoved(const Extension* extension) { +void BrowserActionsContainer::ToolbarExtensionRemoved( + const Extension* extension) { CloseOverflowMenu(); size_t visible_actions = VisibleBrowserActionsAfterAnimation(); @@ -851,8 +870,8 @@ void BrowserActionsContainer::BrowserActionRemoved(const Extension* extension) { } } -void BrowserActionsContainer::BrowserActionMoved(const Extension* extension, - int index) { +void BrowserActionsContainer::ToolbarExtensionMoved(const Extension* extension, + int index) { if (!ShouldDisplayBrowserAction(extension)) return; @@ -867,16 +886,17 @@ void BrowserActionsContainer::BrowserActionMoved(const Extension* extension, SchedulePaint(); } -bool BrowserActionsContainer::BrowserActionShowPopup( +bool BrowserActionsContainer::ShowExtensionActionPopup( const Extension* extension) { return ShowPopupForExtension(extension, false, false); } -void BrowserActionsContainer::VisibleCountChanged() { +void BrowserActionsContainer::ToolbarVisibleCountChanged() { SetContainerWidth(); } -void BrowserActionsContainer::HighlightModeChanged(bool is_highlighting) { +void BrowserActionsContainer::ToolbarHighlightModeChanged( + bool is_highlighting) { // The visual highlighting is done in OnPaint(). It's a bit of a pain that // we delete and recreate everything here, but that's how it's done in // BrowserActionMoved(), too. If we want to optimize it, we could move the diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container.h b/chrome/browser/ui/views/toolbar/browser_actions_container.h index f704ead..5d789ba7ee 100644 --- a/chrome/browser/ui/views/toolbar/browser_actions_container.h +++ b/chrome/browser/ui/views/toolbar/browser_actions_container.h @@ -290,16 +290,16 @@ class BrowserActionsContainer static int IconHeight(); // extensions::ExtensionToolbarModel::Observer implementation. - virtual void BrowserActionAdded(const extensions::Extension* extension, - int index) OVERRIDE; - virtual void BrowserActionRemoved( + virtual void ToolbarExtensionAdded(const extensions::Extension* extension, + int index) OVERRIDE; + virtual void ToolbarExtensionRemoved( const extensions::Extension* extension) OVERRIDE; - virtual void BrowserActionMoved(const extensions::Extension* extension, - int index) OVERRIDE; - virtual bool BrowserActionShowPopup( + virtual void ToolbarExtensionMoved(const extensions::Extension* extension, + int index) OVERRIDE; + virtual bool ShowExtensionActionPopup( const extensions::Extension* extension) OVERRIDE; - virtual void VisibleCountChanged() OVERRIDE; - virtual void HighlightModeChanged(bool is_highlighting) OVERRIDE; + virtual void ToolbarVisibleCountChanged() OVERRIDE; + virtual void ToolbarHighlightModeChanged(bool is_highlighting) OVERRIDE; void LoadImages(); diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 000d680..8c2728d 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -965,6 +965,7 @@ 'browser/extensions/extension_special_storage_policy_unittest.cc', 'browser/extensions/extension_sync_data_unittest.cc', 'browser/extensions/extension_test_message_listener_unittest.cc', + 'browser/extensions/extension_toolbar_model_unittest.cc', 'browser/extensions/extension_ui_unittest.cc', 'browser/extensions/extension_warning_badge_service_unittest.cc', 'browser/extensions/extension_warning_service_unittest.cc', diff --git a/chrome/common/extensions/manifest_handlers/synthesize_browser_action_handler.cc b/chrome/common/extensions/manifest_handlers/synthesize_browser_action_handler.cc index c824c9f..d56a383 100644 --- a/chrome/common/extensions/manifest_handlers/synthesize_browser_action_handler.cc +++ b/chrome/common/extensions/manifest_handlers/synthesize_browser_action_handler.cc @@ -28,12 +28,9 @@ bool SynthesizeBrowserActionHandler::Parse(Extension* extension, if (extension->manifest()->HasKey(manifest_keys::kSynthesizeBrowserAction)) return false; // This key is reserved, no extension should be using it. - // TODO(devlin): Make sure we don't have two icons showing for page action - // extensions if we show page action icons in the browser action - // toolbar. - if (!extension->manifest()->HasKey(manifest_keys::kBrowserAction)) + if (!extension->manifest()->HasKey(manifest_keys::kBrowserAction) && + !extension->manifest()->HasKey(manifest_keys::kPageAction)) ActionInfo::SetBrowserActionInfo(extension, new ActionInfo()); - return true; } |