Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: chrome/browser/extensions/extension_message_bubble_controller_unittest.cc

Issue 95133002: Add an extension bubble explaining which extensions are in dev mode. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix compile error Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 "base/command_line.h"
6 #include "base/strings/string_util.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/extensions/dev_mode_bubble_controller_delegate.h"
9 #include "chrome/browser/extensions/extension_function_test_utils.h"
10 #include "chrome/browser/extensions/extension_message_bubble.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/suspicious_extension_bubble_controller_deleg ate.h"
13 #include "chrome/browser/extensions/test_extension_system.h"
14 #include "chrome/test/base/testing_profile.h"
15 #include "content/public/test/test_browser_thread_bundle.h"
16 #include "extensions/common/extension.h"
17
18 namespace extensions {
19
20 class TestDelegate {
21 public:
22 TestDelegate()
23 : action_button_callback_count_(0),
24 dismiss_button_callback_count_(0),
25 link_click_callback_count_(0) {
26 }
27
28 // Returns how often the dismiss button has been called.
29 size_t action_click_count() {
30 return action_button_callback_count_;
31 }
32
33 // Returns how often the dismiss button has been called.
34 size_t dismiss_click_count() {
35 return dismiss_button_callback_count_;
36 }
37
38 // Returns how often the link has been clicked.
39 size_t link_click_count() {
40 return link_click_callback_count_;
41 }
42
43 void DetermineAction(ExtensionMessageBubbleController::BubbleAction action) {
44 switch (action) {
45 case ExtensionMessageBubbleController::ACTION_EXECUTE:
46 ++action_button_callback_count_;
47 break;
48 case ExtensionMessageBubbleController::ACTION_DISMISS:
49 ++dismiss_button_callback_count_;
50 break;
51 case ExtensionMessageBubbleController::ACTION_LEARN_MORE:
52 ++link_click_callback_count_;
53 break;
54 case ExtensionMessageBubbleController::ACTION_BOUNDARY:
55 NOTREACHED();
56 break;
57 }
58 }
59
60 protected:
61 size_t action_button_callback_count_;
62 size_t dismiss_button_callback_count_;
63 size_t link_click_callback_count_;
64 };
65
66 // A test class for the SuspiciousExtensionBubbleControllerDelegate.
67 class TestSuspiciousExtensionBubbleControllerDelegate
68 : public SuspiciousExtensionBubbleControllerDelegate,
69 public TestDelegate {
70 public:
71 explicit TestSuspiciousExtensionBubbleControllerDelegate(Profile* profile)
72 : SuspiciousExtensionBubbleControllerDelegate(profile) {
73 }
74
75 virtual void LogAction(
76 ExtensionMessageBubbleController::BubbleAction action) OVERRIDE {
77 DetermineAction(action);
78 SuspiciousExtensionBubbleControllerDelegate::LogAction(action);
79 }
80 };
81
82 // A test class for the DevModeBubbleControllerDelegate.
83 class TestDevModeBubbleControllerDelegate
84 : public DevModeBubbleControllerDelegate,
85 public TestDelegate {
86 public:
87 explicit TestDevModeBubbleControllerDelegate(Profile* profile)
88 : DevModeBubbleControllerDelegate(profile) {
89 }
90
91 virtual void LogAction(
92 ExtensionMessageBubbleController::BubbleAction action) OVERRIDE {
93 DetermineAction(action);
94 DevModeBubbleControllerDelegate::LogAction(action);
95 }
96 };
97
98 // A fake bubble used for testing the controller. Takes an action that specifies
99 // what should happen when the bubble is "shown" (the bubble is actually not
100 // shown, the corresponding action is taken immediately).
101 class FakeExtensionMessageBubble : public ExtensionMessageBubble {
102 public:
103 enum ExtensionBubbleAction {
104 BUBBLE_ACTION_CLICK_ACTION_BUTTON = 0,
105 BUBBLE_ACTION_CLICK_DISMISS_BUTTON,
106 BUBBLE_ACTION_CLICK_LINK,
107 };
108
109 FakeExtensionMessageBubble() {}
110
111 void set_action_on_show(ExtensionBubbleAction action) {
112 action_ = action;
113 }
114
115 virtual void Show() OVERRIDE {
116 if (action_ == BUBBLE_ACTION_CLICK_ACTION_BUTTON)
117 action_callback_.Run();
118 else if (action_ == BUBBLE_ACTION_CLICK_DISMISS_BUTTON)
119 dismiss_callback_.Run();
120 else if (action_ == BUBBLE_ACTION_CLICK_LINK)
121 link_callback_.Run();
122 }
123
124 virtual void OnActionButtonClicked(const base::Closure& callback) OVERRIDE {
125 action_callback_ = callback;
126 }
127
128 virtual void OnDismissButtonClicked(const base::Closure& callback) OVERRIDE {
129 dismiss_callback_ = callback;
130 }
131
132 virtual void OnLinkClicked(const base::Closure& callback) OVERRIDE {
133 link_callback_ = callback;
134 }
135
136 private:
137 ExtensionBubbleAction action_;
138
139 base::Closure action_callback_;
140 base::Closure dismiss_callback_;
141 base::Closure link_callback_;
142 };
143
144 class ExtensionMessageBubbleTest : public testing::Test {
145 public:
146 ExtensionMessageBubbleTest() {
147 // The two lines of magical incantation required to get the extension
148 // service to work inside a unit test and access the extension prefs.
149 thread_bundle_.reset(new content::TestBrowserThreadBundle);
150 profile_.reset(new TestingProfile);
151
152 static_cast<TestExtensionSystem*>(
153 ExtensionSystem::Get(profile_.get()))->CreateExtensionService(
154 CommandLine::ForCurrentProcess(),
155 base::FilePath(),
156 false);
157 service_ = profile_->GetExtensionService();
158 service_->Init();
159
160 std::string basic_extension =
161 "{\"name\": \"Extension #\","
162 "\"version\": \"1.0\","
163 "\"manifest_version\": 2}";
164 std::string basic_extension_with_action =
165 "{\"name\": \"Extension #\","
166 "\"version\": \"1.0\","
167 "\"browser_action\": {"
168 " \"default_title\": \"Default title\""
169 "},"
170 "\"manifest_version\": 2}";
171
172 std::string extension_data;
173 base::ReplaceChars(basic_extension_with_action, "#", "1", &extension_data);
174 scoped_refptr<Extension> my_test_extension1(
175 CreateExtension(
176 Manifest::COMMAND_LINE,
177 extension_data,
178 "Autogenerated 1"));
179
180 base::ReplaceChars(basic_extension, "#", "2", &extension_data);
181 scoped_refptr<Extension> my_test_extension2(
182 CreateExtension(
183 Manifest::UNPACKED,
184 extension_data,
185 "Autogenerated 2"));
186
187 base::ReplaceChars(basic_extension, "#", "3", &extension_data);
188 scoped_refptr<Extension> regular_extension(
189 CreateExtension(
190 Manifest::EXTERNAL_POLICY,
191 extension_data,
192 "Autogenerated 3"));
193
194 extension_id1_ = my_test_extension1->id();
195 extension_id2_ = my_test_extension2->id();
196 extension_id3_ = regular_extension->id();
197
198 service_->AddExtension(regular_extension);
199 service_->AddExtension(my_test_extension1);
200 service_->AddExtension(my_test_extension2);
201 }
202 virtual ~ExtensionMessageBubbleTest() {}
203
204 virtual void SetUp() {
205 command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM));
206 }
207
208 protected:
209 scoped_refptr<Extension> CreateExtension(
210 Manifest::Location location,
211 const std::string& data,
212 const std::string& id) {
213 scoped_ptr<base::DictionaryValue> parsed_manifest(
214 extension_function_test_utils::ParseDictionary(data));
215 return extension_function_test_utils::CreateExtension(
216 location,
217 parsed_manifest.get(),
218 id);
219 }
220
221 scoped_ptr<TestingProfile> profile_;
222 ExtensionService* service_;
223 std::string extension_id1_;
224 std::string extension_id2_;
225 std::string extension_id3_;
226
227 private:
228 scoped_ptr<CommandLine> command_line_;
229 scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_;
230
231 DISALLOW_COPY_AND_ASSIGN(ExtensionMessageBubbleTest);
232 };
233
234 // The feature this is meant to test is only implemented on Windows.
235 #if defined(OS_WIN)
236 #define MAYBE_WipeoutControllerTest WipeoutControllerTest
237 #else
238 #define MAYBE_WipeoutControllerTest DISABLED_WipeoutControllerTest
239 #endif
240
241 TEST_F(ExtensionMessageBubbleTest, MAYBE_WipeoutControllerTest) {
242 // The test base class adds three extensions, and we control two of them in
243 // this test (ids are: extension_id1_ and extension_id2_).
244 scoped_ptr<TestSuspiciousExtensionBubbleControllerDelegate> controller(
245 new TestSuspiciousExtensionBubbleControllerDelegate(profile_.get()));
246 FakeExtensionMessageBubble bubble;
247 bubble.set_action_on_show(
248 FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_DISMISS_BUTTON);
249
250 // Validate that we don't have a suppress value for the extensions.
251 ExtensionPrefs* prefs = service_->extension_prefs();
252 EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id1_));
253 EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id2_));
254
255 EXPECT_FALSE(controller->HasExtensionList());
256 std::vector<string16> suspicious_extensions = controller->GetExtensionList();
257 EXPECT_EQ(0U, suspicious_extensions.size());
258 EXPECT_EQ(0U, controller->link_click_count());
259 EXPECT_EQ(0U, controller->dismiss_click_count());
260
261 // Now disable an extension, specifying the wipeout flag.
262 service_->DisableExtension(extension_id1_,
263 Extension::DISABLE_NOT_VERIFIED);
264
265 EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id1_));
266 EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id2_));
267 controller.reset(new TestSuspiciousExtensionBubbleControllerDelegate(
268 profile_.get()));
269 EXPECT_TRUE(controller->HasExtensionList());
270 suspicious_extensions = controller->GetExtensionList();
271 ASSERT_EQ(1U, suspicious_extensions.size());
272 EXPECT_TRUE(ASCIIToUTF16("Extension 1") == suspicious_extensions[0]);
273 controller->Show(&bubble); // Simulate showing the bubble.
274 EXPECT_EQ(0U, controller->link_click_count());
275 EXPECT_EQ(1U, controller->dismiss_click_count());
276 // Now the acknowledge flag should be set only for the first extension.
277 EXPECT_TRUE(prefs->HasWipeoutBeenAcknowledged(extension_id1_));
278 EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id2_));
279 // Clear the flag.
280 prefs->SetWipeoutAcknowledged(extension_id1_, false);
281 EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id1_));
282
283 // Now disable the other extension and exercise the link click code path.
284 service_->DisableExtension(extension_id2_,
285 Extension::DISABLE_NOT_VERIFIED);
286
287 bubble.set_action_on_show(
288 FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_LINK);
289 controller.reset(new TestSuspiciousExtensionBubbleControllerDelegate(
290 profile_.get()));
291 EXPECT_TRUE(controller->HasExtensionList());
292 suspicious_extensions = controller->GetExtensionList();
293 ASSERT_EQ(2U, suspicious_extensions.size());
294 EXPECT_TRUE(ASCIIToUTF16("Extension 1") == suspicious_extensions[1]);
295 EXPECT_TRUE(ASCIIToUTF16("Extension 2") == suspicious_extensions[0]);
296 controller->Show(&bubble); // Simulate showing the bubble.
297 EXPECT_EQ(1U, controller->link_click_count());
298 EXPECT_EQ(0U, controller->dismiss_click_count());
299 EXPECT_TRUE(prefs->HasWipeoutBeenAcknowledged(extension_id1_));
300 }
301
302 // The feature this is meant to test is only implemented on Windows.
303 #if defined(OS_WIN)
304 #define MAYBE_DevModeControllerTest DevModeControllerTest
305 #else
306 #define MAYBE_DevModeControllerTest DISABLED_DevModeControllerTest
307 #endif
308
309 TEST_F(ExtensionMessageBubbleTest, MAYBE_DevModeControllerTest) {
310 // The test base class adds three extensions, and we control two of them in
311 // this test (ids are: extension_id1_ and extension_id2_). Extension 1 is a
312 // regular extension, Extension 2 is UNPACKED so it counts as a DevMode
313 // extension.
314 scoped_ptr<TestDevModeBubbleControllerDelegate> controller(
315 new TestDevModeBubbleControllerDelegate(profile_.get()));
316
317 // The list will contain one enabled unpacked extension.
318 EXPECT_TRUE(controller->HasExtensionList());
319 std::vector<string16> dev_mode_extensions = controller->GetExtensionList();
320 ASSERT_EQ(2U, dev_mode_extensions.size());
321 EXPECT_TRUE(ASCIIToUTF16("Extension 2") == dev_mode_extensions[0]);
322 EXPECT_TRUE(ASCIIToUTF16("Extension 1") == dev_mode_extensions[1]);
323 EXPECT_EQ(0U, controller->link_click_count());
324 EXPECT_EQ(0U, controller->dismiss_click_count());
325 EXPECT_EQ(0U, controller->action_click_count());
326
327 // Simulate showing the bubble.
328 FakeExtensionMessageBubble bubble;
329 bubble.set_action_on_show(
330 FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_DISMISS_BUTTON);
331 controller->Show(&bubble);
332 EXPECT_EQ(0U, controller->link_click_count());
333 EXPECT_EQ(0U, controller->action_click_count());
334 EXPECT_EQ(1U, controller->dismiss_click_count());
335 EXPECT_TRUE(service_->GetExtensionById(extension_id1_, false) != NULL);
336 EXPECT_TRUE(service_->GetExtensionById(extension_id2_, false) != NULL);
337
338 // Do it again, but now press different button (Disable).
339 bubble.set_action_on_show(
340 FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_ACTION_BUTTON);
341 controller.reset(new TestDevModeBubbleControllerDelegate(
342 profile_.get()));
343 EXPECT_TRUE(controller->HasExtensionList());
344 dev_mode_extensions = controller->GetExtensionList();
345 EXPECT_EQ(2U, dev_mode_extensions.size());
346 controller->Show(&bubble); // Simulate showing the bubble.
347 EXPECT_EQ(0U, controller->link_click_count());
348 EXPECT_EQ(1U, controller->action_click_count());
349 EXPECT_EQ(0U, controller->dismiss_click_count());
350 EXPECT_TRUE(service_->GetExtensionById(extension_id1_, false) == NULL);
351 EXPECT_TRUE(service_->GetExtensionById(extension_id2_, false) == NULL);
352
353 // Re-enable the extensions (disabled by the action button above).
354 service_->EnableExtension(extension_id1_);
355 service_->EnableExtension(extension_id2_);
356
357 // Show the dialog a third time, but now press the learn more link.
358 bubble.set_action_on_show(
359 FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_LINK);
360 controller.reset(new TestDevModeBubbleControllerDelegate(
361 profile_.get()));
362 EXPECT_TRUE(controller->HasExtensionList());
363 dev_mode_extensions = controller->GetExtensionList();
364 EXPECT_EQ(2U, dev_mode_extensions.size());
365 controller->Show(&bubble); // Simulate showing the bubble.
366 EXPECT_EQ(1U, controller->link_click_count());
367 EXPECT_EQ(0U, controller->action_click_count());
368 EXPECT_EQ(0U, controller->dismiss_click_count());
369 EXPECT_TRUE(service_->GetExtensionById(extension_id1_, false) != NULL);
370 EXPECT_TRUE(service_->GetExtensionById(extension_id2_, false) != NULL);
371
372 // Now disable the unpacked extension.
373 service_->DisableExtension(extension_id1_, Extension::DISABLE_USER_ACTION);
374 service_->DisableExtension(extension_id2_, Extension::DISABLE_USER_ACTION);
375
376 controller.reset(new TestDevModeBubbleControllerDelegate(
377 profile_.get()));
378 EXPECT_FALSE(controller->HasExtensionList());
379 dev_mode_extensions = controller->GetExtensionList();
380 EXPECT_EQ(0U, dev_mode_extensions.size());
381 }
382
383 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698