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

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

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