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

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

Issue 2751013002: Simplify ExtensionInstallChecker into a single-use class (Closed)
Patch Set: todo Created 3 years, 9 months 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 <map> 7 #include <map>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h" 13 #include "base/files/scoped_temp_dir.h"
14 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
15 #include "base/macros.h" 15 #include "base/macros.h"
16 #include "base/memory/ptr_util.h" 16 #include "base/memory/ptr_util.h"
17 #include "base/metrics/histogram_macros.h" 17 #include "base/metrics/histogram_macros.h"
18 #include "base/sequenced_task_runner.h" 18 #include "base/sequenced_task_runner.h"
19 #include "base/strings/string_util.h" 19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h" 20 #include "base/strings/utf_string_conversions.h"
21 #include "base/threading/sequenced_worker_pool.h" 21 #include "base/threading/sequenced_worker_pool.h"
22 #include "base/threading/thread_restrictions.h" 22 #include "base/threading/thread_restrictions.h"
23 #include "base/time/time.h" 23 #include "base/time/time.h"
24 #include "base/version.h" 24 #include "base/version.h"
25 #include "build/build_config.h" 25 #include "build/build_config.h"
26 #include "chrome/browser/extensions/convert_user_script.h" 26 #include "chrome/browser/extensions/convert_user_script.h"
27 #include "chrome/browser/extensions/convert_web_app.h" 27 #include "chrome/browser/extensions/convert_web_app.h"
28 #include "chrome/browser/extensions/extension_assets_manager.h" 28 #include "chrome/browser/extensions/extension_assets_manager.h"
29 #include "chrome/browser/extensions/extension_error_reporter.h" 29 #include "chrome/browser/extensions/extension_error_reporter.h"
30 #include "chrome/browser/extensions/extension_install_checker.h"
30 #include "chrome/browser/extensions/extension_service.h" 31 #include "chrome/browser/extensions/extension_service.h"
31 #include "chrome/browser/extensions/install_tracker.h" 32 #include "chrome/browser/extensions/install_tracker.h"
32 #include "chrome/browser/extensions/install_tracker_factory.h" 33 #include "chrome/browser/extensions/install_tracker_factory.h"
33 #include "chrome/browser/extensions/permissions_updater.h" 34 #include "chrome/browser/extensions/permissions_updater.h"
34 #include "chrome/browser/extensions/webstore_installer.h" 35 #include "chrome/browser/extensions/webstore_installer.h"
35 #include "chrome/browser/profiles/profile.h" 36 #include "chrome/browser/profiles/profile.h"
36 #include "chrome/browser/web_applications/web_app.h" 37 #include "chrome/browser/web_applications/web_app.h"
37 #include "chrome/common/chrome_paths.h" 38 #include "chrome/common/chrome_paths.h"
38 #include "chrome/common/extensions/extension_constants.h" 39 #include "chrome/common/extensions/extension_constants.h"
39 #include "chrome/grit/generated_resources.h" 40 #include "chrome/grit/generated_resources.h"
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 scoped_refptr<CrxInstaller> CrxInstaller::Create( 102 scoped_refptr<CrxInstaller> CrxInstaller::Create(
102 ExtensionService* service, 103 ExtensionService* service,
103 std::unique_ptr<ExtensionInstallPrompt> client, 104 std::unique_ptr<ExtensionInstallPrompt> client,
104 const WebstoreInstaller::Approval* approval) { 105 const WebstoreInstaller::Approval* approval) {
105 return new CrxInstaller(service->AsWeakPtr(), std::move(client), approval); 106 return new CrxInstaller(service->AsWeakPtr(), std::move(client), approval);
106 } 107 }
107 108
108 CrxInstaller::CrxInstaller(base::WeakPtr<ExtensionService> service_weak, 109 CrxInstaller::CrxInstaller(base::WeakPtr<ExtensionService> service_weak,
109 std::unique_ptr<ExtensionInstallPrompt> client, 110 std::unique_ptr<ExtensionInstallPrompt> client,
110 const WebstoreInstaller::Approval* approval) 111 const WebstoreInstaller::Approval* approval)
111 : install_directory_(service_weak->install_directory()), 112 : profile_(service_weak->profile()),
113 install_directory_(service_weak->install_directory()),
112 install_source_(Manifest::INTERNAL), 114 install_source_(Manifest::INTERNAL),
113 approved_(false), 115 approved_(false),
114 hash_check_failed_(false), 116 hash_check_failed_(false),
115 expected_manifest_check_level_( 117 expected_manifest_check_level_(
116 WebstoreInstaller::MANIFEST_CHECK_LEVEL_STRICT), 118 WebstoreInstaller::MANIFEST_CHECK_LEVEL_STRICT),
117 fail_install_if_unexpected_version_(false), 119 fail_install_if_unexpected_version_(false),
118 extensions_enabled_(service_weak->extensions_enabled()), 120 extensions_enabled_(service_weak->extensions_enabled()),
119 delete_source_(false), 121 delete_source_(false),
120 create_app_shortcut_(false), 122 create_app_shortcut_(false),
121 service_weak_(service_weak), 123 service_weak_(service_weak),
122 // See header file comment on |client_| for why we use a raw pointer here. 124 // See header file comment on |client_| for why we use a raw pointer here.
123 client_(client.release()), 125 client_(client.release()),
124 apps_require_extension_mime_type_(false), 126 apps_require_extension_mime_type_(false),
125 allow_silent_install_(false), 127 allow_silent_install_(false),
126 grant_permissions_(true), 128 grant_permissions_(true),
127 install_cause_(extension_misc::INSTALL_CAUSE_UNSET), 129 install_cause_(extension_misc::INSTALL_CAUSE_UNSET),
128 creation_flags_(Extension::NO_FLAGS), 130 creation_flags_(Extension::NO_FLAGS),
129 off_store_install_allow_reason_(OffStoreInstallDisallowed), 131 off_store_install_allow_reason_(OffStoreInstallDisallowed),
130 did_handle_successfully_(true), 132 did_handle_successfully_(true),
131 error_on_unsupported_requirements_(false), 133 error_on_unsupported_requirements_(false),
132 update_from_settings_page_(false), 134 update_from_settings_page_(false),
133 install_flags_(kInstallFlagNone), 135 install_flags_(kInstallFlagNone) {
134 install_checker_(service_weak->profile()) {
135 installer_task_runner_ = service_weak->GetFileTaskRunner(); 136 installer_task_runner_ = service_weak->GetFileTaskRunner();
136 if (!approval) 137 if (!approval)
137 return; 138 return;
138 139
139 CHECK(profile()->IsSameProfile(approval->profile)); 140 CHECK(profile()->IsSameProfile(approval->profile));
140 if (client_) { 141 if (client_) {
141 client_->install_ui()->SetUseAppInstalledBubble( 142 client_->install_ui()->SetUseAppInstalledBubble(
142 approval->use_app_installed_bubble); 143 approval->use_app_installed_bubble);
143 client_->install_ui()->SetSkipPostInstallUI(approval->skip_post_install_ui); 144 client_->install_ui()->SetSkipPostInstallUI(approval->skip_post_install_ui);
144 } 145 }
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 // manually if they want. 349 // manually if they want.
349 delete_source_ = false; 350 delete_source_ = false;
350 did_handle_successfully_ = false; 351 did_handle_successfully_ = false;
351 352
352 return CrxInstallError( 353 return CrxInstallError(
353 CrxInstallError::ERROR_OFF_STORE, 354 CrxInstallError::ERROR_OFF_STORE,
354 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE)); 355 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE));
355 } 356 }
356 } 357 }
357 358
358 if (install_checker_.extension()->is_app()) { 359 if (extension_->is_app()) {
359 // If the app was downloaded, apps_require_extension_mime_type_ 360 // If the app was downloaded, apps_require_extension_mime_type_
360 // will be set. In this case, check that it was served with the 361 // will be set. In this case, check that it was served with the
361 // right mime type. Make an exception for file URLs, which come 362 // right mime type. Make an exception for file URLs, which come
362 // from the users computer and have no headers. 363 // from the users computer and have no headers.
363 if (!download_url_.SchemeIsFile() && 364 if (!download_url_.SchemeIsFile() &&
364 apps_require_extension_mime_type_ && 365 apps_require_extension_mime_type_ &&
365 original_mime_type_ != Extension::kMimeType) { 366 original_mime_type_ != Extension::kMimeType) {
366 return CrxInstallError(l10n_util::GetStringFUTF16( 367 return CrxInstallError(l10n_util::GetStringFUTF16(
367 IDS_EXTENSION_INSTALL_INCORRECT_APP_CONTENT_TYPE, 368 IDS_EXTENSION_INSTALL_INCORRECT_APP_CONTENT_TYPE,
368 base::ASCIIToUTF16(Extension::kMimeType))); 369 base::ASCIIToUTF16(Extension::kMimeType)));
(...skipping 12 matching lines...) Expand all
381 l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE))); 382 l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE)));
382 } 383 }
383 384
384 // For self-hosted apps, verify that the entire extent is on the same 385 // For self-hosted apps, verify that the entire extent is on the same
385 // host (or a subdomain of the host) the download happened from. There's 386 // host (or a subdomain of the host) the download happened from. There's
386 // no way for us to verify that the app controls any other hosts. 387 // no way for us to verify that the app controls any other hosts.
387 URLPattern pattern(UserScript::ValidUserScriptSchemes()); 388 URLPattern pattern(UserScript::ValidUserScriptSchemes());
388 pattern.SetHost(download_url_.host()); 389 pattern.SetHost(download_url_.host());
389 pattern.SetMatchSubdomains(true); 390 pattern.SetMatchSubdomains(true);
390 391
391 URLPatternSet patterns = install_checker_.extension()->web_extent(); 392 URLPatternSet patterns = extension_->web_extent();
392 for (URLPatternSet::const_iterator i = patterns.begin(); 393 for (URLPatternSet::const_iterator i = patterns.begin();
393 i != patterns.end(); ++i) { 394 i != patterns.end(); ++i) {
394 if (!pattern.MatchesHost(i->host())) { 395 if (!pattern.MatchesHost(i->host())) {
395 return CrxInstallError(l10n_util::GetStringUTF16( 396 return CrxInstallError(l10n_util::GetStringUTF16(
396 IDS_EXTENSION_INSTALL_INCORRECT_INSTALL_HOST)); 397 IDS_EXTENSION_INSTALL_INCORRECT_INSTALL_HOST));
397 } 398 }
398 } 399 }
399 } 400 }
400 } 401 }
401 402
(...skipping 22 matching lines...) Expand all
424 DCHECK(installer_task_runner_->RunsTasksOnCurrentThread()); 425 DCHECK(installer_task_runner_->RunsTasksOnCurrentThread());
425 426
426 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallSource", 427 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallSource",
427 install_source(), Manifest::NUM_LOCATIONS); 428 install_source(), Manifest::NUM_LOCATIONS);
428 429
429 430
430 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallCause", 431 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallCause",
431 install_cause(), 432 install_cause(),
432 extension_misc::NUM_INSTALL_CAUSES); 433 extension_misc::NUM_INSTALL_CAUSES);
433 434
434 install_checker_.set_extension(extension); 435 extension_ = extension;
435 temp_dir_ = temp_dir; 436 temp_dir_ = temp_dir;
436 if (!install_icon.empty()) 437 if (!install_icon.empty())
437 install_icon_.reset(new SkBitmap(install_icon)); 438 install_icon_.reset(new SkBitmap(install_icon));
438 439
439 if (original_manifest) 440 if (original_manifest)
440 original_manifest_.reset(new Manifest( 441 original_manifest_.reset(new Manifest(
441 Manifest::INVALID_LOCATION, 442 Manifest::INVALID_LOCATION,
442 std::unique_ptr<base::DictionaryValue>(original_manifest->DeepCopy()))); 443 std::unique_ptr<base::DictionaryValue>(original_manifest->DeepCopy())));
443 444
444 // We don't have to delete the unpack dir explicity since it is a child of 445 // We don't have to delete the unpack dir explicity since it is a child of
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 base::UTF8ToUTF16(extension()->name()), 504 base::UTF8ToUTF16(extension()->name()),
504 base::UTF8ToUTF16(imported_module->name())))); 505 base::UTF8ToUTF16(imported_module->name()))));
505 return; 506 return;
506 } 507 }
507 } 508 }
508 } 509 }
509 510
510 // Run the policy, requirements and blacklist checks in parallel. Skip the 511 // Run the policy, requirements and blacklist checks in parallel. Skip the
511 // checks if the extension is a bookmark app. 512 // checks if the extension is a bookmark app.
512 if (extension()->from_bookmark()) { 513 if (extension()->from_bookmark()) {
513 CrxInstaller::OnInstallChecksComplete(0); 514 ConfirmInstall();
514 } else { 515 } else {
515 install_checker_.Start( 516 install_checker_ = base::MakeUnique<ExtensionInstallChecker>(
516 ExtensionInstallChecker::CHECK_ALL, 517 profile_, extension_, ExtensionInstallChecker::CHECK_ALL,
517 false /* fail fast */, 518 false /* fail fast */);
519 install_checker_->Start(
518 base::Bind(&CrxInstaller::OnInstallChecksComplete, this)); 520 base::Bind(&CrxInstaller::OnInstallChecksComplete, this));
519 } 521 }
520 } 522 }
521 523
522 void CrxInstaller::OnInstallChecksComplete(int failed_checks) { 524 void CrxInstaller::OnInstallChecksComplete(int failed_checks) {
523 DCHECK_CURRENTLY_ON(BrowserThread::UI); 525 DCHECK_CURRENTLY_ON(BrowserThread::UI);
524 if (!service_weak_) 526 if (!service_weak_)
525 return; 527 return;
526 528
527 // Check for requirement errors. 529 // Check for requirement errors.
528 if (!install_checker_.requirement_errors().empty()) { 530 if (!install_checker_->requirement_errors().empty()) {
529 if (error_on_unsupported_requirements_) { 531 if (error_on_unsupported_requirements_) {
530 ReportFailureFromUIThread( 532 ReportFailureFromUIThread(
531 CrxInstallError(CrxInstallError::ERROR_DECLINED, 533 CrxInstallError(CrxInstallError::ERROR_DECLINED,
532 base::UTF8ToUTF16(base::JoinString( 534 base::UTF8ToUTF16(base::JoinString(
533 install_checker_.requirement_errors(), " ")))); 535 install_checker_->requirement_errors(), " "))));
534 return; 536 return;
535 } 537 }
536 install_flags_ |= kInstallFlagHasRequirementErrors; 538 install_flags_ |= kInstallFlagHasRequirementErrors;
537 } 539 }
538 540
539 // Check the blacklist state. 541 // Check the blacklist state.
540 if (install_checker_.blacklist_state() == BLACKLISTED_MALWARE) { 542 if (install_checker_->blacklist_state() == BLACKLISTED_MALWARE) {
541 install_flags_ |= kInstallFlagIsBlacklistedForMalware; 543 install_flags_ |= kInstallFlagIsBlacklistedForMalware;
542 } 544 }
543 545
544 if ((install_checker_.blacklist_state() == BLACKLISTED_MALWARE || 546 if ((install_checker_->blacklist_state() == BLACKLISTED_MALWARE ||
545 install_checker_.blacklist_state() == BLACKLISTED_UNKNOWN) && 547 install_checker_->blacklist_state() == BLACKLISTED_UNKNOWN) &&
546 !allow_silent_install_) { 548 !allow_silent_install_) {
547 // User tried to install a blacklisted extension. Show an error and 549 // User tried to install a blacklisted extension. Show an error and
548 // refuse to install it. 550 // refuse to install it.
549 ReportFailureFromUIThread(CrxInstallError( 551 ReportFailureFromUIThread(CrxInstallError(
550 CrxInstallError::ERROR_DECLINED, 552 CrxInstallError::ERROR_DECLINED,
551 l10n_util::GetStringFUTF16(IDS_EXTENSION_IS_BLACKLISTED, 553 l10n_util::GetStringFUTF16(IDS_EXTENSION_IS_BLACKLISTED,
552 base::UTF8ToUTF16(extension()->name())))); 554 base::UTF8ToUTF16(extension()->name()))));
553 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlockCRX", 555 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlockCRX",
554 extension()->location(), 556 extension()->location(),
555 Manifest::NUM_LOCATIONS); 557 Manifest::NUM_LOCATIONS);
556 return; 558 return;
557 } 559 }
558 560
559 // NOTE: extension may still be blacklisted, but we're forced to silently 561 // NOTE: extension may still be blacklisted, but we're forced to silently
560 // install it. In this case, ExtensionService::OnExtensionInstalled needs to 562 // install it. In this case, ExtensionService::OnExtensionInstalled needs to
561 // deal with it. 563 // deal with it.
562 564
563 // Check for policy errors. 565 // Check for policy errors.
564 if (!install_checker_.policy_error().empty()) { 566 if (!install_checker_->policy_error().empty()) {
565 // We don't want to show the error infobar for installs from the WebStore, 567 // We don't want to show the error infobar for installs from the WebStore,
566 // because the WebStore already shows an error dialog itself. 568 // because the WebStore already shows an error dialog itself.
567 // Note: |client_| can be NULL in unit_tests! 569 // Note: |client_| can be NULL in unit_tests!
568 if (extension()->from_webstore() && client_) 570 if (extension()->from_webstore() && client_)
569 client_->install_ui()->SetSkipPostInstallUI(true); 571 client_->install_ui()->SetSkipPostInstallUI(true);
570 ReportFailureFromUIThread( 572 ReportFailureFromUIThread(
571 CrxInstallError(CrxInstallError::ERROR_DECLINED, 573 CrxInstallError(CrxInstallError::ERROR_DECLINED,
572 base::UTF8ToUTF16(install_checker_.policy_error()))); 574 base::UTF8ToUTF16(install_checker_->policy_error())));
573 return; 575 return;
574 } 576 }
575 577
576 ConfirmInstall(); 578 ConfirmInstall();
577 } 579 }
578 580
579 void CrxInstaller::ConfirmInstall() { 581 void CrxInstaller::ConfirmInstall() {
580 DCHECK_CURRENTLY_ON(BrowserThread::UI); 582 DCHECK_CURRENTLY_ON(BrowserThread::UI);
581 ExtensionService* service = service_weak_.get(); 583 ExtensionService* service = service_weak_.get();
582 if (!service || service->browser_terminating()) 584 if (!service || service->browser_terminating())
583 return; 585 return;
584 586
585 if (KioskModeInfo::IsKioskOnly(install_checker_.extension().get())) { 587 if (KioskModeInfo::IsKioskOnly(extension())) {
586 bool in_kiosk_mode = false; 588 bool in_kiosk_mode = false;
587 #if defined(OS_CHROMEOS) 589 #if defined(OS_CHROMEOS)
588 user_manager::UserManager* user_manager = user_manager::UserManager::Get(); 590 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
589 in_kiosk_mode = user_manager && user_manager->IsLoggedInAsKioskApp(); 591 in_kiosk_mode = user_manager && user_manager->IsLoggedInAsKioskApp();
590 #endif 592 #endif
591 if (!in_kiosk_mode) { 593 if (!in_kiosk_mode) {
592 ReportFailureFromUIThread(CrxInstallError( 594 ReportFailureFromUIThread(CrxInstallError(
593 CrxInstallError::ERROR_DECLINED, 595 CrxInstallError::ERROR_DECLINED,
594 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_KIOSK_MODE_ONLY))); 596 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_KIOSK_MODE_ONLY)));
595 return; 597 return;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 716
715 // This is lame, but we must reload the extension because absolute paths 717 // This is lame, but we must reload the extension because absolute paths
716 // inside the content scripts are established inside InitFromValue() and we 718 // inside the content scripts are established inside InitFromValue() and we
717 // just moved the extension. 719 // just moved the extension.
718 // TODO(aa): All paths to resources inside extensions should be created 720 // TODO(aa): All paths to resources inside extensions should be created
719 // lazily and based on the Extension's root path at that moment. 721 // lazily and based on the Extension's root path at that moment.
720 // TODO(rdevlin.cronin): Continue removing std::string errors and replacing 722 // TODO(rdevlin.cronin): Continue removing std::string errors and replacing
721 // with base::string16 723 // with base::string16
722 std::string extension_id = extension()->id(); 724 std::string extension_id = extension()->id();
723 std::string error; 725 std::string error;
724 install_checker_.set_extension( 726 extension_ = file_util::LoadExtension(
725 file_util::LoadExtension( 727 version_dir, install_source_,
726 version_dir, 728 // Note: modified by UpdateCreationFlagsAndCompleteInstall.
727 install_source_, 729 creation_flags_, &error);
728 // Note: modified by UpdateCreationFlagsAndCompleteInstall.
729 creation_flags_,
730 &error).get());
731 730
732 if (extension()) { 731 if (extension()) {
733 ReportSuccessFromFileThread(); 732 ReportSuccessFromFileThread();
734 } else { 733 } else {
735 LOG(ERROR) << error << " " << extension_id << " " << download_url_; 734 LOG(ERROR) << error << " " << extension_id << " " << download_url_;
736 ReportFailureFromFileThread(CrxInstallError(base::UTF8ToUTF16(error))); 735 ReportFailureFromFileThread(CrxInstallError(base::UTF8ToUTF16(error)));
737 } 736 }
738 } 737 }
739 738
740 void CrxInstaller::ReportFailureFromFileThread(const CrxInstallError& error) { 739 void CrxInstaller::ReportFailureFromFileThread(const CrxInstallError& error) {
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
908 ExtensionInstallPrompt::GetReEnablePromptTypeForExtension( 907 ExtensionInstallPrompt::GetReEnablePromptTypeForExtension(
909 service->profile(), extension()); 908 service->profile(), extension());
910 client_->ShowDialog(base::Bind(&CrxInstaller::OnInstallPromptDone, this), 909 client_->ShowDialog(base::Bind(&CrxInstaller::OnInstallPromptDone, this),
911 extension(), nullptr, 910 extension(), nullptr,
912 base::MakeUnique<ExtensionInstallPrompt::Prompt>(type), 911 base::MakeUnique<ExtensionInstallPrompt::Prompt>(type),
913 ExtensionInstallPrompt::GetDefaultShowDialogCallback()); 912 ExtensionInstallPrompt::GetDefaultShowDialogCallback());
914 } 913 }
915 } 914 }
916 915
917 } // namespace extensions 916 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/crx_installer.h ('k') | chrome/browser/extensions/crx_installer_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698