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