| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/extension_install_checker.h" | 5 #include "chrome/browser/extensions/extension_install_checker.h" |
| 6 | 6 |
| 7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
| 8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 9 #include "chrome/browser/extensions/blacklist.h" | 9 #include "chrome/browser/extensions/blacklist.h" |
| 10 #include "chrome/browser/extensions/blacklist_check.h" | 10 #include "chrome/browser/extensions/blacklist_check.h" |
| 11 #include "chrome/browser/extensions/chrome_requirements_checker.h" | |
| 12 #include "chrome/browser/profiles/profile.h" | 11 #include "chrome/browser/profiles/profile.h" |
| 13 #include "content/public/browser/browser_thread.h" | 12 #include "content/public/browser/browser_thread.h" |
| 14 #include "extensions/browser/extension_system.h" | 13 #include "extensions/browser/extension_system.h" |
| 15 #include "extensions/browser/policy_check.h" | 14 #include "extensions/browser/policy_check.h" |
| 15 #include "extensions/browser/requirements_checker.h" |
| 16 | 16 |
| 17 namespace extensions { | 17 namespace extensions { |
| 18 | 18 |
| 19 ExtensionInstallChecker::ExtensionInstallChecker(Profile* profile) | 19 ExtensionInstallChecker::ExtensionInstallChecker(Profile* profile) |
| 20 : profile_(profile), | 20 : profile_(profile), |
| 21 blacklist_error_(PolicyCheck::NONE), | 21 blacklist_error_(PreloadCheck::NONE), |
| 22 current_sequence_number_(0), | 22 is_running_(false), |
| 23 running_checks_(0), | 23 fail_fast_(false)/*, |
| 24 fail_fast_(false), | 24 weak_ptr_factory_(this)*/ { |
| 25 weak_ptr_factory_(this) {} | 25 } |
| 26 | 26 |
| 27 ExtensionInstallChecker::~ExtensionInstallChecker() { | 27 ExtensionInstallChecker::~ExtensionInstallChecker() { |
| 28 } | 28 } |
| 29 | 29 |
| 30 void ExtensionInstallChecker::Start(int enabled_checks, | 30 void ExtensionInstallChecker::Start(scoped_refptr<const Extension> extension, |
| 31 int enabled_checks, |
| 31 bool fail_fast, | 32 bool fail_fast, |
| 32 const Callback& callback) { | 33 const Callback& callback) { |
| 33 // Profile is null in tests. | 34 // Profile is null in tests. |
| 34 if (profile_) { | 35 if (profile_) { |
| 35 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 36 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 36 if (!extension_.get()) { | 37 if (!extension.get()) { |
| 37 NOTREACHED(); | 38 NOTREACHED(); |
| 38 return; | 39 return; |
| 39 } | 40 } |
| 40 } | 41 } |
| 41 | 42 |
| 42 if (is_running() || !enabled_checks || callback.is_null()) { | 43 if (is_running() || !enabled_checks || callback.is_null()) { |
| 43 NOTREACHED(); | 44 NOTREACHED(); |
| 44 return; | 45 return; |
| 45 } | 46 } |
| 46 | 47 |
| 47 running_checks_ = enabled_checks; | 48 extension_ = extension; |
| 49 |
| 48 fail_fast_ = fail_fast; | 50 fail_fast_ = fail_fast; |
| 49 callback_ = callback; | 51 callback_ = callback; |
| 50 ResetResults(); | 52 preload_check_group_ = |
| 53 base::MakeUnique<PreloadCheckGroup>(extension_.get(), fail_fast_); |
| 51 | 54 |
| 52 // Execute the management policy check first as it is synchronous. | 55 // Add the management policy check first as it is synchronous. |
| 53 if (enabled_checks & CHECK_MANAGEMENT_POLICY) { | 56 if (enabled_checks & CHECK_MANAGEMENT_POLICY) { |
| 54 CheckManagementPolicy(); | 57 if (!policy_check_) |
| 55 if (!is_running()) | 58 policy_check_ = base::MakeUnique<PolicyCheck>(profile_, extension_.get()); |
| 56 return; | 59 preload_check_group_->AddCheck(policy_check_.get()); |
| 57 } | 60 } |
| 58 | 61 |
| 59 if (enabled_checks & CHECK_REQUIREMENTS) { | 62 if (enabled_checks & CHECK_REQUIREMENTS) { |
| 60 CheckRequirements(); | 63 if (!requirements_checker_) { |
| 61 if (!is_running()) | 64 requirements_checker_ = |
| 62 return; | 65 base::MakeUnique<RequirementsChecker>(extension_.get()); |
| 66 } |
| 67 preload_check_group_->AddCheck(requirements_checker_.get()); |
| 63 } | 68 } |
| 64 | 69 |
| 65 if (enabled_checks & CHECK_BLACKLIST) | 70 if (enabled_checks & CHECK_BLACKLIST) { |
| 66 CheckBlacklistState(); | 71 if (!blacklist_check_) { |
| 72 blacklist_check_ = base::MakeUnique<BlacklistCheck>( |
| 73 Blacklist::Get(profile_), extension_.get()); |
| 74 } |
| 75 preload_check_group_->AddCheck(blacklist_check_.get()); |
| 76 } |
| 77 |
| 78 is_running_ = true; |
| 79 preload_check_group_->Start( |
| 80 base::BindOnce(&ExtensionInstallChecker::OnInstallChecksComplete, |
| 81 base::Unretained(this))); |
| 67 } | 82 } |
| 68 | 83 |
| 69 void ExtensionInstallChecker::CheckManagementPolicy() { | 84 void ExtensionInstallChecker::OnInstallChecksComplete( |
| 70 DCHECK(extension_.get()); | 85 PreloadCheck::Errors errors) { |
| 86 is_running_ = false; |
| 71 | 87 |
| 72 if (!policy_check_) | 88 int failed_mask = ProcessErrors(errors); |
| 73 policy_check_ = base::MakeUnique<PolicyCheck>(profile_, extension_.get()); | 89 |
| 74 policy_check_->Start( | 90 // Discard any pending results. |
| 75 base::BindOnce(&ExtensionInstallChecker::OnManagementPolicyCheckDone, | 91 preload_check_group_.reset(); |
| 76 weak_ptr_factory_.GetWeakPtr())); | 92 requirements_checker_.reset(); |
| 93 policy_check_.reset(); |
| 94 blacklist_check_.reset(); |
| 95 |
| 96 // This instance may be owned by the callback recipient and deleted here, |
| 97 // so reset |callback_| first and invoke a copy of the callback. |
| 98 Callback callback_copy = callback_; |
| 99 callback_.Reset(); |
| 100 callback_copy.Run(failed_mask); |
| 77 } | 101 } |
| 78 | 102 |
| 79 void ExtensionInstallChecker::OnManagementPolicyCheckDone( | 103 int ExtensionInstallChecker::ProcessErrors(PreloadCheck::Errors errors) { |
| 80 PreloadCheck::Errors errors) { | |
| 81 if (errors.count(PreloadCheck::DISALLOWED_BY_POLICY)) | |
| 82 policy_error_ = base::UTF16ToUTF8(policy_check_->GetErrorMessage()); | |
| 83 | |
| 84 running_checks_ &= ~CHECK_MANAGEMENT_POLICY; | |
| 85 MaybeInvokeCallback(); | |
| 86 } | |
| 87 | |
| 88 void ExtensionInstallChecker::CheckRequirements() { | |
| 89 DCHECK(extension_.get()); | |
| 90 | |
| 91 if (!requirements_checker_.get()) | |
| 92 requirements_checker_.reset(new ChromeRequirementsChecker()); | |
| 93 requirements_checker_->Check( | |
| 94 extension_, | |
| 95 base::Bind(&ExtensionInstallChecker::OnRequirementsCheckDone, | |
| 96 weak_ptr_factory_.GetWeakPtr(), | |
| 97 current_sequence_number_)); | |
| 98 } | |
| 99 | |
| 100 void ExtensionInstallChecker::OnRequirementsCheckDone( | |
| 101 int sequence_number, | |
| 102 const std::vector<std::string>& errors) { | |
| 103 // Some pending results may arrive after fail fast. | |
| 104 if (sequence_number != current_sequence_number_) | |
| 105 return; | |
| 106 | |
| 107 requirement_errors_ = errors; | |
| 108 | |
| 109 running_checks_ &= ~CHECK_REQUIREMENTS; | |
| 110 MaybeInvokeCallback(); | |
| 111 } | |
| 112 | |
| 113 void ExtensionInstallChecker::CheckBlacklistState() { | |
| 114 DCHECK(extension_.get()); | |
| 115 | |
| 116 if (!blacklist_check_) { | |
| 117 blacklist_check_ = base::MakeUnique<BlacklistCheck>( | |
| 118 Blacklist::Get(profile_), extension_.get()); | |
| 119 } | |
| 120 blacklist_check_->Start( | |
| 121 base::BindOnce(&ExtensionInstallChecker::OnBlacklistStateCheckDone, | |
| 122 weak_ptr_factory_.GetWeakPtr(), current_sequence_number_)); | |
| 123 } | |
| 124 | |
| 125 void ExtensionInstallChecker::OnBlacklistStateCheckDone( | |
| 126 int sequence_number, | |
| 127 PreloadCheck::Errors errors) { | |
| 128 // Some pending results may arrive after fail fast. | |
| 129 if (sequence_number != current_sequence_number_) | |
| 130 return; | |
| 131 | |
| 132 if (errors.empty()) | |
| 133 blacklist_error_ = PreloadCheck::NONE; | |
| 134 else | |
| 135 blacklist_error_ = *errors.begin(); | |
| 136 | |
| 137 running_checks_ &= ~CHECK_BLACKLIST; | |
| 138 MaybeInvokeCallback(); | |
| 139 } | |
| 140 | |
| 141 void ExtensionInstallChecker::ResetResults() { | |
| 142 requirement_errors_.clear(); | |
| 143 blacklist_error_ = PreloadCheck::NONE; | |
| 144 policy_error_.clear(); | |
| 145 } | |
| 146 | |
| 147 void ExtensionInstallChecker::MaybeInvokeCallback() { | |
| 148 if (callback_.is_null()) | |
| 149 return; | |
| 150 | |
| 151 // Set bits for failed checks. | 104 // Set bits for failed checks. |
| 152 int failed_mask = 0; | 105 int failed_mask = 0; |
| 153 if (blacklist_error_ == PreloadCheck::BLACKLISTED_ID) | 106 |
| 154 failed_mask |= CHECK_BLACKLIST; | 107 if (errors.count(PreloadCheck::DISALLOWED_BY_POLICY)) { |
| 155 if (!requirement_errors_.empty()) | 108 DCHECK(policy_check_); |
| 156 failed_mask |= CHECK_REQUIREMENTS; | 109 policy_error_ = policy_check_->GetErrorMessage(); |
| 157 if (!policy_error_.empty()) | |
| 158 failed_mask |= CHECK_MANAGEMENT_POLICY; | 110 failed_mask |= CHECK_MANAGEMENT_POLICY; |
| 159 | 111 |
| 160 // Invoke callback if all checks are complete or there was at least one | 112 if (fail_fast_) |
| 161 // failure and |fail_fast_| is true. | 113 return failed_mask; |
| 162 if (!is_running() || (failed_mask && fail_fast_)) { | 114 } |
| 163 // If we are failing fast, discard any pending results. | |
| 164 weak_ptr_factory_.InvalidateWeakPtrs(); | |
| 165 running_checks_ = 0; | |
| 166 ++current_sequence_number_; | |
| 167 | 115 |
| 168 policy_check_.reset(); | 116 if (requirements_checker_) |
| 169 blacklist_check_.reset(); | 117 requirement_error_message_ = requirements_checker_->GetErrorMessage(); |
| 118 if (requirement_error_message_.size()) { |
| 119 failed_mask |= CHECK_REQUIREMENTS; |
| 120 if (fail_fast_) |
| 121 return failed_mask; |
| 122 } |
| 170 | 123 |
| 171 Callback callback_copy = callback_; | 124 if (errors.count(PreloadCheck::BLACKLISTED_ID)) |
| 172 callback_.Reset(); | 125 blacklist_error_ = PreloadCheck::BLACKLISTED_ID; |
| 126 else if (errors.count(PreloadCheck::BLACKLISTED_UNKNOWN)) |
| 127 blacklist_error_ = PreloadCheck::BLACKLISTED_UNKNOWN; |
| 128 if (blacklist_error_ != PreloadCheck::NONE) |
| 129 failed_mask |= CHECK_BLACKLIST; |
| 173 | 130 |
| 174 // This instance may be owned by the callback recipient and deleted here, | 131 return failed_mask; |
| 175 // so reset |callback_| first and invoke a copy of the callback. | |
| 176 callback_copy.Run(failed_mask); | |
| 177 } | |
| 178 } | 132 } |
| 179 | 133 |
| 180 } // namespace extensions | 134 } // namespace extensions |
| OLD | NEW |