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 |