1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file.
4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/extensions/extension_install_checker.h"
6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/strings/utf_string_conversions.h"
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/extensions/blacklist.h"
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/extensions/requirements_checker.h"
10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/profiles/profile.h"
11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/browser/browser_thread.h"
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/browser/extension_system.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/browser/management_policy.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace extensions {
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
17116680a4aac90f2aa7413d9095a592090648e557Ben MurdochExtensionInstallChecker::ExtensionInstallChecker(Profile* profile)
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : profile_(profile),
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      blacklist_state_(NOT_BLACKLISTED),
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      policy_allows_load_(true),
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      current_sequence_number_(0),
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      running_checks_(0),
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      fail_fast_(false),
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      weak_ptr_factory_(this) {
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
27116680a4aac90f2aa7413d9095a592090648e557Ben MurdochExtensionInstallChecker::~ExtensionInstallChecker() {
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ExtensionInstallChecker::Start(int enabled_checks,
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                    bool fail_fast,
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                    const Callback& callback) {
33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Profile is null in tests.
34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (profile_) {
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!extension_.get()) {
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      NOTREACHED();
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (is_running() || !enabled_checks || callback.is_null()) {
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    NOTREACHED();
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  running_checks_ = enabled_checks;
48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  fail_fast_ = fail_fast;
49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  callback_ = callback;
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ResetResults();
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Execute the management policy check first as it is synchronous.
53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (enabled_checks & CHECK_MANAGEMENT_POLICY) {
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    CheckManagementPolicy();
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!is_running())
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (enabled_checks & CHECK_REQUIREMENTS) {
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    CheckRequirements();
61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!is_running())
62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (enabled_checks & CHECK_BLACKLIST)
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    CheckBlacklistState();
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
69116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ExtensionInstallChecker::CheckManagementPolicy() {
70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(extension_.get());
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::string16 error;
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool allow = ExtensionSystem::Get(profile_)->management_policy()->UserMayLoad(
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      extension_.get(), &error);
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  OnManagementPolicyCheckDone(allow, base::UTF16ToUTF8(error));
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
78116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ExtensionInstallChecker::OnManagementPolicyCheckDone(
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool allows_load,
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::string& error) {
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  policy_allows_load_ = allows_load;
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  policy_error_ = error;
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(policy_allows_load_ || !policy_error_.empty());
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  running_checks_ &= ~CHECK_MANAGEMENT_POLICY;
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MaybeInvokeCallback();
87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
89116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ExtensionInstallChecker::CheckRequirements() {
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(extension_.get());
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!requirements_checker_.get())
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    requirements_checker_.reset(new RequirementsChecker());
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  requirements_checker_->Check(
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      extension_,
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&ExtensionInstallChecker::OnRequirementsCheckDone,
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 weak_ptr_factory_.GetWeakPtr(),
98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 current_sequence_number_));
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ExtensionInstallChecker::OnRequirementsCheckDone(
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int sequence_number,
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    std::vector<std::string> errors) {
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Some pending results may arrive after fail fast.
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (sequence_number != current_sequence_number_)
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  requirement_errors_ = errors;
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  running_checks_ &= ~CHECK_REQUIREMENTS;
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MaybeInvokeCallback();
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ExtensionInstallChecker::CheckBlacklistState() {
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(extension_.get());
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  extensions::Blacklist* blacklist =
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ExtensionSystem::Get(profile_)->blacklist();
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  blacklist->IsBlacklisted(
120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      extension_->id(),
121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&ExtensionInstallChecker::OnBlacklistStateCheckDone,
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 weak_ptr_factory_.GetWeakPtr(),
123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 current_sequence_number_));
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ExtensionInstallChecker::OnBlacklistStateCheckDone(int sequence_number,
127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                        BlacklistState state) {
128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Some pending results may arrive after fail fast.
129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (sequence_number != current_sequence_number_)
130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  blacklist_state_ = state;
133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  running_checks_ &= ~CHECK_BLACKLIST;
135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MaybeInvokeCallback();
136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
138116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ExtensionInstallChecker::ResetResults() {
139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  requirement_errors_.clear();
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  blacklist_state_ = NOT_BLACKLISTED;
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  policy_allows_load_ = true;
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  policy_error_.clear();
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
145116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ExtensionInstallChecker::MaybeInvokeCallback() {
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (callback_.is_null())
147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Set bits for failed checks.
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int failed_mask = 0;
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (blacklist_state_ == BLACKLISTED_MALWARE)
152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    failed_mask |= CHECK_BLACKLIST;
153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!requirement_errors_.empty())
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    failed_mask |= CHECK_REQUIREMENTS;
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!policy_allows_load_)
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    failed_mask |= CHECK_MANAGEMENT_POLICY;
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Invoke callback if all checks are complete or there was at least one
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // failure and |fail_fast_| is true.
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!is_running() || (failed_mask && fail_fast_)) {
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // If we are failing fast, discard any pending results.
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    weak_ptr_factory_.InvalidateWeakPtrs();
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    running_checks_ = 0;
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ++current_sequence_number_;
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    Callback callback_copy = callback_;
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    callback_.Reset();
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // This instance may be owned by the callback recipient and deleted here,
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // so reset |callback_| first and invoke a copy of the callback.
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    callback_copy.Run(failed_mask);
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace extensions
176