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

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

Issue 1527043002: [Extensions] Don't use ExtensionInstallPrompt subclasses for auto-confirmation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/crx_installer.h" 5 #include "chrome/browser/extensions/crx_installer.h"
6 6
7 #include "base/at_exit.h" 7 #include "base/at_exit.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/memory/ref_counted.h" 9 #include "base/memory/ref_counted.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
(...skipping 13 matching lines...) Expand all
24 #include "chrome/browser/ui/tabs/tab_strip_model.h" 24 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/common/web_application_info.h" 25 #include "chrome/common/web_application_info.h"
26 #include "chrome/grit/generated_resources.h" 26 #include "chrome/grit/generated_resources.h"
27 #include "chrome/test/base/ui_test_utils.h" 27 #include "chrome/test/base/ui_test_utils.h"
28 #include "content/public/browser/browser_thread.h" 28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/download_manager.h" 29 #include "content/public/browser/download_manager.h"
30 #include "content/public/browser/render_view_host.h" 30 #include "content/public/browser/render_view_host.h"
31 #include "content/public/test/browser_test_utils.h" 31 #include "content/public/test/browser_test_utils.h"
32 #include "content/public/test/download_test_observer.h" 32 #include "content/public/test/download_test_observer.h"
33 #include "content/public/test/test_utils.h" 33 #include "content/public/test/test_utils.h"
34 #include "extensions/browser/extension_dialog_auto_confirm.h"
34 #include "extensions/browser/extension_prefs.h" 35 #include "extensions/browser/extension_prefs.h"
35 #include "extensions/browser/extension_registry.h" 36 #include "extensions/browser/extension_registry.h"
36 #include "extensions/browser/extension_system.h" 37 #include "extensions/browser/extension_system.h"
37 #include "extensions/browser/install/crx_install_error.h" 38 #include "extensions/browser/install/crx_install_error.h"
38 #include "extensions/browser/management_policy.h" 39 #include "extensions/browser/management_policy.h"
39 #include "extensions/browser/notification_types.h" 40 #include "extensions/browser/notification_types.h"
40 #include "extensions/common/extension.h" 41 #include "extensions/common/extension.h"
41 #include "extensions/common/feature_switch.h" 42 #include "extensions/common/feature_switch.h"
42 #include "extensions/common/file_util.h" 43 #include "extensions/common/file_util.h"
43 #include "extensions/common/permissions/api_permission.h" 44 #include "extensions/common/permissions/api_permission.h"
(...skipping 23 matching lines...) Expand all
67 namespace extensions { 68 namespace extensions {
68 69
69 namespace { 70 namespace {
70 71
71 class MockInstallPrompt; 72 class MockInstallPrompt;
72 73
73 // This class holds information about things that happen with a 74 // This class holds information about things that happen with a
74 // MockInstallPrompt. We create the MockInstallPrompt but need to pass 75 // MockInstallPrompt. We create the MockInstallPrompt but need to pass
75 // ownership of it to CrxInstaller, so it isn't safe to hang this data on 76 // ownership of it to CrxInstaller, so it isn't safe to hang this data on
76 // MockInstallPrompt itself becuase we can't guarantee it's lifetime. 77 // MockInstallPrompt itself becuase we can't guarantee it's lifetime.
77 class MockPromptProxy : public base::RefCountedThreadSafe<MockPromptProxy> { 78 class MockPromptProxy {
78 public: 79 public:
79 explicit MockPromptProxy(content::WebContents* web_contents); 80 explicit MockPromptProxy(content::WebContents* web_contents);
81 ~MockPromptProxy();
80 82
81 bool did_succeed() const { return !extension_id_.empty(); } 83 bool did_succeed() const { return !extension_id_.empty(); }
82 const std::string& extension_id() { return extension_id_; } 84 const std::string& extension_id() { return extension_id_; }
83 bool confirmation_requested() const { return confirmation_requested_; } 85 bool confirmation_requested() const { return confirmation_requested_; }
84 const base::string16& error() const { return error_; } 86 const base::string16& error() const { return error_; }
85 87
86 void set_extension_id(const std::string& id) { extension_id_ = id; } 88 void set_extension_id(const std::string& id) { extension_id_ = id; }
87 void set_confirmation_requested() { confirmation_requested_ = true; } 89 void set_confirmation_requested(bool requested) {
90 confirmation_requested_ = requested;
91 }
88 void set_error(const base::string16& error) { error_ = error; } 92 void set_error(const base::string16& error) { error_ = error; }
89 93
90 scoped_ptr<ExtensionInstallPrompt> CreatePrompt(); 94 scoped_ptr<ExtensionInstallPrompt> CreatePrompt();
91 95
92 private: 96 private:
93 friend class base::RefCountedThreadSafe<MockPromptProxy>;
94 virtual ~MockPromptProxy();
95 97
96 // Data used to create a prompt. 98 // Data used to create a prompt.
97 content::WebContents* web_contents_; 99 content::WebContents* web_contents_;
98 100
99 // Data reported back to us by the prompt we created. 101 // Data reported back to us by the prompt we created.
100 bool confirmation_requested_; 102 bool confirmation_requested_;
101 std::string extension_id_; 103 std::string extension_id_;
102 base::string16 error_; 104 base::string16 error_;
105
106 scoped_ptr<ScopedTestDialogAutoConfirm> auto_confirm;
107
108 DISALLOW_COPY_AND_ASSIGN(MockPromptProxy);
103 }; 109 };
104 110
105 SkBitmap CreateSquareBitmap(int size) { 111 SkBitmap CreateSquareBitmap(int size) {
106 SkBitmap bitmap; 112 SkBitmap bitmap;
107 bitmap.allocN32Pixels(size, size); 113 bitmap.allocN32Pixels(size, size);
108 bitmap.eraseColor(SK_ColorRED); 114 bitmap.eraseColor(SK_ColorRED);
109 return bitmap; 115 return bitmap;
110 } 116 }
111 117
112 WebApplicationInfo::IconInfo CreateIconInfoWithBitmap(int size) { 118 WebApplicationInfo::IconInfo CreateIconInfoWithBitmap(int size) {
(...skipping 19 matching lines...) Expand all
132 } 138 }
133 139
134 class MockInstallPrompt : public ExtensionInstallPrompt { 140 class MockInstallPrompt : public ExtensionInstallPrompt {
135 public: 141 public:
136 MockInstallPrompt(content::WebContents* web_contents, 142 MockInstallPrompt(content::WebContents* web_contents,
137 MockPromptProxy* proxy) : 143 MockPromptProxy* proxy) :
138 ExtensionInstallPrompt(web_contents), 144 ExtensionInstallPrompt(web_contents),
139 proxy_(proxy) {} 145 proxy_(proxy) {}
140 146
141 // Overriding some of the ExtensionInstallUI API. 147 // Overriding some of the ExtensionInstallUI API.
142 void ShowDialog(Delegate* delegate,
143 const Extension* extension,
144 const SkBitmap* bitmap,
145 const ShowDialogCallback& show_dialog_callback) override {
146 proxy_->set_confirmation_requested();
147 delegate->InstallUIProceed();
148 }
149 void OnInstallSuccess(const Extension* extension, SkBitmap* icon) override { 148 void OnInstallSuccess(const Extension* extension, SkBitmap* icon) override {
150 proxy_->set_extension_id(extension->id()); 149 proxy_->set_extension_id(extension->id());
150 proxy_->set_confirmation_requested(did_call_show_dialog());
151 base::MessageLoopForUI::current()->QuitWhenIdle(); 151 base::MessageLoopForUI::current()->QuitWhenIdle();
152 } 152 }
153 void OnInstallFailure(const CrxInstallError& error) override { 153 void OnInstallFailure(const CrxInstallError& error) override {
154 proxy_->set_error(error.message()); 154 proxy_->set_error(error.message());
155 proxy_->set_confirmation_requested(did_call_show_dialog());
155 base::MessageLoopForUI::current()->QuitWhenIdle(); 156 base::MessageLoopForUI::current()->QuitWhenIdle();
156 } 157 }
157 158
158 private: 159 private:
159 scoped_refptr<MockPromptProxy> proxy_; 160 MockPromptProxy* proxy_;
161
162 DISALLOW_COPY_AND_ASSIGN(MockInstallPrompt);
160 }; 163 };
161 164
162 MockPromptProxy::MockPromptProxy(content::WebContents* web_contents) 165 MockPromptProxy::MockPromptProxy(content::WebContents* web_contents)
163 : web_contents_(web_contents), confirmation_requested_(false) { 166 : web_contents_(web_contents),
167 confirmation_requested_(false),
168 auto_confirm(new ScopedTestDialogAutoConfirm(
169 ScopedTestDialogAutoConfirm::ACCEPT)) {
164 } 170 }
165 171
166 MockPromptProxy::~MockPromptProxy() {} 172 MockPromptProxy::~MockPromptProxy() {}
167 173
168 scoped_ptr<ExtensionInstallPrompt> MockPromptProxy::CreatePrompt() { 174 scoped_ptr<ExtensionInstallPrompt> MockPromptProxy::CreatePrompt() {
169 return scoped_ptr<MockInstallPrompt>( 175 return scoped_ptr<MockInstallPrompt>(
170 new MockInstallPrompt(web_contents_, this)); 176 new MockInstallPrompt(web_contents_, this));
171 } 177 }
172 178
173 179
174 scoped_refptr<MockPromptProxy> CreateMockPromptProxyForBrowser( 180 scoped_ptr<MockPromptProxy> CreateMockPromptProxyForBrowser(
175 Browser* browser) { 181 Browser* browser) {
176 return new MockPromptProxy( 182 return make_scoped_ptr(new MockPromptProxy(
177 browser->tab_strip_model()->GetActiveWebContents()); 183 browser->tab_strip_model()->GetActiveWebContents()));
178 } 184 }
179 185
180 class ManagementPolicyMock : public extensions::ManagementPolicy::Provider { 186 class ManagementPolicyMock : public extensions::ManagementPolicy::Provider {
181 public: 187 public:
182 ManagementPolicyMock() {} 188 ManagementPolicyMock() {}
183 189
184 std::string GetDebugPolicyProviderName() const override { 190 std::string GetDebugPolicyProviderName() const override {
185 return "ManagementPolicyMock"; 191 return "ManagementPolicyMock";
186 } 192 }
187 193
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 installer->set_allow_silent_install(true); 250 installer->set_allow_silent_install(true);
245 installer->set_is_gallery_install(true); 251 installer->set_is_gallery_install(true);
246 installer->InstallCrx(crx_path); 252 installer->InstallCrx(crx_path);
247 content::RunMessageLoop(); 253 content::RunMessageLoop();
248 } 254 }
249 255
250 // Installs a crx from |crx_relpath| (a path relative to the extension test 256 // Installs a crx from |crx_relpath| (a path relative to the extension test
251 // data dir) with expected id |id|. 257 // data dir) with expected id |id|.
252 void InstallWithPrompt(const char* ext_relpath, 258 void InstallWithPrompt(const char* ext_relpath,
253 const std::string& id, 259 const std::string& id,
254 scoped_refptr<MockPromptProxy> mock_install_prompt) { 260 MockPromptProxy* mock_install_prompt) {
255 base::FilePath ext_path = test_data_dir_.AppendASCII(ext_relpath); 261 base::FilePath ext_path = test_data_dir_.AppendASCII(ext_relpath);
256 262
257 scoped_ptr<WebstoreInstaller::Approval> approval; 263 scoped_ptr<WebstoreInstaller::Approval> approval;
258 if (!id.empty()) 264 if (!id.empty())
259 approval = GetApproval(ext_relpath, id, true); 265 approval = GetApproval(ext_relpath, id, true);
260 266
261 base::FilePath crx_path = PackExtension(ext_path); 267 base::FilePath crx_path = PackExtension(ext_path);
262 EXPECT_FALSE(crx_path.empty()); 268 EXPECT_FALSE(crx_path.empty());
263 RunCrxInstaller(approval.get(), mock_install_prompt->CreatePrompt(), 269 RunCrxInstaller(approval.get(), mock_install_prompt->CreatePrompt(),
264 crx_path); 270 crx_path);
265 271
266 EXPECT_TRUE(mock_install_prompt->did_succeed()); 272 EXPECT_TRUE(mock_install_prompt->did_succeed());
267 } 273 }
268 274
269 // Installs an extension and checks that it has scopes granted IFF 275 // Installs an extension and checks that it has scopes granted IFF
270 // |record_oauth2_grant| is true. 276 // |record_oauth2_grant| is true.
271 void CheckHasEmptyScopesAfterInstall(const std::string& ext_relpath, 277 void CheckHasEmptyScopesAfterInstall(const std::string& ext_relpath,
272 bool record_oauth2_grant) { 278 bool record_oauth2_grant) {
273 ScopedExperimentalCommandLine scope; 279 ScopedExperimentalCommandLine scope;
274 280
275 scoped_refptr<MockPromptProxy> mock_prompt = 281 scoped_ptr<MockPromptProxy> mock_prompt =
276 CreateMockPromptProxyForBrowser(browser()); 282 CreateMockPromptProxyForBrowser(browser());
277 283
278 InstallWithPrompt("browsertest/scopes", std::string(), mock_prompt); 284 InstallWithPrompt("browsertest/scopes", std::string(), mock_prompt.get());
279 285
280 scoped_ptr<const PermissionSet> permissions = 286 scoped_ptr<const PermissionSet> permissions =
281 ExtensionPrefs::Get(browser()->profile()) 287 ExtensionPrefs::Get(browser()->profile())
282 ->GetGrantedPermissions(mock_prompt->extension_id()); 288 ->GetGrantedPermissions(mock_prompt->extension_id());
283 ASSERT_TRUE(permissions.get()); 289 ASSERT_TRUE(permissions.get());
284 } 290 }
285 291
286 // Returns a FilePath to an unpacked "experimental" extension (a test 292 // Returns a FilePath to an unpacked "experimental" extension (a test
287 // Extension which requests the "experimental" permission). 293 // Extension which requests the "experimental" permission).
288 base::FilePath PackExperimentalExtension() { 294 base::FilePath PackExperimentalExtension() {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 327
322 // This test is skipped on ChromeOS because it requires the NPAPI, 328 // This test is skipped on ChromeOS because it requires the NPAPI,
323 // which is not available on that platform. 329 // which is not available on that platform.
324 #if !defined(OS_CHROMEOS) 330 #if !defined(OS_CHROMEOS)
325 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, Whitelisting) { 331 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, Whitelisting) {
326 std::string id = "hdgllgikmikobbofgnabhfimcfoopgnd"; 332 std::string id = "hdgllgikmikobbofgnabhfimcfoopgnd";
327 ExtensionRegistry* registry = ExtensionRegistry::Get( 333 ExtensionRegistry* registry = ExtensionRegistry::Get(
328 browser()->profile()); 334 browser()->profile());
329 335
330 // Even whitelisted extensions with NPAPI should not prompt. 336 // Even whitelisted extensions with NPAPI should not prompt.
331 scoped_refptr<MockPromptProxy> mock_prompt = 337 scoped_ptr<MockPromptProxy> mock_prompt =
332 CreateMockPromptProxyForBrowser(browser()); 338 CreateMockPromptProxyForBrowser(browser());
333 InstallWithPrompt("uitest/plugins", id, mock_prompt); 339 InstallWithPrompt("uitest/plugins", id, mock_prompt.get());
334 EXPECT_FALSE(mock_prompt->confirmation_requested()); 340 EXPECT_FALSE(mock_prompt->confirmation_requested());
335 EXPECT_TRUE(registry->enabled_extensions().GetByID(id)); 341 EXPECT_TRUE(registry->enabled_extensions().GetByID(id));
336 } 342 }
337 #endif 343 #endif
338 344
339 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, 345 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest,
340 ExperimentalExtensionFromGallery) { 346 ExperimentalExtensionFromGallery) {
341 // Gallery-installed extensions should have their experimental permission 347 // Gallery-installed extensions should have their experimental permission
342 // preserved, since we allow the Webstore to make that decision. 348 // preserved, since we allow the Webstore to make that decision.
343 base::FilePath crx_path = PackExperimentalExtension(); 349 base::FilePath crx_path = PackExperimentalExtension();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 388
383 const int kNumDownloadsExpected = 1; 389 const int kNumDownloadsExpected = 1;
384 390
385 LOG(ERROR) << "PackAndInstallExtension: Packing extension"; 391 LOG(ERROR) << "PackAndInstallExtension: Packing extension";
386 base::FilePath crx_path = PackExtension( 392 base::FilePath crx_path = PackExtension(
387 test_data_dir_.AppendASCII("common/background_page")); 393 test_data_dir_.AppendASCII("common/background_page"));
388 ASSERT_FALSE(crx_path.empty()); 394 ASSERT_FALSE(crx_path.empty());
389 std::string crx_path_string(crx_path.value().begin(), crx_path.value().end()); 395 std::string crx_path_string(crx_path.value().begin(), crx_path.value().end());
390 GURL url = GURL(std::string("file:///").append(crx_path_string)); 396 GURL url = GURL(std::string("file:///").append(crx_path_string));
391 397
392 scoped_refptr<MockPromptProxy> mock_prompt = 398 scoped_ptr<MockPromptProxy> mock_prompt =
393 CreateMockPromptProxyForBrowser(browser()); 399 CreateMockPromptProxyForBrowser(browser());
394 download_crx_util::SetMockInstallPromptForTesting( 400 download_crx_util::SetMockInstallPromptForTesting(
395 mock_prompt->CreatePrompt()); 401 mock_prompt->CreatePrompt());
396 402
397 LOG(ERROR) << "PackAndInstallExtension: Getting download manager"; 403 LOG(ERROR) << "PackAndInstallExtension: Getting download manager";
398 content::DownloadManager* download_manager = 404 content::DownloadManager* download_manager =
399 content::BrowserContext::GetDownloadManager(browser()->profile()); 405 content::BrowserContext::GetDownloadManager(browser()->profile());
400 406
401 LOG(ERROR) << "PackAndInstallExtension: Setting observer"; 407 LOG(ERROR) << "PackAndInstallExtension: Setting observer";
402 scoped_ptr<content::DownloadTestObserver> observer( 408 scoped_ptr<content::DownloadTestObserver> observer(
(...skipping 26 matching lines...) Expand all
429 EXPECT_NO_FATAL_FAILURE(CheckHasEmptyScopesAfterInstall("browsertest/scopes", 435 EXPECT_NO_FATAL_FAILURE(CheckHasEmptyScopesAfterInstall("browsertest/scopes",
430 false)); 436 false));
431 } 437 }
432 438
433 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, AllowOffStore) { 439 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, AllowOffStore) {
434 ExtensionService* service = extensions::ExtensionSystem::Get( 440 ExtensionService* service = extensions::ExtensionSystem::Get(
435 browser()->profile())->extension_service(); 441 browser()->profile())->extension_service();
436 const bool kTestData[] = {false, true}; 442 const bool kTestData[] = {false, true};
437 443
438 for (size_t i = 0; i < arraysize(kTestData); ++i) { 444 for (size_t i = 0; i < arraysize(kTestData); ++i) {
439 scoped_refptr<MockPromptProxy> mock_prompt = 445 scoped_ptr<MockPromptProxy> mock_prompt =
440 CreateMockPromptProxyForBrowser(browser()); 446 CreateMockPromptProxyForBrowser(browser());
441 447
442 scoped_refptr<CrxInstaller> crx_installer( 448 scoped_refptr<CrxInstaller> crx_installer(
443 CrxInstaller::Create(service, mock_prompt->CreatePrompt())); 449 CrxInstaller::Create(service, mock_prompt->CreatePrompt()));
444 crx_installer->set_install_cause( 450 crx_installer->set_install_cause(
445 extension_misc::INSTALL_CAUSE_USER_DOWNLOAD); 451 extension_misc::INSTALL_CAUSE_USER_DOWNLOAD);
446 452
447 if (kTestData[i]) { 453 if (kTestData[i]) {
448 crx_installer->set_off_store_install_allow_reason( 454 crx_installer->set_off_store_install_allow_reason(
449 CrxInstaller::OffStoreInstallAllowedInTest); 455 CrxInstaller::OffStoreInstallAllowedInTest);
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 559
554 blacklist_db->SetUnsafe("gllekhaobjnhgeagipipnkpmmmpchacm"); 560 blacklist_db->SetUnsafe("gllekhaobjnhgeagipipnkpmmmpchacm");
555 561
556 base::FilePath crx_path = test_data_dir_.AppendASCII("theme_hidpi_crx") 562 base::FilePath crx_path = test_data_dir_.AppendASCII("theme_hidpi_crx")
557 .AppendASCII("theme_hidpi.crx"); 563 .AppendASCII("theme_hidpi.crx");
558 EXPECT_FALSE(InstallExtension(crx_path, 0)); 564 EXPECT_FALSE(InstallExtension(crx_path, 0));
559 } 565 }
560 #endif 566 #endif
561 567
562 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, NonStrictManifestCheck) { 568 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, NonStrictManifestCheck) {
563 scoped_refptr<MockPromptProxy> mock_prompt = 569 scoped_ptr<MockPromptProxy> mock_prompt =
564 CreateMockPromptProxyForBrowser(browser()); 570 CreateMockPromptProxyForBrowser(browser());
565 571
566 // We want to simulate the case where the webstore sends a more recent 572 // We want to simulate the case where the webstore sends a more recent
567 // version of the manifest, but the downloaded .crx file is old since 573 // version of the manifest, but the downloaded .crx file is old since
568 // the newly published version hasn't fully propagated to all the download 574 // the newly published version hasn't fully propagated to all the download
569 // servers yet. So load the v2 manifest, but then install the v1 crx file. 575 // servers yet. So load the v2 manifest, but then install the v1 crx file.
570 std::string id = "lhnaeclnpobnlbjbgogdanmhadigfnjp"; 576 std::string id = "lhnaeclnpobnlbjbgogdanmhadigfnjp";
571 scoped_ptr<WebstoreInstaller::Approval> approval = 577 scoped_ptr<WebstoreInstaller::Approval> approval =
572 GetApproval("crx_installer/v2_no_permission_change/", id, false); 578 GetApproval("crx_installer/v2_no_permission_change/", id, false);
573 579
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 // these checks (see https://crbug.com/545541). 666 // these checks (see https://crbug.com/545541).
661 ManagementPolicyMock policy; 667 ManagementPolicyMock policy;
662 extensions::ExtensionSystem::Get(profile()) 668 extensions::ExtensionSystem::Get(profile())
663 ->management_policy() 669 ->management_policy()
664 ->RegisterProvider(&policy); 670 ->RegisterProvider(&policy);
665 671
666 InstallWebAppAndVerifyNoErrors(); 672 InstallWebAppAndVerifyNoErrors();
667 } 673 }
668 674
669 } // namespace extensions 675 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/download/download_browsertest.cc ('k') | chrome/browser/extensions/extension_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698