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

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: Sync'ed 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.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.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 TestController {
21 public:
22 TestController()
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 protected:
44 size_t action_button_callback_count_;
45 size_t dismiss_button_callback_count_;
46 size_t link_click_callback_count_;
47 };
48
49 // A test class for the SuspiciousExtensionBubbleController.
50 class TestSuspiciousExtensionBubbleController
51 : public SuspiciousExtensionBubbleController,
52 public TestController {
53 public:
54 explicit TestSuspiciousExtensionBubbleController(Profile* profile)
55 : SuspiciousExtensionBubbleController(profile) {
56 }
57
58 // Callbacks from bubble.
59 virtual void OnBubbleAction() OVERRIDE {
60 // This bubble offers no user action so this should never get called.
61 NOTREACHED();
62 }
63
64 virtual void OnBubbleDismiss() OVERRIDE {
65 ++dismiss_button_callback_count_;
66 SuspiciousExtensionBubbleController::OnBubbleDismiss();
67 }
68 virtual void OnLinkClicked() OVERRIDE {
69 ++link_click_callback_count_;
70 SuspiciousExtensionBubbleController::OnLinkClicked();
71 }
72 };
73
74 // A test class for the DevModeBubbleController.
75 class TestDevModeBubbleController
76 : public DevModeBubbleController,
77 public TestController {
78 public:
79 explicit TestDevModeBubbleController(Profile* profile)
80 : DevModeBubbleController(profile) {
81 }
82
83 // Callbacks from bubble.
84 // Callbacks from bubble.
85 virtual void OnBubbleAction() OVERRIDE {
86 ++action_button_callback_count_;
87 DevModeBubbleController::OnBubbleAction();
88 }
89
90 virtual void OnBubbleDismiss() OVERRIDE {
91 ++dismiss_button_callback_count_;
92 DevModeBubbleController::OnBubbleDismiss();
93 }
94 virtual void OnLinkClicked() OVERRIDE {
95 ++link_click_callback_count_;
96 DevModeBubbleController::OnLinkClicked();
97 }
98 };
99
100 // A fake bubble used for testing the controller. Takes an action that specifies
101 // what should happen when the bubble is "shown" (the bubble is actually not
102 // shown, the corresponding action is taken immediately).
103 class FakeExtensionMessageBubble : public ExtensionMessageBubble {
104 public:
105 enum ExtensionBubbleAction {
106 BUBBLE_ACTION_CLICK_ACTION_BUTTON = 0,
107 BUBBLE_ACTION_CLICK_DISMISS_BUTTON,
108 BUBBLE_ACTION_CLICK_LINK
109 };
110
111 FakeExtensionMessageBubble() {}
112
113 void set_action_on_show(ExtensionBubbleAction action) {
114 action_ = action;
115 }
116
117 virtual void Show() OVERRIDE {
118 if (action_ == BUBBLE_ACTION_CLICK_ACTION_BUTTON)
119 action_callback_.Run();
120 else if (action_ == BUBBLE_ACTION_CLICK_DISMISS_BUTTON)
121 dismiss_callback_.Run();
122 else if (action_ == BUBBLE_ACTION_CLICK_LINK)
123 link_callback_.Run();
124 }
125
126 virtual void OnActionButtonClicked(const base::Closure& callback) OVERRIDE {
127 action_callback_ = callback;
128 }
129
130 virtual void OnDismissButtonClicked(const base::Closure& callback) OVERRIDE {
131 dismiss_callback_ = callback;
132 }
133
134 virtual void OnLinkClicked(const base::Closure& callback) OVERRIDE {
135 link_callback_ = callback;
136 }
137
138 private:
139 ExtensionBubbleAction action_;
140
141 base::Closure action_callback_;
142 base::Closure dismiss_callback_;
143 base::Closure link_callback_;
144 };
145
146 class ExtensionMessageBubbleTest : public testing::Test {
147 public:
148 ExtensionMessageBubbleTest() {
149 // The two lines of magical incantation required to get the extension
150 // service to work inside a unit test and access the extension prefs.
151 thread_bundle_.reset(new content::TestBrowserThreadBundle);
152 profile_.reset(new TestingProfile);
153
154 static_cast<TestExtensionSystem*>(
155 ExtensionSystem::Get(profile_.get()))->CreateExtensionService(
156 CommandLine::ForCurrentProcess(),
157 base::FilePath(),
158 false);
159 service_ = profile_->GetExtensionService();
160 service_->Init();
161
162 std::string basic_extension =
163 "{\"name\": \"Extension #\","
164 "\"version\": \"1.0\","
165 "\"manifest_version\": 2}";
166 std::string basic_extension_with_action =
167 "{\"name\": \"Extension #\","
168 "\"version\": \"1.0\","
169 "\"browser_action\": {"
170 " \"default_title\": \"Default title\""
171 "},"
172 "\"manifest_version\": 2}";
173
174 std::string extension_data;
175 ReplaceChars(basic_extension_with_action, "#", "1", &extension_data);
176 scoped_refptr<Extension> my_test_extension1(
177 CreateExtension(
178 Manifest::COMMAND_LINE,
179 extension_data,
180 "Autogenerated 1"));
181
182 ReplaceChars(basic_extension, "#", "2", &extension_data);
183 scoped_refptr<Extension> my_test_extension2(
184 CreateExtension(
185 Manifest::UNPACKED,
186 extension_data,
187 "Autogenerated 2"));
188
189 ReplaceChars(basic_extension, "#", "3", &extension_data);
190 scoped_refptr<Extension> regular_extension(
191 CreateExtension(
192 Manifest::EXTERNAL_POLICY,
193 extension_data,
194 "Autogenerated 3"));
195
196 extension_id1_ = my_test_extension1->id();
197 extension_id2_ = my_test_extension2->id();
198 extension_id3_ = regular_extension->id();
199
200 service_->AddExtension(regular_extension);
201 service_->AddExtension(my_test_extension1);
202 service_->AddExtension(my_test_extension2);
203 }
204 virtual ~ExtensionMessageBubbleTest() {}
205 virtual void SetUp() {
206 command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM));
207 }
208 scoped_ptr<CommandLine> command_line_;
209
210 protected:
211 scoped_refptr<Extension> CreateExtension(
212 Manifest::Location location,
213 const std::string& data,
214 const std::string& id) {
215 scoped_ptr<base::DictionaryValue> parsed_manifest(
216 extension_function_test_utils::ParseDictionary(data));
217 return extension_function_test_utils::CreateExtension(
218 location,
219 parsed_manifest.get(),
220 id);
221 }
222
223 scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_;
224 scoped_ptr<TestingProfile> profile_;
225 ExtensionService* service_;
226 std::string extension_id1_;
227 std::string extension_id2_;
228 std::string extension_id3_;
229
230 private:
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_SuspiciousExtensionControllerTest SuspiciousExtensionControllerTes t
237 #else
238 #define MAYBE_SuspiciousExtensionControllerTest DISABLED_SuspiciousExtensionCont rollerTest
239 #endif
240
241 TEST_F(ExtensionMessageBubbleTest, MAYBE_SuspiciousExtensionControllerTest) {
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<TestSuspiciousExtensionBubbleController> controller(
245 new TestSuspiciousExtensionBubbleController(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 TestSuspiciousExtensionBubbleController(profile_.get()));
268 EXPECT_TRUE(controller->HasExtensionList());
269 suspicious_extensions = controller->GetExtensionList();
270 ASSERT_EQ(1U, suspicious_extensions.size());
271 EXPECT_TRUE(ASCIIToUTF16("Extension 1") == suspicious_extensions[0]);
272 controller->Show(&bubble); // Simulate showing the bubble.
273 EXPECT_EQ(0U, controller->link_click_count());
274 EXPECT_EQ(1U, controller->dismiss_click_count());
275 // Now the acknowledge flag should be set only for the first extension.
276 EXPECT_TRUE(prefs->HasWipeoutBeenAcknowledged(extension_id1_));
277 EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id2_));
278 // Clear the flag.
279 prefs->SetWipeoutAcknowledged(extension_id1_, false);
280 EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id1_));
281
282 // Now disable the other extension and exercise the link click code path.
283 service_->DisableExtension(extension_id2_,
284 Extension::DISABLE_NOT_VERIFIED);
285
286 bubble.set_action_on_show(
287 FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_LINK);
288 controller.reset(new TestSuspiciousExtensionBubbleController(profile_.get()));
289 EXPECT_TRUE(controller->HasExtensionList());
290 suspicious_extensions = controller->GetExtensionList();
291 ASSERT_EQ(2U, suspicious_extensions.size());
292 EXPECT_TRUE(ASCIIToUTF16("Extension 1") == suspicious_extensions[1]);
293 EXPECT_TRUE(ASCIIToUTF16("Extension 2") == suspicious_extensions[0]);
294 controller->Show(&bubble); // Simulate showing the bubble.
295 EXPECT_EQ(1U, controller->link_click_count());
296 EXPECT_EQ(0U, controller->dismiss_click_count());
297 EXPECT_TRUE(prefs->HasWipeoutBeenAcknowledged(extension_id1_));
298 }
299
300 // The feature this is meant to test is only implemented on Windows.
301 #if defined(OS_WIN)
302 #define MAYBE_DevModeControllerTest DevModeControllerTest
303 #else
304 #define MAYBE_DevModeControllerTest DISABLED_DevModeControllerTest
305 #endif
306
307 TEST_F(ExtensionMessageBubbleTest, MAYBE_DevModeControllerTest) {
308 // The test base class adds three extensions, and we control two of them in
309 // this test (ids are: extension_id1_ and extension_id2_). Extension 1 is a
310 // regular extension, Extension 2 is UNPACKED so it counts as a DevMode
311 // extension.
312 scoped_ptr<TestDevModeBubbleController> controller(
313 new TestDevModeBubbleController(profile_.get()));
314
315 // Validate that we don't have a suppress value for the two extensions.
316 ExtensionPrefs* prefs = service_->extension_prefs();
317 EXPECT_FALSE(prefs->HasDevModeBeenAcknowledged(extension_id1_));
318 EXPECT_FALSE(prefs->HasDevModeBeenAcknowledged(extension_id2_));
319
320 // The list will contain one enabled unpacked extension.
321 EXPECT_TRUE(controller->HasExtensionList());
322 std::vector<string16> dev_mode_extensions = controller->GetExtensionList();
323 ASSERT_EQ(2U, dev_mode_extensions.size());
324 EXPECT_TRUE(ASCIIToUTF16("Extension 2") == dev_mode_extensions[0]);
325 EXPECT_TRUE(ASCIIToUTF16("Extension 1") == dev_mode_extensions[1]);
326 EXPECT_EQ(0U, controller->link_click_count());
327 EXPECT_EQ(0U, controller->dismiss_click_count());
328 EXPECT_EQ(0U, controller->action_click_count());
329
330 // Simulate showing the bubble.
331 FakeExtensionMessageBubble bubble;
332 bubble.set_action_on_show(
333 FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_DISMISS_BUTTON);
334 controller->Show(&bubble);
335 EXPECT_EQ(0U, controller->link_click_count());
336 EXPECT_EQ(0U, controller->action_click_count());
337 EXPECT_EQ(1U, controller->dismiss_click_count());
338 // The user dismissed, so we should have ack'ed the extension shown in bubble.
339 EXPECT_TRUE(prefs->HasDevModeBeenAcknowledged(extension_id1_));
340 EXPECT_TRUE(prefs->HasDevModeBeenAcknowledged(extension_id2_));
341 EXPECT_FALSE(prefs->HasDevModeBeenAcknowledged(extension_id3_));
342 EXPECT_TRUE(service_->GetExtensionById(extension_id1_, false) != NULL);
343 EXPECT_TRUE(service_->GetExtensionById(extension_id2_, false) != NULL);
344
345 // Clear the flags.
346 prefs->SetDevModeAcknowledged(extension_id1_, false);
347 prefs->SetDevModeAcknowledged(extension_id2_, false);
348
349 // Do it again, but now press different button (Disable).
350 bubble.set_action_on_show(
351 FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_ACTION_BUTTON);
352 controller.reset(new TestDevModeBubbleController(profile_.get()));
353 EXPECT_TRUE(controller->HasExtensionList());
354 dev_mode_extensions = controller->GetExtensionList();
355 EXPECT_EQ(2U, dev_mode_extensions.size());
356 controller->Show(&bubble); // Simulate showing the bubble.
357 EXPECT_EQ(0U, controller->link_click_count());
358 EXPECT_EQ(1U, controller->action_click_count());
359 EXPECT_EQ(0U, controller->dismiss_click_count());
360 // No extension should be acknowledged (since we want to warn again when they
361 // become re-enabled).
362 EXPECT_FALSE(prefs->HasDevModeBeenAcknowledged(extension_id1_));
363 EXPECT_FALSE(prefs->HasDevModeBeenAcknowledged(extension_id2_));
364 EXPECT_FALSE(prefs->HasDevModeBeenAcknowledged(extension_id3_));
365 EXPECT_TRUE(service_->GetExtensionById(extension_id1_, false) == NULL);
366 EXPECT_TRUE(service_->GetExtensionById(extension_id2_, false) == NULL);
367
368 // Re-enable the extensions (disabled by the action button above).
369 service_->EnableExtension(extension_id1_);
370 service_->EnableExtension(extension_id2_);
371
372 // Show the dialog a third time, but now press the learn more link.
373 bubble.set_action_on_show(
374 FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_LINK);
375 controller.reset(new TestDevModeBubbleController(profile_.get()));
376 EXPECT_TRUE(controller->HasExtensionList());
377 dev_mode_extensions = controller->GetExtensionList();
378 EXPECT_EQ(2U, dev_mode_extensions.size());
379 controller->Show(&bubble); // Simulate showing the bubble.
380 EXPECT_EQ(1U, controller->link_click_count());
381 EXPECT_EQ(0U, controller->action_click_count());
382 EXPECT_EQ(0U, controller->dismiss_click_count());
383 // No extension should be acknowledged (we should show the bubble again on
384 // next startup).
385 EXPECT_FALSE(prefs->HasDevModeBeenAcknowledged(extension_id1_));
386 EXPECT_FALSE(prefs->HasDevModeBeenAcknowledged(extension_id2_));
387 EXPECT_TRUE(service_->GetExtensionById(extension_id1_, false) != NULL);
388 EXPECT_TRUE(service_->GetExtensionById(extension_id2_, false) != NULL);
389
390 // Now disable the unpacked extension.
391 service_->DisableExtension(extension_id1_, Extension::DISABLE_USER_ACTION);
392 service_->DisableExtension(extension_id2_, Extension::DISABLE_USER_ACTION);
393
394 // We should find no extension and none should be acknowledged.
395 EXPECT_FALSE(prefs->HasDevModeBeenAcknowledged(extension_id1_));
396 EXPECT_FALSE(prefs->HasDevModeBeenAcknowledged(extension_id2_));
397
398 controller.reset(new TestDevModeBubbleController(profile_.get()));
399 EXPECT_FALSE(controller->HasExtensionList());
400 dev_mode_extensions = controller->GetExtensionList();
401 EXPECT_EQ(0U, dev_mode_extensions.size());
402 EXPECT_FALSE(prefs->HasDevModeBeenAcknowledged(extension_id2_));
403 }
404
405 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698