blob: 1a9de97ac5167f6f0d9d470b5e516db42c0e6de0 [file] [log] [blame]
rdevlin.cronin6e7e5edc2014-08-29 16:23:231// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/extension_action_test_util.h"
6
isherman30fa851a2015-06-09 23:32:107#include "base/memory/scoped_ptr.h"
rdevlin.cronind2d87abc2014-12-01 19:23:558#include "base/run_loop.h"
rdevlin.cronin6e7e5edc2014-08-29 16:23:239#include "chrome/browser/extensions/extension_action.h"
10#include "chrome/browser/extensions/extension_action_manager.h"
rdevlin.cronin6e7e5edc2014-08-29 16:23:2311#include "chrome/browser/extensions/location_bar_controller.h"
12#include "chrome/browser/extensions/tab_helper.h"
rdevlin.cronind2d87abc2014-12-01 19:23:5513#include "chrome/browser/extensions/test_extension_system.h"
rdevlin.cronin6e7e5edc2014-08-29 16:23:2314#include "chrome/browser/profiles/profile.h"
15#include "chrome/browser/sessions/session_tab_helper.h"
apaciblef9cfc4d2015-08-18 05:14:1416#include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
17#include "chrome/browser/ui/toolbar/toolbar_actions_model_factory.h"
rdevlin.cronind2d87abc2014-12-01 19:23:5518#include "components/crx_file/id_util.h"
rdevlin.cronin6e7e5edc2014-08-29 16:23:2319#include "content/public/browser/web_contents.h"
apaciblef9cfc4d2015-08-18 05:14:1420#include "extensions/browser/extension_registry.h"
rdevlin.cronin6e7e5edc2014-08-29 16:23:2321#include "extensions/common/extension.h"
rdevlin.cronind2d87abc2014-12-01 19:23:5522#include "extensions/common/extension_builder.h"
rdevlin.cronin6e7e5edc2014-08-29 16:23:2323#include "extensions/common/feature_switch.h"
rdevlin.cronind2d87abc2014-12-01 19:23:5524#include "extensions/common/manifest_constants.h"
25#include "extensions/common/value_builder.h"
rdevlin.cronin6e7e5edc2014-08-29 16:23:2326
27namespace extensions {
28namespace extension_action_test_util {
29
30namespace {
31
32size_t GetPageActionCount(content::WebContents* web_contents,
33 bool only_count_visible) {
34 DCHECK(web_contents);
35 size_t count = 0u;
36 int tab_id = SessionTabHelper::IdForTab(web_contents);
37 // Page actions are either stored in the location bar (and provided by the
38 // LocationBarController), or in the main toolbar (and provided by the
apaciblef9cfc4d2015-08-18 05:14:1439 // ToolbarActionsModel), depending on whether or not the extension action
rdevlin.cronin6e7e5edc2014-08-29 16:23:2340 // redesign is enabled.
41 if (!FeatureSwitch::extension_action_redesign()->IsEnabled()) {
42 std::vector<ExtensionAction*> page_actions =
43 TabHelper::FromWebContents(web_contents)->
44 location_bar_controller()->GetCurrentActions();
45 count = page_actions.size();
46 // Trim any invisible page actions, if necessary.
47 if (only_count_visible) {
48 for (std::vector<ExtensionAction*>::iterator iter = page_actions.begin();
49 iter != page_actions.end(); ++iter) {
50 if (!(*iter)->GetIsVisible(tab_id))
51 --count;
52 }
53 }
54 } else {
apaciblef9cfc4d2015-08-18 05:14:1455 Profile* profile =
56 Profile::FromBrowserContext(web_contents->GetBrowserContext());
57 ToolbarActionsModel* toolbar_model = ToolbarActionsModel::Get(profile);
58 const std::vector<ToolbarActionsModel::ToolbarItem>& toolbar_items =
59 toolbar_model->toolbar_items();
rdevlin.cronin6e7e5edc2014-08-29 16:23:2360 ExtensionActionManager* action_manager =
61 ExtensionActionManager::Get(web_contents->GetBrowserContext());
apaciblef9cfc4d2015-08-18 05:14:1462 for (const ToolbarActionsModel::ToolbarItem& item : toolbar_items) {
63 if (item.type == ToolbarActionsModel::EXTENSION_ACTION) {
64 const Extension* extension =
65 ExtensionRegistry::Get(profile)->enabled_extensions().GetByID(
66 item.id);
67 ExtensionAction* extension_action =
68 action_manager->GetPageAction(*extension);
69 if (extension_action &&
70 (!only_count_visible || extension_action->GetIsVisible(tab_id)))
71 ++count;
72 }
rdevlin.cronin6e7e5edc2014-08-29 16:23:2373 }
74 }
75
76 return count;
77}
78
apaciblef9cfc4d2015-08-18 05:14:1479// Creates a new ToolbarActionsModel for the given |context|.
isherman30fa851a2015-06-09 23:32:1080scoped_ptr<KeyedService> BuildToolbarModel(content::BrowserContext* context) {
apaciblef9cfc4d2015-08-18 05:14:1481 return make_scoped_ptr(
82 new ToolbarActionsModel(Profile::FromBrowserContext(context),
83 extensions::ExtensionPrefs::Get(context)));
rdevlin.cronind2d87abc2014-12-01 19:23:5584}
85
apaciblef9cfc4d2015-08-18 05:14:1486// Creates a new ToolbarActionsModel for the given profile, optionally
rdevlin.cronind2d87abc2014-12-01 19:23:5587// triggering the extension system's ready signal.
apaciblef9cfc4d2015-08-18 05:14:1488ToolbarActionsModel* CreateToolbarModelImpl(Profile* profile,
89 bool wait_for_ready) {
90 ToolbarActionsModel* model = ToolbarActionsModel::Get(profile);
rdevlin.cronind2d87abc2014-12-01 19:23:5591 if (model)
92 return model;
93
94 // No existing model means it's a new profile (since we, by default, don't
95 // create the ToolbarModel in testing).
apaciblef9cfc4d2015-08-18 05:14:1496 ToolbarActionsModelFactory::GetInstance()->SetTestingFactory(
rdevlin.cronind2d87abc2014-12-01 19:23:5597 profile, &BuildToolbarModel);
apaciblef9cfc4d2015-08-18 05:14:1498 model = ToolbarActionsModel::Get(profile);
rdevlin.cronind2d87abc2014-12-01 19:23:5599 if (wait_for_ready) {
100 // Fake the extension system ready signal.
101 // HACK ALERT! In production, the ready task on ExtensionSystem (and most
102 // everything else on it, too) is shared between incognito and normal
103 // profiles, but a TestExtensionSystem doesn't have the concept of "shared".
104 // Because of this, we have to set any new profile's TestExtensionSystem's
105 // ready task, too.
106 static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile))->
107 SetReady();
108 // Run tasks posted to TestExtensionSystem.
109 base::RunLoop().RunUntilIdle();
110 }
111
112 return model;
113}
114
rdevlin.cronin6e7e5edc2014-08-29 16:23:23115} // namespace
116
117size_t GetVisiblePageActionCount(content::WebContents* web_contents) {
118 return GetPageActionCount(web_contents, true);
119}
120
121size_t GetTotalPageActionCount(content::WebContents* web_contents) {
122 return GetPageActionCount(web_contents, false);
123}
124
rdevlin.cronind2d87abc2014-12-01 19:23:55125scoped_refptr<const Extension> CreateActionExtension(const std::string& name,
126 ActionType action_type) {
rdevlin.cronin70fc6052015-04-15 17:49:06127 return CreateActionExtension(name, action_type, Manifest::INTERNAL);
128}
129
130scoped_refptr<const Extension> CreateActionExtension(
131 const std::string& name,
132 ActionType action_type,
133 Manifest::Location location) {
rdevlin.cronind2d87abc2014-12-01 19:23:55134 DictionaryBuilder manifest;
135 manifest.Set("name", name)
136 .Set("description", "An extension")
137 .Set("manifest_version", 2)
138 .Set("version", "1.0.0");
139
140 const char* action_key = nullptr;
141 switch (action_type) {
142 case NO_ACTION:
143 break;
144 case PAGE_ACTION:
145 action_key = manifest_keys::kPageAction;
146 break;
147 case BROWSER_ACTION:
148 action_key = manifest_keys::kBrowserAction;
149 break;
150 }
151
152 if (action_key)
153 manifest.Set(action_key, DictionaryBuilder().Pass());
154
155 return ExtensionBuilder().SetManifest(manifest.Pass()).
156 SetID(crx_file::id_util::GenerateId(name)).
rdevlin.cronin70fc6052015-04-15 17:49:06157 SetLocation(location).
rdevlin.cronind2d87abc2014-12-01 19:23:55158 Build();
159}
160
apaciblef9cfc4d2015-08-18 05:14:14161ToolbarActionsModel* CreateToolbarModelForProfile(Profile* profile) {
rdevlin.cronind2d87abc2014-12-01 19:23:55162 return CreateToolbarModelImpl(profile, true);
163}
164
apaciblef9cfc4d2015-08-18 05:14:14165ToolbarActionsModel* CreateToolbarModelForProfileWithoutWaitingForReady(
rdevlin.cronind2d87abc2014-12-01 19:23:55166 Profile* profile) {
167 return CreateToolbarModelImpl(profile, false);
168}
169
rdevlin.cronin6e7e5edc2014-08-29 16:23:23170} // namespace extension_action_test_util
171} // namespace extensions