1 // 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.
5 #include "chrome/browser/extensions/extension_action_test_util.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/run_loop.h"
9 #include "chrome/browser/extensions/extension_action.h"
10 #include "chrome/browser/extensions/extension_action_manager.h"
11 #include "chrome/browser/extensions/location_bar_controller.h"
12 #include "chrome/browser/extensions/tab_helper.h"
13 #include "chrome/browser/extensions/test_extension_system.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/sessions/session_tab_helper.h"
16 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
17 #include "chrome/browser/ui/toolbar/toolbar_actions_model_factory.h"
18 #include "components/crx_file/id_util.h"
19 #include "content/public/browser/web_contents.h"
20 #include "extensions/browser/extension_registry.h"
21 #include "extensions/common/extension.h"
22 #include "extensions/common/extension_builder.h"
23 #include "extensions/common/feature_switch.h"
24 #include "extensions/common/manifest_constants.h"
25 #include "extensions/common/value_builder.h"
27 namespace extensions
{
28 namespace extension_action_test_util
{
32 size_t GetPageActionCount(content::WebContents
* web_contents
,
33 bool only_count_visible
) {
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
39 // ToolbarActionsModel), depending on whether or not the extension action
40 // 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
))
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();
60 ExtensionActionManager
* action_manager
=
61 ExtensionActionManager::Get(web_contents
->GetBrowserContext());
62 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(
67 ExtensionAction
* extension_action
=
68 action_manager
->GetPageAction(*extension
);
69 if (extension_action
&&
70 (!only_count_visible
|| extension_action
->GetIsVisible(tab_id
)))
79 // Creates a new ToolbarActionsModel for the given |context|.
80 scoped_ptr
<KeyedService
> BuildToolbarModel(content::BrowserContext
* context
) {
81 return make_scoped_ptr(
82 new ToolbarActionsModel(Profile::FromBrowserContext(context
),
83 extensions::ExtensionPrefs::Get(context
)));
86 // Creates a new ToolbarActionsModel for the given profile, optionally
87 // triggering the extension system's ready signal.
88 ToolbarActionsModel
* CreateToolbarModelImpl(Profile
* profile
,
89 bool wait_for_ready
) {
90 ToolbarActionsModel
* model
= ToolbarActionsModel::Get(profile
);
94 // No existing model means it's a new profile (since we, by default, don't
95 // create the ToolbarModel in testing).
96 ToolbarActionsModelFactory::GetInstance()->SetTestingFactory(
97 profile
, &BuildToolbarModel
);
98 model
= ToolbarActionsModel::Get(profile
);
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
106 static_cast<TestExtensionSystem
*>(ExtensionSystem::Get(profile
))->
108 // Run tasks posted to TestExtensionSystem.
109 base::RunLoop().RunUntilIdle();
117 size_t GetVisiblePageActionCount(content::WebContents
* web_contents
) {
118 return GetPageActionCount(web_contents
, true);
121 size_t GetTotalPageActionCount(content::WebContents
* web_contents
) {
122 return GetPageActionCount(web_contents
, false);
125 scoped_refptr
<const Extension
> CreateActionExtension(const std::string
& name
,
126 ActionType action_type
) {
127 return CreateActionExtension(name
, action_type
, Manifest::INTERNAL
);
130 scoped_refptr
<const Extension
> CreateActionExtension(
131 const std::string
& name
,
132 ActionType action_type
,
133 Manifest::Location location
) {
134 DictionaryBuilder manifest
;
135 manifest
.Set("name", name
)
136 .Set("description", "An extension")
137 .Set("manifest_version", 2)
138 .Set("version", "1.0.0");
140 const char* action_key
= nullptr;
141 switch (action_type
) {
145 action_key
= manifest_keys::kPageAction
;
148 action_key
= manifest_keys::kBrowserAction
;
153 manifest
.Set(action_key
, DictionaryBuilder().Pass());
155 return ExtensionBuilder().SetManifest(manifest
.Pass()).
156 SetID(crx_file::id_util::GenerateId(name
)).
157 SetLocation(location
).
161 ToolbarActionsModel
* CreateToolbarModelForProfile(Profile
* profile
) {
162 return CreateToolbarModelImpl(profile
, true);
165 ToolbarActionsModel
* CreateToolbarModelForProfileWithoutWaitingForReady(
167 return CreateToolbarModelImpl(profile
, false);
170 } // namespace extension_action_test_util
171 } // namespace extensions