Merge from Chromium at DEPS revision 33.0.1750.70
This commit was generated by merge_to_master.py.
Change-Id: I6569f95eba2f2906773a1fa9738645cc45bf3845
diff --git a/build/util/LASTCHANGE b/build/util/LASTCHANGE
index da046b4..1f34fb6 100644
--- a/build/util/LASTCHANGE
+++ b/build/util/LASTCHANGE
@@ -1 +1 @@
-LASTCHANGE=248643
+LASTCHANGE=248816
diff --git a/build/util/LASTCHANGE.blink b/build/util/LASTCHANGE.blink
index d1bae50..3919cfb 100644
--- a/build/util/LASTCHANGE.blink
+++ b/build/util/LASTCHANGE.blink
@@ -1 +1 @@
-LASTCHANGE=166343
+LASTCHANGE=166424
diff --git a/chrome/VERSION b/chrome/VERSION
index a755828..d7622a7 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
MAJOR=33
MINOR=0
BUILD=1750
-PATCH=68
+PATCH=70
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 0b6531f..dfd8999 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -343,8 +343,10 @@
// Component extensions don't always notify us when they're unloaded. Ensure
// we clean up ChromeVox observers here.
- if (profile_) {
- extensions::ExtensionSystem::Get(profile_)->
+ for (std::set<Profile*>::iterator it = chromevox_profiles_.begin();
+ it != chromevox_profiles_.end();
+ it++) {
+ extensions::ExtensionSystem::Get(*it)->
event_router()->UnregisterObserver(this);
}
}
@@ -742,11 +744,6 @@
autoclick_pref_handler_.HandleProfileChanged(profile_, profile);
autoclick_delay_pref_handler_.HandleProfileChanged(profile_, profile);
- if (!profile && profile_) {
- extensions::ExtensionSystem::Get(profile_)->
- event_router()->UnregisterObserver(this);
- }
-
if (profile && spoken_feedback_enabled_)
SetUpPreLoadChromeVox(profile);
@@ -856,6 +853,9 @@
Profile* profile = content::Source<Profile>(source).ptr();
if (profile_ == profile)
SetProfile(NULL);
+
+ if (IsSpokenFeedbackEnabled())
+ TearDownPostUnloadChromeVox(profile);
break;
}
case chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED: {
@@ -944,6 +944,7 @@
event_router()->RegisterObserver(this,
extensions::api::experimental_accessibility::
OnChromeVoxLoadStateChanged::kEventName);
+ chromevox_profiles_.insert(profile);
}
}
@@ -952,12 +953,12 @@
if (profile) {
extensions::ExtensionSystem::Get(profile)->
event_router()->UnregisterObserver(this);
+ chromevox_profiles_.erase(profile);
}
}
void AccessibilityManager::PlaySound(int sound_key) const {
- if (system_sounds_enabled_)
- media::SoundsManager::Get()->Play(sound_key);
+ media::SoundsManager::Get()->Play(sound_key);
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h
index 8ea472b..b662a0f 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -5,6 +5,8 @@
#ifndef CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_ACCESSIBILITY_MANAGER_H_
#define CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_ACCESSIBILITY_MANAGER_H_
+#include <set>
+
#include "ash/accessibility_delegate.h"
#include "ash/session_state_observer.h"
#include "base/memory/weak_ptr.h"
@@ -176,10 +178,9 @@
virtual void OnListenerRemoved(
const extensions::EventListenerInfo& details) OVERRIDE;
- // Plays sound identified by |sound_key| if |system_sounds_enabled_|.
- // |sound_key| must be an ID for sound registered by
- // AccessibilityManager. If there is no such sound or
- // !|system_sounds_enabled_|, sound isn't played.
+ // Plays sound identified by |sound_key|. |sound_key| must be an ID for sound
+ // registered by AccessibilityManager. If there is no such sound, sound isn't
+ // played.
void PlaySound(int sound_key) const;
// Profile which has the current a11y context.
@@ -190,6 +191,9 @@
bool chrome_vox_loaded_on_lock_screen_;
bool chrome_vox_loaded_on_user_screen_;
+ // Set of profiles ChromeVox is loaded to.
+ std::set<Profile*> chromevox_profiles_;
+
content::NotificationRegistrar notification_registrar_;
scoped_ptr<PrefChangeRegistrar> pref_change_registrar_;
scoped_ptr<PrefChangeRegistrar> local_state_pref_change_registrar_;
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 7e32fc1..91f2db1 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -181,6 +181,36 @@
DISALLOW_COPY_AND_ASSIGN(SharedModuleProvider);
};
+enum VerifyAllSuccess {
+ VERIFY_ALL_BOOTSTRAP_SUCCESS = 0,
+ VERIFY_ALL_BOOTSTRAP_FAILURE,
+ VERIFY_ALL_NON_BOOTSTRAP_SUCCESS,
+ VERIFY_ALL_NON_BOOTSTRAP_FAILURE,
+
+ // Used in histograms. Do not remove/reorder any entries above, and the below
+ // MAX entry should always come last.
+
+ VERIFY_ALL_SUCCESS_MAX
+};
+
+void LogVerifyAllSuccessHistogram(bool bootstrap, bool success) {
+ VerifyAllSuccess result;
+ if (bootstrap && success)
+ result = VERIFY_ALL_BOOTSTRAP_SUCCESS;
+ else if (bootstrap && !success)
+ result = VERIFY_ALL_BOOTSTRAP_FAILURE;
+ else if (!bootstrap && success)
+ result = VERIFY_ALL_NON_BOOTSTRAP_SUCCESS;
+ else
+ result = VERIFY_ALL_NON_BOOTSTRAP_FAILURE;
+
+ UMA_HISTOGRAM_ENUMERATION("ExtensionService.VerifyAllSuccess",
+ result, VERIFY_ALL_SUCCESS_MAX);
+}
+
+void LogAddVerifiedSuccess(bool success) {
+ UMA_HISTOGRAM_BOOLEAN("ExtensionService.AddVerified", success);
+}
} // namespace
@@ -576,7 +606,7 @@
InstallVerifier* verifier =
extensions::ExtensionSystem::Get(profile_)->install_verifier();
if (verifier->NeedsBootstrap())
- VerifyAllExtensions();
+ VerifyAllExtensions(true); // bootstrap=true.
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
@@ -595,7 +625,7 @@
base::Time::Now() - begin_time);
}
-void ExtensionService::VerifyAllExtensions() {
+void ExtensionService::VerifyAllExtensions(bool bootstrap) {
ExtensionIdSet to_add;
scoped_ptr<ExtensionSet> all_extensions = GenerateInstalledExtensionsSet();
@@ -608,10 +638,11 @@
}
extensions::ExtensionSystem::Get(profile_)->install_verifier()->AddMany(
to_add, base::Bind(&ExtensionService::FinishVerifyAllExtensions,
- AsWeakPtr()));
+ AsWeakPtr(), bootstrap));
}
-void ExtensionService::FinishVerifyAllExtensions(bool success) {
+void ExtensionService::FinishVerifyAllExtensions(bool bootstrap, bool success) {
+ LogVerifyAllSuccessHistogram(bootstrap, success);
if (success) {
// Check to see if any currently unverified extensions became verified.
InstallVerifier* verifier =
@@ -2226,7 +2257,7 @@
delayed_installs_.Remove(extension->id());
if (InstallVerifier::NeedsVerification(*extension)) {
extensions::ExtensionSystem::Get(profile_)->install_verifier()->Add(
- extension->id(), InstallVerifier::AddResultCallback());
+ extension->id(), base::Bind(LogAddVerifiedSuccess));
}
FinishInstallation(extension);
}
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 258d7c6..ecf69fa 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -209,12 +209,15 @@
// Initialize and start all installed extensions.
void Init();
- // Attempts to verify all extensions using the InstallVerifier.
- void VerifyAllExtensions();
+ // Attempts to verify all extensions using the InstallVerifier. The
+ // |bootstrap| parameter indicates whether we're doing this because the
+ // InstallVerifier needed to be bootstrapped (otherwise it's for another
+ // reason, e.g. extension install/uninstall).
+ void VerifyAllExtensions(bool bootstrap);
// Once the verifier work is finished, we may want to re-check management
// policy if |success| indicates the verifier got a new signature back.
- void FinishVerifyAllExtensions(bool success);
+ void FinishVerifyAllExtensions(bool bootstrap, bool success);
// Called when the associated Profile is going to be destroyed.
void Shutdown();
diff --git a/chrome/browser/extensions/install_signer.cc b/chrome/browser/extensions/install_signer.cc
index 4783d1e..877608f 100644
--- a/chrome/browser/extensions/install_signer.cc
+++ b/chrome/browser/extensions/install_signer.cc
@@ -9,13 +9,16 @@
#include "base/command_line.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
+#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
+#include "base/process/process_info.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
#include "base/values.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_constants.h"
@@ -243,6 +246,44 @@
return ExtensionIdSet(ids.begin(), ids.end());
}
+namespace {
+
+static int g_request_count = 0;
+
+base::LazyInstance<base::TimeTicks> g_last_request_time =
+ LAZY_INSTANCE_INITIALIZER;
+
+base::LazyInstance<base::ThreadChecker> g_single_thread_checker =
+ LAZY_INSTANCE_INITIALIZER;
+
+void LogRequestStartHistograms() {
+ // Make sure we only ever call this from one thread, so that we don't have to
+ // worry about race conditions setting g_last_request_time.
+ DCHECK(g_single_thread_checker.Get().CalledOnValidThread());
+
+ // CurrentProcessInfo::CreationTime is only defined on some platforms.
+#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
+ const base::Time process_creation_time =
+ base::CurrentProcessInfo::CreationTime();
+ UMA_HISTOGRAM_COUNTS("ExtensionInstallSigner.UptimeAtTimeOfRequest",
+ (base::Time::Now() - process_creation_time).InSeconds());
+#endif // defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
+
+ base::TimeDelta delta;
+ base::TimeTicks now = base::TimeTicks::Now();
+ if (!g_last_request_time.Get().is_null())
+ delta = now - g_last_request_time.Get();
+ g_last_request_time.Get() = now;
+ UMA_HISTOGRAM_COUNTS("ExtensionInstallSigner.SecondsSinceLastRequest",
+ delta.InSeconds());
+
+ g_request_count += 1;
+ UMA_HISTOGRAM_COUNTS_100("ExtensionInstallSigner.RequestCount",
+ g_request_count);
+}
+
+} // namespace
+
void InstallSigner::GetSignature(const SignatureCallback& callback) {
CHECK(!url_fetcher_.get());
CHECK(callback_.is_null());
@@ -301,6 +342,7 @@
return;
}
url_fetcher_->SetUploadData("application/json", json);
+ LogRequestStartHistograms();
url_fetcher_->Start();
}
@@ -311,10 +353,17 @@
}
void InstallSigner::ParseFetchResponse() {
+ bool fetch_success = url_fetcher_->GetStatus().is_success();
+ UMA_HISTOGRAM_BOOLEAN("ExtensionInstallSigner.FetchSuccess", fetch_success);
+
std::string response;
- if (!url_fetcher_->GetStatus().is_success() ||
- !url_fetcher_->GetResponseAsString(&response) ||
- response.empty()) {
+ if (fetch_success) {
+ if (!url_fetcher_->GetResponseAsString(&response))
+ response.clear();
+ }
+ UMA_HISTOGRAM_BOOLEAN("ExtensionInstallSigner.GetResponseSuccess",
+ !response.empty());
+ if (!fetch_success || response.empty()) {
ReportErrorViaCallback();
return;
}
@@ -331,7 +380,10 @@
base::DictionaryValue* dictionary = NULL;
scoped_ptr<base::Value> parsed(base::JSONReader::Read(response));
- if (!parsed.get() || !parsed->GetAsDictionary(&dictionary)) {
+ bool json_success = parsed.get() && parsed->GetAsDictionary(&dictionary);
+ UMA_HISTOGRAM_BOOLEAN("ExtensionInstallSigner.ParseJsonSuccess",
+ json_success);
+ if (!json_success) {
ReportErrorViaCallback();
return;
}
@@ -345,9 +397,13 @@
dictionary->GetString(kSignatureKey, &signature_base64);
dictionary->GetString(kExpiryKey, &expire_date);
- if (protocol_version != 1 || signature_base64.empty() ||
- !ValidateExpireDateFormat(expire_date) ||
- !base::Base64Decode(signature_base64, &signature)) {
+ bool fields_success =
+ protocol_version == 1 && !signature_base64.empty() &&
+ ValidateExpireDateFormat(expire_date) &&
+ base::Base64Decode(signature_base64, &signature);
+ UMA_HISTOGRAM_BOOLEAN("ExtensionInstallSigner.ParseFieldsSuccess",
+ fields_success);
+ if (!fields_success) {
ReportErrorViaCallback();
return;
}
@@ -381,10 +437,10 @@
result->salt = salt_;
result->signature = signature;
result->expire_date = expire_date;
- if (!VerifySignature(*result)) {
- UMA_HISTOGRAM_BOOLEAN("InstallSigner.InvalidSignature", true);
+ bool verified = VerifySignature(*result);
+ UMA_HISTOGRAM_BOOLEAN("ExtensionInstallSigner.ResultWasValid", verified);
+ if (!verified)
result.reset();
- }
UMA_HISTOGRAM_COUNTS_100("ExtensionInstallSigner.InvalidCount",
invalid_ids.size());
}
diff --git a/chrome/browser/extensions/install_verifier.cc b/chrome/browser/extensions/install_verifier.cc
index aae2555..407da5d 100644
--- a/chrome/browser/extensions/install_verifier.cc
+++ b/chrome/browser/extensions/install_verifier.cc
@@ -29,6 +29,11 @@
NONE = 0, // Do not request install signatures, and do not enforce them.
BOOTSTRAP, // Request install signatures, but do not enforce them.
ENFORCE, // Request install signatures, and enforce them.
+
+ // This is used in histograms - do not remove or reorder entries above! Also
+ // the "MAX" item below should always be the last element.
+
+ VERIFY_STATUS_MAX
};
#if defined(GOOGLE_CHROME_BUILD)
@@ -48,7 +53,7 @@
return ENFORCE;
}
- VerifyStatus default_status = BOOTSTRAP;
+ VerifyStatus default_status = NONE;
if (group == "Enforce")
return ENFORCE;
@@ -106,6 +111,23 @@
namespace {
+enum InitResult {
+ INIT_NO_PREF = 0,
+ INIT_UNPARSEABLE_PREF,
+ INIT_INVALID_SIGNATURE,
+ INIT_VALID_SIGNATURE,
+
+ // This is used in histograms - do not remove or reorder entries above! Also
+ // the "MAX" item below should always be the last element.
+
+ INIT_RESULT_MAX
+};
+
+void LogInitResultHistogram(InitResult result) {
+ UMA_HISTOGRAM_ENUMERATION("ExtensionInstallVerifier.InitResult",
+ result, INIT_RESULT_MAX);
+}
+
bool FromStore(const Extension& extension) {
bool updates_from_store = ManifestURL::UpdatesFromGallery(&extension);
return extension.from_webstore() || updates_from_store;
@@ -123,23 +145,29 @@
}
void InstallVerifier::Init() {
+ UMA_HISTOGRAM_ENUMERATION("ExtensionInstallVerifier.ExperimentStatus",
+ GetExperimentStatus(), VERIFY_STATUS_MAX);
+ UMA_HISTOGRAM_ENUMERATION("ExtensionInstallVerifier.ActualStatus",
+ GetStatus(), VERIFY_STATUS_MAX);
+
const DictionaryValue* pref = prefs_->GetInstallSignature();
if (pref) {
scoped_ptr<InstallSignature> signature_from_prefs =
InstallSignature::FromValue(*pref);
if (!signature_from_prefs.get()) {
- UMA_HISTOGRAM_BOOLEAN("InstallVerifier.InitUnparseablePref", true);
+ LogInitResultHistogram(INIT_UNPARSEABLE_PREF);
} else if (!InstallSigner::VerifySignature(*signature_from_prefs.get())) {
- UMA_HISTOGRAM_BOOLEAN("InstallVerifier.InitInvalidSignature", true);
+ LogInitResultHistogram(INIT_INVALID_SIGNATURE);
DVLOG(1) << "Init - ignoring invalid signature";
} else {
signature_ = signature_from_prefs.Pass();
- UMA_HISTOGRAM_COUNTS("InstallVerifier.InitGoodSignature",
- signature_->ids.size());
+ LogInitResultHistogram(INIT_VALID_SIGNATURE);
+ UMA_HISTOGRAM_COUNTS_100("ExtensionInstallVerifier.InitSignatureCount",
+ signature_->ids.size());
GarbageCollect();
}
} else {
- UMA_HISTOGRAM_BOOLEAN("InstallVerifier.InitNoSignature", true);
+ LogInitResultHistogram(INIT_NO_PREF);
}
}
@@ -224,30 +252,72 @@
return std::string("InstallVerifier");
}
+namespace {
+
+enum MustRemainDisabledOutcome {
+ VERIFIED = 0,
+ NOT_EXTENSION,
+ UNPACKED,
+ ENTERPRISE_POLICY_ALLOWED,
+ FORCED_NOT_VERIFIED,
+ NOT_FROM_STORE,
+ NO_SIGNATURE,
+ NOT_VERIFIED_BUT_NOT_ENFORCING,
+ NOT_VERIFIED,
+
+ // This is used in histograms - do not remove or reorder entries above! Also
+ // the "MAX" item below should always be the last element.
+
+ MUST_REMAIN_DISABLED_OUTCOME_MAX
+};
+
+void MustRemainDisabledHistogram(MustRemainDisabledOutcome outcome) {
+ UMA_HISTOGRAM_ENUMERATION("ExtensionInstallVerifier.MustRemainDisabled",
+ outcome, MUST_REMAIN_DISABLED_OUTCOME_MAX);
+}
+
+} // namespace
+
bool InstallVerifier::MustRemainDisabled(const Extension* extension,
Extension::DisableReason* reason,
base::string16* error) const {
- if (!CanUseExtensionApis(*extension) ||
- Manifest::IsUnpackedLocation(extension->location()) ||
- AllowedByEnterprisePolicy(extension->id()))
- return false;
-
- // If we don't have a signature yet, we'll temporarily consider every
- // extension from the webstore verified to avoid false positives on existing
- // profiles hitting this code for the first time, and rely on consumers of
- // this class to check NeedsBootstrap() and schedule a first check so we can
- // get a signature.
- bool verified =
- FromStore(*extension) &&
- (signature_.get() == NULL || IsVerified(extension->id())) &&
- !ContainsKey(InstallSigner::GetForcedNotFromWebstore(), extension->id());
-
- if (!verified && !ShouldEnforce()) {
- if (signature_.get())
- UMA_HISTOGRAM_BOOLEAN("InstallVerifier.SignatureFailedButNotEnforcing",
- true);
+ if (!CanUseExtensionApis(*extension)) {
+ MustRemainDisabledHistogram(NOT_EXTENSION);
return false;
}
+ if (Manifest::IsUnpackedLocation(extension->location())) {
+ MustRemainDisabledHistogram(UNPACKED);
+ return false;
+ }
+ if (AllowedByEnterprisePolicy(extension->id())) {
+ MustRemainDisabledHistogram(ENTERPRISE_POLICY_ALLOWED);
+ return false;
+ }
+
+ bool verified = true;
+ MustRemainDisabledOutcome outcome = VERIFIED;
+ if (ContainsKey(InstallSigner::GetForcedNotFromWebstore(), extension->id())) {
+ verified = false;
+ outcome = FORCED_NOT_VERIFIED;
+ } else if (!FromStore(*extension)) {
+ verified = false;
+ outcome = NOT_FROM_STORE;
+ } else if (signature_.get() == NULL) {
+ // If we don't have a signature yet, we'll temporarily consider every
+ // extension from the webstore verified to avoid false positives on existing
+ // profiles hitting this code for the first time, and rely on consumers of
+ // this class to check NeedsBootstrap() and schedule a first check so we can
+ // get a signature.
+ outcome = NO_SIGNATURE;
+ } else if (!IsVerified(extension->id())) {
+ verified = false;
+ outcome = NOT_VERIFIED;
+ }
+ if (!verified && !ShouldEnforce()) {
+ verified = true;
+ outcome = NOT_VERIFIED_BUT_NOT_ENFORCING;
+ }
+ MustRemainDisabledHistogram(outcome);
if (!verified) {
if (reason)
@@ -359,6 +429,26 @@
}
}
+namespace {
+
+enum CallbackResult {
+ CALLBACK_NO_SIGNATURE = 0,
+ CALLBACK_INVALID_SIGNATURE,
+ CALLBACK_VALID_SIGNATURE,
+
+ // This is used in histograms - do not remove or reorder entries above! Also
+ // the "MAX" item below should always be the last element.
+
+ CALLBACK_RESULT_MAX
+};
+
+void GetSignatureResultHistogram(CallbackResult result) {
+ UMA_HISTOGRAM_ENUMERATION("ExtensionInstallVerifier.GetSignatureResult",
+ result, CALLBACK_RESULT_MAX);
+}
+
+} // namespace
+
void InstallVerifier::SignatureCallback(
scoped_ptr<InstallSignature> signature) {
@@ -367,11 +457,11 @@
bool success = false;
if (!signature.get()) {
- UMA_HISTOGRAM_BOOLEAN("InstallVerifier.CallbackNoSignature", true);
+ GetSignatureResultHistogram(CALLBACK_NO_SIGNATURE);
} else if (!InstallSigner::VerifySignature(*signature)) {
- UMA_HISTOGRAM_BOOLEAN("InstallVerifier.CallbackInvalidSignature", true);
+ GetSignatureResultHistogram(CALLBACK_INVALID_SIGNATURE);
} else {
- UMA_HISTOGRAM_BOOLEAN("InstallVerifier.CallbackValidSignature", true);
+ GetSignatureResultHistogram(CALLBACK_VALID_SIGNATURE);
success = true;
}
diff --git a/chrome/browser/extensions/installed_loader.cc b/chrome/browser/extensions/installed_loader.cc
index 6b39ffb..8131d11 100644
--- a/chrome/browser/extensions/installed_loader.cc
+++ b/chrome/browser/extensions/installed_loader.cc
@@ -153,6 +153,7 @@
extension_service_->profile())->management_policy();
if (extension.get()) {
Extension::DisableReason disable_reason = Extension::DISABLE_NONE;
+ bool force_disabled = false;
if (!policy->UserMayLoad(extension.get(), NULL)) {
// The error message from UserMayInstall() often contains the extension ID
// and is therefore not well suited to this UI.
@@ -162,7 +163,10 @@
policy->MustRemainDisabled(extension, &disable_reason, NULL)) {
extension_prefs_->SetExtensionState(extension->id(), Extension::DISABLED);
extension_prefs_->AddDisableReason(extension->id(), disable_reason);
+ force_disabled = true;
}
+ UMA_HISTOGRAM_BOOLEAN("ExtensionInstalledLoader.ForceDisabled",
+ force_disabled);
}
if (!extension.get()) {
diff --git a/chrome/browser/resources/chromeos/genius_app/manifest.json b/chrome/browser/resources/chromeos/genius_app/manifest.json
index 8af509d..fd5624d 100644
--- a/chrome/browser/resources/chromeos/genius_app/manifest.json
+++ b/chrome/browser/resources/chromeos/genius_app/manifest.json
@@ -32,6 +32,5 @@
"https://www-googleapis-test.sandbox.google.com/*",
"https://www.googleapis.com/*"
],
- "display_in_launcher": false,
"display_in_new_tab_page": false
}
diff --git a/chrome/browser/resources/chromeos/offline_net_load.html b/chrome/browser/resources/chromeos/offline_net_load.html
index ddd5ce8..804cc8d 100644
--- a/chrome/browser/resources/chromeos/offline_net_load.html
+++ b/chrome/browser/resources/chromeos/offline_net_load.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html i18n-values="dir:textdirection">
<head>
+ <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0,
maximum-scale=1.0, user-scalable=no">
<title i18n-content="title"></title>
diff --git a/chrome/browser/resources/file_manager/foreground/css/file_manager.css b/chrome/browser/resources/file_manager/foreground/css/file_manager.css
index d4b2f17..560cef7 100644
--- a/chrome/browser/resources/file_manager/foreground/css/file_manager.css
+++ b/chrome/browser/resources/file_manager/foreground/css/file_manager.css
@@ -518,6 +518,11 @@
-webkit-margin-start: 20px;
}
+select.file-type:hover {
+ /* Original value is '5 fill', which hides the dropdown triangle. */
+ border-image-slice: 5;
+}
+
/* The container for breadcrumb elements. */
.breadcrumbs {
-webkit-box-align: center;
diff --git a/chrome/browser/resources/options/browser_options.html b/chrome/browser/resources/options/browser_options.html
index 8545d49..22c61ff 100644
--- a/chrome/browser/resources/options/browser_options.html
+++ b/chrome/browser/resources/options/browser_options.html
@@ -646,8 +646,6 @@
<span i18n-content="accessibilityExplanation"></span>
<a target="_blank" i18n-content="learnMore"
i18n-values="href:accessibilityLearnMoreURL"></a>
- <a target="_blank" i18n-content="accessibilitySettings"
- i18n-values="href:accessibilitySettingsURL"></a>
</p>
<div class="option-name">
<div class="checkbox">
@@ -726,6 +724,10 @@
</span>
</span>
</span>
+ <div id="accessibility-settings" hidden>
+ <button id="accessibility-settings-button"
+ i18n-content="accessibilitySettings"></button>
+ </div>
</div>
</div>
<div class="option-name">
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js
index 27e2d3d..60cacd1 100644
--- a/chrome/browser/resources/options/browser_options.js
+++ b/chrome/browser/resources/options/browser_options.js
@@ -424,10 +424,22 @@
// Accessibility section (CrOS only).
if (cr.isChromeOS) {
+ var updateAccessibilitySettingsButton = function() {
+ $('accessibility-settings').hidden =
+ !($('accessibility-spoken-feedback-check').checked);
+ };
+ Preferences.getInstance().addEventListener(
+ 'settings.accessibility',
+ updateAccessibilitySettingsButton);
+ $('accessibility-settings-button').onclick = function(event) {
+ window.open(loadTimeData.getString('accessibilitySettingsURL'));
+ };
$('accessibility-spoken-feedback-check').onchange = function(event) {
chrome.send('spokenFeedbackChange',
[$('accessibility-spoken-feedback-check').checked]);
+ updateAccessibilitySettingsButton();
};
+ updateAccessibilitySettingsButton();
$('accessibility-high-contrast-check').onchange = function(event) {
chrome.send('highContrastChange',
diff --git a/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc b/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc
index 693e403..41060c8 100644
--- a/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc
+++ b/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc
@@ -310,51 +310,6 @@
EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
}
-// Set up a DTM with 2 controllers. configure it. One of them is still loading
-// after the timeout. Slow loading type should be reported.
-TEST_F(SyncDataTypeManagerImplTest, ConfigureSlowLoadingType) {
- AddController(BOOKMARKS);
- AddController(APPS);
-
- GetController(BOOKMARKS)->SetDelayModelLoad();
-
- SetConfigureStartExpectation();
-
- syncer::ModelTypeSet types;
- types.Put(BOOKMARKS);
- types.Put(APPS);
-
- Configure(dtm_.get(), types);
- EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
-
- FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
- FinishDownload(*dtm_, types, ModelTypeSet());
- EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
-
- // Let APPS controller finish association.
- GetController(APPS)->FinishStart(DataTypeController::OK);
-
- base::OneShotTimer<ModelAssociationManager>* timer =
- dtm_->GetModelAssociationManagerForTesting()->GetTimerForTesting();
-
- base::Closure task = timer->user_task();
- timer->Stop();
- task.Run();
-
- DataTypeManager::ConfigureResult result = dtm_->configure_result();
- EXPECT_EQ(DataTypeManager::PARTIAL_SUCCESS, result.status);
- EXPECT_TRUE(result.requested_types.Has(BOOKMARKS));
- EXPECT_TRUE(result.requested_types.Has(APPS));
- EXPECT_TRUE(syncer::ModelTypeSet(BOOKMARKS).Equals(
- result.unfinished_data_types));
- EXPECT_TRUE(result.failed_data_types.empty());
- EXPECT_TRUE(result.needs_crypto.Empty());
-
- dtm_->Stop();
- EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
-}
-
-
// Set up a DTM with a single controller, configure it, but stop it
// before finishing the download. It should still be safe to run the
// download callback even after the DTM is stopped and destroyed.
diff --git a/chrome/browser/sync/glue/model_association_manager.cc b/chrome/browser/sync/glue/model_association_manager.cc
index 106f1c4..261154a 100644
--- a/chrome/browser/sync/glue/model_association_manager.cc
+++ b/chrome/browser/sync/glue/model_association_manager.cc
@@ -297,6 +297,10 @@
DVLOG(1) << "ModelAssociationManager: ModelLoadCallback for "
<< syncer::ModelTypeToString(type);
+ // TODO(haitaol): temporary fix for 335606.
+ if (slow_types_.Has(type))
+ return;
+
// This happens when slow loading type is disabled by new configuration.
if (!desired_types_.Has(type))
return;
@@ -331,6 +335,10 @@
const syncer::SyncMergeResult& syncer_merge_result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // TODO(haitaol): temporary fix for 335606.
+ if (slow_types_.Has(type))
+ return;
+
// This happens when slow associating type is disabled by new configuration.
if (!desired_types_.Has(type))
return;
@@ -404,6 +412,16 @@
timer_.Stop();
+ slow_types_.PutAll(associating_types_);
+
+ // TODO(haitaol): temporary fix for 335606.
+ for (syncer::ModelTypeSet::Iterator it = associating_types_.First();
+ it.Good(); it.Inc()) {
+ AppendToFailedDatatypesAndLogError(
+ syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR,
+ "Association timed out.", it.Get()));
+ }
+
// Stop controllers of failed types.
StopDisabledTypes();
@@ -417,8 +435,6 @@
configure_status_ = DataTypeManager::PARTIAL_SUCCESS;
}
- slow_types_.PutAll(associating_types_);
-
DataTypeManager::ConfigureResult result(configure_status_,
requested_types_,
failed_data_types_info_,
diff --git a/chrome/browser/sync/glue/model_association_manager_unittest.cc b/chrome/browser/sync/glue/model_association_manager_unittest.cc
index 3789b39..4c02b4a 100644
--- a/chrome/browser/sync/glue/model_association_manager_unittest.cc
+++ b/chrome/browser/sync/glue/model_association_manager_unittest.cc
@@ -124,10 +124,17 @@
syncer::ModelTypeSet types;
types.Put(syncer::BOOKMARKS);
+ std::map<syncer::ModelType, syncer::SyncError> errors;
+ syncer::SyncError error(FROM_HERE,
+ syncer::SyncError::DATATYPE_ERROR,
+ "Failed",
+ syncer::BOOKMARKS);
+ errors[syncer::BOOKMARKS] = error;
+
DataTypeManager::ConfigureResult expected_result(
DataTypeManager::ABORTED,
types,
- std::map<syncer::ModelType, syncer::SyncError>(),
+ errors,
syncer::ModelTypeSet(syncer::BOOKMARKS),
syncer::ModelTypeSet());
@@ -244,69 +251,7 @@
DataTypeController::UNRECOVERABLE_ERROR);
}
-TEST_F(SyncModelAssociationManagerTest, InitializeWhileLoading) {
- controllers_[syncer::BOOKMARKS] =
- new FakeDataTypeController(syncer::BOOKMARKS);
- controllers_[syncer::THEMES] =
- new FakeDataTypeController(syncer::THEMES);
-
- GetController(controllers_, syncer::BOOKMARKS)->SetDelayModelLoad();
- ModelAssociationManager model_association_manager(&controllers_,
- &result_processor_);
- syncer::ModelTypeSet types(syncer::BOOKMARKS, syncer::THEMES);
-
- syncer::ModelTypeSet expected_types_waiting_to_load;
- expected_types_waiting_to_load.Put(syncer::BOOKMARKS);
- DataTypeManager::ConfigureResult expected_result_partially_done(
- DataTypeManager::PARTIAL_SUCCESS,
- types,
- std::map<syncer::ModelType, syncer::SyncError>(),
- expected_types_waiting_to_load,
- syncer::ModelTypeSet());
-
- model_association_manager.Initialize(types);
-
- model_association_manager.StartAssociationAsync(types);
-
- EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
- WillOnce(VerifyResult(expected_result_partially_done));
-
- // THEMES finishes associating here.
- GetController(controllers_, syncer::THEMES)->FinishStart(
- DataTypeController::OK);
-
- base::OneShotTimer<ModelAssociationManager>* timer =
- model_association_manager.GetTimerForTesting();
-
- base::Closure task = timer->user_task();
- timer->Stop();
- task.Run(); // Bookmark load times out here.
-
- EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
- DataTypeController::MODEL_STARTING);
-
- model_association_manager.Initialize(types);
-
- DataTypeManager::ConfigureResult expected_result_done(
- DataTypeManager::OK,
- types,
- std::map<syncer::ModelType, syncer::SyncError>(),
- syncer::ModelTypeSet(),
- syncer::ModelTypeSet());
- EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
- WillOnce(VerifyResult(expected_result_done));
-
- model_association_manager.StartAssociationAsync(types);
-
- GetController(controllers_,
- syncer::BOOKMARKS)->SimulateModelLoadFinishing();
- GetController(controllers_, syncer::BOOKMARKS)->FinishStart(
- DataTypeController::OK);
-}
-
-// Start 2 types. One of which timeout loading. Ensure that type is
-// fully configured eventually.
-TEST_F(SyncModelAssociationManagerTest, ModelStartWithSlowType) {
+TEST_F(SyncModelAssociationManagerTest, SlowTypeAsFailedType) {
controllers_[syncer::BOOKMARKS] =
new FakeDataTypeController(syncer::BOOKMARKS);
controllers_[syncer::APPS] =
@@ -318,12 +263,19 @@
types.Put(syncer::BOOKMARKS);
types.Put(syncer::APPS);
+ std::map<syncer::ModelType, syncer::SyncError> errors;
+ syncer::SyncError error(FROM_HERE,
+ syncer::SyncError::DATATYPE_ERROR,
+ "Association timed out.",
+ syncer::BOOKMARKS);
+ errors[syncer::BOOKMARKS] = error;
+
syncer::ModelTypeSet expected_types_unfinished;
expected_types_unfinished.Put(syncer::BOOKMARKS);
DataTypeManager::ConfigureResult expected_result_partially_done(
DataTypeManager::PARTIAL_SUCCESS,
types,
- std::map<syncer::ModelType, syncer::SyncError>(),
+ errors,
expected_types_unfinished,
syncer::ModelTypeSet());
@@ -332,30 +284,12 @@
model_association_manager.Initialize(types);
model_association_manager.StartAssociationAsync(types);
-
- // Simulate delayed loading of bookmark model.
GetController(controllers_, syncer::APPS)->FinishStart(
DataTypeController::OK);
- base::OneShotTimer<ModelAssociationManager>* timer =
- model_association_manager.GetTimerForTesting();
+ model_association_manager.GetTimerForTesting()->user_task().Run();
- // Note: Independent of the timeout value this test is not flaky.
- // The reason is timer posts a task which would never be executed
- // as we don't let the message loop run.
- base::Closure task = timer->user_task();
- timer->Stop();
- task.Run();
-
- EXPECT_EQ(DataTypeController::MODEL_STARTING,
- GetController(controllers_, syncer::BOOKMARKS)->state());
- GetController(controllers_,
- syncer::BOOKMARKS)->SimulateModelLoadFinishing();
- EXPECT_EQ(DataTypeController::ASSOCIATING,
- GetController(controllers_, syncer::BOOKMARKS)->state());
- GetController(controllers_, syncer::BOOKMARKS)->FinishStart(
- DataTypeController::OK);
- EXPECT_EQ(DataTypeController::RUNNING,
+ EXPECT_EQ(DataTypeController::NOT_RUNNING,
GetController(controllers_, syncer::BOOKMARKS)->state());
}
@@ -452,182 +386,4 @@
GetController(controllers_, syncer::BOOKMARKS)->state());
}
-// Test that a slow type is stopped if it fails to load when association
-// manager is in IDLE mode.
-TEST_F(SyncModelAssociationManagerTest, SlowTypeFailToLoadInIdleMode) {
- controllers_[syncer::BOOKMARKS] =
- new FakeDataTypeController(syncer::BOOKMARKS);
- GetController(controllers_, syncer::BOOKMARKS)->SetDelayModelLoad();
- GetController(controllers_, syncer::BOOKMARKS)->SetModelLoadError(
- syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR,
- "", syncer::BOOKMARKS));
- ModelAssociationManager model_association_manager(&controllers_,
- &result_processor_);
- syncer::ModelTypeSet types;
- types.Put(syncer::BOOKMARKS);
-
- DataTypeManager::ConfigureResult expected_result_partially_done(
- DataTypeManager::PARTIAL_SUCCESS,
- types,
- std::map<syncer::ModelType, syncer::SyncError>(),
- types,
- syncer::ModelTypeSet());
- EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
- WillOnce(VerifyResult(expected_result_partially_done));
-
- model_association_manager.Initialize(types);
- model_association_manager.StartAssociationAsync(types);
-
- base::OneShotTimer<ModelAssociationManager>* timer =
- model_association_manager.GetTimerForTesting();
- base::Closure task = timer->user_task();
- timer->Stop();
- task.Run();
-
- EXPECT_EQ(DataTypeController::MODEL_STARTING,
- GetController(controllers_, syncer::BOOKMARKS)->state());
- GetController(controllers_,
- syncer::BOOKMARKS)->SimulateModelLoadFinishing();
- // Failed DTC is stopped in IDLE mode.
- EXPECT_EQ(DataTypeController::NOT_RUNNING,
- GetController(controllers_, syncer::BOOKMARKS)->state());
-}
-
-// Test that a slow type is reported and stopped if it fails to load when
-// association manager is in INITIALIZED_TO_CONFIGURE mode.
-TEST_F(SyncModelAssociationManagerTest,
- SlowTypeFailToLoadInInitToConfigureMode) {
- controllers_[syncer::BOOKMARKS] =
- new FakeDataTypeController(syncer::BOOKMARKS);
- GetController(controllers_, syncer::BOOKMARKS)->SetDelayModelLoad();
- GetController(controllers_, syncer::BOOKMARKS)->SetModelLoadError(
- syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR,
- "", syncer::BOOKMARKS));
- ModelAssociationManager model_association_manager(&controllers_,
- &result_processor_);
- syncer::ModelTypeSet types;
- types.Put(syncer::BOOKMARKS);
-
- // 1st configuration.
- DataTypeManager::ConfigureResult first_result(
- DataTypeManager::PARTIAL_SUCCESS,
- types,
- std::map<syncer::ModelType, syncer::SyncError>(),
- types,
- syncer::ModelTypeSet());
- EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
- WillOnce(VerifyResult(first_result));
- model_association_manager.Initialize(types);
- model_association_manager.StartAssociationAsync(types);
- base::OneShotTimer<ModelAssociationManager>* timer =
- model_association_manager.GetTimerForTesting();
- base::Closure task = timer->user_task();
- timer->Stop();
- task.Run();
- EXPECT_EQ(DataTypeController::MODEL_STARTING,
- GetController(controllers_, syncer::BOOKMARKS)->state());
-
- // 2nd configuration.
- std::map<syncer::ModelType, syncer::SyncError> error;
- error[syncer::BOOKMARKS] =
- syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR,
- "", syncer::BOOKMARKS);
- DataTypeManager::ConfigureResult second_result(
- DataTypeManager::PARTIAL_SUCCESS, types, error, syncer::ModelTypeSet(),
- syncer::ModelTypeSet());
- EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
- WillOnce(VerifyResult(second_result));
- model_association_manager.Initialize(types);
- GetController(controllers_,
- syncer::BOOKMARKS)->SimulateModelLoadFinishing();
- model_association_manager.StartAssociationAsync(types);
- EXPECT_EQ(DataTypeController::NOT_RUNNING,
- GetController(controllers_, syncer::BOOKMARKS)->state());
-}
-
-// Test that a slow type is stopped if it fails to associate when association
-// manager is in IDLE mode.
-TEST_F(SyncModelAssociationManagerTest, SlowTypeFailToAssociateInIdleMode) {
- controllers_[syncer::BOOKMARKS] =
- new FakeDataTypeController(syncer::BOOKMARKS);
- ModelAssociationManager model_association_manager(&controllers_,
- &result_processor_);
- syncer::ModelTypeSet types;
- types.Put(syncer::BOOKMARKS);
-
- DataTypeManager::ConfigureResult expected_result_partially_done(
- DataTypeManager::PARTIAL_SUCCESS,
- types,
- std::map<syncer::ModelType, syncer::SyncError>(),
- types,
- syncer::ModelTypeSet());
- EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
- WillOnce(VerifyResult(expected_result_partially_done));
-
- model_association_manager.Initialize(types);
- model_association_manager.StartAssociationAsync(types);
-
- base::OneShotTimer<ModelAssociationManager>* timer =
- model_association_manager.GetTimerForTesting();
- base::Closure task = timer->user_task();
- timer->Stop();
- task.Run();
-
- EXPECT_EQ(DataTypeController::ASSOCIATING,
- GetController(controllers_, syncer::BOOKMARKS)->state());
- GetController(controllers_, syncer::BOOKMARKS)->FinishStart(
- DataTypeController::ASSOCIATION_FAILED);
- // Failed DTC is stopped in IDLE mode.
- EXPECT_EQ(DataTypeController::NOT_RUNNING,
- GetController(controllers_, syncer::BOOKMARKS)->state());
-}
-
-// Test that a slow type is reported and stopped if it fails to associate when
-// association manager is in INITIALIZED_TO_CONFIGURE mode.
-TEST_F(SyncModelAssociationManagerTest,
- SlowTypeFailToAssociateInInitToConfigureMode) {
- controllers_[syncer::BOOKMARKS] =
- new FakeDataTypeController(syncer::BOOKMARKS);
- ModelAssociationManager model_association_manager(&controllers_,
- &result_processor_);
- syncer::ModelTypeSet types;
- types.Put(syncer::BOOKMARKS);
-
- // 1st configuration.
- DataTypeManager::ConfigureResult first_result(
- DataTypeManager::PARTIAL_SUCCESS,
- types,
- std::map<syncer::ModelType, syncer::SyncError>(),
- types,
- syncer::ModelTypeSet());
- EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
- WillOnce(VerifyResult(first_result));
- model_association_manager.Initialize(types);
- model_association_manager.StartAssociationAsync(types);
- base::OneShotTimer<ModelAssociationManager>* timer =
- model_association_manager.GetTimerForTesting();
- base::Closure task = timer->user_task();
- timer->Stop();
- task.Run();
- EXPECT_EQ(DataTypeController::ASSOCIATING,
- GetController(controllers_, syncer::BOOKMARKS)->state());
-
- // 2nd configuration.
- std::map<syncer::ModelType, syncer::SyncError> error;
- error[syncer::BOOKMARKS] =
- syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR,
- "", syncer::BOOKMARKS);
- DataTypeManager::ConfigureResult second_result(
- DataTypeManager::PARTIAL_SUCCESS, types, error, syncer::ModelTypeSet(),
- syncer::ModelTypeSet());
- EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
- WillOnce(VerifyResult(second_result));
- model_association_manager.Initialize(types);
- GetController(controllers_, syncer::BOOKMARKS)->FinishStart(
- DataTypeController::ASSOCIATION_FAILED);
- model_association_manager.StartAssociationAsync(types);
- EXPECT_EQ(DataTypeController::NOT_RUNNING,
- GetController(controllers_, syncer::BOOKMARKS)->state());
-}
-
} // namespace browser_sync
diff --git a/chrome/browser/task_manager/extension_process_resource_provider.cc b/chrome/browser/task_manager/extension_process_resource_provider.cc
index 11ebdf0..e385fd3 100644
--- a/chrome/browser/task_manager/extension_process_resource_provider.cc
+++ b/chrome/browser/task_manager/extension_process_resource_provider.cc
@@ -315,7 +315,8 @@
ExtensionProcessResource* resource =
new ExtensionProcessResource(render_view_host);
- CHECK(resources_.find(render_view_host) == resources_.end());
+ if (resources_.find(render_view_host) != resources_.end())
+ return;
resources_[render_view_host] = resource;
task_manager_->AddResource(resource);
}
diff --git a/chrome/browser/ui/cocoa/history_overlay_controller.mm b/chrome/browser/ui/cocoa/history_overlay_controller.mm
index 16f3ab5..cdfb196 100644
--- a/chrome/browser/ui/cocoa/history_overlay_controller.mm
+++ b/chrome/browser/ui/cocoa/history_overlay_controller.mm
@@ -135,9 +135,7 @@
- (void)showPanelForView:(NSView*)view {
parent_.reset([view retain]);
[self setProgress:0 finished:NO]; // Set initial view position.
- [[parent_ superview] addSubview:self.view
- positioned:NSWindowAbove
- relativeTo:parent_];
+ [parent_ addSubview:self.view];
[[BrowserWindowController
browserWindowControllerForView:[self view]] onOverlappedViewShown];
}
diff --git a/chrome/browser/ui/cocoa/history_overlay_controller_unittest.mm b/chrome/browser/ui/cocoa/history_overlay_controller_unittest.mm
index d550f81..66cb5a9 100644
--- a/chrome/browser/ui/cocoa/history_overlay_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/history_overlay_controller_unittest.mm
@@ -17,9 +17,10 @@
virtual void SetUp() {
CocoaTest::SetUp();
- // The overlay controller shows the panel in the superview of a given
- // view, so create the given view.
+ // The overlay controller shows the panel as a subview of the given view.
test_view_.reset([[NSView alloc] initWithFrame:NSMakeRect(10, 10, 10, 10)]);
+
+ // We add it to the test_window for authenticity.
[[test_window() contentView] addSubview:test_view_];
}
@@ -35,13 +36,12 @@
// is removed when the animation completes. The view should be added and
// removed at the appropriate times.
TEST_F(HistoryOverlayControllerTest, DismissClearsAnimationsAndRemovesView) {
- NSView* content_view = [test_window() contentView];
- EXPECT_EQ(1u, [[content_view subviews] count]);
+ EXPECT_EQ(0u, [[test_view() subviews] count]);
base::scoped_nsobject<HistoryOverlayController> controller(
[[HistoryOverlayController alloc] initForMode:kHistoryOverlayModeBack]);
[controller showPanelForView:test_view()];
- EXPECT_EQ(2u, [[content_view subviews] count]);
+ EXPECT_EQ(1u, [[test_view() subviews] count]);
scoped_ptr<base::MessagePumpNSRunLoop> message_pump(
new base::MessagePumpNSRunLoop);
@@ -78,5 +78,5 @@
// After the animation runs, there should be no more animations.
EXPECT_FALSE([[controller view] animations]);
- EXPECT_EQ(1u, [[content_view subviews] count]);
+ EXPECT_EQ(0u, [[test_view() subviews] count]);
}
diff --git a/chrome/browser/ui/views/app_list/win/app_list_service_win.cc b/chrome/browser/ui/views/app_list/win/app_list_service_win.cc
index 9015ac1..ca30268 100644
--- a/chrome/browser/ui/views/app_list/win/app_list_service_win.cc
+++ b/chrome/browser/ui/views/app_list/win/app_list_service_win.cc
@@ -23,6 +23,7 @@
#include "base/win/windows_version.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
@@ -516,8 +517,10 @@
}
bool AppListServiceWin::IsWarmupNeeded() {
- if (!g_browser_process || g_browser_process->IsShuttingDown())
+ if (!g_browser_process || g_browser_process->IsShuttingDown() ||
+ browser_shutdown::IsTryingToQuit()) {
return false;
+ }
// We only need to initialize the view if there's no view already created and
// there's no profile loading to be shown.
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
index d81ab98..6e49612 100644
--- a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
+++ b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
@@ -16,6 +16,7 @@
#include "base/command_line.h"
#include "base/location.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -735,9 +736,11 @@
"extensions.ExtensionSettings.returnExtensionsData", results);
MaybeRegisterForNotifications();
+ UMA_HISTOGRAM_BOOLEAN("ExtensionSettings.ShouldDoVerificationCheck",
+ should_do_verification_check_);
if (should_do_verification_check_) {
should_do_verification_check_ = false;
- extension_service_->VerifyAllExtensions();
+ extension_service_->VerifyAllExtensions(false); // bootstrap=false.
}
}
diff --git a/chrome/renderer/resources/blocked_plugin.html b/chrome/renderer/resources/blocked_plugin.html
index a858914..da2d7c9 100644
--- a/chrome/renderer/resources/blocked_plugin.html
+++ b/chrome/renderer/resources/blocked_plugin.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
+<meta charset="utf-8">
<script>
function debug(msg) {
document.getElementById('debug').textContent = msg;
diff --git a/chrome/renderer/resources/click_to_play_plugin.html b/chrome/renderer/resources/click_to_play_plugin.html
index 3c1a601..b1cd58f 100644
--- a/chrome/renderer/resources/click_to_play_plugin.html
+++ b/chrome/renderer/resources/click_to_play_plugin.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
+<meta charset="utf-8">
<script>
function debug(msg) {
document.getElementById('debug').textContent = msg;
diff --git a/chrome/renderer/resources/disabled_plugin.html b/chrome/renderer/resources/disabled_plugin.html
index 3a49acb..a63cfa0 100644
--- a/chrome/renderer/resources/disabled_plugin.html
+++ b/chrome/renderer/resources/disabled_plugin.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
+<meta charset="utf-8">
<script>
function debug(msg) {
document.getElementById('debug').textContent = msg;
diff --git a/chrome/renderer/resources/error_app.html b/chrome/renderer/resources/error_app.html
index 028548a..dd02891 100644
--- a/chrome/renderer/resources/error_app.html
+++ b/chrome/renderer/resources/error_app.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html i18n-values="dir:textdirection">
<head>
+<meta charset="utf-8">
<title i18n-content="title">
</title>
<style>
diff --git a/chrome/renderer/resources/neterror.html b/chrome/renderer/resources/neterror.html
index fdd92cc..f2724de 100644
--- a/chrome/renderer/resources/neterror.html
+++ b/chrome/renderer/resources/neterror.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html i18n-values="dir:textdirection">
<head>
+ <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0,
maximum-scale=1.0, user-scalable=no">
<title i18n-content="title"></title>
diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc
index de6313f..0045f84 100644
--- a/chromeos/audio/cras_audio_handler.cc
+++ b/chromeos/audio/cras_audio_handler.cc
@@ -529,7 +529,7 @@
size_t old_devices_size,
size_t new_devices_size,
uint64 current_active_node) {
- return (new_devices_size <= old_devices_size &&
+ return (new_devices_size < old_devices_size &&
GetDeviceFromId(current_active_node));
}
diff --git a/chromeos/audio/cras_audio_handler_unittest.cc b/chromeos/audio/cras_audio_handler_unittest.cc
index 573daea..f4c3c99 100644
--- a/chromeos/audio/cras_audio_handler_unittest.cc
+++ b/chromeos/audio/cras_audio_handler_unittest.cc
@@ -24,6 +24,7 @@
const uint64 kHDMIOutputId = 10006;
const uint64 kUSBHeadphoneId1 = 10007;
const uint64 kUSBHeadphoneId2 = 10008;
+const uint64 kMicJackId = 10009;
const uint64 kOtherTypeOutputId = 90001;
const uint64 kOtherTypeInputId = 90002;
@@ -57,6 +58,16 @@
0
);
+const AudioNode kMicJack(
+ true,
+ kMicJackId,
+ "Fake Mic Jack",
+ "MIC",
+ "Mic Jack",
+ false,
+ 0
+);
+
const AudioNode kUSBMic(
true,
kUSBMicId,
@@ -1131,6 +1142,169 @@
EXPECT_EQ(kInternalSpeaker.id, cras_audio_handler_->GetActiveOutputNode());
}
+TEST_F(CrasAudioHandlerTest, PlugHeadphoneAutoUnplugSpeakerWithActiveUSB) {
+ // Set up initial audio devices.
+ AudioNodeList audio_nodes;
+ audio_nodes.push_back(kUSBHeadphone1);
+ audio_nodes.push_back(kInternalSpeaker);
+ audio_nodes.push_back(kInternalMic);
+ SetUpCrasAudioHandler(audio_nodes);
+ const size_t init_nodes_size = audio_nodes.size();
+
+ // Verify the audio devices size.
+ EXPECT_EQ(0, test_observer_->audio_nodes_changed_count());
+ AudioDeviceList audio_devices;
+ cras_audio_handler_->GetAudioDevices(&audio_devices);
+ EXPECT_EQ(init_nodes_size, audio_devices.size());
+
+ // Verify the internal mic is selected as the active input.
+ EXPECT_EQ(0, test_observer_->active_input_node_changed_count());
+ EXPECT_EQ(kInternalMicId, cras_audio_handler_->GetActiveInputNode());
+ EXPECT_FALSE(cras_audio_handler_->has_alternative_input());
+
+ // Verify the USB headphone is selected as the active output.
+ EXPECT_EQ(0, test_observer_->active_output_node_changed_count());
+ EXPECT_EQ(kUSBHeadphoneId1, cras_audio_handler_->GetActiveOutputNode());
+ EXPECT_TRUE(cras_audio_handler_->has_alternative_output());
+
+ // Plug the headphone and auto-unplug internal speaker.
+ audio_nodes.clear();
+ AudioNode usb_headphone_node(kUSBHeadphone1);
+ usb_headphone_node.active = true;
+ audio_nodes.push_back(usb_headphone_node);
+ AudioNode headphone_node(kHeadphone);
+ headphone_node.plugged_time = 1000;
+ audio_nodes.push_back(headphone_node);
+ AudioNode internal_mic(kInternalMic);
+ internal_mic.active = true;
+ audio_nodes.push_back(internal_mic);
+ ChangeAudioNodes(audio_nodes);
+
+ // Verify the AudioNodesChanged event is fired, with nodes count unchanged.
+ EXPECT_EQ(1, test_observer_->audio_nodes_changed_count());
+ cras_audio_handler_->GetAudioDevices(&audio_devices);
+ EXPECT_EQ(init_nodes_size, audio_devices.size());
+
+ // Verify the active output device is switched to headphone, and
+ // an ActiveOutputChanged event is fired.
+ EXPECT_EQ(1, test_observer_->active_output_node_changed_count());
+ EXPECT_EQ(kHeadphone.id, cras_audio_handler_->GetActiveOutputNode());
+ EXPECT_TRUE(cras_audio_handler_->has_alternative_output());
+
+ // Unplug the headphone and internal speaker auto-plugs back.
+ audio_nodes.clear();
+ audio_nodes.push_back(kUSBHeadphone1);
+ AudioNode internal_speaker_node(kInternalSpeaker);
+ internal_speaker_node.plugged_time = 2000;
+ audio_nodes.push_back(internal_speaker_node);
+ audio_nodes.push_back(internal_mic);
+ ChangeAudioNodes(audio_nodes);
+
+ // Verify the AudioNodesChanged event is fired, with nodes count unchanged.
+ EXPECT_EQ(2, test_observer_->audio_nodes_changed_count());
+ cras_audio_handler_->GetAudioDevices(&audio_devices);
+ EXPECT_EQ(init_nodes_size, audio_devices.size());
+
+ // Verify the active output device is switched back to USB, and
+ // an ActiveOutputChanged event is fired.
+ EXPECT_EQ(2, test_observer_->active_output_node_changed_count());
+ EXPECT_EQ(kUSBHeadphone1.id, cras_audio_handler_->GetActiveOutputNode());
+ EXPECT_TRUE(cras_audio_handler_->has_alternative_output());
+
+ // Verify the active input device is not changed.
+ EXPECT_EQ(0, test_observer_->active_input_node_changed_count());
+ EXPECT_EQ(kInternalMic.id, cras_audio_handler_->GetActiveInputNode());
+}
+
+TEST_F(CrasAudioHandlerTest, PlugMicAutoUnplugInternalMicWithActiveUSB) {
+ // Set up initial audio devices.
+ AudioNodeList audio_nodes;
+ audio_nodes.push_back(kUSBHeadphone1);
+ audio_nodes.push_back(kInternalSpeaker);
+ audio_nodes.push_back(kUSBMic);
+ audio_nodes.push_back(kInternalMic);
+ SetUpCrasAudioHandler(audio_nodes);
+ const size_t init_nodes_size = audio_nodes.size();
+
+ // Verify the audio devices size.
+ EXPECT_EQ(0, test_observer_->audio_nodes_changed_count());
+ AudioDeviceList audio_devices;
+ cras_audio_handler_->GetAudioDevices(&audio_devices);
+ EXPECT_EQ(init_nodes_size, audio_devices.size());
+
+ // Verify the internal mic is selected as the active input.
+ EXPECT_EQ(0, test_observer_->active_input_node_changed_count());
+ EXPECT_EQ(kUSBMicId, cras_audio_handler_->GetActiveInputNode());
+ EXPECT_TRUE(cras_audio_handler_->has_alternative_input());
+
+ // Verify the internal speaker is selected as the active output.
+ EXPECT_EQ(0, test_observer_->active_output_node_changed_count());
+ EXPECT_EQ(kUSBHeadphoneId1, cras_audio_handler_->GetActiveOutputNode());
+ EXPECT_TRUE(cras_audio_handler_->has_alternative_output());
+
+ // Plug the headphone and mic, auto-unplug internal mic and speaker.
+ audio_nodes.clear();
+ AudioNode usb_headphone_node(kUSBHeadphone1);
+ usb_headphone_node.active = true;
+ audio_nodes.push_back(usb_headphone_node);
+ AudioNode headphone_node(kHeadphone);
+ headphone_node.plugged_time = 1000;
+ audio_nodes.push_back(headphone_node);
+ AudioNode usb_mic(kUSBMic);
+ usb_mic.active = true;
+ audio_nodes.push_back(usb_mic);
+ AudioNode mic_jack(kMicJack);
+ mic_jack.plugged_time = 1000;
+ audio_nodes.push_back(mic_jack);
+ ChangeAudioNodes(audio_nodes);
+
+ // Verify the AudioNodesChanged event is fired, with nodes count unchanged.
+ EXPECT_EQ(1, test_observer_->audio_nodes_changed_count());
+ cras_audio_handler_->GetAudioDevices(&audio_devices);
+ EXPECT_EQ(init_nodes_size, audio_devices.size());
+
+ // Verify the active output device is switched to headphone, and
+ // an ActiveOutputChanged event is fired.
+ EXPECT_EQ(1, test_observer_->active_output_node_changed_count());
+ EXPECT_EQ(kHeadphone.id, cras_audio_handler_->GetActiveOutputNode());
+ EXPECT_TRUE(cras_audio_handler_->has_alternative_output());
+
+ // Verify the active input device is switched to mic jack, and
+ // an ActiveInputChanged event is fired.
+ EXPECT_EQ(1, test_observer_->active_input_node_changed_count());
+ EXPECT_EQ(kMicJack.id, cras_audio_handler_->GetActiveInputNode());
+ EXPECT_TRUE(cras_audio_handler_->has_alternative_input());
+
+ // Unplug the headphone and internal speaker auto-plugs back.
+ audio_nodes.clear();
+ audio_nodes.push_back(kUSBHeadphone1);
+ AudioNode internal_speaker_node(kInternalSpeaker);
+ internal_speaker_node.plugged_time = 2000;
+ audio_nodes.push_back(internal_speaker_node);
+ audio_nodes.push_back(kUSBMic);
+ AudioNode internal_mic(kInternalMic);
+ internal_mic.plugged_time = 2000;
+ audio_nodes.push_back(internal_mic);
+ ChangeAudioNodes(audio_nodes);
+
+ // Verify the AudioNodesChanged event is fired, with nodes count unchanged.
+ EXPECT_EQ(2, test_observer_->audio_nodes_changed_count());
+ cras_audio_handler_->GetAudioDevices(&audio_devices);
+ EXPECT_EQ(init_nodes_size, audio_devices.size());
+
+ // Verify the active output device is switched back to USB, and
+ // an ActiveOutputChanged event is fired.
+ EXPECT_EQ(2, test_observer_->active_output_node_changed_count());
+ EXPECT_EQ(kUSBHeadphone1.id, cras_audio_handler_->GetActiveOutputNode());
+ EXPECT_TRUE(cras_audio_handler_->has_alternative_output());
+
+ // Verify the active input device is switched back to USB mic, and
+ // an ActiveInputChanged event is fired.
+ EXPECT_EQ(2, test_observer_->active_input_node_changed_count());
+ EXPECT_EQ(kUSBMic.id, cras_audio_handler_->GetActiveInputNode());
+ EXPECT_TRUE(cras_audio_handler_->has_alternative_input());
+}
+
TEST_F(CrasAudioHandlerTest, MultipleNodesChangedSignalsOnPlugInHeadphone) {
// Set up initial audio devices.
AudioNodeList audio_nodes;
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index 1de255e..dfb8c10 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -1652,6 +1652,13 @@
env, obj.obj(), jresult.obj());
}
+void ContentViewCoreImpl::WebContentsDestroyed(WebContents* web_contents) {
+ WebContentsViewAndroid* wcva =
+ static_cast<WebContentsViewAndroid*>(web_contents->GetView());
+ DCHECK(wcva);
+ wcva->SetContentViewCore(NULL);
+}
+
// This is called for each ContentView.
jlong Init(JNIEnv* env, jobject obj,
jboolean hardware_accelerated,
diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h
index f34d42d..5c61ae6 100644
--- a/content/browser/android/content_view_core_impl.h
+++ b/content/browser/android/content_view_core_impl.h
@@ -329,6 +329,7 @@
// WebContentsObserver implementation.
virtual void RenderViewReady() OVERRIDE;
+ virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
// --------------------------------------------------------------------------
// Other private methods and data
diff --git a/net/base/dir_header.html b/net/base/dir_header.html
index c467f75..77b48b1 100644
--- a/net/base/dir_header.html
+++ b/net/base/dir_header.html
@@ -3,6 +3,7 @@
<html i18n-values="dir:textdirection">
<head>
+<meta charset="utf-8">
<script>
function addRow(name, url, isdir, size, date_modified) {
diff --git a/net/http/http_request_headers.cc b/net/http/http_request_headers.cc
index bf557df..8c9c428 100644
--- a/net/http/http_request_headers.cc
+++ b/net/http/http_request_headers.cc
@@ -11,6 +11,18 @@
#include "base/values.h"
#include "net/http/http_util.h"
+namespace {
+
+bool ShouldShowHttpHeaderValue(const std::string& header_name) {
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+ if (header_name == "Proxy-Authorization")
+ return false;
+#endif
+ return true;
+}
+
+} // namespace
+
namespace net {
const char HttpRequestHeaders::kGetMethod[] = "GET";
@@ -191,10 +203,11 @@
base::ListValue* headers = new base::ListValue();
for (HeaderVector::const_iterator it = headers_.begin();
it != headers_.end(); ++it) {
- headers->Append(
- new base::StringValue(base::StringPrintf("%s: %s",
- it->key.c_str(),
- it->value.c_str())));
+ headers->Append(new base::StringValue(
+ base::StringPrintf("%s: %s",
+ it->key.c_str(),
+ (ShouldShowHttpHeaderValue(it->key) ?
+ it->value.c_str() : "[elided]"))));
}
dict->Set("headers", headers);
return dict;
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc
index 9d95153..289facd 100644
--- a/net/http/http_response_headers.cc
+++ b/net/http/http_response_headers.cc
@@ -113,6 +113,14 @@
CHECK(str.find('\0') == std::string::npos);
}
+bool ShouldShowHttpHeaderValue(const std::string& header_name) {
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+ if (header_name == "Proxy-Authenticate")
+ return false;
+#endif
+ return true;
+}
+
} // namespace
struct HttpResponseHeaders::ParsedHeader {
@@ -1309,9 +1317,11 @@
std::string value;
while (EnumerateHeaderLines(&iterator, &name, &value)) {
headers->Append(
- new base::StringValue(base::StringPrintf("%s: %s",
- name.c_str(),
- value.c_str())));
+ new base::StringValue(
+ base::StringPrintf("%s: %s",
+ name.c_str(),
+ (ShouldShowHttpHeaderValue(name) ?
+ value.c_str() : "[elided]"))));
}
dict->Set("headers", headers);
return dict;
diff --git a/sandbox/win/src/named_pipe_dispatcher.cc b/sandbox/win/src/named_pipe_dispatcher.cc
index 54b3162..da4045c 100644
--- a/sandbox/win/src/named_pipe_dispatcher.cc
+++ b/sandbox/win/src/named_pipe_dispatcher.cc
@@ -5,6 +5,7 @@
#include "sandbox/win/src/named_pipe_dispatcher.h"
#include "base/basictypes.h"
+#include "base/strings/string_split.h"
#include "sandbox/win/src/crosscall_client.h"
#include "sandbox/win/src/interception.h"
@@ -43,6 +44,23 @@
IPCInfo* ipc, base::string16* name, DWORD open_mode, DWORD pipe_mode,
DWORD max_instances, DWORD out_buffer_size, DWORD in_buffer_size,
DWORD default_timeout) {
+ ipc->return_info.win32_result = ERROR_ACCESS_DENIED;
+ ipc->return_info.handle = INVALID_HANDLE_VALUE;
+
+ std::vector<base::string16> paths;
+ std::vector<base::string16> innerpaths;
+ base::SplitString(*name, '/', &paths);
+
+ for (std::vector<base::string16>::const_iterator iter = paths.begin();
+ iter != paths.end(); ++iter) {
+ base::SplitString(*iter, '\\', &innerpaths);
+ for (std::vector<base::string16>::const_iterator iter2 = innerpaths.begin();
+ iter2 != innerpaths.end(); ++iter2) {
+ if (*iter2 == L"..")
+ return true;
+ }
+ }
+
const wchar_t* pipe_name = name->c_str();
CountedParameterSet<NameBased> params;
params[NameBased::NAME] = ParamPickerMake(pipe_name);
@@ -50,6 +68,16 @@
EvalResult eval = policy_base_->EvalPolicy(IPC_CREATENAMEDPIPEW_TAG,
params.GetBase());
+ // "For file I/O, the "\\?\" prefix to a path string tells the Windows APIs to
+ // disable all string parsing and to send the string that follows it straight
+ // to the file system."
+ // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx
+ // This ensures even if there is a path traversal in the pipe name, and it is
+ // able to get past the checks above, it will still not be allowed to escape
+ // our whitelisted namespace.
+ if (name->compare(0, 4, L"\\\\.\\") == 0)
+ name->replace(0, 4, L"\\\\\?\\");
+
HANDLE pipe;
DWORD ret = NamedPipePolicy::CreateNamedPipeAction(eval, *ipc->client_info,
*name, open_mode,
diff --git a/sandbox/win/src/named_pipe_policy_test.cc b/sandbox/win/src/named_pipe_policy_test.cc
index b89a191..fe8c71f 100644
--- a/sandbox/win/src/named_pipe_policy_test.cc
+++ b/sandbox/win/src/named_pipe_policy_test.cc
@@ -1,18 +1,20 @@
-// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "testing/gtest/include/gtest/gtest.h"
+#include "base/win/windows_version.h"
+#include "sandbox/win/src/handle_closer.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "sandbox/win/tests/common/controller.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace sandbox {
SBOX_TESTS_COMMAND int NamedPipe_Create(int argc, wchar_t **argv) {
- if (argc != 1) {
+ if (argc < 1 || argc > 2) {
return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
}
if ((NULL == argv) || (NULL == argv[0])) {
@@ -26,6 +28,18 @@
if (INVALID_HANDLE_VALUE == pipe)
return SBOX_TEST_DENIED;
+ // The second parameter allows us to enforce a whitelist for where the
+ // pipe should be in the object namespace after creation.
+ if (argc == 2) {
+ base::string16 handle_name;
+ if (GetHandleName(pipe, &handle_name)) {
+ if (handle_name.compare(0, wcslen(argv[1]), argv[1]) != 0)
+ return SBOX_TEST_FAILED;
+ } else {
+ return SBOX_TEST_FAILED;
+ }
+ }
+
OVERLAPPED overlapped = {0};
overlapped.hEvent = ::CreateEvent(NULL, TRUE, TRUE, NULL);
BOOL result = ::ConnectNamedPipe(pipe, &overlapped);
@@ -45,19 +59,59 @@
return SBOX_TEST_SUCCEEDED;
}
-// Tests if we can create a pipe in the sandbox. On XP, the sandbox can create
-// a pipe without any help but it fails on Vista, this is why we do not test
-// the "denied" case.
+// Tests if we can create a pipe in the sandbox.
TEST(NamedPipePolicyTest, CreatePipe) {
TestRunner runner;
// TODO(nsylvain): This policy is wrong because "*" is a valid char in a
// namedpipe name. Here we apply it like a wildcard. http://b/893603
EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
TargetPolicy::NAMEDPIPES_ALLOW_ANY,
+ L"\\\\.\\pipe\\test*"));
+
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED,
+ runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh"));
+
+ // On XP, the sandbox can create a pipe without any help but it fails on
+ // Vista+, this is why we do not test the "denied" case.
+ if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) {
+ EXPECT_EQ(SBOX_TEST_DENIED,
+ runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh"));
+ }
+}
+
+// Tests if we can create a pipe with a path traversal in the sandbox.
+TEST(NamedPipePolicyTest, CreatePipeTraversal) {
+ TestRunner runner;
+ // TODO(nsylvain): This policy is wrong because "*" is a valid char in a
+ // namedpipe name. Here we apply it like a wildcard. http://b/893603
+ EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
+ TargetPolicy::NAMEDPIPES_ALLOW_ANY,
L"\\\\.\\pipe\\test*"));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED,
- runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh"));
+ // On XP, the sandbox can create a pipe without any help but it fails on
+ // Vista+, this is why we do not test the "denied" case.
+ if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) {
+ EXPECT_EQ(SBOX_TEST_DENIED,
+ runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\..\\bleh"));
+ EXPECT_EQ(SBOX_TEST_DENIED,
+ runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/../bleh"));
+ EXPECT_EQ(SBOX_TEST_DENIED,
+ runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\../bleh"));
+ EXPECT_EQ(SBOX_TEST_DENIED,
+ runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/..\\bleh"));
+ }
+}
+
+// This tests that path canonicalization is actually disabled if we use \\?\
+// syntax.
+TEST(NamedPipePolicyTest, CreatePipeCanonicalization) {
+ // "For file I/O, the "\\?\" prefix to a path string tells the Windows APIs to
+ // disable all string parsing and to send the string that follows it straight
+ // to the file system."
+ // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx
+ wchar_t* argv[2] = { L"\\\\?\\pipe\\test\\..\\bleh",
+ L"\\Device\\NamedPipe\\test" };
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, NamedPipe_Create(2, argv));
}
// The same test as CreatePipe but this time using strict interceptions.
@@ -73,6 +127,13 @@
EXPECT_EQ(SBOX_TEST_SUCCEEDED,
runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh"));
+
+ // On XP, the sandbox can create a pipe without any help but it fails on
+ // Vista+, this is why we do not test the "denied" case.
+ if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) {
+ EXPECT_EQ(SBOX_TEST_DENIED,
+ runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh"));
+ }
}
} // namespace sandbox
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 478520e..15e41d7 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -4347,6 +4347,40 @@
</summary>
</histogram>
+<histogram name="ExtensionInstalledLoader.ForceDisabled"
+ enum="BooleanForceDisabled">
+ <summary>
+ Counts whether we force-disabled an installed extension at startup because a
+ policy provider indicated it must remain disabled.
+ </summary>
+</histogram>
+
+<histogram name="ExtensionInstallSigner.ResultWasValid">
+ <summary>
+ Whether the server result received by the extensions install signer was
+ valid or invalid.
+ </summary>
+</histogram>
+
+<histogram name="ExtensionInstallVerifier.GetSignatureResult"
+ enum="ExtensionInstallVerifierGetSignatureResult">
+ <summary>The result of the verifier trying to get a new signature.</summary>
+</histogram>
+
+<histogram name="ExtensionInstallVerifier.InitResult"
+ enum="ExtensionInstallVerifierInitResult">
+ <summary>
+ The result of initialization for the extension install verifier.
+ </summary>
+</histogram>
+
+<histogram name="ExtensionInstallVerifier.MustRemainDisabled"
+ enum="ExtensionInstallVerifierMustRemainDisabled">
+ <summary>
+ The outcome for each call to InstallVerifier::MustRemainDisabled.
+ </summary>
+</histogram>
+
<histogram name="Extensions.AllocatePortIdPairOverflow">
<summary>
Records when the allocation of IDs for chrome.runtime.Port overflows.
@@ -22134,6 +22168,11 @@
<int value="1" label="Expired"/>
</enum>
+<enum name="BooleanForceDisabled" type="int">
+ <int value="0" label="Not Force Disabled"/>
+ <int value="1" label="Force Disabled"/>
+</enum>
+
<enum name="BooleanHasCrc" type="int">
<int value="0" label="No CRC"/>
<int value="1" label="Has CRC"/>
@@ -24392,6 +24431,31 @@
<int value="4" label="INSTALL_CAUSE_AUTOMATION"/>
</enum>
+<enum name="ExtensionInstallVerifierGetSignatureResult" type="int">
+ <int value="0" label="No signature (network error, etc)"/>
+ <int value="1" label="Invalid signature"/>
+ <int value="2" label="Valid signature"/>
+</enum>
+
+<enum name="ExtensionInstallVerifierInitResult" type="int">
+ <int value="0" label="No value in prefs"/>
+ <int value="1" label="Pref present but parsing failed"/>
+ <int value="2" label="Invalid signature"/>
+ <int value="3" label="Valid signature"/>
+</enum>
+
+<enum name="ExtensionInstallVerifierMustRemainDisabled" type="int">
+ <int value="0" label="VERIFIED"/>
+ <int value="1" label="NOT_EXTENSION"/>
+ <int value="2" label="UNPACKED"/>
+ <int value="3" label="ENTERPRISE_POLICY_ALLOWED"/>
+ <int value="4" label="FORCED_NOT_VERIFIED"/>
+ <int value="5" label="NOT_FROM_STORE"/>
+ <int value="6" label="NO_SIGNATURE"/>
+ <int value="7" label="NOT_VERIFIED_BUT_NOT_ENFORCING"/>
+ <int value="8" label="NOT_VERIFIED"/>
+</enum>
+
<enum name="ExtensionLaunchType" type="int">
<int value="0" label="PINNED"/>
<int value="1" label="REGULAR"/>