diff --git a/BUILD.gn b/BUILD.gn index b1fd306..04dde8d 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -273,6 +273,7 @@ "//base/android/linker:chromium_android_linker", "//build/android/gyp/test:hello_world", "//build/android/gyp/test:hello_world", + "//build/android/stacktrace:java_deobfuscate", "//chrome/android/webapk/shell_apk:webapk", "//chrome/test/vr/perf:motopho_latency_test", "//components/invalidation/impl:components_invalidation_impl_junit_tests",
diff --git a/DEPS b/DEPS index 6ede7f92..99e5dd5 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '9d5dcda7818abfb1443400b391d3b35f18ffd96a', + 'skia_revision': 'fe11e458b0282bf5ebb7943d3bb9455cb46adf9e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'd98fa02005a2439cae36c36f6e19c867bc07f43d', + 'v8_revision': '0119b296ffa860518b215487ce89d442e0967938', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -235,7 +235,7 @@ Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067', 'src/third_party/webrtc': - Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '9677ff7f09e4265be6e387f513f68e78202d2f34', # commit position 18894 + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'eb8eec46f7c57ab1bc38111c70ae08eb16b8793d', # commit position 18901 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'),
diff --git a/base/metrics/histogram_samples.cc b/base/metrics/histogram_samples.cc index 59f38fc..965d1783 100644 --- a/base/metrics/histogram_samples.cc +++ b/base/metrics/histogram_samples.cc
@@ -164,17 +164,6 @@ memset(this, 0, sizeof(*this)); } -// Don't try to delegate behavior to the constructor below that accepts a -// Matadata pointer by passing &local_meta_. Such cannot be reliably passed -// because it has not yet been constructed -- no member variables have; the -// class itself is in the middle of being constructed. Using it to -// initialize meta_ is okay because the object now exists and local_meta_ -// is before meta_ in the construction order. -HistogramSamples::HistogramSamples(uint64_t id) - : meta_(&local_meta_) { - meta_->id = id; -} - HistogramSamples::HistogramSamples(uint64_t id, Metadata* meta) : meta_(meta) { DCHECK(meta_->id == 0 || meta_->id == id); @@ -185,6 +174,8 @@ meta_->id = id; } +// This mustn't do anything with |meta_|. It was passed to the ctor and may +// be invalid by the time this dtor gets called. HistogramSamples::~HistogramSamples() {} void HistogramSamples::Add(const HistogramSamples& other) {
diff --git a/base/metrics/histogram_samples.h b/base/metrics/histogram_samples.h index cc27d3dd..e6257da 100644 --- a/base/metrics/histogram_samples.h +++ b/base/metrics/histogram_samples.h
@@ -128,7 +128,6 @@ LocalMetadata(); }; - explicit HistogramSamples(uint64_t id); HistogramSamples(uint64_t id, Metadata* meta); virtual ~HistogramSamples(); @@ -180,11 +179,9 @@ return meta_->single_sample; } + Metadata* meta() { return meta_; } + private: - // In order to support histograms shared through an external memory segment, - // meta values may be the local storage or external storage depending on the - // wishes of the derived class. - LocalMetadata local_meta_; Metadata* meta_; DISALLOW_COPY_AND_ASSIGN(HistogramSamples);
diff --git a/base/metrics/sample_map.cc b/base/metrics/sample_map.cc index f0e4e5ed..08fe032 100644 --- a/base/metrics/sample_map.cc +++ b/base/metrics/sample_map.cc
@@ -79,9 +79,11 @@ SampleMap::SampleMap() : SampleMap(0) {} -SampleMap::SampleMap(uint64_t id) : HistogramSamples(id) {} +SampleMap::SampleMap(uint64_t id) : HistogramSamples(id, new LocalMetadata()) {} -SampleMap::~SampleMap() {} +SampleMap::~SampleMap() { + delete static_cast<LocalMetadata*>(meta()); +} void SampleMap::Accumulate(Sample value, Count count) { sample_counts_[value] += count;
diff --git a/base/metrics/sample_vector.cc b/base/metrics/sample_vector.cc index 5306c3e..98214f2 100644 --- a/base/metrics/sample_vector.cc +++ b/base/metrics/sample_vector.cc
@@ -24,12 +24,6 @@ typedef HistogramBase::Sample Sample; SampleVectorBase::SampleVectorBase(uint64_t id, - const BucketRanges* bucket_ranges) - : HistogramSamples(id), bucket_ranges_(bucket_ranges) { - CHECK_GE(bucket_ranges_->bucket_count(), 1u); -} - -SampleVectorBase::SampleVectorBase(uint64_t id, Metadata* meta, const BucketRanges* bucket_ranges) : HistogramSamples(id, meta), bucket_ranges_(bucket_ranges) { @@ -286,9 +280,11 @@ : SampleVector(0, bucket_ranges) {} SampleVector::SampleVector(uint64_t id, const BucketRanges* bucket_ranges) - : SampleVectorBase(id, bucket_ranges) {} + : SampleVectorBase(id, new LocalMetadata(), bucket_ranges) {} -SampleVector::~SampleVector() {} +SampleVector::~SampleVector() { + delete static_cast<LocalMetadata*>(meta()); +} bool SampleVector::MountExistingCountsStorage() const { // There is never any existing storage other than what is already in use.
diff --git a/base/metrics/sample_vector.h b/base/metrics/sample_vector.h index 8e28e29..622bf2c 100644 --- a/base/metrics/sample_vector.h +++ b/base/metrics/sample_vector.h
@@ -29,7 +29,6 @@ class BASE_EXPORT SampleVectorBase : public HistogramSamples { public: - SampleVectorBase(uint64_t id, const BucketRanges* bucket_ranges); SampleVectorBase(uint64_t id, Metadata* meta, const BucketRanges* bucket_ranges);
diff --git a/build/android/adb_command_line.py b/build/android/adb_command_line.py index bf6a65e..78e9e50 100755 --- a/build/android/adb_command_line.py +++ b/build/android/adb_command_line.py
@@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright 2015 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.
diff --git a/build/android/binary_size/apk_downloader.py b/build/android/binary_size/apk_downloader.py index e6d7082..062930d 100755 --- a/build/android/binary_size/apk_downloader.py +++ b/build/android/binary_size/apk_downloader.py
@@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright 2017 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.
diff --git a/build/android/emma_coverage_stats.py b/build/android/emma_coverage_stats.py index 20ec8ea..fe1775a 100755 --- a/build/android/emma_coverage_stats.py +++ b/build/android/emma_coverage_stats.py
@@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright 2015 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.
diff --git a/build/android/emma_coverage_stats_test.py b/build/android/emma_coverage_stats_test.py index 30b409e2..44f6dc3 100755 --- a/build/android/emma_coverage_stats_test.py +++ b/build/android/emma_coverage_stats_test.py
@@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright 2015 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.
diff --git a/build/android/pylib/utils/decorators_test.py b/build/android/pylib/utils/decorators_test.py index d31db9c..60f4811 100755 --- a/build/android/pylib/utils/decorators_test.py +++ b/build/android/pylib/utils/decorators_test.py
@@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright 2017 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.
diff --git a/build/android/resource_sizes.py b/build/android/resource_sizes.py index 0a942a3..c93f675 100755 --- a/build/android/resource_sizes.py +++ b/build/android/resource_sizes.py
@@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright (c) 2011 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.
diff --git a/build/android/stacktrace/BUILD.gn b/build/android/stacktrace/BUILD.gn new file mode 100644 index 0000000..a3957fec --- /dev/null +++ b/build/android/stacktrace/BUILD.gn
@@ -0,0 +1,17 @@ +# Copyright 2017 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. + +import("//build/config/android/rules.gni") + +java_binary("java_deobfuscate") { + main_class = "org.chromium.build.FlushingReTrace" + java_files = [ "java/org/chromium/build/FlushingReTrace.java" ] + deps = [ + "//third_party/proguard:retrace_java", + ] + data = [ + "$root_build_dir/lib.java/build/android/stacktrace/java_deobfuscate.jar", + "$root_build_dir/bin/java_deobfuscate", + ] +}
diff --git a/build/android/stacktrace/README.md b/build/android/stacktrace/README.md new file mode 100644 index 0000000..fb4c035c --- /dev/null +++ b/build/android/stacktrace/README.md
@@ -0,0 +1,18 @@ +# java_deobfuscate + +A wrapper around ProGuard's ReTrace tool, which: + +1) Updates the regular expression used to identify stack lines, and +2) Streams its output. + +The second point here is what allows you to run: + + adb logcat | out/Default/bin/java_deobfuscate + +And have it actually show output without logcat terminating. + + +# stackwalker.py + +Extracts Breakpad microdumps from a log file and uses `stackwalker` to symbolize +them.
diff --git a/build/android/stacktrace/java/org/chromium/build/FlushingReTrace.java b/build/android/stacktrace/java/org/chromium/build/FlushingReTrace.java new file mode 100644 index 0000000..1402511 --- /dev/null +++ b/build/android/stacktrace/java/org/chromium/build/FlushingReTrace.java
@@ -0,0 +1,60 @@ +// Copyright 2017 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. + +package org.chromium.build; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; + +import proguard.retrace.ReTrace; + +/** + * A wrapper around ReTrace that: + * 1. Hardcodes a more useful line regular expression + * 2. Disables output buffering + */ +public class FlushingReTrace { + // This regex is based on the one from: + // http://proguard.sourceforge.net/manual/retrace/usage.html. + // But with the "at" part changed to "(?::|\bat)", to account for lines like: + // 06-22 13:58:02.895 4674 4674 E THREAD_STATE: bLA.a(PG:173) + // Normal stack trace lines look like: + // java.lang.RuntimeException: Intentional Java Crash + // at org.chromium.chrome.browser.tab.Tab.handleJavaCrash(Tab.java:682) + // at org.chromium.chrome.browser.tab.Tab.loadUrl(Tab.java:644) + private static final String LINE_PARSE_REGEX = + "(?:.*?(?::|\\bat)\\s+%c\\.%m\\s*\\(%s(?::%l)?\\)\\s*)|(?:(?:.*?[:\"]\\s+)?%c(?::.*)?)"; + + public static void main(String[] args) { + if (args.length != 1) { + System.err.println("Usage: retrace Foo.apk.map < foo.log > bar.log"); + System.exit(1); + } + + File mappingFile = new File(args[0]); + try { + LineNumberReader reader = new LineNumberReader( + new BufferedReader(new InputStreamReader(System.in, "UTF-8"))); + + // Enabling autoFlush is the main difference from ReTrace.main(). + boolean autoFlush = true; + PrintWriter writer = + new PrintWriter(new OutputStreamWriter(System.out, "UTF-8"), autoFlush); + + boolean verbose = false; + new ReTrace(LINE_PARSE_REGEX, verbose, mappingFile).retrace(reader, writer); + } catch (IOException ex) { + // Print a verbose stack trace. + ex.printStackTrace(); + System.exit(1); + } + + System.exit(0); + } +}
diff --git a/build/android/stacktrace/java_deobfuscate.py b/build/android/stacktrace/java_deobfuscate.py deleted file mode 100755 index 1c73300..0000000 --- a/build/android/stacktrace/java_deobfuscate.py +++ /dev/null
@@ -1,53 +0,0 @@ -#!/usr/bin/env python -# Copyright 2016 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. - -"""A tool to deobfuscate Java stack traces. - -Utility wrapper around ReTrace to deobfuscate stack traces that have been -mangled by ProGuard. Takes stack traces from stdin (eg. adb logcat | -java_deobfuscate.py proguard.mapping) and files. -""" - -import argparse -import os - -_SRC_DIR = os.path.normpath( - os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir)) - -# This regex is based on the one from: -# http://proguard.sourceforge.net/manual/retrace/usage.html. -# But with the "at" part changed to "(?::|\bat)", to account for lines like: -# 06-22 13:58:02.895 4674 4674 E THREAD_STATE: bLA.a(PG:173) -# Normal stack trace lines look like: -# java.lang.RuntimeException: Intentional Java Crash -# at org.chromium.chrome.browser.tab.Tab.handleJavaCrash(Tab.java:682) -# at org.chromium.chrome.browser.tab.Tab.loadUrl(Tab.java:644) -_LINE_PARSE_REGEX = ( - r'(?:.*?(?::|\bat)\s+%c\.%m\s*\(%s(?::%l)?\)\s*)|' - r'(?:(?:.*?[:"]\s+)?%c(?::.*)?)') - - -def main(): - parser = argparse.ArgumentParser(description=(__doc__)) - parser.add_argument( - 'mapping_file', - help='ProGuard mapping file from build which the stacktrace is from.') - parser.add_argument( - '--stacktrace', - help='Stacktrace file to be deobfuscated.') - args = parser.parse_args() - - retrace_path = os.path.join( - _SRC_DIR, 'third_party', 'proguard', 'lib', 'retrace.jar') - - cmd = ['java', '-jar', retrace_path, '-regex', _LINE_PARSE_REGEX, - args.mapping_file] - if args.stacktrace: - cmd.append(args.stacktrace) - os.execvp('java', cmd) - - -if __name__ == '__main__': - main()
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index aef8ea4..611fda7 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -2058,7 +2058,11 @@ } group(target_name) { - forward_variables_from(invoker, [ "data_deps" ]) + forward_variables_from(invoker, + [ + "data", + "data_deps", + ]) public_deps = [ ":$_ijar_target_name", ":$_process_jar_target_name",
diff --git a/build/env_dump.py b/build/env_dump.py index 21edfe63..3f82173 100755 --- a/build/env_dump.py +++ b/build/env_dump.py
@@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright 2013 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.
diff --git a/build/ios/clean_env.py b/build/ios/clean_env.py index 548e2b9..bf56b2f 100755 --- a/build/ios/clean_env.py +++ b/build/ios/clean_env.py
@@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright (c) 2012 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.
diff --git a/build/util/java_action.py b/build/util/java_action.py index abf084c..ed9bb60 100755 --- a/build/util/java_action.py +++ b/build/util/java_action.py
@@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright 2015 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.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java index ffed54c..30113479 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -478,9 +478,10 @@ /** * Constructs a valid referrer using the given authority. * @param authority The authority to use. - * @return Referrer with default policy that uses the valid android app scheme. + * @return Referrer with default policy that uses the valid android app scheme, or null. */ public static Referrer constructValidReferrerForAuthority(String authority) { + if (TextUtils.isEmpty(authority)) return null; return new Referrer(new Uri.Builder().scheme(ANDROID_APP_REFERRER_SCHEME) .authority(authority).build().toString(), Referrer.REFERRER_POLICY_DEFAULT); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHelper.java index 186a039..40274d94 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHelper.java
@@ -40,7 +40,7 @@ static void sendEmail( String email, String subject, String body, String chooserTitle, String fileToAttach) { if (TextUtils.isEmpty(email)) { - Account[] accounts = AccountManagerHelper.get().getGoogleAccounts(); + Account[] accounts = AccountManagerHelper.get().tryGetGoogleAccounts(); if (accounts != null && accounts.length == 1 && Patterns.EMAIL_ADDRESS.matcher(accounts[0].name).matches()) { email = accounts[0].name;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java b/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java index 1a91056..62de119 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java
@@ -42,7 +42,7 @@ public static void checkHasChildAccount(Context context, final Callback<Boolean> callback) { ThreadUtils.assertOnUiThread(); final AccountManagerHelper helper = AccountManagerHelper.get(); - helper.getGoogleAccounts(new Callback<Account[]>() { + helper.tryGetGoogleAccounts(new Callback<Account[]>() { @Override public void onResult(Account[] accounts) { if (accounts.length != 1) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java index 1f7eadcc..b0733e29 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
@@ -115,7 +115,7 @@ @VisibleForTesting protected Account[] getGoogleAccounts() { - return AccountManagerHelper.get().getGoogleAccounts(); + return AccountManagerHelper.get().tryGetGoogleAccounts(); } @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java index 3d3a58a..f2ed200 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java
@@ -75,7 +75,7 @@ Log.d(TAG, "Sign in disallowed"); return; } - AccountManagerHelper.get().getGoogleAccounts(new Callback<Account[]>() { + AccountManagerHelper.get().tryGetGoogleAccounts(new Callback<Account[]>() { @Override public void onResult(Account[] accounts) { if (accounts.length != 1) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAckedReceiver.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAckedReceiver.java index 248e6cfa..5d93ffa 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAckedReceiver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAckedReceiver.java
@@ -57,7 +57,7 @@ TOS_ACKED_ACCOUNTS, null); if (toSAckedAccounts == null || toSAckedAccounts.isEmpty()) return false; AccountManagerHelper accountHelper = AccountManagerHelper.get(); - List<String> accountNames = accountHelper.getGoogleAccountNames(); + List<String> accountNames = accountHelper.tryGetGoogleAccountNames(); if (accountNames.isEmpty()) return false; for (int k = 0; k < accountNames.size(); k++) { if (toSAckedAccounts.contains(accountNames.get(k))) return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SyncedAccountPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SyncedAccountPreference.java index 91deddcc..333893b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SyncedAccountPreference.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SyncedAccountPreference.java
@@ -47,7 +47,7 @@ // signed in account } - Account[] accounts = AccountManagerHelper.get().getGoogleAccounts(); + Account[] accounts = AccountManagerHelper.get().tryGetGoogleAccounts(); String[] accountNames = new String[accounts.length]; String[] accountValues = new String[accounts.length];
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java index 3a9c31b2..44b88cf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java
@@ -195,7 +195,7 @@ * @param profile Profile to use. */ private static void startFetchingAccountsInformation(Context context, Profile profile) { - Account[] accounts = AccountManagerHelper.get().getGoogleAccounts(); + Account[] accounts = AccountManagerHelper.get().tryGetGoogleAccounts(); for (Account account : accounts) { startFetchingAccountInformation(context, profile, account.name); } @@ -381,7 +381,7 @@ accountsCategory.removeAll(); boolean isChildAccount = mProfile.isChild(); - Account[] accounts = AccountManagerHelper.get().getGoogleAccounts(); + Account[] accounts = AccountManagerHelper.get().tryGetGoogleAccounts(); for (final Account account : accounts) { Preference pref = new Preference(getActivity()); pref.setLayoutResource(R.layout.account_management_account_row);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java index 05d495b..0d87f0ed 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java
@@ -253,7 +253,7 @@ updatingGmsDialog = null; } - mAccountManagerHelper.getGoogleAccountNames(new Callback<List<String>>() { + mAccountManagerHelper.tryGetGoogleAccountNames(new Callback<List<String>>() { @Override public void onResult(List<String> result) { if (updatingGmsDialog != null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountTrackerService.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountTrackerService.java index f8f278c..a605db4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountTrackerService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountTrackerService.java
@@ -113,7 +113,7 @@ mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_NOT_STARTED; return; } - AccountManagerHelper.get().getGoogleAccounts(new Callback<Account[]>() { + AccountManagerHelper.get().tryGetGoogleAccounts(new Callback<Account[]>() { @Override public void onResult(final Account[] accounts) { new AsyncTask<Void, Void, String[][]>() { @@ -199,7 +199,7 @@ } mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_VALIDATING; - AccountManagerHelper.get().getGoogleAccounts(new Callback<Account[]>() { + AccountManagerHelper.get().tryGetGoogleAccounts(new Callback<Account[]>() { @Override public void onResult(final Account[] accounts) { if (mSystemAccountsChanged
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java index ce2b8028..b187323 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java
@@ -109,7 +109,7 @@ @CalledByNative public static String[] getSystemAccountNames() { AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(); - java.util.List<String> accountNames = accountManagerHelper.getGoogleAccountNames(); + java.util.List<String> accountNames = accountManagerHelper.tryGetGoogleAccountNames(); return accountNames.toArray(new String[accountNames.size()]); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java index a9728e1..f7dc3ed 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
@@ -146,7 +146,7 @@ if (lastSyncAccountName != null && !lastSyncAccountName.isEmpty()) return; if (!chromePreferenceManager.getSigninPromoShown() - && AccountManagerHelper.get().getGoogleAccountNames().size() > 0) { + && AccountManagerHelper.get().tryGetGoogleAccountNames().size() > 0) { chromePreferenceManager.setShowSigninPromo(true); } @@ -257,7 +257,7 @@ } private static boolean accountExists(Context context, Account account) { - Account[] accounts = AccountManagerHelper.get().getGoogleAccounts(); + Account[] accounts = AccountManagerHelper.get().tryGetGoogleAccounts(); for (Account a : accounts) { if (a.equals(account)) { return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java index cafe88e..cc54812 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java
@@ -10,7 +10,6 @@ import org.chromium.base.Callback; import org.chromium.base.VisibleForTesting; -import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.NativePageHost; import org.chromium.chrome.browser.download.ui.ThumbnailProvider; import org.chromium.chrome.browser.favicon.FaviconHelper; @@ -24,7 +23,6 @@ import java.net.URI; import java.net.URISyntaxException; -import java.util.concurrent.TimeUnit; /** * Class responsible for fetching images for the views in the NewTabPage and Chrome Home. @@ -169,6 +167,10 @@ mIsDestroyed = true; } + public static String getSnippetDomain(URI snippetUri) { + return String.format("%s://%s", snippetUri.getScheme(), snippetUri.getHost()); + } + private void fetchFaviconFromLocalCache(final URI snippetUri, final boolean fallbackToService, final long faviconFetchStartTimeMs, final int faviconSizePx, final SnippetArticle suggestion, final Callback<Bitmap> faviconCallback) { @@ -180,15 +182,15 @@ assert faviconCallback != null; faviconCallback.onResult(image); - recordFaviconFetchResult(suggestion, + recordFaviconFetchHistograms(suggestion, fallbackToService ? FaviconFetchResult.SUCCESS_CACHED : FaviconFetchResult.SUCCESS_FETCHED, - faviconFetchStartTimeMs); + SystemClock.elapsedRealtime() - faviconFetchStartTimeMs); } else if (fallbackToService) { if (!fetchFaviconFromService(suggestion, snippetUri, faviconFetchStartTimeMs, faviconSizePx, faviconCallback)) { - recordFaviconFetchResult(suggestion, FaviconFetchResult.FAILURE, - faviconFetchStartTimeMs); + recordFaviconFetchHistograms(suggestion, FaviconFetchResult.FAILURE, + SystemClock.elapsedRealtime() - faviconFetchStartTimeMs); } } } @@ -202,7 +204,8 @@ /* desiredSizePx */ 0, new Callback<Bitmap>() { @Override public void onResult(Bitmap image) { - recordFaviconFetchTime(faviconFetchStartTimeMs); + SuggestionsMetrics.recordArticleFaviconFetchTime( + SystemClock.elapsedRealtime() - faviconFetchStartTimeMs); if (image == null) return; faviconCallback.onResult(image); } @@ -227,8 +230,8 @@ @Override public void onIconAvailabilityChecked(boolean newlyAvailable) { if (!newlyAvailable) { - recordFaviconFetchResult(suggestion, FaviconFetchResult.FAILURE, - faviconFetchStartTimeMs); + recordFaviconFetchHistograms(suggestion, FaviconFetchResult.FAILURE, + SystemClock.elapsedRealtime() - faviconFetchStartTimeMs); return; } // The download succeeded, the favicon is in the cache; fetch it. @@ -240,22 +243,6 @@ return true; } - private void recordFaviconFetchTime(long faviconFetchStartTimeMs) { - RecordHistogram.recordMediumTimesHistogram( - "NewTabPage.ContentSuggestions.ArticleFaviconFetchTime", - SystemClock.elapsedRealtime() - faviconFetchStartTimeMs, TimeUnit.MILLISECONDS); - } - - private void recordFaviconFetchResult(SnippetArticle suggestion, @FaviconFetchResult int result, - long faviconFetchStartTimeMs) { - // Record the histogram for articles only to have a fair comparision. - if (!suggestion.isArticle()) return; - RecordHistogram.recordEnumeratedHistogram( - "NewTabPage.ContentSuggestions.ArticleFaviconFetchResult", result, - FaviconFetchResult.COUNT); - recordFaviconFetchTime(faviconFetchStartTimeMs); - } - /** * Checks if an icon with the given URL is available. If not, * downloads it and stores it as a favicon/large icon for the given {@code pageUrl}. @@ -285,8 +272,12 @@ return 0; } - public static String getSnippetDomain(URI snippetUri) { - return String.format("%s://%s", snippetUri.getScheme(), snippetUri.getHost()); + private void recordFaviconFetchHistograms( + SnippetArticle suggestion, int result, long fetchTime) { + // Record the histogram for articles only to have a fair comparision. + if (!suggestion.isArticle()) return; + SuggestionsMetrics.recordArticleFaviconFetchResult(result); + SuggestionsMetrics.recordArticleFaviconFetchTime(fetchTime); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java index 61c717a..195549ba 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java
@@ -7,13 +7,17 @@ import android.support.v7.widget.RecyclerView; import org.chromium.base.Callback; +import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.ntp.snippets.CategoryInt; +import org.chromium.chrome.browser.ntp.snippets.FaviconFetchResult; import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.tab.Tab; +import java.util.concurrent.TimeUnit; + /** * Exposes methods to report suggestions related events, for UMA or Fetch scheduling purposes. */ @@ -84,6 +88,30 @@ }); } + // Histogram recordings + + /** + * Records the time it took to fetch a favicon for an article. + * + * @param fetchTime The time it took to fetch the favicon. + */ + public static void recordArticleFaviconFetchTime(long fetchTime) { + RecordHistogram.recordMediumTimesHistogram( + "NewTabPage.ContentSuggestions.ArticleFaviconFetchTime", fetchTime, + TimeUnit.MILLISECONDS); + } + + /** + * Records the result from a favicon fetch for an article. + * + * @param result {@link FaviconFetchResult} The result from the fetch. + */ + public static void recordArticleFaviconFetchResult(@FaviconFetchResult int result) { + RecordHistogram.recordEnumeratedHistogram( + "NewTabPage.ContentSuggestions.ArticleFaviconFetchResult", result, + FaviconFetchResult.COUNT); + } + /** * One-shot reporter that records the first time the user scrolls a {@link RecyclerView}. If it * should be reused, call {@link #reset()} to rearm it.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java index e2de479..ca15dbb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java
@@ -335,7 +335,7 @@ // We remove the the SyncedAccountPreference if there's only 1 account on the device, so // it's possible for accountList to be null if (accountList != null) { - Account[] accounts = AccountManagerHelper.get().getGoogleAccounts(); + Account[] accounts = AccountManagerHelper.get().tryGetGoogleAccounts(); if (accounts.length <= 1) { getPreferenceScreen().removePreference(accountList); } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java index 9a70b610..cb9a248c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -681,7 +681,7 @@ mVrShell.setWebVrModeEnabled(webVrMode, false); // We're entering VR, but not in WebVr mode. - mVrBrowserUsed = !webVrMode; + mVrBrowserUsed = !webVrMode && !mAutopresentWebVr; // onResume needs to be called on GvrLayout after initialization to make sure DON flow works // properly.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/util/FeatureUtilitiesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/util/FeatureUtilitiesTest.java index fdf6d6f4..5a56cc6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/util/FeatureUtilitiesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/util/FeatureUtilitiesTest.java
@@ -26,6 +26,7 @@ import org.chromium.base.test.util.Feature; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.signin.AccountManagerHelper; +import org.chromium.components.signin.test.util.AccountHolder; import org.chromium.components.signin.test.util.FakeAccountManagerDelegate; import java.util.ArrayList; @@ -115,18 +116,6 @@ } @Override - public Account[] getAccountsByType(String accountType) { - if (accountType.equals(mAccountType)) { - // Calling function uses length of array to determine if - // accounts of the requested type are available, so return - // a non-empty array to indicate the account type is correct. - return new Account[] { AccountManagerHelper.createAccountFromName("Dummy") }; - } - - return new Account[0]; - } - - @Override public AuthenticatorDescription[] getAuthenticatorTypes() { AuthenticatorDescription googleAuthenticator = new AuthenticatorDescription(mAccountType, "p1", 0, 0, 0, 0); @@ -149,14 +138,17 @@ }); } - private void setUpAccount(final String accountType) { - mAccountManager = new FakeAuthenticationAccountManager( - mAccountTestingContext, accountType, mTestAccount); - + private void setUpAccountManager(String accountType) { + mAccountManager = new FakeAuthenticationAccountManager(mAccountTestingContext, accountType); AccountManagerHelper.overrideAccountManagerHelperForTests( mAccountTestingContext, mAccountManager); } + private void addTestAccount() { + mAccountManager.addAccountHolderExplicitly( + AccountHolder.builder(mTestAccount).alwaysAccept(true).build()); + } + @Test @SmallTest @Feature({"FeatureUtilities", "Speech"}) @@ -220,7 +212,8 @@ public void testHasGoogleAccountCorrectlyDetected() { // Set up an account manager mock that returns Google account types // when queried. - setUpAccount(AccountManagerHelper.GOOGLE_ACCOUNT_TYPE); + setUpAccountManager(AccountManagerHelper.GOOGLE_ACCOUNT_TYPE); + addTestAccount(); boolean hasAccounts = FeatureUtilities.hasGoogleAccounts( mAccountTestingContext); @@ -242,9 +235,9 @@ @SmallTest @Feature({"FeatureUtilities", "GoogleAccounts"}) public void testHasNoGoogleAccountCorrectlyDetected() { - // Set up an account manager mock that doesn't return Google account - // types when queried. - setUpAccount("Not A Google Account"); + // Set up an account manager mock that doesn't have any accounts and doesn't have Google + // account authenticator. + setUpAccountManager("Not A Google Account"); boolean hasAccounts = FeatureUtilities.hasGoogleAccounts( mAccountTestingContext);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderUnitTest.java index 3698d006..1c1c69a 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderUnitTest.java
@@ -38,6 +38,7 @@ import org.chromium.chrome.browser.init.ChromeBrowserInitializer; import org.chromium.chrome.browser.superviseduser.SupervisedUserContentProvider.SupervisedUserQueryReply; import org.chromium.components.signin.AccountManagerDelegate; +import org.chromium.components.signin.AccountManagerDelegateException; import org.chromium.components.signin.AccountManagerHelper; import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.webrestrictions.browser.WebRestrictionsContentProvider.WebRestrictionsResult; @@ -214,7 +215,8 @@ @SuppressWarnings("unchecked") @Test - public void testShouldProceed_notSignedIn() throws ProcessInitException { + public void testShouldProceed_notSignedIn() + throws ProcessInitException, AccountManagerDelegateException { // Mock things called during startup ChromeBrowserInitializer mockBrowserInitializer = mock(ChromeBrowserInitializer.class); ChromeBrowserInitializer.setForTesting(mockBrowserInitializer); @@ -222,7 +224,7 @@ AccountManagerHelper.overrideAccountManagerHelperForTests( RuntimeEnvironment.application, mockDelegate); Account account = new Account("Google", "Dummy"); - when(mockDelegate.getAccountsByType("Google")).thenReturn(new Account[] {account}); + when(mockDelegate.getAccountsSync()).thenReturn(new Account[] {account}); WebRestrictionsResult result = mSupervisedUserContentProvider.shouldProceed(DEFAULT_CALLING_PACKAGE, "url"); @@ -242,7 +244,7 @@ } @Test - public void testShouldProceed_cannotSignIn() { + public void testShouldProceed_cannotSignIn() throws AccountManagerDelegateException { // Mock things called during startup ChromeBrowserInitializer mockBrowserInitializer = mock(ChromeBrowserInitializer.class); ChromeBrowserInitializer.setForTesting(mockBrowserInitializer); @@ -250,7 +252,7 @@ AccountManagerHelper.overrideAccountManagerHelperForTests( RuntimeEnvironment.application, mockDelegate); Account account = new Account("Google", "Dummy"); - when(mockDelegate.getAccountsByType("Google")).thenReturn(new Account[] {account}); + when(mockDelegate.getAccountsSync()).thenReturn(new Account[] {account}); // Change the behavior of the forced sign-in processor to not sign in. doAnswer(new Answer<Void>() {
diff --git a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc index 4c71856..855d6595 100644 --- a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc +++ b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
@@ -11,12 +11,10 @@ #include <vector> #include "base/location.h" -#include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "chrome/browser/password_manager/native_backend_gnome_x.h" #include "chrome/test/base/testing_profile.h"
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc b/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc index 634ecfc0..1de9f288 100644 --- a/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc +++ b/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc
@@ -16,10 +16,8 @@ #include "base/callback.h" #include "base/location.h" #include "base/pickle.h" -#include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/password_manager/native_backend_kwallet_x.h" #include "chrome/test/base/testing_profile.h" #include "components/autofill/core/common/password_form.h"
diff --git a/chrome/browser/password_manager/native_backend_libsecret_unittest.cc b/chrome/browser/password_manager/native_backend_libsecret_unittest.cc index 217cc48..031395f9 100644 --- a/chrome/browser/password_manager/native_backend_libsecret_unittest.cc +++ b/chrome/browser/password_manager/native_backend_libsecret_unittest.cc
@@ -9,13 +9,11 @@ #include "base/location.h" #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" -#include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_task_environment.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "chrome/browser/password_manager/native_backend_libsecret.h" #include "chrome/test/base/testing_profile.h"
diff --git a/chrome/browser/password_manager/password_store_factory.cc b/chrome/browser/password_manager/password_store_factory.cc index 808fc9f..399a3b2 100644 --- a/chrome/browser/password_manager/password_store_factory.cc +++ b/chrome/browser/password_manager/password_store_factory.cc
@@ -12,8 +12,8 @@ #include "base/memory/ref_counted.h" #include "base/metrics/histogram_macros.h" #include "base/rand_util.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/sequenced_task_runner.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "build/build_config.h" #include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/profile.h" @@ -106,8 +106,7 @@ password_manager::ToggleAffiliationBasedMatchingBasedOnPasswordSyncedState( password_store.get(), sync_service, request_context_getter, - profile->GetPath(), content::BrowserThread::GetTaskRunnerForThread( - content::BrowserThread::DB)); + profile->GetPath()); } PasswordStoreFactory::PasswordStoreFactory() @@ -158,9 +157,9 @@ std::unique_ptr<password_manager::LoginDatabase> login_db( password_manager::CreateLoginDatabase(profile->GetPath())); - scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner( - base::ThreadTaskRunnerHandle::Get()); - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner( + scoped_refptr<base::SequencedTaskRunner> main_thread_runner( + base::SequencedTaskRunnerHandle::Get()); + scoped_refptr<base::SequencedTaskRunner> db_thread_runner( content::BrowserThread::GetTaskRunnerForThread( content::BrowserThread::DB));
diff --git a/chrome/browser/password_manager/password_store_mac.cc b/chrome/browser/password_manager/password_store_mac.cc index 9a2ce7ec..d84ba77 100644 --- a/chrome/browser/password_manager/password_store_mac.cc +++ b/chrome/browser/password_manager/password_store_mac.cc
@@ -11,7 +11,7 @@ using password_manager::MigrationStatus; PasswordStoreMac::PasswordStoreMac( - scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner, + scoped_refptr<base::SequencedTaskRunner> main_thread_runner, std::unique_ptr<password_manager::LoginDatabase> login_db, PrefService* prefs) : PasswordStoreDefault(main_thread_runner, nullptr, std::move(login_db)) { @@ -49,7 +49,7 @@ migration_status_.Destroy(); } -scoped_refptr<base::SingleThreadTaskRunner> +scoped_refptr<base::SequencedTaskRunner> PasswordStoreMac::GetBackgroundTaskRunner() { return thread_ ? thread_->task_runner() : nullptr; } @@ -57,7 +57,7 @@ PasswordStoreMac::~PasswordStoreMac() = default; void PasswordStoreMac::InitOnBackgroundThread(MigrationStatus status) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); if (login_db() && (status == MigrationStatus::NOT_STARTED || status == MigrationStatus::FAILED_ONCE ||
diff --git a/chrome/browser/password_manager/password_store_mac.h b/chrome/browser/password_manager/password_store_mac.h index fa720d5..044a1554 100644 --- a/chrome/browser/password_manager/password_store_mac.h +++ b/chrome/browser/password_manager/password_store_mac.h
@@ -20,17 +20,15 @@ // Password store for Mac. It creates a dedicated background thread class PasswordStoreMac : public password_manager::PasswordStoreDefault { public: - PasswordStoreMac( - scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner, - std::unique_ptr<password_manager::LoginDatabase> login_db, - PrefService* prefs); + PasswordStoreMac(scoped_refptr<base::SequencedTaskRunner> main_thread_runner, + std::unique_ptr<password_manager::LoginDatabase> login_db, + PrefService* prefs); // PasswordStore: bool Init(const syncer::SyncableService::StartSyncFlare& flare, PrefService* prefs) override; void ShutdownOnUIThread() override; - scoped_refptr<base::SingleThreadTaskRunner> GetBackgroundTaskRunner() - override; + scoped_refptr<base::SequencedTaskRunner> GetBackgroundTaskRunner() override; #if defined(UNIT_TEST) password_manager::LoginDatabase* login_metadata_db() { return login_db(); }
diff --git a/chrome/browser/password_manager/password_store_win.cc b/chrome/browser/password_manager/password_store_win.cc index 252b2700..5835bf3 100644 --- a/chrome/browser/password_manager/password_store_win.cc +++ b/chrome/browser/password_manager/password_store_win.cc
@@ -174,8 +174,8 @@ } PasswordStoreWin::PasswordStoreWin( - scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner, - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner, + scoped_refptr<base::SequencedTaskRunner> main_thread_runner, + scoped_refptr<base::SequencedTaskRunner> db_thread_runner, std::unique_ptr<password_manager::LoginDatabase> login_db, const scoped_refptr<PasswordWebDataService>& web_data_service) : PasswordStoreDefault(main_thread_runner,
diff --git a/chrome/browser/password_manager/password_store_win.h b/chrome/browser/password_manager/password_store_win.h index acdaca0..e46344c 100644 --- a/chrome/browser/password_manager/password_store_win.h +++ b/chrome/browser/password_manager/password_store_win.h
@@ -8,7 +8,7 @@ #include <memory> #include "base/macros.h" -#include "base/single_thread_task_runner.h" +#include "base/sequenced_task_runner.h" #include "components/password_manager/core/browser/password_store_default.h" class PasswordWebDataService; @@ -25,8 +25,8 @@ // a deferred manner on the DB thread. The |web_data_service| is only used for // IE7 password fetching. PasswordStoreWin( - scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner, - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner, + scoped_refptr<base::SequencedTaskRunner> main_thread_runner, + scoped_refptr<base::SequencedTaskRunner> db_thread_runner, std::unique_ptr<password_manager::LoginDatabase> login_db, const scoped_refptr<PasswordWebDataService>& web_data_service);
diff --git a/chrome/browser/password_manager/password_store_win_unittest.cc b/chrome/browser/password_manager/password_store_win_unittest.cc index 62c9c76..1477c8f 100644 --- a/chrome/browser/password_manager/password_store_win_unittest.cc +++ b/chrome/browser/password_manager/password_store_win_unittest.cc
@@ -18,9 +18,9 @@ #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "base/single_thread_task_runner.h" +#include "base/sequenced_task_runner.h" #include "base/synchronization/waitable_event.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" #include "chrome/test/base/testing_profile.h" #include "components/os_crypt/ie7_password_win.h" @@ -171,7 +171,7 @@ PasswordStoreWin* CreatePasswordStore() { return new PasswordStoreWin( - base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), BrowserThread::GetTaskRunnerForThread(BrowserThread::DB), base::MakeUnique<LoginDatabase>(test_login_db_file_path()), wds_.get()); }
diff --git a/chrome/browser/password_manager/password_store_x.cc b/chrome/browser/password_manager/password_store_x.cc index b802e900..927dc6e 100644 --- a/chrome/browser/password_manager/password_store_x.cc +++ b/chrome/browser/password_manager/password_store_x.cc
@@ -61,8 +61,8 @@ } // namespace PasswordStoreX::PasswordStoreX( - scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner, - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner, + scoped_refptr<base::SequencedTaskRunner> main_thread_runner, + scoped_refptr<base::SequencedTaskRunner> db_thread_runner, std::unique_ptr<password_manager::LoginDatabase> login_db, NativeBackend* backend) : PasswordStoreDefault(main_thread_runner,
diff --git a/chrome/browser/password_manager/password_store_x.h b/chrome/browser/password_manager/password_store_x.h index 3d16ecb..5207456e 100644 --- a/chrome/browser/password_manager/password_store_x.h +++ b/chrome/browser/password_manager/password_store_x.h
@@ -11,7 +11,7 @@ #include <vector> #include "base/macros.h" -#include "base/single_thread_task_runner.h" +#include "base/sequenced_task_runner.h" #include "base/time/time.h" #include "components/password_manager/core/browser/password_store_default.h" @@ -88,8 +88,8 @@ // Takes ownership of |login_db| and |backend|. |backend| may be NULL in which // case this PasswordStoreX will act the same as PasswordStoreDefault. - PasswordStoreX(scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner, - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner, + PasswordStoreX(scoped_refptr<base::SequencedTaskRunner> main_thread_runner, + scoped_refptr<base::SequencedTaskRunner> db_thread_runner, std::unique_ptr<password_manager::LoginDatabase> login_db, NativeBackend* backend);
diff --git a/chrome/browser/password_manager/password_store_x_unittest.cc b/chrome/browser/password_manager/password_store_x_unittest.cc index a779c0d0..67cd935 100644 --- a/chrome/browser/password_manager/password_store_x_unittest.cc +++ b/chrome/browser/password_manager/password_store_x_unittest.cc
@@ -18,7 +18,7 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" #include "chrome/test/base/testing_browser_process.h" #include "components/password_manager/core/browser/password_manager_test_utils.h" @@ -333,8 +333,8 @@ PasswordStoreXTestDelegate::PasswordStoreXTestDelegate(BackendType backend_type) : backend_type_(backend_type) { SetupTempDir(); - store_ = new PasswordStoreX(base::ThreadTaskRunnerHandle::Get(), - base::ThreadTaskRunnerHandle::Get(), + store_ = new PasswordStoreX(base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::MakeUnique<password_manager::LoginDatabase>( test_login_db_file_path()), GetBackend(backend_type_)); @@ -402,9 +402,10 @@ TEST_P(PasswordStoreXTest, Notifications) { std::unique_ptr<password_manager::LoginDatabase> login_db( new password_manager::LoginDatabase(test_login_db_file_path())); - scoped_refptr<PasswordStoreX> store(new PasswordStoreX( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), - std::move(login_db), GetBackend(GetParam()))); + scoped_refptr<PasswordStoreX> store( + new PasswordStoreX(base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + std::move(login_db), GetBackend(GetParam()))); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); password_manager::PasswordFormData form_data = { @@ -508,9 +509,10 @@ // Initializing the PasswordStore shouldn't trigger a native migration (yet). login_db.reset(new password_manager::LoginDatabase(login_db_file)); - scoped_refptr<PasswordStoreX> store(new PasswordStoreX( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), - std::move(login_db), GetBackend(GetParam()))); + scoped_refptr<PasswordStoreX> store( + new PasswordStoreX(base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + std::move(login_db), GetBackend(GetParam()))); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); MockPasswordStoreConsumer consumer;
diff --git a/chrome/browser/resource_coordinator/tab_manager.cc b/chrome/browser/resource_coordinator/tab_manager.cc index 296ab6d8b..9db21d6 100644 --- a/chrome/browser/resource_coordinator/tab_manager.cc +++ b/chrome/browser/resource_coordinator/tab_manager.cc
@@ -224,6 +224,20 @@ min_time_to_purge_ = kDefaultMinTimeToPurge; else min_time_to_purge_ = base::TimeDelta::FromSeconds(min_time_to_purge_sec); + + std::string max_purge_and_suspend_time = variations::GetVariationParamValue( + "PurgeAndSuspend", "max-purge-and-suspend-time"); + unsigned int max_time_to_purge_sec = 0; + // If max-purge-and-suspend-time is not specified or + // max-purge-and-suspend-time is not valid (not number or smaller than + // min-purge-and-suspend-time), use default max-time-to-purge, i.e. + // min-time-to-purge times kDefaultMinMaxTimeToPurgeRatio. + if (max_purge_and_suspend_time.empty() || + !base::StringToUint(max_purge_and_suspend_time, &max_time_to_purge_sec) || + max_time_to_purge_sec < min_time_to_purge_.InSeconds()) + max_time_to_purge_ = min_time_to_purge_ * kDefaultMinMaxTimeToPurgeRatio; + else + max_time_to_purge_ = base::TimeDelta::FromSeconds(max_time_to_purge_sec); } void TabManager::Stop() { @@ -670,10 +684,10 @@ } base::TimeDelta TabManager::GetTimeToPurge( - base::TimeDelta min_time_to_purge) const { - return base::TimeDelta::FromSeconds( - base::RandInt(min_time_to_purge.InSeconds(), - min_time_to_purge.InSeconds() * kMinMaxTimeToPurgeRatio)); + base::TimeDelta min_time_to_purge, + base::TimeDelta max_time_to_purge) const { + return base::TimeDelta::FromSeconds(base::RandInt( + min_time_to_purge.InSeconds(), max_time_to_purge.InSeconds())); } bool TabManager::ShouldPurgeNow(content::WebContents* content) const { @@ -812,7 +826,8 @@ GetWebContentsData(old_contents)->SetLastInactiveTime(NowTicks()); // Re-setting time-to-purge every time a tab becomes inactive. GetWebContentsData(old_contents) - ->set_time_to_purge(GetTimeToPurge(min_time_to_purge_)); + ->set_time_to_purge( + GetTimeToPurge(min_time_to_purge_, max_time_to_purge_)); // Only record switch-to-tab metrics when a switch happens, i.e. // |old_contents| is set. RecordSwitchToTab(new_contents); @@ -842,7 +857,7 @@ GetWebContentsData(contents)->SetLastInactiveTime(NowTicks()); // Re-setting time-to-purge every time a tab becomes inactive. GetWebContentsData(contents)->set_time_to_purge( - GetTimeToPurge(min_time_to_purge_)); + GetTimeToPurge(min_time_to_purge_, max_time_to_purge_)); } void TabManager::OnBrowserSetLastActive(Browser* browser) {
diff --git a/chrome/browser/resource_coordinator/tab_manager.h b/chrome/browser/resource_coordinator/tab_manager.h index 9f3ecddd..83f6a1b 100644 --- a/chrome/browser/resource_coordinator/tab_manager.h +++ b/chrome/browser/resource_coordinator/tab_manager.h
@@ -203,7 +203,7 @@ // The min/max time to purge ratio. The max time to purge is set to be // min time to purge times this value. - const int kMinMaxTimeToPurgeRatio = 2; + const int kDefaultMinMaxTimeToPurgeRatio = 2; // This is needed so WebContentsData can call OnDiscardedStateChange, and // can use PurgeState. @@ -259,8 +259,9 @@ content::WebContents* GetWebContentsById(int64_t tab_contents_id) const; // Returns a random time-to-purge whose min value is min_time_to_purge and max - // value is min_time_to_purge * kMinMaxTimeToPurgeRatio. - base::TimeDelta GetTimeToPurge(base::TimeDelta min_time_to_purge) const; + // value is max_time_to_purge. + base::TimeDelta GetTimeToPurge(base::TimeDelta min_time_to_purge, + base::TimeDelta max_time_to_purge) const; // Returns true if the tab specified by |content| is now eligible to have // its memory purged. @@ -373,8 +374,10 @@ // backgrounded. base::TimeDelta minimum_protection_time_; - // A backgrounded renderer will be purged when this time passes. + // A backgrounded renderer will be purged between min_time_to_purge_ and + // max_time_to_purge_. base::TimeDelta min_time_to_purge_; + base::TimeDelta max_time_to_purge_; #if defined(OS_CHROMEOS) std::unique_ptr<TabManagerDelegate> delegate_;
diff --git a/chrome/browser/resource_coordinator/tab_manager_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_unittest.cc index 6e3f7507..63a8ed33 100644 --- a/chrome/browser/resource_coordinator/tab_manager_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_unittest.cc
@@ -415,7 +415,8 @@ TEST_F(TabManagerTest, DefaultTimeToPurgeInCorrectRange) { TabManager tab_manager; base::TimeDelta time_to_purge = - tab_manager.GetTimeToPurge(TabManager::kDefaultMinTimeToPurge); + tab_manager.GetTimeToPurge(TabManager::kDefaultMinTimeToPurge, + TabManager::kDefaultMinTimeToPurge * 2); EXPECT_GE(time_to_purge, base::TimeDelta::FromMinutes(30)); EXPECT_LT(time_to_purge, base::TimeDelta::FromMinutes(60)); }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java index bfd92e5..9945784 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java
@@ -84,7 +84,7 @@ * Removes all fake accounts from the OS. */ public void removeAllFakeAccountsFromOs() { - for (Account acct : mFakeAccountManagerDelegate.getAccountsByType(GOOGLE_ACCOUNT_TYPE)) { + for (Account acct : mFakeAccountManagerDelegate.getAccountsSyncNoThrow()) { mFakeAccountManagerDelegate.removeAccountHolderExplicitly( AccountHolder.builder(acct).build()); } @@ -97,11 +97,7 @@ * @return {@code true} if fake account is on OS, false otherwise. */ public boolean isExistingFakeAccountOnOs(String username) { - if (mFakeAccountManagerDelegate.getAccountsByType(GOOGLE_ACCOUNT_TYPE).length == 0) { - return false; - } - - for (Account acct : mFakeAccountManagerDelegate.getAccountsByType(GOOGLE_ACCOUNT_TYPE)) { + for (Account acct : mFakeAccountManagerDelegate.getAccountsSyncNoThrow()) { if (username.equals(acct.name)) { return true; }
diff --git a/chrome/test/base/mash_browser_tests_main.cc b/chrome/test/base/mash_browser_tests_main.cc index af58976c..023ca48b 100644 --- a/chrome/test/base/mash_browser_tests_main.cc +++ b/chrome/test/base/mash_browser_tests_main.cc
@@ -28,6 +28,7 @@ #include "chrome/test/base/mojo_test_connector.h" #include "content/public/app/content_main.h" #include "content/public/common/service_manager_connection.h" +#include "content/public/common/service_names.mojom.h" #include "content/public/test/test_launcher.h" #include "mash/session/public/interfaces/constants.mojom.h" #include "services/service_manager/public/cpp/connector.h" @@ -178,6 +179,20 @@ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); if (!command_line->HasSwitch("run-in-mash") && !command_line->HasSwitch("run-in-mus")) { + // Currently launching content_package_services via the browser_tests binary + // will lead to a nested test suite, trying to run all tests again. However + // they will be in a strange mixed mode, of a local-Ash, but non-local Aura. + // + // This leads to continuous crashes in OzonePlatform. + // + // For now disable this launch until the requesting site can be identified. + // + // TODO(jonross): find an appropriate way to launch content_package_services + // within the mash_browser_tests (crbug.com/738449) + if (command_line->GetSwitchValueASCII("service-name") == + content::mojom::kPackagedServicesServiceName) { + return true; + } return false; }
diff --git a/components/password_manager/content/browser/credential_manager_impl_unittest.cc b/components/password_manager/content/browser/credential_manager_impl_unittest.cc index d4a7b17..af7f513 100644 --- a/components/password_manager/content/browser/credential_manager_impl_unittest.cc +++ b/components/password_manager/content/browser/credential_manager_impl_unittest.cc
@@ -18,10 +18,9 @@ #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "base/single_thread_task_runner.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "components/password_manager/core/browser/android_affiliation/mock_affiliated_match_helper.h" #include "components/password_manager/core/browser/credential_manager_password_form_manager.h" #include "components/password_manager/core/browser/password_manager.h" @@ -104,7 +103,7 @@ const CredentialsCallback& callback) override { EXPECT_FALSE(local_forms.empty()); const autofill::PasswordForm* form = local_forms[0].get(); - base::ThreadTaskRunnerHandle::Get()->PostTask( + base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(callback, base::Owned(new autofill::PasswordForm(*form)))); std::vector<autofill::PasswordForm*> raw_forms(local_forms.size());
diff --git a/components/password_manager/content/renderer/credential_manager_client_browsertest.cc b/components/password_manager/content/renderer/credential_manager_client_browsertest.cc index 1a0342c..8e3c029 100644 --- a/components/password_manager/content/renderer/credential_manager_client_browsertest.cc +++ b/components/password_manager/content/renderer/credential_manager_client_browsertest.cc
@@ -13,8 +13,6 @@ #include "base/location.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" #include "content/public/test/render_view_test.h"
diff --git a/components/password_manager/core/browser/android_affiliation/affiliated_match_helper.cc b/components/password_manager/core/browser/android_affiliation/affiliated_match_helper.cc index b4c85c64..8f250dbd 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliated_match_helper.cc +++ b/components/password_manager/core/browser/android_affiliation/affiliated_match_helper.cc
@@ -9,8 +9,7 @@ #include "base/barrier_closure.h" #include "base/bind.h" #include "base/callback.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/browser/android_affiliation/affiliation_service.h" @@ -50,7 +49,7 @@ void AffiliatedMatchHelper::Initialize() { DCHECK(password_store_); DCHECK(affiliation_service_); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&AffiliatedMatchHelper::DoDeferredInitialization, weak_ptr_factory_.GetWeakPtr()),
diff --git a/components/password_manager/core/browser/android_affiliation/affiliated_match_helper.h b/components/password_manager/core/browser/android_affiliation/affiliated_match_helper.h index 2266160..45f9606 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliated_match_helper.h +++ b/components/password_manager/core/browser/android_affiliation/affiliated_match_helper.h
@@ -142,7 +142,6 @@ std::vector<std::unique_ptr<autofill::PasswordForm>> results) override; PasswordStore* const password_store_; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_waiting_; // Being the sole consumer of AffiliationService, |this| owns the service. std::unique_ptr<AffiliationService> affiliation_service_;
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_backend.cc b/components/password_manager/core/browser/android_affiliation/affiliation_backend.cc index 4221dafe..20b8e0c 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliation_backend.cc +++ b/components/password_manager/core/browser/android_affiliation/affiliation_backend.cc
@@ -12,8 +12,7 @@ #include "base/location.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_checker.h" +#include "base/sequenced_task_runner.h" #include "base/time/clock.h" #include "base/time/tick_clock.h" #include "base/time/time.h" @@ -27,7 +26,7 @@ AffiliationBackend::AffiliationBackend( const scoped_refptr<net::URLRequestContextGetter>& request_context_getter, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, + const scoped_refptr<base::SequencedTaskRunner>& task_runner, std::unique_ptr<base::Clock> time_source, std::unique_ptr<base::TickClock> time_tick_source) : request_context_getter_(request_context_getter), @@ -37,14 +36,14 @@ construction_time_(clock_->Now()), weak_ptr_factory_(this) { DCHECK_LT(base::Time(), clock_->Now()); + DETACH_FROM_SEQUENCE(sequence_checker_); } AffiliationBackend::~AffiliationBackend() { } void AffiliationBackend::Initialize(const base::FilePath& db_path) { - thread_checker_.reset(new base::ThreadChecker); - + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!throttler_); throttler_.reset( new AffiliationFetchThrottler(this, task_runner_, tick_clock_.get())); @@ -62,7 +61,7 @@ StrategyOnCacheMiss cache_miss_strategy, const AffiliationService::ResultCallback& callback, const scoped_refptr<base::TaskRunner>& callback_task_runner) { - DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); FacetManager* facet_manager = GetOrCreateFacetManager(facet_uri); DCHECK(facet_manager); @@ -75,7 +74,7 @@ void AffiliationBackend::Prefetch(const FacetURI& facet_uri, const base::Time& keep_fresh_until) { - DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); FacetManager* facet_manager = GetOrCreateFacetManager(facet_uri); DCHECK(facet_manager); @@ -87,7 +86,7 @@ void AffiliationBackend::CancelPrefetch(const FacetURI& facet_uri, const base::Time& keep_fresh_until) { - DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto facet_manager_it = facet_managers_.find(facet_uri); if (facet_manager_it == facet_managers_.end()) @@ -99,7 +98,7 @@ } void AffiliationBackend::TrimCacheForFacet(const FacetURI& facet_uri) { - DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); AffiliatedFacetsWithUpdateTime affiliation; if (cache_->GetAffiliationsForFacet(facet_uri, &affiliation)) @@ -123,7 +122,7 @@ void AffiliationBackend::DiscardCachedDataIfNoLongerNeeded( const AffiliatedFacets& affiliated_facets) { - DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Discard the equivalence class if there is no facet in the class whose // FacetManager claims that it needs to keep the data. @@ -140,7 +139,7 @@ } void AffiliationBackend::OnSendNotification(const FacetURI& facet_uri) { - DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto facet_manager_it = facet_managers_.find(facet_uri); if (facet_manager_it == facet_managers_.end()) @@ -173,7 +172,7 @@ void AffiliationBackend::OnFetchSucceeded( std::unique_ptr<AffiliationFetcherDelegate::Result> result) { - DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); fetcher_.reset(); throttler_->InformOfNetworkRequestComplete(true); @@ -219,7 +218,7 @@ } void AffiliationBackend::OnFetchFailed() { - DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); fetcher_.reset(); throttler_->InformOfNetworkRequestComplete(false); @@ -234,7 +233,7 @@ } void AffiliationBackend::OnMalformedResponse() { - DCHECK(thread_checker_ && thread_checker_->CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // TODO(engedy): Potentially handle this case differently. crbug.com/437865. OnFetchFailed();
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_backend.h b/components/password_manager/core/browser/android_affiliation/affiliation_backend.h index 467cc650..44f3ec9 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliation_backend.h +++ b/components/password_manager/core/browser/android_affiliation/affiliation_backend.h
@@ -15,6 +15,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" #include "components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_delegate.h" #include "components/password_manager/core/browser/android_affiliation/affiliation_fetcher_delegate.h" #include "components/password_manager/core/browser/android_affiliation/affiliation_service.h" @@ -24,9 +25,8 @@ namespace base { class Clock; class FilePath; -class SingleThreadTaskRunner; +class SequencedTaskRunner; class TaskRunner; -class ThreadChecker; class TickClock; class Time; } // namespace base @@ -62,7 +62,7 @@ // Construction is very cheap, expensive steps are deferred to Initialize(). AffiliationBackend( const scoped_refptr<net::URLRequestContextGetter>& request_context_getter, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, + const scoped_refptr<base::SequencedTaskRunner>& task_runner, std::unique_ptr<base::Clock> time_source, std::unique_ptr<base::TickClock> time_tick_source); ~AffiliationBackend() override; @@ -135,12 +135,12 @@ void SetThrottlerForTesting( std::unique_ptr<AffiliationFetchThrottler> throttler); - // Created in Initialize(), and ensures that all subsequent methods are called - // on the same thread. - std::unique_ptr<base::ThreadChecker> thread_checker_; + // Ensures that all methods, excluding construction, are called on the same + // sequence. + SEQUENCE_CHECKER(sequence_checker_); scoped_refptr<net::URLRequestContextGetter> request_context_getter_; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + scoped_refptr<base::SequencedTaskRunner> task_runner_; std::unique_ptr<base::Clock> clock_; std::unique_ptr<base::TickClock> tick_clock_;
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler.cc b/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler.cc index 0ec5f76a..9721b72 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler.cc +++ b/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler.cc
@@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/rand_util.h" +#include "base/sequenced_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/tick_clock.h" #include "base/time/time.h" @@ -50,7 +51,7 @@ AffiliationFetchThrottler::AffiliationFetchThrottler( AffiliationFetchThrottlerDelegate* delegate, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, + const scoped_refptr<base::SequencedTaskRunner>& task_runner, base::TickClock* tick_clock) : delegate_(delegate), task_runner_(task_runner),
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler.h b/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler.h index 770cd65..d9a3cba 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler.h +++ b/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler.h
@@ -18,7 +18,7 @@ namespace base { class TickClock; -class SingleThreadTaskRunner; +class SequencedTaskRunner; } // namespace base namespace password_manager { @@ -57,7 +57,7 @@ // |delegate| and |tick_clock| should outlive the throttler. AffiliationFetchThrottler( AffiliationFetchThrottlerDelegate* delegate, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, + const scoped_refptr<base::SequencedTaskRunner>& task_runner, base::TickClock* tick_clock); ~AffiliationFetchThrottler() override; @@ -118,7 +118,7 @@ void OnConnectionTypeChanged( net::NetworkChangeNotifier::ConnectionType type) override; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + scoped_refptr<base::SequencedTaskRunner> task_runner_; base::TickClock* tick_clock_; State state_; bool has_network_connectivity_;
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_service.cc b/components/password_manager/core/browser/android_affiliation/affiliation_service.cc index 71463423..98eb5f56 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliation_service.cc +++ b/components/password_manager/core/browser/android_affiliation/affiliation_service.cc
@@ -9,8 +9,8 @@ #include "base/files/file_path.h" #include "base/location.h" #include "base/memory/ptr_util.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/sequenced_task_runner.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/time/default_clock.h" #include "base/time/default_tick_clock.h" #include "components/password_manager/core/browser/android_affiliation/affiliation_backend.h" @@ -19,14 +19,13 @@ namespace password_manager { AffiliationService::AffiliationService( - scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner) + scoped_refptr<base::SequencedTaskRunner> backend_task_runner) : backend_(nullptr), backend_task_runner_(backend_task_runner), - weak_ptr_factory_(this) { -} + weak_ptr_factory_(this) {} AffiliationService::~AffiliationService() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (backend_) { backend_task_runner_->DeleteSoon(FROM_HERE, backend_); backend_ = nullptr; @@ -36,7 +35,7 @@ void AffiliationService::Initialize( net::URLRequestContextGetter* request_context_getter, const base::FilePath& db_path) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!backend_); backend_ = new AffiliationBackend(request_context_getter, backend_task_runner_, @@ -53,18 +52,18 @@ const FacetURI& facet_uri, StrategyOnCacheMiss cache_miss_strategy, const ResultCallback& result_callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(backend_); backend_task_runner_->PostTask( FROM_HERE, base::Bind(&AffiliationBackend::GetAffiliations, base::Unretained(backend_), facet_uri, cache_miss_strategy, - result_callback, base::ThreadTaskRunnerHandle::Get())); + result_callback, base::SequencedTaskRunnerHandle::Get())); } void AffiliationService::Prefetch(const FacetURI& facet_uri, const base::Time& keep_fresh_until) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(backend_); backend_task_runner_->PostTask( FROM_HERE, @@ -74,7 +73,7 @@ void AffiliationService::CancelPrefetch(const FacetURI& facet_uri, const base::Time& keep_fresh_until) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(backend_); backend_task_runner_->PostTask( FROM_HERE, @@ -83,7 +82,7 @@ } void AffiliationService::TrimCacheForFacet(const FacetURI& facet_uri) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(backend_); backend_task_runner_->PostTask( FROM_HERE, base::Bind(&AffiliationBackend::TrimCacheForFacet,
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_service.h b/components/password_manager/core/browser/android_affiliation/affiliation_service.h index 5e94a3a..168cae9 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliation_service.h +++ b/components/password_manager/core/browser/android_affiliation/affiliation_service.h
@@ -11,13 +11,13 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "base/threading/thread_checker.h" +#include "base/sequence_checker.h" #include "components/keyed_service/core/keyed_service.h" #include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h" namespace base { class FilePath; -class SingleThreadTaskRunner; +class SequencedTaskRunner; } // namespace base namespace net { @@ -98,8 +98,8 @@ // The |backend_task_runner| should be a task runner corresponding to a thread // that can take blocking I/O, and is normally Chrome's DB thread. - AffiliationService( - scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner); + explicit AffiliationService( + scoped_refptr<base::SequencedTaskRunner> backend_task_runner); ~AffiliationService() override; // Initializes the service by creating its backend and transferring it to the @@ -150,10 +150,10 @@ // thread, so it will outlive |this| along with all its in-flight tasks. AffiliationBackend* backend_; - // TaskRunner to be used to run the |backend_| (usually the DB thread). - scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner_; + // TaskRunner to be used to run the |backend_|. + scoped_refptr<base::SequencedTaskRunner> backend_task_runner_; - base::ThreadChecker thread_checker_; + SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory<AffiliationService> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(AffiliationService);
diff --git a/components/password_manager/core/browser/hash_password_manager.cc b/components/password_manager/core/browser/hash_password_manager.cc index a12d7bd7..8d6bb63c 100644 --- a/components/password_manager/core/browser/hash_password_manager.cc +++ b/components/password_manager/core/browser/hash_password_manager.cc
@@ -8,6 +8,7 @@ #include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" #include "components/os_crypt/os_crypt.h" +#include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_service.h" #include "crypto/random.h" @@ -24,8 +25,9 @@ return false; std::string salt = CreateRandomSalt(); - // TODO(crbug.com/657041) Implement hash calculation. - prefs_->SetString(prefs::kSyncPasswordHash, std::string()); + std::string hash = base::Uint64ToString( + password_manager_util::CalculateSyncPasswordHash(password, salt)); + EncryptAndSaveToPrefs(prefs::kSyncPasswordHash, hash); // Password length and salt are stored together. std::string length_salt = LengthAndSaltToString(salt, password.size()); @@ -40,15 +42,13 @@ base::Optional<SyncPasswordData> HashPasswordManager::RetrievePasswordHash() { if (!prefs_ || !prefs_->HasPrefPath(prefs::kSyncPasswordHash)) - return base::Optional<SyncPasswordData>(); + return base::nullopt; SyncPasswordData result; std::string hash_str = RetrivedDecryptedStringFromPrefs(prefs::kSyncPasswordHash); - // TODO(crbug.com/657041) Add checking of hash correctness retrieving when - // hash calculation is implemented. if (!base::StringToUint64(hash_str, &result.hash)) - result.hash = 0; + return base::nullopt; StringToLengthAndSalt( RetrivedDecryptedStringFromPrefs(prefs::kSyncPasswordLengthAndHashSalt),
diff --git a/components/password_manager/core/browser/hash_password_manager_unittest.cc b/components/password_manager/core/browser/hash_password_manager_unittest.cc index 06ef4c445..ebbf616 100644 --- a/components/password_manager/core/browser/hash_password_manager_unittest.cc +++ b/components/password_manager/core/browser/hash_password_manager_unittest.cc
@@ -6,6 +6,7 @@ #include "base/strings/utf_string_conversions.h" #include "components/os_crypt/os_crypt_mocker.h" +#include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" @@ -58,13 +59,14 @@ hash_password_manager.SavePasswordHash(base::ASCIIToUTF16("sync_password")); EXPECT_TRUE(prefs_.HasPrefPath(prefs::kSyncPasswordLengthAndHashSalt)); - base::Optional<SyncPasswordData> sync_password_date = + base::Optional<SyncPasswordData> sync_password_data = hash_password_manager.RetrievePasswordHash(); - ASSERT_TRUE(sync_password_date); - EXPECT_EQ(13u, sync_password_date->length); - EXPECT_EQ(16u, sync_password_date->salt.size()); - // TODO(crbug.com/657041) Add proper checking of hash when hash calculation is - // implemented. + ASSERT_TRUE(sync_password_data); + EXPECT_EQ(13u, sync_password_data->length); + EXPECT_EQ(16u, sync_password_data->salt.size()); + uint64_t expected_hash = password_manager_util::CalculateSyncPasswordHash( + base::ASCIIToUTF16("sync_password"), sync_password_data->salt); + EXPECT_EQ(expected_hash, sync_password_data->hash); } } // namespace
diff --git a/components/password_manager/core/browser/http_data_cleaner.cc b/components/password_manager/core/browser/http_data_cleaner.cc index 0df47eab..9b29a50 100644 --- a/components/password_manager/core/browser/http_data_cleaner.cc +++ b/components/password_manager/core/browser/http_data_cleaner.cc
@@ -203,11 +203,11 @@ // round trip of tasks will be scheduled. Finally, when no weak ptrs remain, // this method sets a boolean preference flag and returns. if (cleaner->HasWeakPtrs()) { - scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner = - base::ThreadTaskRunnerHandle::Get(); + scoped_refptr<base::SequencedTaskRunner> main_thread_runner = + base::SequencedTaskRunnerHandle::Get(); const auto post_to_thread = [](std::unique_ptr<ObsoleteHttpCleaner> cleaner, PrefService* prefs, - scoped_refptr<base::SingleThreadTaskRunner> thread_runner) { + scoped_refptr<base::SequencedTaskRunner> thread_runner) { thread_runner->PostTask( FROM_HERE, base::Bind(&WaitUntilCleaningIsDone, base::Passed(std::move(cleaner)), prefs)); @@ -243,7 +243,7 @@ int delay_in_seconds) { if (!prefs->GetBoolean( password_manager::prefs::kWasObsoleteHttpDataCleaned)) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&InitiateCleaning, make_scoped_refptr(store), prefs, request_context),
diff --git a/components/password_manager/core/browser/http_password_store_migrator.cc b/components/password_manager/core/browser/http_password_store_migrator.cc index 46114572..859b04af 100644 --- a/components/password_manager/core/browser/http_password_store_migrator.cc +++ b/components/password_manager/core/browser/http_password_store_migrator.cc
@@ -53,7 +53,7 @@ void HttpPasswordStoreMigrator::OnGetPasswordStoreResults( std::vector<std::unique_ptr<autofill::PasswordForm>> results) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); results_ = std::move(results); got_password_store_results_ = true; @@ -62,7 +62,7 @@ } void HttpPasswordStoreMigrator::OnHSTSQueryResult(bool is_hsts) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); mode_ = is_hsts ? MigrationMode::MOVE : MigrationMode::COPY; got_hsts_query_result_ = true;
diff --git a/components/password_manager/core/browser/http_password_store_migrator.h b/components/password_manager/core/browser/http_password_store_migrator.h index 47a378c..a3075ce 100644 --- a/components/password_manager/core/browser/http_password_store_migrator.h +++ b/components/password_manager/core/browser/http_password_store_migrator.h
@@ -9,7 +9,7 @@ #include <vector> #include "base/macros.h" -#include "base/threading/thread_checker.h" +#include "base/sequence_checker.h" #include "components/password_manager/core/browser/password_store_consumer.h" #include "url/gurl.h" @@ -76,7 +76,7 @@ MigrationMode mode_; std::vector<std::unique_ptr<autofill::PasswordForm>> results_; GURL http_origin_domain_; - base::ThreadChecker thread_checker_; + SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(HttpPasswordStoreMigrator); };
diff --git a/components/password_manager/core/browser/mock_password_store.cc b/components/password_manager/core/browser/mock_password_store.cc index b0e2c3a..7992d2b 100644 --- a/components/password_manager/core/browser/mock_password_store.cc +++ b/components/password_manager/core/browser/mock_password_store.cc
@@ -5,14 +5,13 @@ #include "components/password_manager/core/browser/mock_password_store.h" #include "base/memory/ptr_util.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" namespace password_manager { MockPasswordStore::MockPasswordStore() - : PasswordStore(base::ThreadTaskRunnerHandle::Get(), - base::ThreadTaskRunnerHandle::Get()) { -} + : PasswordStore(base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get()) {} MockPasswordStore::~MockPasswordStore() { }
diff --git a/components/password_manager/core/browser/password_reuse_detector.cc b/components/password_manager/core/browser/password_reuse_detector.cc index 51eb81d..7d6e1ca 100644 --- a/components/password_manager/core/browser/password_reuse_detector.cc +++ b/components/password_manager/core/browser/password_reuse_detector.cc
@@ -89,9 +89,18 @@ if (Origin(GURL(domain)).IsSameOriginWith(gaia_origin)) return false; - // TODO(crbug.com/657041): Implement checking a hash of |input| with - // |sync_password_data_|. + if (input.size() < sync_password_data_->length) + return false; + size_t offset = input.size() - sync_password_data_->length; + base::string16 reuse_candidate = input.substr(offset); + + if (password_manager_util::CalculateSyncPasswordHash( + reuse_candidate, sync_password_data_->salt) == + sync_password_data_->hash) { + consumer->OnReuseFound(reuse_candidate, kSyncPasswordDomain, 1, 0); + return true; + } return false; }
diff --git a/components/password_manager/core/browser/password_reuse_detector_unittest.cc b/components/password_manager/core/browser/password_reuse_detector_unittest.cc index 6266693..8b510f85 100644 --- a/components/password_manager/core/browser/password_reuse_detector_unittest.cc +++ b/components/password_manager/core/browser/password_reuse_detector_unittest.cc
@@ -12,6 +12,7 @@ #include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/browser/hash_password_manager.h" #include "components/password_manager/core/browser/password_manager_test_utils.h" +#include "components/password_manager/core/browser/password_manager_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -60,6 +61,15 @@ return changes; } +SyncPasswordData GetSyncPasswordData(const std::string& sync_password) { + SyncPasswordData sync_password_data; + sync_password_data.salt = "1234567890123456"; + sync_password_data.length = sync_password.size(); + sync_password_data.hash = password_manager_util::CalculateSyncPasswordHash( + base::ASCIIToUTF16(sync_password), sync_password_data.salt); + return sync_password_data; +} + TEST(PasswordReuseDetectorTest, TypingPasswordOnDifferentSite) { PasswordReuseDetector reuse_detector; reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords())); @@ -185,33 +195,30 @@ &mockConsumer); } -// TODO(crbug.com/657041): Enable when hash calculation is implemented. -TEST(PasswordReuseDetectorTest, DISABLED_SyncPasswordNoReuse) { +TEST(PasswordReuseDetectorTest, SyncPasswordNoReuse) { PasswordReuseDetector reuse_detector; reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords())); MockPasswordReuseDetectorConsumer mockConsumer; - // TODO(crbug.com/657041): Pass a password hash when hash calculation is - // implemented. - reuse_detector.UseSyncPasswordHash(base::Optional<SyncPasswordData>()); + std::string sync_password = "sync_password"; + reuse_detector.UseSyncPasswordHash(GetSyncPasswordData(sync_password)); EXPECT_CALL(mockConsumer, OnReuseFound(_, _, _, _)).Times(0); - reuse_detector.CheckReuse(ASCIIToUTF16("sync_password"), + // Typing sync password on https://accounts.google.com is OK. + reuse_detector.CheckReuse(ASCIIToUTF16("123sync_password"), "https://accounts.google.com", &mockConsumer); // Only suffixes are verifed. reuse_detector.CheckReuse(ASCIIToUTF16("sync_password123"), "https://evil.com", &mockConsumer); } -// TODO(crbug.com/657041): Enable when hash calculation is implemented. -TEST(PasswordReuseDetectorTest, DISABLED_SyncPasswordReuseFound) { +TEST(PasswordReuseDetectorTest, SyncPasswordReuseFound) { PasswordReuseDetector reuse_detector; reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords())); MockPasswordReuseDetectorConsumer mockConsumer; - // TODO(crbug.com/657041): Pass a password hash when hash calculation is - // implemented. - reuse_detector.UseSyncPasswordHash(base::Optional<SyncPasswordData>()); + std::string sync_password = "sync_password"; + reuse_detector.UseSyncPasswordHash(GetSyncPasswordData(sync_password)); EXPECT_CALL(mockConsumer, OnReuseFound(ASCIIToUTF16("sync_password"), @@ -220,18 +227,15 @@ &mockConsumer); } -// TODO(crbug.com/657041): Enable when hash calculation is implemented. -TEST(PasswordReuseDetectorTest, - DISABLED_SavedPasswordsReuseSyncPasswordAvailable) { +TEST(PasswordReuseDetectorTest, SavedPasswordsReuseSyncPasswordAvailable) { // Check that reuse of saved passwords is detected also if the sync password // hash is saved. PasswordReuseDetector reuse_detector; reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords())); MockPasswordReuseDetectorConsumer mockConsumer; - // TODO(crbug.com/657041): Pass a password hash when hash calculation is - // implemented. - reuse_detector.UseSyncPasswordHash(base::Optional<SyncPasswordData>()); + std::string sync_password = "sync_password"; + reuse_detector.UseSyncPasswordHash(GetSyncPasswordData(sync_password)); EXPECT_CALL(mockConsumer, OnReuseFound(ASCIIToUTF16("password"), "google.com", 5, 1)); @@ -239,6 +243,20 @@ &mockConsumer); } +TEST(PasswordReuseDetectorTest, ClearSyncPasswordHash) { + PasswordReuseDetector reuse_detector; + reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords())); + MockPasswordReuseDetectorConsumer mockConsumer; + + std::string sync_password = "sync_password"; + reuse_detector.UseSyncPasswordHash(GetSyncPasswordData(sync_password)); + reuse_detector.ClearSyncPasswordHash(); + + // Check that no reuse is found, since hash is cleared. + reuse_detector.CheckReuse(ASCIIToUTF16("sync_password"), "https://evil.com", + &mockConsumer); +} + } // namespace } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index 46b25fb..6b243b99b 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -14,7 +14,7 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/browser/android_affiliation/affiliated_match_helper.h" #include "components/password_manager/core/browser/password_manager_util.h" @@ -33,7 +33,7 @@ PasswordStore::GetLoginsRequest::GetLoginsRequest( PasswordStoreConsumer* consumer) : consumer_weak_(consumer->GetWeakPtr()) { - origin_task_runner_ = base::ThreadTaskRunnerHandle::Get(); + origin_task_runner_ = base::SequencedTaskRunnerHandle::Get(); } PasswordStore::GetLoginsRequest::~GetLoginsRequest() { @@ -64,7 +64,7 @@ #if !defined(OS_ANDROID) && !defined(OS_IOS) PasswordStore::CheckReuseRequest::CheckReuseRequest( PasswordReuseDetectorConsumer* consumer) - : origin_task_runner_(base::ThreadTaskRunnerHandle::Get()), + : origin_task_runner_(base::SequencedTaskRunnerHandle::Get()), consumer_weak_(consumer->AsWeakPtr()) {} PasswordStore::CheckReuseRequest::~CheckReuseRequest() {} @@ -107,8 +107,8 @@ } PasswordStore::PasswordStore( - scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner, - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner) + scoped_refptr<base::SequencedTaskRunner> main_thread_runner, + scoped_refptr<base::SequencedTaskRunner> db_thread_runner) : main_thread_runner_(main_thread_runner), db_thread_runner_(db_thread_runner), observers_(new base::ObserverListThreadSafe<Observer>()), @@ -259,7 +259,7 @@ void PasswordStore::ReportMetrics(const std::string& sync_username, bool custom_passphrase_sync_enabled) { - scoped_refptr<base::SingleThreadTaskRunner> task_runner( + scoped_refptr<base::SequencedTaskRunner> task_runner( GetBackgroundTaskRunner()); if (task_runner) { base::Closure task = @@ -301,7 +301,7 @@ } bool PasswordStore::ScheduleTask(const base::Closure& task) { - scoped_refptr<base::SingleThreadTaskRunner> task_runner( + scoped_refptr<base::SequencedTaskRunner> task_runner( GetBackgroundTaskRunner()); if (task_runner.get()) return task_runner->PostTask(FROM_HERE, task); @@ -321,7 +321,7 @@ base::WeakPtr<syncer::SyncableService> PasswordStore::GetPasswordSyncableService() { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); DCHECK(syncable_service_); return syncable_service_->AsWeakPtr(); } @@ -365,7 +365,7 @@ DCHECK(shutdown_called_); } -scoped_refptr<base::SingleThreadTaskRunner> +scoped_refptr<base::SequencedTaskRunner> PasswordStore::GetBackgroundTaskRunner() { return db_thread_runner_; } @@ -420,7 +420,7 @@ void PasswordStore::NotifyLoginsChanged( const PasswordStoreChangeList& changes) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); if (!changes.empty()) { observers_->Notify(FROM_HERE, &Observer::OnLoginsChanged, changes); if (syncable_service_) @@ -609,7 +609,7 @@ const FormDigest& form, std::unique_ptr<GetLoginsRequest> request, const std::vector<std::string>& additional_android_realms) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); std::vector<std::unique_ptr<PasswordForm>> results(FillMatchingLogins(form)); for (const std::string& realm : additional_android_realms) { std::vector<std::unique_ptr<PasswordForm>> more_results( @@ -649,7 +649,7 @@ std::unique_ptr<PasswordForm> PasswordStore::GetLoginImpl( const PasswordForm& primary_key) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); std::vector<std::unique_ptr<PasswordForm>> candidates( FillMatchingLogins(FormDigest(primary_key))); for (auto& candidate : candidates) { @@ -683,7 +683,7 @@ void PasswordStore::UpdateAffiliatedWebLoginsImpl( const PasswordForm& updated_android_form, const std::vector<std::string>& affiliated_web_realms) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); PasswordStoreChangeList all_changes; for (const std::string& affiliated_web_realm : affiliated_web_realms) { std::vector<std::unique_ptr<PasswordForm>> web_logins(FillMatchingLogins( @@ -769,7 +769,7 @@ void PasswordStore::InitOnBackgroundThread( const syncer::SyncableService::StartSyncFlare& flare) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); DCHECK(!syncable_service_); syncable_service_.reset(new PasswordSyncableService(this)); syncable_service_->InjectStartSyncFlare(flare); @@ -782,7 +782,7 @@ } void PasswordStore::DestroyOnBackgroundThread() { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); syncable_service_.reset(); // TODO(crbug.com/706392): Fix password reuse detection for Android. #if !defined(OS_ANDROID) && !defined(OS_IOS)
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h index 3d94d90..11fe83f 100644 --- a/components/password_manager/core/browser/password_store.h +++ b/components/password_manager/core/browser/password_store.h
@@ -14,7 +14,7 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/observer_list_threadsafe.h" -#include "base/single_thread_task_runner.h" +#include "base/sequenced_task_runner.h" #include "base/time/time.h" #include "components/keyed_service/core/refcounted_keyed_service.h" #include "components/password_manager/core/browser/password_store_change.h" @@ -90,8 +90,8 @@ GURL origin; }; - PasswordStore(scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner, - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner); + PasswordStore(scoped_refptr<base::SequencedTaskRunner> main_thread_runner, + scoped_refptr<base::SequencedTaskRunner> db_thread_runner); // Reimplement this to add custom initialization. Always call this too. virtual bool Init(const syncer::SyncableService::StartSyncFlare& flare, @@ -298,7 +298,7 @@ // See GetLogins(). Logins older than this will be removed from the reply. base::Time ignore_logins_cutoff_; - scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; + scoped_refptr<base::SequencedTaskRunner> origin_task_runner_; base::WeakPtr<PasswordStoreConsumer> consumer_weak_; DISALLOW_COPY_AND_ASSIGN(GetLoginsRequest); @@ -322,7 +322,7 @@ int number_matches) override; private: - const scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; + const scoped_refptr<base::SequencedTaskRunner> origin_task_runner_; const base::WeakPtr<PasswordReuseDetectorConsumer> consumer_weak_; DISALLOW_COPY_AND_ASSIGN(CheckReuseRequest); @@ -332,9 +332,9 @@ ~PasswordStore() override; // Get the TaskRunner to use for PasswordStore background tasks. - // By default, a SingleThreadTaskRunner on the DB thread is used, but + // By default, a SequencedTaskRunner on the DB thread is used, but // subclasses can override. - virtual scoped_refptr<base::SingleThreadTaskRunner> GetBackgroundTaskRunner(); + virtual scoped_refptr<base::SequencedTaskRunner> GetBackgroundTaskRunner(); // Methods below will be run in PasswordStore's own thread. // Synchronous implementation that reports usage metrics. @@ -443,11 +443,11 @@ #endif // TaskRunner for tasks that run on the main thread (usually the UI thread). - scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner_; + scoped_refptr<base::SequencedTaskRunner> main_thread_runner_; // TaskRunner for the DB thread. By default, this is the task runner used for // background tasks -- see |GetBackgroundTaskRunner|. - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner_; + scoped_refptr<base::SequencedTaskRunner> db_thread_runner_; private: FRIEND_TEST_ALL_PREFIXES(PasswordStoreTest, GetLoginImpl);
diff --git a/components/password_manager/core/browser/password_store_default.cc b/components/password_manager/core/browser/password_store_default.cc index 2e05c0a..64261d99 100644 --- a/components/password_manager/core/browser/password_store_default.cc +++ b/components/password_manager/core/browser/password_store_default.cc
@@ -17,8 +17,8 @@ namespace password_manager { PasswordStoreDefault::PasswordStoreDefault( - scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner, - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner, + scoped_refptr<base::SequencedTaskRunner> main_thread_runner, + scoped_refptr<base::SequencedTaskRunner> db_thread_runner, std::unique_ptr<LoginDatabase> login_db) : PasswordStore(main_thread_runner, db_thread_runner), login_db_(std::move(login_db)) {} @@ -39,7 +39,7 @@ } void PasswordStoreDefault::InitOnDBThread() { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); DCHECK(login_db_); if (!login_db_->Init()) { login_db_.reset(); @@ -52,13 +52,13 @@ bool custom_passphrase_sync_enabled) { if (!login_db_) return; - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); login_db_->ReportMetrics(sync_username, custom_passphrase_sync_enabled); } PasswordStoreChangeList PasswordStoreDefault::AddLoginImpl( const PasswordForm& form) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); if (!login_db_) return PasswordStoreChangeList(); return login_db_->AddLogin(form); @@ -66,7 +66,7 @@ PasswordStoreChangeList PasswordStoreDefault::UpdateLoginImpl( const PasswordForm& form) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); if (!login_db_) return PasswordStoreChangeList(); return login_db_->UpdateLogin(form); @@ -74,7 +74,7 @@ PasswordStoreChangeList PasswordStoreDefault::RemoveLoginImpl( const PasswordForm& form) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); PasswordStoreChangeList changes; if (login_db_ && login_db_->RemoveLogin(form)) changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form)); @@ -194,43 +194,43 @@ bool PasswordStoreDefault::FillAutofillableLogins( std::vector<std::unique_ptr<PasswordForm>>* forms) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); return login_db_ && login_db_->GetAutofillableLogins(forms); } bool PasswordStoreDefault::FillBlacklistLogins( std::vector<std::unique_ptr<PasswordForm>>* forms) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); return login_db_ && login_db_->GetBlacklistLogins(forms); } void PasswordStoreDefault::AddSiteStatsImpl(const InteractionsStats& stats) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); if (login_db_) login_db_->stats_table().AddRow(stats); } void PasswordStoreDefault::RemoveSiteStatsImpl(const GURL& origin_domain) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); if (login_db_) login_db_->stats_table().RemoveRow(origin_domain); } std::vector<InteractionsStats> PasswordStoreDefault::GetAllSiteStatsImpl() { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); return login_db_ ? login_db_->stats_table().GetAllRows() : std::vector<InteractionsStats>(); } std::vector<InteractionsStats> PasswordStoreDefault::GetSiteStatsImpl( const GURL& origin_domain) { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); return login_db_ ? login_db_->stats_table().GetRows(origin_domain) : std::vector<InteractionsStats>(); } void PasswordStoreDefault::ResetLoginDB() { - DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + DCHECK(GetBackgroundTaskRunner()->RunsTasksInCurrentSequence()); login_db_.reset(); }
diff --git a/components/password_manager/core/browser/password_store_default.h b/components/password_manager/core/browser/password_store_default.h index be550455..4fd5570 100644 --- a/components/password_manager/core/browser/password_store_default.h +++ b/components/password_manager/core/browser/password_store_default.h
@@ -10,7 +10,7 @@ #include <vector> #include "base/macros.h" -#include "base/single_thread_task_runner.h" +#include "base/sequenced_task_runner.h" #include "components/password_manager/core/browser/login_database.h" #include "components/password_manager/core/browser/password_store.h" @@ -25,8 +25,8 @@ // The |login_db| must not have been Init()-ed yet. It will be initialized in // a deferred manner on the DB thread. PasswordStoreDefault( - scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner, - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner, + scoped_refptr<base::SequencedTaskRunner> main_thread_runner, + scoped_refptr<base::SequencedTaskRunner> db_thread_runner, std::unique_ptr<LoginDatabase> login_db); bool Init(const syncer::SyncableService::StartSyncFlare& flare,
diff --git a/components/password_manager/core/browser/password_store_default_unittest.cc b/components/password_manager/core/browser/password_store_default_unittest.cc index cc2e8afd..8a7374a 100644 --- a/components/password_manager/core/browser/password_store_default_unittest.cc +++ b/components/password_manager/core/browser/password_store_default_unittest.cc
@@ -16,7 +16,7 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_task_environment.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" #include "components/password_manager/core/browser/login_database.h" #include "components/password_manager/core/browser/password_manager_test_utils.h" @@ -143,8 +143,8 @@ PasswordStoreDefaultTestDelegate::CreateInitializedStore( std::unique_ptr<LoginDatabase> database) { scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), - std::move(database))); + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), std::move(database))); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); return store;
diff --git a/components/password_manager/core/browser/password_store_factory_util.cc b/components/password_manager/core/browser/password_store_factory_util.cc index 28b7724..6f19620 100644 --- a/components/password_manager/core/browser/password_store_factory_util.cc +++ b/components/password_manager/core/browser/password_store_factory_util.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/memory/ptr_util.h" +#include "base/task_scheduler/post_task.h" #include "components/password_manager/core/browser/android_affiliation/affiliated_match_helper.h" #include "components/password_manager/core/browser/android_affiliation/affiliation_service.h" #include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h" @@ -28,13 +29,17 @@ void ActivateAffiliationBasedMatching( PasswordStore* password_store, net::URLRequestContextGetter* request_context_getter, - const base::FilePath& db_path, - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner) { + const base::FilePath& db_path) { // The PasswordStore is so far the only consumer of the AffiliationService, // therefore the service is owned by the AffiliatedMatchHelper, which in // turn is owned by the PasswordStore. + // Task priority is USER_VISIBLE, because AffiliationService-related tasks + // block obtaining credentials from PasswordStore, which matches the + // USER_VISIBLE example: "Loading data that might be shown in the UI after a + // future user interaction." std::unique_ptr<AffiliationService> affiliation_service( - new AffiliationService(db_thread_runner)); + new AffiliationService(base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE}))); affiliation_service->Initialize(request_context_getter, db_path); std::unique_ptr<AffiliatedMatchHelper> affiliated_match_helper( new AffiliatedMatchHelper(password_store, @@ -56,8 +61,7 @@ PasswordStore* password_store, syncer::SyncService* sync_service, net::URLRequestContextGetter* request_context_getter, - const base::FilePath& profile_path, - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner) { + const base::FilePath& profile_path) { DCHECK(password_store); const bool matching_should_be_active = @@ -67,8 +71,7 @@ if (matching_should_be_active && !matching_is_active) { ActivateAffiliationBasedMatching(password_store, request_context_getter, - GetAffiliationDatabasePath(profile_path), - db_thread_runner); + GetAffiliationDatabasePath(profile_path)); } else if (!matching_should_be_active && matching_is_active) { password_store->SetAffiliatedMatchHelper( base::WrapUnique<AffiliatedMatchHelper>(nullptr));
diff --git a/components/password_manager/core/browser/password_store_factory_util.h b/components/password_manager/core/browser/password_store_factory_util.h index 6f3a707..b3f7a1c4 100644 --- a/components/password_manager/core/browser/password_store_factory_util.h +++ b/components/password_manager/core/browser/password_store_factory_util.h
@@ -9,7 +9,6 @@ #include "base/files/file_path.h" #include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" #include "components/keyed_service/core/keyed_service.h" #include "components/keyed_service/core/service_access_type.h" #include "components/password_manager/core/browser/login_database.h" @@ -22,16 +21,14 @@ // Activates or deactivates affiliation-based matching for |password_store|, // depending on whether or not the |sync_service| is syncing passwords stored -// therein. The AffiliationService will use |db_thread_runner| as its backend -// thread, and |request_context_getter| to fetch affiliation information. This -// function should be called whenever there is a possibility that syncing -// passwords has just started or ended. +// therein. The AffiliationService will use |request_context_getter| to fetch +// affiliation information. This function should be called whenever there is a +// possibility that syncing passwords has just started or ended. void ToggleAffiliationBasedMatchingBasedOnPasswordSyncedState( PasswordStore* password_store, syncer::SyncService* sync_service, net::URLRequestContextGetter* request_context_getter, - const base::FilePath& profile_path, - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner); + const base::FilePath& profile_path); // Creates a LoginDatabase. Looks in |profile_path| for the database file. // Does not call LoginDatabase::Init() -- to avoid UI jank, that needs to be
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc index e95ed71..f536b89c 100644 --- a/components/password_manager/core/browser/password_store_unittest.cc +++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -21,7 +21,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/synchronization/waitable_event.h" #include "base/test/scoped_task_environment.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" #include "build/build_config.h" #include "components/password_manager/core/browser/android_affiliation/affiliated_match_helper.h" @@ -140,7 +140,8 @@ TEST_F(PasswordStoreTest, IgnoreOldWwwGoogleLogins) { scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::MakeUnique<LoginDatabase>(test_login_db_file_path()))); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); @@ -234,7 +235,8 @@ TEST_F(PasswordStoreTest, StartSyncFlare) { scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::MakeUnique<LoginDatabase>(test_login_db_file_path()))); StartSyncFlareMock mock; store->Init( @@ -264,7 +266,8 @@ /* clang-format on */ scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::MakeUnique<LoginDatabase>(test_login_db_file_path()))); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); @@ -327,7 +330,8 @@ /* clang-format on */ scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::MakeUnique<LoginDatabase>(test_login_db_file_path()))); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); @@ -380,7 +384,8 @@ /* clang-format on */ scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::WrapUnique(new LoginDatabase(test_login_db_file_path())))); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); @@ -433,7 +438,8 @@ /* clang-format on */ scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::WrapUnique(new LoginDatabase(test_login_db_file_path())))); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); @@ -538,7 +544,8 @@ /* clang-format on */ scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::WrapUnique(new LoginDatabase(test_login_db_file_path())))); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); @@ -721,8 +728,8 @@ << test_remove_and_add_login); scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), - base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::WrapUnique(new LoginDatabase(test_login_db_file_path())))); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); store->RemoveLoginsCreatedBetween(base::Time(), base::Time::Max(), @@ -830,8 +837,8 @@ for (bool blacklisted : kFalseTrue) { SCOPED_TRACE(testing::Message("use blacklisted logins: ") << blacklisted); scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), - base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::MakeUnique<LoginDatabase>(test_login_db_file_path()))); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); store->RemoveLoginsCreatedBetween(base::Time(), base::Time::Max(), @@ -912,7 +919,8 @@ L"username_value_6", L"", true, 1}}; scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::MakeUnique<LoginDatabase>(test_login_db_file_path()))); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); @@ -947,7 +955,8 @@ "https://facebook.com", "", L"", L"", L"", L"", L"topsecret", true, 1}}; scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::MakeUnique<LoginDatabase>(test_login_db_file_path()))); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); @@ -990,7 +999,8 @@ #if !defined(OS_CHROMEOS) TEST_F(PasswordStoreTest, SavingClearingSyncPassword) { scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::MakeUnique<LoginDatabase>(test_login_db_file_path()))); TestingPrefServiceSimple prefs; @@ -1008,15 +1018,22 @@ base::RunLoop().RunUntilIdle(); EXPECT_TRUE(prefs.HasPrefPath(prefs::kSyncPasswordHash)); - // TODO(crbug.com/657041): Check that password reuse works when sync hash - // calculation is implemented. + // Check that sync password reuse is found. + MockPasswordReuseDetectorConsumer mock_consumer; + EXPECT_CALL( + mock_consumer, + OnReuseFound(sync_password, std::string(kSyncPasswordDomain), 1, 0)); + store->CheckReuse(input, "https://facebook.com", &mock_consumer); + base::RunLoop().RunUntilIdle(); + testing::Mock::VerifyAndClearExpectations(&mock_consumer); // Check that no sync password reuse is found after clearing the saved sync // password hash. store->ClearSyncPasswordHash(); EXPECT_FALSE(prefs.HasPrefPath(prefs::kSyncPasswordHash)); - // TODO(crbug.com/657041): Check that no password reuse happens here when sync - // hash calculation is implemented. + EXPECT_CALL(mock_consumer, OnReuseFound(_, _, _, _)).Times(0); + store->CheckReuse(input, "https://facebook.com", &mock_consumer); + base::RunLoop().RunUntilIdle(); store->ShutdownOnUIThread(); base::RunLoop().RunUntilIdle(); @@ -1024,7 +1041,8 @@ TEST_F(PasswordStoreTest, SubscriptionAndUnsubscriptionFromSignInEvents) { scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( - base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get(), base::MakeUnique<LoginDatabase>(test_login_db_file_path()))); std::unique_ptr<MockPasswordStoreSigninNotifier> notifier =
diff --git a/components/password_manager/core/browser/sql_table_builder.cc b/components/password_manager/core/browser/sql_table_builder.cc index f49caa65..caa654be 100644 --- a/components/password_manager/core/browser/sql_table_builder.cc +++ b/components/password_manager/core/browser/sql_table_builder.cc
@@ -35,6 +35,9 @@ struct SQLTableBuilder::Column { std::string name; std::string type; + // Whether this column is part of the table's PRIMARY KEY constraint. + bool part_of_primary_key; + // Whether this column is part of the table's UNIQUE constraint. bool part_of_unique_key; // The first version this column is part of. unsigned min_version; @@ -69,10 +72,16 @@ void SQLTableBuilder::AddColumn(std::string name, std::string type) { DCHECK(FindLastColumnByName(name) == columns_.rend()); - columns_.push_back({std::move(name), std::move(type), false, + columns_.push_back({std::move(name), std::move(type), false, false, sealed_version_ + 1, kInvalidVersion, false}); } +void SQLTableBuilder::AddColumnToPrimaryKey(std::string name, + std::string type) { + AddColumn(std::move(name), std::move(type)); + columns_.back().part_of_primary_key = true; +} + void SQLTableBuilder::AddColumnToUniqueKey(std::string name, std::string type) { AddColumn(std::move(name), std::move(type)); columns_.back().part_of_unique_key = true; @@ -99,6 +108,7 @@ // just replaced, it needs to be kept for generating the migration code. Column new_column = {new_name, old_column->type, + old_column->part_of_primary_key, old_column->part_of_unique_key, sealed_version_ + 1, kInvalidVersion, @@ -205,17 +215,23 @@ unsigned SQLTableBuilder::SealVersion() { if (sealed_version_ == kInvalidVersion) { - DCHECK_EQ(std::string(), unique_constraint_); - // First sealed version, time to compute the UNIQUE string. + DCHECK_EQ(std::string(), constraints_); + // First sealed version, time to compute the PRIMARY KEY and UNIQUE string. + std::string primary_key; std::string unique_key; for (const Column& column : columns_) { + if (column.part_of_primary_key) + Append(column.name, &primary_key); if (column.part_of_unique_key) Append(column.name, &unique_key); } - DCHECK(!unique_key.empty()); - unique_constraint_ = "UNIQUE (" + unique_key + ")"; + DCHECK(!primary_key.empty() || !unique_key.empty()); + if (!primary_key.empty()) + Append("PRIMARY KEY (" + primary_key + ")", &constraints_); + if (!unique_key.empty()) + Append("UNIQUE (" + unique_key + ")", &constraints_); } - DCHECK(!unique_constraint_.empty()); + DCHECK(!constraints_.empty()); return ++sealed_version_; } @@ -230,7 +246,7 @@ bool SQLTableBuilder::CreateTable(sql::Connection* db) { DCHECK(IsVersionLastAndSealed(sealed_version_)); - DCHECK(!unique_constraint_.empty()); + DCHECK(!constraints_.empty()); if (db->DoesTableExist(table_name_.c_str())) return true; @@ -255,7 +271,7 @@ return transaction.Begin() && db->Execute(base::StringPrintf("CREATE TABLE %s (%s, %s)", table_name_.c_str(), names.c_str(), - unique_constraint_.c_str()) + constraints_.c_str()) .c_str()) && std::all_of(create_index_sqls.begin(), create_index_sqls.end(), [&db](const std::string& sql) { @@ -278,7 +294,8 @@ DCHECK(IsVersionLastAndSealed(sealed_version_)); std::string result; for (const Column& column : columns_) { - if (IsColumnInLastVersion(column) && !column.part_of_unique_key) + if (IsColumnInLastVersion(column) && + !(column.part_of_primary_key || column.part_of_unique_key)) Append(column.name + "=?", &result); } return result; @@ -288,7 +305,8 @@ DCHECK(IsVersionLastAndSealed(sealed_version_)); std::string result; for (const Column& column : columns_) { - if (IsColumnInLastVersion(column) && column.part_of_unique_key) { + if (IsColumnInLastVersion(column) && + (column.part_of_primary_key || column.part_of_unique_key)) { if (!result.empty()) result += " AND "; result += column.name + "=?"; @@ -297,12 +315,26 @@ return result; } -std::string SQLTableBuilder::ListAllIndexNames() const { +std::vector<base::StringPiece> SQLTableBuilder::AllPrimaryKeyNames() const { DCHECK(IsVersionLastAndSealed(sealed_version_)); - std::string result; + std::vector<base::StringPiece> result; + result.reserve(columns_.size()); + for (const Column& column : columns_) { + if (IsColumnInLastVersion(column) && column.part_of_primary_key) { + result.emplace_back(column.name); + } + } + return result; +} + +std::vector<base::StringPiece> SQLTableBuilder::AllIndexNames() const { + DCHECK(IsVersionLastAndSealed(sealed_version_)); + std::vector<base::StringPiece> result; + result.reserve(indices_.size()); for (const Index& index : indices_) { - if (IsIndexInLastVersion(index)) - Append(index.name, &result); + if (IsIndexInLastVersion(index)) { + result.emplace_back(index.name); + } } return result; } @@ -326,7 +358,7 @@ DCHECK_LT(old_version, sealed_version_); DCHECK_GE(old_version, 0u); DCHECK(IsVersionLastAndSealed(sealed_version_)); - DCHECK(!unique_constraint_.empty()); + DCHECK(!constraints_.empty()); // Names of columns from old version, values of which are copied. std::string old_names; @@ -340,6 +372,7 @@ for (auto column = columns_.begin(); column != columns_.end(); ++column) { if (column->max_version == old_version) { + DCHECK(!column->part_of_primary_key); DCHECK(!column->part_of_unique_key); // This column was deleted after |old_version|. It can have two reasons: needs_temp_table = true; @@ -356,6 +389,7 @@ } } else if (column->min_version == old_version + 1) { // This column was added after old_version. + DCHECK(!column->part_of_primary_key); DCHECK(!column->part_of_unique_key); added_names.push_back(column->name + " " + column->type); } else if (column->min_version <= old_version && @@ -384,7 +418,7 @@ if (!(transaction.Begin() && db->Execute(base::StringPrintf( "CREATE TABLE %s (%s, %s)", temp_table_name.c_str(), - new_names.c_str(), unique_constraint_.c_str()) + new_names.c_str(), constraints_.c_str()) .c_str()) && db->Execute( base::StringPrintf("INSERT OR REPLACE INTO %s SELECT %s FROM %s",
diff --git a/components/password_manager/core/browser/sql_table_builder.h b/components/password_manager/core/browser/sql_table_builder.h index 8407186d..6cf78cca 100644 --- a/components/password_manager/core/browser/sql_table_builder.h +++ b/components/password_manager/core/browser/sql_table_builder.h
@@ -10,6 +10,7 @@ #include <vector> #include "base/macros.h" +#include "base/strings/string_piece.h" namespace sql { class Connection; @@ -25,6 +26,7 @@ // SQLTableBuilder builder("logins"); // // // First describe a couple of versions: +// builder.AddColumnToPrimaryKey("id", "INTEGER"); // builder.AddColumn("name", "VARCHAR"); // builder.AddColumn("icon", "VARCHAR"); // builder.AddColumn("password", "VARCHAR NOT NULL"); @@ -53,6 +55,11 @@ // must not have been added to the table in this version before. void AddColumn(std::string name, std::string type); + // As AddColumn but also adds column |name| to the primary key of the table. + // SealVersion must not have been called yet (the builder does not currently + // support migration code for changing the primary key between versions). + void AddColumnToPrimaryKey(std::string name, std::string type); + // As AddColumn but also adds column |name| to the unique key of the table. // SealVersion must not have been called yet (the builder does not currently // support migration code for changing the unique key between versions). @@ -105,17 +112,22 @@ // version. The last version must be sealed. std::string ListAllColumnNames() const; - // Same as ListAllColumnNames, but for non-unique key names only, and with - // names followed by " = ?". + // Same as ListAllColumnNames, but for non-unique key names only (i.e. keys + // that are part of neither the PRIMARY KEY nor the UNIQUE constraint), and + // with names followed by " = ?". std::string ListAllNonuniqueKeyNames() const; // Same as ListAllNonuniqueKeyNames, but for unique key names and separated by // " AND ". std::string ListAllUniqueKeyNames() const; - // Returns the comma-separated list of all index names present in the last + // Returns a vector of all PRIMARY KEY names that are present in the last // version. The last version must be sealed. - std::string ListAllIndexNames() const; + std::vector<base::StringPiece> AllPrimaryKeyNames() const; + + // Returns a vector of all index names that are present in the last + // version. The last version must be sealed. + std::vector<base::StringPiece> AllIndexNames() const; // Returns the number of all columns present in the last version. The last // version must be sealed. @@ -177,9 +189,9 @@ std::vector<Index> indices_; // Indices of the table, across all versions. - // The "UNIQUE" part of an SQL CREATE TABLE constraint. This value is - // computed dring sealing the first version (0). - std::string unique_constraint_; + // The SQL CREATE TABLE constraints. This value is computed during sealing the + // first version (0). + std::string constraints_; // The name of the table. const std::string table_name_;
diff --git a/components/password_manager/core/browser/sql_table_builder_unittest.cc b/components/password_manager/core/browser/sql_table_builder_unittest.cc index 3fbe38a8..b1c1393c 100644 --- a/components/password_manager/core/browser/sql_table_builder_unittest.cc +++ b/components/password_manager/core/browser/sql_table_builder_unittest.cc
@@ -9,8 +9,11 @@ #include "base/macros.h" #include "sql/connection.h" #include "sql/statement.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using ::testing::UnorderedElementsAre; + namespace password_manager { class SQLTableBuilderTest : public testing::Test { @@ -266,6 +269,7 @@ } TEST_F(SQLTableBuilderTest, MigrateFrom_RenameAndAddColumns) { + builder()->AddColumnToPrimaryKey("id", "INTEGER"); builder()->AddColumn("old_name", "INTEGER"); EXPECT_EQ(0u, builder()->SealVersion()); @@ -279,14 +283,18 @@ EXPECT_TRUE(builder()->MigrateFrom(0, db())); EXPECT_FALSE(db()->DoesColumnExist("my_logins_table", "old_name")); + EXPECT_TRUE(db()->DoesColumnExist("my_logins_table", "id")); EXPECT_TRUE(db()->DoesColumnExist("my_logins_table", "added")); EXPECT_TRUE(db()->DoesColumnExist("my_logins_table", "new_name")); + EXPECT_TRUE(IsColumnOfType("id", "INTEGER")); EXPECT_TRUE(IsColumnOfType("added", "VARCHAR")); EXPECT_TRUE(IsColumnOfType("new_name", "INTEGER")); - EXPECT_EQ(3u, builder()->NumberOfColumns()); - EXPECT_EQ("signon_realm, new_name, added", builder()->ListAllColumnNames()); + EXPECT_EQ(4u, builder()->NumberOfColumns()); + EXPECT_EQ("signon_realm, id, new_name, added", + builder()->ListAllColumnNames()); EXPECT_EQ("new_name=?, added=?", builder()->ListAllNonuniqueKeyNames()); - EXPECT_EQ("signon_realm=?", builder()->ListAllUniqueKeyNames()); + EXPECT_EQ("signon_realm=? AND id=?", builder()->ListAllUniqueKeyNames()); + EXPECT_THAT(builder()->AllPrimaryKeyNames(), UnorderedElementsAre("id")); } TEST_F(SQLTableBuilderTest, MigrateFrom_RenameAndAddIndices) { @@ -306,10 +314,13 @@ EXPECT_TRUE(db()->DoesIndexExist("added")); EXPECT_TRUE(db()->DoesIndexExist("new_name")); EXPECT_EQ(2u, builder()->NumberOfIndices()); - EXPECT_EQ("new_name, added", builder()->ListAllIndexNames()); + EXPECT_THAT(builder()->AllIndexNames(), + UnorderedElementsAre("new_name", "added")); } TEST_F(SQLTableBuilderTest, MigrateFrom_RenameAndAddAndDropColumns) { + builder()->AddColumnToPrimaryKey("pk_1", "VARCHAR NOT NULL"); + builder()->AddColumnToPrimaryKey("pk_2", "VARCHAR NOT NULL"); builder()->AddColumnToUniqueKey("uni", "VARCHAR NOT NULL"); builder()->AddColumn("old_name", "INTEGER"); EXPECT_EQ(0u, builder()->SealVersion()); @@ -328,13 +339,19 @@ EXPECT_TRUE(builder()->MigrateFrom(0, db())); EXPECT_FALSE(db()->DoesColumnExist("my_logins_table", "old_name")); EXPECT_FALSE(db()->DoesColumnExist("my_logins_table", "added")); + EXPECT_TRUE(db()->DoesColumnExist("my_logins_table", "pk_1")); + EXPECT_TRUE(db()->DoesColumnExist("my_logins_table", "pk_2")); EXPECT_TRUE(db()->DoesColumnExist("my_logins_table", "uni")); EXPECT_TRUE(db()->DoesColumnExist("my_logins_table", "new_name")); EXPECT_TRUE(IsColumnOfType("new_name", "INTEGER")); - EXPECT_EQ(3u, builder()->NumberOfColumns()); - EXPECT_EQ("signon_realm, uni, new_name", builder()->ListAllColumnNames()); + EXPECT_EQ(5u, builder()->NumberOfColumns()); + EXPECT_EQ("signon_realm, pk_1, pk_2, uni, new_name", + builder()->ListAllColumnNames()); EXPECT_EQ("new_name=?", builder()->ListAllNonuniqueKeyNames()); - EXPECT_EQ("signon_realm=? AND uni=?", builder()->ListAllUniqueKeyNames()); + EXPECT_EQ("signon_realm=? AND pk_1=? AND pk_2=? AND uni=?", + builder()->ListAllUniqueKeyNames()); + EXPECT_THAT(builder()->AllPrimaryKeyNames(), + UnorderedElementsAre("pk_1", "pk_2")); } TEST_F(SQLTableBuilderTest, MigrateFrom_RenameAndAddAndDropIndices) { @@ -357,7 +374,7 @@ EXPECT_FALSE(db()->DoesIndexExist("added")); EXPECT_TRUE(db()->DoesIndexExist("new_name")); EXPECT_EQ(1u, builder()->NumberOfColumns()); - EXPECT_EQ("new_name", builder()->ListAllIndexNames()); + EXPECT_THAT(builder()->AllIndexNames(), UnorderedElementsAre("new_name")); } } // namespace password_manager
diff --git a/components/password_manager/core/browser/test_password_store.cc b/components/password_manager/core/browser/test_password_store.cc index 1e11a32..5c4c585e 100644 --- a/components/password_manager/core/browser/test_password_store.cc +++ b/components/password_manager/core/browser/test_password_store.cc
@@ -7,7 +7,7 @@ #include <stddef.h> #include "base/memory/ptr_util.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/browser/psl_matching_helper.h" #include "components/password_manager/core/browser/statistics_table.h" @@ -15,9 +15,8 @@ namespace password_manager { TestPasswordStore::TestPasswordStore() - : PasswordStore(base::ThreadTaskRunnerHandle::Get(), - base::ThreadTaskRunnerHandle::Get()) { -} + : PasswordStore(base::SequencedTaskRunnerHandle::Get(), + base::SequencedTaskRunnerHandle::Get()) {} TestPasswordStore::~TestPasswordStore() { }
diff --git a/components/signin/core/browser/android/BUILD.gn b/components/signin/core/browser/android/BUILD.gn index 760282f..d9dda3e 100644 --- a/components/signin/core/browser/android/BUILD.gn +++ b/components/signin/core/browser/android/BUILD.gn
@@ -25,6 +25,7 @@ "java/src/org/chromium/components/signin/AuthException.java", "java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java", "java/src/org/chromium/components/signin/ChromeSigninController.java", + "java/src/org/chromium/components/signin/AccountManagerDelegateException.java", "java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java", ] }
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java index 2e52e58..004d68c 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java
@@ -20,10 +20,18 @@ public interface AccountManagerDelegate { /** * Get all the accounts for a given {@code type}. + * This is deprecated an will be removed soon. + */ + @Deprecated + @WorkerThread + Account[] getAccountsByType(String type); + + /** + * Get all the accounts. * This method shouldn't be called on the UI thread (violated due to crbug.com/517697). */ @WorkerThread - Account[] getAccountsByType(String type); + Account[] getAccountsSync() throws AccountManagerDelegateException; /** * Get an auth token.
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegateException.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegateException.java new file mode 100644 index 0000000..ed32737 --- /dev/null +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegateException.java
@@ -0,0 +1,13 @@ +// Copyright 2017 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. + +package org.chromium.components.signin; + +/** + * AccountManagerDelegateException encapsulates errors that can happen while getting list of + * accounts. + * + * Currently, this exception is a stub. Support for different errors will be added soon. + */ +public class AccountManagerDelegateException extends Exception {}
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java index 9b3b9fe..2b08786c 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java
@@ -140,12 +140,13 @@ } /** - * This method is deprecated; please use the asynchronous version below instead. + * Retrieves a list of the Google account names on the device. * - * See http://crbug.com/517697 for details. + * @throws AccountManagerDelegateException if Google Play Services are out of date, + * Chrome lacks necessary permissions, etc. */ @WorkerThread - public List<String> getGoogleAccountNames() { + public List<String> getGoogleAccountNames() throws AccountManagerDelegateException { List<String> accountNames = new ArrayList<>(); for (Account account : getGoogleAccounts()) { accountNames.add(account.name); @@ -154,11 +155,24 @@ } /** - * Retrieves a list of the Google account names on the device asynchronously. + * Retrieves a list of the Google account names on the device. + * Returns an empty list if Google Play Services aren't available or out of date. + */ + @WorkerThread + public List<String> tryGetGoogleAccountNames() { + List<String> accountNames = new ArrayList<>(); + for (Account account : tryGetGoogleAccounts()) { + accountNames.add(account.name); + } + return accountNames; + } + + /** + * Asynchronous version of {@link #tryGetGoogleAccountNames()}. */ @MainThread - public void getGoogleAccountNames(final Callback<List<String>> callback) { - getGoogleAccounts(new Callback<Account[]>() { + public void tryGetGoogleAccountNames(final Callback<List<String>> callback) { + tryGetGoogleAccounts(new Callback<Account[]>() { @Override public void onResult(Account[] accounts) { List<String> accountNames = new ArrayList<>(); @@ -171,25 +185,39 @@ } /** - * This method is deprecated; please use the asynchronous version below instead. + * Retrieves all Google accounts on the device. * - * See http://crbug.com/517697 for details. + * @throws AccountManagerDelegateException if Google Play Services are out of date, + * Chrome lacks necessary permissions, etc. */ @WorkerThread - public Account[] getGoogleAccounts() { - return mDelegate.getAccountsByType(GOOGLE_ACCOUNT_TYPE); + public Account[] getGoogleAccounts() throws AccountManagerDelegateException { + return mDelegate.getAccountsSync(); } /** - * Retrieves all Google accounts on the device asynchronously. + * Retrieves all Google accounts on the device. + * Returns an empty array if an error occurs while getting account list. + */ + @WorkerThread + public Account[] tryGetGoogleAccounts() { + try { + return getGoogleAccounts(); + } catch (AccountManagerDelegateException e) { + return new Account[0]; + } + } + + /** + * Asynchronous version of {@link #tryGetGoogleAccounts()}. */ @MainThread - public void getGoogleAccounts(final Callback<Account[]> callback) { + public void tryGetGoogleAccounts(final Callback<Account[]> callback) { ThreadUtils.assertOnUiThread(); new AsyncTask<Void, Void, Account[]>() { @Override protected Account[] doInBackground(Void... params) { - return getGoogleAccounts(); + return tryGetGoogleAccounts(); } @Override @@ -200,21 +228,29 @@ } /** - * This method is deprecated; please use the asynchronous version below instead. - * - * See http://crbug.com/517697 for details. + * This method is deprecated and will be removed soon. */ - @WorkerThread - public boolean hasGoogleAccounts() { - return getGoogleAccounts().length > 0; + // TODO(bsazonov) remove this method after fixing internal usages. + @MainThread + public void getGoogleAccounts(final Callback<Account[]> callback) { + tryGetGoogleAccounts(callback); } /** - * Asynchronously determine whether any Google accounts have been added. + * Determine whether there are any Google accounts on the device. + * Returns false if an error occurs while getting account list. + */ + @WorkerThread + public boolean hasGoogleAccounts() { + return tryGetGoogleAccounts().length > 0; + } + + /** + * Asynchronous version of {@link #hasGoogleAccounts()}. */ @MainThread public void hasGoogleAccounts(final Callback<Boolean> callback) { - getGoogleAccounts(new Callback<Account[]>() { + tryGetGoogleAccounts(new Callback<Account[]>() { @Override public void onResult(Account[] accounts) { callback.onResult(accounts.length > 0); @@ -236,14 +272,13 @@ } /** - * This method is deprecated; please use the asynchronous version below instead. - * - * See http://crbug.com/517697 for details. + * Returns the account if it exists; null if account doesn't exists or an error occurs + * while getting account list. */ @WorkerThread public Account getAccountFromName(String accountName) { String canonicalName = canonicalizeName(accountName); - Account[] accounts = getGoogleAccounts(); + Account[] accounts = tryGetGoogleAccounts(); for (Account account : accounts) { if (canonicalizeName(account.name).equals(canonicalName)) { return account; @@ -253,12 +288,12 @@ } /** - * Asynchronously returns the account if it exists; null otherwise. + * Asynchronous version of {@link #getAccountFromName(String)}. */ @MainThread public void getAccountFromName(String accountName, final Callback<Account> callback) { final String canonicalName = canonicalizeName(accountName); - getGoogleAccounts(new Callback<Account[]>() { + tryGetGoogleAccounts(new Callback<Account[]>() { @Override public void onResult(Account[] accounts) { Account accountForName = null; @@ -274,9 +309,8 @@ } /** - * This method is deprecated; please use the asynchronous version below instead. - * - * See http://crbug.com/517697 for details. + * Returns whether an account exists with the given name. + * Returns false if an error occurs while getting account list. */ @WorkerThread public boolean hasAccountForName(String accountName) { @@ -284,7 +318,7 @@ } /** - * Asynchronously returns whether an account exists with the given name. + * Asynchronous version of {@link #hasAccountForName(String)}. */ // TODO(maxbogue): Remove once this function is used outside of tests. @VisibleForTesting
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java index ba1b73d..f1231936 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java
@@ -61,6 +61,11 @@ } @Override + public Account[] getAccountsSync() throws AccountManagerDelegateException { + return getAccountsByType(GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE); + } + + @Override public String getAuthToken(Account account, String authTokenScope) throws AuthException { assert !ThreadUtils.runningOnUiThread(); assert AccountManagerHelper.GOOGLE_ACCOUNT_TYPE.equals(account.type);
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java index 64eaf04..d61073e84 100644 --- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java +++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java
@@ -16,6 +16,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.VisibleForTesting; import org.chromium.components.signin.AccountManagerDelegate; +import org.chromium.components.signin.AccountManagerDelegateException; import org.chromium.components.signin.AccountManagerHelper; import java.util.ArrayList; @@ -68,6 +69,19 @@ return validAccounts.toArray(new Account[0]); } + @Override + public Account[] getAccountsSync() throws AccountManagerDelegateException { + return getAccountsSyncNoThrow(); + } + + public Account[] getAccountsSyncNoThrow() { + ArrayList<Account> result = new ArrayList<>(); + for (AccountHolder ah : mAccounts) { + result.add(ah.getAccount()); + } + return result.toArray(new Account[0]); + } + /** * Add an AccountHolder directly. *
diff --git a/components/sync/android/java/src/org/chromium/components/sync/AndroidSyncSettings.java b/components/sync/android/java/src/org/chromium/components/sync/AndroidSyncSettings.java index e131335f..5207bb6 100644 --- a/components/sync/android/java/src/org/chromium/components/sync/AndroidSyncSettings.java +++ b/components/sync/android/java/src/org/chromium/components/sync/AndroidSyncSettings.java
@@ -252,7 +252,7 @@ ThreadUtils.postOnUiThread(new Runnable() { @Override public void run() { - AccountManagerHelper.get().getGoogleAccounts(new Callback<Account[]>() { + AccountManagerHelper.get().tryGetGoogleAccounts(new Callback<Account[]>() { @Override public void onResult(Account[] accounts) { synchronized (mLock) {
diff --git a/content/browser/blob_storage/blob_url_loader_factory.cc b/content/browser/blob_storage/blob_url_loader_factory.cc index 5b79e7c..dbb2883 100644 --- a/content/browser/blob_storage/blob_url_loader_factory.cc +++ b/content/browser/blob_storage/blob_url_loader_factory.cc
@@ -351,15 +351,18 @@ } // namespace -BlobURLLoaderFactory::BlobURLLoaderFactory( +// static +scoped_refptr<BlobURLLoaderFactory> BlobURLLoaderFactory::Create( BlobContextGetter blob_storage_context_getter, - scoped_refptr<storage::FileSystemContext> file_system_context) - : file_system_context_(file_system_context) { + scoped_refptr<storage::FileSystemContext> file_system_context) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + auto factory = base::MakeRefCounted<BlobURLLoaderFactory>( + std::move(file_system_context)); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::BindOnce(&BlobURLLoaderFactory::InitializeOnIO, this, + base::BindOnce(&BlobURLLoaderFactory::InitializeOnIO, factory, std::move(blob_storage_context_getter))); + return factory; } void BlobURLLoaderFactory::HandleRequest( @@ -370,6 +373,10 @@ std::move(request))); } +BlobURLLoaderFactory::BlobURLLoaderFactory( + scoped_refptr<storage::FileSystemContext> file_system_context) + : file_system_context_(std::move(file_system_context)) {} + BlobURLLoaderFactory::~BlobURLLoaderFactory() {} void BlobURLLoaderFactory::InitializeOnIO(
diff --git a/content/browser/blob_storage/blob_url_loader_factory.h b/content/browser/blob_storage/blob_url_loader_factory.h index 35df893..9f01143 100644 --- a/content/browser/blob_storage/blob_url_loader_factory.h +++ b/content/browser/blob_storage/blob_url_loader_factory.h
@@ -30,7 +30,8 @@ public: using BlobContextGetter = base::OnceCallback<base::WeakPtr<storage::BlobStorageContext>()>; - CONTENT_EXPORT BlobURLLoaderFactory( + + static CONTENT_EXPORT scoped_refptr<BlobURLLoaderFactory> Create( BlobContextGetter blob_storage_context_getter, scoped_refptr<storage::FileSystemContext> file_system_context); @@ -66,7 +67,11 @@ private: friend class base::DeleteHelper<BlobURLLoaderFactory>; friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>; + template <typename T, typename... Args> + friend scoped_refptr<T> base::MakeRefCounted(Args&&... args); + BlobURLLoaderFactory( + scoped_refptr<storage::FileSystemContext> file_system_context); ~BlobURLLoaderFactory() override; void InitializeOnIO(BlobContextGetter blob_storage_context_getter);
diff --git a/content/browser/blob_storage/blob_url_unittest.cc b/content/browser/blob_storage/blob_url_unittest.cc index 93d7cc9..32b4837 100644 --- a/content/browser/blob_storage/blob_url_unittest.cc +++ b/content/browser/blob_storage/blob_url_unittest.cc
@@ -283,10 +283,11 @@ mojom::URLLoaderAssociatedPtr url_loader; TestURLLoaderClient url_loader_client; - scoped_refptr<BlobURLLoaderFactory> factory = new BlobURLLoaderFactory( - base::Bind(&BlobURLRequestJobTest::GetStorageContext, - base::Unretained(this)), - file_system_context_); + scoped_refptr<BlobURLLoaderFactory> factory = + BlobURLLoaderFactory::Create( + base::Bind(&BlobURLRequestJobTest::GetStorageContext, + base::Unretained(this)), + file_system_context_); base::RunLoop().RunUntilIdle(); factory->CreateLoaderAndStart(mojo::MakeRequest(&url_loader), 0, 0, mojom::kURLLoadOptionNone, request,
diff --git a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc index e9f5acc..cfb976b 100644 --- a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc +++ b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
@@ -20,9 +20,9 @@ #include "build/build_config.h" #include "content/public/common/media_stream_request.h" #include "content/public/test/test_browser_thread_bundle.h" -#include "media/audio/audio_manager_base.h" #include "media/audio/audio_system_impl.h" #include "media/audio/audio_thread_impl.h" +#include "media/audio/mock_audio_manager.h" #include "media/base/media_switches.h" #include "media/base/test_helpers.h" #include "testing/gmock/include/gmock/gmock.h" @@ -64,7 +64,7 @@ MAYBE_AudioInputDeviceManagerTest() {} protected: - void SetUp() override { + virtual void Initialize() { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kUseFakeDeviceForMediaStream); // AudioInputDeviceManager accesses AudioSystem from IO thread, so it never @@ -74,16 +74,20 @@ // Flush the message loop to ensure proper initialization of AudioManager. base::RunLoop().RunUntilIdle(); - audio_system_ = media::AudioSystemImpl::Create(audio_manager_.get()); - manager_ = new AudioInputDeviceManager(audio_system_.get()); - audio_input_listener_.reset(new MockAudioInputDeviceManagerListener()); - manager_->RegisterListener(audio_input_listener_.get()); - // Use fake devices. devices_.emplace_back(MEDIA_DEVICE_AUDIO_CAPTURE, "Fake Device 1", "fake_device_1"); devices_.emplace_back(MEDIA_DEVICE_AUDIO_CAPTURE, "Fake Device 2", "fake_device_2"); + } + + void SetUp() override { + Initialize(); + + audio_system_ = media::AudioSystemImpl::Create(audio_manager_.get()); + manager_ = new AudioInputDeviceManager(audio_system_.get()); + audio_input_listener_.reset(new MockAudioInputDeviceManagerListener()); + manager_->RegisterListener(audio_input_listener_.get()); // Wait until we get the list. base::RunLoop().RunUntilIdle(); @@ -296,4 +300,62 @@ base::RunLoop().RunUntilIdle(); } +class AudioInputDeviceManagerNoDevicesTest + : public MAYBE_AudioInputDeviceManagerTest { + public: + AudioInputDeviceManagerNoDevicesTest(){}; + + protected: + void Initialize() override { + // MockAudioManager has no input and no output audio devices. + audio_manager_ = base::MakeUnique<media::MockAudioManager>( + base::MakeUnique<media::AudioThreadImpl>()); + + // Devices to request from AudioInputDeviceManager. + devices_.emplace_back(MEDIA_TAB_AUDIO_CAPTURE, "Tab capture", + "tab_capture"); + devices_.emplace_back(MEDIA_DESKTOP_AUDIO_CAPTURE, "Desktop capture", + "desktop_capture"); + devices_.emplace_back(MEDIA_DEVICE_AUDIO_CAPTURE, "Fake Device", + "fake_device"); + } + + private: + DISALLOW_COPY_AND_ASSIGN(AudioInputDeviceManagerNoDevicesTest); +}; + +TEST_F(AudioInputDeviceManagerNoDevicesTest, + ParametersValidWithoutAudioDevices) { + ASSERT_FALSE(devices_.empty()); + + InSequence s; + + for (const auto& device_request : devices_) { + int session_id = manager_->Open(device_request.device); + + EXPECT_CALL(*audio_input_listener_, + Opened(device_request.device.type, session_id)) + .Times(1); + WaitForOpenCompletion(); + + // Expects that device parameters stored by the manager are valid. + const StreamDeviceInfo* device_info = + manager_->GetOpenedDeviceInfoById(session_id); + EXPECT_TRUE( + media::AudioParameters(media::AudioParameters::AUDIO_FAKE, + static_cast<media::ChannelLayout>( + device_info->device.input.channel_layout), + device_info->device.input.sample_rate, 16, + device_info->device.input.frames_per_buffer) + .IsValid()); + + manager_->Close(session_id); + EXPECT_CALL(*audio_input_listener_, + Closed(device_request.device.type, session_id)) + .Times(1); + + base::RunLoop().RunUntilIdle(); + } +} + } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_event_handler.cc b/content/browser/renderer_host/render_widget_host_view_event_handler.cc index 5052626..ed267bc 100644 --- a/content/browser/renderer_host/render_widget_host_view_event_handler.cc +++ b/content/browser/renderer_host/render_widget_host_view_event_handler.cc
@@ -313,9 +313,10 @@ // As the overscroll is handled during scroll events from the trackpad, the // RWHVA window is transformed by the overscroll controller. This transform // triggers a synthetic mouse-move event to be generated (by the aura - // RootWindow). But this event interferes with the overscroll gesture. So, - // ignore such synthetic mouse-move events if an overscroll gesture is in - // progress. + // RootWindow). Also, with a touchscreen, we may get a synthetic mouse-move + // caused by a pointer grab. But these events interfere with the overscroll + // gesture. So, ignore such synthetic mouse-move events if an overscroll + // gesture is in progress. OverscrollController* overscroll_controller = delegate_->overscroll_controller(); if (overscroll_controller &&
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 7e6db81..8369ba8 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -550,7 +550,7 @@ ChromeBlobStorageContext::GetFor(context); BlobURLLoaderFactory::BlobContextGetter blob_getter = base::BindOnce(&BlobStorageContextGetter, blob_context); - partition->blob_url_loader_factory_ = new BlobURLLoaderFactory( + partition->blob_url_loader_factory_ = BlobURLLoaderFactory::Create( std::move(blob_getter), partition->filesystem_context_); partition->url_loader_factory_getter_ = new URLLoaderFactoryGetter();
diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc index c8009fe5..9cd07123 100644 --- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc +++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -28,6 +28,7 @@ #include "content/common/input_messages.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_message_filter.h" +#include "content/public/browser/overscroll_configuration.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_widget_host.h" #include "content/public/browser/web_contents_delegate.h" @@ -429,6 +430,108 @@ TestOverscrollNavigation(true); } +namespace { +// This fails the test if it sees any mouse move events. +class SpuriousMouseMoveEventObserver + : public RenderWidgetHost::InputEventObserver { + public: + explicit SpuriousMouseMoveEventObserver(RenderWidgetHost* host) + : host_(host) { + host_->AddInputEventObserver(this); + } + + ~SpuriousMouseMoveEventObserver() override { + host_->RemoveInputEventObserver(this); + } + + void OnInputEvent(const blink::WebInputEvent& event) override { + EXPECT_NE(blink::WebInputEvent::kMouseMove, event.GetType()) + << "Unexpected mouse move event."; + } + + private: + RenderWidgetHost* host_; + + DISALLOW_COPY_AND_ASSIGN(SpuriousMouseMoveEventObserver); +}; +} // namespace + +// Start an overscroll gesture and then check if the gesture is interrupted by +// a spurious mouse event. Overscrolling may trigger mouse-move events, but +// these should all be marked as synthesized and get dropped while the +// overscroll gesture is in progress. +// See crbug.com/731914 +IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, + OverscrollNotInterruptedBySpuriousMouseEvents) { + ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html")); + WebContentsImpl* web_contents = + static_cast<WebContentsImpl*>(shell()->web_contents()); + NavigationController& controller = web_contents->GetController(); + RenderFrameHost* main_frame = web_contents->GetMainFrame(); + + EXPECT_FALSE(controller.CanGoBack()); + EXPECT_FALSE(controller.CanGoForward()); + int index = -1; + std::unique_ptr<base::Value> value = + content::ExecuteScriptAndGetValue(main_frame, "get_current()"); + ASSERT_TRUE(value->GetAsInteger(&index)); + EXPECT_EQ(0, index); + + ExecuteSyncJSFunction(main_frame, "navigate_next()"); + value = content::ExecuteScriptAndGetValue(main_frame, "get_current()"); + ASSERT_TRUE(value->GetAsInteger(&index)); + EXPECT_EQ(1, index); + EXPECT_TRUE(controller.CanGoBack()); + EXPECT_FALSE(controller.CanGoForward()); + + // We start an overscroll gesture, but pause mid-gesture. + + // Fail the test if the following gesture produces mouse-moves that don't get + // dropped. + SpuriousMouseMoveEventObserver mouse_observer(GetRenderWidgetHost()); + + blink::WebGestureEvent gesture_scroll_begin( + blink::WebGestureEvent::kGestureScrollBegin, + blink::WebInputEvent::kNoModifiers, + blink::WebInputEvent::kTimeStampForTesting); + gesture_scroll_begin.source_device = blink::kWebGestureDeviceTouchscreen; + gesture_scroll_begin.data.scroll_begin.delta_hint_units = + blink::WebGestureEvent::ScrollUnits::kPrecisePixels; + gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0.f; + gesture_scroll_begin.data.scroll_begin.delta_y_hint = 0.f; + GetRenderWidgetHost()->ForwardGestureEvent(gesture_scroll_begin); + + blink::WebGestureEvent gesture_scroll_update( + blink::WebGestureEvent::kGestureScrollUpdate, + blink::WebInputEvent::kNoModifiers, + blink::WebInputEvent::kTimeStampForTesting); + gesture_scroll_update.source_device = blink::kWebGestureDeviceTouchscreen; + gesture_scroll_update.data.scroll_update.delta_units = + blink::WebGestureEvent::ScrollUnits::kPrecisePixels; + gesture_scroll_update.data.scroll_update.delta_y = 0.f; + float horiz_threshold = + GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN); + gesture_scroll_update.data.scroll_update.delta_x = horiz_threshold + 1; + GetRenderWidgetHost()->ForwardGestureEvent(gesture_scroll_update); + + // Wait for the overscroll gesture to start and then allow some time for the + // spurious mouse event. Since we're testing that an event does not happen, + // we just have a timeout. This could potentially result in the event + // happening after the timeout, which would cause the test to succeed + // incorrectly. That said, the event we're worried about happens almost + // instantly after the start of the overscroll gesture. + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout()); + run_loop.Run(); + + // Check that the overscroll gesture was not reset. + OverscrollController* overscroll_controller = + static_cast<RenderWidgetHostViewAura*>(GetRenderWidgetHostView()) + ->overscroll_controller(); + EXPECT_NE(OVERSCROLL_NONE, overscroll_controller->overscroll_mode()); +} + // Disabled because the test always fails the first time it runs on the Win Aura // bots, and usually but not always passes second-try (See crbug.com/179532). // On Linux, the test frequently times out. (See crbug.com/440043).
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py index 2f5f3cf..4cfc06a 100755 --- a/content/test/gpu/generate_buildbot_json.py +++ b/content/test/gpu/generate_buildbot_json.py
@@ -1119,11 +1119,14 @@ 'gpu': '10de:104a', 'os': 'Windows-2008ServerR2-SP1' }, + # Temporarily disable AMD deqp ES3 tests due to issues with the log + # size causing out-of-memory errors in the recipe engine. + # crbug.com/713196 # AMD Win 7 - { - 'gpu': '1002:6613', - 'os': 'Windows-2008ServerR2-SP1' - } + #{ + # 'gpu': '1002:6613', + # 'os': 'Windows-2008ServerR2-SP1' + #} ], } ],
diff --git a/docs/android_debugging_instructions.md b/docs/android_debugging_instructions.md index fbb4f98..3c4eba2a 100644 --- a/docs/android_debugging_instructions.md +++ b/docs/android_debugging_instructions.md
@@ -203,19 +203,23 @@ ```shell out/Default/apks/ChromePublic.apk.mapping -out/Default/apks/Chrome.apk.mapping +out/Default/apks/ChromeModernPublic.apk.mapping +etc. ``` -To deobfuscate a stack trace from a file, run +Build the `java_deobfuscate` tool: ```shell -build/android/stacktrace/java_deobfuscate.py PROGUARD_MAPPING_FILE.mapping --stacktrace STACKTRACE_FILE +ninja -C out/Default java_deobfuscate ``` -Deobfuscation also works from `stdin`: +Then run it via: ```shell -adb logcat -d | build/android/stacktrace/java_deobfuscate.py PROGUARD_MAPPING_FILE.mapping +# For a file: +out/Default/bin/java_deobfuscate PROGUARD_MAPPING_FILE.mapping < FILE +# For logcat: +adb logcat | out/Default/bin/java_deobfuscate PROGUARD_MAPPING_FILE.mapping ``` ## Get WebKit code to output to the adb log
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_store_factory.cc b/ios/chrome/browser/passwords/ios_chrome_password_store_factory.cc index d5d74614..d6ac1a2 100644 --- a/ios/chrome/browser/passwords/ios_chrome_password_store_factory.cc +++ b/ios/chrome/browser/passwords/ios_chrome_password_store_factory.cc
@@ -9,8 +9,8 @@ #include "base/command_line.h" #include "base/memory/singleton.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/sequenced_task_runner.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "components/browser_sync/profile_sync_service.h" #include "components/keyed_service/core/service_access_type.h" #include "components/keyed_service/ios/browser_state_dependency_manager.h" @@ -60,8 +60,7 @@ browser_state->GetRequestContext(); password_manager::ToggleAffiliationBasedMatchingBasedOnPasswordSyncedState( password_store.get(), sync_service, request_context_getter, - browser_state->GetStatePath(), - web::WebThread::GetTaskRunnerForThread(web::WebThread::DB)); + browser_state->GetStatePath()); } IOSChromePasswordStoreFactory::IOSChromePasswordStoreFactory() @@ -79,9 +78,9 @@ std::unique_ptr<password_manager::LoginDatabase> login_db( password_manager::CreateLoginDatabase(context->GetStatePath())); - scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner( - base::ThreadTaskRunnerHandle::Get()); - scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner( + scoped_refptr<base::SequencedTaskRunner> main_thread_runner( + base::SequencedTaskRunnerHandle::Get()); + scoped_refptr<base::SequencedTaskRunner> db_thread_runner( web::WebThread::GetTaskRunnerForThread(web::WebThread::DB)); scoped_refptr<password_manager::PasswordStore> store =
diff --git a/ios/chrome/browser/web/progress_indicator_egtest.mm b/ios/chrome/browser/web/progress_indicator_egtest.mm index 93beaf4e..5f5daf7 100644 --- a/ios/chrome/browser/web/progress_indicator_egtest.mm +++ b/ios/chrome/browser/web/progress_indicator_egtest.mm
@@ -13,7 +13,6 @@ #include "ios/chrome/test/app/web_view_interaction_test_util.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" -#import "ios/chrome/test/earl_grey/chrome_matchers.h" #import "ios/chrome/test/earl_grey/chrome_test_case.h" #import "ios/third_party/material_components_ios/src/components/ProgressView/src/MaterialProgressView.h" #include "ios/web/public/test/http_server/html_response_provider.h" @@ -25,8 +24,6 @@ #error "This file requires ARC support." #endif -using chrome_test_util::WebViewContainingText; - namespace { // Text to display in form page. @@ -184,20 +181,12 @@ // Load form first. [ChromeEarlGrey loadURL:formURL]; - - // TODO(crbug.com/707009): Replace this matcher with - // [ChromeEarlGrey waitForWebViewContainingText]. It fails to synchronize with - // the progress bar. - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kFormPageText)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kFormPageText]; chrome_test_util::SubmitWebViewFormWithId(kFormID); // Wait until the page is half loaded. - // TODO(crbug.com/707009): Replace this matcher with - // [ChromeEarlGrey waitForWebViewContainingText]. - [[EarlGrey selectElementWithMatcher:WebViewContainingText(kPageText)] - assertWithMatcher:grey_notNil()]; + [ChromeEarlGrey waitForWebViewContainingText:kPageText]; // Verify progress view visible and halfway progress. [[EarlGrey selectElementWithMatcher:ProgressViewWithProgress(0.5)]
diff --git a/net/BUILD.gn b/net/BUILD.gn index 4201f5b..69809871 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -1315,6 +1315,9 @@ "quic/core/quic_spdy_stream.h", "quic/core/quic_stream.cc", "quic/core/quic_stream.h", + "quic/core/quic_stream_frame_data_producer.h", + "quic/core/quic_stream_send_buffer.cc", + "quic/core/quic_stream_send_buffer.h", "quic/core/quic_stream_sequencer.cc", "quic/core/quic_stream_sequencer.h", "quic/core/quic_stream_sequencer_buffer.cc", @@ -3104,6 +3107,8 @@ "quic/test_tools/quic_time_wait_list_manager_peer.h", "quic/test_tools/rtt_stats_peer.cc", "quic/test_tools/rtt_stats_peer.h", + "quic/test_tools/simple_data_producer.cc", + "quic/test_tools/simple_data_producer.h", "quic/test_tools/simple_quic_framer.cc", "quic/test_tools/simple_quic_framer.h", "quic/test_tools/simulator/actor.cc", @@ -4921,6 +4926,7 @@ "quic/core/quic_simple_buffer_allocator_test.cc", "quic/core/quic_socket_address_coder_test.cc", "quic/core/quic_spdy_stream_test.cc", + "quic/core/quic_stream_send_buffer_test.cc", "quic/core/quic_stream_sequencer_buffer_test.cc", "quic/core/quic_stream_sequencer_test.cc", "quic/core/quic_stream_test.cc",
diff --git a/net/quic/core/frames/quic_stream_frame.cc b/net/quic/core/frames/quic_stream_frame.cc index ba346396..ccae486 100644 --- a/net/quic/core/frames/quic_stream_frame.cc +++ b/net/quic/core/frames/quic_stream_frame.cc
@@ -52,6 +52,12 @@ QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id, bool fin, QuicStreamOffset offset, + QuicPacketLength data_length) + : QuicStreamFrame(stream_id, fin, offset, nullptr, data_length, nullptr) {} + +QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id, + bool fin, + QuicStreamOffset offset, const char* data_buffer, QuicPacketLength data_length, UniqueStreamBuffer buffer)
diff --git a/net/quic/core/frames/quic_stream_frame.h b/net/quic/core/frames/quic_stream_frame.h index 138cc48..90cfbfe 100644 --- a/net/quic/core/frames/quic_stream_frame.h +++ b/net/quic/core/frames/quic_stream_frame.h
@@ -50,6 +50,10 @@ QuicStreamOffset offset, QuicPacketLength data_length, UniqueStreamBuffer buffer); + QuicStreamFrame(QuicStreamId stream_id, + bool fin, + QuicStreamOffset offset, + QuicPacketLength data_length); ~QuicStreamFrame(); friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, @@ -60,6 +64,10 @@ QuicPacketLength data_length; const char* data_buffer; QuicStreamOffset offset; // Location of this data in the stream. + // TODO(fayang): When deprecating + // FLAGS_quic_reloadable_flag_quic_stream_owns_data: (1) Remove buffer from + // QuicStreamFrame; (2) remove the constructor uses UniqueStreamBuffer and (3) + // Move definition of UniqueStreamBuffer to QuicStreamSendBuffer. // nullptr when the QuicStreamFrame is received, and non-null when sent. UniqueStreamBuffer buffer;
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc index 26f097d..4f6c889 100644 --- a/net/quic/core/quic_connection.cc +++ b/net/quic/core/quic_connection.cc
@@ -2441,4 +2441,23 @@ sent_packet_manager_.SetStreamNotifier(stream_notifier); } +void QuicConnection::SetDelegateSavesData(bool delegate_saves_data) { + packet_generator_.SetDelegateSavesData(delegate_saves_data); +} + +void QuicConnection::SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) { + visitor_->SaveStreamData(id, iov, iov_offset, offset, data_length); +} + +bool QuicConnection::WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) { + return visitor_->WriteStreamData(id, offset, data_length, writer); +} + } // namespace net
diff --git a/net/quic/core/quic_connection.h b/net/quic/core/quic_connection.h index 4503c6c..4d081cc 100644 --- a/net/quic/core/quic_connection.h +++ b/net/quic/core/quic_connection.h
@@ -160,6 +160,19 @@ // Called to ask if any streams are open in this visitor, excluding the // reserved crypto and headers stream. virtual bool HasOpenDynamicStreams() const = 0; + + // Save |data_length| data starts at |iov_offset| in |iov|. + virtual void SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) = 0; + + // Write |data_length| data with |offset| of stream |id| to |writer|. + virtual bool WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) = 0; }; // Interface which gets callbacks from the QuicConnection at interesting @@ -464,6 +477,17 @@ // QuicPacketCreator::DelegateInterface void OnSerializedPacket(SerializedPacket* packet) override; + // QuicStreamFrameDataProducer methods: + void SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) override; + bool WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override; + // QuicSentPacketManager::NetworkChangeVisitor void OnCongestionChange() override; void OnPathDegrading() override; @@ -662,6 +686,11 @@ // Sets the stream notifer on the SentPacketManager. void SetStreamNotifier(StreamNotifierInterface* stream_notifier); + // Enable/disable delegate saves data in PacketCreator. + // TODO(fayang): Remove this method when deprecating + // quic_reloadable_flag_quic_stream_owns_data. + void SetDelegateSavesData(bool delegate_saves_data); + // Return the name of the cipher of the primary decrypter of the framer. const char* cipher_name() const { return framer_.decrypter()->cipher_name(); } // Return the id of the cipher of the primary decrypter of the framer.
diff --git a/net/quic/core/quic_connection_test.cc b/net/quic/core/quic_connection_test.cc index c2eb3023..554675ec 100644 --- a/net/quic/core/quic_connection_test.cc +++ b/net/quic/core/quic_connection_test.cc
@@ -826,8 +826,9 @@ QuicPacketHeader header; QuicPacketCreatorPeer::FillPacketHeader(&peer_creator_, &header); char encrypted_buffer[kMaxPacketSize]; + // TODO(fayang): Use data producer to produce data. size_t length = peer_framer_.BuildDataPacket( - header, frames, encrypted_buffer, kMaxPacketSize); + header, frames, encrypted_buffer, kMaxPacketSize, nullptr); DCHECK_GT(length, 0u); const size_t encrypted_length = peer_framer_.EncryptInPlace( @@ -1907,13 +1908,13 @@ // using writev. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - char data[] = "ABCD"; + char data[] = "ABCDEF"; struct iovec iov[2]; iov[0].iov_base = data; - iov[0].iov_len = 2; - iov[1].iov_base = data + 2; + iov[0].iov_len = 4; + iov[1].iov_base = data + 4; iov[1].iov_len = 2; - connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, NO_FIN, nullptr); + connection_.SendStreamData(1, QuicIOVector(iov, 2, 6), 0, NO_FIN, nullptr); EXPECT_EQ(0u, connection_.NumQueuedPackets()); EXPECT_FALSE(connection_.HasQueuedData()); @@ -1925,7 +1926,7 @@ EXPECT_EQ(1u, writer_->padding_frames().size()); QuicStreamFrame* frame = writer_->stream_frames()[0].get(); EXPECT_EQ(1u, frame->stream_id); - EXPECT_EQ("ABCD", QuicStringPiece(frame->data_buffer, frame->data_length)); + EXPECT_EQ("ABCDEF", QuicStringPiece(frame->data_buffer, frame->data_length)); } TEST_P(QuicConnectionTest, FramePackingSendvQueued) { @@ -1933,13 +1934,13 @@ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); BlockOnNextWrite(); - char data[] = "ABCD"; + char data[] = "ABCDEF"; struct iovec iov[2]; iov[0].iov_base = data; - iov[0].iov_len = 2; - iov[1].iov_base = data + 2; + iov[0].iov_len = 4; + iov[1].iov_base = data + 4; iov[1].iov_len = 2; - connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, NO_FIN, nullptr); + connection_.SendStreamData(1, QuicIOVector(iov, 2, 6), 0, NO_FIN, nullptr); EXPECT_EQ(1u, connection_.NumQueuedPackets()); EXPECT_TRUE(connection_.HasQueuedData()); @@ -3099,7 +3100,8 @@ // Send more packets, and ensure that none of them sets the alarm. for (QuicPacketCount i = 0; i < 4 * kPacketsBetweenMtuProbesBase; i++) { - SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); + SendStreamDataToPeer(3, ".", kPacketsBetweenMtuProbesBase + 1 + i, NO_FIN, + nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } @@ -3228,7 +3230,8 @@ // Send more packets, and ensure that none of them sets the alarm. for (QuicPacketCount i = 0; i < 4 * kPacketsBetweenMtuProbesBase; i++) { - SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); + SendStreamDataToPeer(3, ".", kPacketsBetweenMtuProbesBase + 1 + i, NO_FIN, + nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } @@ -3327,7 +3330,7 @@ // Now send more data. This will not move the timeout becase // no data has been recieved since the previous write. clock_.AdvanceTime(five_ms); - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 3, FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); // The original alarm will fire. We should not time out because we had a @@ -3466,7 +3469,7 @@ // Now send more data. This will not move the timeout becase // no data has been recieved since the previous write. clock_.AdvanceTime(five_ms); - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 3, FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); // The original alarm will fire. We should not time out because we had a
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h index 324093b..add549a 100644 --- a/net/quic/core/quic_flags_list.h +++ b/net/quic/core/quic_flags_list.h
@@ -177,6 +177,9 @@ // When true, defaults to BBR congestion control instead of Cubic. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_default_to_bbr, false) +// If true, stream sent data is saved in streams rather than stream frames. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_stream_owns_data, false) + // Allow a new rate based recovery in QUIC BBR to be enabled via connection // option. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_rate_recovery, false)
diff --git a/net/quic/core/quic_framer.cc b/net/quic/core/quic_framer.cc index f5d771c..590f1aec 100644 --- a/net/quic/core/quic_framer.cc +++ b/net/quic/core/quic_framer.cc
@@ -18,6 +18,7 @@ #include "net/quic/core/quic_data_reader.h" #include "net/quic/core/quic_data_writer.h" #include "net/quic/core/quic_socket_address_coder.h" +#include "net/quic/core/quic_stream_frame_data_producer.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_aligned.h" #include "net/quic/platform/api/quic_bug_tracker.h" @@ -312,7 +313,8 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header, const QuicFrames& frames, char* buffer, - size_t packet_length) { + size_t packet_length, + QuicStreamFrameDataProducer* data_producer) { QuicDataWriter writer(packet_length, buffer, perspective_, endianness()); if (!AppendPacketHeader(header, &writer)) { QUIC_BUG << "AppendPacketHeader failed"; @@ -338,7 +340,7 @@ break; case STREAM_FRAME: if (!AppendStreamFrame(*frame.stream_frame, no_stream_frame_length, - &writer)) { + &writer, data_producer)) { QUIC_BUG << "AppendStreamFrame failed"; return 0; } @@ -1791,7 +1793,8 @@ bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame, bool no_stream_frame_length, - QuicDataWriter* writer) { + QuicDataWriter* writer, + QuicStreamFrameDataProducer* data_producer) { if (!AppendStreamId(GetStreamIdSize(frame.stream_id), frame.stream_id, writer)) { QUIC_BUG << "Writing stream id size failed."; @@ -1810,6 +1813,19 @@ } } + if (data_producer != nullptr) { + DCHECK_EQ(nullptr, frame.data_buffer); + if (frame.data_length == 0) { + return true; + } + if (!data_producer->WriteStreamData(frame.stream_id, frame.offset, + frame.data_length, writer)) { + QUIC_BUG << "Writing frame data failed."; + return false; + } + return true; + } + if (!writer->WriteBytes(frame.data_buffer, frame.data_length)) { QUIC_BUG << "Writing frame data failed."; return false;
diff --git a/net/quic/core/quic_framer.h b/net/quic/core/quic_framer.h index f244191f..5131bab 100644 --- a/net/quic/core/quic_framer.h +++ b/net/quic/core/quic_framer.h
@@ -27,6 +27,7 @@ class QuicDecrypter; class QuicEncrypter; class QuicFramer; +class QuicStreamFrameDataProducer; // Number of bytes reserved for the frame type preceding each frame. const size_t kQuicFrameTypeSize = 1; @@ -241,7 +242,8 @@ size_t BuildDataPacket(const QuicPacketHeader& header, const QuicFrames& frames, char* buffer, - size_t packet_length); + size_t packet_length, + QuicStreamFrameDataProducer* data_producer); // Returns a new public reset packet. static std::unique_ptr<QuicEncryptedPacket> BuildPublicResetPacket( @@ -262,7 +264,8 @@ QuicDataWriter* writer); bool AppendStreamFrame(const QuicStreamFrame& frame, bool last_frame_in_packet, - QuicDataWriter* builder); + QuicDataWriter* writer, + QuicStreamFrameDataProducer* data_producer); // SetDecrypter sets the primary decrypter, replacing any that already exists, // and takes ownership. If an alternative decrypter is in place then the
diff --git a/net/quic/core/quic_headers_stream_test.cc b/net/quic/core/quic_headers_stream_test.cc index 14401ee6..4f3b9d4 100644 --- a/net/quic/core/quic_headers_stream_test.cc +++ b/net/quic/core/quic_headers_stream_test.cc
@@ -1048,7 +1048,7 @@ EXPECT_CALL(session_, WritevData(headers_stream_, kHeadersStreamId, _, _, NO_FIN, _)) .WillRepeatedly( - WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov))); + Invoke(&session_, &MockQuicSpdySession::ConsumeAndSaveAllData)); InSequence s; QuicReferenceCountedPointer<MockAckListener> ack_listener1( new MockAckListener());
diff --git a/net/quic/core/quic_packet_creator.cc b/net/quic/core/quic_packet_creator.cc index 05508cb..84413a9 100644 --- a/net/quic/core/quic_packet_creator.cc +++ b/net/quic/core/quic_packet_creator.cc
@@ -16,6 +16,7 @@ #include "net/quic/platform/api/quic_flag_utils.h" #include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" +#include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_string_piece.h" using std::string; @@ -47,7 +48,8 @@ latched_flag_no_stop_waiting_frames_( FLAGS_quic_reloadable_flag_quic_no_stop_waiting_frames), pending_padding_bytes_(0), - needs_full_padding_(false) { + needs_full_padding_(false), + delegate_saves_data_(false) { SetMaxPacketLength(kDefaultMaxPacketSize); } @@ -130,22 +132,17 @@ } CreateStreamFrame(id, iov, iov_offset, offset, fin, frame); // Explicitly disallow multi-packet CHLOs. - if (id == kCryptoStreamId && - frame->stream_frame->data_length >= sizeof(kCHLO) && - strncmp(frame->stream_frame->data_buffer, - reinterpret_cast<const char*>(&kCHLO), sizeof(kCHLO)) == 0) { - DCHECK_EQ(0u, iov_offset); - if (FLAGS_quic_enforce_single_packet_chlo && - frame->stream_frame->data_length < iov.iov->iov_len) { - const string error_details = "Client hello won't fit in a single packet."; - QUIC_BUG << error_details << " Constructed stream frame length: " - << frame->stream_frame->data_length - << " CHLO length: " << iov.iov->iov_len; - delegate_->OnUnrecoverableError(QUIC_CRYPTO_CHLO_TOO_LARGE, error_details, - ConnectionCloseSource::FROM_SELF); - delete frame->stream_frame; - return false; - } + if (StreamFrameStartsWithChlo(iov, iov_offset, *frame->stream_frame) && + FLAGS_quic_enforce_single_packet_chlo && + frame->stream_frame->data_length < iov.iov->iov_len) { + const string error_details = "Client hello won't fit in a single packet."; + QUIC_BUG << error_details << " Constructed stream frame length: " + << frame->stream_frame->data_length + << " CHLO length: " << iov.iov->iov_len; + delegate_->OnUnrecoverableError(QUIC_CRYPTO_CHLO_TOO_LARGE, error_details, + ConnectionCloseSource::FROM_SELF); + delete frame->stream_frame; + return false; } if (!AddFrame(*frame, /*save_retransmittable_frames=*/true)) { // Fails if we try to write unencrypted stream data. @@ -211,6 +208,14 @@ std::min<size_t>(BytesFree() - min_frame_size, data_size); bool set_fin = fin && bytes_consumed == data_size; // Last frame. + if (delegate_saves_data_) { + *frame = + QuicFrame(new QuicStreamFrame(id, set_fin, offset, bytes_consumed)); + if (bytes_consumed > 0) { + delegate_->SaveStreamData(id, iov, iov_offset, offset, bytes_consumed); + } + return; + } UniqueStreamBuffer buffer = NewStreamBuffer(buffer_allocator_, bytes_consumed); QuicUtils::CopyToBuffer(iov, iov_offset, bytes_consumed, buffer.get()); @@ -332,11 +337,22 @@ std::min<size_t>(available_size, remaining_data_size); const bool set_fin = fin && (bytes_consumed == remaining_data_size); - UniqueStreamBuffer stream_buffer = - NewStreamBuffer(buffer_allocator_, bytes_consumed); - QuicUtils::CopyToBuffer(iov, iov_offset, bytes_consumed, stream_buffer.get()); - std::unique_ptr<QuicStreamFrame> frame(new QuicStreamFrame( - id, set_fin, stream_offset, bytes_consumed, std::move(stream_buffer))); + std::unique_ptr<QuicStreamFrame> frame; + if (delegate_saves_data_) { + frame = QuicMakeUnique<QuicStreamFrame>(id, set_fin, stream_offset, + bytes_consumed); + if (bytes_consumed > 0) { + delegate_->SaveStreamData(id, iov, iov_offset, stream_offset, + bytes_consumed); + } + } else { + UniqueStreamBuffer stream_buffer = + NewStreamBuffer(buffer_allocator_, bytes_consumed); + QuicUtils::CopyToBuffer(iov, iov_offset, bytes_consumed, + stream_buffer.get()); + frame = QuicMakeUnique<QuicStreamFrame>( + id, set_fin, stream_offset, bytes_consumed, std::move(stream_buffer)); + } QUIC_DVLOG(1) << ENDPOINT << "Adding frame: " << *frame; // TODO(ianswett): AppendTypeByte and AppendStreamFrame could be optimized @@ -347,7 +363,8 @@ return; } if (!framer_->AppendStreamFrame(*frame, /* no stream frame length */ true, - &writer)) { + &writer, + delegate_saves_data_ ? delegate_ : nullptr)) { QUIC_BUG << "AppendStreamFrame failed"; return; } @@ -438,8 +455,9 @@ DCHECK_GE(max_plaintext_size_, packet_size_); // Use the packet_size_ instead of the buffer size to ensure smaller // packet sizes are properly used. - size_t length = framer_->BuildDataPacket(header, queued_frames_, - encrypted_buffer, packet_size_); + size_t length = framer_->BuildDataPacket( + header, queued_frames_, encrypted_buffer, packet_size_, + delegate_saves_data_ ? delegate_ : nullptr); if (length == 0) { QUIC_BUG << "Failed to serialize " << queued_frames_.size() << " frames."; return; @@ -609,4 +627,30 @@ pending_padding_bytes_ += size; } +bool QuicPacketCreator::StreamFrameStartsWithChlo( + QuicIOVector iov, + size_t iov_offset, + const QuicStreamFrame& frame) const { + if (!delegate_saves_data_) { + return frame.stream_id == kCryptoStreamId && + frame.data_length >= sizeof(kCHLO) && + strncmp(frame.data_buffer, reinterpret_cast<const char*>(&kCHLO), + sizeof(kCHLO)) == 0; + } + + if (framer_->perspective() == Perspective::IS_SERVER || + frame.stream_id != kCryptoStreamId || iov_offset != 0 || + frame.data_length < sizeof(kCHLO)) { + return false; + } + + if (iov.iov[0].iov_len < sizeof(kCHLO)) { + QUIC_BUG << "iov length " << iov.iov[0].iov_len << " is less than " + << sizeof(kCHLO); + return false; + } + return strncmp(reinterpret_cast<const char*>(iov.iov[0].iov_base), + reinterpret_cast<const char*>(&kCHLO), sizeof(kCHLO)) == 0; +} + } // namespace net
diff --git a/net/quic/core/quic_packet_creator.h b/net/quic/core/quic_packet_creator.h index 57c1615..667c659d 100644 --- a/net/quic/core/quic_packet_creator.h +++ b/net/quic/core/quic_packet_creator.h
@@ -21,6 +21,7 @@ #include "net/quic/core/quic_iovector.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_pending_retransmission.h" +#include "net/quic/core/quic_stream_frame_data_producer.h" #include "net/quic/platform/api/quic_export.h" namespace net { @@ -32,7 +33,8 @@ public: // A delegate interface for further processing serialized packet. class QUIC_EXPORT_PRIVATE DelegateInterface - : public QuicConnectionCloseDelegateInterface { + : public QuicConnectionCloseDelegateInterface, + public QuicStreamFrameDataProducer { public: ~DelegateInterface() override {} // Called when a packet is serialized. Delegate does not take the ownership @@ -216,6 +218,10 @@ QuicByteCount pending_padding_bytes() const { return pending_padding_bytes_; } + void set_delegate_saves_data(bool delegate_saves_data) { + delegate_saves_data_ = delegate_saves_data; + } + private: friend class test::QuicPacketCreatorPeer; @@ -261,6 +267,11 @@ // packet's public header. bool IncludeNonceInPublicHeader(); + // Returns true if |frame| starts with CHLO. + bool StreamFrameStartsWithChlo(QuicIOVector iov, + size_t iov_offset, + const QuicStreamFrame& frame) const; + // Does not own these delegates or the framer. DelegateInterface* delegate_; DebugDelegate* debug_delegate_; @@ -310,6 +321,10 @@ // bytes. bool needs_full_padding_; + // Indicates whether frame data is saved by delegate_. TODO(fayang): Remove + // this boolean when deprecating quic_reloadable_flag_quic_stream_owns_data. + bool delegate_saves_data_; + DISALLOW_COPY_AND_ASSIGN(QuicPacketCreator); };
diff --git a/net/quic/core/quic_packet_creator_test.cc b/net/quic/core/quic_packet_creator_test.cc index ae31766..0499ba71 100644 --- a/net/quic/core/quic_packet_creator_test.cc +++ b/net/quic/core/quic_packet_creator_test.cc
@@ -13,6 +13,7 @@ #include "net/quic/core/crypto/null_encrypter.h" #include "net/quic/core/crypto/quic_decrypter.h" #include "net/quic/core/crypto/quic_encrypter.h" +#include "net/quic/core/quic_data_writer.h" #include "net/quic/core/quic_pending_retransmission.h" #include "net/quic/core/quic_simple_buffer_allocator.h" #include "net/quic/core/quic_utils.h" @@ -41,21 +42,25 @@ struct TestParams { TestParams(QuicVersion version, bool version_serialization, - QuicConnectionIdLength length) + QuicConnectionIdLength length, + bool delegate_saves_data) : version(version), connection_id_length(length), - version_serialization(version_serialization) {} + version_serialization(version_serialization), + delegate_saves_data(delegate_saves_data) {} friend std::ostream& operator<<(std::ostream& os, const TestParams& p) { os << "{ client_version: " << QuicVersionToString(p.version) << " connection id length: " << p.connection_id_length - << " include version: " << p.version_serialization << " }"; + << " include version: " << p.version_serialization + << " delegate_saves_data: " << p.delegate_saves_data << " }"; return os; } QuicVersion version; QuicConnectionIdLength connection_id_length; bool version_serialization; + bool delegate_saves_data; }; // Constructs various test permutations. @@ -63,31 +68,22 @@ std::vector<TestParams> params; constexpr QuicConnectionIdLength kMax = PACKET_8BYTE_CONNECTION_ID; QuicVersionVector all_supported_versions = AllSupportedVersions(); - for (size_t i = 0; i < all_supported_versions.size(); ++i) { - params.push_back(TestParams(all_supported_versions[i], true, kMax)); - params.push_back(TestParams(all_supported_versions[i], false, kMax)); + for (bool delegate_saves_data : {true, false}) { + for (size_t i = 0; i < all_supported_versions.size(); ++i) { + params.push_back(TestParams(all_supported_versions[i], true, kMax, + delegate_saves_data)); + params.push_back(TestParams(all_supported_versions[i], false, kMax, + delegate_saves_data)); + } + params.push_back(TestParams(all_supported_versions[0], true, + PACKET_0BYTE_CONNECTION_ID, + delegate_saves_data)); + params.push_back( + TestParams(all_supported_versions[0], true, kMax, delegate_saves_data)); } - params.push_back( - TestParams(all_supported_versions[0], true, PACKET_0BYTE_CONNECTION_ID)); - params.push_back(TestParams(all_supported_versions[0], true, kMax)); return params; } -class MockDelegate : public QuicPacketCreator::DelegateInterface { - public: - MockDelegate() {} - ~MockDelegate() override {} - - MOCK_METHOD1(OnSerializedPacket, void(SerializedPacket* packet)); - MOCK_METHOD3(OnUnrecoverableError, - void(QuicErrorCode, - const string&, - ConnectionCloseSource source)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockDelegate); -}; - class QuicPacketCreatorTest : public QuicTestWithParam<TestParams> { public: void ClearSerializedPacketForTests(SerializedPacket* serialized_packet) { @@ -136,6 +132,9 @@ new NullEncrypter(Perspective::IS_CLIENT)); client_framer_.set_visitor(&framer_visitor_); server_framer_.set_visitor(&framer_visitor_); + if (GetParam().delegate_saves_data) { + creator_.set_delegate_saves_data(true); + } } ~QuicPacketCreatorTest() override { @@ -165,8 +164,19 @@ EXPECT_EQ(STREAM_FRAME, frame.type); ASSERT_TRUE(frame.stream_frame); EXPECT_EQ(stream_id, frame.stream_frame->stream_id); - EXPECT_EQ(data, QuicStringPiece(frame.stream_frame->data_buffer, - frame.stream_frame->data_length)); + if (GetParam().delegate_saves_data) { + char buf[kMaxPacketSize]; + QuicDataWriter writer(kMaxPacketSize, buf, Perspective::IS_CLIENT, + HOST_BYTE_ORDER); + if (frame.stream_frame->data_length > 0) { + delegate_.WriteStreamData(stream_id, frame.stream_frame->offset, + frame.stream_frame->data_length, &writer); + } + EXPECT_EQ(data, QuicStringPiece(buf, frame.stream_frame->data_length)); + } else { + EXPECT_EQ(data, QuicStringPiece(frame.stream_frame->data_buffer, + frame.stream_frame->data_length)); + } EXPECT_EQ(offset, frame.stream_frame->offset); EXPECT_EQ(fin, frame.stream_frame->fin); } @@ -216,7 +226,7 @@ QuicFramer server_framer_; QuicFramer client_framer_; StrictMock<MockFramerVisitor> framer_visitor_; - StrictMock<MockDelegate> delegate_; + StrictMock<MockPacketCreatorDelegate> delegate_; QuicConnectionId connection_id_; string data_; struct iovec iov_;
diff --git a/net/quic/core/quic_packet_generator.cc b/net/quic/core/quic_packet_generator.cc index 7487cde..be882ce 100644 --- a/net/quic/core/quic_packet_generator.cc +++ b/net/quic/core/quic_packet_generator.cc
@@ -353,4 +353,8 @@ packet_creator_.HasPendingRetransmittableFrames(); } +void QuicPacketGenerator::SetDelegateSavesData(bool delegate_saves_data) { + packet_creator_.set_delegate_saves_data(delegate_saves_data); +} + } // namespace net
diff --git a/net/quic/core/quic_packet_generator.h b/net/quic/core/quic_packet_generator.h index 43bffc1..1b04881 100644 --- a/net/quic/core/quic_packet_generator.h +++ b/net/quic/core/quic_packet_generator.h
@@ -180,6 +180,9 @@ // when there are frames queued in the creator. void SetMaxPacketLength(QuicByteCount length); + // Let delegate save stream data in creator. + void SetDelegateSavesData(bool delegate_saves_data); + void set_debug_delegate(QuicPacketCreator::DebugDelegate* debug_delegate) { packet_creator_.set_debug_delegate(debug_delegate); }
diff --git a/net/quic/core/quic_packet_generator_test.cc b/net/quic/core/quic_packet_generator_test.cc index d72e191c..254098c 100644 --- a/net/quic/core/quic_packet_generator_test.cc +++ b/net/quic/core/quic_packet_generator_test.cc
@@ -22,6 +22,7 @@ #include "net/quic/test_tools/quic_packet_creator_peer.h" #include "net/quic/test_tools/quic_packet_generator_peer.h" #include "net/quic/test_tools/quic_test_utils.h" +#include "net/quic/test_tools/simple_data_producer.h" #include "net/quic/test_tools/simple_quic_framer.h" using std::string; @@ -69,7 +70,23 @@ .WillRepeatedly(Return(true)); } + void SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) override { + producer_.SaveStreamData(id, iov, iov_offset, offset, data_length); + } + bool WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override { + return producer_.WriteStreamData(id, offset, data_length, writer); + } + private: + SimpleDataProducer producer_; + DISALLOW_COPY_AND_ASSIGN(MockDelegate); }; @@ -116,6 +133,8 @@ creator_->SetEncrypter(ENCRYPTION_FORWARD_SECURE, new NullEncrypter(Perspective::IS_CLIENT)); creator_->set_encryption_level(ENCRYPTION_FORWARD_SECURE); + generator_.SetDelegateSavesData( + FLAGS_quic_reloadable_flag_quic_stream_owns_data); } ~QuicPacketGeneratorTest() override { @@ -228,6 +247,7 @@ private: std::unique_ptr<char[]> data_array_; struct iovec iov_; + SimpleDataProducer producer_; }; class MockDebugDelegate : public QuicPacketCreator::DebugDelegate {
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc index 5aa0de73..aaae090 100644 --- a/net/quic/core/quic_session.cc +++ b/net/quic/core/quic_session.cc
@@ -47,13 +47,18 @@ currently_writing_stream_id_(0), respect_goaway_(true), use_stream_notifier_( - FLAGS_quic_reloadable_flag_quic_use_stream_notifier2) {} + FLAGS_quic_reloadable_flag_quic_use_stream_notifier2), + streams_own_data_(use_stream_notifier_ && + FLAGS_quic_reloadable_flag_quic_stream_owns_data) {} void QuicSession::Initialize() { connection_->set_visitor(this); if (use_stream_notifier_) { connection_->SetStreamNotifier(this); } + if (streams_own_data_) { + connection_->SetDelegateSavesData(true); + } connection_->SetFromConfig(config_); DCHECK_EQ(kCryptoStreamId, GetMutableCryptoStream()->id()); @@ -1022,4 +1027,34 @@ stream->OnStreamFrameDiscarded(frame); } +void QuicSession::SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) { + QuicStream* stream = GetStream(id); + if (stream == nullptr) { + QUIC_BUG << "Stream " << id << " does not exist when trying to save data."; + connection()->CloseConnection( + QUIC_INTERNAL_ERROR, "Attempt to save data of a closed stream", + ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); + return; + } + stream->SaveStreamData(iov, iov_offset, offset, data_length); +} + +bool QuicSession::WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) { + QuicStream* stream = GetStream(id); + if (stream == nullptr) { + // This causes the connection to be closed because of failed to serialize + // packet. + QUIC_BUG << "Stream " << id << " does not exist when trying to write data."; + return false; + } + return stream->WriteStreamData(offset, data_length, writer); +} + } // namespace net
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h index bad3a73..9310f9a 100644 --- a/net/quic/core/quic_session.h +++ b/net/quic/core/quic_session.h
@@ -108,6 +108,15 @@ bool HasPendingHandshake() const override; bool HasOpenDynamicStreams() const override; void OnPathDegrading() override; + void SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) override; + bool WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override; // StreamNotifierInterface methods: void OnStreamFrameAcked(const QuicStreamFrame& frame, @@ -269,6 +278,8 @@ bool use_stream_notifier() const { return use_stream_notifier_; } + bool streams_own_data() const { return streams_own_data_; } + protected: using StaticStreamMap = QuicSmallMap<QuicStreamId, QuicStream*, 2>; @@ -516,6 +527,10 @@ // This session is notified on every ack or loss. const bool use_stream_notifier_; + // Streams of this session own their outstanding data. Outstanding data here + // means sent data waiting to be acked. + const bool streams_own_data_; + DISALLOW_COPY_AND_ASSIGN(QuicSession); };
diff --git a/net/quic/core/quic_spdy_stream_test.cc b/net/quic/core/quic_spdy_stream_test.cc index 2ebc374..eb29525 100644 --- a/net/quic/core/quic_spdy_stream_test.cc +++ b/net/quic/core/quic_spdy_stream_test.cc
@@ -973,7 +973,8 @@ } EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .Times(AnyNumber()) - .WillRepeatedly(Invoke(MockQuicSession::ConsumeAllData)); + .WillRepeatedly( + Invoke(session_.get(), &MockQuicSpdySession::ConsumeAndSaveAllData)); testing::InSequence s; QuicReferenceCountedPointer<MockAckListener> ack_listener1( new MockAckListener());
diff --git a/net/quic/core/quic_stream.cc b/net/quic/core/quic_stream.cc index 4e8d7a6..e8583b6 100644 --- a/net/quic/core/quic_stream.cc +++ b/net/quic/core/quic_stream.cc
@@ -77,7 +77,8 @@ stream_contributes_to_connection_flow_control_(true), busy_counter_(0), add_random_padding_after_fin_(false), - ack_listener_(nullptr) { + ack_listener_(nullptr), + send_buffer_(session->connection()->helper()->GetBufferAllocator()) { SetFromConfig(); } @@ -532,6 +533,9 @@ if (frame.fin) { fin_outstanding_ = false; } + if (session_->streams_own_data() && frame.data_length > 0) { + send_buffer_.RemoveStreamFrame(frame.offset, frame.data_length); + } if (!IsWaitingForAcks()) { session_->OnStreamDoneWaitingForAcks(id_); } @@ -541,4 +545,19 @@ return stream_bytes_outstanding_ || fin_outstanding_; } +void QuicStream::SaveStreamData(QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) { + DCHECK_LT(0u, data_length); + send_buffer_.SaveStreamData(iov, iov_offset, offset, data_length); +} + +bool QuicStream::WriteStreamData(QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) { + DCHECK_LT(0u, data_length); + return send_buffer_.WriteStreamData(offset, data_length, writer); +} + } // namespace net
diff --git a/net/quic/core/quic_stream.h b/net/quic/core/quic_stream.h index 6c4d831..a8bff46 100644 --- a/net/quic/core/quic_stream.h +++ b/net/quic/core/quic_stream.h
@@ -27,6 +27,7 @@ #include "net/quic/core/quic_flow_controller.h" #include "net/quic/core/quic_iovector.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/core/quic_stream_send_buffer.h" #include "net/quic/core/quic_stream_sequencer.h" #include "net/quic/core/quic_types.h" #include "net/quic/core/stream_notifier_interface.h" @@ -196,6 +197,17 @@ // Adds random padding after the fin is consumed for this stream. void AddRandomPaddingAfterFin(); + // Save |data_length| of data starts at |iov_offset| in |iov| to send buffer. + void SaveStreamData(QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length); + + // Write |data_length| of data starts at |offset| from send buffer. + bool WriteStreamData(QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer); + // StreamNotifierInterface methods: void OnStreamFrameAcked(const QuicStreamFrame& frame, QuicTime::Delta ack_delay_time) override; @@ -350,6 +362,10 @@ // are acked. QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener_; + // Send buffer of this stream. Send buffer is cleaned up when data gets acked + // or discarded. + QuicStreamSendBuffer send_buffer_; + DISALLOW_COPY_AND_ASSIGN(QuicStream); };
diff --git a/net/quic/core/quic_stream_frame_data_producer.h b/net/quic/core/quic_stream_frame_data_producer.h new file mode 100644 index 0000000..abe8af1f --- /dev/null +++ b/net/quic/core/quic_stream_frame_data_producer.h
@@ -0,0 +1,39 @@ +// Copyright (c) 2017 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. + +#ifndef NET_QUIC_CORE_QUIC_STREAM_FRAME_DATA_PRODUCER_H_ +#define NET_QUIC_CORE_QUIC_STREAM_FRAME_DATA_PRODUCER_H_ + +#include "net/quic/core/quic_iovector.h" +#include "net/quic/core/quic_types.h" + +namespace net { + +class QuicDataWriter; + +// Pure virtual class to save and retrieve stream data. +class QUIC_EXPORT_PRIVATE QuicStreamFrameDataProducer { + public: + virtual ~QuicStreamFrameDataProducer() {} + + // Save |data_length| data starts at |iov_offset| in |iov|. + virtual void SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) = 0; + + // Let |writer| write |data_length| data with |offset| of stream |id|. Returns + // false when the writing fails either because stream is closed or + // corresponding data is failed to be retrieved. This method allows writing a + // single stream frame from data that spans multiple buffers. + virtual bool WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) = 0; +}; + +} // namespace net + +#endif // NET_QUIC_CORE_QUIC_STREAM_FRAME_DATA_PRODUCER_H_
diff --git a/net/quic/core/quic_stream_send_buffer.cc b/net/quic/core/quic_stream_send_buffer.cc new file mode 100644 index 0000000..e38d100 --- /dev/null +++ b/net/quic/core/quic_stream_send_buffer.cc
@@ -0,0 +1,94 @@ +// Copyright (c) 2017 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 <algorithm> + +#include "net/quic/core/crypto/crypto_protocol.h" +#include "net/quic/core/quic_data_writer.h" +#include "net/quic/core/quic_stream_send_buffer.h" +#include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_bug_tracker.h" + +namespace net { + +QuicStreamDataSlice::QuicStreamDataSlice(UniqueStreamBuffer data, + QuicStreamOffset offset, + QuicByteCount data_length) + : data(std::move(data)), + offset(offset), + data_length(data_length), + data_length_waiting_for_acks(data_length) {} + +QuicStreamDataSlice::~QuicStreamDataSlice() {} + +QuicStreamSendBuffer::QuicStreamSendBuffer(QuicBufferAllocator* allocator) + : allocator_(allocator) {} + +QuicStreamSendBuffer::~QuicStreamSendBuffer() {} + +void QuicStreamSendBuffer::SaveStreamData(QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) { + DCHECK_LE(iov_offset + data_length, iov.total_length); + UniqueStreamBuffer buffer = NewStreamBuffer(allocator_, data_length); + QuicUtils::CopyToBuffer(iov, iov_offset, data_length, buffer.get()); + send_buffer_.emplace_back(std::move(buffer), offset, data_length); +} + +bool QuicStreamSendBuffer::WriteStreamData(QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) { + for (const QuicStreamDataSlice& slice : send_buffer_) { + if (offset < slice.offset) { + break; + } + if (offset >= slice.offset + slice.data_length) { + continue; + } + QuicByteCount slice_offset = offset - slice.offset; + QuicByteCount copy_length = + std::min(data_length, slice.data_length - slice_offset); + if (!writer->WriteBytes(slice.data.get() + slice_offset, copy_length)) { + return false; + } + offset += copy_length; + data_length -= copy_length; + } + + return data_length == 0; +} + +void QuicStreamSendBuffer::RemoveStreamFrame(QuicStreamOffset offset, + QuicByteCount data_length) { + DCHECK_LT(0u, data_length); + for (QuicStreamDataSlice& slice : send_buffer_) { + if (offset < slice.offset) { + break; + } + if (offset >= slice.offset + slice.data_length) { + continue; + } + QuicByteCount slice_offset = offset - slice.offset; + QuicByteCount removing_length = + std::min(data_length, slice.data_length - slice_offset); + slice.data_length_waiting_for_acks -= removing_length; + offset += removing_length; + data_length -= removing_length; + } + DCHECK_EQ(0u, data_length); + + // Remove data which stops waiting for acks. Please note, data can be + // acked out of order, but send buffer is cleaned up in order. + while (!send_buffer_.empty() && + send_buffer_.front().data_length_waiting_for_acks == 0) { + send_buffer_.pop_front(); + } +} + +size_t QuicStreamSendBuffer::size() const { + return send_buffer_.size(); +} + +} // namespace net
diff --git a/net/quic/core/quic_stream_send_buffer.h b/net/quic/core/quic_stream_send_buffer.h new file mode 100644 index 0000000..1534521 --- /dev/null +++ b/net/quic/core/quic_stream_send_buffer.h
@@ -0,0 +1,73 @@ +// Copyright (c) 2017 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. + +#ifndef NET_QUIC_CORE_QUIC_STREAM_SEND_BUFFER_H_ +#define NET_QUIC_CORE_QUIC_STREAM_SEND_BUFFER_H_ + +#include <deque> + +#include "net/quic/core/frames/quic_stream_frame.h" +#include "net/quic/core/quic_iovector.h" + +namespace net { + +class QuicDataWriter; + +// QuicStreamDataSlice comprises information of a piece of stream data. +struct QuicStreamDataSlice { + QuicStreamDataSlice(UniqueStreamBuffer data, + QuicStreamOffset offset, + QuicByteCount data_length); + QuicStreamDataSlice(const QuicStreamDataSlice& other) = delete; + QuicStreamDataSlice(QuicStreamDataSlice&& other) = delete; + ~QuicStreamDataSlice(); + + // Stream data of this data slice. + UniqueStreamBuffer data; + // Location of this data slice in the stream. + QuicStreamOffset offset; + // Length of this data slice in bytes. + QuicByteCount data_length; + // Length of payload which is waiting for acks. + QuicByteCount data_length_waiting_for_acks; +}; + +// QuicStreamSendBuffer contains a list of QuicStreamDataSlices. New data slices +// are added to the tail of the list. Data slices are removed from the head of +// the list when they get fully acked. Stream data can be retrieved and acked +// across slice boundaries. +class QUIC_EXPORT_PRIVATE QuicStreamSendBuffer { + public: + explicit QuicStreamSendBuffer(QuicBufferAllocator* allocator); + QuicStreamSendBuffer(const QuicStreamSendBuffer& other) = delete; + QuicStreamSendBuffer(QuicStreamSendBuffer&& other) = delete; + ~QuicStreamSendBuffer(); + + // Save |data_length| of data starts at |iov_offset| in |iov| to send buffer. + void SaveStreamData(QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length); + + // Write |data_length| of data starts at |offset|. + bool WriteStreamData(QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer); + + // Called when data [offset, offset + data_length) is acked or removed as + // stream is canceled. Removes fully acked data slice from send buffer. + void RemoveStreamFrame(QuicStreamOffset offset, QuicByteCount data_length); + + // Number of data slices in send buffer. + size_t size() const; + + private: + std::deque<QuicStreamDataSlice> send_buffer_; + + QuicBufferAllocator* allocator_; +}; + +} // namespace net + +#endif // NET_QUIC_CORE_QUIC_STREAM_SEND_BUFFER_H_
diff --git a/net/quic/core/quic_stream_send_buffer_test.cc b/net/quic/core/quic_stream_send_buffer_test.cc new file mode 100644 index 0000000..d3520a8 --- /dev/null +++ b/net/quic/core/quic_stream_send_buffer_test.cc
@@ -0,0 +1,112 @@ +// Copyright (c) 2017 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 "net/quic/core/quic_stream_send_buffer.h" + +#include "net/quic/core/quic_data_writer.h" +#include "net/quic/core/quic_simple_buffer_allocator.h" +#include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_test.h" +#include "net/quic/test_tools/quic_test_utils.h" + +using std::string; + +namespace net { +namespace test { +namespace { + +struct iovec MakeIovec(QuicStringPiece data) { + struct iovec iov = {const_cast<char*>(data.data()), + static_cast<size_t>(data.size())}; + return iov; +} + +class QuicStreamSendBufferTest : public QuicTest { + public: + QuicStreamSendBufferTest() : send_buffer_(&allocator_) { + EXPECT_EQ(0u, send_buffer_.size()); + string data1(1536, 'a'); + string data2(256, 'b'); + string data3(2048, 'c'); + struct iovec iov[3]; + iov[0] = MakeIovec(QuicStringPiece(data1)); + iov[1] = MakeIovec(QuicStringPiece(data2)); + iov[2] = MakeIovec(QuicStringPiece(data3)); + QuicIOVector quic_iov(iov, 3, 3840); + + // Add all data. + send_buffer_.SaveStreamData(quic_iov, /*iov_offset=*/0, /*offset=*/0, 1024); + send_buffer_.SaveStreamData(quic_iov, /*iov_offset=*/1024, + /*offset=*/1024, 1024); + send_buffer_.SaveStreamData(quic_iov, /*iov_offset=*/2048, + /*offset=*/2048, 1024); + send_buffer_.SaveStreamData(quic_iov, /*iov_offset=*/3072, + /*offset=*/3072, 768); + EXPECT_EQ(4u, send_buffer_.size()); + } + + SimpleBufferAllocator allocator_; + QuicStreamSendBuffer send_buffer_; +}; + +TEST_F(QuicStreamSendBufferTest, CopyDataToBuffer) { + char buf[4000]; + QuicDataWriter writer(4000, buf, Perspective::IS_CLIENT, HOST_BYTE_ORDER); + string copy1(1024, 'a'); + string copy2 = string(512, 'a') + string(256, 'b') + string(256, 'c'); + string copy3(1024, 'c'); + string copy4(768, 'c'); + + ASSERT_TRUE(send_buffer_.WriteStreamData(0, 1024, &writer)); + EXPECT_EQ(copy1, QuicStringPiece(buf, 1024)); + ASSERT_TRUE(send_buffer_.WriteStreamData(1024, 1024, &writer)); + EXPECT_EQ(copy2, QuicStringPiece(buf + 1024, 1024)); + ASSERT_TRUE(send_buffer_.WriteStreamData(2048, 1024, &writer)); + EXPECT_EQ(copy3, QuicStringPiece(buf + 2048, 1024)); + ASSERT_TRUE(send_buffer_.WriteStreamData(2048, 768, &writer)); + EXPECT_EQ(copy4, QuicStringPiece(buf + 3072, 768)); + + // Test data piece across boundries. + QuicDataWriter writer2(4000, buf, Perspective::IS_CLIENT, HOST_BYTE_ORDER); + string copy5 = string(536, 'a') + string(256, 'b') + string(232, 'c'); + ASSERT_TRUE(send_buffer_.WriteStreamData(1000, 1024, &writer2)); + EXPECT_EQ(copy5, QuicStringPiece(buf, 1024)); + ASSERT_TRUE(send_buffer_.WriteStreamData(2500, 1024, &writer2)); + EXPECT_EQ(copy3, QuicStringPiece(buf + 1024, 1024)); + + // Invalid data copy. + QuicDataWriter writer3(4000, buf, Perspective::IS_CLIENT, HOST_BYTE_ORDER); + EXPECT_FALSE(send_buffer_.WriteStreamData(3000, 1024, &writer3)); + EXPECT_FALSE(send_buffer_.WriteStreamData(0, 4000, &writer3)); +} + +TEST_F(QuicStreamSendBufferTest, RemoveStreamFrame) { + send_buffer_.RemoveStreamFrame(1024, 1024); + EXPECT_EQ(4u, send_buffer_.size()); + send_buffer_.RemoveStreamFrame(2048, 1024); + EXPECT_EQ(4u, send_buffer_.size()); + send_buffer_.RemoveStreamFrame(0, 1024); + // Send buffer is cleaned up in order. + EXPECT_EQ(1u, send_buffer_.size()); + send_buffer_.RemoveStreamFrame(3072, 768); + EXPECT_EQ(0u, send_buffer_.size()); +} + +TEST_F(QuicStreamSendBufferTest, RemoveStreamFrameAcrossBoundries) { + send_buffer_.RemoveStreamFrame(2024, 576); + EXPECT_EQ(4u, send_buffer_.size()); + send_buffer_.RemoveStreamFrame(0, 1000); + EXPECT_EQ(4u, send_buffer_.size()); + send_buffer_.RemoveStreamFrame(1000, 1024); + // Send buffer is cleaned up in order. + EXPECT_EQ(2u, send_buffer_.size()); + send_buffer_.RemoveStreamFrame(2600, 1024); + EXPECT_EQ(1u, send_buffer_.size()); + send_buffer_.RemoveStreamFrame(3624, 216); + EXPECT_EQ(0u, send_buffer_.size()); +} + +} // namespace +} // namespace test +} // namespace net
diff --git a/net/quic/core/quic_stream_test.cc b/net/quic/core/quic_stream_test.cc index c08eba40..e9e04a92 100644 --- a/net/quic/core/quic_stream_test.cc +++ b/net/quic/core/quic_stream_test.cc
@@ -717,45 +717,110 @@ TEST_F(QuicStreamTest, StreamWaitsForAcks) { Initialize(kShouldProcessData); EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) - .WillRepeatedly(Invoke(MockQuicSession::ConsumeAllData)); + .WillRepeatedly( + Invoke(session_.get(), &MockQuicSession::ConsumeAndSaveAllData)); // Stream is not waiting for acks initially. EXPECT_FALSE(stream_->IsWaitingForAcks()); + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); // Send kData1. stream_->WriteOrBufferData(kData1, false, nullptr); + if (session_->streams_own_data()) { + EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size()); + } else { + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); + } EXPECT_TRUE(stream_->IsWaitingForAcks()); QuicStreamFrame frame1(stream_->id(), false, 0, kData1); stream_->OnStreamFrameAcked(frame1, QuicTime::Delta::Zero()); // Stream is not waiting for acks as all sent data is acked. EXPECT_FALSE(stream_->IsWaitingForAcks()); + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); // Send kData2. stream_->WriteOrBufferData(kData2, false, nullptr); EXPECT_TRUE(stream_->IsWaitingForAcks()); + if (session_->streams_own_data()) { + EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size()); + } else { + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); + } // Send FIN. stream_->WriteOrBufferData("", true, nullptr); + if (session_->streams_own_data()) { + // Fin only frame is not stored in send buffer. + EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size()); + } else { + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); + } // kData2 is acked. QuicStreamFrame frame2(stream_->id(), false, 9, kData2); stream_->OnStreamFrameAcked(frame2, QuicTime::Delta::Zero()); // Stream is waiting for acks as FIN is not acked. EXPECT_TRUE(stream_->IsWaitingForAcks()); + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); // FIN is acked. QuicStreamFrame frame3(stream_->id(), true, 18, ""); stream_->OnStreamFrameAcked(frame3, QuicTime::Delta::Zero()); EXPECT_FALSE(stream_->IsWaitingForAcks()); + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); +} + +TEST_F(QuicStreamTest, StreamDataGetAckedOutOfOrder) { + Initialize(kShouldProcessData); + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) + .WillRepeatedly( + Invoke(session_.get(), &MockQuicSession::ConsumeAndSaveAllData)); + // Send data. + stream_->WriteOrBufferData(kData1, false, nullptr); + stream_->WriteOrBufferData(kData1, false, nullptr); + stream_->WriteOrBufferData(kData1, false, nullptr); + stream_->WriteOrBufferData("", true, nullptr); + if (session_->streams_own_data()) { + EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size()); + } else { + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); + } + EXPECT_TRUE(stream_->IsWaitingForAcks()); + + QuicStreamFrame frame1(stream_->id(), false, 0, kData1); + QuicStreamFrame frame2(stream_->id(), false, 9, kData1); + QuicStreamFrame frame3(stream_->id(), false, 18, kData1); + QuicStreamFrame frame4(stream_->id(), true, 27, ""); + stream_->OnStreamFrameAcked(frame2, QuicTime::Delta::Zero()); + if (session_->streams_own_data()) { + EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size()); + } + stream_->OnStreamFrameAcked(frame3, QuicTime::Delta::Zero()); + if (session_->streams_own_data()) { + EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size()); + } + stream_->OnStreamFrameDiscarded(frame1); + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); + // FIN is not acked yet. + EXPECT_TRUE(stream_->IsWaitingForAcks()); + stream_->OnStreamFrameAcked(frame4, QuicTime::Delta::Zero()); + EXPECT_FALSE(stream_->IsWaitingForAcks()); } TEST_F(QuicStreamTest, CancelStream) { Initialize(kShouldProcessData); EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) - .WillRepeatedly(Invoke(MockQuicSession::ConsumeAllData)); + .WillRepeatedly( + Invoke(session_.get(), &MockQuicSession::ConsumeAndSaveAllData)); EXPECT_FALSE(stream_->IsWaitingForAcks()); + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); stream_->WriteOrBufferData(kData1, false, nullptr); QuicStreamFrame frame(stream_->id(), 0, false, kData1); EXPECT_TRUE(stream_->IsWaitingForAcks()); + if (session_->streams_own_data()) { + EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size()); + } else { + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); + } // Cancel stream. stream_->Reset(QUIC_STREAM_NO_ERROR); // stream still waits for acks as the error code is QUIC_STREAM_NO_ERROR, and @@ -768,18 +833,26 @@ stream_->OnStreamFrameDiscarded(frame); // Stream stops waiting for acks as data is not going to be retransmitted. EXPECT_FALSE(stream_->IsWaitingForAcks()); + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); } } TEST_F(QuicStreamTest, RstFrameReceivedStreamNotFinishSending) { Initialize(kShouldProcessData); EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) - .WillRepeatedly(Invoke(MockQuicSession::ConsumeAllData)); + .WillRepeatedly( + Invoke(session_.get(), &MockQuicSession::ConsumeAndSaveAllData)); EXPECT_FALSE(stream_->IsWaitingForAcks()); + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); stream_->WriteOrBufferData(kData1, false, nullptr); QuicStreamFrame frame(stream_->id(), 0, false, kData1); EXPECT_TRUE(stream_->IsWaitingForAcks()); + if (session_->streams_own_data()) { + EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size()); + } else { + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); + } // RST_STREAM received. QuicRstStreamFrame rst_frame(stream_->id(), QUIC_STREAM_CANCELLED, 9); @@ -791,14 +864,17 @@ // Stream stops waiting for acks as it does not finish sending and rst is // sent. EXPECT_FALSE(stream_->IsWaitingForAcks()); + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); } } TEST_F(QuicStreamTest, RstFrameReceivedStreamFinishSending) { Initialize(kShouldProcessData); EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) - .WillRepeatedly(Invoke(MockQuicSession::ConsumeAllData)); + .WillRepeatedly( + Invoke(session_.get(), &MockQuicSession::ConsumeAndSaveAllData)); EXPECT_FALSE(stream_->IsWaitingForAcks()); + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); stream_->WriteOrBufferData(kData1, true, nullptr); EXPECT_TRUE(stream_->IsWaitingForAcks()); @@ -809,13 +885,20 @@ stream_->OnStreamReset(rst_frame); // Stream stops waiting for acks as it has unacked data. EXPECT_TRUE(stream_->IsWaitingForAcks()); + if (session_->streams_own_data()) { + EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size()); + } else { + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); + } } TEST_F(QuicStreamTest, ConnectionClosed) { Initialize(kShouldProcessData); EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) - .WillRepeatedly(Invoke(MockQuicSession::ConsumeAllData)); + .WillRepeatedly( + Invoke(session_.get(), &MockQuicSession::ConsumeAndSaveAllData)); EXPECT_FALSE(stream_->IsWaitingForAcks()); + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); stream_->WriteOrBufferData(kData1, false, nullptr); QuicStreamFrame frame(stream_->id(), 0, false, kData1); @@ -829,6 +912,7 @@ stream_->OnStreamFrameDiscarded(frame); // Stream stops waiting for acks as connection is going to close. EXPECT_FALSE(stream_->IsWaitingForAcks()); + EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); } }
diff --git a/net/quic/test_tools/quic_stream_peer.cc b/net/quic/test_tools/quic_stream_peer.cc index 4dfbea7e..213be66 100644 --- a/net/quic/test_tools/quic_stream_peer.cc +++ b/net/quic/test_tools/quic_stream_peer.cc
@@ -81,5 +81,10 @@ return stream->session(); } +// static +QuicStreamSendBuffer& QuicStreamPeer::SendBuffer(QuicStream* stream) { + return stream->send_buffer_; +} + } // namespace test } // namespace net
diff --git a/net/quic/test_tools/quic_stream_peer.h b/net/quic/test_tools/quic_stream_peer.h index b7c3356..3f1ce44 100644 --- a/net/quic/test_tools/quic_stream_peer.h +++ b/net/quic/test_tools/quic_stream_peer.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/core/quic_stream_send_buffer.h" #include "net/quic/core/quic_stream_sequencer.h" #include "net/quic/platform/api/quic_string_piece.h" @@ -43,6 +44,8 @@ static QuicStreamSequencer* sequencer(QuicStream* stream); static QuicSession* session(QuicStream* stream); + static QuicStreamSendBuffer& SendBuffer(QuicStream* stream); + private: DISALLOW_COPY_AND_ASSIGN(QuicStreamPeer); };
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc index 51136c56..8edd8c7 100644 --- a/net/quic/test_tools/quic_test_utils.cc +++ b/net/quic/test_tools/quic_test_utils.cc
@@ -72,7 +72,8 @@ const QuicFrames& frames, size_t packet_size) { char* buffer = new char[packet_size]; - size_t length = framer->BuildDataPacket(header, frames, buffer, packet_size); + size_t length = + framer->BuildDataPacket(header, frames, buffer, packet_size, nullptr); DCHECK_NE(0u, length); // Re-construct the data packet with data ownership. return new QuicPacket(buffer, length, /* owns_buffer */ true, @@ -211,6 +212,20 @@ MockQuicConnectionVisitor::~MockQuicConnectionVisitor() {} +void MockQuicConnectionVisitor::SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) { + producer_.SaveStreamData(id, iov, iov_offset, offset, data_length); +} +bool MockQuicConnectionVisitor::WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) { + return producer_.WriteStreamData(id, offset, data_length, writer); +} + MockQuicConnectionHelper::MockQuicConnectionHelper() {} MockQuicConnectionHelper::~MockQuicConnectionHelper() {} @@ -379,6 +394,21 @@ return QuicConsumedData(data.total_length, state != NO_FIN); } +QuicConsumedData MockQuicSession::ConsumeAndSaveAllData( + QuicStream* stream, + QuicStreamId id, + const QuicIOVector& data, + QuicStreamOffset offset, + StreamSendingState state, + const QuicReferenceCountedPointer<QuicAckListenerInterface>& ack_listener) { + QuicConsumedData consumed = + QuicConsumedData(data.total_length, state != NO_FIN); + if (streams_own_data() && data.total_length > 0) { + SaveStreamData(id, data, 0, offset, data.total_length); + } + return consumed; +} + MockQuicCryptoStream::MockQuicCryptoStream(QuicSession* session) : QuicCryptoStream(session), params_(new QuicCryptoNegotiatedParameters) {} @@ -427,6 +457,21 @@ return WriteHeadersMock(id, write_headers_, fin, priority, ack_listener); } +QuicConsumedData MockQuicSpdySession::ConsumeAndSaveAllData( + QuicStream* stream, + QuicStreamId id, + const QuicIOVector& data, + QuicStreamOffset offset, + StreamSendingState state, + const QuicReferenceCountedPointer<QuicAckListenerInterface>& ack_listener) { + QuicConsumedData consumed = + QuicConsumedData(data.total_length, state != NO_FIN); + if (streams_own_data() && data.total_length > 0) { + SaveStreamData(id, data, 0, offset, data.total_length); + } + return consumed; +} + TestQuicSpdyServerSession::TestQuicSpdyServerSession( QuicConnection* connection, const QuicConfig& config, @@ -811,6 +856,24 @@ MockConnectionCloseDelegate::~MockConnectionCloseDelegate() {} +MockPacketCreatorDelegate::MockPacketCreatorDelegate() {} +MockPacketCreatorDelegate::~MockPacketCreatorDelegate() {} + +void MockPacketCreatorDelegate::SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) { + producer_.SaveStreamData(id, iov, iov_offset, offset, data_length); +} + +bool MockPacketCreatorDelegate::WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) { + return producer_.WriteStreamData(id, offset, data_length, writer); +} + void CreateClientSessionForTest(QuicServerId server_id, bool supports_stateless_rejects, QuicTime::Delta connection_start_time,
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h index 1781752..d74a8dc 100644 --- a/net/quic/test_tools/quic_test_utils.h +++ b/net/quic/test_tools/quic_test_utils.h
@@ -28,6 +28,7 @@ #include "net/quic/platform/api/quic_string_piece.h" #include "net/quic/test_tools/mock_clock.h" #include "net/quic/test_tools/mock_random.h" +#include "net/quic/test_tools/simple_data_producer.h" #include "net/test/gtest_util.h" #include "net/tools/quic/quic_per_connection_packet_writer.h" #include "net/tools/quic/test_tools/mock_quic_session_visitor.h" @@ -295,8 +296,19 @@ MOCK_METHOD0(OnConfigNegotiated, void()); MOCK_METHOD0(PostProcessAfterData, void()); MOCK_METHOD0(OnAckNeedsRetransmittableFrame, void()); + void SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) override; + bool WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override; private: + SimpleDataProducer producer_; + DISALLOW_COPY_AND_ASSIGN(MockQuicConnectionVisitor); }; @@ -511,6 +523,15 @@ const QuicReferenceCountedPointer<QuicAckListenerInterface>& ack_listener); + QuicConsumedData ConsumeAndSaveAllData( + QuicStream* stream, + QuicStreamId id, + const QuicIOVector& data, + QuicStreamOffset offset, + StreamSendingState state, + const QuicReferenceCountedPointer<QuicAckListenerInterface>& + ack_listener); + private: std::unique_ptr<QuicCryptoStream> crypto_stream_; @@ -630,6 +651,15 @@ return QuicSpdySession::ShouldCreateOutgoingDynamicStream2(); } + QuicConsumedData ConsumeAndSaveAllData( + QuicStream* stream, + QuicStreamId id, + const QuicIOVector& data, + QuicStreamOffset offset, + StreamSendingState state, + const QuicReferenceCountedPointer<QuicAckListenerInterface>& + ack_listener); + using QuicSession::ActivateStream; private: @@ -917,6 +947,33 @@ ConnectionCloseSource source)); }; +class MockPacketCreatorDelegate : public QuicPacketCreator::DelegateInterface { + public: + MockPacketCreatorDelegate(); + ~MockPacketCreatorDelegate() override; + + MOCK_METHOD1(OnSerializedPacket, void(SerializedPacket* packet)); + MOCK_METHOD3(OnUnrecoverableError, + void(QuicErrorCode, + const std::string&, + ConnectionCloseSource source)); + + void SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) override; + bool WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override; + + private: + SimpleDataProducer producer_; + + DISALLOW_COPY_AND_ASSIGN(MockPacketCreatorDelegate); +}; + // Creates a client session for testing. // // server_id: The server id associated with this stream.
diff --git a/net/quic/test_tools/simple_data_producer.cc b/net/quic/test_tools/simple_data_producer.cc new file mode 100644 index 0000000..65eb3e61 --- /dev/null +++ b/net/quic/test_tools/simple_data_producer.cc
@@ -0,0 +1,36 @@ +// Copyright (c) 2017 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 "net/quic/test_tools/simple_data_producer.h" + +#include "net/quic/platform/api/quic_map_util.h" + +namespace net { + +namespace test { + +SimpleDataProducer::SimpleDataProducer() {} +SimpleDataProducer::~SimpleDataProducer() {} + +void SimpleDataProducer::SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) { + if (!QuicContainsKey(send_buffer_map_, id)) { + send_buffer_map_[id].reset(new QuicStreamSendBuffer(&allocator_)); + } + send_buffer_map_[id]->SaveStreamData(iov, iov_offset, offset, data_length); +} + +bool SimpleDataProducer::WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) { + return send_buffer_map_[id]->WriteStreamData(offset, data_length, writer); +} + +} // namespace test + +} // namespace net
diff --git a/net/quic/test_tools/simple_data_producer.h b/net/quic/test_tools/simple_data_producer.h new file mode 100644 index 0000000..73d7eb0 --- /dev/null +++ b/net/quic/test_tools/simple_data_producer.h
@@ -0,0 +1,49 @@ +// Copyright (c) 2017 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. + +#ifndef NET_QUIC_TEST_TOOLS_SIMPLE_DATA_PRODUCER_H_ +#define NET_QUIC_TEST_TOOLS_SIMPLE_DATA_PRODUCER_H_ + +#include <unordered_map> + +#include "net/quic/core/quic_simple_buffer_allocator.h" +#include "net/quic/core/quic_stream_frame_data_producer.h" +#include "net/quic/core/quic_stream_send_buffer.h" + +namespace net { + +namespace test { + +// A simple data producer which copies stream data into a map from stream +// id to send buffer. +class SimpleDataProducer : public QuicStreamFrameDataProducer { + public: + SimpleDataProducer(); + ~SimpleDataProducer() override; + + // QuicStreamFrameDataProducer methods: + void SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) override; + bool WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override; + + private: + using SendBufferMap = + std::unordered_map<QuicStreamId, std::unique_ptr<QuicStreamSendBuffer>>; + + SimpleBufferAllocator allocator_; + + SendBufferMap send_buffer_map_; +}; + +} // namespace test + +} // namespace net + +#endif // NET_QUIC_TEST_TOOLS_SIMPLE_DATA_PRODUCER_H_
diff --git a/net/quic/test_tools/simulator/quic_endpoint.cc b/net/quic/test_tools/simulator/quic_endpoint.cc index 6e810d43..f936be8 100644 --- a/net/quic/test_tools/simulator/quic_endpoint.cc +++ b/net/quic/test_tools/simulator/quic_endpoint.cc
@@ -244,6 +244,21 @@ } } +void QuicEndpoint::SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) { + producer_.SaveStreamData(id, iov, iov_offset, offset, data_length); +} + +bool QuicEndpoint::WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) { + return producer_.WriteStreamData(id, offset, data_length, writer); +} + QuicEndpointMultiplexer::QuicEndpointMultiplexer( string name, std::initializer_list<QuicEndpoint*> endpoints)
diff --git a/net/quic/test_tools/simulator/quic_endpoint.h b/net/quic/test_tools/simulator/quic_endpoint.h index 3199994..8d76b55 100644 --- a/net/quic/test_tools/simulator/quic_endpoint.h +++ b/net/quic/test_tools/simulator/quic_endpoint.h
@@ -9,6 +9,7 @@ #include "net/quic/core/crypto/null_encrypter.h" #include "net/quic/core/quic_connection.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/test_tools/simple_data_producer.h" #include "net/quic/test_tools/simulator/link.h" #include "net/quic/test_tools/simulator/queue.h" #include "net/tools/quic/quic_default_packet_writer.h" @@ -90,6 +91,15 @@ void OnPathDegrading() override {} void PostProcessAfterData() override {} void OnAckNeedsRetransmittableFrame() override {} + void SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) override; + bool WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override; // End QuicConnectionVisitorInterface implementation. private: @@ -140,6 +150,8 @@ bool wrong_data_received_; std::unique_ptr<char[]> transmission_buffer_; + + test::SimpleDataProducer producer_; }; // Multiplexes multiple connections at the same host on the network.
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc index a5cb9a7..cc17c80 100644 --- a/net/tools/quic/quic_dispatcher.cc +++ b/net/tools/quic/quic_dispatcher.cc
@@ -52,6 +52,8 @@ // to be handed off to the time wait list manager. class PacketCollector : public QuicPacketCreator::DelegateInterface { public: + explicit PacketCollector(QuicBufferAllocator* allocator) + : send_buffer_(allocator) {} ~PacketCollector() override {} void OnSerializedPacket(SerializedPacket* serialized_packet) override { @@ -68,12 +70,32 @@ const string& error_details, ConnectionCloseSource source) override {} + void SaveStreamData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + QuicByteCount data_length) override { + DCHECK_EQ(kCryptoStreamId, id); + send_buffer_.SaveStreamData(iov, iov_offset, offset, data_length); + } + + bool WriteStreamData(QuicStreamId id, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override { + DCHECK_EQ(kCryptoStreamId, id); + return send_buffer_.WriteStreamData(offset, data_length, writer); + } + std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() { return &packets_; } private: std::vector<std::unique_ptr<QuicEncryptedPacket>> packets_; + // This is only needed until the packets are encrypted. Once packets are + // encrypted, the stream data is no longer required. + QuicStreamSendBuffer send_buffer_; }; // Helper for statelessly closing connections by generating the @@ -87,6 +109,7 @@ QuicTimeWaitListManager* time_wait_list_manager) : connection_id_(connection_id), framer_(framer), + collector_(helper->GetBufferAllocator()), creator_(connection_id, framer, helper->GetBufferAllocator(),
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index e6beca6..87107b1 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -16773,25 +16773,6 @@ }, { "args": [ - "--test-launcher-batch-limit=400", - "--deqp-egl-display-type=angle-d3d11" - ], - "name": "angle_deqp_gles3_d3d11_tests", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "1002:6613", - "os": "Windows-2008ServerR2-SP1" - } - ], - "shards": 12 - }, - "test": "angle_deqp_gles3_tests", - "use_xvfb": false - }, - { - "args": [ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ], @@ -17391,25 +17372,6 @@ }, { "args": [ - "--test-launcher-batch-limit=400", - "--deqp-egl-display-type=angle-d3d11" - ], - "name": "angle_deqp_gles3_d3d11_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6613", - "os": "Windows-2008ServerR2-SP1" - } - ], - "shards": 12 - }, - "test": "angle_deqp_gles3_tests", - "use_xvfb": false - }, - { - "args": [ "--use-gpu-in-tests", "--test-launcher-retry-limit=0" ],
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIContent.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIContent.cpp index 15d9d08e..c7ad5a8e 100644 --- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIContent.cpp +++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIContent.cpp
@@ -15,8 +15,6 @@ class CSSParserLocalContext; namespace blink { -using CSSCounterValue = cssvalue::CSSCounterValue; - namespace { CSSValue* ConsumeAttr(CSSParserTokenRange args, @@ -67,7 +65,7 @@ if (!args.AtEnd()) return nullptr; - return blink::CSSCounterValue::Create(identifier, list_style, separator); + return cssvalue::CSSCounterValue::Create(identifier, list_style, separator); } } // namespace
diff --git a/third_party/proguard/BUILD.gn b/third_party/proguard/BUILD.gn new file mode 100644 index 0000000..e43a60d9 --- /dev/null +++ b/third_party/proguard/BUILD.gn
@@ -0,0 +1,22 @@ +# Copyright 2017 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. + +import("//build/config/android/rules.gni") + +java_prebuilt("proguard_java") { + jar_path = "lib/proguard.jar" + data = [ + "$root_build_dir/lib.java/third_party/proguard/proguard.jar", + ] +} + +java_prebuilt("retrace_java") { + jar_path = "lib/retrace.jar" + deps = [ + ":proguard_java", + ] + data = [ + "$root_build_dir/lib.java/third_party/proguard/retrace.jar", + ] +}
diff --git a/third_party/proguard/OWNERS b/third_party/proguard/OWNERS index 4f349f6a..3a28457 100644 --- a/third_party/proguard/OWNERS +++ b/third_party/proguard/OWNERS
@@ -1,2 +1,3 @@ +agrieve@chromium.org torne@chromium.org yfriedman@chromium.org
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py index 3d95293a..61acdd8 100644 --- a/tools/perf/benchmarks/system_health_smoke_test.py +++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -36,8 +36,6 @@ 'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_mobile.browse:news:cnn', # pylint: disable=line-too-long # cburg.com/721549 'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_mobile.browse:news:toi', # pylint: disable=line-too-long - # crbug.com/702455 - 'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.browse:media:youtube', # pylint: disable=line-too-long # crbug.com/637230 'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.browse:news:cnn', # pylint: disable=line-too-long # Permenently disabled from smoke test for being long-running.
diff --git a/ui/aura/env_input_state_controller.cc b/ui/aura/env_input_state_controller.cc index 7e3b291..6807055 100644 --- a/ui/aura/env_input_state_controller.cc +++ b/ui/aura/env_input_state_controller.cc
@@ -26,8 +26,11 @@ break; } + // If a synthesized event is created from a native event (e.g. EnterNotify + // XEvents), then we should take the location as we would for a + // non-synthesized event. if (event.type() != ui::ET_MOUSE_CAPTURE_CHANGED && - !(event.flags() & ui::EF_IS_SYNTHESIZED)) { + (!(event.flags() & ui::EF_IS_SYNTHESIZED) || event.HasNativeEvent())) { SetLastMouseLocation(window, event.root_location()); } }
diff --git a/ui/aura/window_tree_host_x11.cc b/ui/aura/window_tree_host_x11.cc index 0635b7a..d57358c 100644 --- a/ui/aura/window_tree_host_x11.cc +++ b/ui/aura/window_tree_host_x11.cc
@@ -252,9 +252,6 @@ root_window); cursor_client->SetDisplay(display); } - // EnterNotify creates ET_MOUSE_MOVE. Mark as synthesized as this is - // not a real mouse move event. - mouse_event.set_flags(mouse_event.flags() | ui::EF_IS_SYNTHESIZED); } TranslateAndDispatchLocatedEvent(&mouse_event);
diff --git a/ui/events/platform/x11/x11_event_source_libevent.cc b/ui/events/platform/x11/x11_event_source_libevent.cc index 7edd46c8..85bdb73 100644 --- a/ui/events/platform/x11/x11_event_source_libevent.cc +++ b/ui/events/platform/x11/x11_event_source_libevent.cc
@@ -87,10 +87,6 @@ switch (xev.type) { case LeaveNotify: case EnterNotify: - // EnterNotify creates ET_MOUSE_MOVED. Mark as synthesized as this is - // not real mouse move event. - if (xev.type == EnterNotify) - flags |= EF_IS_SYNTHESIZED; return base::MakeUnique<MouseEvent>(ET_MOUSE_MOVED, EventLocationFromXEvent(xev), EventSystemLocationFromXEvent(xev),
diff --git a/ui/events/x/events_x_unittest.cc b/ui/events/x/events_x_unittest.cc index cf62b2b..a7082e6 100644 --- a/ui/events/x/events_x_unittest.cc +++ b/ui/events/x/events_x_unittest.cc
@@ -189,6 +189,7 @@ // the way views handle mouse enter. See comments for EnterNotify case in // ui::EventTypeFromNative for more details. EXPECT_EQ(ui::ET_MOUSE_MOVED, ui::EventTypeFromNative(&event)); + EXPECT_TRUE(ui::EventFlagsFromNative(&event) & ui::EF_IS_SYNTHESIZED); EXPECT_EQ( "10,20", gfx::ToFlooredPoint(ui::EventLocationFromNative(&event)).ToString());
diff --git a/ui/events/x/events_x_utils.cc b/ui/events/x/events_x_utils.cc index fa37616..af656b4 100644 --- a/ui/events/x/events_x_utils.cc +++ b/ui/events/x/events_x_utils.cc
@@ -474,6 +474,9 @@ return flags; } case EnterNotify: + // EnterNotify creates ET_MOUSE_MOVED. Mark as synthesized as this is not + // a real mouse move event. + return GetEventFlagsFromXState(xev.xcrossing.state) | EF_IS_SYNTHESIZED; case LeaveNotify: return GetEventFlagsFromXState(xev.xcrossing.state); case MotionNotify:
diff --git a/ui/gl/test/gl_image_test_template.h b/ui/gl/test/gl_image_test_template.h index fdd9983..d4a250f 100644 --- a/ui/gl/test/gl_image_test_template.h +++ b/ui/gl/test/gl_image_test_template.h
@@ -186,7 +186,9 @@ TYPED_TEST_CASE_P(GLImageTest); TYPED_TEST_P(GLImageTest, Create) { - const gfx::Size small_image_size(4, 4); + // NOTE: On some drm devices (mediatek) the mininum width/height to add an fb + // for a bo must be 64. + const gfx::Size small_image_size(64, 64); const gfx::Size large_image_size(512, 512); const uint8_t* image_color = this->delegate_.GetImageColor();
diff --git a/ui/message_center/notification.cc b/ui/message_center/notification.cc index 2b7a312..4f49cf7 100644 --- a/ui/message_center/notification.cc +++ b/ui/message_center/notification.cc
@@ -32,19 +32,7 @@ ButtonInfo& ButtonInfo::operator=(const ButtonInfo& other) = default; -RichNotificationData::RichNotificationData() - : priority(DEFAULT_PRIORITY), - never_timeout(false), - timestamp(base::Time::Now()), - context_message(base::string16()), - progress(0), - should_make_spoken_feedback_for_popup_updates(true), - clickable(true), -#if defined(OS_CHROMEOS) - pinned(false), -#endif // defined(OS_CHROMEOS) - renotify(false), - silent(false) {} +RichNotificationData::RichNotificationData() : timestamp(base::Time::Now()) {} RichNotificationData::RichNotificationData(const RichNotificationData& other) : priority(other.priority), @@ -67,9 +55,9 @@ silent(other.silent), accessible_name(other.accessible_name) {} -RichNotificationData::~RichNotificationData() {} +RichNotificationData::~RichNotificationData() = default; -Notification::Notification() {} +Notification::Notification() = default; Notification::Notification(NotificationType type, const std::string& id, @@ -143,7 +131,7 @@ return *this; } -Notification::~Notification() {} +Notification::~Notification() = default; bool Notification::IsRead() const { return is_read_ || optional_fields_.priority == MIN_PRIORITY;
diff --git a/ui/message_center/notification.h b/ui/message_center/notification.h index 6aff50c..3e9a1a8 100644 --- a/ui/message_center/notification.h +++ b/ui/message_center/notification.h
@@ -32,52 +32,114 @@ } #endif +// Represents an individual item in NOTIFICATION_TYPE_MULTIPLE notifications. struct MESSAGE_CENTER_EXPORT NotificationItem { + NotificationItem(const base::string16& title, const base::string16& message); + base::string16 title; base::string16 message; - - NotificationItem(const base::string16& title, const base::string16& message); }; -enum class ButtonType { BUTTON, TEXT }; +enum class ButtonType { + // A simple button having an icon and a title that the user can click on. + BUTTON, + // A button having an icon and a title that should also enable the user to + // input text, enabling them to quickly respond from the notification. + TEXT +}; + +// Represents a button to be shown as part of a notification. struct MESSAGE_CENTER_EXPORT ButtonInfo { - base::string16 title; - gfx::Image icon; - ButtonType type = ButtonType::BUTTON; - base::string16 placeholder; - explicit ButtonInfo(const base::string16& title); ButtonInfo(const ButtonInfo& other); ~ButtonInfo(); ButtonInfo& operator=(const ButtonInfo& other); + + // Title that should be displayed on the notification button. + base::string16 title; + + // Icon that should be displayed on the notification button. Optional. On some + // platforms, a mask will be applied to the icon, to match the visual + // requirements of the notification. + gfx::Image icon; + + // Type of this button. + ButtonType type = ButtonType::BUTTON; + + // The placeholder string that should be displayed in the input field for TEXT + // type buttons until the user has entered a response themselves. + base::string16 placeholder; }; +// Represents rich features available for notifications. class MESSAGE_CENTER_EXPORT RichNotificationData { public: RichNotificationData(); RichNotificationData(const RichNotificationData& other); ~RichNotificationData(); - int priority; - bool never_timeout; + // Priority of the notification. This must be one of the NotificationPriority + // values defined in notification_types.h. + int priority = DEFAULT_PRIORITY; + + // Whether the notification should remain on screen indefinitely. + bool never_timeout = false; + + // Time indicating when the notification was shown. Defaults to the time at + // which the RichNotificationData instance is constructed. base::Time timestamp; + + // Context message to display below the notification's content. Optional. May + // not be used for notifications that have an explicit origin URL set. base::string16 context_message; + + // Large image to display on the notification. Optional. gfx::Image image; + + // Small badge to display on the notification to illustrate the source of the + // notification. Optional. gfx::Image small_image; + + // Items to display on the notification. Only applicable for notifications + // that have type NOTIFICATION_TYPE_MULTIPLE. std::vector<NotificationItem> items; - int progress; + + // Progress, in range of [0-100], of NOTIFICATION_TYPE_PROGRESS notifications. + int progress = 0; + + // Buttons that should show up on the notification. A maximum of 16 buttons + // is supported by the current implementation, but this may differ between + // platforms. std::vector<ButtonInfo> buttons; - bool should_make_spoken_feedback_for_popup_updates; - bool clickable; + + // Whether updates to the visible notification should be announced to users + // depending on visual assistance systems. + bool should_make_spoken_feedback_for_popup_updates = true; + + // Whether it should be possible for the user to click on the notification. + bool clickable = true; + #if defined(OS_CHROMEOS) // Flag if the notification is pinned. If true, the notification is pinned - // and user can't remove it. - bool pinned; + // and the user can't remove it. + bool pinned = false; #endif // defined(OS_CHROMEOS) + + // Vibration pattern to play when displaying the notification. There must be + // an odd number of entries in this pattern when it's set: numbers of + // milliseconds to vibrate separated by numbers of milliseconds to pause. std::vector<int> vibration_pattern; - bool renotify; - bool silent; + + // Whether the vibration pattern and other applicable announcement mechanisms + // should be considered when updating the notification. + bool renotify = false; + + // Whether all announcement mechansims should be suppressed when displaying + // the notification. + bool silent = false; + + // An accessible description of the notification's contents. base::string16 accessible_name; }; @@ -86,6 +148,24 @@ // Default constructor needed for generated mojom files Notification(); + // Creates a new notification. + // + // |type|: Type of the notification that dictates the layout. + // |id|: Identifier of the notification. Showing a notification that shares + // its profile and identifier with an already visible notification will + // replace the former one + // |title|: Title of the notification. + // |message|: Body text of the notification. May not be used for certain + // values of |type|, for example list-style notifications. + // |icon|: Icon to show alongside of the notification. + // |display_source|: Textual representation of who's shown the notification. + // |origin_url|: URL of the website responsible for showing the notification. + // |notifier_id|: NotifierId instance representing the system responsible for + // showing the notification. + // |optional_fields|: Rich data that can be used to assign more elaborate + // features to notifications. + // |delegate|: Delegate that will influence the behaviour of this notification + // and receives events on its behalf. Notification(NotificationType type, const std::string& id, const base::string16& title, @@ -97,8 +177,13 @@ const RichNotificationData& optional_fields, NotificationDelegate* delegate); + // Creates a copy of the |other| notification. The delegate, if any, will be + // identical for both the Notification instances. The |id| of the notification + // will be replaced by the given value. Notification(const std::string& id, const Notification& other); + // Creates a copy of the |other| notification. The delegate, if any, will be + // identical for both the Notification instances. Notification(const Notification& other); Notification& operator=(const Notification& other);
diff --git a/ui/message_center/views/notification_control_buttons_view.cc b/ui/message_center/views/notification_control_buttons_view.cc index 2db5a2d..322734a 100644 --- a/ui/message_center/views/notification_control_buttons_view.cc +++ b/ui/message_center/views/notification_control_buttons_view.cc
@@ -46,7 +46,8 @@ void NotificationControlButtonsView::ShowCloseButton(bool show) { if (show && !close_button_) { - close_button_ = new message_center::PaddedButton(this); + close_button_ = base::MakeUnique<message_center::PaddedButton>(this); + close_button_->set_owned_by_client(); close_button_->SetImage(views::CustomButton::STATE_NORMAL, message_center::GetCloseIcon()); close_button_->SetAccessibleName(l10n_util::GetStringUTF16( @@ -58,16 +59,17 @@ // Add the button at the last. DCHECK_LE(child_count(), 1); - AddChildView(close_button_); + AddChildView(close_button_.get()); } else if (!show && close_button_) { - RemoveChildView(close_button_); - close_button_ = nullptr; + DCHECK(Contains(close_button_.get())); + close_button_.reset(); } } void NotificationControlButtonsView::ShowSettingsButton(bool show) { if (show && !settings_button_) { - settings_button_ = new message_center::PaddedButton(this); + settings_button_ = base::MakeUnique<message_center::PaddedButton>(this); + settings_button_->set_owned_by_client(); settings_button_->SetImage(views::CustomButton::STATE_NORMAL, message_center::GetSettingsIcon()); settings_button_->SetAccessibleName(l10n_util::GetStringUTF16( @@ -79,10 +81,10 @@ // Add the button at the first. DCHECK_LE(child_count(), 1); - AddChildViewAt(settings_button_, 0); + AddChildViewAt(settings_button_.get(), 0); } else if (!show && settings_button_) { - RemoveChildView(settings_button_); - settings_button_ = nullptr; + DCHECK(Contains(settings_button_.get())); + settings_button_.reset(); } } @@ -113,15 +115,25 @@ return settings_button_ && settings_button_->HasFocus(); } +message_center::PaddedButton* +NotificationControlButtonsView::close_button_for_testing() const { + return close_button_.get(); +} + +message_center::PaddedButton* +NotificationControlButtonsView::settings_button_for_testing() const { + return settings_button_.get(); +} + const char* NotificationControlButtonsView::GetClassName() const { return kViewClassName; } void NotificationControlButtonsView::ButtonPressed(views::Button* sender, const ui::Event& event) { - if (close_button_ && sender == close_button_) { + if (close_button_ && sender == close_button_.get()) { message_view_->OnCloseButtonPressed(); - } else if (settings_button_ && sender == settings_button_) { + } else if (settings_button_ && sender == settings_button_.get()) { message_view_->OnSettingsButtonPressed(); } }
diff --git a/ui/message_center/views/notification_control_buttons_view.h b/ui/message_center/views/notification_control_buttons_view.h index ee9faab..2dcf1d20 100644 --- a/ui/message_center/views/notification_control_buttons_view.h +++ b/ui/message_center/views/notification_control_buttons_view.h
@@ -51,12 +51,9 @@ // close button, false otherwise. bool IsSettingsButtonFocused() const; - message_center::PaddedButton* close_button_for_testing() const { - return close_button_; - } - message_center::PaddedButton* settings_button_for_testing() const { - return settings_button_; - } + // Methods for testing. + message_center::PaddedButton* close_button_for_testing() const; + message_center::PaddedButton* settings_button_for_testing() const; // views::View const char* GetClassName() const override; @@ -72,8 +69,8 @@ private: MessageView* message_view_; - message_center::PaddedButton* close_button_ = nullptr; - message_center::PaddedButton* settings_button_ = nullptr; + std::unique_ptr<message_center::PaddedButton> close_button_; + std::unique_ptr<message_center::PaddedButton> settings_button_; std::unique_ptr<gfx::LinearAnimation> bgcolor_animation_; SkColor bgcolor_origin_;
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/ui/ozone/platform/drm/gpu/gbm_buffer.cc index 7081e84..dd9bfe7 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer.cc +++ b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -66,14 +66,18 @@ // DRM_MODE_FB_MODIFIERS set. We only set that when we've created // a bo with modifiers, otherwise, we rely on the "no modifiers" // behavior doing the right thing. - drm_->AddFramebuffer2(gbm_bo_get_width(bo), gbm_bo_get_height(bo), - framebuffer_pixel_format_, handles, strides, offsets, - modifiers, &framebuffer_, addfb_flags); + bool ret = drm_->AddFramebuffer2( + gbm_bo_get_width(bo), gbm_bo_get_height(bo), framebuffer_pixel_format_, + handles, strides, offsets, modifiers, &framebuffer_, addfb_flags); + PLOG_IF(ERROR, !ret) << "AddFramebuffer2 failed"; + DCHECK(ret); if (opaque_framebuffer_pixel_format_ != framebuffer_pixel_format_) { - drm_->AddFramebuffer2(gbm_bo_get_width(bo), gbm_bo_get_height(bo), - opaque_framebuffer_pixel_format_, handles, strides, - offsets, modifiers, &opaque_framebuffer_, - addfb_flags); + ret = drm_->AddFramebuffer2(gbm_bo_get_width(bo), gbm_bo_get_height(bo), + opaque_framebuffer_pixel_format_, handles, + strides, offsets, modifiers, + &opaque_framebuffer_, addfb_flags); + PLOG_IF(ERROR, !ret) << "AddFramebuffer2 failed"; + DCHECK(ret); } } }
diff --git a/ui/platform_window/x11/x11_window.cc b/ui/platform_window/x11/x11_window.cc index 64bd7a8..9630d3f7 100644 --- a/ui/platform_window/x11/x11_window.cc +++ b/ui/platform_window/x11/x11_window.cc
@@ -87,11 +87,8 @@ XEvent* xev = event; switch (xev->type) { case EnterNotify: { - // EnterNotify creates ET_MOUSE_MOVED. Mark as synthesized as this is - // not real mouse move event. MouseEvent mouse_event(xev); CHECK_EQ(ET_MOUSE_MOVED, mouse_event.type()); - mouse_event.set_flags(mouse_event.flags() | EF_IS_SYNTHESIZED); delegate()->DispatchEvent(&mouse_event); break; }