Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / extensions / chrome_content_verifier_delegate.cc
blobc181e5eb93edf9c29199cc353f777cf70bc24d30
1 // Copyright 2015 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.
5 #include "chrome/browser/extensions/chrome_content_verifier_delegate.h"
7 #include "base/base_switches.h"
8 #include "base/command_line.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/string_util.h"
12 #include "base/version.h"
13 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/extensions/extension_constants.h"
16 #include "extensions/browser/extension_prefs.h"
17 #include "extensions/browser/extension_registry.h"
18 #include "extensions/browser/extension_system.h"
19 #include "extensions/browser/management_policy.h"
20 #include "extensions/common/extension.h"
21 #include "extensions/common/extension_urls.h"
22 #include "extensions/common/extensions_client.h"
23 #include "extensions/common/manifest.h"
24 #include "extensions/common/manifest_url_handlers.h"
25 #include "net/base/escape.h"
27 #if defined(OS_CHROMEOS)
28 #include "chrome/browser/extensions/extension_assets_manager_chromeos.h"
29 #endif
31 namespace {
33 const char kContentVerificationExperimentName[] =
34 "ExtensionContentVerification";
36 } // namespace
38 namespace extensions {
40 // static
41 ContentVerifierDelegate::Mode ChromeContentVerifierDelegate::GetDefaultMode() {
42 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
44 Mode experiment_value = NONE;
45 const std::string group =
46 base::FieldTrialList::FindFullName(kContentVerificationExperimentName);
47 if (group == "EnforceStrict")
48 experiment_value = ContentVerifierDelegate::ENFORCE_STRICT;
49 else if (group == "Enforce")
50 experiment_value = ContentVerifierDelegate::ENFORCE;
51 else if (group == "Bootstrap")
52 experiment_value = ContentVerifierDelegate::BOOTSTRAP;
54 // The field trial value that normally comes from the server can be
55 // overridden on the command line, which we don't want to allow since
56 // malware can set chrome command line flags. There isn't currently a way
57 // to find out what the server-provided value is in this case, so we
58 // conservatively default to the strictest mode if we detect our experiment
59 // name being overridden.
60 if (command_line->HasSwitch(switches::kForceFieldTrials)) {
61 std::string forced_trials =
62 command_line->GetSwitchValueASCII(switches::kForceFieldTrials);
63 if (forced_trials.find(kContentVerificationExperimentName) !=
64 std::string::npos)
65 experiment_value = ContentVerifierDelegate::ENFORCE_STRICT;
68 Mode cmdline_value = NONE;
69 if (command_line->HasSwitch(switches::kExtensionContentVerification)) {
70 std::string switch_value = command_line->GetSwitchValueASCII(
71 switches::kExtensionContentVerification);
72 if (switch_value == switches::kExtensionContentVerificationBootstrap)
73 cmdline_value = ContentVerifierDelegate::BOOTSTRAP;
74 else if (switch_value == switches::kExtensionContentVerificationEnforce)
75 cmdline_value = ContentVerifierDelegate::ENFORCE;
76 else if (switch_value ==
77 switches::kExtensionContentVerificationEnforceStrict)
78 cmdline_value = ContentVerifierDelegate::ENFORCE_STRICT;
79 else
80 // If no value was provided (or the wrong one), just default to enforce.
81 cmdline_value = ContentVerifierDelegate::ENFORCE;
84 // We don't want to allow the command-line flags to eg disable enforcement
85 // if the experiment group says it should be on, or malware may just modify
86 // the command line flags. So return the more restrictive of the 2 values.
87 return std::max(experiment_value, cmdline_value);
90 ChromeContentVerifierDelegate::ChromeContentVerifierDelegate(
91 content::BrowserContext* context)
92 : context_(context), default_mode_(GetDefaultMode()) {
95 ChromeContentVerifierDelegate::~ChromeContentVerifierDelegate() {
98 ContentVerifierDelegate::Mode ChromeContentVerifierDelegate::ShouldBeVerified(
99 const Extension& extension) {
100 #if defined(OS_CHROMEOS)
101 if (ExtensionAssetsManagerChromeOS::IsSharedInstall(&extension))
102 return ContentVerifierDelegate::ENFORCE_STRICT;
103 #endif
105 if (!extension.is_extension() && !extension.is_legacy_packaged_app())
106 return ContentVerifierDelegate::NONE;
107 if (!Manifest::IsAutoUpdateableLocation(extension.location()))
108 return ContentVerifierDelegate::NONE;
110 if (!ManifestURL::UpdatesFromGallery(&extension)) {
111 // It's possible that the webstore update url was overridden for testing
112 // so also consider extensions with the default (production) update url
113 // to be from the store as well.
114 GURL default_webstore_url = extension_urls::GetDefaultWebstoreUpdateUrl();
115 if (ManifestURL::GetUpdateURL(&extension) != default_webstore_url)
116 return ContentVerifierDelegate::NONE;
119 return default_mode_;
122 ContentVerifierKey ChromeContentVerifierDelegate::GetPublicKey() {
123 return ContentVerifierKey(extension_misc::kWebstoreSignaturesPublicKey,
124 extension_misc::kWebstoreSignaturesPublicKeySize);
127 GURL ChromeContentVerifierDelegate::GetSignatureFetchUrl(
128 const std::string& extension_id,
129 const base::Version& version) {
130 // TODO(asargent) Factor out common code from the extension updater's
131 // ManifestFetchData class that can be shared for use here.
132 std::vector<std::string> parts;
133 parts.push_back("uc");
134 parts.push_back("installsource=signature");
135 parts.push_back("id=" + extension_id);
136 parts.push_back("v=" + version.GetString());
137 std::string x_value =
138 net::EscapeQueryParamValue(base::JoinString(parts, "&"), true);
139 std::string query = "response=redirect&x=" + x_value;
141 GURL base_url = extension_urls::GetWebstoreUpdateUrl();
142 GURL::Replacements replacements;
143 replacements.SetQuery(query.c_str(), url::Component(0, query.length()));
144 return base_url.ReplaceComponents(replacements);
147 std::set<base::FilePath> ChromeContentVerifierDelegate::GetBrowserImagePaths(
148 const extensions::Extension* extension) {
149 return ExtensionsClient::Get()->GetBrowserImagePaths(extension);
152 void ChromeContentVerifierDelegate::VerifyFailed(
153 const std::string& extension_id,
154 ContentVerifyJob::FailureReason reason) {
155 ExtensionRegistry* registry = ExtensionRegistry::Get(context_);
156 const Extension* extension =
157 registry->enabled_extensions().GetByID(extension_id);
158 if (!extension)
159 return;
160 ExtensionSystem* system = ExtensionSystem::Get(context_);
161 Mode mode = ShouldBeVerified(*extension);
162 if (mode >= ContentVerifierDelegate::ENFORCE) {
163 if (!system->management_policy()->UserMayModifySettings(extension, NULL)) {
164 LogFailureForPolicyForceInstall(extension_id);
165 return;
167 system->extension_service()->DisableExtension(extension_id,
168 Extension::DISABLE_CORRUPTED);
169 ExtensionPrefs::Get(context_)->IncrementCorruptedDisableCount();
170 UMA_HISTOGRAM_BOOLEAN("Extensions.CorruptExtensionBecameDisabled", true);
171 UMA_HISTOGRAM_ENUMERATION("Extensions.CorruptExtensionDisabledReason",
172 reason, ContentVerifyJob::FAILURE_REASON_MAX);
173 } else if (!ContainsKey(would_be_disabled_ids_, extension_id)) {
174 UMA_HISTOGRAM_BOOLEAN("Extensions.CorruptExtensionWouldBeDisabled", true);
175 would_be_disabled_ids_.insert(extension_id);
179 void ChromeContentVerifierDelegate::LogFailureForPolicyForceInstall(
180 const std::string& extension_id) {
181 if (!ContainsKey(corrupt_policy_extensions_, extension_id)) {
182 corrupt_policy_extensions_.insert(extension_id);
183 UMA_HISTOGRAM_BOOLEAN("Extensions.CorruptPolicyExtensionWouldBeDisabled",
184 true);
188 } // namespace extensions