diff --git a/DEPS b/DEPS index b9d3372..a88bb82 100644 --- a/DEPS +++ b/DEPS
@@ -129,11 +129,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': '5155e09d146665be078494247092fa990d5ae4a7', + 'skia_revision': '5b39dc81534a2c30d5788de9b8a6501b23e96fdf', # 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': 'fd3e5e3a30df06b3f5ef428dab42c3d625ef2c0b', + 'v8_revision': '35b9bf5cf697b1c0fe4313c1313782d626d2afaa', # 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. @@ -141,7 +141,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '3b2c6bfd43536cf9ceca5d1303aa9435e67a432b', + 'angle_revision': 'e3c7134c2717443e925adf37ed6de21eb0187cf2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -264,7 +264,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'shaderc_revision': '59a49bc5cdff252c6e56e2176255398ace226a90', + 'shaderc_revision': '60caf55788c69dbaebe78c03031d8d1d605988cd', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -805,7 +805,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'e72d09e780cedba24bdb63637f9be30a0ba6af7e', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '5a01970efa3a0c5726a303d9cd901ae0d6a144b2', 'condition': 'checkout_linux', }, @@ -1183,7 +1183,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '084712c40e18337cd48e6f5866baf43121e1e2c6', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '3d46e0d12b172526482d343a6d1a25a9a061af35', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1354,7 +1354,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '3f6583d3fee4ab71866ade794504a20eb6f63f88', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '011d3a125e15e38111b2e21e5b089578c8514466', + Var('webrtc_git') + '/src.git' + '@' + 'e0ab81c8c6e570081c2e1fda2e2c0b84f92c7d77', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1395,7 +1395,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@db8bc8a9d46ca921d84554b29a952e8305e08390', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8d6e1e0bfd92a236493718d477376d2ef3fa6c48', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/docs/commandline-flags.md b/android_webview/docs/commandline-flags.md index 4b59123e..94d0e6713 100644 --- a/android_webview/docs/commandline-flags.md +++ b/android_webview/docs/commandline-flags.md
@@ -12,29 +12,38 @@ to the file with: ```sh -$ # Overwrites all flags (and prints the new flag state): -$ build/android/adb_system_webview_command_line \ +# Overwrite flags (supports multiple) +build/android/adb_system_webview_command_line \ --show-composited-layer-borders \ - --log-net-log=foo.json # Supports multiple flags -$ # Simply prints the existing flag state: -$ build/android/adb_system_webview_command_line -$ # Passing empty string clears all flags: -$ build/android/adb_system_webview_command_line "" + --log-net-log=foo.json +# Clear flags +build/android/adb_system_webview_command_line "" +# Print flags +build/android/adb_system_webview_command_line +``` + +Or, for a locally compiled APK: + +```sh +autoninja -C out/Default system_webview_apk +# Overwrite flags (supports multiple) +out/Default/bin/system_webview_apk argv --args='--show-composited-layer-borders --log-net-log=foo.json' +# Clear flags +out/Default/bin/system_webview_apk argv --args='' +# Print flags +out/Default/bin/system_webview_apk argv ``` Or, you can use the `adb` in your `$PATH` like so: ```sh -$ FLAG_FILE=/data/local/tmp/webview-command-line -$ adb shell "echo '_ --show-composited-layer-borders' > ${FLAG_FILE}" -$ # The first token is ignored. We use '_' as a convenient placeholder, but any -$ # token is acceptable. +FLAG_FILE=/data/local/tmp/webview-command-line +# Overwrite flags +adb shell "echo '_ --show-composited-layer-borders' > ${FLAG_FILE}" +# The first token is ignored. We use '_' as a convenient placeholder, but any +# token is acceptable. ``` -*** note -**Note:** either set of commands will overwrite existing flags. -*** - ### Applying Features with flags WebView supports the same `--enable-features=feature1,feature2` and
diff --git a/android_webview/docs/net-debugging.md b/android_webview/docs/net-debugging.md index 2de1b883..b0f906f 100644 --- a/android_webview/docs/net-debugging.md +++ b/android_webview/docs/net-debugging.md
@@ -16,6 +16,30 @@ production builds of Android. *** +```shell +# Optional: set any flags of your choosing before running the script +$ build/android/adb_system_webview_command_line --enable-features=NetworkService,NetworkServiceInProcess +Wrote command line file. Current flags (in webview-command-line): + 005d1ac915b0c7d6 (bullhead-userdebug 6.0 MDB08M 2353240 dev-keys): --enable-features=NetworkService,NetworkServiceInProcess + +# Replace "<app package name>" with your app's package name (ex. the +# WebView Shell is "org.chromium.webview_shell") +$ android_webview/tools/record_netlog.py --package="<app package name>" +Running with flags ['--enable-features=NetworkService,NetworkServiceInProcess', '--log-net-log=netlog.json'] +Netlog will start recording as soon as app starts up. Press ctrl-C to stop recording. +^C +Pulling netlog to "netlog.json" +``` + +Then import the JSON file into [the NetLog +viewer](https://chromium.googlesource.com/catapult/+/master/netlog_viewer/). + +For more details, see the implementation in +[AwUrlRequestContextGetter](/android_webview/browser/net/aw_url_request_context_getter.cc). +For support in the network service code path, see http://crbug.com/902039. + +### Manual steps + 1. Figure out the app's data directory ```sh # appPackageName is the package name of whatever app you're interested (ex. @@ -38,9 +62,4 @@ ```sh adb pull "${appDataDir}/app_webview/${jsonFile}" ``` -1. Import the JSON file into [the NetLog - viewer](https://chromium.googlesource.com/catapult/+/master/netlog_viewer/) - -For more details, see the implementation in -[AwUrlRequestContextGetter](/android_webview/browser/net/aw_url_request_context_getter.cc). -For support in the network service code path, see http://crbug.com/902039. + 1. Follow the step above for using the Netlog viewer
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java index 6f4f333..3057d796 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java
@@ -36,35 +36,28 @@ public void testModeBrowser() throws Exception { HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue(shim.runTestForMode( - "browser", false, "native-include-thread-names", true, false, false)); + Assert.assertTrue( + shim.runTestForMode("browser", false, "native-include-thread-names", false, false)); } @Test @MediumTest public void testModeBrowserDynamicPseudo() throws Exception { HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue(shim.runTestForMode("browser", true, "pseudo", true, false, false)); + Assert.assertTrue(shim.runTestForMode("browser", true, "pseudo", false, false)); } @Test @MediumTest public void testModeBrowserDynamicPseudoSampleEverything() throws Exception { HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue(shim.runTestForMode("browser", true, "pseudo", true, true, true)); + Assert.assertTrue(shim.runTestForMode("browser", true, "pseudo", true, true)); } @Test @MediumTest public void testModeBrowserDynamicPseudoSamplePartial() throws Exception { HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue(shim.runTestForMode("browser", true, "pseudo", true, true, false)); - } - - @Test - @MediumTest - public void testModeBrowserDynamicPseudoSamplePartialNonStreaming() throws Exception { - HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue(shim.runTestForMode("browser", true, "pseudo", false, true, false)); + Assert.assertTrue(shim.runTestForMode("browser", true, "pseudo", true, false)); } }
diff --git a/android_webview/tools/record_netlog.py b/android_webview/tools/record_netlog.py new file mode 100755 index 0000000..559c9fa67 --- /dev/null +++ b/android_webview/tools/record_netlog.py
@@ -0,0 +1,135 @@ +#!/usr/bin/env python +# +# Copyright 2019 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. +"""Takes a netlog for the WebViews in a given application. + +Developer guide: +https://chromium.googlesource.com/chromium/src/+/HEAD/android_webview/docs/net-debugging.md +""" + +from __future__ import print_function + +import argparse +import logging +import os +import re +import sys +import time + +sys.path.append( + os.path.join( + os.path.dirname(__file__), os.pardir, os.pardir, 'build', 'android')) +import devil_chromium # pylint: disable=import-error +from devil.android import device_errors # pylint: disable=import-error +from devil.android import flag_changer # pylint: disable=import-error +from devil.android import device_utils # pylint: disable=import-error +from devil.android.tools import script_common # pylint: disable=import-error +from devil.utils import logging_common # pylint: disable=import-error + +WEBVIEW_COMMAND_LINE = 'webview-command-line' + + +def _WaitUntilCtrlC(): + try: + while True: + time.sleep(1) + except KeyboardInterrupt: + print() # print a new line after the "^C" the user typed to the console + + +# TODO(ntfschr): upstream this into devil, since we can avoid a read+write to +# improve performance. +def _PullFileWithRoot(device, device_path, host_path): + dirname = os.path.dirname(host_path) + if dirname and not os.path.exists(dirname): + os.makedirs(dirname) + with open(host_path, 'w') as f: + contents = device.ReadFile(device_path, as_root=True) + f.write(contents) + + +def CheckAppNotRunning(device, package_name, force): + processes = device.ListProcesses(package_name) + if processes: + msg = ('Netlog requires setting commandline flags, which only works if the ' + 'application ({}) is not already running. Please kill the app and ' + 'restart the script.'.format( + package_name)) + if force: + logging.warning(msg) + else: + # Extend the sentence to mention the user can skip the check. + msg = re.sub(r'\.$', ', or pass --force to ignore this check.', msg) + raise RuntimeError(msg) + + +def main(): + parser = argparse.ArgumentParser(description=""" +Configures WebView to start recording a netlog. This script chooses a suitable +netlog filename for the application, and will pull the netlog off the device +when the user terminates the script (with ctrl-C). For a more complete usage +guide, open your web browser to: +https://chromium.googlesource.com/chromium/src/+/HEAD/android_webview/docs/net-debugging.md +""") + parser.add_argument( + '--package', + required=True, + type=str, + help='Package name of the application you intend to use.') + parser.add_argument( + '--force', + default=False, + action='store_true', + help='Suppress user checks.') + + script_common.AddEnvironmentArguments(parser) + script_common.AddDeviceArguments(parser) + logging_common.AddLoggingArguments(parser) + + args = parser.parse_args() + logging_common.InitializeLogging(args) + devil_chromium.Initialize() + script_common.InitializeEnvironment(args) + + # Only use a single device, for the sake of simplicity (of implementation and + # user experience). + devices = device_utils.DeviceUtils.HealthyDevices(device_arg=args.devices) + device = devices[0] + if len(devices) > 1: + raise device_errors.MultipleDevicesError(devices) + + package_name = args.package + device_netlog_file_name = 'netlog.json' + device_netlog_path = os.path.join( + device.GetApplicationDataDirectory(package_name), 'app_webview', + device_netlog_file_name) + + CheckAppNotRunning(device, package_name, args.force) + + # Append to the existing flags, to allow users to experiment with other + # features/flags enabled. The CustomCommandLineFlags will restore the original + # flag state after the user presses 'ctrl-C'. + changer = flag_changer.FlagChanger(device, WEBVIEW_COMMAND_LINE) + new_flags = changer.GetCurrentFlags() + new_flags.append('--log-net-log={}'.format(device_netlog_path)) + + logging.info('Running with flags %r', new_flags) + with flag_changer.CustomCommandLineFlags(device, WEBVIEW_COMMAND_LINE, + new_flags): + print('Netlog will start recording as soon as app starts up. Press ctrl-C ' + 'to stop recording.') + _WaitUntilCtrlC() + + host_netlog_path = 'netlog.json' + print('Pulling netlog to "%s"' % host_netlog_path) + # The netlog file will be under the app's uid, which the default shell doesn't + # have permission to read (but root does). Prefer this to EnableRoot(), which + # restarts the adb daemon. + _PullFileWithRoot(device, device_netlog_path, host_netlog_path) + device.RemovePath(device_netlog_path, as_root=True) + + +if __name__ == '__main__': + main()
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc index 05d2da1..24d9588 100644 --- a/ash/app_list/views/app_list_view.cc +++ b/ash/app_list/views/app_list_view.cc
@@ -192,10 +192,13 @@ ~StateAnimationMetricsReporter() override = default; - void Start(bool is_in_tablet_mode) { - DCHECK(!started_); - is_in_tablet_mode_ = is_in_tablet_mode; + void SetTargetState(ash::mojom::AppListViewState target_state) { + target_state_ = target_state; + } + + void Start() { #if defined(DCHECK) + DCHECK(!started_); started_ = ui::ScopedAnimationDurationScaleMode::duration_scale_mode() != ui::ScopedAnimationDurationScaleMode::ZERO_DURATION; #endif @@ -203,13 +206,36 @@ void Report(int value) override { UMA_HISTOGRAM_PERCENTAGE("Apps.StateTransition.AnimationSmoothness", value); - if (is_in_tablet_mode_) { - UMA_HISTOGRAM_PERCENTAGE( - "Apps.StateTransition.AnimationSmoothness.TabletMode", value); - } else { - UMA_HISTOGRAM_PERCENTAGE( - "Apps.StateTransition.AnimationSmoothness.ClamshellMode", value); + switch (*target_state_) { + case ash::mojom::AppListViewState::kClosed: + UMA_HISTOGRAM_PERCENTAGE( + "Apps.StateTransition.AnimationSmoothness.Close.ClamshellMode", + value); + break; + case ash::mojom::AppListViewState::kPeeking: + UMA_HISTOGRAM_PERCENTAGE( + "Apps.StateTransition.AnimationSmoothness.Peeking.ClamshellMode", + value); + break; + case ash::mojom::AppListViewState::kHalf: + UMA_HISTOGRAM_PERCENTAGE( + "Apps.StateTransition.AnimationSmoothness.Half.ClamshellMode", + value); + break; + case ash::mojom::AppListViewState::kFullscreenAllApps: + UMA_HISTOGRAM_PERCENTAGE( + "Apps.StateTransition.AnimationSmoothness.FullscreenAllApps." + "ClamshellMode", + value); + break; + case ash::mojom::AppListViewState::kFullscreenSearch: + UMA_HISTOGRAM_PERCENTAGE( + "Apps.StateTransition.AnimationSmoothness.FullscreenSearch." + "ClamshellMode", + value); + break; } + target_state_.reset(); view_->OnStateTransitionAnimationCompleted(); #if defined(DCHECK) started_ = false; @@ -220,7 +246,7 @@ #if defined(DCHECK) bool started_ = false; #endif - bool is_in_tablet_mode_ = false; + base::Optional<ash::mojom::AppListViewState> target_state_; AppListView* view_; DISALLOW_COPY_AND_ASSIGN(StateAnimationMetricsReporter); @@ -1370,6 +1396,7 @@ settings.SetTweenType(gfx::Tween::EASE_OUT); settings.SetPreemptionStrategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + state_animation_metrics_reporter_->SetTargetState(target_state); settings.SetAnimationMetricsReporter(state_animation_metrics_reporter_.get()); settings.AddObserver(transition_animation_observer_.get()); @@ -1392,6 +1419,8 @@ animation_duration /= 2; } + state_animation_metrics_reporter_->SetTargetState( + ash::mojom::AppListViewState::kClosed); SetState(ash::mojom::AppListViewState::kClosed); app_list_main_view_->contents_view()->FadeOutOnClose(animation_duration); } @@ -1606,7 +1635,7 @@ } ui::AnimationMetricsReporter* AppListView::GetStateTransitionMetricsReporter() { - state_animation_metrics_reporter_->Start(is_tablet_mode_); + state_animation_metrics_reporter_->Start(); return state_animation_metrics_reporter_.get(); }
diff --git a/ash/wm/splitview/split_view_divider.cc b/ash/wm/splitview/split_view_divider.cc index 9a5e9bb4..5e06c60 100644 --- a/ash/wm/splitview/split_view_divider.cc +++ b/ash/wm/splitview/split_view_divider.cc
@@ -51,7 +51,7 @@ constexpr SkColor kDividerBackgroundColor = SK_ColorBLACK; constexpr SkColor kWhiteBarBackgroundColor = SK_ColorWHITE; constexpr int kDividerBoundsChangeDurationMs = 250; -constexpr int kWhiteBarBoundsChangeDurationMs = 150; +constexpr int kWhiteBarBoundsChangeDurationMs = 250; // The distance to the divider edge in which a touch gesture will be considered // as a valid event on the divider.
diff --git a/base/android/jni_array.cc b/base/android/jni_array.cc index 0693776..054853d9 100644 --- a/base/android/jni_array.cc +++ b/base/android/jni_array.cc
@@ -124,6 +124,25 @@ return ToJavaFloatArray(env, floats.data(), floats.size()); } +BASE_EXPORT ScopedJavaLocalRef<jdoubleArray> +ToJavaDoubleArray(JNIEnv* env, const double* doubles, size_t len) { + jdoubleArray double_array = env->NewDoubleArray(len); + CheckException(env); + DCHECK(double_array); + + env->SetDoubleArrayRegion(double_array, 0, len, + reinterpret_cast<const jdouble*>(doubles)); + CheckException(env); + + return ScopedJavaLocalRef<jdoubleArray>(env, double_array); +} + +BASE_EXPORT ScopedJavaLocalRef<jdoubleArray> ToJavaDoubleArray( + JNIEnv* env, + const std::vector<double>& doubles) { + return ToJavaDoubleArray(env, doubles.data(), doubles.size()); +} + ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray( JNIEnv* env, const std::vector<std::string>& v) { ScopedJavaLocalRef<jclass> byte_array_clazz = GetClass(env, "[B");
diff --git a/base/android/jni_array.h b/base/android/jni_array.h index c5a1c0368..917f1d0 100644 --- a/base/android/jni_array.h +++ b/base/android/jni_array.h
@@ -60,6 +60,14 @@ JNIEnv* env, const std::vector<float>& floats); +// Returns a new Java double array converted from the given C++ double array. +BASE_EXPORT ScopedJavaLocalRef<jdoubleArray> +ToJavaDoubleArray(JNIEnv* env, const double* doubles, size_t len); + +BASE_EXPORT ScopedJavaLocalRef<jdoubleArray> ToJavaDoubleArray( + JNIEnv* env, + const std::vector<double>& doubles); + // Returns a array of Java byte array converted from |v|. BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray( JNIEnv* env, const std::vector<std::string>& v);
diff --git a/base/profiler/native_unwinder_mac.cc b/base/profiler/native_unwinder_mac.cc index 0bd145c..8c6b18e 100644 --- a/base/profiler/native_unwinder_mac.cc +++ b/base/profiler/native_unwinder_mac.cc
@@ -131,7 +131,7 @@ } bool NativeUnwinderMac::CanUnwindFrom(const Frame* current_frame) const { - return current_frame->module; + return current_frame->module && current_frame->module->IsNative(); } UnwindResult NativeUnwinderMac::TryUnwind(x86_thread_state64_t* thread_context, @@ -222,10 +222,13 @@ // libunwind adds the expected stack size, it will look for the return // address in the wrong place. This check ensures we don't continue trying // to unwind using the resulting bad IP value. - // - // We return UNRECOGNIZED_FRAME on the optimistic assumption that this may - // be a frame the AuxUnwinder knows how to handle (e.g. a frame in V8 - // generated code). + return UnwindResult::ABORTED; + } + + if (!current_frame->module->IsNative()) { + // This is a non-native module associated with the auxiliary unwinder + // (e.g. corresponding to a frame in V8 generated code). Report as + // UNRECOGNIZED_FRAME to allow that unwinder to unwind the frame. return UnwindResult::UNRECOGNIZED_FRAME; }
diff --git a/base/profiler/native_unwinder_win.cc b/base/profiler/native_unwinder_win.cc index 47f6309..bd93438 100644 --- a/base/profiler/native_unwinder_win.cc +++ b/base/profiler/native_unwinder_win.cc
@@ -10,7 +10,7 @@ namespace base { bool NativeUnwinderWin::CanUnwindFrom(const Frame* current_frame) const { - return current_frame->module; + return current_frame->module && current_frame->module->IsNative(); } // Attempts to unwind the frame represented by the context values. If @@ -28,22 +28,24 @@ for (;;) { if (!stack->back().module) { // There's no loaded module corresponding to the current frame. This can - // be due to executing code that is not in a module (e.g. V8 generated - // code or runtime-generated code associated with third-party injected - // DLLs). It can also be due to the the module having been unloaded since - // we recorded the stack. In the latter case the function unwind - // information was part of the unloaded module, so it's not possible to - // unwind further. + // be due to executing code not in a module (e.g. runtime-generated code + // associated with third-party injected DLLs) or the module having been + // unloaded since we recorded the stack. In the latter case the function + // unwind information was part of the unloaded module, so it's not + // possible to unwind further. // - // If a module was found, it's still theoretically possible for the + // NB: if a module was found it's still theoretically possible for the // detected module module to be different than the one that was loaded - // when the stack was copied (i.e. if the module was unloaded and a - // different module loaded in overlapping memory). This likely would cause - // a crash, but has not been observed in practice. - // - // We return UNRECOGNIZED_FRAME on the optimistic assumption that this may - // be a frame the AuxUnwinder knows how to handle (e.g. a frame in V8 - // generated code). + // when the stack was copied, if the module was unloaded and a different + // module loaded in overlapping memory. This likely would cause a crash + // but has not been observed in practice. + return UnwindResult::ABORTED; + } + + if (!stack->back().module->IsNative()) { + // This is a non-native module associated with the auxiliary unwinder + // (e.g. corresponding to a frame in V8 generated code). Report as + // UNRECOGNIZED_FRAME to allow that unwinder to unwind the frame. return UnwindResult::UNRECOGNIZED_FRAME; }
diff --git a/base/profiler/register_context.h b/base/profiler/register_context.h index 7c7dfd8b..9c6eaf1 100644 --- a/base/profiler/register_context.h +++ b/base/profiler/register_context.h
@@ -19,6 +19,8 @@ #include <mach/machine/thread_status.h> #endif +namespace base { + // Helper function to account for the fact that platform-specific register state // types may be unsigned and of the same size as uintptr_t, but not of the same // type -- e.g. unsigned int vs. unsigned long on 32-bit Windows and unsigned @@ -104,4 +106,6 @@ #endif // #if defined(OS_WIN) +} // namespace base + #endif // BASE_PROFILER_REGISTER_CONTEXT_H_
diff --git a/base/profiler/stack_sampler_impl.cc b/base/profiler/stack_sampler_impl.cc index fffb59a1..0b808fba 100644 --- a/base/profiler/stack_sampler_impl.cc +++ b/base/profiler/stack_sampler_impl.cc
@@ -87,6 +87,7 @@ void StackSamplerImpl::AddAuxUnwinder(Unwinder* unwinder) { aux_unwinder_ = unwinder; + aux_unwinder_->AddNonNativeModules(module_cache_); } void StackSamplerImpl::RecordStackFrames(StackBuffer* stack_buffer, @@ -103,7 +104,20 @@ if (test_delegate_) test_delegate_->OnPreStackWalk(); - profile_builder->OnSampleCompleted(WalkStack(&thread_context, stack_top)); + profile_builder->OnSampleCompleted( + WalkStack(module_cache_, &thread_context, stack_top, + native_unwinder_.get(), aux_unwinder_)); +} +// static + +std::vector<Frame> StackSamplerImpl::WalkStackForTesting( + ModuleCache* module_cache, + RegisterContext* thread_context, + uintptr_t stack_top, + Unwinder* native_unwinder, + Unwinder* aux_unwinder) { + return WalkStack(module_cache, thread_context, stack_top, native_unwinder, + aux_unwinder); } // Suspends the thread, copies its stack, top address of the stack copy, and @@ -160,10 +174,12 @@ return true; } -// Walks the stack represented by |thread_context|, recording and returning the -// frames. -std::vector<Frame> StackSamplerImpl::WalkStack(RegisterContext* thread_context, - uintptr_t stack_top) { +// static +std::vector<Frame> StackSamplerImpl::WalkStack(ModuleCache* module_cache, + RegisterContext* thread_context, + uintptr_t stack_top, + Unwinder* native_unwinder, + Unwinder* aux_unwinder) { std::vector<Frame> stack; // Reserve enough memory for most stacks, to avoid repeated // allocations. Approximately 99.9% of recorded stacks are 128 frames or @@ -172,10 +188,32 @@ // Record the first frame from the context values. stack.emplace_back(RegisterContextInstructionPointer(thread_context), - module_cache_->GetModuleForAddress( + module_cache->GetModuleForAddress( RegisterContextInstructionPointer(thread_context))); - native_unwinder_->TryUnwind(thread_context, stack_top, module_cache_, &stack); + size_t prior_stack_size; + UnwindResult result; + do { + // Choose an authoritative unwinder for the current module. Use the aux + // unwinder if it thinks it can unwind from the current frame, otherwise use + // the native unwinder. + Unwinder* unwinder = + aux_unwinder && aux_unwinder->CanUnwindFrom(&stack.back()) + ? aux_unwinder + : native_unwinder; + + prior_stack_size = stack.size(); + result = + unwinder->TryUnwind(thread_context, stack_top, module_cache, &stack); + + // The native unwinder should be the only one that returns COMPLETED + // since the stack starts in native code. + DCHECK(result != UnwindResult::COMPLETED || unwinder == native_unwinder); + } while (result != UnwindResult::ABORTED && + result != UnwindResult::COMPLETED && + // Give up if the authoritative unwinder for the module was unable to + // unwind. + stack.size() > prior_stack_size); return stack; }
diff --git a/base/profiler/stack_sampler_impl.h b/base/profiler/stack_sampler_impl.h index d7aaac1..8b73e0d8 100644 --- a/base/profiler/stack_sampler_impl.h +++ b/base/profiler/stack_sampler_impl.h
@@ -35,14 +35,24 @@ void RecordStackFrames(StackBuffer* stack_buffer, ProfileBuilder* profile_builder) override; + // Exposes the internal function for unit testing. + static std::vector<Frame> WalkStackForTesting(ModuleCache* module_cache, + RegisterContext* thread_context, + uintptr_t stack_top, + Unwinder* native_unwinder, + Unwinder* aux_unwinder); + private: bool CopyStack(StackBuffer* stack_buffer, uintptr_t* stack_top, ProfileBuilder* profile_builder, RegisterContext* thread_context); - std::vector<Frame> WalkStack(RegisterContext* thread_context, - uintptr_t stack_top); + static std::vector<Frame> WalkStack(ModuleCache* module_cache, + RegisterContext* thread_context, + uintptr_t stack_top, + Unwinder* native_unwinder, + Unwinder* aux_unwinder); const std::unique_ptr<ThreadDelegate> thread_delegate_; const std::unique_ptr<Unwinder> native_unwinder_;
diff --git a/base/profiler/stack_sampler_impl_unittest.cc b/base/profiler/stack_sampler_impl_unittest.cc index 130eaff..86aac6a 100644 --- a/base/profiler/stack_sampler_impl_unittest.cc +++ b/base/profiler/stack_sampler_impl_unittest.cc
@@ -134,18 +134,19 @@ class TestModule : public ModuleCache::Module { public: - TestModule(uintptr_t base_address, size_t size) - : base_address_(base_address), size_(size) {} + TestModule(uintptr_t base_address, size_t size, bool is_native = true) + : base_address_(base_address), size_(size), is_native_(is_native) {} uintptr_t GetBaseAddress() const override { return base_address_; } std::string GetId() const override { return ""; } FilePath GetDebugBasename() const override { return FilePath(); } size_t GetSize() const override { return size_; } - bool IsNative() const override { return true; } + bool IsNative() const override { return is_native_; } private: const uintptr_t base_address_; const size_t size_; + const bool is_native_; }; // Injects a fake module covering the initial instruction pointer value, to @@ -158,6 +159,70 @@ std::make_unique<TestModule>(stack[0], sizeof(uintptr_t))); } +// Returns a plausible instruction pointer value for use in tests that don't +// care about the instruction pointer value in the context, and hence don't need +// InjectModuleForContextInstructionPointer(). +uintptr_t GetTestInstructionPointer() { + return reinterpret_cast<uintptr_t>(&GetTestInstructionPointer); +} + +// An unwinder fake that replays the provided outputs. +class FakeTestUnwinder : public Unwinder { + public: + struct Result { + Result(bool can_unwind) + : can_unwind(can_unwind), result(UnwindResult::UNRECOGNIZED_FRAME) {} + + Result(UnwindResult result, std::vector<uintptr_t> instruction_pointers) + : can_unwind(true), + result(result), + instruction_pointers(instruction_pointers) {} + + bool can_unwind; + UnwindResult result; + std::vector<uintptr_t> instruction_pointers; + }; + + // Construct the unwinder with the outputs. The relevant unwinder functions + // are expected to be invoked at least as many times as the number of values + // specified in the arrays (except for CanUnwindFrom() which will always + // return true if provided an empty array. + explicit FakeTestUnwinder(std::vector<Result> results) + : results_(std::move(results)) {} + + FakeTestUnwinder(const FakeTestUnwinder&) = delete; + FakeTestUnwinder& operator=(const FakeTestUnwinder&) = delete; + + bool CanUnwindFrom(const Frame* current_frame) const override { + bool can_unwind = results_[current_unwind_].can_unwind; + // NB: If CanUnwindFrom() returns false then TryUnwind() will not be + // invoked, so current_unwind_ is guarantee to be incremented only once for + // each result. + if (!can_unwind) + ++current_unwind_; + return can_unwind; + } + + UnwindResult TryUnwind(RegisterContext* thread_context, + uintptr_t stack_top, + ModuleCache* module_cache, + std::vector<Frame>* stack) const override { + CHECK_LT(current_unwind_, results_.size()); + const Result& current_result = results_[current_unwind_]; + ++current_unwind_; + CHECK(current_result.can_unwind); + for (const auto instruction_pointer : current_result.instruction_pointers) + stack->emplace_back( + instruction_pointer, + module_cache->GetModuleForAddress(instruction_pointer)); + return current_result.result; + } + + private: + mutable size_t current_unwind_ = 0; + std::vector<Result> results_; +}; + } // namespace TEST(StackSamplerImplTest, CopyStack) { @@ -250,4 +315,120 @@ RegisterContextFramePointer(&thread_context)); } +TEST(StackSamplerImplTest, WalkStack_Completed) { + ModuleCache module_cache; + RegisterContext thread_context; + RegisterContextInstructionPointer(&thread_context) = + GetTestInstructionPointer(); + module_cache.InjectModuleForTesting(std::make_unique<TestModule>(1u, 1u)); + FakeTestUnwinder native_unwinder({{UnwindResult::COMPLETED, {1u}}}); + + std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting( + &module_cache, &thread_context, 0u, &native_unwinder, nullptr); + + ASSERT_EQ(2u, stack.size()); + EXPECT_EQ(1u, stack[1].instruction_pointer); +} + +TEST(StackSamplerImplTest, WalkStack_Aborted) { + ModuleCache module_cache; + RegisterContext thread_context; + RegisterContextInstructionPointer(&thread_context) = + GetTestInstructionPointer(); + module_cache.InjectModuleForTesting(std::make_unique<TestModule>(1u, 1u)); + FakeTestUnwinder native_unwinder({{UnwindResult::ABORTED, {1u}}}); + + std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting( + &module_cache, &thread_context, 0u, &native_unwinder, nullptr); + + ASSERT_EQ(2u, stack.size()); + EXPECT_EQ(1u, stack[1].instruction_pointer); +} + +TEST(StackSamplerImplTest, WalkStack_NotUnwound) { + ModuleCache module_cache; + RegisterContext thread_context; + RegisterContextInstructionPointer(&thread_context) = + GetTestInstructionPointer(); + FakeTestUnwinder native_unwinder({{UnwindResult::UNRECOGNIZED_FRAME, {}}}); + + std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting( + &module_cache, &thread_context, 0u, &native_unwinder, nullptr); + + ASSERT_EQ(1u, stack.size()); +} + +TEST(StackSamplerImplTest, WalkStack_AuxUnwind) { + ModuleCache module_cache; + RegisterContext thread_context; + RegisterContextInstructionPointer(&thread_context) = + GetTestInstructionPointer(); + + // Treat the context instruction pointer as being in the aux unwinder's + // non-native module. + module_cache.AddNonNativeModule( + std::make_unique<TestModule>(GetTestInstructionPointer(), 1u, false)); + + FakeTestUnwinder aux_unwinder({{UnwindResult::ABORTED, {1u}}}); + + std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting( + &module_cache, &thread_context, 0u, nullptr, &aux_unwinder); + + ASSERT_EQ(2u, stack.size()); + EXPECT_EQ(GetTestInstructionPointer(), stack[0].instruction_pointer); + EXPECT_EQ(1u, stack[1].instruction_pointer); +} + +TEST(StackSamplerImplTest, WalkStack_AuxThenNative) { + ModuleCache module_cache; + RegisterContext thread_context; + RegisterContextInstructionPointer(&thread_context) = 0u; + + // Treat the context instruction pointer as being in the aux unwinder's + // non-native module. + module_cache.AddNonNativeModule(std::make_unique<TestModule>(0u, 1u, false)); + // Inject a fake native module for the second frame. + module_cache.InjectModuleForTesting(std::make_unique<TestModule>(1u, 1u)); + + FakeTestUnwinder aux_unwinder( + {{{UnwindResult::UNRECOGNIZED_FRAME, {1u}}, {false}}}); + FakeTestUnwinder native_unwinder({{UnwindResult::COMPLETED, {2u}}}); + + std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting( + &module_cache, &thread_context, 0u, &native_unwinder, &aux_unwinder); + + ASSERT_EQ(3u, stack.size()); + EXPECT_EQ(0u, stack[0].instruction_pointer); + EXPECT_EQ(1u, stack[1].instruction_pointer); + EXPECT_EQ(2u, stack[2].instruction_pointer); +} + +TEST(StackSamplerImplTest, WalkStack_NativeThenAux) { + ModuleCache module_cache; + RegisterContext thread_context; + RegisterContextInstructionPointer(&thread_context) = 0u; + + // Inject fake native modules for the instruction pointer from the context and + // the third frame. + module_cache.InjectModuleForTesting(std::make_unique<TestModule>(0u, 1u)); + module_cache.InjectModuleForTesting(std::make_unique<TestModule>(2u, 1u)); + // Treat the second frame's pointer as being in the aux unwinder's non-native + // module. + module_cache.AddNonNativeModule(std::make_unique<TestModule>(1u, 1u, false)); + + FakeTestUnwinder aux_unwinder( + {{false}, {UnwindResult::UNRECOGNIZED_FRAME, {2u}}, {false}}); + FakeTestUnwinder native_unwinder({{UnwindResult::UNRECOGNIZED_FRAME, {1u}}, + {UnwindResult::COMPLETED, {3u}}}); + + std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting( + &module_cache, &thread_context, 0u, &native_unwinder, &aux_unwinder); + + ASSERT_EQ(4u, stack.size()); + EXPECT_EQ(0u, stack[0].instruction_pointer); + EXPECT_EQ(1u, stack[1].instruction_pointer); + EXPECT_EQ(2u, stack[2].instruction_pointer); + EXPECT_EQ(3u, stack[3].instruction_pointer); +} + } // namespace base
diff --git a/base/profiler/unwinder.h b/base/profiler/unwinder.h index 09b3efa..7ffc1ffa 100644 --- a/base/profiler/unwinder.h +++ b/base/profiler/unwinder.h
@@ -37,6 +37,10 @@ public: virtual ~Unwinder() = default; + // Invoked to allow the unwinder to add any non-native modules it recognizes + // to the ModuleCache. + virtual void AddNonNativeModules(ModuleCache* module_cache) {} + // Returns true if the unwinder recognizes the code referenced by // |current_frame| as code from which it should be able to unwind. When // multiple unwinders are in use, each should return true for a disjoint set
diff --git a/base/sampling_heap_profiler/poisson_allocation_sampler.h b/base/sampling_heap_profiler/poisson_allocation_sampler.h index 79d2a4b..7709e02 100644 --- a/base/sampling_heap_profiler/poisson_allocation_sampler.h +++ b/base/sampling_heap_profiler/poisson_allocation_sampler.h
@@ -33,7 +33,7 @@ // class BASE_EXPORT PoissonAllocationSampler { public: - enum AllocatorType : uint32_t { kMalloc, kPartitionAlloc, kBlinkGC, kMax }; + enum AllocatorType : uint32_t { kMalloc, kPartitionAlloc, kBlinkGC }; // When the sampler is just enabled it needs to see up to that amount // of allocation sizes before it starts recording samples.
diff --git a/base/task/sequence_manager/work_queue_unittest.cc b/base/task/sequence_manager/work_queue_unittest.cc index ccf6822..5dba2b5 100644 --- a/base/task/sequence_manager/work_queue_unittest.cc +++ b/base/task/sequence_manager/work_queue_unittest.cc
@@ -8,10 +8,13 @@ #include <memory> #include "base/bind.h" +#include "base/task/sequence_manager/lazy_now.h" #include "base/task/sequence_manager/real_time_domain.h" -#include "base/task/sequence_manager/sequence_manager_impl.h" +#include "base/task/sequence_manager/sequence_manager.h" #include "base/task/sequence_manager/task_queue_impl.h" #include "base/task/sequence_manager/work_queue_sets.h" +#include "base/time/default_tick_clock.h" +#include "base/time/time.h" #include "testing/gmock/include/gmock/gmock.h" namespace base { @@ -35,19 +38,22 @@ WeakPtrFactory<Cancelable> weak_ptr_factory; }; +class RealTimeDomainFake : public RealTimeDomain { + public: + LazyNow CreateLazyNow() const override { + return LazyNow(DefaultTickClock::GetInstance()); + } + + TimeTicks Now() const override { return TimeTicks::Now(); } +}; + } // namespace class WorkQueueTest : public testing::Test { public: void SetUp() override { - dummy_sequence_manager_ = - SequenceManagerImpl::CreateUnbound(SequenceManager::Settings{}); - scoped_refptr<AssociatedThreadId> thread_checker = - dummy_sequence_manager_->associated_thread(); - thread_checker->BindToCurrentThread(); - time_domain_.reset(new RealTimeDomain()); - dummy_sequence_manager_->RegisterTimeDomain(time_domain_.get()); - task_queue_ = std::make_unique<TaskQueueImpl>(dummy_sequence_manager_.get(), + time_domain_.reset(new RealTimeDomainFake()); + task_queue_ = std::make_unique<TaskQueueImpl>(/*sequence_manager=*/nullptr, time_domain_.get(), TaskQueue::Spec("test")); @@ -62,7 +68,6 @@ void TearDown() override { work_queue_sets_->RemoveQueue(work_queue_.get()); task_queue_->UnregisterTaskQueue(); - dummy_sequence_manager_->UnregisterTimeDomain(time_domain_.get()); } protected: @@ -91,7 +96,6 @@ } std::unique_ptr<MockObserver> mock_observer_; - std::unique_ptr<SequenceManagerImpl> dummy_sequence_manager_; std::unique_ptr<RealTimeDomain> time_domain_; std::unique_ptr<TaskQueueImpl> task_queue_; std::unique_ptr<WorkQueue> work_queue_;
diff --git a/base/threading/thread_local_storage.h b/base/threading/thread_local_storage.h index 9cb5aeb..5bba459 100644 --- a/base/threading/thread_local_storage.h +++ b/base/threading/thread_local_storage.h
@@ -18,10 +18,6 @@ #include <pthread.h> #endif -namespace heap_profiling { -class ScopedAllowAlloc; -} // namespace heap_profiling - namespace ui { class TLSDestructionCheckerForX11; } @@ -165,7 +161,6 @@ friend class base::internal::ThreadLocalStorageTestInternal; friend class base::trace_event::MallocDumpProvider; friend class debug::GlobalActivityTracker; - friend class heap_profiling::ScopedAllowAlloc; friend class ui::TLSDestructionCheckerForX11; static bool HasBeenDestroyed();
diff --git a/build/android/adb_command_line.py b/build/android/adb_command_line.py index 2f3a615a..5763da4 100755 --- a/build/android/adb_command_line.py +++ b/build/android/adb_command_line.py
@@ -19,6 +19,20 @@ from devil.utils import logging_common +def CheckBuildTypeSupportsFlags(device, command_line_flags_file): + is_webview = command_line_flags_file == 'webview-command-line' + if device.IsUserBuild() and is_webview: + raise device_errors.CommandFailedError( + 'WebView only respects flags on a userdebug or eng device, yours ' + 'is a user build.', device) + elif device.IsUserBuild(): + logging.warning( + 'Your device (%s) is a user build; Chrome may or may not pick up ' + 'your commandline flags. Check your ' + '"command_line_on_non_rooted_enabled" preference, or switch ' + 'devices.', device) + + def main(): parser = argparse.ArgumentParser(description=__doc__) parser.usage = '''%(prog)s --name FILENAME [--device SERIAL] [flags...] @@ -55,19 +69,8 @@ else: action = 'Wrote command line file. ' - is_webview = args.name == 'webview-command-line' - def update_flags(device): - if device.IsUserBuild() and is_webview: - raise device_errors.CommandFailedError( - 'WebView only respects flags on a userdebug or eng device, yours ' - 'is a user build.', device) - elif device.IsUserBuild(): - logging.warning( - 'Your device (%s) is a user build; Chrome may or may not pick up ' - 'your commandline flags. Check your ' - '"command_line_on_non_rooted_enabled" preference, or switch ' - 'devices.', device) + CheckBuildTypeSupportsFlags(device, args.name) changer = flag_changer.FlagChanger(device, args.name) if remote_args is not None: flags = changer.ReplaceFlags(remote_args)
diff --git a/build/android/apk_operations.py b/build/android/apk_operations.py index 91f6851c..c4e6877 100755 --- a/build/android/apk_operations.py +++ b/build/android/apk_operations.py
@@ -21,6 +21,7 @@ import tempfile import textwrap +import adb_command_line import devil_chromium from devil import devil_env from devil.android import apk_helper @@ -323,6 +324,8 @@ changer = flag_changer.FlagChanger(device, command_line_flags_file) flags = [] if argv: + adb_command_line.CheckBuildTypeSupportsFlags(device, + command_line_flags_file) flags = shlex.split(argv) try: changer.ReplaceFlags(flags) @@ -353,6 +356,8 @@ else: flags = shlex.split(argv) def update(device): + adb_command_line.CheckBuildTypeSupportsFlags(device, + command_line_flags_file) changer = flag_changer.FlagChanger(device, command_line_flags_file) changer.ReplaceFlags(flags) device_utils.DeviceUtils.parallel(devices).pMap(update)
diff --git a/build/android/gyp/create_bundle_wrapper_script.pydeps b/build/android/gyp/create_bundle_wrapper_script.pydeps index 5587566..fb35bc0 100644 --- a/build/android/gyp/create_bundle_wrapper_script.pydeps +++ b/build/android/gyp/create_bundle_wrapper_script.pydeps
@@ -22,6 +22,7 @@ ../../../third_party/catapult/devil/devil/android/constants/chrome.py ../../../third_party/catapult/devil/devil/android/constants/file_system.py ../../../third_party/catapult/devil/devil/android/decorators.py +../../../third_party/catapult/devil/devil/android/device_blacklist.py ../../../third_party/catapult/devil/devil/android/device_errors.py ../../../third_party/catapult/devil/devil/android/device_signal.py ../../../third_party/catapult/devil/devil/android/device_temp_file.py @@ -40,6 +41,8 @@ ../../../third_party/catapult/devil/devil/android/sdk/keyevent.py ../../../third_party/catapult/devil/devil/android/sdk/split_select.py ../../../third_party/catapult/devil/devil/android/sdk/version_codes.py +../../../third_party/catapult/devil/devil/android/tools/__init__.py +../../../third_party/catapult/devil/devil/android/tools/script_common.py ../../../third_party/catapult/devil/devil/base_error.py ../../../third_party/catapult/devil/devil/constants/__init__.py ../../../third_party/catapult/devil/devil/constants/exit_codes.py @@ -81,6 +84,7 @@ ../../../third_party/markupsafe/_compat.py ../../../third_party/markupsafe/_native.py ../../gn_helpers.py +../adb_command_line.py ../apk_operations.py ../devil_chromium.py ../incremental_install/__init__.py
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 60438e79..24b4bc37 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -1656,7 +1656,8 @@ host_impl->SetHasGpuRasterizationTrigger(has_gpu_rasterization_trigger_); host_impl->SetContentHasSlowPaths(content_has_slow_paths_); host_impl->SetContentHasNonAAPaint(content_has_non_aa_paint_); - host_impl->set_pinch_gesture_active(is_external_pinch_gesture_active_); + host_impl->set_external_pinch_gesture_active( + is_external_pinch_gesture_active_); RecordGpuRasterizationHistogram(host_impl); host_impl->SetDebugState(debug_state_);
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 12276be..d7e7b2b 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -592,15 +592,19 @@ return accumulated_root_overscroll_; } - bool pinch_gesture_active() const { return pinch_gesture_active_; } + bool pinch_gesture_active() const { + return pinch_gesture_active_ || external_pinch_gesture_active_; + } // Used to set the pinch gesture active state when the pinch gesture is // handled on another layer tree. In a page with OOPIFs, only the main // frame's layer tree directly handles pinch events. But layer trees for // sub-frames need to know when pinch gestures are active so they can // throttle the re-rastering. This function allows setting this flag on // OOPIF layer trees using information sent (initially) from the main-frame. - void set_pinch_gesture_active(bool external_pinch_gesture_active) { - pinch_gesture_active_ = external_pinch_gesture_active; + void set_external_pinch_gesture_active(bool external_pinch_gesture_active) { + external_pinch_gesture_active_ = external_pinch_gesture_active; + // Only one of the flags should ever be true at any given time. + DCHECK(!pinch_gesture_active_ || !external_pinch_gesture_active_); } void SetTreePriority(TreePriority priority); @@ -1035,6 +1039,7 @@ // is set from the main thread during the commit process, using information // sent from the root layer tree via IPC messaging. bool pinch_gesture_active_ = false; + bool external_pinch_gesture_active_ = false; bool pinch_gesture_end_should_clear_scrolling_node_ = false; std::unique_ptr<BrowserControlsOffsetManager>
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 795737f..386b35a 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -885,6 +885,30 @@ float max_page_scale_factor_; }; +TEST_F(LayerTreeHostImplTest, LocalAndExternalPinchState) { + // PinchGestureBegin/End update pinch_gesture_active() properly. + EXPECT_FALSE(host_impl_->pinch_gesture_active()); + host_impl_->PinchGestureBegin(); + EXPECT_TRUE(host_impl_->pinch_gesture_active()); + host_impl_->PinchGestureEnd(gfx::Point(), false /* snap_to_min */); + EXPECT_FALSE(host_impl_->pinch_gesture_active()); + + // set_external_pinch_gesture_active updates pinch_gesture_active() properly. + host_impl_->set_external_pinch_gesture_active(true); + EXPECT_TRUE(host_impl_->pinch_gesture_active()); + host_impl_->set_external_pinch_gesture_active(false); + EXPECT_FALSE(host_impl_->pinch_gesture_active()); + + // Clearing external_pinch_gesture_active doesn't affect + // pinch_gesture_active() if it was set by PinchGestureBegin(). + host_impl_->PinchGestureBegin(); + EXPECT_TRUE(host_impl_->pinch_gesture_active()); + host_impl_->set_external_pinch_gesture_active(false); + EXPECT_TRUE(host_impl_->pinch_gesture_active()); + host_impl_->PinchGestureEnd(gfx::Point(), false /* snap_to_min */); + EXPECT_FALSE(host_impl_->pinch_gesture_active()); +} + TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) { // Note: It is not possible to disable the renderer once it has been set, // so we do not need to test that disabling the renderer notifies us
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 8b0b3e8..db42ce9 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -2422,7 +2422,6 @@ "java/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizer.java", "java/src/org/chromium/chrome/browser/omnibox/OmniboxViewUtil.java", "java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java", - "java/src/org/chromium/chrome/browser/omnibox/suggestions/AnswersImageFetcher.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java", "java/src/org/chromium/chrome/browser/page_info/CertificateChainHelper.java", "java/src/org/chromium/chrome/browser/page_info/CertificateViewer.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index a07bd7f..918acf3 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -93,8 +93,7 @@ "java/src/org/chromium/chrome/browser/autofill/PhoneNumberUtil.java", "java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/AutofillKeyboardAccessoryBridge.java", "java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingMetricsRecorder.java", - "java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardExtensionSizeManager.java", - "java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardExtensionSizeManagerImpl.java", + "java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardExtensionViewResizer.java", "java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingBridge.java", "java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingComponent.java", "java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingComponentFactory.java", @@ -222,6 +221,7 @@ "java/src/org/chromium/chrome/browser/compositor/CompositorSurfaceManagerImpl.java", "java/src/org/chromium/chrome/browser/compositor/CompositorView.java", "java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java", + "java/src/org/chromium/chrome/browser/compositor/CompositorViewResizer.java", "java/src/org/chromium/chrome/browser/compositor/EventOffsetHandler.java", "java/src/org/chromium/chrome/browser/compositor/Invalidator.java", "java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java", @@ -1138,7 +1138,6 @@ "java/src/org/chromium/chrome/browser/omnibox/status/StatusViewBinder.java", "java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java", "java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java", - "java/src/org/chromium/chrome/browser/omnibox/suggestions/AnswersImageFetcher.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java",
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn index d002e2a0..27c9f969f 100644 --- a/chrome/android/features/autofill_assistant/BUILD.gn +++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -62,10 +62,12 @@ "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java", "java/src/org/chromium/chrome/browser/autofill_assistant/EditDistance.java", "java/src/org/chromium/chrome/browser/autofill_assistant/SizeListenableLinearLayout.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantActionsCarouselCoordinator.java", "java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantCarouselCoordinator.java", "java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantCarouselModel.java", "java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChip.java", "java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipViewHolder.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantSuggestionsCarouselCoordinator.java", "java/src/org/chromium/chrome/browser/autofill_assistant/carousel/ButtonView.java", "java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetails.java", "java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsCoordinator.java",
diff --git a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_bottom_sheet_toolbar.xml b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_bottom_sheet_toolbar.xml index 8c71681c..81a63651 100644 --- a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_bottom_sheet_toolbar.xml +++ b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_bottom_sheet_toolbar.xml
@@ -6,7 +6,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="20dp" + android:layout_height="@dimen/autofill_assistant_peek_height" android:paddingTop="8dp" android:paddingBottom="8dp" android:orientation="horizontal"
diff --git a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_button_filled.xml b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_button_filled.xml index 686da94a..c12be82c 100644 --- a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_button_filled.xml +++ b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_button_filled.xml
@@ -7,7 +7,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:minHeight="40dp" + android:minHeight="@dimen/autofill_assistant_button_height" app:chipColor="@color/filled_button_bg" app:rippleColor="@color/filled_button_ripple_color" app:cornerRadius="40dp"
diff --git a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_button_hairline.xml b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_button_hairline.xml index d952f25..83485ee 100644 --- a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_button_hairline.xml +++ b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_button_hairline.xml
@@ -7,7 +7,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:minHeight="40dp" + android:minHeight="@dimen/autofill_assistant_button_height" style="@style/AssistiveChip" app:chipColor="@color/default_text_color_inverse" app:cornerRadius="40dp"
diff --git a/chrome/android/features/autofill_assistant/java/res/values-v17/dimens.xml b/chrome/android/features/autofill_assistant/java/res/values-v17/dimens.xml index c332709..f5a7c9fa8 100644 --- a/chrome/android/features/autofill_assistant/java/res/values-v17/dimens.xml +++ b/chrome/android/features/autofill_assistant/java/res/values-v17/dimens.xml
@@ -11,4 +11,7 @@ <dimen name="autofill_assistant_info_box_spacing">16dp</dimen> <dimen name="autofill_assistant_poodle_view_size">34dp</dimen> <dimen name="autofill_assistant_filled_button_border_width">0dp</dimen> + <dimen name="autofill_assistant_peek_height">20dp</dimen> + <dimen name="autofill_assistant_button_height">40dp</dimen> + <dimen name="autofill_assistant_carousel_chips_spacing">16dp</dimen> </resources>
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java index 08ef123..498701a 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java
@@ -14,10 +14,13 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; +import org.chromium.base.ObserverList; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.autofill_assistant.R; +import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantActionsCarouselCoordinator; import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantCarouselCoordinator; import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip; +import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantSuggestionsCarouselCoordinator; import org.chromium.chrome.browser.autofill_assistant.details.AssistantDetailsCoordinator; import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderCoordinator; import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderModel; @@ -25,6 +28,7 @@ import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayModel; import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayState; import org.chromium.chrome.browser.autofill_assistant.payment.AssistantPaymentRequestCoordinator; +import org.chromium.chrome.browser.compositor.CompositorViewResizer; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController; import org.chromium.chrome.browser.widget.bottomsheet.EmptyBottomSheetObserver; @@ -33,7 +37,7 @@ /** * Coordinator responsible for the Autofill Assistant bottom bar. */ -class AssistantBottomBarCoordinator { +class AssistantBottomBarCoordinator implements CompositorViewResizer { private final AssistantModel mModel; private final BottomSheetController mBottomSheetController; private final AssistantBottomSheetContent mContent; @@ -46,6 +50,11 @@ private final AssistantCarouselCoordinator mSuggestionsCoordinator; private final AssistantCarouselCoordinator mActionsCoordinator; + private final ObserverList<CompositorViewResizer.Observer> mSizeObservers = + new ObserverList<>(); + private final int mPeekHeight; + private int mContentHeight; + @Nullable private ScrollView mOnboardingScrollView; @@ -54,6 +63,8 @@ mModel = model; mBottomSheetController = controller; mContent = new AssistantBottomSheetContent(context); + mPeekHeight = context.getResources().getDimensionPixelSize( + R.dimen.autofill_assistant_peek_height); // Instantiate child components. mHeaderCoordinator = new AssistantHeaderCoordinator( @@ -63,8 +74,9 @@ mPaymentRequestCoordinator = new AssistantPaymentRequestCoordinator(context, model.getPaymentRequestModel()); mSuggestionsCoordinator = - new AssistantCarouselCoordinator(context, model.getSuggestionsModel()); - mActionsCoordinator = new AssistantCarouselCoordinator(context, model.getActionsModel()); + new AssistantSuggestionsCarouselCoordinator(context, model.getSuggestionsModel()); + mActionsCoordinator = + new AssistantActionsCarouselCoordinator(context, model.getActionsModel()); // Add child views to bottom bar container. mContent.mBottomBarView.addView(mInfoBoxCoordinator.getView()); @@ -107,6 +119,17 @@ mContent.mToolbarView.setBackgroundColor(ApiCompatibilityUtils.getColor( context.getResources(), R.color.modern_primary_color)); } + + @Override + public void onSheetContentChanged(@Nullable BottomSheet.BottomSheetContent newContent) { + // As resizing the web content area is an expensive operation, we only shrink it by + // our peek height when our BottomSheetContent is shown. This way, the whole web + // content will be visible when the sheet is in the PEEK state. + // TODO(crbug.com/806868): Make sure this works and does not interfere with Duet + // once we are in ChromeTabbedActivity. + mContentHeight = newContent == mContent ? mPeekHeight : 0; + notifyAutofillAssistantSizeChanged(); + } }); // Show or hide the bottom sheet content when the Autofill Assistant visibility is changed. @@ -209,6 +232,27 @@ view.setLayoutParams(layoutParams); } + private void notifyAutofillAssistantSizeChanged() { + for (Observer observer : mSizeObservers) observer.onHeightChanged(mContentHeight); + } + + // Implementation of methods from AutofillAssistantSizeManager. + + @Override + public int getHeight() { + return mContentHeight; + } + + @Override + public void addObserver(Observer observer) { + mSizeObservers.addObserver(observer); + } + + @Override + public void removeObserver(Observer observer) { + mSizeObservers.removeObserver(observer); + } + // TODO(crbug.com/806868): Move this class at the top of the file once it is a static class. private class AssistantBottomSheetContent implements BottomSheet.BottomSheetContent { private final View mToolbarView;
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java index 573f17b..a3f0902 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java
@@ -39,13 +39,19 @@ // Instantiate child components. mBottomBarCoordinator = new AssistantBottomBarCoordinator(activity, mModel, controller); mKeyboardCoordinator = new AssistantKeyboardCoordinator(activity, mModel); - mOverlayCoordinator = new AssistantOverlayCoordinator(activity, mModel.getOverlayModel()); + mOverlayCoordinator = new AssistantOverlayCoordinator( + activity, mModel.getOverlayModel(), mBottomBarCoordinator); + activity.getCompositorViewHolder().addCompositorViewResizer(mBottomBarCoordinator); mModel.setVisible(true); } /** Detaches and destroys the view. */ public void destroy() { + if (mActivity.getCompositorViewHolder() != null) { + mActivity.getCompositorViewHolder().removeCompositorViewResizer(mBottomBarCoordinator); + } + mModel.setVisible(false); mOverlayCoordinator.destroy(); mBottomBarCoordinator.destroy();
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantActionsCarouselCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantActionsCarouselCoordinator.java new file mode 100644 index 0000000..bb768da5 --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantActionsCarouselCoordinator.java
@@ -0,0 +1,234 @@ +// Copyright 2018 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.chrome.browser.autofill_assistant.carousel; + +import android.content.Context; +import android.support.v7.widget.OrientationHelper; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.LayoutManager; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.chrome.autofill_assistant.R; +import org.chromium.ui.modelutil.RecyclerViewAdapter; +import org.chromium.ui.modelutil.SimpleRecyclerViewMcp; + +/** + * A coordinator responsible for suggesting chips to the user. If there is one chip to display, it + * will be centered on the screen. If there are more than one chip, all but the last one will be + * displayed from the right of the screen to the left, and the last one will be displayed at the + * left of the screen. + * + * <p>For instance, if chips = [1, 2, 3]: + * | | + * |[3] [2][1]| + * | | + * + * <p>If there are too many chips to display all of them on the screen, the carousel will scroll + * such that the last chips is fixed. For instance, if chips = [1, 2, 3, 4, 5, 6]: + * | | + * |[6][4][3][2][1]| (before) + * | | + * + * | | + * |[6][5][4][3][2]| (after horizontal scrolling from left to right) + * | | + */ +public class AssistantActionsCarouselCoordinator implements AssistantCarouselCoordinator { + private final RecyclerView mView; + + public AssistantActionsCarouselCoordinator(Context context, AssistantCarouselModel model) { + mView = new RecyclerView(context); + + int horizontalPadding = context.getResources().getDimensionPixelSize( + R.dimen.autofill_assistant_bottombar_horizontal_spacing); + int spaceBetweenViewsPx = context.getResources().getDimensionPixelSize( + R.dimen.autofill_assistant_carousel_chips_spacing); + + LayoutManager layoutManager = + new CustomLayoutManager(spaceBetweenViewsPx, horizontalPadding); + // Workaround for b/128679161. + layoutManager.setMeasurementCacheEnabled(false); + + // We set the left padding on the parent as we want the recycler view to clip its children + // on the left side. The right padding is computed by the layout manager as we don't want + // children to be clipped when scrolling them to the right. We also have to compensate the + // padding with the half space that will be added to the chip on the left of the screen. + mView.setPadding(horizontalPadding - spaceBetweenViewsPx / 2, 0, 0, 0); + mView.setLayoutManager(layoutManager); + + // TODO(crbug.com/806868): WRAP_CONTENT height should also work. + mView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + context.getResources().getDimensionPixelSize( + R.dimen.autofill_assistant_button_height))); + + mView.setAdapter(new RecyclerViewAdapter<>( + new SimpleRecyclerViewMcp<>(model.getChipsModel(), + AssistantChipViewHolder::getViewType, CustomViewHolder::bind), + CustomViewHolder::create)); + } + + @Override + public RecyclerView getView() { + return mView; + } + + /** + * Custom ViewHolder that wraps a ButtonView and a rectangular background. Setting a rectangular + * background behind the chips is necessary as chips are scrolled behind the last (fixed) one + * and need to be hidden. + */ + private static class CustomViewHolder extends RecyclerView.ViewHolder { + private final View mView; + private final AssistantChipViewHolder mDelegateViewHolder; + + public CustomViewHolder(View view, AssistantChipViewHolder delegateViewHolder) { + super(view); + mView = view; + mDelegateViewHolder = delegateViewHolder; + } + + static CustomViewHolder create(ViewGroup parent, int viewType) { + // Wrap the chip inside a rectangular FrameLayout with white background. + FrameLayout frameLayout = new FrameLayout(parent.getContext()); + frameLayout.setBackgroundColor(ApiCompatibilityUtils.getColor( + parent.getContext().getResources(), R.color.sheet_bg_color)); + frameLayout.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + AssistantChipViewHolder delegateViewHolder = + AssistantChipViewHolder.create(frameLayout, viewType); + ButtonView delegateView = delegateViewHolder.mView; + frameLayout.addView(delegateView); + + // Center the chip inside the FrameLayout. + FrameLayout.LayoutParams layoutParams = + (FrameLayout.LayoutParams) delegateView.getLayoutParams(); + layoutParams.gravity = Gravity.CENTER_HORIZONTAL; + delegateView.setLayoutParams(layoutParams); + + return new CustomViewHolder(frameLayout, delegateViewHolder); + } + + void bind(AssistantChip chip) { + mDelegateViewHolder.bind(chip); + } + } + + // TODO(crbug.com/806868): Handle RTL layouts. + // TODO(crbug.com/806868): Recycle invisible children instead of laying all of them out. + private class CustomLayoutManager extends RecyclerView.LayoutManager { + private final OrientationHelper mOrientationHelper; + private final int mPaddingEnd; + private final int mSpaceBetweenChildren; + private int mMaxScroll; + private int mScroll; + + private CustomLayoutManager(int spaceBetweenViewsPx, int paddingEndPx) { + mOrientationHelper = OrientationHelper.createHorizontalHelper(this); + mSpaceBetweenChildren = spaceBetweenViewsPx; + mPaddingEnd = paddingEndPx; + } + + @Override + public RecyclerView.LayoutParams generateDefaultLayoutParams() { + return new RecyclerView.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + } + + @Override + public boolean isAutoMeasureEnabled() { + // We need to enable auto measure to support RecyclerView's that wrap their content + // height. + return true; + } + + @Override + public boolean canScrollHorizontally() { + return mMaxScroll > 0; + } + + @Override + public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { + int itemCount = state.getItemCount(); + detachAndScrapAttachedViews(recycler); + if (itemCount == 0) { + return; + } + + int extraWidth = getWidth() - getPaddingLeft() - getPaddingRight() - mPaddingEnd + - mSpaceBetweenChildren / 2; + extraWidth -= mSpaceBetweenChildren * (itemCount - 1); + + // Add children and measure them. The extra available width will be added after the + // first chip if there are more than one, or will be used to center it if there is only + // one. + for (int i = 0; i < itemCount; i++) { + View child = recycler.getViewForPosition(i); + addView(child); + measureChildWithMargins(child, 0, 0); + int childWidth = mOrientationHelper.getDecoratedMeasurement(child); + extraWidth -= childWidth; + } + + // If we are missing space, allow scrolling. + if (extraWidth < 0) { + mMaxScroll = -extraWidth; + } else { + mMaxScroll = 0; + } + + // TODO(crbug.com/806868): When chips are added/removed, this will automatically scroll + // chips back to the initial state (with first chips visible). We might want to have a + // smart scroll that doesn't move too much when adding/removing chips. + mScroll = 0; + + int top = getPaddingTop(); + int right = getWidth() - getPaddingRight() - mPaddingEnd + mSpaceBetweenChildren / 2; + // Layout all child views but the last one from right to left. + for (int i = 0; i < getChildCount() - 1; i++) { + View child = getChildAt(i); + int width = mOrientationHelper.getDecoratedMeasurement(child); + int height = mOrientationHelper.getDecoratedMeasurementInOther(child); + int bottom = top + height; + int left = right - width - mSpaceBetweenChildren; + layoutDecoratedWithMargins(child, left, top, right, bottom); + + right = left; + } + + // Layout last child on the left. We need to layout this one after the others such that + // it sits on top of them when scrolling. + int left = getPaddingLeft(); + if (itemCount == 1) { + // Center it using extra available space. + left += extraWidth / 2; + } + + View firstChild = getChildAt(getChildCount() - 1); + right = left + mOrientationHelper.getDecoratedMeasurement(firstChild) + + mSpaceBetweenChildren; + int bottom = top + mOrientationHelper.getDecoratedMeasurementInOther(firstChild); + layoutDecoratedWithMargins(firstChild, left, top, right, bottom); + } + + @Override + public int scrollHorizontallyBy( + int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { + // dx > 0 == scroll from right to left. + int scrollBy = dx > 0 ? Math.min(mScroll, dx) : Math.max(-(mMaxScroll - mScroll), dx); + mScroll -= scrollBy; + + // Offset all children except the last one. + for (int i = 0; i < getChildCount() - 1; i++) { + getChildAt(i).offsetLeftAndRight(-scrollBy); + } + + return scrollBy; + } + } +}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantCarouselCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantCarouselCoordinator.java index 7128bbd..b0ae554 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantCarouselCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantCarouselCoordinator.java
@@ -4,163 +4,12 @@ package org.chromium.chrome.browser.autofill_assistant.carousel; -import android.content.Context; -import android.graphics.Rect; -import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.RecyclerView.ViewHolder; -import android.util.TypedValue; -import android.view.View; - -import org.chromium.base.ThreadUtils; -import org.chromium.chrome.autofill_assistant.R; -import org.chromium.chrome.browser.autofill_assistant.AbstractListObserver; -import org.chromium.ui.modelutil.RecyclerViewAdapter; -import org.chromium.ui.modelutil.SimpleRecyclerViewMcp; /** - * Coordinator responsible for suggesting chips to the user. + * A generic interface to represent a carousel coordinator to expose its view to other components. */ -public class AssistantCarouselCoordinator { - // TODO(crbug.com/806868): Get those from XML. - private static final int CHIPS_INNER_SPACING_DP = 16; - - private final LinearLayoutManager mLayoutManager; - private final RecyclerView mView; - - private boolean mCentered; - - public AssistantCarouselCoordinator(Context context, AssistantCarouselModel model) { - mLayoutManager = new LinearLayoutManager( - context, LinearLayoutManager.HORIZONTAL, /* reverseLayout= */ false); - - // Workaround for b/128679161. - mLayoutManager.setMeasurementCacheEnabled(false); - - mView = new RecyclerView(context); - mView.setLayoutManager(mLayoutManager); - mView.addItemDecoration(new SpaceItemDecoration(context)); - mView.setAdapter(new RecyclerViewAdapter<>( - new SimpleRecyclerViewMcp<>(model.getChipsModel(), - AssistantChipViewHolder::getViewType, AssistantChipViewHolder::bind), - AssistantChipViewHolder::create)); - - // Listen for changes on REVERSE_LAYOUT. - model.addObserver((source, propertyKey) -> { - if (AssistantCarouselModel.ALIGNMENT == propertyKey) { - switch (model.get(AssistantCarouselModel.ALIGNMENT)) { - case AssistantCarouselModel.Alignment.START: - mLayoutManager.setReverseLayout(false); - mCentered = false; - break; - case AssistantCarouselModel.Alignment.CENTER: - mCentered = true; - mView.invalidateItemDecorations(); - break; - case AssistantCarouselModel.Alignment.END: - mLayoutManager.setReverseLayout(true); - mCentered = false; - break; - } - } else { - assert false : "Unhandled property detected in AssistantCarouselCoordinator!"; - } - }); - - // Listen for changes on chips, and set visibility accordingly. - model.getChipsModel().addObserver(new AbstractListObserver<Void>() { - @Override - public void onDataSetChanged() { - mView.invalidateItemDecorations(); - } - }); - - // Invalidate decorations when the width of the recycler view changes. - mView.addOnLayoutChangeListener( - (view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { - if (right - left != oldRight - oldLeft) { - // We post the invalidation because ItemDecoration::getItemOffsets is called - // before this listener when the size of the recycler view changes (when - // that happens, the width of the parent is still the old width), so calling - // mView.invalidateItemDecorations() directly will not do anything. - ThreadUtils.postOnUiThread(mView::invalidateItemDecorations); - } - }); - } - - /** - * Return the view associated to this carousel. - */ - public RecyclerView getView() { - return mView; - } - - private class SpaceItemDecoration extends RecyclerView.ItemDecoration { - private final int mInnerSpacePx; - private final int mOuterSpacePx; - - SpaceItemDecoration(Context context) { - mInnerSpacePx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, - CHIPS_INNER_SPACING_DP / 2, context.getResources().getDisplayMetrics()); - mOuterSpacePx = context.getResources().getDimensionPixelSize( - R.dimen.autofill_assistant_bottombar_horizontal_spacing); - } - - @Override - public void getItemOffsets( - Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { - // We use RecyclerView.State#getItemCount() as it returns the correct value when the - // carousel is being animated. - if (mCentered && state.getItemCount() == 1) { - // We have one view and want it horizontally centered. By this time the parent - // measured width is correct (as it matches its parent), but we need to explicitly - // measure how big the chip view wants to be. - int availableWidth = parent.getMeasuredWidth(); - view.measure( - View.MeasureSpec.makeMeasureSpec(availableWidth, View.MeasureSpec.AT_MOST), - View.MeasureSpec.makeMeasureSpec( - parent.getMeasuredHeight(), View.MeasureSpec.UNSPECIFIED)); - - int margin = (availableWidth - view.getMeasuredWidth()) / 2; - outRect.left = margin; - outRect.right = margin; - return; - } - - int position = parent.getChildAdapterPosition(view); - - // If old position != NO_POSITION, it means the carousel is being animated and we should - // use that position in our logic. - ViewHolder viewHolder = parent.getChildViewHolder(view); - if (viewHolder != null && viewHolder.getOldPosition() != RecyclerView.NO_POSITION) { - position = viewHolder.getOldPosition(); - } - - if (position == RecyclerView.NO_POSITION) { - return; - } - - int left; - int right; - if (position == 0) { - left = mOuterSpacePx; - } else { - left = mInnerSpacePx; - } - - if (position == state.getItemCount() - 1) { - right = mOuterSpacePx; - } else { - right = mInnerSpacePx; - } - - if (!mLayoutManager.getReverseLayout()) { - outRect.left = left; - outRect.right = right; - } else { - outRect.left = right; - outRect.right = left; - } - } - } -} +public interface AssistantCarouselCoordinator { + /** Return the view associated to this carousel. */ + RecyclerView getView(); +} \ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipViewHolder.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipViewHolder.java index 6cdbabb2..e1901b1d 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipViewHolder.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipViewHolder.java
@@ -16,7 +16,7 @@ * ButtonView}. */ class AssistantChipViewHolder extends ViewHolder { - private final ButtonView mView; + final ButtonView mView; private AssistantChipViewHolder(ButtonView view) { super(view); @@ -42,6 +42,8 @@ assert false : "Unsupported view type " + viewType; } + view.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); if (viewType >= AssistantChip.Type.NUM_ENTRIES) { view.setEnabled(false); } @@ -66,6 +68,7 @@ mView.getPrimaryTextView().setVisibility(View.GONE); } else { mView.getPrimaryTextView().setText(text); + mView.getPrimaryTextView().setVisibility(View.VISIBLE); } mView.setOnClickListener(ignoredView -> chip.getSelectedListener().run());
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantSuggestionsCarouselCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantSuggestionsCarouselCoordinator.java new file mode 100644 index 0000000..55794d0 --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantSuggestionsCarouselCoordinator.java
@@ -0,0 +1,164 @@ +// Copyright 2018 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.chrome.browser.autofill_assistant.carousel; + +import android.content.Context; +import android.graphics.Rect; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.ViewHolder; +import android.util.TypedValue; +import android.view.View; + +import org.chromium.base.ThreadUtils; +import org.chromium.chrome.autofill_assistant.R; +import org.chromium.chrome.browser.autofill_assistant.AbstractListObserver; +import org.chromium.ui.modelutil.RecyclerViewAdapter; +import org.chromium.ui.modelutil.SimpleRecyclerViewMcp; + +/** + * Coordinator responsible for suggesting chips to the user. + */ +public class AssistantSuggestionsCarouselCoordinator implements AssistantCarouselCoordinator { + private final LinearLayoutManager mLayoutManager; + private final RecyclerView mView; + + private boolean mCentered; + + public AssistantSuggestionsCarouselCoordinator(Context context, AssistantCarouselModel model) { + mLayoutManager = new LinearLayoutManager( + context, LinearLayoutManager.HORIZONTAL, /* reverseLayout= */ false); + + // Workaround for b/128679161. + mLayoutManager.setMeasurementCacheEnabled(false); + + mView = new RecyclerView(context); + mView.setLayoutManager(mLayoutManager); + mView.addItemDecoration(new SpaceItemDecoration(context)); + mView.setAdapter(new RecyclerViewAdapter<>( + new SimpleRecyclerViewMcp<>(model.getChipsModel(), + AssistantChipViewHolder::getViewType, AssistantChipViewHolder::bind), + AssistantChipViewHolder::create)); + + // Listen for changes on REVERSE_LAYOUT. + model.addObserver((source, propertyKey) -> { + if (AssistantCarouselModel.ALIGNMENT == propertyKey) { + switch (model.get(AssistantCarouselModel.ALIGNMENT)) { + case AssistantCarouselModel.Alignment.START: + mLayoutManager.setReverseLayout(false); + mCentered = false; + break; + case AssistantCarouselModel.Alignment.CENTER: + mCentered = true; + mView.invalidateItemDecorations(); + break; + case AssistantCarouselModel.Alignment.END: + mLayoutManager.setReverseLayout(true); + mCentered = false; + break; + } + } else { + assert false : "Unhandled property detected in AssistantCarouselCoordinator!"; + } + }); + + // Listen for changes on chips, and set visibility accordingly. + model.getChipsModel().addObserver(new AbstractListObserver<Void>() { + @Override + public void onDataSetChanged() { + mView.invalidateItemDecorations(); + } + }); + + // Invalidate decorations when the width of the recycler view changes. + mView.addOnLayoutChangeListener( + (view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { + if (right - left != oldRight - oldLeft) { + // We post the invalidation because ItemDecoration::getItemOffsets is called + // before this listener when the size of the recycler view changes (when + // that happens, the width of the parent is still the old width), so calling + // mView.invalidateItemDecorations() directly will not do anything. + ThreadUtils.postOnUiThread(mView::invalidateItemDecorations); + } + }); + } + + @Override + public RecyclerView getView() { + return mView; + } + + private class SpaceItemDecoration extends RecyclerView.ItemDecoration { + private final int mInnerSpacePx; + private final int mOuterSpacePx; + + SpaceItemDecoration(Context context) { + mInnerSpacePx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + context.getResources().getDimensionPixelSize( + R.dimen.autofill_assistant_carousel_chips_spacing) + / 2, + context.getResources().getDisplayMetrics()); + mOuterSpacePx = context.getResources().getDimensionPixelSize( + R.dimen.autofill_assistant_bottombar_horizontal_spacing); + } + + @Override + public void getItemOffsets( + Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + // We use RecyclerView.State#getItemCount() as it returns the correct value when the + // carousel is being animated. + if (mCentered && state.getItemCount() == 1) { + // We have one view and want it horizontally centered. By this time the parent + // measured width is correct (as it matches its parent), but we need to explicitly + // measure how big the chip view wants to be. + int availableWidth = parent.getMeasuredWidth(); + view.measure( + View.MeasureSpec.makeMeasureSpec(availableWidth, View.MeasureSpec.AT_MOST), + View.MeasureSpec.makeMeasureSpec( + parent.getMeasuredHeight(), View.MeasureSpec.UNSPECIFIED)); + + int margin = (availableWidth - view.getMeasuredWidth()) / 2; + outRect.left = margin; + outRect.right = margin; + return; + } + + int position = parent.getChildAdapterPosition(view); + + // If old position != NO_POSITION, it means the carousel is being animated and we should + // use that position in our logic. + ViewHolder viewHolder = parent.getChildViewHolder(view); + if (viewHolder != null && viewHolder.getOldPosition() != RecyclerView.NO_POSITION) { + position = viewHolder.getOldPosition(); + } + + if (position == RecyclerView.NO_POSITION) { + return; + } + + int left; + int right; + if (position == 0) { + left = mOuterSpacePx; + } else { + left = mInnerSpacePx; + } + + if (position == state.getItemCount() - 1) { + right = mOuterSpacePx; + } else { + right = mInnerSpacePx; + } + + if (!mLayoutManager.getReverseLayout()) { + outRect.left = left; + outRect.right = right; + } else { + outRect.left = right; + outRect.right = left; + } + } + } +}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java index 5b458f5c..3cc360d 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java
@@ -7,6 +7,7 @@ import android.graphics.RectF; import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.compositor.CompositorViewResizer; import org.chromium.chrome.browser.util.AccessibilityUtil; import org.chromium.chrome.browser.widget.ScrimView; import org.chromium.chrome.browser.widget.ScrimView.ScrimParams; @@ -24,12 +25,14 @@ private final ScrimView mScrim; private boolean mScrimEnabled; - public AssistantOverlayCoordinator(ChromeActivity activity, AssistantOverlayModel model) { + public AssistantOverlayCoordinator(ChromeActivity activity, AssistantOverlayModel model, + CompositorViewResizer viewResizer) { mActivity = activity; mScrim = mActivity.getScrim(); mEventFilter = new AssistantOverlayEventFilter( mActivity, mActivity.getFullscreenManager(), mActivity.getCompositorViewHolder()); - mDrawable = new AssistantOverlayDrawable(mActivity, mActivity.getFullscreenManager()); + mDrawable = new AssistantOverlayDrawable( + mActivity, mActivity.getFullscreenManager(), viewResizer); // Listen for changes in the state. // TODO(crbug.com/806868): Bind model to view through a ViewBinder instead.
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayDrawable.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayDrawable.java index c866acf..9c1cb22 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayDrawable.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayDrawable.java
@@ -26,6 +26,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.compositor.CompositorViewResizer; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener; import org.chromium.content_public.browser.GestureListenerManager; @@ -48,8 +49,8 @@ * <p>While scrolling, it keeps track of the current scrolling offset and avoids drawing on top of * the top bar which is can be, during animations, just drawn on top of the compositor. */ -class AssistantOverlayDrawable - extends Drawable implements FullscreenListener, GestureStateListener { +class AssistantOverlayDrawable extends Drawable + implements FullscreenListener, GestureStateListener, CompositorViewResizer.Observer { private static final int FADE_DURATION_MS = 250; /** Alpha value of the background, used for animations. */ @@ -65,6 +66,12 @@ private static final int BOX_CORNER_DP = 8; private final ChromeFullscreenManager mFullscreenManager; + + /** + * The {@link CompositorViewResizer} associated to the Autofill Assistant BottomSheet content. + */ + private final CompositorViewResizer mViewResizer; + private final Paint mBackground; private final Paint mBoxStroke; private final Paint mBoxClear; @@ -129,8 +136,10 @@ private AssistantOverlayDelegate mDelegate; private GestureListenerManager mGestureListenerManager; - AssistantOverlayDrawable(Context context, ChromeFullscreenManager fullscreenManager) { + AssistantOverlayDrawable(Context context, ChromeFullscreenManager fullscreenManager, + CompositorViewResizer viewResizer) { mFullscreenManager = fullscreenManager; + mViewResizer = viewResizer; DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); @@ -162,6 +171,7 @@ TypedValue.COMPLEX_UNIT_DIP, BOX_CORNER_DP, displayMetrics); mFullscreenManager.addListener(this); + mViewResizer.addObserver(this); } void setDelegate(AssistantOverlayDelegate delegate) { @@ -182,6 +192,7 @@ void destroy() { setWebContents(null); mFullscreenManager.removeListener(this); + mViewResizer.removeObserver(this); mDelegate = null; } @@ -265,7 +276,7 @@ Rect bounds = getBounds(); int width = bounds.width(); int yBottom = bounds.height() - - (int) (mFullscreenManager.getBottomControlsHeight() + - (int) (mFullscreenManager.getBottomControlsHeight() + mViewResizer.getHeight() - mFullscreenManager.getBottomControlOffset()); // Don't draw over the top or bottom bars. @@ -329,6 +340,11 @@ invalidateSelf(); } + @Override + public void onHeightChanged(int height) { + invalidateSelf(); + } + /** Called at the beginning of a scroll gesture triggered by the browser. */ @Override public void onScrollStarted(int scrollOffsetY, int scrollExtentY) {
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java index d4bd5d0..cb3dfbe 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
@@ -178,8 +178,12 @@ testChips(inOrder, assistantCoordinator.getModel().getSuggestionsModel(), assistantCoordinator.getBottomBarCoordinator().getSuggestionsCoordinator()); - testChips(inOrder, assistantCoordinator.getModel().getActionsModel(), - assistantCoordinator.getBottomBarCoordinator().getActionsCoordinator()); + // TODO(crbug.com/806868): Fix test of actions carousel. This is currently broken as chips + // are displayed in the reversed order in the actions carousel and calling + // View#performClick() does not work as chips in the actions carousel are wrapped into a + // FrameLayout that does not react to clicks. + // testChips(inOrder, assistantCoordinator.getModel().getActionsModel(), + // assistantCoordinator.getBottomBarCoordinator().getActionsCoordinator()); // Show movie details. String movieTitle = "testTitle";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/BitmapCache.java b/chrome/android/java/src/org/chromium/chrome/browser/BitmapCache.java index d7b2d53..67b9806 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/BitmapCache.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/BitmapCache.java
@@ -121,6 +121,14 @@ sDeduplicationCache.put(key, new WeakReference<>(bitmap)); } + /** + * Evict all bitmaps from the cache. + */ + public void clear() { + getBitmapCache().evictAll(); + scheduleDeduplicationCache(); + } + /** @return The total number of bytes taken by the bitmaps in this cache. */ public int size() { return getBitmapCache().size();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index 99061962..3d15de49 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -506,7 +506,7 @@ ((BottomContainer) findViewById(R.id.bottom_container)) .initialize(mFullscreenManager, - mManualFillingComponent.getKeyboardExtensionSizeManager()); + mManualFillingComponent.getKeyboardExtensionViewResizer()); // If onStart was called before postLayoutInflation (because inflation was done in a // background thread) then make sure to call the relevant methods belatedly. @@ -1450,8 +1450,8 @@ mManualFillingComponent.initialize(getWindowAndroid(), findViewById(R.id.keyboard_accessory_stub), findViewById(R.id.keyboard_accessory_sheet_stub)); - getCompositorViewHolder().setKeyboardExtensionView( - mManualFillingComponent.getKeyboardExtensionSizeManager()); + getCompositorViewHolder().addCompositorViewResizer( + mManualFillingComponent.getKeyboardExtensionViewResizer()); if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_ENGAGEMENT_REPORTING_ANDROID)) { // The lifetime of this object is managed by the lifecycle dispatcher.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardExtensionSizeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardExtensionSizeManager.java deleted file mode 100644 index 9850b8b..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardExtensionSizeManager.java +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2018 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.chrome.browser.autofill.keyboard_accessory; - -import android.support.annotation.Px; - -/** - * This class holds the size of any extension to or even replacement for a keyboard. The height can - * be used to either compute an offset for bottom bars (e.g. CCTs or PWAs) or to push up the content - * area. - */ -public interface KeyboardExtensionSizeManager { - /** - * Observers are notified when the size of the keyboard extension changes. - */ - interface Observer { - /** - * Called when the extension height changes. - * @param keyboardHeight The new height of the keyboard extension. - */ - void onKeyboardExtensionHeightChanged(@Px int keyboardHeight); - } - - /** - * Returns the height of the keyboard extension. - * @return A height in pixels. - */ - @Px - int getKeyboardExtensionHeight(); - - /** - * Registered observers are called whenever the extension size changes until unregistered. - * Does not guarantee order. - * @param observer a {@link KeyboardExtensionSizeManager.Observer}. - */ - void addObserver(Observer observer); - - /** - * Removes a registered observer if present. - * @param observer a registered {@link KeyboardExtensionSizeManager.Observer}. - */ - void removeObserver(Observer observer); -} \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardExtensionSizeManagerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardExtensionViewResizer.java similarity index 80% rename from chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardExtensionSizeManagerImpl.java rename to chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardExtensionViewResizer.java index 86e9a18..9381d44 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardExtensionSizeManagerImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardExtensionViewResizer.java
@@ -7,17 +7,18 @@ import android.support.annotation.Px; import org.chromium.base.ObserverList; +import org.chromium.chrome.browser.compositor.CompositorViewResizer; /** * This class is used by {@link ManualFillingMediator} to provide the combined height of * KeyboardAccessoryCoordinator and AccessorySheetCoordinator. */ -class KeyboardExtensionSizeManagerImpl implements KeyboardExtensionSizeManager { +class KeyboardExtensionViewResizer implements CompositorViewResizer { private int mHeight; private final ObserverList<Observer> mObservers = new ObserverList<>(); @Override - public @Px int getKeyboardExtensionHeight() { + public @Px int getHeight() { return mHeight; } @@ -34,6 +35,6 @@ void setKeyboardExtensionHeight(@Px int newKeyboardExtensionHeight) { if (mHeight == newKeyboardExtensionHeight) return; mHeight = newKeyboardExtensionHeight; - for (Observer observer : mObservers) observer.onKeyboardExtensionHeightChanged(mHeight); + for (Observer observer : mObservers) observer.onHeightChanged(mHeight); } } \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingComponent.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingComponent.java index 4c443867..0d0c501 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingComponent.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingComponent.java
@@ -9,6 +9,7 @@ import org.chromium.chrome.browser.autofill.keyboard_accessory.data.KeyboardAccessoryData; import org.chromium.chrome.browser.autofill.keyboard_accessory.data.PropertyProvider; +import org.chromium.chrome.browser.compositor.CompositorViewResizer; import org.chromium.components.autofill.AutofillDelegate; import org.chromium.components.autofill.AutofillSuggestion; import org.chromium.ui.DropdownPopupWindow; @@ -112,12 +113,12 @@ void onPause(); /** - * Returns a size manager that allows to access the combined height of + * Returns a {@link CompositorViewResizer} that allows to access the combined height of * KeyboardAccessoryCoordinator and AccessorySheetCoordinator, and to be * notified when it changes. - * @return A {@link KeyboardExtensionSizeManager}. + * @return A {@link CompositorViewResizer}. */ - KeyboardExtensionSizeManager getKeyboardExtensionSizeManager(); + CompositorViewResizer getKeyboardExtensionViewResizer(); /** * Returns whether the Keyboard is replaced by an accessory sheet or is about to do so.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingCoordinator.java index 36f854a..594a53d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingCoordinator.java
@@ -14,6 +14,7 @@ import org.chromium.chrome.browser.autofill.keyboard_accessory.data.KeyboardAccessoryData; import org.chromium.chrome.browser.autofill.keyboard_accessory.data.PropertyProvider; import org.chromium.chrome.browser.autofill.keyboard_accessory.sheet_component.AccessorySheetCoordinator; +import org.chromium.chrome.browser.compositor.CompositorViewResizer; import org.chromium.components.autofill.AutofillDelegate; import org.chromium.components.autofill.AutofillSuggestion; import org.chromium.ui.DropdownPopupWindow; @@ -134,8 +135,8 @@ } @Override - public KeyboardExtensionSizeManager getKeyboardExtensionSizeManager() { - return mMediator.getKeyboardExtensionSizeManager(); + public CompositorViewResizer getKeyboardExtensionViewResizer() { + return mMediator.getKeyboardExtensionViewResizer(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingMediator.java index f520765..77466515 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingMediator.java
@@ -38,6 +38,7 @@ import org.chromium.chrome.browser.autofill.keyboard_accessory.sheet_tabs.CreditCardAccessorySheetCoordinator; import org.chromium.chrome.browser.autofill.keyboard_accessory.sheet_tabs.PasswordAccessorySheetCoordinator; import org.chromium.chrome.browser.compositor.CompositorViewHolder; +import org.chromium.chrome.browser.compositor.CompositorViewResizer; import org.chromium.chrome.browser.compositor.layouts.Layout; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; import org.chromium.chrome.browser.compositor.layouts.SceneChangeObserver; @@ -72,8 +73,8 @@ private PropertyModel mModel = ManualFillingProperties.createFillingModel(); private WindowAndroid mWindowAndroid; private Supplier<InsetObserverView> mInsetObserverViewSupplier; - private final KeyboardExtensionSizeManagerImpl mKeyboardExtensionSizeManager = - new KeyboardExtensionSizeManagerImpl(); + private final KeyboardExtensionViewResizer mKeyboardExtensionViewResizer = + new KeyboardExtensionViewResizer(); private final ManualFillingStateCache mStateCache = new ManualFillingStateCache(); private final HashSet<Tab> mObservedTabs = new HashSet<>(); private KeyboardAccessoryCoordinator mKeyboardAccessory; @@ -293,14 +294,14 @@ WebContents webContents = mActivity.getCurrentWebContents(); if (webContents == null) return false; float height = webContents.getHeight(); // getHeight actually returns dip, not Px! - height += mKeyboardExtensionSizeManager.getKeyboardExtensionHeight() + height += mKeyboardExtensionViewResizer.getHeight() / mWindowAndroid.getDisplay().getDipScale(); return height >= MINIMAL_AVAILABLE_VERTICAL_SPACE && webContents.getWidth() >= MINIMAL_AVAILABLE_HORIZONTAL_SPACE; } - KeyboardExtensionSizeManager getKeyboardExtensionSizeManager() { - return mKeyboardExtensionSizeManager; + CompositorViewResizer getKeyboardExtensionViewResizer() { + return mKeyboardExtensionViewResizer; } private void onPropertyChanged(PropertyObservable<PropertyKey> source, PropertyKey property) { @@ -468,7 +469,7 @@ newControlsOffset += mAccessorySheet.getHeight(); } mKeyboardAccessory.setBottomOffset(newControlsOffset); - mKeyboardExtensionSizeManager.setKeyboardExtensionHeight(newControlsHeight); + mKeyboardExtensionViewResizer.setKeyboardExtensionHeight(newControlsHeight); mActivity.getFullscreenManager().updateViewportSize(); } @@ -557,7 +558,7 @@ float density = mWindowAndroid.getDisplay().getDipScale(); // The maximal height for the sheet ensures a minimal amount of WebContents space. @Px - int maxHeight = mKeyboardExtensionSizeManager.getKeyboardExtensionHeight(); + int maxHeight = mKeyboardExtensionViewResizer.getHeight(); maxHeight += Math.round(density * webContents.getHeight()); maxHeight -= Math.round(density * MINIMAL_AVAILABLE_VERTICAL_SPACE); maxHeight -= calculateAccessoryBarHeight();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java index cba212d..3c99c11 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -15,7 +15,6 @@ import android.os.Bundle; import android.os.Handler; import android.support.annotation.Nullable; -import android.support.annotation.Px; import android.support.v4.view.ViewCompat; import android.support.v4.view.accessibility.AccessibilityEventCompat; import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; @@ -35,7 +34,6 @@ import org.chromium.base.compat.ApiHelperForO; import org.chromium.chrome.R; import org.chromium.chrome.browser.InsetObserverView; -import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardExtensionSizeManager; import org.chromium.chrome.browser.compositor.Invalidator.Client; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; import org.chromium.chrome.browser.compositor.layouts.LayoutManagerHost; @@ -66,7 +64,9 @@ import org.chromium.ui.resources.dynamics.DynamicResourceLoader; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * This class holds a {@link CompositorView}. This level of indirection is needed to benefit from @@ -78,7 +78,7 @@ public class CompositorViewHolder extends FrameLayout implements ContentOffsetProvider, LayoutManagerHost, LayoutRenderHost, Invalidator.Host, FullscreenListener, InsetObserverView.WindowInsetObserver, - KeyboardExtensionSizeManager.Observer { + CompositorViewResizer.Observer { private static final long SYSTEM_UI_VIEWPORT_UPDATE_DELAY_MS = 500; private EventOffsetHandler mEventOffsetHandler; @@ -111,7 +111,7 @@ /** The toolbar control container. **/ private ControlContainer mControlContainer; - private @Nullable KeyboardExtensionSizeManager mKeyboardExtensionSizeManager; + private Set<CompositorViewResizer> mViewResizers = new HashSet<>(); private InsetObserverView mInsetObserverView; private boolean mShowingFullscreen; private Runnable mSystemUiFullscreenResizeRunnable; @@ -414,35 +414,30 @@ public void onSafeAreaChanged(Rect area) {} /** - * Allows to set (or unset if called with null) the {@link KeyboardExtensionSizeManager} that - * provides the dimensions of any keyboard extensions or replacements. Registers an observer to - * react to size changes immediately. - * @param manager A {@link KeyboardExtensionSizeManager}. Optional. + * Add a {@link CompositorViewResizer} whose height should be taken into account when computing + * the size of the content area. Registers an observer to react to size changes immediately. + * @param viewResizer A {@link CompositorViewResizer}. */ - public void setKeyboardExtensionView(@Nullable KeyboardExtensionSizeManager manager) { - if (mKeyboardExtensionSizeManager != null) { - mKeyboardExtensionSizeManager.removeObserver(this); - } - mKeyboardExtensionSizeManager = manager; - if (mKeyboardExtensionSizeManager != null) { - mKeyboardExtensionSizeManager.addObserver(this); - onViewportChanged(); - } - } - - @Override - public void onKeyboardExtensionHeightChanged(int keyboardHeight) { - onUpdateViewportSize(); + public void addCompositorViewResizer(CompositorViewResizer viewResizer) { + mViewResizers.add(viewResizer); + viewResizer.addObserver(this); + onViewportChanged(); } /** - * Returns the combined height of all extensions to or replacements of the keyboard which - * consume space at the bottom of the content area. - * @return the full height in pixels. + * Remove a {@link CompositorViewResizer} that was previously added via {@link + * #addCompositorViewResizer(CompositorViewResizer)}. + * @param viewResizer A {@link CompositorViewResizer}. */ - public @Px int getKeyboardExtensionsHeight() { - if (mKeyboardExtensionSizeManager == null) return 0; - return mKeyboardExtensionSizeManager.getKeyboardExtensionHeight(); + public void removeCompositorViewResizer(CompositorViewResizer viewResizer) { + viewResizer.removeObserver(this); + mViewResizers.remove(viewResizer); + onViewportChanged(); + } + + @Override + public void onHeightChanged(int height) { + onUpdateViewportSize(); } /** @@ -637,7 +632,20 @@ int controlsHeight = controlsResizeView() ? getTopControlsHeightPixels() + getBottomControlsHeightPixels() : 0; - controlsHeight += getKeyboardExtensionsHeight(); + + int resizerHeight = 0; + for (CompositorViewResizer viewResizer : mViewResizers) { + int resizerImplHeight = viewResizer.getHeight(); + if (resizerImplHeight != 0) { + if (resizerHeight != 0) { + throw new IllegalStateException( + "Multiple CompositorViewResizer with height > 0 are not supported."); + } + resizerHeight = resizerImplHeight; + } + } + controlsHeight += resizerHeight; + if (isAttachedToWindow(view)) { webContents.setSize(w, h - controlsHeight); } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewResizer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewResizer.java new file mode 100644 index 0000000..32b3fc61 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewResizer.java
@@ -0,0 +1,45 @@ +// Copyright 2018 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.chrome.browser.compositor; + +import android.support.annotation.Px; + +/** + * This class holds the size of any component shown at the bottom of the screen. The height can be + * used to either compute an offset for bottom bars (e.g. CCTs or PWAs) or to push up the content + * area. + */ +public interface CompositorViewResizer { + /** + * Observers are notified when the size of the component changes. + */ + interface Observer { + /** + * Called when the component height changes. + * @param height The new height of the component. + */ + void onHeightChanged(@Px int height); + } + + /** + * Returns the height of the component. + * @return A height in pixels. + */ + @Px + int getHeight(); + + /** + * Registered observers are called whenever the components size changes until unregistered. + * Does not guarantee order. + * @param observer a {@link CompositorViewResizer.Observer}. + */ + void addObserver(Observer observer); + + /** + * Removes a registered observer if present. + * @param observer a registered {@link CompositorViewResizer.Observer}. + */ + void removeObserver(Observer observer); +} \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java index bad3caf5..f7823ef 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
@@ -345,9 +345,8 @@ if (mBottomBarView == null) return; // Check bottom bar view but don't inflate it. // Hide the container of the bottom bar while the extension is showing. This doesn't // affect the content. - boolean keyboardExtensionHidesBottomBar = mActivity.getManualFillingComponent() - .getKeyboardExtensionSizeManager() - .getKeyboardExtensionHeight() + boolean keyboardExtensionHidesBottomBar = + mActivity.getManualFillingComponent().getKeyboardExtensionViewResizer().getHeight() > 0; if (keyboardExtensionHidesBottomBar) { getBottomBarView().setVisibility(View.GONE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/empty/EmptyCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/empty/EmptyCoordinator.java index 963e1edc..907a88c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/empty/EmptyCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/empty/EmptyCoordinator.java
@@ -15,7 +15,6 @@ import org.chromium.chrome.browser.download.home.filter.Filters.FilterType; import org.chromium.chrome.browser.download.home.filter.OfflineItemFilterObserver; import org.chromium.chrome.browser.download.home.filter.OfflineItemFilterSource; -import org.chromium.chrome.browser.offlinepages.prefetch.PrefetchConfiguration; import org.chromium.components.offline_items_collection.OfflineItem; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; @@ -97,17 +96,10 @@ int iconId; if (mShowingPrefetch) { iconId = R.drawable.ic_library_news_feed; - - if (PrefetchConfiguration.isPrefetchingEnabled()) { - textId = mInSearchMode ? R.string.download_manager_prefetch_tab_no_results - : R.string.download_manager_prefetch_tab_empty; - } else { - textId = R.string.download_manager_enable_prefetch_message; - } + textId = R.string.download_manager_prefetch_tab_empty; } else { iconId = R.drawable.downloads_big; - textId = mInSearchMode ? R.string.download_manager_no_results - : R.string.download_manager_ui_empty; + textId = R.string.download_manager_no_downloads; } mModel.set(EmptyProperties.EMPTY_TEXT_RES_ID, textId);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java index afff8f2..bc78140 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java
@@ -110,6 +110,9 @@ } @Override + public void clear() {} + + @Override public @ImageFetcherConfig int getConfig() { return ImageFetcherConfig.DISK_CACHE_ONLY; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java index d05a052..114652c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java
@@ -19,6 +19,7 @@ */ public abstract class ImageFetcher { // All UMA client names collected here to prevent duplicates. + public static final String ANSWER_SUGGESTIONS_UMA_CLIENT_NAME = "AnswerSuggestions"; public static final String ASSISTANT_DETAILS_UMA_CLIENT_NAME = "AssistantDetails"; public static final String ASSISTANT_INFO_BOX_UMA_CLIENT_NAME = "AssistantInfoBox"; public static final String CONTEXTUAL_SUGGESTIONS_UMA_CLIENT_NAME = "ContextualSuggestions"; @@ -100,6 +101,11 @@ } /** + * Clear the cache of any bitmaps that may be in-memory. + */ + public abstract void clear(); + + /** * Returns the type of Image Fetcher this is based on class arrangements. See * image_fetcher_service.h for a detailed description of the available configurations. *
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java index 748fd4a..14b76ab3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java
@@ -16,25 +16,28 @@ /** * Alias for createImageFetcher below. - * - * @param config The type of ImageFetcher you need. - * @return The correct ImageFetcher according to the provided config. */ public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config) { - return createImageFetcher(config, null); + return createImageFetcher(config, ImageFetcherBridge.getInstance(), null, + InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE); } /** * Alias for createImageFetcher below. - * - * @param config The type of ImageFetcher you need. - * @param discardableReferencePool Used to store images in-memory. - * @return The correct ImageFetcher according to the provided config. */ public static ImageFetcher createImageFetcher( @ImageFetcherConfig int config, DiscardableReferencePool discardableReferencePool) { - return createImageFetcher( - config, discardableReferencePool, ImageFetcherBridge.getInstance()); + return createImageFetcher(config, ImageFetcherBridge.getInstance(), + discardableReferencePool, InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE); + } + + /** + * Alias for createImageFetcher below. + */ + public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config, + DiscardableReferencePool discardableReferencePool, int inMemoryCacheSize) { + return createImageFetcher(config, ImageFetcherBridge.getInstance(), + discardableReferencePool, inMemoryCacheSize); } /** @@ -42,13 +45,14 @@ * config that you must destroy. * * @param config The type of ImageFetcher you need. - * @param discardableReferencePool Used to store images in-memory. * @param imageFetcherBridge Bridge to use. + * @param discardableReferencePool Used to store images in-memory. + * @param inMemoryCacheSize The size of the in memory cache (in bytes). * @return The correct ImageFetcher according to the provided config. */ public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config, - DiscardableReferencePool discardableReferencePool, - ImageFetcherBridge imageFetcherBridge) { + ImageFetcherBridge imageFetcherBridge, + DiscardableReferencePool discardableReferencePool, int inMemoryCacheSize) { // TODO(crbug.com/947191):Allow server-side configuration image fetcher clients. switch (config) { case ImageFetcherConfig.NETWORK_ONLY: @@ -64,15 +68,15 @@ case ImageFetcherConfig.IN_MEMORY_ONLY: assert discardableReferencePool != null; return new InMemoryCachedImageFetcher( - createImageFetcher( - ImageFetcherConfig.NETWORK_ONLY, null, imageFetcherBridge), - discardableReferencePool); + createImageFetcher(ImageFetcherConfig.NETWORK_ONLY, imageFetcherBridge, + discardableReferencePool, inMemoryCacheSize), + discardableReferencePool, inMemoryCacheSize); case ImageFetcherConfig.IN_MEMORY_WITH_DISK_CACHE: assert discardableReferencePool != null; return new InMemoryCachedImageFetcher( - createImageFetcher( - ImageFetcherConfig.DISK_CACHE_ONLY, null, imageFetcherBridge), - discardableReferencePool); + createImageFetcher(ImageFetcherConfig.DISK_CACHE_ONLY, imageFetcherBridge, + discardableReferencePool, inMemoryCacheSize), + discardableReferencePool, inMemoryCacheSize); default: return null; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java index e1bc4b8..2cecdfe 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java
@@ -19,7 +19,7 @@ * ImageFetcher implementation with an in-memory cache. Can also be configured to use a disk cache. */ public class InMemoryCachedImageFetcher extends ImageFetcher { - private static final int DEFAULT_CACHE_SIZE = 20 * ConversionUtils.BYTES_PER_MEGABYTE; // 20mb + public static final int DEFAULT_CACHE_SIZE = 20 * ConversionUtils.BYTES_PER_MEGABYTE; // 20mb private static final float PORTION_OF_AVAILABLE_MEMORY = 1.f / 8.f; // Will do the work if the image isn't cached in memory. @@ -111,6 +111,11 @@ } @Override + public void clear() { + mBitmapCache.clear(); + } + + @Override public @ImageFetcherConfig int getConfig() { return mConfig; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java index ed0b04e..3954166 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java
@@ -43,6 +43,9 @@ } @Override + public void clear() {} + + @Override public @ImageFetcherConfig int getConfig() { return ImageFetcherConfig.NETWORK_ONLY; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java index 03cee93..0b07d9d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
@@ -25,6 +25,11 @@ */ public interface LocationBar extends UrlBarDelegate { /** + * Cleanup resources when this goes out of scope. + */ + void destroy(); + + /** * Handles native dependent initialization for this class. */ void onNativeLibraryReady();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index b670f3a..cea7caa 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -193,6 +193,12 @@ } @Override + public void destroy() { + mAutocompleteCoordinator.destroy(); + mAutocompleteCoordinator = null; + } + + @Override protected void onFinishInflate() { super.onFinishInflate();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AnswersImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AnswersImageFetcher.java deleted file mode 100644 index 39a6122..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AnswersImageFetcher.java +++ /dev/null
@@ -1,104 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.omnibox.suggestions; - -import android.graphics.Bitmap; -import android.support.v4.util.LruCache; - -import org.chromium.base.annotations.CalledByNative; -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.util.ConversionUtils; - -/** - * Provides access to images used by Answers in Suggest. - */ -public class AnswersImageFetcher { - // Matches the value in BitmapFetcherService. - private static final int INVALID_IMAGE_REQUEST_ID = 0; - private static final int MAX_CACHE_SIZE = 500 * ConversionUtils.BYTES_PER_KILOBYTE; - - /** - * Observer for updating an image when it is available. - */ - public interface AnswersImageObserver { - /** - * Called when the image is updated. - * - * @param bitmap the image - */ - @CalledByNative("AnswersImageObserver") - void onAnswersImageChanged(Bitmap bitmap); - } - - // Intentionally not using BitmapCache as that does not cache for low end devices (it ensures - // the bitmaps are de-dups across instances, but discards them if there is not an active - // reference to one). - private final LruCache<String, Bitmap> mBitmapCache = - new LruCache<String, Bitmap>(MAX_CACHE_SIZE) { - @Override - protected int sizeOf(String key, Bitmap value) { - return value.getByteCount(); - } - }; - - /** - * Clears the cached answer images. - */ - public void clearCache() { - mBitmapCache.evictAll(); - } - - /** - * Request image, observer is notified when image is loaded. - * @param profile Profile that the request is for. - * @param imageUrl URL for image data. - * @param observer Observer to be notified when image is updated. The C++ side will hold a - * strong reference to this. - * @return A request_id. - */ - public int requestAnswersImage( - Profile profile, String imageUrl, AnswersImageObserver observer) { - if (!profile.isOffTheRecord()) { - Bitmap bitmap = mBitmapCache.get(imageUrl); - if (bitmap != null) { - observer.onAnswersImageChanged(bitmap); - return INVALID_IMAGE_REQUEST_ID; - } - } - AnswersImageObserver cacheObserver = observer; - if (!profile.isOffTheRecord()) { - cacheObserver = new AnswersImageObserver() { - @Override - public void onAnswersImageChanged(Bitmap bitmap) { - if (bitmap == null) return; - mBitmapCache.put(imageUrl, bitmap); - observer.onAnswersImageChanged(bitmap); - } - }; - } - return nativeRequestAnswersImage(profile, imageUrl, cacheObserver); - } - - /** - * Cancel a pending image request. - * @param profile Profile the request was issued for. - * @param requestId The ID of the request to be cancelled. - */ - public void cancelAnswersImageRequest(Profile profile, int requestId) { - nativeCancelAnswersImageRequest(profile, requestId); - } - - /** - * Requests an image at |imageUrl| for the given |profile| with |observer| being notified. - * @returns an AnswersImageRequest - */ - private static native int nativeRequestAnswersImage( - Profile profile, String imageUrl, AnswersImageObserver observer); - - /** - * Cancels a pending request. - */ - private static native void nativeCancelAnswersImageRequest(Profile profile, int requestId); -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java index a77cf3d..74624f95 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
@@ -50,7 +50,7 @@ */ public class AutocompleteCoordinator implements UrlFocusChangeListener, UrlTextChangeListener { private final ViewGroup mParent; - private final AutocompleteMediator mMediator; + private AutocompleteMediator mMediator; private ListView mListView; @@ -170,6 +170,11 @@ new AutocompleteMediator(context, delegate, urlBarEditingTextProvider, listModel); } + public void destroy() { + mMediator.destroy(); + mMediator = null; + } + private ViewProvider<SuggestionListViewHolder> createViewProvider(Context context) { return new ViewProvider<SuggestionListViewHolder>() { private List<Callback<SuggestionListViewHolder>> mCallbacks = new ArrayList<>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java index 77d63a4..e63d273 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -93,7 +93,7 @@ private final Handler mHandler; private final BasicSuggestionProcessor mBasicSuggestionProcessor; private EditUrlSuggestionProcessor mEditUrlProcessor; - private final AnswerSuggestionProcessor mAnswerSuggestionProcessor; + private AnswerSuggestionProcessor mAnswerSuggestionProcessor; private ToolbarDataProvider mDataProvider; private boolean mNativeInitialized; @@ -157,6 +157,11 @@ delegate, (suggestion) -> onSelection(suggestion, 0)); } + public void destroy() { + mAnswerSuggestionProcessor.destroy(); + mAnswerSuggestionProcessor = null; + } + @Override public void onStartWithNative() {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java index 7ddabaed..4be65e7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
@@ -11,10 +11,13 @@ import android.view.View; import org.chromium.base.ThreadUtils; +import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.image_fetcher.ImageFetcher; +import org.chromium.chrome.browser.image_fetcher.ImageFetcherConfig; +import org.chromium.chrome.browser.image_fetcher.ImageFetcherFactory; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider; -import org.chromium.chrome.browser.omnibox.suggestions.AnswersImageFetcher; import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinator.SuggestionProcessor; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType; @@ -24,6 +27,7 @@ import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties.SuggestionIcon; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties.SuggestionTextContainer; +import org.chromium.chrome.browser.util.ConversionUtils; import org.chromium.components.omnibox.AnswerType; import org.chromium.components.omnibox.SuggestionAnswer; import org.chromium.ui.modelutil.PropertyModel; @@ -35,10 +39,12 @@ /** A class that handles model and view creation for the most commonly used omnibox suggestion. */ public class AnswerSuggestionProcessor implements SuggestionProcessor { + private static final int MAX_CACHE_SIZE = 500 * ConversionUtils.BYTES_PER_KILOBYTE; + private final Map<String, List<PropertyModel>> mPendingAnswerRequestUrls; private final Context mContext; private final SuggestionHost mSuggestionHost; - private final AnswersImageFetcher mImageFetcher; + private ImageFetcher mImageFetcher; private final UrlBarEditingTextStateProvider mUrlBarEditingTextProvider; private boolean mEnableNewAnswerLayout; @@ -51,10 +57,16 @@ mContext = context; mSuggestionHost = suggestionHost; mPendingAnswerRequestUrls = new HashMap<>(); - mImageFetcher = new AnswersImageFetcher(); mUrlBarEditingTextProvider = editingTextProvider; } + public void destroy() { + if (mImageFetcher != null) { + mImageFetcher.destroy(); + mImageFetcher = null; + } + } + @Override public boolean doesProcessSuggestion(OmniboxSuggestion suggestion) { // Calculation answers are specific in a way that these are basic suggestions, but processed @@ -96,7 +108,10 @@ @Override public void onUrlFocusChange(boolean hasFocus) { - if (!hasFocus) mImageFetcher.clearCache(); + // This clear is necessary for memory as well as clearing when switching to/from incognito. + if (!hasFocus && mImageFetcher != null) { + mImageFetcher.clear(); + } } private void maybeFetchAnswerIcon(OmniboxSuggestion suggestion, PropertyModel model) { @@ -117,30 +132,35 @@ return; } + if (mImageFetcher == null) { + mImageFetcher = ImageFetcherFactory.createImageFetcher( + ImageFetcherConfig.IN_MEMORY_ONLY, + ((ChromeApplication) mContext.getApplicationContext()).getReferencePool(), + MAX_CACHE_SIZE); + } + List<PropertyModel> models = new ArrayList<>(); models.add(model); mPendingAnswerRequestUrls.put(url, models); - mImageFetcher.requestAnswersImage(mSuggestionHost.getCurrentProfile(), url, - new AnswersImageFetcher.AnswersImageObserver() { - @Override - public void onAnswersImageChanged(Bitmap bitmap) { - ThreadUtils.assertOnUiThread(); - List<PropertyModel> models = mPendingAnswerRequestUrls.remove(url); - boolean didUpdate = false; - for (int i = 0; i < models.size(); i++) { - PropertyModel model = models.get(i); - if (!mSuggestionHost.isActiveModel(model)) continue; + mImageFetcher.fetchImage( + url, ImageFetcher.ANSWER_SUGGESTIONS_UMA_CLIENT_NAME, (Bitmap bitmap) -> { + ThreadUtils.assertOnUiThread(); - if (mEnableNewAnswerLayout) { - model.set(AnswerSuggestionViewProperties.ANSWER_IMAGE, bitmap); - } else { - model.set(SuggestionViewProperties.ANSWER_IMAGE, bitmap); - } - didUpdate = true; + List<PropertyModel> currentModels = mPendingAnswerRequestUrls.remove(url); + boolean didUpdate = false; + for (int i = 0; i < currentModels.size(); i++) { + PropertyModel currentModel = currentModels.get(i); + if (!mSuggestionHost.isActiveModel(currentModel)) continue; + + if (mEnableNewAnswerLayout) { + model.set(AnswerSuggestionViewProperties.ANSWER_IMAGE, bitmap); + } else { + model.set(SuggestionViewProperties.ANSWER_IMAGE, bitmap); } - if (didUpdate) mSuggestionHost.notifyPropertyModelsChanged(); + didUpdate = true; } + if (didUpdate) mSuggestionHost.notifyPropertyModelsChanged(); }); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/BottomContainer.java b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/BottomContainer.java index 8abe980..b64c5d7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/BottomContainer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/BottomContainer.java
@@ -8,7 +8,7 @@ import android.util.AttributeSet; import android.widget.FrameLayout; -import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardExtensionSizeManager; +import org.chromium.chrome.browser.compositor.CompositorViewResizer; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet; @@ -19,12 +19,12 @@ * bottom controls' offset changes. */ public class BottomContainer - extends FrameLayout implements FullscreenListener, KeyboardExtensionSizeManager.Observer { + extends FrameLayout implements FullscreenListener, CompositorViewResizer.Observer { /** The {@link ChromeFullscreenManager} to listen for controls offset changes. */ private ChromeFullscreenManager mFullscreenManager; - /** A {@link KeyboardExtensionSizeManager} to listen to for keyboard extension size changes. */ - private KeyboardExtensionSizeManager mKeyboardExtensionSizeManager; + /** A {@link CompositorViewResizer} to listen to for keyboard extension size changes. */ + private CompositorViewResizer mKeyboardExtensionSizeManager; /** The desired Y offset if unaffected by other UI. */ private float mBaseYOffset; @@ -43,7 +43,7 @@ * Initializes this container. */ public void initialize(ChromeFullscreenManager fullscreenManager, - KeyboardExtensionSizeManager keyboardExtensionSizeManager) { + CompositorViewResizer keyboardExtensionSizeManager) { mFullscreenManager = fullscreenManager; mFullscreenManager.addListener(this); mKeyboardExtensionSizeManager = keyboardExtensionSizeManager; @@ -70,9 +70,9 @@ }); } - // KeyboardExtensionSizeManager methods + // CompositorViewResizer methods @Override - public void onKeyboardExtensionHeightChanged(int keyboardHeight) { + public void onHeightChanged(int keyboardHeight) { setTranslationY(mBaseYOffset); } @@ -88,7 +88,7 @@ float offsetFromControls = mFullscreenManager.getBottomControlOffset() - mFullscreenManager.getBottomControlsHeight(); - offsetFromControls -= mKeyboardExtensionSizeManager.getKeyboardExtensionHeight(); + offsetFromControls -= mKeyboardExtensionSizeManager.getHeight(); // Sit on top of either the bottom sheet or the bottom toolbar depending on which is larger // (offsets are negative).
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java index 34311da..fa02707 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java
@@ -198,6 +198,9 @@ } @Override + public void destroy() {} + + @Override void initialize(ToolbarDataProvider toolbarDataProvider, ToolbarTabController tabController, AppMenuButtonHelper appMenuButtonHelper) { super.initialize(toolbarDataProvider, tabController, appMenuButtonHelper);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java index e2d5d0c..b5d5327 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
@@ -137,6 +137,8 @@ mThemeColorProvider.removeThemeColorObserver(this); mThemeColorProvider = null; } + + getLocationBar().destroy(); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java index cc1dff4..f52121f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java
@@ -109,6 +109,11 @@ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + // Close the notification tray. + ContextUtils.getApplicationContext().sendBroadcast( + new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); + long createTimestamp = SystemClock.elapsedRealtime(); Intent intent = getIntent();
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index ea7a0ea..3bac4c0 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -2646,6 +2646,9 @@ <message name="IDS_DOWNLOAD_MANAGER_UI_EMPTY" desc="Indicates that there are no downloaded items."> No downloads here </message> + <message name="IDS_DOWNLOAD_MANAGER_NO_DOWNLOADS" desc="Text appearing on an empty tab that indicates that downloaded files appear on this tab."> + Files that you download appear here + </message> <message name="IDS_DOWNLOAD_MANAGER_OPEN_WITH" desc="Menu item to open an item with another app."> Open with… </message> @@ -2670,14 +2673,8 @@ <message name="IDS_DOWNLOAD_MANAGER_PREFETCH_CAPTION" desc="Text containing the prefetched article description."> <ph name="DESCRIPTION">%1$s<ex>www.example.com</ex></ph> <ph name="SEPARATOR">•</ph> <ph name="FILE_SIZE">%2$s<ex>1.56 MB</ex></ph> </message> - <message name="IDS_DOWNLOAD_MANAGER_PREFETCH_TAB_EMPTY" desc="Tab text indicating that there is no prefetched content."> - No content here - </message> - <message name="IDS_DOWNLOAD_MANAGER_PREFETCH_TAB_NO_RESULTS" desc="Tab text indicating that no prefetched content matched a search query."> - No content found - </message> - <message name="IDS_DOWNLOAD_MANAGER_ENABLE_PREFETCH_MESSAGE" desc="Tab text indicating that users can enable prefetch to allow chrome to download articles on Wi-Fi."> - Allow Chrome to download articles for you when on Wi-Fi under settings. + <message name="IDS_DOWNLOAD_MANAGER_PREFETCH_TAB_EMPTY" desc="Tab text when there is no prefetched content, indicating that prefetched articles appear in this tab which can be viewed when offline."> + Articles appear here, which you can read even when you're offline </message> <message name="IDS_DOWNLOAD_MANAGER_N_HOURS" desc="How many hours ago an item was downloaded (if downloaded on the same day). [ICU Syntax]"> {HOURS, plural, =1 {# hr} other {# hrs}}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java index 1b926dca..ed469620 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java
@@ -43,38 +43,22 @@ public void testModeBrowser() throws Exception { HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue(shim.runTestForMode( - "browser", false, "native-include-thread-names", true, false, false)); - } - - @Test - @MediumTest - @CommandLineFlags.Add({"memlog-in-process=off"}) - public void testModeBrowserDynamic() throws Exception { - HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue(shim.runTestForMode("browser", true, "native", true, false, false)); + Assert.assertTrue( + shim.runTestForMode("browser", false, "native-include-thread-names", false, false)); } @Test @MediumTest public void testModeBrowserDynamicNonStreaming() throws Exception { HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue(shim.runTestForMode("browser", true, "native", false, false, false)); - } - - @Test - @MediumTest - @CommandLineFlags.Add({"memlog-in-process=off"}) - public void testModeBrowserDynamicPseudo() throws Exception { - HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue(shim.runTestForMode("browser", true, "pseudo", true, false, false)); + Assert.assertTrue(shim.runTestForMode("browser", true, "native", false, false)); } @Test @MediumTest public void testModeBrowserDynamicPseudoNonStreaming() throws Exception { HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue(shim.runTestForMode("browser", true, "pseudo", false, false, false)); + Assert.assertTrue(shim.runTestForMode("browser", true, "pseudo", false, false)); } // Non-browser processes must be profiled with a command line flag, since @@ -89,8 +73,7 @@ Add({"memlog=all-renderers", "memlog-stack-mode=pseudo", "memlog-sampling-rate=1"}) public void testModeRendererPseudo() throws Exception { HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue( - shim.runTestForMode("all-renderers", false, "pseudo", true, false, false)); + Assert.assertTrue(shim.runTestForMode("all-renderers", false, "pseudo", false, false)); } @Test @@ -98,29 +81,20 @@ @CommandLineFlags.Add({"memlog=gpu", "memlog-stack-mode=pseudo", "memlog-sampling-rate=1"}) public void testModeGpuPseudo() throws Exception { HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue(shim.runTestForMode("gpu", false, "native", true, false, false)); - } - - @Test - @MediumTest - @CommandLineFlags.Add({"memlog-in-process=off"}) - public void testModeBrowserDynamicPseudoSampleEverything() throws Exception { - HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue(shim.runTestForMode("browser", true, "pseudo", true, true, true)); + Assert.assertTrue(shim.runTestForMode("gpu", false, "native", false, false)); } @Test @MediumTest public void testModeBrowserDynamicPseudoSamplePartial() throws Exception { HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue(shim.runTestForMode("browser", true, "pseudo", true, true, false)); + Assert.assertTrue(shim.runTestForMode("browser", true, "pseudo", true, false)); } @Test @MediumTest public void testModeBrowserAndAllUtility() throws Exception { HeapProfilingTestShim shim = new HeapProfilingTestShim(); - Assert.assertTrue( - shim.runTestForMode("utility-and-browser", true, "pseudo", true, true, false)); + Assert.assertTrue(shim.runTestForMode("utility-and-browser", true, "pseudo", true, false)); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactoryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactoryTest.java index 3c115c1..4c3aae3 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactoryTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactoryTest.java
@@ -39,23 +39,24 @@ public void testGetImageFetcher() { assertEquals(ImageFetcherConfig.NETWORK_ONLY, ImageFetcherFactory - .createImageFetcher(ImageFetcherConfig.NETWORK_ONLY, mReferencePool, - mImageFetcherBridge) + .createImageFetcher(ImageFetcherConfig.NETWORK_ONLY, mImageFetcherBridge, + mReferencePool, InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE) .getConfig()); assertEquals(ImageFetcherConfig.DISK_CACHE_ONLY, ImageFetcherFactory - .createImageFetcher(ImageFetcherConfig.DISK_CACHE_ONLY, mReferencePool, - mImageFetcherBridge) + .createImageFetcher(ImageFetcherConfig.DISK_CACHE_ONLY, mImageFetcherBridge, + mReferencePool, InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE) .getConfig()); assertEquals(ImageFetcherConfig.IN_MEMORY_ONLY, ImageFetcherFactory - .createImageFetcher(ImageFetcherConfig.IN_MEMORY_ONLY, mReferencePool, - mImageFetcherBridge) + .createImageFetcher(ImageFetcherConfig.IN_MEMORY_ONLY, mImageFetcherBridge, + mReferencePool, InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE) .getConfig()); assertEquals(ImageFetcherConfig.IN_MEMORY_WITH_DISK_CACHE, ImageFetcherFactory .createImageFetcher(ImageFetcherConfig.IN_MEMORY_WITH_DISK_CACHE, - mReferencePool, mImageFetcherBridge) + mImageFetcherBridge, mReferencePool, + InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE) .getConfig()); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherTest.java index 60be0f4..0c1c454 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherTest.java
@@ -45,6 +45,9 @@ String url, String clientName, int width, int height, Callback<Bitmap> callback) {} @Override + public void clear() {} + + @Override public int getConfig() { return 0; }
diff --git a/chrome/android/touchless/java/res/layout/open_last_tab_button.xml b/chrome/android/touchless/java/res/layout/open_last_tab_button.xml index 50656a3..3527ae3 100644 --- a/chrome/android/touchless/java/res/layout/open_last_tab_button.xml +++ b/chrome/android/touchless/java/res/layout/open_last_tab_button.xml
@@ -4,21 +4,47 @@ found in the LICENSE file. --> <merge xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> + xmlns:tools="http://schemas.android.com/tools" + tools:targetApi="21"> <!-- The Chrome Explore header displayed when the user has no history. --> <include layout="@layout/open_last_tab_fallback_view"/> - <org.chromium.ui.widget.ChipView - android:id="@+id/last_tab_chip" + <LinearLayout + android:id="@+id/open_last_tab" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:layout_marginHorizontal="@dimen/open_last_tab_button_horizontal_margin" + android:layout_gravity="center" android:paddingHorizontal="@dimen/open_last_tab_button_padding_horizontal" android:paddingVertical="@dimen/open_last_tab_button_padding_vertical" - app:iconWidth="@dimen/open_last_tab_icon_size" - app:iconHeight="@dimen/open_last_tab_icon_size" - android:visibility="gone" /> + android:background="@drawable/hairline_border_card_background" + android:theme="@style/Theme.AppCompat.Light"> + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/favicon" + android:layout_width="@dimen/open_last_tab_icon_size" + android:layout_height="@dimen/open_last_tab_icon_size" + android:layout_gravity="center_vertical" + android:scaleType="centerInside"/> + + <TextView + android:id="@+id/title" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_marginStart="@dimen/open_last_tab_title_text_margin_left" + android:textAppearance="@style/TextAppearance.BlackTitle2" + android:ellipsize="end" + android:maxLines="1"/> + + <TextView + android:id="@+id/timestamp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/open_last_tab_timestamp_text_margin_left" + android:textAppearance="@style/TextAppearance.BlackCaption" + android:ellipsize="end" + android:maxLines="1" /> + + </LinearLayout> </merge> \ No newline at end of file
diff --git a/chrome/android/touchless/java/res/values-v17/dimens.xml b/chrome/android/touchless/java/res/values-v17/dimens.xml index bfa5041b..bbca39d6 100644 --- a/chrome/android/touchless/java/res/values-v17/dimens.xml +++ b/chrome/android/touchless/java/res/values-v17/dimens.xml
@@ -19,11 +19,11 @@ <dimen name="open_last_tab_placeholder_image_margin_bottom">13dp</dimen> <!-- Open last tab button dimensions. --> - <dimen name="open_last_tab_button_horizontal_margin">8dp</dimen> <dimen name="open_last_tab_button_padding_horizontal">12dp</dimen> - <dimen name="open_last_tab_button_padding_vertical">8dp</dimen> + <dimen name="open_last_tab_button_padding_vertical">9dp</dimen> <dimen name="open_last_tab_icon_size">16dp</dimen> - <dimen name="open_last_tab_primary_text_margin_left">8dp</dimen> + <dimen name="open_last_tab_title_text_margin_left">12dp</dimen> + <dimen name="open_last_tab_timestamp_text_margin_left">10dp</dimen> <!-- Most likely carousel dimensions. --> <dimen name="most_likely_tile_focus_stroke_width">2dp</dimen>
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabView.java index 442c26e4..a4ebf21 100644 --- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabView.java +++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabView.java
@@ -7,17 +7,15 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; -import android.text.TextUtils; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.touchless.R; -import org.chromium.ui.widget.ChipView; /** * View for the button to open the last tab. @@ -25,7 +23,11 @@ // TODO(crbug.com/948858): Add render tests for this view. public class OpenLastTabView extends FrameLayout { private LinearLayout mPlaceholder; - private ChipView mLastTabChip; + + private LinearLayout mLastTabView; + private ImageView mIconView; + private TextView mTitleText; + private TextView mTimestampText; public OpenLastTabView(Context context, AttributeSet attrs) { super(context, attrs); @@ -38,35 +40,10 @@ super.onFinishInflate(); mPlaceholder = findViewById(R.id.placeholder); - mLastTabChip = findViewById(R.id.last_tab_chip); - // Allow the system ui to control our background. - mLastTabChip.setBackground(null); - - TextView primaryTextView = mLastTabChip.getPrimaryTextView(); - TextView secondaryTextView = mLastTabChip.getSecondaryTextView(); - - LinearLayout.LayoutParams params = - new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT); - // Allow timestamp to expand to as much as it needs. - params.weight = 1; - primaryTextView.setLayoutParams(params); - primaryTextView.setSingleLine(true); - primaryTextView.setEllipsize(TextUtils.TruncateAt.END); - primaryTextView.setPadding((int) getContext().getResources().getDimension( - R.dimen.open_last_tab_primary_text_margin_left), - 0, 0, 0); - ApiCompatibilityUtils.setTextAppearance( - primaryTextView, R.style.TextAppearance_BlackTitle2); - - params = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); - secondaryTextView.setLayoutParams(params); - secondaryTextView.setSingleLine(true); - // Note: this should never actually need to truncate, but I've included it as a fallback. - secondaryTextView.setEllipsize(TextUtils.TruncateAt.END); - secondaryTextView.setTextAlignment(TEXT_ALIGNMENT_VIEW_END); - ApiCompatibilityUtils.setTextAppearance( - secondaryTextView, R.style.TextAppearance_BlackCaption); + mLastTabView = findViewById(R.id.open_last_tab); + mIconView = findViewById(R.id.favicon); + mTitleText = findViewById(R.id.title); + mTimestampText = findViewById(R.id.timestamp); } void setLoadSuccess(boolean loadSuccess) { @@ -74,26 +51,26 @@ if (loadSuccess) { mPlaceholder.setVisibility(View.GONE); - mLastTabChip.setVisibility(View.VISIBLE); + mLastTabView.setVisibility(View.VISIBLE); } else { - mLastTabChip.setVisibility(View.GONE); + mLastTabView.setVisibility(View.GONE); mPlaceholder.setVisibility(View.VISIBLE); } } void setOpenLastTabOnClickListener(OnClickListener onClickListener) { - mLastTabChip.setOnClickListener(onClickListener); + mLastTabView.setOnClickListener(onClickListener); } void setFavicon(Bitmap favicon) { - mLastTabChip.setIcon(new BitmapDrawable(getContext().getResources(), favicon), false); + mIconView.setImageDrawable(new BitmapDrawable(getContext().getResources(), favicon)); } void setTitle(String title) { - mLastTabChip.getPrimaryTextView().setText(title); + mTitleText.setText(title); } void setTimestamp(String timestamp) { - mLastTabChip.getSecondaryTextView().setText(timestamp); + mTimestampText.setText(timestamp); } }
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index 345f6c1..c223373 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -49,7 +49,6 @@ #include "components/gwp_asan/buildflags/buildflags.h" #include "components/nacl/common/buildflags.h" #include "components/services/heap_profiling/public/cpp/sampling_profiler_wrapper.h" -#include "components/services/heap_profiling/public/cpp/stream.h" #include "components/tracing/common/tracing_sampler_profiler.h" #include "components/version_info/version_info.h" #include "content/public/common/content_client.h"
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 493ee87..9b4bf0f 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -1629,7 +1629,9 @@ <message name="IDS_CONTROLLED_SETTING_DEMO_SESSION" desc="Text displayed in the controlled settings bubble when a setting's value is enforced by demo session."> This setting can't be changed in a demo session. </message> - + <message name="IDS_CONTROLLED_SETTING_PARENT" desc="Text displayed in the controlled settings bubble when a setting's value is controlled by user's parent."> + This setting is managed by a parent. + </message> <message name="IDS_STATUSBAR_DISABLE_SPOKEN_FEEDBACK" desc="The menu option to disable spoken feedback accessibility feature."> Disable ChromeVox (spoken feedback) </message>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 5544c32..ff1680f 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -3347,9 +3347,6 @@ <message name="IDS_UTILITY_PROCESS_PATCH_NAME" desc="The name of the utility process used for patching file operations."> Patch Service </message> - <message name="IDS_UTILITY_PROCESS_PROFILING_SERVICE_NAME" desc="The name of the utility process used for heap profiling."> - Profiling Service - </message> <message name="IDS_UTILITY_PROCESS_UNZIP_NAME" desc="The name of the utility process used for unzipping files."> Unzip Service </message> @@ -4269,6 +4266,9 @@ <message name="IDS_EXTENSIONS_MENU_TITLE" desc="Title of the Extensions Menu"> Extensions </message> + <message name="IDS_EXTENSIONS_MENU_CONTEXT_MENU_TOOLTIP" desc="Title of the context menu for individual extensions in the Extensions Menu"> + More actions + </message> <!-- Settings API bubble --> <message name="IDS_EXTENSIONS_SETTINGS_API_TITLE_HOME_PAGE_BUBBLE" desc="Title of a bubble warning users that an extension has overridden their home page setting">
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index b104c244..400844e5 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2429,7 +2429,6 @@ "android/ntp/recent_tabs_page_prefs.cc", "android/ntp/recent_tabs_page_prefs.h", "android/ntp/suggestions_event_reporter_bridge.cc", - "android/omnibox/answers_image_bridge.cc", "android/omnibox/autocomplete_controller_android.cc", "android/omnibox/autocomplete_controller_android.h", "android/omnibox/omnibox_prerender.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 57cb8638..977131d 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -720,15 +720,6 @@ heap_profiling::kMemlogStackModeMixed}, }; -const FeatureEntry::Choice kMemlogInProcessChoices[] = { - {flags_ui::kGenericExperimentChoiceDefault, "", ""}, - {flag_descriptions::kMemlogInProcessDisabled, - heap_profiling::kMemlogInProcess, - heap_profiling::kMemlogInProcessDisabled}, - {flag_descriptions::kMemlogInProcessEnabled, - heap_profiling::kMemlogInProcess, heap_profiling::kMemlogInProcessEnabled}, -}; - const FeatureEntry::Choice kMemlogSamplingRateChoices[] = { {flags_ui::kGenericExperimentChoiceDefault, "", ""}, {flag_descriptions::kMemlogSamplingRate10KB, @@ -2597,10 +2588,6 @@ flag_descriptions::kMemlogDescription, kOsAll, MULTI_VALUE_TYPE(kMemlogModeChoices)}, - {"memlog-in-process", flag_descriptions::kMemlogInProcessName, - flag_descriptions::kMemlogInProcessDescription, kOsAll, - MULTI_VALUE_TYPE(kMemlogInProcessChoices)}, - {"memlog-sampling-rate", flag_descriptions::kMemlogSamplingRateName, flag_descriptions::kMemlogSamplingRateDescription, kOsAll, MULTI_VALUE_TYPE(kMemlogSamplingRateChoices)},
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc index 9cafebe..fbbb397 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -381,16 +381,14 @@ if (!has_close_or_cancel) { if (ui_delegate_->GetState() == AutofillAssistantState::STOPPED) { Java_AutofillAssistantUiController_addCloseButton( - env, java_object_, chips, NO_ICON, - base::android::ConvertUTF8ToJavaString( - env, l10n_util::GetStringUTF8(IDS_CLOSE)), + env, java_object_, chips, ICON_CLEAR, + base::android::ConvertUTF8ToJavaString(env, ""), /* disabled= */ false); } else if (ui_delegate_->GetState() != AutofillAssistantState::INACTIVE) { Java_AutofillAssistantUiController_addCancelButton( - env, java_object_, chips, NO_ICON, - base::android::ConvertUTF8ToJavaString( - env, l10n_util::GetStringUTF8(IDS_CANCEL)), - -1, /* disabled= */ false); + env, java_object_, chips, ICON_CLEAR, + base::android::ConvertUTF8ToJavaString(env, ""), -1, + /* disabled= */ false); } }
diff --git a/chrome/browser/android/omnibox/answers_image_bridge.cc b/chrome/browser/android/omnibox/answers_image_bridge.cc deleted file mode 100644 index 9ce2b252..0000000 --- a/chrome/browser/android/omnibox/answers_image_bridge.cc +++ /dev/null
@@ -1,77 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "base/android/scoped_java_ref.h" -#include "base/bind.h" -#include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h" -#include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service_factory.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_android.h" -#include "jni/AnswersImageFetcher_jni.h" -#include "net/traffic_annotation/network_traffic_annotation.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/gfx/android/java_bitmap.h" -#include "url/gurl.h" - -using base::android::JavaParamRef; -using base::android::ScopedJavaLocalRef; -using base::android::ConvertUTF8ToJavaString; - -namespace { - -class AnswersImageObserverAndroid : public BitmapFetcherService::Observer { - public: - explicit AnswersImageObserverAndroid(JNIEnv* env, - jobject java_answers_image_observer) { - java_answers_image_observer_.Reset(env, java_answers_image_observer); - } - - ~AnswersImageObserverAndroid() override {} - - // AnswersImageObserver: - void OnImageChanged(BitmapFetcherService::RequestId request_id, - const SkBitmap& answers_image) override { - DCHECK(!answers_image.empty()); - - JNIEnv* env = base::android::AttachCurrentThread(); - ScopedJavaLocalRef<jobject> java_bitmap = - gfx::ConvertToJavaBitmap(&answers_image); - Java_AnswersImageObserver_onAnswersImageChanged( - env, java_answers_image_observer_, java_bitmap); - } - - private: - base::android::ScopedJavaGlobalRef<jobject> java_answers_image_observer_; -}; - -} // namespace - -static void JNI_AnswersImageFetcher_CancelAnswersImageRequest( - JNIEnv* env, - const JavaParamRef<jobject>& java_profile, - jint java_request_id) { - Profile* profile = ProfileAndroid::FromProfileAndroid(java_profile); - DCHECK(profile); - BitmapFetcherService* bitmap_fetcher_service = - BitmapFetcherServiceFactory::GetForBrowserContext(profile); - bitmap_fetcher_service->CancelRequest(java_request_id); -} - -static int JNI_AnswersImageFetcher_RequestAnswersImage( - JNIEnv* env, - const JavaParamRef<jobject>& java_profile, - const JavaParamRef<jstring>& java_url, - const JavaParamRef<jobject>& java_callback) { - Profile* profile = ProfileAndroid::FromProfileAndroid(java_profile); - DCHECK(profile); - BitmapFetcherService* bitmap_fetcher_service = - BitmapFetcherServiceFactory::GetForBrowserContext(profile); - std::string url; - base::android::ConvertJavaStringToUTF8(env, java_url, &url); - return bitmap_fetcher_service->RequestImage( - GURL(url), new AnswersImageObserverAndroid(env, java_callback), - TRAFFIC_ANNOTATION_WITHOUT_PROTO("Omnibox answers image")); -}
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index fd01f07d..3d1a4c9 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -3866,11 +3866,9 @@ "download_manager", base::BindRepeating(&StartDownloadManager)); #endif - if (heap_profiling::IsInProcessModeEnabled()) { - connection->AddServiceRequestHandler( - heap_profiling::mojom::kServiceName, - heap_profiling::HeapProfilingService::GetServiceFactory()); - } + connection->AddServiceRequestHandler( + heap_profiling::mojom::kServiceName, + heap_profiling::HeapProfilingService::GetServiceFactory()); } void ChromeContentBrowserClient::RegisterOutOfProcessServices( @@ -3915,11 +3913,6 @@ IDS_UTILITY_PROCESS_PRINTING_SERVICE_NAME); #endif - if (!heap_profiling::IsInProcessModeEnabled()) { - (*services)[heap_profiling::mojom::kServiceName] = base::BindRepeating( - &l10n_util::GetStringUTF16, IDS_UTILITY_PROCESS_PROFILING_SERVICE_NAME); - } - #if BUILDFLAG(ENABLE_EXTENSIONS) || defined(OS_ANDROID) (*services)[chrome::mojom::kMediaGalleryUtilServiceName] = base::BindRepeating(&l10n_util::GetStringUTF16,
diff --git a/chrome/browser/chrome_navigation_browsertest.cc b/chrome/browser/chrome_navigation_browsertest.cc index a0fef21..28c02a7 100644 --- a/chrome/browser/chrome_navigation_browsertest.cc +++ b/chrome/browser/chrome_navigation_browsertest.cc
@@ -1439,6 +1439,8 @@ // foo.com should not be isolated to start with. Verify that a cross-site // iframe does not become an OOPIF. + EXPECT_FALSE( + contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess()); std::string kAppendIframe = R"( var i = document.createElement('iframe'); i.id = 'child'; @@ -1458,8 +1460,19 @@ EXPECT_TRUE(content::ExecJs(contents, kFillAndSubmit)); observer.Wait(); - // Open a fresh tab (forcing a new BrowsingInstance), navigate to foo.com, - // and verify that a cross-site iframe now becomes an OOPIF. + // Since there were no script references from other windows, we should've + // swapped BrowsingInstances and put the result of the form submission into a + // dedicated process, locked to foo.com. Check that a cross-site iframe now + // becomes an OOPIF. + EXPECT_TRUE( + contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess()); + EXPECT_TRUE(ExecJs(contents, kAppendIframe)); + EXPECT_TRUE(NavigateIframeToURL(contents, "child", bar_url)); + child = ChildFrameAt(contents->GetMainFrame(), 0); + EXPECT_TRUE(child->IsCrossProcessSubframe()); + + // Open a fresh tab (also forcing a new BrowsingInstance), navigate to + // foo.com, and verify that a cross-site iframe becomes an OOPIF. AddBlankTabAndShow(browser()); EXPECT_EQ(2, browser()->tab_strip_model()->count()); content::WebContents* new_contents =
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc index 51d11d3..9266d9c 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc +++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -24,7 +24,7 @@ #include "base/command_line.h" #include "base/memory/ptr_util.h" #include "base/memory/singleton.h" -#include "base/metrics/histogram_macros.h" +#include "base/metrics/histogram_functions.h" #include "base/path_service.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" @@ -135,11 +135,13 @@ } void EnableChromeVoxAfterSwitchAccessMetric(bool val) { - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosChromeVoxAfterSwitchAccess", val); + base::UmaHistogramBoolean("Accessibility.CrosChromeVoxAfterSwitchAccess", + val); } void EnableSwitchAccessAfterChromeVoxMetric(bool val) { - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosSwitchAccessAfterChromeVox", val); + base::UmaHistogramBoolean("Accessibility.CrosSwitchAccessAfterChromeVox", + val); } // Restarts (stops, then starts brltty). If |address| is empty, only stops. @@ -1173,49 +1175,55 @@ } void AccessibilityManager::UpdateChromeOSAccessibilityHistograms() { - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosSpokenFeedback", - IsSpokenFeedbackEnabled()); - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosHighContrast", - IsHighContrastEnabled()); - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosVirtualKeyboard", - IsVirtualKeyboardEnabled()); - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosStickyKeys", IsStickyKeysEnabled()); + base::UmaHistogramBoolean("Accessibility.CrosSpokenFeedback", + IsSpokenFeedbackEnabled()); + base::UmaHistogramBoolean("Accessibility.CrosHighContrast", + IsHighContrastEnabled()); + base::UmaHistogramBoolean("Accessibility.CrosVirtualKeyboard", + IsVirtualKeyboardEnabled()); + base::UmaHistogramBoolean("Accessibility.CrosStickyKeys", + IsStickyKeysEnabled()); if (MagnificationManager::Get()) { - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosScreenMagnifier", - MagnificationManager::Get()->IsMagnifierEnabled()); + base::UmaHistogramBoolean( + "Accessibility.CrosScreenMagnifier", + MagnificationManager::Get()->IsMagnifierEnabled()); + base::UmaHistogramBoolean( + "Accessibility.CrosDockedMagnifier", + MagnificationManager::Get()->IsDockedMagnifierEnabled()); } if (profile_) { const PrefService* const prefs = profile_->GetPrefs(); bool large_cursor_enabled = prefs->GetBoolean(ash::prefs::kAccessibilityLargeCursorEnabled); - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosLargeCursor", - large_cursor_enabled); + base::UmaHistogramBoolean("Accessibility.CrosLargeCursor", + large_cursor_enabled); if (large_cursor_enabled) { - UMA_HISTOGRAM_COUNTS_100( + base::UmaHistogramCounts100( "Accessibility.CrosLargeCursorSize", prefs->GetInteger(ash::prefs::kAccessibilityLargeCursorDipSize)); } - UMA_HISTOGRAM_BOOLEAN( + base::UmaHistogramBoolean( "Accessibility.CrosAlwaysShowA11yMenu", prefs->GetBoolean(ash::prefs::kShouldAlwaysShowAccessibilityMenu)); bool autoclick_enabled = prefs->GetBoolean(ash::prefs::kAccessibilityAutoclickEnabled); - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosAutoclick", autoclick_enabled); + base::UmaHistogramBoolean("Accessibility.CrosAutoclick", autoclick_enabled); } - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosCaretHighlight", - IsCaretHighlightEnabled()); - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosCursorHighlight", - IsCursorHighlightEnabled()); - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosDictation", IsDictationEnabled()); - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosFocusHighlight", - IsFocusHighlightEnabled()); - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosSelectToSpeak", - IsSelectToSpeakEnabled()); - UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosSwitchAccess", - IsSwitchAccessEnabled()); + base::UmaHistogramBoolean("Accessibility.CrosCaretHighlight", + IsCaretHighlightEnabled()); + base::UmaHistogramBoolean("Accessibility.CrosCursorHighlight", + IsCursorHighlightEnabled()); + base::UmaHistogramBoolean("Accessibility.CrosDictation", + IsDictationEnabled()); + base::UmaHistogramBoolean("Accessibility.CrosFocusHighlight", + IsFocusHighlightEnabled()); + base::UmaHistogramBoolean("Accessibility.CrosSelectToSpeak", + IsSelectToSpeakEnabled()); + base::UmaHistogramBoolean("Accessibility.CrosSwitchAccess", + IsSwitchAccessEnabled()); } void AccessibilityManager::Observe(
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session_browsertest.cc b/chrome/browser/chromeos/login/demo_mode/demo_session_browsertest.cc index 9614172..8593daf9 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_session_browsertest.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_session_browsertest.cc
@@ -7,214 +7,165 @@ #include "base/macros.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h" -#include "chrome/browser/chromeos/login/login_manager_test.h" +#include "chrome/browser/chromeos/login/test/device_state_mixin.h" +#include "chrome/browser/chromeos/login/test/oobe_base_test.h" #include "chrome/common/pref_names.h" -#include "chromeos/tpm/stub_install_attributes.h" #include "components/prefs/pref_service.h" namespace chromeos { namespace { -constexpr char kFakeDeviceId[] = "device_id"; -constexpr char kNonDemoDomain[] = "non-demo-mode.com"; - void SetDemoConfigPref(DemoSession::DemoModeConfig demo_config) { PrefService* prefs = g_browser_process->local_state(); prefs->SetInteger(prefs::kDemoModeConfig, static_cast<int>(demo_config)); } +void CheckDemoMode() { + EXPECT_TRUE(DemoSession::IsDeviceInDemoMode()); + EXPECT_EQ(DemoSession::DemoModeConfig::kOffline, + DemoSession::GetDemoConfig()); + + SetDemoConfigPref(DemoSession::DemoModeConfig::kOnline); + EXPECT_TRUE(DemoSession::IsDeviceInDemoMode()); + EXPECT_EQ(DemoSession::DemoModeConfig::kOnline, DemoSession::GetDemoConfig()); + + SetDemoConfigPref(DemoSession::DemoModeConfig::kOffline); + EXPECT_TRUE(DemoSession::IsDeviceInDemoMode()); + EXPECT_EQ(DemoSession::DemoModeConfig::kOffline, + DemoSession::GetDemoConfig()); +} + +void CheckNoDemoMode() { + EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); + EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); + + SetDemoConfigPref(DemoSession::DemoModeConfig::kOnline); + EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); + EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); + + SetDemoConfigPref(DemoSession::DemoModeConfig::kOffline); + EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); + EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); +} + } // namespace // Tests locking device to policy::DEVICE_MODE_DEMO mode. It is an equivalent to // going through online demo mode setup or using offline setup. -class DemoSessionDemoDeviceModeTest : public LoginManagerTest { +class DemoSessionDemoDeviceModeTest : public OobeBaseTest { protected: - DemoSessionDemoDeviceModeTest() - : LoginManagerTest(true /*should_launch_browser*/, - true /* should_initialize_webui */), - install_attributes_( - StubInstallAttributes::CreateDemoMode(kFakeDeviceId)) {} + DemoSessionDemoDeviceModeTest() = default; ~DemoSessionDemoDeviceModeTest() override = default; - // LoginManagerTest: + // OobeBaseTest: void SetUpOnMainThread() override { - LoginManagerTest::SetUpOnMainThread(); + OobeBaseTest::SetUpOnMainThread(); SetDemoConfigPref(DemoSession::DemoModeConfig::kOffline); } private: - const ScopedStubInstallAttributes install_attributes_; + DeviceStateMixin device_state_{ + &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_DEMO_MODE}; DISALLOW_COPY_AND_ASSIGN(DemoSessionDemoDeviceModeTest); }; IN_PROC_BROWSER_TEST_F(DemoSessionDemoDeviceModeTest, IsDemoMode) { - EXPECT_TRUE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kOffline, - DemoSession::GetDemoConfig()); - - SetDemoConfigPref(DemoSession::DemoModeConfig::kOnline); - EXPECT_TRUE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kOnline, DemoSession::GetDemoConfig()); - - SetDemoConfigPref(DemoSession::DemoModeConfig::kOffline); - EXPECT_TRUE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kOffline, - DemoSession::GetDemoConfig()); + CheckDemoMode(); } // Tests locking device to demo mode domain without policy::DEVICE_MODE_DEMO // mode. It is an equivalent to enrolling device directly by using enterprise // enrollment flow. -class DemoSessionDemoEnrolledDeviceTest : public LoginManagerTest { +class DemoSessionDemoEnrolledDeviceTest : public OobeBaseTest { protected: - DemoSessionDemoEnrolledDeviceTest() - : LoginManagerTest(true /*should_launch_browser*/, - true /* should_initialize_webui */), - install_attributes_( - StubInstallAttributes::CreateCloudManaged(policy::kDemoModeDomain, - kFakeDeviceId)) {} + DemoSessionDemoEnrolledDeviceTest() : OobeBaseTest() { + device_state_.set_domain(policy::kDemoModeDomain); + } ~DemoSessionDemoEnrolledDeviceTest() override = default; - // LoginManagerTest: + // OobeBaseTest: void SetUpOnMainThread() override { - LoginManagerTest::SetUpOnMainThread(); + OobeBaseTest::SetUpOnMainThread(); SetDemoConfigPref(DemoSession::DemoModeConfig::kOffline); } private: - const ScopedStubInstallAttributes install_attributes_; + DeviceStateMixin device_state_{ + &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED}; DISALLOW_COPY_AND_ASSIGN(DemoSessionDemoEnrolledDeviceTest); }; IN_PROC_BROWSER_TEST_F(DemoSessionDemoEnrolledDeviceTest, IsDemoMode) { - EXPECT_TRUE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kOffline, - DemoSession::GetDemoConfig()); - - SetDemoConfigPref(DemoSession::DemoModeConfig::kOnline); - EXPECT_TRUE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kOnline, DemoSession::GetDemoConfig()); - - SetDemoConfigPref(DemoSession::DemoModeConfig::kOffline); - EXPECT_TRUE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kOffline, - DemoSession::GetDemoConfig()); + CheckDemoMode(); } -class DemoSessionNonDemoEnrolledDeviceTest : public LoginManagerTest { +class DemoSessionNonDemoEnrolledDeviceTest : public OobeBaseTest { public: - DemoSessionNonDemoEnrolledDeviceTest() - : LoginManagerTest(true /*should_launch_browser*/, - true /* should_initialize_webui */), - install_attributes_( - StubInstallAttributes::CreateCloudManaged(kNonDemoDomain, - kFakeDeviceId)) {} + DemoSessionNonDemoEnrolledDeviceTest() = default; ~DemoSessionNonDemoEnrolledDeviceTest() override = default; private: - ScopedStubInstallAttributes install_attributes_; + DeviceStateMixin device_state_{ + &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED}; DISALLOW_COPY_AND_ASSIGN(DemoSessionNonDemoEnrolledDeviceTest); }; IN_PROC_BROWSER_TEST_F(DemoSessionNonDemoEnrolledDeviceTest, NotDemoMode) { - EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); - - SetDemoConfigPref(DemoSession::DemoModeConfig::kOnline); - EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); - - SetDemoConfigPref(DemoSession::DemoModeConfig::kOffline); - EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); + CheckNoDemoMode(); } -class DemoSessionConsumerDeviceTest : public LoginManagerTest { +class DemoSessionConsumerDeviceTest : public OobeBaseTest { public: - DemoSessionConsumerDeviceTest() - : LoginManagerTest(true /*should_launch_browser*/, - true /* should_initialize_webui */), - install_attributes_(StubInstallAttributes::CreateConsumerOwned()) {} + DemoSessionConsumerDeviceTest() = default; ~DemoSessionConsumerDeviceTest() override = default; private: - ScopedStubInstallAttributes install_attributes_; + DeviceStateMixin device_state_{ + &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_CONSUMER_OWNED}; DISALLOW_COPY_AND_ASSIGN(DemoSessionConsumerDeviceTest); }; IN_PROC_BROWSER_TEST_F(DemoSessionConsumerDeviceTest, NotDemoMode) { - EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); - - SetDemoConfigPref(DemoSession::DemoModeConfig::kOnline); - EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); - - SetDemoConfigPref(DemoSession::DemoModeConfig::kOffline); - EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); + CheckNoDemoMode(); } -class DemoSessionUnownedDeviceTest : public LoginManagerTest { +class DemoSessionUnownedDeviceTest : public OobeBaseTest { public: - DemoSessionUnownedDeviceTest() - : LoginManagerTest(true /*should_launch_browser*/, - true /* should_initialize_webui */), - install_attributes_(StubInstallAttributes::CreateUnset()) {} + DemoSessionUnownedDeviceTest() = default; ~DemoSessionUnownedDeviceTest() override = default; private: - ScopedStubInstallAttributes install_attributes_; + DeviceStateMixin device_state_{ + &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_UNOWNED}; DISALLOW_COPY_AND_ASSIGN(DemoSessionUnownedDeviceTest); }; IN_PROC_BROWSER_TEST_F(DemoSessionUnownedDeviceTest, NotDemoMode) { - EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); - - SetDemoConfigPref(DemoSession::DemoModeConfig::kOnline); - EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); - - SetDemoConfigPref(DemoSession::DemoModeConfig::kOffline); - EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); + CheckNoDemoMode(); } -class DemoSessionActiveDirectoryDeviceTest : public LoginManagerTest { +class DemoSessionActiveDirectoryDeviceTest : public OobeBaseTest { public: - DemoSessionActiveDirectoryDeviceTest() - : LoginManagerTest(true /*should_launch_browser*/, - true /* should_initialize_webui */), - install_attributes_(StubInstallAttributes::CreateActiveDirectoryManaged( - policy::kDemoModeDomain, - kFakeDeviceId)) {} + DemoSessionActiveDirectoryDeviceTest() = default; ~DemoSessionActiveDirectoryDeviceTest() override = default; private: - ScopedStubInstallAttributes install_attributes_; + DeviceStateMixin device_state_{ + &mixin_host_, + DeviceStateMixin::State::OOBE_COMPLETED_ACTIVE_DIRECTORY_ENROLLED}; DISALLOW_COPY_AND_ASSIGN(DemoSessionActiveDirectoryDeviceTest); }; IN_PROC_BROWSER_TEST_F(DemoSessionActiveDirectoryDeviceTest, NotDemoMode) { - EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); - - SetDemoConfigPref(DemoSession::DemoModeConfig::kOnline); - EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); - - SetDemoConfigPref(DemoSession::DemoModeConfig::kOffline); - EXPECT_FALSE(DemoSession::IsDeviceInDemoMode()); - EXPECT_EQ(DemoSession::DemoModeConfig::kNone, DemoSession::GetDemoConfig()); + CheckNoDemoMode(); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/device_state_mixin.cc b/chrome/browser/chromeos/login/test/device_state_mixin.cc index a11048af..690d99b 100644 --- a/chrome/browser/chromeos/login/test/device_state_mixin.cc +++ b/chrome/browser/chromeos/login/test/device_state_mixin.cc
@@ -32,15 +32,18 @@ void DeviceStateMixin::SetDeviceState() { DCHECK(!is_setup_); + DCHECK(domain_.empty() || state_ == State::OOBE_COMPLETED_CLOUD_ENROLLED); is_setup_ = true; switch (state_) { case State::BEFORE_OOBE: case State::OOBE_COMPLETED_UNOWNED: install_attributes_.Get()->Clear(); return; - case State::OOBE_COMPLETED_CLOUD_ENROLLED: - install_attributes_.Get()->SetCloudManaged(kFakeDomain, kFakeDeviceId); + case State::OOBE_COMPLETED_CLOUD_ENROLLED: { + const std::string domain = !domain_.empty() ? domain_ : kFakeDomain; + install_attributes_.Get()->SetCloudManaged(domain, kFakeDeviceId); return; + } case State::OOBE_COMPLETED_ACTIVE_DIRECTORY_ENROLLED: install_attributes_.Get()->SetActiveDirectoryManaged(kFakeDomain, kFakeDeviceId); @@ -48,6 +51,9 @@ case State::OOBE_COMPLETED_CONSUMER_OWNED: install_attributes_.Get()->SetConsumerOwned(); return; + case State::OOBE_COMPLETED_DEMO_MODE: + install_attributes_.Get()->SetDemoMode(kFakeDeviceId); + return; } }
diff --git a/chrome/browser/chromeos/login/test/device_state_mixin.h b/chrome/browser/chromeos/login/test/device_state_mixin.h index 4e47414..07e1688 100644 --- a/chrome/browser/chromeos/login/test/device_state_mixin.h +++ b/chrome/browser/chromeos/login/test/device_state_mixin.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_CHROMEOS_LOGIN_TEST_DEVICE_STATE_MIXIN_H_ #include <memory> +#include <string> #include "base/macros.h" #include "base/values.h" @@ -23,6 +24,7 @@ OOBE_COMPLETED_CLOUD_ENROLLED, OOBE_COMPLETED_ACTIVE_DIRECTORY_ENROLLED, OOBE_COMPLETED_CONSUMER_OWNED, + OOBE_COMPLETED_DEMO_MODE, }; DeviceStateMixin(InProcessBrowserTestMixinHost* host, State initial_state); @@ -32,10 +34,12 @@ void SetUpInProcessBrowserTestFixture() override; void SetState(State state); + void set_domain(const std::string& domain) { domain_ = domain; } private: void SetDeviceState(); State state_; + std::string domain_; ScopedStubInstallAttributes install_attributes_; bool is_setup_ = false;
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc index 52de951..13b8da3 100644 --- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc +++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc
@@ -9,7 +9,6 @@ #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_switches.h" -#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/origin_util.h" @@ -42,8 +41,8 @@ EXTENSION_FUNCTION_VALIDATE(args_->GetSize() > 0); EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &request_id_)); - DesktopCaptureRequestsRegistry::GetInstance()->AddRequest( - render_frame_host()->GetProcess()->GetID(), request_id_, this); + DesktopCaptureRequestsRegistry::GetInstance()->AddRequest(source_process_id(), + request_id_, this); args_->Remove(0, NULL);
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc index b3ddc3af..07369df4 100644 --- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc +++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
@@ -57,11 +57,8 @@ DesktopCaptureChooseDesktopMediaFunctionBase:: ~DesktopCaptureChooseDesktopMediaFunctionBase() { - // RenderFrameHost may be already destroyed. - if (render_frame_host()) { - DesktopCaptureRequestsRegistry::GetInstance()->RemoveRequest( - render_frame_host()->GetProcess()->GetID(), request_id_); - } + DesktopCaptureRequestsRegistry::GetInstance()->RemoveRequest( + source_process_id(), request_id_); } void DesktopCaptureChooseDesktopMediaFunctionBase::Cancel() { @@ -213,7 +210,7 @@ EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &request_id)); DesktopCaptureRequestsRegistry::GetInstance()->CancelRequest( - render_frame_host()->GetProcess()->GetID(), request_id); + source_process_id(), request_id); return RespondNow(NoArguments()); }
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc index c0a3148..99e4494 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -59,7 +59,6 @@ #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/site_instance.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" @@ -1417,11 +1416,10 @@ } return LoadByFileSystemAPI(directory_url); } else { - // Check if the DirecotryEntry is the instance of chrome filesystem. + // Check if the DirectoryEntry is the instance of chrome filesystem. if (!app_file_handler_util::ValidateFileEntryAndGetPath( - filesystem_name, filesystem_path, - render_frame_host()->GetProcess()->GetID(), &project_base_path_, - &error_)) { + filesystem_name, filesystem_path, source_process_id(), + &project_base_path_, &error_)) { SetError("DirectoryEntry of unsupported filesystem."); return false; }
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc index 40e574d..9b7a6503 100644 --- a/chrome/browser/extensions/api/downloads/downloads_api.cc +++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -65,7 +65,6 @@ #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" @@ -1029,7 +1028,7 @@ })"); std::unique_ptr<download::DownloadUrlParameters> download_params( new download::DownloadUrlParameters( - download_url, render_frame_host()->GetProcess()->GetID(), + download_url, source_process_id(), render_frame_host()->GetRenderViewHost()->GetRoutingID(), render_frame_host()->GetRoutingID(), traffic_annotation));
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc index b75af54..923a556 100644 --- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc +++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -50,6 +50,7 @@ #include "content/public/browser/download_manager.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" @@ -672,6 +673,8 @@ current_browser(), url, ui::PAGE_TRANSITION_LINK); function->set_extension(extension_); function->SetRenderFrameHost(tab->GetMainFrame()); + function->set_source_process_id( + tab->GetMainFrame()->GetProcess()->GetID()); } }
diff --git a/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc b/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc index 0556e1d3..9528629 100644 --- a/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc +++ b/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc
@@ -12,8 +12,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "extensions/browser/api/file_handlers/app_file_handler_util.h" namespace image_writer_api = extensions::api::image_writer_private; @@ -97,8 +95,8 @@ base::FilePath path; if (!extensions::app_file_handler_util::ValidateFileEntryAndGetPath( - filesystem_name, filesystem_path, - render_frame_host()->GetProcess()->GetID(), &path, &error_)) + filesystem_name, filesystem_path, source_process_id(), &path, + &error_)) return false; image_writer::OperationManager::Get(GetProfile())
diff --git a/chrome/browser/extensions/api/page_capture/page_capture_api.cc b/chrome/browser/extensions/api/page_capture/page_capture_api.cc index 3edc8b9..0d7ad81 100644 --- a/chrome/browser/extensions/api/page_capture/page_capture_api.cc +++ b/chrome/browser/extensions/api/page_capture/page_capture_api.cc
@@ -23,8 +23,6 @@ #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/mhtml_generation_params.h" #include "extensions/common/extension_messages.h" @@ -278,9 +276,8 @@ return; } - int child_id = render_frame_host()->GetProcess()->GetID(); - ChildProcessSecurityPolicy::GetInstance()->GrantReadFile( - child_id, mhtml_path_); + ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(source_process_id(), + mhtml_path_); std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); dict->SetString("mhtmlFilePath", mhtml_path_.value());
diff --git a/chrome/browser/extensions/api/settings_private/generated_time_zone_pref_base.cc b/chrome/browser/extensions/api/settings_private/generated_time_zone_pref_base.cc index de95d889..133958a 100644 --- a/chrome/browser/extensions/api/settings_private/generated_time_zone_pref_base.cc +++ b/chrome/browser/extensions/api/settings_private/generated_time_zone_pref_base.cc
@@ -37,7 +37,7 @@ void GeneratedTimeZonePrefBase::UpdateTimeZonePrefControlledBy( settings_api::PrefObject* out_pref) const { if (profile_->IsChild()) { - out_pref->controlled_by = settings_api::CONTROLLED_BY_USER_POLICY; + out_pref->controlled_by = settings_api::ControlledBy::CONTROLLED_BY_PARENT; out_pref->enforcement = settings_api::ENFORCEMENT_ENFORCED; } else if (chromeos::system::TimeZoneResolverManager:: IsTimeZoneResolutionPolicyControlled()) {
diff --git a/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.cc b/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.cc index 298ee34d..cc33832 100644 --- a/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.cc +++ b/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.cc
@@ -11,8 +11,6 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/api/tabs.h" #include "chrome/common/extensions/api/webrtc_desktop_capture_private.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/origin_util.h" #include "net/base/url_util.h" @@ -42,8 +40,8 @@ EXTENSION_FUNCTION_VALIDATE(args_->GetSize() > 0); EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &request_id_)); - DesktopCaptureRequestsRegistry::GetInstance()->AddRequest( - render_frame_host()->GetProcess()->GetID(), request_id_, this); + DesktopCaptureRequestsRegistry::GetInstance()->AddRequest(source_process_id(), + request_id_, this); args_->Remove(0, NULL);
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index ba2e99d3..1f6359d 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -293,8 +293,8 @@ }, { "name": "bypass-app-banner-engagement-checks", - // "owners": [ "your-team" ], - "expiry_milestone": 76 + "owners": [ "dominickn" ], + "expiry_milestone": 78 }, { "name": "calculate-native-win-occlusion", @@ -2244,15 +2244,6 @@ "expiry_milestone": -1 }, { - "name": "memlog-in-process", - "owners": [ "erikchen", "ssid", "etienneb", "alph" ], - // Memlog is Chrome's heap profiler. It is used for both automated and - // manual performance analysis. This flag allows a user or developer to - // capture a memlog without disturbing the situation under test by - // restarting to apply a switch. It should not be removed. - "expiry_milestone": -1 - }, - { "name": "memlog-sampling-rate", "owners": [ "erikchen", "ssid", "etienneb", "alph" ], // Memlog is Chrome's heap profiler. It is used for both automated and
diff --git a/chrome/browser/flag-never-expire-list.json b/chrome/browser/flag-never-expire-list.json index 880605b..9033305 100644 --- a/chrome/browser/flag-never-expire-list.json +++ b/chrome/browser/flag-never-expire-list.json
@@ -48,8 +48,6 @@ "list-all-display-modes", "load-media-router-component-extension", "memlog", - "memlog-keep-small-allocations", - "memlog-in-process", "memlog-sampling-rate", "memlog-stack-mode", "overlay-strategies",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 6c48402..7d0b02f 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -824,13 +824,6 @@ const char kMemlogModeBrowser[] = "Browser only"; const char kMemlogModeGpu[] = "GPU only"; -const char kMemlogInProcessName[] = "Heap profiling service process type."; -const char kMemlogInProcessDescription[] = - "Controls if the heap profiling service runs within the browser process " - "(default) or in a dedicated utility process."; -const char kMemlogInProcessEnabled[] = "In browser process"; -const char kMemlogInProcessDisabled[] = "As separate process"; - const char kMemlogSamplingRateName[] = "Heap profiling sampling interval (in bytes)."; const char kMemlogSamplingRateDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index f085421b..9b2599c 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -485,11 +485,6 @@ extern const char kMemlogModeManual[]; extern const char kMemlogModeRendererSampling[]; -extern const char kMemlogInProcessName[]; -extern const char kMemlogInProcessDescription[]; -extern const char kMemlogInProcessDisabled[]; -extern const char kMemlogInProcessEnabled[]; - extern const char kMemlogSamplingRateName[]; extern const char kMemlogSamplingRateDescription[]; extern const char kMemlogSamplingRate10KB[];
diff --git a/chrome/browser/notifications/scheduler/BUILD.gn b/chrome/browser/notifications/scheduler/BUILD.gn index 8cef5e6..4329d019 100644 --- a/chrome/browser/notifications/scheduler/BUILD.gn +++ b/chrome/browser/notifications/scheduler/BUILD.gn
@@ -88,6 +88,8 @@ "notification_scheduler_context.h", "proto_conversion.cc", "proto_conversion.h", + "scheduled_notification_manager.cc", + "scheduled_notification_manager.h", "scheduler_config.cc", "scheduler_config.h", "scheduler_utils.cc", @@ -113,6 +115,7 @@ "impression_history_tracker_unittest.cc", "impression_store_unittest.cc", "proto_conversion_unittest.cc", + "scheduled_notification_manager_unittest.cc", "scheduler_utils_unittest.cc", ]
diff --git a/chrome/browser/notifications/scheduler/notification_entry.cc b/chrome/browser/notifications/scheduler/notification_entry.cc index 8703595..c85bb0cd 100644 --- a/chrome/browser/notifications/scheduler/notification_entry.cc +++ b/chrome/browser/notifications/scheduler/notification_entry.cc
@@ -10,7 +10,7 @@ NotificationEntry::NotificationEntry(SchedulerClientType type, const std::string& guid) - : type(type), guid(guid) {} + : type(type), guid(guid), create_time(base::Time::Now()) {} NotificationEntry::NotificationEntry(const NotificationEntry& other) = default;
diff --git a/chrome/browser/notifications/scheduler/notification_entry.h b/chrome/browser/notifications/scheduler/notification_entry.h index 9dc8cb91..2adb0d8 100644 --- a/chrome/browser/notifications/scheduler/notification_entry.h +++ b/chrome/browser/notifications/scheduler/notification_entry.h
@@ -7,6 +7,7 @@ #include <string> +#include "base/time/time.h" #include "chrome/browser/notifications/scheduler/notification_data.h" #include "chrome/browser/notifications/scheduler/notification_scheduler_types.h" #include "chrome/browser/notifications/scheduler/schedule_params.h" @@ -26,6 +27,9 @@ // The unique id of the notification database entry. std::string guid; + // Creation timestamp. + base::Time create_time; + // Contains information to construct the notification. NotificationData notification_data;
diff --git a/chrome/browser/notifications/scheduler/notification_params.cc b/chrome/browser/notifications/scheduler/notification_params.cc index bf42f6b..8cf8ab81 100644 --- a/chrome/browser/notifications/scheduler/notification_params.cc +++ b/chrome/browser/notifications/scheduler/notification_params.cc
@@ -6,15 +6,17 @@ #include <utility> +#include "base/guid.h" #include "chrome/browser/notifications/scheduler/schedule_params.h" namespace notifications { NotificationParams::NotificationParams(SchedulerClientType type, - NotificationData notification, + NotificationData notification_data, ScheduleParams schedule_params) : type(type), - notification(std::move(notification)), + guid(base::GenerateGUID()), + notification_data(std::move(notification_data)), schedule_params(std::move(schedule_params)) {} NotificationParams::~NotificationParams() = default;
diff --git a/chrome/browser/notifications/scheduler/notification_params.h b/chrome/browser/notifications/scheduler/notification_params.h index 5b684f9c..6bfabf7 100644 --- a/chrome/browser/notifications/scheduler/notification_params.h +++ b/chrome/browser/notifications/scheduler/notification_params.h
@@ -23,9 +23,12 @@ // The type of notification using the scheduling system. SchedulerClientType type; + // An auto generated unique id of the scheduled notification. + std::string guid; + // Data used to show the notification, such as text or title on the // notification. - NotificationData notification; + NotificationData notification_data; // Scheduling details used to determine when to show the notification. ScheduleParams schedule_params;
diff --git a/chrome/browser/notifications/scheduler/scheduled_notification_manager.cc b/chrome/browser/notifications/scheduler/scheduled_notification_manager.cc new file mode 100644 index 0000000..3b1badb --- /dev/null +++ b/chrome/browser/notifications/scheduler/scheduled_notification_manager.cc
@@ -0,0 +1,140 @@ +// Copyright 2019 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 "chrome/browser/notifications/scheduler/scheduled_notification_manager.h" + +#include <algorithm> +#include <map> + +#include "base/bind.h" +#include "base/guid.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/notifications/scheduler/notification_entry.h" +#include "chrome/browser/notifications/scheduler/notification_params.h" + +namespace notifications { +namespace { + +// Comparator used to sort notification entries based on creation time. +bool CreateTimeCompare(const NotificationEntry* lhs, + const NotificationEntry* rhs) { + DCHECK(lhs && rhs); + return lhs->create_time <= rhs->create_time; +} + +class ScheduledNotificationManagerImpl : public ScheduledNotificationManager { + public: + using Store = std::unique_ptr<CollectionStore<NotificationEntry>>; + + ScheduledNotificationManagerImpl(Store store, Delegate* delegate) + : store_(std::move(store)), + delegate_(delegate), + weak_ptr_factory_(this) {} + + private: + void Init(InitCallback callback) override { + store_->InitAndLoad( + base::BindOnce(&ScheduledNotificationManagerImpl::OnStoreInitialized, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); + } + + // NotificationManager implementation. + void ScheduleNotification( + std::unique_ptr<NotificationParams> notification_params) override { + DCHECK(notification_params); + std::string guid = notification_params->guid; + DCHECK(!guid.empty()); + if (notifications_.find(guid) != notifications_.end()) { + // TODO(xingliu): Report duplicate guid failure. + return; + } + + auto entry = + std::make_unique<NotificationEntry>(notification_params->type, guid); + entry->notification_data = + std::move(notification_params->notification_data); + entry->schedule_params = std::move(notification_params->schedule_params); + auto* entry_ptr = entry.get(); + notifications_.emplace(guid, std::move(entry)); + store_->Add( + guid, *entry_ptr, + base::BindOnce(&ScheduledNotificationManagerImpl::OnNotificationAdded, + weak_ptr_factory_.GetWeakPtr())); + } + + void DisplayNotification(const std::string& guid) override { + auto it = notifications_.find(guid); + if (it == notifications_.end()) + return; + + // Move the entry to delegate, and delete it from the storage. + auto notification_entry = std::move(it->second); + notifications_.erase(guid); + store_->Delete( + guid, + base::BindOnce(&ScheduledNotificationManagerImpl::OnNotificationDeleted, + weak_ptr_factory_.GetWeakPtr())); + if (delegate_) + delegate_->DisplayNotification(std::move(notification_entry)); + } + + void GetAllNotifications(Notifications* notifications) override { + DCHECK(notifications); + + for (const auto& pair : notifications_) { + const auto& notif = pair.second; + DCHECK(notif); + (*notifications)[notif->type].emplace_back(notif.get()); + } + + // Sort by creation time for each notification type. + for (auto it = notifications->begin(); it != notifications->end(); ++it) { + std::sort(it->second.begin(), it->second.end(), &CreateTimeCompare); + } + } + + void OnStoreInitialized(InitCallback callback, + bool success, + CollectionStore<NotificationEntry>::Entries entries) { + if (!success) { + std::move(callback).Run(false); + return; + } + + for (auto it = entries.begin(); it != entries.end(); ++it) { + std::string guid = (*it)->guid; + notifications_.emplace(guid, std::move(*it)); + } + + std::move(callback).Run(true); + } + + void OnNotificationAdded(bool success) { NOTIMPLEMENTED(); } + + void OnNotificationDeleted(bool success) { NOTIMPLEMENTED(); } + + Store store_; + Delegate* delegate_; + std::map<std::string, std::unique_ptr<NotificationEntry>> notifications_; + + base::WeakPtrFactory<ScheduledNotificationManagerImpl> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(ScheduledNotificationManagerImpl); +}; + +} // namespace + +// static +std::unique_ptr<ScheduledNotificationManager> +ScheduledNotificationManager::Create( + std::unique_ptr<CollectionStore<NotificationEntry>> store, + Delegate* delegate) { + return std::make_unique<ScheduledNotificationManagerImpl>(std::move(store), + delegate); +} + +ScheduledNotificationManager::ScheduledNotificationManager() = default; + +ScheduledNotificationManager::~ScheduledNotificationManager() = default; + +} // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/scheduled_notification_manager.h b/chrome/browser/notifications/scheduler/scheduled_notification_manager.h new file mode 100644 index 0000000..01293a5 --- /dev/null +++ b/chrome/browser/notifications/scheduler/scheduled_notification_manager.h
@@ -0,0 +1,74 @@ +// Copyright 2019 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 CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_SCHEDULED_NOTIFICATION_MANAGER_H_ +#define CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_SCHEDULED_NOTIFICATION_MANAGER_H_ + +#include <map> +#include <memory> +#include <string> + +#include "base/callback.h" +#include "base/macros.h" +#include "chrome/browser/notifications/scheduler/collection_store.h" +#include "chrome/browser/notifications/scheduler/notification_scheduler_types.h" + +namespace notifications { + +struct NotificationEntry; +struct NotificationParams; + +// Class to manage in-memory scheduled notifications loaded from the storage. +class ScheduledNotificationManager { + public: + using InitCallback = base::OnceCallback<void(bool)>; + using Notifications = + std::map<SchedulerClientType, std::vector<const NotificationEntry*>>; + + // Delegate that receives events from the manager. + class Delegate { + public: + // Displays a notification to the user. + virtual void DisplayNotification( + std::unique_ptr<NotificationEntry> notification) = 0; + + Delegate() = default; + virtual ~Delegate() = default; + + private: + DISALLOW_COPY_AND_ASSIGN(Delegate); + }; + + // Creates the instance. + static std::unique_ptr<ScheduledNotificationManager> Create( + std::unique_ptr<CollectionStore<NotificationEntry>> store, + Delegate* delegate); + + // Initializes the notification store. + virtual void Init(InitCallback callback) = 0; + + // Adds a new notification. + virtual void ScheduleNotification( + std::unique_ptr<NotificationParams> notification_params) = 0; + + // Displays a notification, the scheduled notification will be removed from + // storage, then Delegate::DisplayNotification() should be invoked. + virtual void DisplayNotification(const std::string& guid) = 0; + + // Gets all scheduled notifications. For each type, notifications are sorted + // by creation timestamp. + virtual void GetAllNotifications(Notifications* notifications) = 0; + + virtual ~ScheduledNotificationManager(); + + protected: + ScheduledNotificationManager(); + + private: + DISALLOW_COPY_AND_ASSIGN(ScheduledNotificationManager); +}; + +} // namespace notifications + +#endif // CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_SCHEDULED_NOTIFICATION_MANAGER_H_
diff --git a/chrome/browser/notifications/scheduler/scheduled_notification_manager_unittest.cc b/chrome/browser/notifications/scheduler/scheduled_notification_manager_unittest.cc new file mode 100644 index 0000000..43d350a9 --- /dev/null +++ b/chrome/browser/notifications/scheduler/scheduled_notification_manager_unittest.cc
@@ -0,0 +1,228 @@ +// Copyright 2019 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 "chrome/browser/notifications/scheduler/scheduled_notification_manager.h" + +#include "base/bind.h" +#include "base/guid.h" +#include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" +#include "chrome/browser/notifications/scheduler/collection_store.h" +#include "chrome/browser/notifications/scheduler/notification_entry.h" +#include "chrome/browser/notifications/scheduler/notification_params.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; +using ::testing::Invoke; +using Entries = std::vector<std::unique_ptr<notifications::NotificationEntry>>; + +namespace notifications { +namespace { + +const char kGuid[] = "test_guid_1234"; +const char kTitle[] = "test_title"; + +NotificationEntry CreateNotificationEntry() { + return NotificationEntry(SchedulerClientType::kUnknown, base::GenerateGUID()); +} + +class MockDelegate : public ScheduledNotificationManager::Delegate { + public: + MockDelegate() = default; + MOCK_METHOD1(DisplayNotification, void(std::unique_ptr<NotificationEntry>)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockDelegate); +}; + +class MockNotificationStore : public CollectionStore<NotificationEntry> { + public: + MockNotificationStore() {} + + MOCK_METHOD1(InitAndLoad, + void(CollectionStore<NotificationEntry>::LoadCallback)); + MOCK_METHOD3(Add, + void(const std::string&, + const NotificationEntry&, + base::OnceCallback<void(bool)>)); + MOCK_METHOD3(Update, + void(const std::string&, + const NotificationEntry&, + base::OnceCallback<void(bool)>)); + MOCK_METHOD2(Delete, + void(const std::string&, base::OnceCallback<void(bool)>)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockNotificationStore); +}; + +class ScheduledNotificationManagerTest : public testing::Test { + public: + ScheduledNotificationManagerTest() : store_(nullptr) {} + ~ScheduledNotificationManagerTest() override = default; + + void SetUp() override { + delegate_ = std::make_unique<MockDelegate>(); + auto store = std::make_unique<MockNotificationStore>(); + store_ = store.get(); + manager_ = + ScheduledNotificationManager::Create(std::move(store), delegate_.get()); + } + + protected: + ScheduledNotificationManager* manager() { return manager_.get(); } + MockNotificationStore* store() { return store_; } + MockDelegate* delegate() { return delegate_.get(); } + + // Initializes the manager with predefined data in the store. + void InitWithData(std::vector<NotificationEntry> data) { + Entries entries; + for (auto it = data.begin(); it != data.end(); ++it) { + auto entry_ptr = std::make_unique<NotificationEntry>( + SchedulerClientType::kUnknown, it->guid); + *(entry_ptr.get()) = *it; + entries.emplace_back(std::move(entry_ptr)); + } + + // Initialize the store and call the callback. + EXPECT_CALL(*store(), InitAndLoad(_)) + .WillOnce( + Invoke([&entries](base::OnceCallback<void(bool, Entries)> cb) { + std::move(cb).Run(true, std::move(entries)); + })); + base::RunLoop loop; + manager()->Init(base::BindOnce( + [](base::RepeatingClosure closure, bool success) { + EXPECT_TRUE(success); + std::move(closure).Run(); + }, + loop.QuitClosure())); + loop.Run(); + } + + private: + base::test::ScopedTaskEnvironment scoped_task_environment_; + std::unique_ptr<MockDelegate> delegate_; + MockNotificationStore* store_; + std::unique_ptr<ScheduledNotificationManager> manager_; + DISALLOW_COPY_AND_ASSIGN(ScheduledNotificationManagerTest); +}; + +// Verify that error is received when initialization failed. +TEST_F(ScheduledNotificationManagerTest, InitFailed) { + EXPECT_CALL(*store(), InitAndLoad(_)) + .WillOnce(Invoke([](base::OnceCallback<void(bool, Entries)> cb) { + std::move(cb).Run(false, Entries()); + })); + + base::RunLoop loop; + manager()->Init(base::BindOnce( + [](base::RepeatingClosure closure, bool success) { + // Expected to receive error. + EXPECT_FALSE(success); + std::move(closure).Run(); + }, + loop.QuitClosure())); + loop.Run(); +} + +// Test to schedule a notification. +TEST_F(ScheduledNotificationManagerTest, ScheduleNotification) { + InitWithData(std::vector<NotificationEntry>()); + NotificationData notification_data; + notification_data.title = kTitle; + ScheduleParams schedule_params; + schedule_params.priority = ScheduleParams::Priority::kHigh; + auto params = std::make_unique<NotificationParams>( + SchedulerClientType::kUnknown, notification_data, schedule_params); + std::string guid = params->guid; + EXPECT_FALSE(guid.empty()); + + // Verify call contract. + EXPECT_CALL(*store(), Add(guid, _, _)); + manager()->ScheduleNotification(std::move(params)); + + // Verify in-memory data. + ScheduledNotificationManager::Notifications notifications; + manager()->GetAllNotifications(¬ifications); + EXPECT_EQ(notifications.size(), 1u); + const NotificationEntry* entry = *(notifications.begin()->second.begin()); + EXPECT_EQ(entry->guid, guid); + EXPECT_NE(entry->create_time, base::Time()); + + // TODO(xingliu): change these to compare with operator==. + EXPECT_EQ(entry->notification_data.title, kTitle); + EXPECT_EQ(entry->schedule_params.priority, ScheduleParams::Priority::kHigh); +} + +// Test to schedule a notification without guid, we will auto generated one. +TEST_F(ScheduledNotificationManagerTest, ScheduleNotificationEmptyGuid) { + InitWithData(std::vector<NotificationEntry>()); + auto params = std::make_unique<NotificationParams>( + SchedulerClientType::kUnknown, NotificationData(), ScheduleParams()); + + // Verify call contract. + EXPECT_CALL(*store(), Add(_, _, _)); + manager()->ScheduleNotification(std::move(params)); + + // Verify in-memory data. + ScheduledNotificationManager::Notifications notifications; + manager()->GetAllNotifications(¬ifications); + EXPECT_EQ(notifications.size(), 1u); + const NotificationEntry* entry = *(notifications.begin()->second.begin()); + EXPECT_NE(entry->guid, std::string()); + EXPECT_NE(entry->create_time, base::Time()); +} + +// TODO(xingliu): change this to compare with operator==. +MATCHER_P(NotificationEntryIs, expected, "") { + return arg->guid == expected.guid; +} + +// Test to display a notification. +TEST_F(ScheduledNotificationManagerTest, DisplayNotification) { + auto entry = CreateNotificationEntry(); + entry.guid = kGuid; + InitWithData(std::vector<NotificationEntry>({entry})); + + // Verify delegate and dependency call contract. + EXPECT_CALL(*store(), Delete(kGuid, _)); + EXPECT_CALL(*delegate(), DisplayNotification(NotificationEntryIs(entry))); + manager()->DisplayNotification(kGuid); + + // Verify in-memory data. + ScheduledNotificationManager::Notifications notifications; + manager()->GetAllNotifications(¬ifications); + EXPECT_TRUE(notifications.empty()); +} + +// Verify GetAllNotifications API, the notification should be sorted based on +// creation timestamp. +TEST_F(ScheduledNotificationManagerTest, GetAllNotifications) { + // Ordering: entry1.create_time < entry0.create_time < entry2.create_time. + auto now = base::Time::Now(); + auto entry0 = CreateNotificationEntry(); + entry0.create_time = now; + auto entry1 = CreateNotificationEntry(); + entry1.create_time = now - base::TimeDelta::FromMinutes(1); + auto entry2 = CreateNotificationEntry(); + entry2.create_time = now + base::TimeDelta::FromMinutes(1); + + InitWithData(std::vector<NotificationEntry>({entry0, entry1, entry2})); + ScheduledNotificationManager::Notifications notifications; + manager()->GetAllNotifications(¬ifications); + EXPECT_EQ(notifications.size(), 1u); + EXPECT_EQ(notifications.begin()->second.size(), 3u); + + // Entries returned by GetAllNotifications() should be sorted by creation + // timestamp. + const NotificationEntry* output0 = notifications.begin()->second.front(); + const NotificationEntry* output2 = notifications.begin()->second.back(); + EXPECT_EQ(output0->create_time, entry1.create_time); + EXPECT_EQ(output2->create_time, entry2.create_time); +} + +} // namespace +} // namespace notifications
diff --git a/chrome/browser/profiling_host/memlog_browsertest.cc b/chrome/browser/profiling_host/memlog_browsertest.cc index 074f641..89a5a19e 100644 --- a/chrome/browser/profiling_host/memlog_browsertest.cc +++ b/chrome/browser/profiling_host/memlog_browsertest.cc
@@ -34,7 +34,6 @@ struct TestParam { Mode mode; mojom::StackMode stack_mode; - bool stream_samples; bool start_profiling_with_command_line_flag; bool should_sample; bool sample_everything; @@ -45,11 +44,6 @@ void SetUpDefaultCommandLine(base::CommandLine* command_line) override { InProcessBrowserTest::SetUpDefaultCommandLine(command_line); - if (GetParam().stream_samples) { - command_line->AppendSwitchASCII(heap_profiling::kMemlogInProcess, - heap_profiling::kMemlogInProcessDisabled); - } - if (!GetParam().start_profiling_with_command_line_flag) return; @@ -99,7 +93,6 @@ IN_PROC_BROWSER_TEST_P(MemlogBrowserTest, MAYBE_EndToEnd) { LOG(INFO) << "Memlog mode: " << static_cast<int>(GetParam().mode); LOG(INFO) << "Memlog stack mode: " << static_cast<int>(GetParam().stack_mode); - LOG(INFO) << "Stream samples: " << GetParam().stream_samples; LOG(INFO) << "Started via command line flag: " << GetParam().start_profiling_with_command_line_flag; LOG(INFO) << "Should sample: " << GetParam().should_sample; @@ -108,7 +101,6 @@ TestDriver::Options options; options.mode = GetParam().mode; options.stack_mode = GetParam().stack_mode; - options.stream_samples = GetParam().stream_samples; options.profiling_already_started = GetParam().start_profiling_with_command_line_flag; options.should_sample = GetParam().should_sample; @@ -132,10 +124,12 @@ stack_modes.push_back(mojom::StackMode::NATIVE_WITHOUT_THREAD_NAMES); stack_modes.push_back(mojom::StackMode::PSEUDO); - for (bool stream_samples : (bool[]){true, false}) { + // TODO(https://crbug.com/923459): The outer loop is left in place to keep + // the parameterized tests order. Remove it in a follow-up patch. + for (int i = 0; i < 2; ++i) { for (const auto& mode : dynamic_start_modes) { for (const auto& stack_mode : stack_modes) { - params.push_back({mode, stack_mode, stream_samples, + params.push_back({mode, stack_mode, false /* start_profiling_with_command_line_flag */, true /* should_sample */, false /* sample_everything*/}); @@ -155,7 +149,7 @@ command_line_start_modes.push_back(Mode::kAllRenderers); for (const auto& mode : command_line_start_modes) { for (const auto& stack_mode : stack_modes) { - params.push_back({mode, stack_mode, stream_samples, + params.push_back({mode, stack_mode, true /* start_profiling_with_command_line_flag */, true /* should_sample */, false /* sample_everything*/});
diff --git a/chrome/browser/resource_coordinator/tab_load_tracker.cc b/chrome/browser/resource_coordinator/tab_load_tracker.cc index ec9ca2a..143e0016 100644 --- a/chrome/browser/resource_coordinator/tab_load_tracker.cc +++ b/chrome/browser/resource_coordinator/tab_load_tracker.cc
@@ -223,8 +223,10 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // TabManager::ResourceCoordinatorSignalObserver filters late notifications // so here we can assume the event pertains to a live web_contents and - // its most recent navigation. - DCHECK(base::ContainsKey(tabs_, web_contents)); + // its most recent navigation. However, the graph tracks contents that aren't + // tracked by this object. + if (!base::ContainsKey(tabs_, web_contents)) + return; MaybeTransitionToLoaded(web_contents); }
diff --git a/chrome/browser/resource_coordinator/tab_load_tracker.h b/chrome/browser/resource_coordinator/tab_load_tracker.h index c16a0aab..92e97de 100644 --- a/chrome/browser/resource_coordinator/tab_load_tracker.h +++ b/chrome/browser/resource_coordinator/tab_load_tracker.h
@@ -151,9 +151,8 @@ void RenderProcessGone(content::WebContents* web_contents, base::TerminationStatus status); - // This is an analog of a PageSignalObserver function. This class is not - // actually a PageSignalObserver, but these notifications are forwarded to it - // from the TabManager. + // Notifications to this are driven by the + // TabManager::ResourceCoordinatorSignalObserver. void OnPageAlmostIdle(content::WebContents* web_contents); // Returns true if |web_contents| is a UI tab and false otherwise. This is
diff --git a/chrome/browser/resource_coordinator/tab_manager.cc b/chrome/browser/resource_coordinator/tab_manager.cc index e73da5d..fa636cda 100644 --- a/chrome/browser/resource_coordinator/tab_manager.cc +++ b/chrome/browser/resource_coordinator/tab_manager.cc
@@ -183,10 +183,22 @@ #endif browser_tab_strip_tracker_.Init(); session_restore_observer_.reset(new TabManagerSessionRestoreObserver(this)); - if (performance_manager::PerformanceManager::GetInstance()) { - resource_coordinator_signal_observer_.reset( - new ResourceCoordinatorSignalObserver(page_signal_receiver)); + + // Create the graph observer. This is the source of page almost idle data and + // EQT measurements. + if (auto* perf_man = performance_manager::PerformanceManager::GetInstance()) { + // The performance manager is torn down on its own sequence so its safe to + // pass it unretained. The observer itself learns of the tab manager tear + // down via the weak ptr it is given. + perf_man->task_runner()->PostTask( + FROM_HERE, + base::BindOnce( + &performance_manager::PerformanceManager::RegisterObserver, + base::Unretained(perf_man), + std::make_unique<ResourceCoordinatorSignalObserver>( + weak_ptr_factory_.GetWeakPtr()))); } + stats_collector_.reset(new TabManagerStatsCollector()); proactive_freeze_discard_params_ = GetStaticProactiveTabFreezeAndDiscardParams(); @@ -200,7 +212,6 @@ TabManager::~TabManager() { tab_load_tracker_->RemoveObserver(this); - resource_coordinator_signal_observer_.reset(); if (metrics::DesktopSessionDurationTracker::IsInitialized()) metrics::DesktopSessionDurationTracker::Get()->RemoveObserver(this);
diff --git a/chrome/browser/resource_coordinator/tab_manager.h b/chrome/browser/resource_coordinator/tab_manager.h index bf78f2d4..6186551 100644 --- a/chrome/browser/resource_coordinator/tab_manager.h +++ b/chrome/browser/resource_coordinator/tab_manager.h
@@ -480,11 +480,6 @@ // in parallel. size_t loading_slots_; - // |resource_coordinator_signal_observer_| is owned by TabManager and is used - // to receive various signals from ResourceCoordinator. - std::unique_ptr<ResourceCoordinatorSignalObserver> - resource_coordinator_signal_observer_; - // Records UMAs for tab and system-related events and properties during // session restore. std::unique_ptr<TabManagerStatsCollector> stats_collector_;
diff --git a/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.cc b/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.cc index f7eee2104..86755647 100644 --- a/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.cc +++ b/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.cc
@@ -4,13 +4,19 @@ #include "chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.h" +#include "base/task/post_task.h" #include "base/time/time.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/performance_manager/graph/frame_node_impl.h" +#include "chrome/browser/performance_manager/graph/page_node_impl.h" +#include "chrome/browser/performance_manager/graph/process_node_impl.h" #include "chrome/browser/resource_coordinator/resource_coordinator_parts.h" #include "chrome/browser/resource_coordinator/tab_load_tracker.h" #include "chrome/browser/resource_coordinator/tab_manager_stats_collector.h" #include "chrome/browser/resource_coordinator/tab_manager_web_contents_data.h" #include "chrome/browser/resource_coordinator/utils.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" namespace resource_coordinator { @@ -20,53 +26,100 @@ class TabManagerResourceCoordinatorSignalObserverHelper { public: static void OnPageAlmostIdle(content::WebContents* web_contents) { + // This object is create on demand, so always exists. TabLoadTracker::Get()->OnPageAlmostIdle(web_contents); } }; TabManager::ResourceCoordinatorSignalObserver:: - ResourceCoordinatorSignalObserver(PageSignalReceiver* page_signal_receiver) - : page_signal_receiver_(page_signal_receiver) { - if (page_signal_receiver_) - page_signal_receiver_->AddObserver(this); -} + ResourceCoordinatorSignalObserver( + const base::WeakPtr<TabManager>& tab_manager) + : tab_manager_(tab_manager) {} TabManager::ResourceCoordinatorSignalObserver:: - ~ResourceCoordinatorSignalObserver() { - if (page_signal_receiver_) - page_signal_receiver_->RemoveObserver(this); + ~ResourceCoordinatorSignalObserver() = default; + +bool TabManager::ResourceCoordinatorSignalObserver::ShouldObserve( + const NodeBase* node) { + return node->id().type == resource_coordinator::CoordinationUnitType::kPage || + node->id().type == + resource_coordinator::CoordinationUnitType::kProcess; } -void TabManager::ResourceCoordinatorSignalObserver::OnPageAlmostIdle( - content::WebContents* web_contents, - const PageNavigationIdentity& page_navigation_id) { - DCHECK_NE(nullptr, page_signal_receiver_); - - // Only dispatch the event if it pertains to the current navigation. - if (page_signal_receiver_->GetNavigationIDForWebContents(web_contents) == - page_navigation_id.navigation_id) { - TabManagerResourceCoordinatorSignalObserverHelper::OnPageAlmostIdle( - web_contents); - } +void TabManager::ResourceCoordinatorSignalObserver::OnPageAlmostIdleChanged( + PageNodeImpl* page_node) { + // Only notify of changes to almost idle. + if (!page_node->page_almost_idle()) + return; + // Forward the notification over to the UI thread. + base::PostTaskWithTraits( + FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(&OnPageAlmostIdleOnUi, tab_manager_, + page_node->contents_proxy(), page_node->navigation_id())); } void TabManager::ResourceCoordinatorSignalObserver:: - OnExpectedTaskQueueingDurationSet( - content::WebContents* web_contents, - const PageNavigationIdentity& page_navigation_id, - base::TimeDelta duration) { - DCHECK_NE(nullptr, page_signal_receiver_); + OnExpectedTaskQueueingDurationSample(ProcessNodeImpl* process_node) { + // Report this measurement to all pages that are hosting a main frame in + // the process that was sampled. + const base::TimeDelta& duration = + process_node->expected_task_queueing_duration(); + for (auto* frame_node : process_node->GetFrameNodes()) { + if (!frame_node->IsMainFrame()) + continue; + auto* page_node = frame_node->page_node(); - if (page_signal_receiver_->GetNavigationIDForWebContents(web_contents) != - page_navigation_id.navigation_id) { - // |web_contents| has been re-navigated, drop this notification rather than - // recording it against the wrong origin. - return; + // Forward the notification over to the UI thread. + base::PostTaskWithTraits( + FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(&OnExpectedTaskQueueingDurationSampleOnUi, tab_manager_, + page_node->contents_proxy(), page_node->navigation_id(), + duration)); } +} - g_browser_process->GetTabManager() - ->stats_collector() - ->RecordExpectedTaskQueueingDuration(web_contents, duration); +// static +content::WebContents* +TabManager::ResourceCoordinatorSignalObserver::GetContentsForDispatch( + const base::WeakPtr<TabManager>& tab_manager, + const base::WeakPtr<WebContentsProxy>& contents_proxy, + int64_t navigation_id) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!tab_manager.get() || !contents_proxy.get() || + contents_proxy.get()->LastNavigationId() != navigation_id) { + return nullptr; + } + return contents_proxy.get()->GetWebContents(); +} + +// static +void TabManager::ResourceCoordinatorSignalObserver::OnPageAlmostIdleOnUi( + const base::WeakPtr<TabManager>& tab_manager, + const base::WeakPtr<WebContentsProxy>& contents_proxy, + int64_t navigation_id) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (auto* contents = + GetContentsForDispatch(tab_manager, contents_proxy, navigation_id)) { + TabManagerResourceCoordinatorSignalObserverHelper::OnPageAlmostIdle( + contents); + } +} + +// static +void TabManager::ResourceCoordinatorSignalObserver:: + OnExpectedTaskQueueingDurationSampleOnUi( + const base::WeakPtr<TabManager>& tab_manager, + const base::WeakPtr<WebContentsProxy>& contents_proxy, + int64_t navigation_id, + base::TimeDelta duration) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (auto* contents = + GetContentsForDispatch(tab_manager, contents_proxy, navigation_id)) { + // This object is create on demand, so always exists. + g_browser_process->GetTabManager() + ->stats_collector() + ->RecordExpectedTaskQueueingDuration(contents, duration); + } } } // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.h b/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.h index 778ba64..43782e5 100644 --- a/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.h +++ b/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.h
@@ -6,6 +6,8 @@ #define CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_RESOURCE_COORDINATOR_SIGNAL_OBSERVER_H_ #include "base/macros.h" +#include "chrome/browser/performance_manager/observers/graph_observer.h" +#include "chrome/browser/performance_manager/web_contents_proxy.h" #include "chrome/browser/resource_coordinator/page_signal_receiver.h" #include "chrome/browser/resource_coordinator/tab_manager.h" @@ -15,24 +17,54 @@ // interfaces, for example it currently implements PageSignalObserver but can // implement more; and receives signals from resource coordinator through those // interfaces. +// TODO(chrisha): Kill this thing entirely and move all of tab manager into the +// performance manager. class TabManager::ResourceCoordinatorSignalObserver - : public PageSignalObserver { + : public performance_manager::GraphObserver { public: + using NodeBase = performance_manager::NodeBase; + using PageNodeImpl = performance_manager::PageNodeImpl; + using ProcessNodeImpl = performance_manager::ProcessNodeImpl; + using WebContentsProxy = performance_manager::WebContentsProxy; + explicit ResourceCoordinatorSignalObserver( - PageSignalReceiver* page_signal_receiver); + const base::WeakPtr<TabManager>& tab_manager); ~ResourceCoordinatorSignalObserver() override; - // PageSignalObserver implementation. - void OnPageAlmostIdle( - content::WebContents* web_contents, - const PageNavigationIdentity& page_navigation_id) override; - void OnExpectedTaskQueueingDurationSet( - content::WebContents* web_contents, - const PageNavigationIdentity& page_navigation_id, - base::TimeDelta duration) override; + // GraphObserver: + // These functions run on the performance manager sequence. + bool ShouldObserve(const NodeBase* node) override; + void OnPageAlmostIdleChanged(PageNodeImpl* page_node) override; + void OnExpectedTaskQueueingDurationSample( + ProcessNodeImpl* process_node) override; private: - PageSignalReceiver* const page_signal_receiver_; + // Determines if a message should still be dispatched for the given + // |tab_manager|, |contents_proxy| and |navigation_id|. If so, returns the + // WebContents, otherwise returns nullptr. This should only be called on the + // UI thread. + static content::WebContents* GetContentsForDispatch( + const base::WeakPtr<TabManager>& tab_manager, + const base::WeakPtr<WebContentsProxy>& contents_proxy, + int64_t navigation_id); + + // Equivalent to the the GraphObserver functions above, but these are the + // counterparts that run on the UI thread. + static void OnPageAlmostIdleOnUi( + const base::WeakPtr<TabManager>& tab_manager, + const base::WeakPtr<WebContentsProxy>& contents_proxy, + int64_t navigation_id); + static void OnExpectedTaskQueueingDurationSampleOnUi( + const base::WeakPtr<TabManager>& tab_manager, + const base::WeakPtr<WebContentsProxy>& contents_proxy, + int64_t navigation_id, + base::TimeDelta duration); + + // Can only be dereferenced on the UI thread. When the tab manager dies this + // is used to drop messages received from the performance manager. Ideally + // we'd also then tear down this observer on the perf manager sequence itself, + // but when one dies they're both about to die. + base::WeakPtr<TabManager> tab_manager_; DISALLOW_COPY_AND_ASSIGN(ResourceCoordinatorSignalObserver); };
diff --git a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog.html b/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog.html index 76b33c6..5e56d30 100644 --- a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog.html +++ b/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog.html
@@ -37,7 +37,8 @@ </style> <bluetooth-dialog id="deviceDialog" no-cancel on-close="onDialogClose_" - pairing-device="[[pairingDevice_]]"> + pairing-device="[[pairingDevice_]]" + dialog-title="$i18n{bluetoothPairDeviceTitle}"> </bluetooth-dialog> </template> <script src="bluetooth_pairing_dialog.js"></script>
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js index ada6cbc..417f625 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
@@ -266,14 +266,17 @@ var root = this.node_.root; if (!root || !root.selectionStartObject || !root.selectionEndObject || - root.selectionStartOffset === undefined || - root.selectionEndOffset === undefined) + !root.focusObject || root.selectionStartOffset === undefined || + root.selectionEndOffset === undefined || root.focusOffset === undefined) return; - this.anchorLine_ = new editing.EditableLine( + this.startLine_ = new editing.EditableLine( root.selectionStartObject, root.selectionStartOffset, root.selectionStartObject, root.selectionStartOffset); - this.focusLine_ = new editing.EditableLine( + + // TODO(nektar): |focus| below should be |end|. Change once new selection code + // lands. + this.endLine_ = new editing.EditableLine( root.focusObject, root.focusOffset, root.focusObject, root.focusOffset); this.line_ = new editing.EditableLine( @@ -361,27 +364,30 @@ onUpdate: function(eventFrom) { var root = this.node_.root; if (!root.selectionStartObject || !root.selectionEndObject || - root.selectionStartOffset === undefined || - root.selectionEndOffset === undefined) + !root.focusObject || root.selectionStartOffset === undefined || + root.selectionEndOffset === undefined || root.focusOffset === undefined) return; - var anchorLine = new editing.EditableLine( + var startLine = new editing.EditableLine( root.selectionStartObject, root.selectionStartOffset, root.selectionStartObject, root.selectionStartOffset); - var focusLine = new editing.EditableLine( + + // TODO(nektar): |focus| below should be |end|. Change once new selection + // code lands. + var endLine = new editing.EditableLine( root.focusObject, root.focusOffset, root.focusObject, root.focusOffset); - var prevAnchorLine = this.anchorLine_; - var prevFocusLine = this.focusLine_; - this.anchorLine_ = anchorLine; - this.focusLine_ = focusLine; + var prevStartLine = this.startLine_; + var prevEndLine = this.endLine_; + this.startLine_ = startLine; + this.endLine_ = endLine; // Compute the current line based upon whether the current selection was // extended from anchor or focus. The default behavior is to compute lines // via focus. - var baseLineOnStart = prevFocusLine.isSameLineAndSelection(focusLine); + var baseLineOnStart = prevEndLine.isSameLineAndSelection(endLine); var isSameSelection = - baseLineOnStart && prevAnchorLine.isSameLineAndSelection(anchorLine); + baseLineOnStart && prevStartLine.isSameLineAndSelection(startLine); var cur; if (isSameSelection && this.line_) { @@ -411,8 +417,8 @@ // We must validate the previous lines as state changes in the accessibility // tree may have invalidated the lines. - if (anchorLine.isSameLine(prevAnchorLine) && - focusLine.isSameLine(prevFocusLine)) { + if (startLine.isSameLine(prevStartLine) && + endLine.isSameLine(prevEndLine)) { // Intra-line changes. var text = cur.text; if (text == '\n') @@ -462,14 +468,14 @@ // unordered (i.e. anchor is where the selection starts and focus // where it ends). The latter is correct. Change this once Blink // ax gets fixed. - var curBase = baseLineOnStart ? focusLine : anchorLine; + var curBase = baseLineOnStart ? endLine : startLine; if ((cur.startContainer_.role == RoleType.TEXT_FIELD || (cur.startContainer_ == prev.startContainer_ && cur.endContainer_ == prev.endContainer_)) && cur.startContainerValue_ != prev.startContainerValue_) { // This block catches text changes between |prev| and | cur|. Note that we - // can end up here if |prevAnchorLine| or |prevFocusLine| were invalid + // can end up here if |prevStartLine| or |prevEndLine| were invalid // above for intra-line changes. This block therefore catches all text // changes including those that occur within a single line and up to those // that occur within a static text. It also catches text changes that @@ -497,12 +503,12 @@ .go(); } else if ( !cur.hasCollapsedSelection() && - (curBase.isSameLine(prevAnchorLine) || - curBase.isSameLine(prevFocusLine))) { + (curBase.isSameLine(prevStartLine) || + curBase.isSameLine(prevEndLine))) { // This is a selection that gets extended from the same anchor. // Speech requires many more states than braille. - var curExtent = baseLineOnStart ? anchorLine : focusLine; + var curExtent = baseLineOnStart ? startLine : endLine; var text = ''; var suffixMsg = ''; if (curBase.isBeforeLine(curExtent)) {
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js index 83f58f71..1757d55b 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js +++ b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js
@@ -113,6 +113,8 @@ loadTimeData.getString('controlledSettingWithOwner'), controlledSettingNoOwner: loadTimeData.getString('controlledSettingNoOwner'), + controlledSettingParent: + loadTimeData.getString('controlledSettingParent'), }; CrOncStrings = {
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.js b/chrome/browser/resources/settings/settings_ui/settings_ui.js index 2d14eb3..291bf5c 100644 --- a/chrome/browser/resources/settings/settings_ui/settings_ui.js +++ b/chrome/browser/resources/settings/settings_ui/settings_ui.js
@@ -114,6 +114,8 @@ loadTimeData.getString('controlledSettingWithOwner'), controlledSettingNoOwner: loadTimeData.getString('controlledSettingNoOwner'), + controlledSettingParent: + loadTimeData.getString('controlledSettingParent'), // </if> };
diff --git a/chrome/browser/search/README.md b/chrome/browser/search/README.md index ca61a61..567ce33 100644 --- a/chrome/browser/search/README.md +++ b/chrome/browser/search/README.md
@@ -7,10 +7,7 @@ variants are implemented as HTML/CSS/JS, but differ in where they are hosted. -* **Google**: either the **[Remote NTP][remote-ntp]** (as of - 2017-12-05, the default) or the **[Local NTP][local-ntp]**, with - Google branding (as of 2017-12-05, planned to replace the Remote NTP - and in experiments on Beta). +* **Google**: The **[Local NTP][local-ntp]**, with Google branding. * **Bing**, **Yandex**: a **[Third-Party NTP][third-party-ntp]**, where the NTP is hosted on third-party servers but Chrome provides @@ -32,7 +29,6 @@ the "Add shortcut" button, deleting/editing shortcuts from the three-dot "Edit shortcut" menu (replaces the "X" button), and reordering via click-and-drag. -[remote-ntp]: #remote-ntp [local-ntp]: #local-ntp [third-party-ntp]: #third_party-ntp [engines]: https://chromium.googlesource.com/chromium/src/+/master/components/search_engines/prepopulated_engines.json @@ -149,11 +145,6 @@ A non-Google local NTP shows only NTP tiles, with no branding. The tiles are centered within the page. -### Remote NTP - -The Remote NTP is hosted on Google servers. It is intended for removal, -and is not documented here. - ### Third-Party NTP TODO(sfiera)
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/app_search_result_ranker_unittest.cc b/chrome/browser/ui/app_list/search/search_result_ranker/app_search_result_ranker_unittest.cc index b1ed01e5..8b31555 100644 --- a/chrome/browser/ui/app_list/search/search_result_ranker/app_search_result_ranker_unittest.cc +++ b/chrome/browser/ui/app_list/search/search_result_ranker/app_search_result_ranker_unittest.cc
@@ -41,7 +41,9 @@ // Waits for all tasks in to finish. void Wait() { scoped_task_environment_.RunUntilIdle(); } - base::test::ScopedTaskEnvironment scoped_task_environment_; + base::test::ScopedTaskEnvironment scoped_task_environment_{ + base::test::ScopedTaskEnvironment::MainThreadType::DEFAULT, + base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED}; base::ScopedTempDir temp_dir_; base::test::ScopedFeatureList scoped_feature_list_; };
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_unittest.cc b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_unittest.cc index caee110..d4bf60de 100644 --- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_unittest.cc +++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_unittest.cc
@@ -67,7 +67,9 @@ } RecurrenceRankerConfigProto config_; - base::test::ScopedTaskEnvironment scoped_task_environment_; + base::test::ScopedTaskEnvironment scoped_task_environment_{ + base::test::ScopedTaskEnvironment::MainThreadType::DEFAULT, + base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED}; base::ScopedTempDir temp_dir_; base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc index 8441002..1979aab 100644 --- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc +++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
@@ -331,8 +331,10 @@ const uint16_t browser_index = GetBrowserIndex(command_id); // Check that the index is valid and the browser has not been closed. + // It's unclear why, but the browser's window may be null: crbug.com/937088 if (browser_index < browser_menu_items_.size() && - browser_menu_items_[browser_index]) { + browser_menu_items_[browser_index] && + browser_menu_items_[browser_index]->window()) { Browser* browser = browser_menu_items_[browser_index]; TabStripModel* tab_strip = browser->tab_strip_model(); const uint16_t tab_index = GetWebContentsIndex(command_id); @@ -344,10 +346,6 @@ TabStripModel::CLOSE_USER_GESTURE); } } else { - // These extra checks should gather info for http://crbug.com/937088 - CHECK(browser); - CHECK(browser->window()); - CHECK(browser->window()->GetNativeWindow()); multi_user_util::MoveWindowToCurrentDesktop( browser->window()->GetNativeWindow()); if (tab_index != kNoTab && tab_strip->ContainsIndex(tab_index))
diff --git a/chrome/browser/ui/ash/launcher_animations_interactive_uitest.cc b/chrome/browser/ui/ash/launcher_animations_interactive_uitest.cc index e19d00b..449ca75 100644 --- a/chrome/browser/ui/ash/launcher_animations_interactive_uitest.cc +++ b/chrome/browser/ui/ash/launcher_animations_interactive_uitest.cc
@@ -35,16 +35,23 @@ // UIPerformanceTest: std::vector<std::string> GetUMAHistogramNames() const override { + DCHECK(!suffix_.empty()); return { - "Apps.StateTransition.AnimationSmoothness.ClamshellMode", + std::string("Apps.StateTransition.AnimationSmoothness.") + suffix_, }; } + protected: + void set_suffix(const std::string& suffix) { suffix_ = suffix; } + private: + std::string suffix_; + DISALLOW_COPY_AND_ASSIGN(LauncherAnimationsTest); }; IN_PROC_BROWSER_TEST_F(LauncherAnimationsTest, Fullscreen) { + set_suffix("FullscreenAllApps.ClamshellMode"); // Browser window is used to identify display, so we can use // use the 1st browser window regardless of number of windows created. BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); @@ -76,6 +83,7 @@ } IN_PROC_BROWSER_TEST_F(LauncherAnimationsTest, Peeking) { + set_suffix("Peeking.ClamshellMode"); // Browser window is used to identify display, so we can use // use the 1st browser window regardless of number of windows created. BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc index 36014411..6d36b63b 100644 --- a/chrome/browser/ui/chrome_pages.cc +++ b/chrome/browser/ui/chrome_pages.cc
@@ -66,6 +66,12 @@ const char kHashMark[] = "#"; +void FocusWebContents(Browser* browser) { + auto* const contents = browser->tab_strip_model()->GetActiveWebContents(); + if (contents) + contents->Focus(); +} + void OpenBookmarkManagerForNode(Browser* browser, int64_t node_id) { GURL url = GURL(kChromeUIBookmarksURL) .Resolve(base::StringPrintf( @@ -314,6 +320,11 @@ void ShowSettingsSubPageInTabbedBrowser(Browser* browser, const std::string& sub_page) { base::RecordAction(UserMetricsAction("ShowOptions")); + + // Since the user may be triggering navigation from another UI element such as + // a menu, ensure the web contents (and therefore the settings page that is + // about to be shown) is focused. (See crbug/926492 for motivation.) + FocusWebContents(browser); GURL gurl = GetSettingsUrl(sub_page); NavigateParams params(GetSingletonTabNavigateParams(browser, gurl)); params.path_behavior = NavigateParams::IGNORE_AND_NAVIGATE;
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.h b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.h index aab52b7..e908066d 100644 --- a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.h +++ b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.h
@@ -14,10 +14,6 @@ class Browser; @class BrowserWindowTouchBarController; -namespace content { -class WebContents; -} - // Provides a default touch bar for the browser window. This class implements // the NSTouchBarDelegate and handles the items in the touch bar. API_AVAILABLE(macos(10.12.2)) @@ -29,19 +25,19 @@ // True if the current page is starred. Used by star touch bar button. @property(nonatomic, assign) BOOL isStarred; -// Designated initializer. -- (instancetype)initWithBrowser:(Browser*)browser - controller:(BrowserWindowTouchBarController*)controller; +// True if the back button is enabled. +@property(nonatomic, assign) BOOL canGoBack; + +// True if the forward button is enabled. +@property(nonatomic, assign) BOOL canGoForward; + +@property(nonatomic, assign) BrowserWindowTouchBarController* controller; + +@property(nonatomic) Browser* browser; // Creates and returns a touch bar for the browser window. - (NSTouchBar*)makeTouchBar; -- (void)updateWebContents:(content::WebContents*)contents; - -// Updates the back/forward button. Called when creating the touch bar or when -// the back and forward commands have changed. -- (void)updateBackForwardControl; - - (BrowserWindowTouchBarController*)controller; @end @@ -49,6 +45,11 @@ // Private methods exposed for testing. @interface BrowserWindowDefaultTouchBar (ExposedForTesting) +@property(readonly, class) NSString* reloadOrStopItemIdentifier; +@property(readonly, class) NSString* backItemIdentifier; +@property(readonly, class) NSString* forwardItemIdentifier; +@property(readonly, class) NSString* fullscreenOriginItemIdentifier; + // Updates the reload/stop button. Called when creating the touch bar or the // page load state has been updated. - (void)updateReloadStopButton; @@ -56,10 +57,6 @@ // Returns the reload/stop button on the touch bar. Creates it if it's null. - (NSButton*)reloadStopButton; -// Returns the back/forward segmented control on the touch bar. Creates it if -// it's null. -- (NSSegmentedControl*)backForwardControl; - // Returns the bridge object that BrowserWindowDefaultTouchBar uses to receive // notifications. - (BookmarkTabHelperObserver*)bookmarkTabObserver;
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm index 84099212..936f484e 100644 --- a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm +++ b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm
@@ -13,6 +13,7 @@ #include "base/strings/sys_string_conversions.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/app/vector_icons/vector_icons.h" +#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/command_observer.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/profiles/profile.h" @@ -32,6 +33,7 @@ #include "components/strings/grit/components_strings.h" #include "components/url_formatter/url_formatter.h" #include "components/vector_icons/vector_icons.h" +#include "content/public/browser/notification_service.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #import "skia/ext/skia_utils_mac.h" @@ -51,7 +53,8 @@ NSString* const kTabFullscreenTouchBarId = @"tab-fullscreen"; // Touch bar items identifiers. -NSString* const kBackForwardTouchId = @"BACK-FWD"; +NSString* const kBackTouchId = @"BACK"; +NSString* const kForwardTouchId = @"FORWARD"; NSString* const kReloadOrStopTouchId = @"RELOAD-STOP"; NSString* const kHomeTouchId = @"HOME"; NSString* const kSearchTouchId = @"SEARCH"; @@ -59,9 +62,11 @@ NSString* const kNewTabTouchId = @"NEW-TAB"; NSString* const kFullscreenOriginLabelTouchId = @"FULLSCREEN-ORIGIN-LABEL"; -// The button indexes in the back and forward segment control. -const int kBackSegmentIndex = 0; -const int kForwardSegmentIndex = 1; +// This is a combined back and forward control which can no longer be selected +// but may be in an existing customized Touch Bar. It now represents a group +// containing the back and forward buttons, and adding the back or forward +// buttons to the Touch Bar individually magically decomposes the group. +NSString* const kBackForwardTouchId = @"BACK-FWD"; // Touch bar icon colors values. const SkColor kTouchBarDefaultIconColor = SK_ColorWHITE; @@ -95,7 +100,7 @@ target:owner action:@selector(executeCommand:)]; button.tag = command; - [button setAccessibilityLabel:l10n_util::GetNSString(tooltip_id)]; + button.accessibilityTitle = l10n_util::GetNSString(tooltip_id); return button; } @@ -128,6 +133,8 @@ class API_AVAILABLE(macos(10.12.2)) TouchBarNotificationBridge : public CommandObserver, public BookmarkTabHelperObserver, + public TabStripModelObserver, + public content::NotificationObserver, public content::WebContentsObserver { public: TouchBarNotificationBridge(BrowserWindowDefaultTouchBar* owner, @@ -135,48 +142,93 @@ : owner_(owner), browser_(browser), contents_(nullptr) { TabStripModel* model = browser_->tab_strip_model(); DCHECK(model); - + model->AddObserver(this); UpdateWebContents(model->GetActiveWebContents()); + + auto* command_controller = browser->command_controller(); + command_controller->AddCommandObserver(IDC_BACK, this); + owner.canGoBack = command_controller->IsCommandEnabled(IDC_BACK); + command_controller->AddCommandObserver(IDC_FORWARD, this); + owner.canGoBack = command_controller->IsCommandEnabled(IDC_FORWARD); + + auto* profile = browser->profile(); + auto* prefs = profile->GetPrefs(); + show_home_button_.Init( + prefs::kShowHomeButton, prefs, + base::BindRepeating(&TouchBarNotificationBridge::UpdateTouchBar, + base::Unretained(this))); + + profile_pref_registrar_.Init(prefs); + profile_pref_registrar_.Add( + DefaultSearchManager::kDefaultSearchProviderDataPrefName, + base::BindRepeating(&TouchBarNotificationBridge::UpdateTouchBar, + base::Unretained(this))); + + notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, + content::Source<Profile>(profile)); } + bool show_home_button() { return show_home_button_.GetValue(); } + ~TouchBarNotificationBridge() override { - if (contents_) - BookmarkTabHelper::FromWebContents(contents_)->RemoveObserver(this); + browser_->tab_strip_model()->RemoveObserver(this); + UpdateWebContents(nullptr); } void UpdateTouchBar() { [[owner_ controller] invalidateTouchBar]; } void UpdateWebContents(content::WebContents* new_contents) { - if (contents_) { + if (contents_ == new_contents) + return; + if (contents_) BookmarkTabHelper::FromWebContents(contents_)->RemoveObserver(this); - } contents_ = new_contents; - Observe(contents_); - bool is_starred = false; - if (contents_) { - BookmarkTabHelper* helper = BookmarkTabHelper::FromWebContents(contents_); - helper->AddObserver(this); - is_starred = helper->is_starred(); - } + // Stop observing the old WebContents and start observing the new one (if + // nonnull). Qualified to disambiguate from NotificationObserver::Observe(). + WebContentsObserver::Observe(contents_); - [owner_ setIsPageLoading:contents_ && contents_->IsLoading()]; - [owner_ setIsStarred:is_starred]; + BookmarkTabHelper* bookmark_helper = + contents_ ? BookmarkTabHelper::FromWebContents(contents_) : nullptr; + if (bookmark_helper) + bookmark_helper->AddObserver(this); + + owner_.isPageLoading = contents_ && contents_->IsLoading(); + owner_.isStarred = bookmark_helper && bookmark_helper->is_starred(); + UpdateTouchBar(); } // BookmarkTabHelperObserver: void URLStarredChanged(content::WebContents* web_contents, bool starred) override { DCHECK(web_contents == contents_); - [owner_ setIsStarred:starred]; + owner_.isStarred = starred; } protected: // CommandObserver: void EnabledStateChangedForCommand(int command, bool enabled) override { DCHECK(command == IDC_BACK || command == IDC_FORWARD); - [owner_ updateBackForwardControl]; + if (command == IDC_BACK) + owner_.canGoBack = enabled; + else if (command == IDC_FORWARD) + owner_.canGoForward = enabled; + } + + // TabStripModelObserver: + void OnTabStripModelChanged( + TabStripModel* tab_strip_model, + const TabStripModelChange& change, + const TabStripSelectionChange& selection) override { + UpdateWebContents(selection.new_contents); + } + + // NotificationObserver: + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override { + owner_.browser = nullptr; } // WebContentsObserver: @@ -187,52 +239,40 @@ void DidStartLoading() override { DCHECK(contents_ && contents_->IsLoading()); - [owner_ setIsPageLoading:YES]; + owner_.isPageLoading = YES; } void DidStopLoading() override { DCHECK(contents_ && !contents_->IsLoading()); - [owner_ setIsPageLoading:NO]; + owner_.isPageLoading = NO; } + void WebContentsDestroyed() override { UpdateWebContents(nullptr); } + private: BrowserWindowDefaultTouchBar* owner_; // Weak. Browser* browser_; // Weak. content::WebContents* contents_; // Weak. + // Used to monitor the optional home button pref. + BooleanPrefMember show_home_button_; + + content::NotificationRegistrar notification_registrar_; + + PrefChangeRegistrar profile_pref_registrar_; + DISALLOW_COPY_AND_ASSIGN(TouchBarNotificationBridge); }; -id<NSAccessibility> ToNSAccessibility(id object) { - return [object conformsToProtocol:@protocol(NSAccessibility)] ? object : nil; -} - } // namespace @interface BrowserWindowDefaultTouchBar () { - // Used to execute commands such as navigating back and forward. - CommandUpdater* commandUpdater_; // Weak, owned by Browser. - - // The browser associated with the touch bar. - Browser* browser_; // Weak. - - BrowserWindowTouchBarController* controller_; // Weak. - - // Used to monitor the optional home button pref. - BooleanPrefMember showHomeButton_; - - // Used to listen for default search engine pref changes. - PrefChangeRegistrar profilePrefRegistrar_; - // Used to receive and handle notifications. std::unique_ptr<TouchBarNotificationBridge> notificationBridge_; // The stop/reload button in the touch bar. base::scoped_nsobject<NSButton> reloadStopButton_; - // The back/forward segmented control in the touch bar. - base::scoped_nsobject<NSSegmentedControl> backForwardControl_; - // The starred button in the touch bar. base::scoped_nsobject<NSButton> starredButton_; } @@ -240,9 +280,6 @@ // Creates and returns a touch bar for tab fullscreen mode. - (NSTouchBar*)createTabFullscreenTouchBar; -// Sets up the back and forward segmented control. -- (void)setupBackForwardControl; - // Updates the starred button in the touch bar. - (void)updateStarredButton; @@ -255,35 +292,10 @@ @synthesize isPageLoading = isPageLoading_; @synthesize isStarred = isStarred_; - -- (instancetype)initWithBrowser:(Browser*)browser - controller:(BrowserWindowTouchBarController*)controller { - if ((self = [super init])) { - DCHECK(browser); - browser_ = browser; - controller_ = controller; - - notificationBridge_.reset(new TouchBarNotificationBridge(self, browser)); - - commandUpdater_ = browser->command_controller(); - commandUpdater_->AddCommandObserver(IDC_BACK, notificationBridge_.get()); - commandUpdater_->AddCommandObserver(IDC_FORWARD, notificationBridge_.get()); - - PrefService* prefs = browser->profile()->GetPrefs(); - showHomeButton_.Init( - prefs::kShowHomeButton, prefs, - base::BindRepeating(&TouchBarNotificationBridge::UpdateTouchBar, - base::Unretained(notificationBridge_.get()))); - - profilePrefRegistrar_.Init(prefs); - profilePrefRegistrar_.Add( - DefaultSearchManager::kDefaultSearchProviderDataPrefName, - base::BindRepeating(&TouchBarNotificationBridge::UpdateTouchBar, - base::Unretained(notificationBridge_.get()))); - } - - return self; -} +@synthesize canGoBack = canGoBack_; +@synthesize canGoForward = canGoForward_; +@synthesize controller = controller_; +@synthesize browser = browser_; - (NSTouchBar*)makeTouchBar { // When in tab or extension fullscreen, we should show a touch bar containing @@ -301,12 +313,12 @@ setCustomizationIdentifier:ui::GetTouchBarId(kBrowserWindowTouchBarId)]; [touchBar setDelegate:self]; - NSMutableArray* customIdentifiers = [NSMutableArray arrayWithCapacity:7]; - NSMutableArray* defaultIdentifiers = [NSMutableArray arrayWithCapacity:6]; + NSMutableArray<NSString*>* customIdentifiers = [NSMutableArray array]; + NSMutableArray<NSString*>* defaultIdentifiers = [NSMutableArray array]; - NSArray* touchBarItems = @[ - kBackForwardTouchId, kReloadOrStopTouchId, kHomeTouchId, kSearchTouchId, - kStarTouchId, kNewTabTouchId + NSArray<NSString*>* touchBarItems = @[ + kBackTouchId, kForwardTouchId, kReloadOrStopTouchId, kHomeTouchId, + kSearchTouchId, kStarTouchId, kNewTabTouchId ]; for (NSString* item in touchBarItems) { @@ -315,8 +327,10 @@ [customIdentifiers addObject:itemIdentifier]; // Don't add the home button if it's not shown in the toolbar. - if (showHomeButton_.GetValue() || ![item isEqualTo:kHomeTouchId]) - [defaultIdentifiers addObject:itemIdentifier]; + if (item == kHomeTouchId && !notificationBridge_->show_home_button()) + continue; + + [defaultIdentifiers addObject:itemIdentifier]; } [customIdentifiers addObject:NSTouchBarItemIdentifierFlexibleSpace]; @@ -332,14 +346,41 @@ if (!touchBar) return nil; + if ([identifier hasSuffix:kBackForwardTouchId]) { + auto* items = @[ + [touchBar itemForIdentifier:ui::GetTouchBarItemId( + kBrowserWindowTouchBarId, kBackTouchId)], + [touchBar + itemForIdentifier:ui::GetTouchBarItemId(kBrowserWindowTouchBarId, + kForwardTouchId)], + ]; + auto groupItem = [NSGroupTouchBarItem groupItemWithIdentifier:identifier + items:items]; + [groupItem setCustomizationLabel: + l10n_util::GetNSString( + IDS_TOUCH_BAR_BACK_FORWARD_CUSTOMIZATION_LABEL)]; + return groupItem; + } + base::scoped_nsobject<NSCustomTouchBarItem> touchBarItem( [[ui::NSCustomTouchBarItem() alloc] initWithIdentifier:identifier]); - if ([identifier hasSuffix:kBackForwardTouchId]) { - [self updateBackForwardControl]; - [touchBarItem setView:backForwardControl_.get()]; - [touchBarItem setCustomizationLabel: - l10n_util::GetNSString( - IDS_TOUCH_BAR_BACK_FORWARD_CUSTOMIZATION_LABEL)]; + if ([identifier hasSuffix:kBackTouchId]) { + auto* button = CreateTouchBarButton(vector_icons::kBackArrowIcon, self, + IDC_BACK, IDS_ACCNAME_BACK); + [button bind:@"enabled" toObject:self withKeyPath:@"canGoBack" options:nil]; + [touchBarItem setView:button]; + [touchBarItem + setCustomizationLabel:l10n_util::GetNSString(IDS_ACCNAME_BACK)]; + } else if ([identifier hasSuffix:kForwardTouchId]) { + auto* button = CreateTouchBarButton(vector_icons::kForwardArrowIcon, self, + IDC_FORWARD, IDS_ACCNAME_FORWARD); + [button bind:@"enabled" + toObject:self + withKeyPath:@"canGoForward" + options:nil]; + [touchBarItem setView:button]; + [touchBarItem + setCustomizationLabel:l10n_util::GetNSString(IDS_ACCNAME_FORWARD)]; } else if ([identifier hasSuffix:kReloadOrStopTouchId]) { [self updateReloadStopButton]; [touchBarItem setView:reloadStopButton_.get()]; @@ -398,6 +439,8 @@ [touchBarItem setView:[NSTextField labelWithAttributedString:attributedString.get()]]; + } else { + return nil; } return touchBarItem.autorelease(); @@ -412,61 +455,12 @@ return touchBar.autorelease(); } -- (void)setupBackForwardControl { - NSMutableArray* images = [NSMutableArray arrayWithArray:@[ - CreateNSImageFromIcon(vector_icons::kBackArrowIcon), - CreateNSImageFromIcon(vector_icons::kForwardArrowIcon) - ]]; - - // Offset the icons so that it matches the height of the other Touch Bar - // items. - const int kIconYOffset = 2; - for (NSUInteger i = 0; i < [images count]; i++) { - NSImage* image = [images objectAtIndex:i]; - NSSize size = [image size]; - size.height += kIconYOffset; - - NSImage* offsettedImage = [[[NSImage alloc] initWithSize:size] autorelease]; - [offsettedImage lockFocus]; - [image drawInRect:NSMakeRect(0, 0, size.width, size.height - kIconYOffset)]; - [offsettedImage unlockFocus]; - [images replaceObjectAtIndex:i withObject:offsettedImage]; - } - - NSSegmentedControl* control = [NSSegmentedControl - segmentedControlWithImages:images - trackingMode:NSSegmentSwitchTrackingMomentary - target:self - action:@selector(backOrForward:)]; - - // Use the accessibility protocol to get the children. - // Use NSAccessibilityUnignoredDescendant to be sure we start with - // the correct object. - id<NSAccessibility> segmentElement = - ToNSAccessibility(NSAccessibilityUnignoredDescendant(control)); - DCHECK(segmentElement); - NSArray<id<NSAccessibility>>* segments = segmentElement.accessibilityChildren; - ToNSAccessibility(segments[0]).accessibilityTitle = - l10n_util::GetNSString(IDS_ACCNAME_BACK); - ToNSAccessibility(segments[1]).accessibilityTitle = - l10n_util::GetNSString(IDS_ACCNAME_FORWARD); - - backForwardControl_.reset([control retain]); -} - -- (void)updateWebContents:(content::WebContents*)contents { - notificationBridge_->UpdateWebContents(contents); -} - -- (void)updateBackForwardControl { - if (!backForwardControl_) - [self setupBackForwardControl]; - - [backForwardControl_ setSegmentStyle:NSSegmentStyleSeparated]; - [backForwardControl_ setEnabled:commandUpdater_->IsCommandEnabled(IDC_BACK) - forSegment:kBackSegmentIndex]; - [backForwardControl_ setEnabled:commandUpdater_->IsCommandEnabled(IDC_FORWARD) - forSegment:kForwardSegmentIndex]; +- (void)setBrowser:(Browser*)browser { + if (browser_ == browser) + return; + browser_ = browser; + notificationBridge_.reset( + browser_ ? new TouchBarNotificationBridge(self, browser_) : nullptr); } - (void)updateStarredButton { @@ -485,10 +479,6 @@ [starredButton_ setAccessibilityLabel:l10n_util::GetNSString(tooltipId)]; } -- (BrowserWindowTouchBarController*)controller { - return controller_; -} - - (NSView*)searchTouchBarView { TemplateURLService* templateUrlService = TemplateURLServiceFactory::GetForProfile(browser_->profile()); @@ -532,18 +522,10 @@ return searchButton; } -- (void)backOrForward:(id)sender { - NSSegmentedControl* control = sender; - int command = - [control selectedSegment] == kBackSegmentIndex ? IDC_BACK : IDC_FORWARD; - LogTouchBarUMA(TouchBarActionFromCommand(command)); - commandUpdater_->ExecuteCommand(command); -} - - (void)executeCommand:(id)sender { int command = [sender tag]; ui::LogTouchBarUMA(TouchBarActionFromCommand(command)); - commandUpdater_->ExecuteCommand(command); + browser_->command_controller()->ExecuteCommand(command); } - (void)setIsPageLoading:(BOOL)isPageLoading { @@ -561,6 +543,23 @@ // Private methods exposed for testing. @implementation BrowserWindowDefaultTouchBar (ExposedForTesting) ++ (NSString*)reloadOrStopItemIdentifier { + return ui::GetTouchBarItemId(kBrowserWindowTouchBarId, kReloadOrStopTouchId); +} + ++ (NSString*)backItemIdentifier { + return ui::GetTouchBarItemId(kBrowserWindowTouchBarId, kBackTouchId); +} + ++ (NSString*)forwardItemIdentifier { + return ui::GetTouchBarItemId(kBrowserWindowTouchBarId, kForwardTouchId); +} + ++ (NSString*)fullscreenOriginItemIdentifier { + return ui::GetTouchBarItemId(kTabFullscreenTouchBarId, + kFullscreenOriginLabelTouchId); +} + - (void)updateReloadStopButton { const gfx::VectorIcon& icon = isPageLoading_ ? kNavigateStopIcon : vector_icons::kReloadIcon; @@ -586,13 +585,6 @@ return reloadStopButton_.get(); } -- (NSSegmentedControl*)backForwardControl { - if (!backForwardControl_) - [self updateBackForwardControl]; - - return backForwardControl_.get(); -} - - (BookmarkTabHelperObserver*)bookmarkTabObserver { return notificationBridge_.get(); }
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm index ec36da0d..9c93039a 100644 --- a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm +++ b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm
@@ -18,33 +18,14 @@ #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" #include "components/strings/grit/components_strings.h" +#include "content/public/test/test_renderer_host.h" +#include "content/public/test/web_contents_tester.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" #import "third_party/ocmock/OCMock/OCMock.h" #import "ui/base/cocoa/touch_bar_util.h" #include "ui/base/l10n/l10n_util_mac.h" -namespace { - -// Touch bar identifiers. -NSString* const kBrowserWindowTouchBarId = @"browser-window"; -NSString* const kTabFullscreenTouchBarId = @"tab-fullscreen"; - -// Touch bar items identifiers. -NSString* const kBackForwardTouchId = @"BACK-FWD"; -NSString* const kReloadOrStopTouchId = @"RELOAD-STOP"; -NSString* const kHomeTouchId = @"HOME"; -NSString* const kSearchTouchId = @"SEARCH"; -NSString* const kStarTouchId = @"BOOKMARK"; -NSString* const kNewTabTouchId = @"NEW-TAB"; -NSString* const kFullscreenOriginLabelTouchId = @"FULLSCREEN-ORIGIN-LABEL"; - -// The button indexes in the back and forward segment control. -const int kBackSegmentIndex = 0; -const int kForwardSegmentIndex = 1; - -} // namespace - class BrowserWindowDefaultTouchBarUnitTest : public CocoaProfileTest { public: void SetUp() override { @@ -53,75 +34,117 @@ command_updater_ = browser()->command_controller(); + browser()->tab_strip_model()->AppendWebContents( + content::WebContentsTester::CreateTestWebContents(profile(), nullptr), + true); + if (@available(macOS 10.12.2, *)) { - touch_bar_.reset([[BrowserWindowDefaultTouchBar alloc] - initWithBrowser:browser() - controller:nil]); + touch_bar_.reset([[BrowserWindowDefaultTouchBar alloc] init]); + touch_bar_.get().browser = browser(); } } - NSString* GetFullscreenTouchBarItemId(NSString* id) { - return ui::GetTouchBarItemId(kTabFullscreenTouchBarId, id); - } - - NSString* GetBrowserTouchBarItemId(NSString* id) { - return ui::GetTouchBarItemId(kBrowserWindowTouchBarId, id); - } - void UpdateCommandEnabled(int id, bool enabled) { command_updater_->UpdateCommandEnabled(id, enabled); } void TearDown() override { - if (@available(macOS 10.12.2, *)) + if (@available(macOS 10.12.2, *)) { + touch_bar_.get().browser = nullptr; touch_bar_.reset(); + } CocoaProfileTest::TearDown(); } CommandUpdater* command_updater_; // Weak, owned by Browser. + content::RenderViewHostTestEnabler rvh_test_enabler_; API_AVAILABLE(macos(10.12.2)) base::scoped_nsobject<BrowserWindowDefaultTouchBar> touch_bar_; }; -// Tests to check if the touch bar contains the correct items. +// Test if any known identifiers no longer work. See the message in the test; +// these identifiers may be written out to disk on users' computers if they +// customize the Touch Bar, and the corresponding items will disappear if they +// can no longer be created. +TEST_F(BrowserWindowDefaultTouchBarUnitTest, HistoricTouchBarItems) { + if (@available(macOS 10.12.2, *)) { + NSTouchBar* touch_bar = [touch_bar_ makeTouchBar]; + for (NSString* item_identifier : { + @"BACK-FWD", + @"BACK", + @"FORWARD", + @"RELOAD-STOP", + @"HOME", + @"SEARCH", + @"BOOKMARK", + @"NEW-TAB", + }) { + auto identifier = + ui::GetTouchBarItemId(@"browser-window", item_identifier); + EXPECT_NE(nil, [touch_bar itemForIdentifier:identifier]) + << "BrowserWindowDefaultTouchBar didn't return a Touch Bar item for " + "an identifier that was once available (" + << identifier.UTF8String + << "). If a user's customized Touch Bar includes this item, it will " + "disappear! Do not update or remove entries in this list just to " + "make the test pass; keep supporting old identifiers when " + "possible, even if they're no longer part of the set of " + "default/customizable items."; + } + } +} + +// Tests if BrowserWindowDefaultTouchBar can produce the items it says it can +// and, for each kind of bar, also verify that the advertised/customizable lists +// include some representative items (if not, the lists might be wrong.) TEST_F(BrowserWindowDefaultTouchBarUnitTest, TouchBarItems) { if (@available(macOS 10.12.2, *)) { + auto test_default_identifiers = + [&](NSSet* expected_identifiers) API_AVAILABLE(macos(10.12.2)) { + NSTouchBar* touch_bar = [touch_bar_ makeTouchBar]; + NSMutableSet<NSString*>* advertised_identifiers = [NSMutableSet set]; + [advertised_identifiers + addObjectsFromArray:touch_bar.defaultItemIdentifiers]; + [advertised_identifiers + addObjectsFromArray:touch_bar + .customizationAllowedItemIdentifiers]; + [advertised_identifiers + addObjectsFromArray:touch_bar + .customizationRequiredItemIdentifiers]; + EXPECT_TRUE( + [expected_identifiers isSubsetOfSet:advertised_identifiers]) + << "Didn't find the expected identifiers " + << expected_identifiers.description.UTF8String + << " in the set of advertised identifiers " + << advertised_identifiers.description.UTF8String << "."; + for (NSString* identifier in advertised_identifiers) { + EXPECT_NE(nil, [touch_bar itemForIdentifier:identifier]) + << "Didn't get a touch bar item for " << identifier.UTF8String; + } + }; + // Set to tab fullscreen. FullscreenController* fullscreen_controller = browser()->exclusive_access_manager()->fullscreen_controller(); fullscreen_controller->set_is_tab_fullscreen_for_testing(true); EXPECT_TRUE(fullscreen_controller->IsTabFullscreen()); - // The touch bar should only contain an item that displays the origin of the - // tab content fullscreen. - NSTouchBar* touch_bar = [touch_bar_ makeTouchBar]; - NSArray* touch_bar_items = [touch_bar itemIdentifiers]; - EXPECT_TRUE( - [touch_bar_items containsObject:GetFullscreenTouchBarItemId( - kFullscreenOriginLabelTouchId)]); - EXPECT_EQ(1u, [touch_bar_items count]); + // The fullscreen Touch Bar should include *at least* these items. + test_default_identifiers([NSSet setWithArray:@[ + BrowserWindowDefaultTouchBar.fullscreenOriginItemIdentifier, + ]]); // Exit fullscreen. fullscreen_controller->set_is_tab_fullscreen_for_testing(false); EXPECT_FALSE(fullscreen_controller->IsTabFullscreen()); - PrefService* prefs = profile()->GetPrefs(); - DCHECK(prefs); - prefs->SetBoolean(prefs::kShowHomeButton, true); - touch_bar_items = [[touch_bar_ makeTouchBar] itemIdentifiers]; - EXPECT_TRUE([touch_bar_items - containsObject:GetBrowserTouchBarItemId(kBackForwardTouchId)]); - EXPECT_TRUE([touch_bar_items - containsObject:GetBrowserTouchBarItemId(kReloadOrStopTouchId)]); - EXPECT_TRUE([touch_bar_items - containsObject:GetBrowserTouchBarItemId(kHomeTouchId)]); - EXPECT_TRUE([touch_bar_items - containsObject:GetBrowserTouchBarItemId(kSearchTouchId)]); - EXPECT_TRUE([touch_bar_items - containsObject:GetBrowserTouchBarItemId(kStarTouchId)]); - EXPECT_TRUE([touch_bar_items - containsObject:GetBrowserTouchBarItemId(kNewTabTouchId)]); + // The default Touch Bar should include *at least* these items. + test_default_identifiers([NSSet setWithArray:@[ + BrowserWindowDefaultTouchBar.backItemIdentifier, + BrowserWindowDefaultTouchBar.forwardItemIdentifier, + BrowserWindowDefaultTouchBar.reloadOrStopItemIdentifier, + ]]); } } @@ -131,56 +154,69 @@ NSTouchBar* touch_bar = [touch_bar_ makeTouchBar]; [touch_bar_ setIsPageLoading:NO]; - NSTouchBarItem* item = [touch_bar_ - touchBar:touch_bar - makeItemForIdentifier:GetBrowserTouchBarItemId(kReloadOrStopTouchId)]; + NSTouchBarItem* item = + [touch_bar itemForIdentifier:BrowserWindowDefaultTouchBar + .reloadOrStopItemIdentifier]; EXPECT_EQ(IDC_RELOAD, [[item view] tag]); [touch_bar_ setIsPageLoading:YES]; - item = [touch_bar_ touchBar:touch_bar - makeItemForIdentifier:GetBrowserTouchBarItemId(kReloadOrStopTouchId)]; + item = [touch_bar itemForIdentifier:BrowserWindowDefaultTouchBar + .reloadOrStopItemIdentifier]; EXPECT_EQ(IDC_STOP, [[item view] tag]); } } -// Tests to see if the back/forward items on the touch bar is in sync with the -// back and forward commands. -TEST_F(BrowserWindowDefaultTouchBarUnitTest, BackForwardCommandUpdate) { +// Tests if the back button on the touch bar is in sync with the back command. +TEST_F(BrowserWindowDefaultTouchBarUnitTest, BackCommandUpdate) { if (@available(macOS 10.12.2, *)) { - NSSegmentedControl* back_forward_control = [touch_bar_ backForwardControl]; + NSTouchBar* touch_bar = [touch_bar_ makeTouchBar]; + NSTouchBarItem* item = [touch_bar + itemForIdentifier:BrowserWindowDefaultTouchBar.backItemIdentifier]; + NSButton* button = base::mac::ObjCCast<NSButton>(item.view); UpdateCommandEnabled(IDC_BACK, true); - UpdateCommandEnabled(IDC_FORWARD, true); - EXPECT_TRUE([back_forward_control isEnabledForSegment:kBackSegmentIndex]); - EXPECT_TRUE( - [back_forward_control isEnabledForSegment:kForwardSegmentIndex]); - + EXPECT_TRUE(button.enabled); UpdateCommandEnabled(IDC_BACK, false); - EXPECT_FALSE([back_forward_control isEnabledForSegment:kBackSegmentIndex]); - EXPECT_TRUE( - [back_forward_control isEnabledForSegment:kForwardSegmentIndex]); - - UpdateCommandEnabled(IDC_FORWARD, false); - EXPECT_FALSE([back_forward_control isEnabledForSegment:kBackSegmentIndex]); - EXPECT_FALSE( - [back_forward_control isEnabledForSegment:kForwardSegmentIndex]); + EXPECT_FALSE(button.enabled); } } -TEST_F(BrowserWindowDefaultTouchBarUnitTest, BackForwardAccessibilityLabels) { +// Tests if the forward button on the touch bar is in sync with the forward +// command. +TEST_F(BrowserWindowDefaultTouchBarUnitTest, ForwardCommandUpdate) { if (@available(macOS 10.12.2, *)) { - NSSegmentedControl* control = touch_bar_.get().backForwardControl; - id<NSAccessibility> cell = NSAccessibilityUnignoredDescendant(control); - ASSERT_TRUE([cell conformsToProtocol:@protocol(NSAccessibility)]); + NSTouchBar* touch_bar = [touch_bar_ makeTouchBar]; + NSTouchBarItem* item = [touch_bar + itemForIdentifier:BrowserWindowDefaultTouchBar.forwardItemIdentifier]; + NSButton* button = base::mac::ObjCCast<NSButton>(item.view); - id<NSAccessibility> back = cell.accessibilityChildren[0]; - EXPECT_TRUE([back conformsToProtocol:@protocol(NSAccessibility)]); - EXPECT_NSEQ(back.accessibilityTitle, + UpdateCommandEnabled(IDC_FORWARD, true); + EXPECT_TRUE(button.enabled); + UpdateCommandEnabled(IDC_FORWARD, false); + EXPECT_FALSE(button.enabled); + } +} + +TEST_F(BrowserWindowDefaultTouchBarUnitTest, BackAccessibilityLabel) { + if (@available(macOS 10.12.2, *)) { + NSTouchBar* touch_bar = [touch_bar_ makeTouchBar]; + NSTouchBarItem* item = [touch_bar + itemForIdentifier:BrowserWindowDefaultTouchBar.backItemIdentifier]; + id<NSAccessibility> view = item.view; + ASSERT_TRUE([view conformsToProtocol:@protocol(NSAccessibility)]); + EXPECT_NSEQ(view.accessibilityTitle, l10n_util::GetNSString(IDS_ACCNAME_BACK)); + } +} - id<NSAccessibility> forward = cell.accessibilityChildren[1]; - EXPECT_TRUE([forward conformsToProtocol:@protocol(NSAccessibility)]); - EXPECT_NSEQ(forward.accessibilityTitle, +TEST_F(BrowserWindowDefaultTouchBarUnitTest, ForwardAccessibilityLabel) { + if (@available(macOS 10.12.2, *)) { + NSTouchBar* touch_bar = [touch_bar_ makeTouchBar]; + NSTouchBarItem* item = [touch_bar + itemForIdentifier:BrowserWindowDefaultTouchBar.forwardItemIdentifier]; + id<NSAccessibility> view = item.view; + ASSERT_TRUE([view conformsToProtocol:@protocol(NSAccessibility)]); + EXPECT_NSEQ(view.accessibilityTitle, l10n_util::GetNSString(IDS_ACCNAME_FORWARD)); } }
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.h b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.h index f5443e06..147775a 100644 --- a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.h +++ b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.h
@@ -32,9 +32,6 @@ // nil. - (void)invalidateTouchBar; -- (void)updateWebContents:(content::WebContents*)contents; - -- (content::WebContents*)webContents; @end @interface BrowserWindowTouchBarController (ExposedForTesting)
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.mm b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.mm index 28d60d07..94bea88d 100644 --- a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.mm +++ b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.mm
@@ -19,66 +19,9 @@ #include "content/public/browser/web_contents_observer.h" #import "ui/base/cocoa/touch_bar_util.h" -class API_AVAILABLE(macos(10.12.2)) WebContentsNotificationBridge - : public TabStripModelObserver, - public content::WebContentsObserver { - public: - WebContentsNotificationBridge(BrowserWindowTouchBarController* owner, - Browser* browser) - : owner_(owner), browser_(browser), contents_(nullptr) { - TabStripModel* model = browser_->tab_strip_model(); - DCHECK(model); - model->AddObserver(this); - - UpdateWebContents(model->GetActiveWebContents()); - } - - ~WebContentsNotificationBridge() override { - TabStripModel* model = browser_->tab_strip_model(); - if (model) - model->RemoveObserver(this); - } - - void UpdateWebContents(content::WebContents* new_contents) { - contents_ = new_contents; - Observe(contents_); - - [owner_ updateWebContents:contents_]; - } - - // TabStripModelObserver: - void OnTabStripModelChanged( - TabStripModel* tab_strip_model, - const TabStripModelChange& change, - const TabStripSelectionChange& selection) override { - if (tab_strip_model->empty() || !selection.active_tab_changed()) - return; - - UpdateWebContents(selection.new_contents); - contents_ = selection.new_contents; - } - - content::WebContents* contents() const { return contents_; } - - protected: - // WebContentsObserver: - void WebContentsDestroyed() override { - // Clean up if the web contents is being destroyed. - UpdateWebContents(nullptr); - } - - private: - BrowserWindowTouchBarController* owner_; // Weak. - Browser* browser_; // Weak. - content::WebContents* contents_; // Weak. -}; - @interface BrowserWindowTouchBarController () { NSWindow* window_; // Weak. - // Used to receive and handle notifications. - std::unique_ptr<WebContentsNotificationBridge> notificationBridge_; - base::scoped_nsobject<BrowserWindowDefaultTouchBar> defaultTouchBar_; base::scoped_nsobject<WebTextfieldTouchBarController> webTextfieldTouchBar_; @@ -92,12 +35,9 @@ DCHECK(browser); window_ = window; - notificationBridge_ = - std::make_unique<WebContentsNotificationBridge>(self, browser); - - defaultTouchBar_.reset([[BrowserWindowDefaultTouchBar alloc] - initWithBrowser:browser - controller:self]); + defaultTouchBar_.reset([[BrowserWindowDefaultTouchBar alloc] init]); + defaultTouchBar_.get().controller = self; + defaultTouchBar_.get().browser = browser; webTextfieldTouchBar_.reset( [[WebTextfieldTouchBarController alloc] initWithController:self]); } @@ -105,6 +45,11 @@ return self; } +- (void)dealloc { + defaultTouchBar_.get().browser = nullptr; + [super dealloc]; +} + - (void)invalidateTouchBar { DCHECK([window_ respondsToSelector:@selector(setTouchBar:)]); [window_ performSelector:@selector(setTouchBar:) withObject:nil]; @@ -118,15 +63,6 @@ return [defaultTouchBar_ makeTouchBar]; } -- (void)updateWebContents:(content::WebContents*)contents { - [defaultTouchBar_ updateWebContents:contents]; - [self invalidateTouchBar]; -} - -- (content::WebContents*)webContents { - return notificationBridge_->web_contents(); -} - @end @implementation BrowserWindowTouchBarController (ExposedForTesting)
diff --git a/chrome/browser/ui/search/local_ntp_test_utils.cc b/chrome/browser/ui/search/local_ntp_test_utils.cc index f0ee8b3d..0325aea 100644 --- a/chrome/browser/ui/search/local_ntp_test_utils.cc +++ b/chrome/browser/ui/search/local_ntp_test_utils.cc
@@ -27,72 +27,8 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "ui/base/resource/resource_bundle.h" -// #include "ui/native_theme/test_native_theme.h" - -// namespace { - -// // Delimiter in the Most Visited icon URL that indicates a dark icon. Keep -// value -// // in sync with NtpIconSource. -// const char kMVIconDarkParameter[] = "/dark/"; - -// } // namespace - namespace local_ntp_test_utils { -// // Tests that dark mode styling is properly applied to the local NTP. -// class BaseDarkModeTest { -// public: -// BaseDarkModeTest() {} - -// ui::TestNativeTheme* theme() { return &theme_; } - -// // Returns true if dark mode is applied on the |frame|. -// bool GetIsDarkModeApplied(const content::ToRenderFrameHost& frame) { -// bool dark_mode_applied = false; -// if (instant_test_utils::GetBoolFromJS( -// frame, -// "document.documentElement.getAttribute('darkmode') === 'true'", -// &dark_mode_applied)) { -// return dark_mode_applied; -// } -// return false; -// } - -// // Returns true if dark mode is applied on the |frame|. -// bool GetIsDarkModeChipApplied(const content::ToRenderFrameHost& frame) { -// bool dark_mode_chip_applied = false; -// if (!instant_test_utils::GetBoolFromJS( -// frame, -// "document.documentElement.getAttribute('darkmode') === 'true' && -// " -// "!document.body.classList.contains('light-chip')", -// &dark_mode_chip_applied)) { -// return dark_mode_chip_applied; -// } -// return false; -// } - -// // Returns true if dark mode is applied to the Most Visited icon at |index| -// // (i.e. the icon URL contains the |kMVIconDarkParameter|). -// bool GetIsDarkTile(const content::ToRenderFrameHost& frame, int index) { -// bool dark_tile = false; -// if (instant_test_utils::GetBoolFromJS( -// frame, -// base::StringPrintf( -// "document.querySelectorAll('#mv-tiles .md-icon img')[%d]" -// ".src.includes('%s')", -// index, kMVIconDarkParameter), -// &dark_tile)) { -// return dark_tile; -// } -// return false; -// } - -// private: -// ui::TestNativeTheme theme_; -// }; - content::WebContents* OpenNewTab(Browser* browser, const GURL& url) { ui_test_utils::NavigateToURLWithDisposition( browser, url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_button.cc b/chrome/browser/ui/views/extensions/extensions_menu_button.cc index 898988d7..de143fe0 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_button.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_button.cc
@@ -4,23 +4,42 @@ #include "chrome/browser/ui/views/extensions/extensions_menu_button.h" +#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h" #include "chrome/browser/ui/views/extensions/extensions_menu_view.h" #include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" +#include "chrome/grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/views/controls/button/image_button.h" +#include "ui/views/controls/button/menu_button.h" +#include "ui/views/layout/box_layout.h" +#include "ui/views/layout/layout_provider.h" +#include "ui/views/view_class_properties.h" const char ExtensionsMenuButton::kClassName[] = "ExtensionsMenuButton"; +namespace { + +constexpr int EXTENSION_CONTEXT_MENU = 13; + +} // namespace + ExtensionsMenuButton::ExtensionsMenuButton( Browser* browser, std::unique_ptr<ToolbarActionViewController> controller) : HoverButton(this, ExtensionsMenuView::CreateFixedSizeIconView(), base::string16(), - base::string16()), + base::string16(), + std::make_unique<views::View>(), + true, + true), browser_(browser), controller_(std::move(controller)) { + ConfigureSecondaryView(); set_auto_compute_tooltip(false); set_context_menu_controller(this); controller_->SetDelegate(this); @@ -35,6 +54,11 @@ void ExtensionsMenuButton::ButtonPressed(Button* sender, const ui::Event& event) { + if (sender->id() == EXTENSION_CONTEXT_MENU) { + ShowContextMenu(gfx::Point(), ui::MENU_SOURCE_MOUSE); + return; + } + DCHECK_EQ(this, sender); controller_->ExecuteAction(true); } @@ -70,8 +94,7 @@ } bool ExtensionsMenuButton::IsMenuRunning() const { - // TODO(pbos): Implement when able to show context menus inside this bubble. - return false; + return menu_runner_ && menu_runner_->IsRunning(); } // views::ContextMenuController: @@ -79,6 +102,64 @@ views::View* source, const gfx::Point& point, ui::MenuSourceType source_type) { - // TODO(pbos): Implement this. This is a no-op implementation as it prevents - // crashing actions that don't have a popup action. + ui::MenuModel* model = controller_->GetContextMenu(); + if (!model) + return; + + // Unretained() is safe here as ExtensionsMenuButton will always outlive the + // menu. Any action that would lead to the deletion of |this| first triggers + // the closing of the menu through lost capture. + menu_adapter_ = std::make_unique<views::MenuModelAdapter>( + model, base::BindRepeating(&ExtensionsMenuButton::OnMenuClosed, + base::Unretained(this))); + + menu_runner_ = std::make_unique<views::MenuRunner>( + model, views::MenuRunner::HAS_MNEMONICS); + menu_runner_->RunMenuAt(GetWidget(), context_menu_button_, + context_menu_button_->GetAnchorBoundsInScreen(), + views::MenuAnchorPosition::kTopRight, source_type); +} + +void ExtensionsMenuButton::OnMenuClosed() { + menu_runner_.reset(); + controller_->OnContextMenuClosed(); + menu_adapter_.reset(); +} + +void ExtensionsMenuButton::ConfigureSecondaryView() { + views::View* container = secondary_view(); + DCHECK(container->children().empty()); + container->SetLayoutManager( + std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal)); + + const SkColor icon_color = + ui::NativeTheme::GetInstanceForNativeUi()->SystemDarkModeEnabled() + ? gfx::kGoogleGrey500 + : gfx::kChromeIconGrey; + + auto context_menu_button = + std::make_unique<views::MenuButton>(base::string16(), this); + context_menu_button->set_id(EXTENSION_CONTEXT_MENU); + context_menu_button->SetTooltipText( + l10n_util::GetStringUTF16(IDS_EXTENSIONS_MENU_CONTEXT_MENU_TOOLTIP)); + + context_menu_button->SetImage( + views::Button::STATE_NORMAL, + gfx::CreateVectorIcon(kBrowserToolsIcon, 16, icon_color)); + context_menu_button->set_ink_drop_base_color(icon_color); + context_menu_button->SetBorder( + views::CreateEmptyBorder(views::LayoutProvider::Get()->GetInsetsMetric( + views::INSETS_VECTOR_IMAGE_BUTTON))); + context_menu_button->SizeToPreferredSize(); + + context_menu_button->SetInkDropMode(InkDropMode::ON); + context_menu_button->set_has_ink_drop_action_on_click(true); + auto highlight_path = std::make_unique<SkPath>(); + highlight_path->addOval( + gfx::RectToSkRect(gfx::Rect(context_menu_button->size()))); + context_menu_button->SetProperty(views::kHighlightPathKey, + highlight_path.release()); + + context_menu_button_ = context_menu_button.get(); + container->AddChildView(std::move(context_menu_button)); }
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_button.h b/chrome/browser/ui/views/extensions/extensions_menu_button.h index e059f0a3..2531dfd 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_button.h +++ b/chrome/browser/ui/views/extensions/extensions_menu_button.h
@@ -14,7 +14,9 @@ #include "ui/views/bubble/bubble_dialog_delegate_view.h" namespace views { -class View; +class MenuButton; +class MenuModelAdapter; +class MenuRunner; } // namespace views class ExtensionsMenuButton : public HoverButton, @@ -46,9 +48,27 @@ const gfx::Point& point, ui::MenuSourceType source_type) override; + // Callback for MenuModelAdapter. + void OnMenuClosed(); + + // Configures the secondary (right-hand-side) view of this HoverButton. + void ConfigureSecondaryView(); + Browser* const browser_; const std::unique_ptr<ToolbarActionViewController> controller_; + // TODO(pbos): There's complicated configuration code in place since menus + // can't be triggered from ImageButtons. When MenuRunner::RunMenuAt accepts + // views::Buttons, turn this into a views::ImageButton and use + // image_button_factory.h methods to configure it. + views::MenuButton* context_menu_button_ = nullptr; + + // Responsible for converting the context menu model into |menu_|. + std::unique_ptr<views::MenuModelAdapter> menu_adapter_; + + // Responsible for running the menu. + std::unique_ptr<views::MenuRunner> menu_runner_; + DISALLOW_COPY_AND_ASSIGN(ExtensionsMenuButton); };
diff --git a/chrome/browser/ui/views/hover_button.cc b/chrome/browser/ui/views/hover_button.cc index 05a37ae..1ae6618 100644 --- a/chrome/browser/ui/views/hover_button.cc +++ b/chrome/browser/ui/views/hover_button.cc
@@ -338,9 +338,14 @@ if (secondary_view_) { gfx::Point point_in_secondary_view(point); ConvertPointToTarget(this, secondary_view_, &point_in_secondary_view); - if (secondary_view_->HitTestPoint(point_in_secondary_view) && - !secondary_view_->GetTooltipText(point_in_secondary_view).empty()) { - return secondary_view_; + View* handler = + secondary_view_->GetTooltipHandlerForPoint(point_in_secondary_view); + if (handler) { + gfx::Point point_in_handler_view(point); + ConvertPointToTarget(this, handler, &point_in_handler_view); + if (!handler->GetTooltipText(point_in_secondary_view).empty()) { + return handler; + } } }
diff --git a/chrome/browser/ui/views/hover_button.h b/chrome/browser/ui/views/hover_button.h index 21d0b91..fe69553 100644 --- a/chrome/browser/ui/views/hover_button.h +++ b/chrome/browser/ui/views/hover_button.h
@@ -111,6 +111,7 @@ views::StyledLabel* title() const { return title_; } views::Label* subtitle() const { return subtitle_; } views::View* icon_view() const { return icon_view_; } + views::View* secondary_view() const { return secondary_view_; } private: FRIEND_TEST_ALL_PREFIXES(media_router::CastDialogSinkButtonTest,
diff --git a/chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.cc b/chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.cc index 3dcc59b..38cfba5 100644 --- a/chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.cc +++ b/chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.cc
@@ -21,13 +21,14 @@ namespace { -constexpr int kBluetoothPairingDialogHeight = 350; +constexpr int kBluetoothPairingDialogHeight = 375; void AddBluetoothStrings(content::WebUIDataSource* html_source) { struct { const char* name; int id; } localized_strings[] = { + {"bluetoothPairDeviceTitle", IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE}, {"ok", IDS_OK}, {"cancel", IDS_CANCEL}, {"close", IDS_CLOSE}, @@ -68,9 +69,8 @@ const base::string16& name_for_display, bool paired, bool connected) - : SystemWebDialogDelegate( - GURL(chrome::kChromeUIBluetoothPairingURL), - l10n_util::GetStringUTF16(IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE)), + : SystemWebDialogDelegate(GURL(chrome::kChromeUIBluetoothPairingURL), + base::string16() /* title */), address_(address) { device_data_.SetString("address", address); device_data_.SetString("name", name_for_display);
diff --git a/chrome/browser/ui/webui/policy_indicator_localized_strings_provider.cc b/chrome/browser/ui/webui/policy_indicator_localized_strings_provider.cc index cf11f3c0..cc28e91 100644 --- a/chrome/browser/ui/webui/policy_indicator_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/policy_indicator_localized_strings_provider.cc
@@ -34,6 +34,7 @@ {"controlledSettingShared", IDS_CONTROLLED_SETTING_SHARED}, {"controlledSettingWithOwner", IDS_CONTROLLED_SETTING_WITH_OWNER}, {"controlledSettingNoOwner", IDS_CONTROLLED_SETTING_NO_OWNER}, + {"controlledSettingParent", IDS_CONTROLLED_SETTING_PARENT}, #endif }; AddLocalizedStringsBulk(html_source, localized_strings,
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc index 3f642cbd..e77572a 100644 --- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -83,12 +83,15 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); PrinterBasicInfo basic_info = ToBasicInfo(*printer); + bool has_secure_protocol = !printer->HasNetworkProtocol() || + printer->GetProtocol() == chromeos::Printer::kIpps; // USER_VISIBLE because the result is displayed in the print preview dialog. base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, base::BindOnce(&GetSettingsOnBlockingPool, printer->id(), basic_info, - PrinterSemanticCapsAndDefaults::Papers(), nullptr), + PrinterSemanticCapsAndDefaults::Papers(), + has_secure_protocol, nullptr), base::BindOnce(&CapabilitiesFetched, std::move(policies), std::move(cb))); }
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc index 8ddb28eb..c4ea832 100644 --- a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
@@ -63,6 +63,7 @@ return base::Value(); return GetSettingsOnBlockingPool(device_name, basic_info, additional_papers, + /* has_secure_protocol */ false, print_backend); }
diff --git a/chrome/common/extensions/api/_features.md b/chrome/common/extensions/api/_features.md index 5c05b24..11e5917 100644 --- a/chrome/common/extensions/api/_features.md +++ b/chrome/common/extensions/api/_features.md
@@ -286,8 +286,8 @@ allowed to access a feature. Extensions with a lesser manifest version cannot access the feature. -The only accepted value is `2`, as this is currently the highest possible -manifest version. +Accepted values are `2` and `3`, as 3 is currently the highest possible manifest +version. ### noparent
diff --git a/chrome/common/extensions/api/automation.idl b/chrome/common/extensions/api/automation.idl index 324d430..3f167a430 100644 --- a/chrome/common/extensions/api/automation.idl +++ b/chrome/common/extensions/api/automation.idl
@@ -718,6 +718,19 @@ // The affinity of the tree selection focus, if any. DOMString? focusAffinity; + // The selection start node of the tree selection, if any. + AutomationNode? selectionStartObject; + // The selection start offset of the tree selection, if any. + long? selectionStartOffset; + // The affinity of the tree selection start, if any. + DOMString? selectionStartAffinity; + // The selection end node of the tree selection, if any. + AutomationNode? selectionEndObject; + // The selection end offset of the tree selection, if any. + long? selectionEndOffset; + // The affinity of the tree selection end, if any. + DOMString? selectionEndAffinity; + // // Range attributes. // @@ -912,6 +925,12 @@ // Indicates whether this node is selected, unselected, or neither. boolean? selected; + // Indicates the font size of this node. + long? fontSize; + + // Indicates the font family. + DOMString fontFamily; + // // Walking the tree. //
diff --git a/chrome/common/extensions/api/devtools/inspected_window.json b/chrome/common/extensions/api/devtools/inspected_window.json index 5ccdc231..17fcc398 100644 --- a/chrome/common/extensions/api/devtools/inspected_window.json +++ b/chrome/common/extensions/api/devtools/inspected_window.json
@@ -37,7 +37,7 @@ { "name": "encoding", "type": "string", - "description": "Empty if content is not encoded, encoding name otherwise. Currently, only base64 is supported." + "description": "Empty if the content is not encoded, encoding name otherwise. Currently, only base64 is supported." } ] }
diff --git a/chrome/common/extensions/api/settings_private.idl b/chrome/common/extensions/api/settings_private.idl index 1e2996c..5a036e8 100644 --- a/chrome/common/extensions/api/settings_private.idl +++ b/chrome/common/extensions/api/settings_private.idl
@@ -13,7 +13,8 @@ USER_POLICY, OWNER, PRIMARY_USER, - EXTENSION + EXTENSION, + PARENT }; enum Enforcement { ENFORCED, RECOMMENDED };
diff --git a/chrome/common/extensions/api/top_sites.json b/chrome/common/extensions/api/top_sites.json index b1bd3cf3..1119a06 100644 --- a/chrome/common/extensions/api/top_sites.json +++ b/chrome/common/extensions/api/top_sites.json
@@ -5,7 +5,7 @@ [ { "namespace": "topSites", - "description": "Use the <code>chrome.topSites</code> API to access the top sites (i.e. most visited) that are displayed on the new tab page. These do not include shortcuts customized by the user.", + "description": "Use the <code>chrome.topSites</code> API to access the top sites (i.e. most visited sites) that are displayed on the new tab page. These do not include shortcuts customized by the user.", "types": [ { "id": "MostVisitedURL",
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_initvalue_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_initvalue_unittest.cc index d6cd935..fa1de5d 100644 --- a/chrome/common/extensions/manifest_tests/extension_manifests_initvalue_unittest.cc +++ b/chrome/common/extensions/manifest_tests/extension_manifests_initvalue_unittest.cc
@@ -72,6 +72,8 @@ Testcase("init_invalid_files_css_item_invalid.json", errors::kInvalidCss), Testcase("init_invalid_permissions_invalid.json", errors::kInvalidPermissions), + Testcase("init_invalid_host_permissions_invalid.json", + errors::kInvalidHostPermissions), Testcase("init_invalid_permissions_item_invalid.json", errors::kInvalidPermission), Testcase("init_invalid_options_url_invalid.json",
diff --git a/chrome/common/extensions/manifest_tests/permissions_parser_unittest.cc b/chrome/common/extensions/manifest_tests/permissions_parser_unittest.cc index ef3a58a..a87649b 100644 --- a/chrome/common/extensions/manifest_tests/permissions_parser_unittest.cc +++ b/chrome/common/extensions/manifest_tests/permissions_parser_unittest.cc
@@ -11,6 +11,15 @@ namespace extensions { +namespace { + +// Install warning for tests running Manifest v3. The current highest +// supported manifest version is 2. +constexpr char kManifestVersionWarning[] = + "The maximum currently-supported manifest version is 2, but this is 3. " + "Certain features may not work as expected."; +} // namespace + using PermissionsParserTest = ChromeManifestTest; TEST_F(PermissionsParserTest, RemoveOverlappingAPIPermissions) { @@ -97,4 +106,33 @@ testing::UnorderedElementsAre("*://*/*")); } +TEST_F(PermissionsParserTest, HostPermissionsKey) { + std::vector<std::string> expected_warnings; + expected_warnings.push_back(ErrorUtils::FormatErrorMessage( + manifest_errors::kPermissionUnknownOrMalformed, "https://google.com/*")); + + expected_warnings.push_back(kManifestVersionWarning); + + scoped_refptr<Extension> extension( + LoadAndExpectWarnings("host_permissions_key.json", expected_warnings)); + + // Expect that the host specified in |host_permissions| is parsed. + const URLPatternSet& required_hosts = + PermissionsParser::GetRequiredPermissions(extension.get()) + .explicit_hosts(); + + EXPECT_THAT(*required_hosts.ToStringVector(), + testing::UnorderedElementsAre("https://example.com/*")); +} + +TEST_F(PermissionsParserTest, HostPermissionsKeyInvalidHosts) { + std::vector<std::string> expected_warnings; + expected_warnings.push_back(ErrorUtils::FormatErrorMessage( + manifest_errors::kPermissionUnknownOrMalformed, "malformed_host")); + + expected_warnings.push_back(kManifestVersionWarning); + + scoped_refptr<Extension> extension(LoadAndExpectWarnings( + "host_permissions_key_invalid_hosts.json", expected_warnings)); +} } // namespace extensions
diff --git a/chrome/common/thread_profiler.cc b/chrome/common/thread_profiler.cc index f77b3f2..db16b3b 100644 --- a/chrome/common/thread_profiler.cc +++ b/chrome/common/thread_profiler.cc
@@ -159,6 +159,9 @@ } void ThreadProfiler::AddAuxUnwinder(std::unique_ptr<base::Unwinder> unwinder) { + if (!StackSamplingConfiguration::Get()->IsProfilerEnabledForCurrentProcess()) + return; + aux_unwinder_ = std::move(unwinder); startup_profiler_->AddAuxUnwinder(aux_unwinder_.get()); if (periodic_profiler_)
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn index 04dc719..b1b07bd7 100644 --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn
@@ -110,6 +110,8 @@ "tts_dispatcher.h", "url_loader_throttle_provider_impl.cc", "url_loader_throttle_provider_impl.h", + "v8_unwinder.cc", + "v8_unwinder.h", "web_apps.cc", "web_apps.h", "websocket_handshake_throttle_provider_impl.cc",
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 4938ded2..52162509 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -64,6 +64,7 @@ #include "chrome/renderer/prerender/prerenderer_client.h" #include "chrome/renderer/tts_dispatcher.h" #include "chrome/renderer/url_loader_throttle_provider_impl.h" +#include "chrome/renderer/v8_unwinder.h" #include "chrome/renderer/websocket_handshake_throttle_provider_impl.h" #include "chrome/renderer/worker_content_settings_client.h" #include "components/autofill/content/renderer/autofill_agent.h"
diff --git a/chrome/renderer/v8_unwinder.cc b/chrome/renderer/v8_unwinder.cc new file mode 100644 index 0000000..b107564 --- /dev/null +++ b/chrome/renderer/v8_unwinder.cc
@@ -0,0 +1,112 @@ +// Copyright 2019 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 "chrome/renderer/v8_unwinder.h" + +#include <memory> +#include <string> + +#include "base/strings/strcat.h" + +namespace { + +// Synthetic build ids to use for V8 modules. The difference is in the digit +// after the leading 5's. +// clang-format off +const char kV8EmbeddedCodeRangeBuildId[] = + "5555555507284E1E874EFA4EB754964B999"; +const char kV8CodeRangeBuildId[] = + "5555555517284E1E874EFA4EB754964B999"; +// clang-format on + +class V8Module : public base::ModuleCache::Module { + public: + V8Module(const v8::MemoryRange& memory_range, + const std::string& build_id, + const std::string& descriptor) + : memory_range_(memory_range), + build_id_(build_id), + descriptor_(descriptor) {} + + V8Module(const V8Module&) = delete; + V8Module& operator=(const V8Module&) = delete; + + // ModuleCache::Module + uintptr_t GetBaseAddress() const override { + return reinterpret_cast<uintptr_t>(memory_range_.start); + } + + std::string GetId() const override { return build_id_; } + + base::FilePath GetDebugBasename() const override { + return base::FilePath().AppendASCII(base::StrCat({"V8 ", descriptor_})); + } + + size_t GetSize() const override { return memory_range_.length_in_bytes; } + + bool IsNative() const override { return false; } + + private: + const v8::MemoryRange memory_range_; + const std::string build_id_; + const std::string descriptor_; +}; + +} // namespace + +V8Unwinder::V8Unwinder(const v8::UnwindState& unwind_state) + : unwind_state_(unwind_state) {} + +V8Unwinder::~V8Unwinder() = default; + +void V8Unwinder::AddNonNativeModules(base::ModuleCache* module_cache) { + std::vector<std::unique_ptr<base::ModuleCache::Module>> modules; + modules.emplace_back(std::make_unique<V8Module>( + unwind_state_.embedded_code_range, kV8EmbeddedCodeRangeBuildId, + "Embedded Code Range")); + modules.emplace_back(std::make_unique<V8Module>( + unwind_state_.code_range, kV8CodeRangeBuildId, "Code Range")); + for (auto& module : modules) { + v8_modules_.insert(module.get()); + module_cache->AddNonNativeModule(std::move(module)); + } +} + +bool V8Unwinder::CanUnwindFrom(const base::Frame* current_frame) const { + return v8_modules_.find(current_frame->module) != v8_modules_.end(); +} + +base::UnwindResult V8Unwinder::TryUnwind( + base::RegisterContext* thread_context, + uintptr_t stack_top, + base::ModuleCache* module_cache, + std::vector<base::Frame>* stack) const { + v8::RegisterState register_state; + register_state.pc = reinterpret_cast<void*>( + base::RegisterContextInstructionPointer(thread_context)); + register_state.sp = reinterpret_cast<void*>( + base::RegisterContextStackPointer(thread_context)); + register_state.fp = reinterpret_cast<void*>( + base::RegisterContextFramePointer(thread_context)); + + if (!v8::Unwinder::TryUnwindV8Frames( + unwind_state_, ®ister_state, + reinterpret_cast<const void*>(stack_top))) { + return base::UnwindResult::ABORTED; + } + + base::RegisterContextInstructionPointer(thread_context) = + reinterpret_cast<uintptr_t>(register_state.pc); + base::RegisterContextStackPointer(thread_context) = + reinterpret_cast<uintptr_t>(register_state.sp); + base::RegisterContextFramePointer(thread_context) = + reinterpret_cast<uintptr_t>(register_state.fp); + + stack->emplace_back( + base::RegisterContextInstructionPointer(thread_context), + module_cache->GetModuleForAddress( + base::RegisterContextInstructionPointer(thread_context))); + + return base::UnwindResult::UNRECOGNIZED_FRAME; +}
diff --git a/chrome/renderer/v8_unwinder.h b/chrome/renderer/v8_unwinder.h new file mode 100644 index 0000000..57f13fc --- /dev/null +++ b/chrome/renderer/v8_unwinder.h
@@ -0,0 +1,35 @@ +// Copyright 2019 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 CHROME_RENDERER_V8_UNWINDER_H_ +#define CHROME_RENDERER_V8_UNWINDER_H_ + +#include "base/containers/flat_set.h" +#include "base/profiler/unwinder.h" +#include "v8/include/v8.h" + +// Implements stack frame unwinding for V8 generated code frames, for use with +// the StackSamplingProfiler. +class V8Unwinder : public base::Unwinder { + public: + explicit V8Unwinder(const v8::UnwindState& unwind_state); + ~V8Unwinder() override; + + V8Unwinder(const V8Unwinder&) = delete; + V8Unwinder& operator=(const V8Unwinder&) = delete; + + // Unwinder: + void AddNonNativeModules(base::ModuleCache* module_cache) override; + bool CanUnwindFrom(const base::Frame* current_frame) const override; + base::UnwindResult TryUnwind(base::RegisterContext* thread_context, + uintptr_t stack_top, + base::ModuleCache* module_cache, + std::vector<base::Frame>* stack) const override; + + private: + const v8::UnwindState unwind_state_; + base::flat_set<const base::ModuleCache::Module*> v8_modules_; +}; + +#endif // CHROME_RENDERER_V8_UNWINDER_H_
diff --git a/chrome/test/chromedriver/element_util.cc b/chrome/test/chromedriver/element_util.cc index 33a4c7b..4f13ca5 100644 --- a/chrome/test/chromedriver/element_util.cc +++ b/chrome/test/chromedriver/element_util.cc
@@ -402,11 +402,17 @@ WebView* web_view, std::unique_ptr<base::Value>* value) { base::ListValue args; - return web_view->CallFunction( + Status status = web_view->CallFunction( session->GetCurrentFrameId(), - "function() { return document.activeElement || document.body }", - args, + "function() { return document.activeElement || document.body }", args, value); + if (status.IsError()) { + return status; + } + if (value->get()->is_none()) { + return Status(kNoSuchElement); + } + return status; } Status IsElementFocused(
diff --git a/chrome/test/data/extensions/manifest_tests/host_permissions_key.json b/chrome/test/data/extensions/manifest_tests/host_permissions_key.json new file mode 100644 index 0000000..c4e8870 --- /dev/null +++ b/chrome/test/data/extensions/manifest_tests/host_permissions_key.json
@@ -0,0 +1,12 @@ +{ + "name": "Host permissions manifest key", + "version": "0.1", + "manifest_version": 3, + "description": "extension with hosts in both |permissions| and |host_permissions|", + "permissions": [ + "https://google.com/*" + ], + "host_permissions": [ + "https://example.com/*" + ] +}
diff --git a/chrome/test/data/extensions/manifest_tests/host_permissions_key_invalid_hosts.json b/chrome/test/data/extensions/manifest_tests/host_permissions_key_invalid_hosts.json new file mode 100644 index 0000000..8414431 --- /dev/null +++ b/chrome/test/data/extensions/manifest_tests/host_permissions_key_invalid_hosts.json
@@ -0,0 +1,9 @@ +{ + "name": "Host permissions with malformed host", + "version": "0.1", + "manifest_version": 3, + "description": "Extension with an invalid host in host_permissions", + "host_permissions": [ + "malformed_host" + ] +}
diff --git a/chrome/test/data/extensions/manifest_tests/init_invalid_host_permissions_invalid.json b/chrome/test/data/extensions/manifest_tests/init_invalid_host_permissions_invalid.json new file mode 100644 index 0000000..f065b4f --- /dev/null +++ b/chrome/test/data/extensions/manifest_tests/init_invalid_host_permissions_invalid.json
@@ -0,0 +1,6 @@ +{ + "name": "Host permissions not a list", + "version": "0.1", + "manifest_version": 3, + "host_permissions": "Why wont this work?!" +}
diff --git a/chrome/test/data/webui/cr_elements/cr_policy_strings.js b/chrome/test/data/webui/cr_elements/cr_policy_strings.js index 5c1c966..8a4583b 100644 --- a/chrome/test/data/webui/cr_elements/cr_policy_strings.js +++ b/chrome/test/data/webui/cr_elements/cr_policy_strings.js
@@ -13,4 +13,5 @@ controlledSettingNoOwner: 'owner', controlledSettingExtension: 'extension: $1', controlledSettingExtensionWithoutName: 'extension', + controlledSettingParent: 'parent', };
diff --git a/chrome/test/data/xr/e2e_test_files/html/test_inline_identity_available.html b/chrome/test/data/xr/e2e_test_files/html/test_inline_identity_available.html index c2ef483..58559d4 100644 --- a/chrome/test/data/xr/e2e_test_files/html/test_inline_identity_available.html +++ b/chrome/test/data/xr/e2e_test_files/html/test_inline_identity_available.html
@@ -33,7 +33,7 @@ navigator.xr.supportsSessionMode('inline') .then(()=> { step = "requestSession"; - return navigator.xr.requestSession(); + return navigator.xr.requestSession('inline'); }) .then((xrSession) => { session = xrSession;
diff --git a/chrome/test/data/xr/e2e_test_files/html/test_stationary_reference_space_rejects.html b/chrome/test/data/xr/e2e_test_files/html/test_stationary_reference_space_rejects.html index 12cf99a..85a8ec4a 100644 --- a/chrome/test/data/xr/e2e_test_files/html/test_stationary_reference_space_rejects.html +++ b/chrome/test/data/xr/e2e_test_files/html/test_stationary_reference_space_rejects.html
@@ -11,7 +11,7 @@ <script src="../resources/webxr_e2e.js"></script> <script> let session_ = null; - navigator.xr.requestSession() + navigator.xr.requestSession('inline') .then((xrSession) => { session_ = xrSession; return xrSession.requestReferenceSpace({ type: 'stationary', subtype: 'floor-level'});
diff --git a/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_rejected_if_don_canceled.html b/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_rejected_if_don_canceled.html index 9b061e9..f0514cc 100644 --- a/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_rejected_if_don_canceled.html +++ b/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_rejected_if_don_canceled.html
@@ -14,7 +14,7 @@ <script src="../resources/webxr_boilerplate.js"></script> <script> function onImmersiveRequestWithDon() { - navigator.xr.requestSession({mode: 'immersive-vr'}).then( (session) => { + navigator.xr.requestSession('immersive-vr').then( (session) => { assert_unreached("requestPresent promise resolved"); }, () => { // Do nothing when the promise is rejected
diff --git a/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_unresolved_during_don.html b/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_unresolved_during_don.html index 58b0882..a6e1566 100644 --- a/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_unresolved_during_don.html +++ b/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_unresolved_during_don.html
@@ -14,7 +14,7 @@ <script src="../resources/webxr_boilerplate.js"></script> <script> function onImmersiveRequestWithDon() { - navigator.xr.requestSession({mode: 'immersive-vr'}).then( (session) => { + navigator.xr.requestSession('immersive-vr').then( (session) => { assert_unreached("requestSession promise resolved"); }, () => { assert_unreached("requestSession promise rejected");
diff --git a/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js b/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js index d599e2e..f7f2fc0 100644 --- a/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js +++ b/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js
@@ -85,7 +85,7 @@ switch (sessionTypeToRequest) { case sessionTypes.IMMERSIVE: console.info('Requesting immersive VR session'); - navigator.xr.requestSession({mode: 'immersive-vr'}).then( (session) => { + navigator.xr.requestSession('immersive-vr').then( (session) => { console.info('Immersive VR session request succeeded'); sessionInfos[sessionTypes.IMMERSIVE].currentSession = session; onSessionStarted(session); @@ -95,17 +95,14 @@ break; case sessionTypes.AR: console.info('Requesting Immersive AR session'); - navigator.xr.requestSession({mode: 'immersive-ar'}).then((session) => { + navigator.xr.requestSession('immersive-ar').then((session) => { console.info('Immersive AR session request succeeded'); sessionInfos[sessionTypes.AR].currentSession = session; onSessionStarted(session); }, (error) => { console.info('Immersive AR session request rejected with: ' + error); console.info('Attempting to fall back to legacy AR mode'); - let sessionOptions = { - mode: 'legacy-inline-ar' - } - navigator.xr.requestSession(sessionOptions).then( + navigator.xr.requestSession('legacy-inline-ar').then( (session) => { session.updateRenderState({ outputContext: webglCanvas.getContext('xrpresent') @@ -198,7 +195,7 @@ // Set up an inline session (magic window) drawing into the full screen canvas // on the page let ctx = webglCanvas.getContext('xrpresent'); - navigator.xr.requestSession() + navigator.xr.requestSession('inline') .then((session) => { session.updateRenderState({ outputContext: ctx
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc index db9ef80..8dc9ba6 100644 --- a/chromecast/browser/cast_content_browser_client.cc +++ b/chromecast/browser/cast_content_browser_client.cc
@@ -1055,25 +1055,12 @@ return chromecast::shell::GetUserAgent(); } -void CastContentBrowserClient::RegisterOutOfProcessServices( - OutOfProcessServiceMap* services) { -#if !defined(OS_FUCHSIA) - if (!heap_profiling::IsInProcessModeEnabled()) { - services->emplace( - heap_profiling::mojom::kServiceName, - base::BindRepeating(&base::ASCIIToUTF16, "Profiling Service")); - } -#endif // !defined(OS_FUCHSIA) -} - void CastContentBrowserClient::RegisterIOThreadServiceHandlers( content::ServiceManagerConnection* connection) { #if !defined(OS_FUCHSIA) - if (heap_profiling::IsInProcessModeEnabled()) { - connection->AddServiceRequestHandler( - heap_profiling::mojom::kServiceName, - heap_profiling::HeapProfilingService::GetServiceFactory()); - } + connection->AddServiceRequestHandler( + heap_profiling::mojom::kServiceName, + heap_profiling::HeapProfilingService::GetServiceFactory()); #endif // !defined(OS_FUCHSIA) }
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h index 9d0d443..6c96f35c 100644 --- a/chromecast/browser/cast_content_browser_client.h +++ b/chromecast/browser/cast_content_browser_client.h
@@ -218,7 +218,6 @@ bool in_memory, const base::FilePath& relative_partition_path) override; std::string GetUserAgent() const override; - void RegisterOutOfProcessServices(OutOfProcessServiceMap* services) override; void RegisterIOThreadServiceHandlers( content::ServiceManagerConnection* connection) override; bool DoesSiteRequireDedicatedProcess(
diff --git a/components/autofill/core/browser/label_formatter_utils.cc b/components/autofill/core/browser/label_formatter_utils.cc index 69e51e7..aaaf9ef 100644 --- a/components/autofill/core/browser/label_formatter_utils.cc +++ b/components/autofill/core/browser/label_formatter_utils.cc
@@ -245,4 +245,48 @@ data_util::GetCountryCodeWithFallback(profile, app_locale))); } +bool HaveSameEmailAddresses(const std::vector<AutofillProfile*>& profiles, + const std::string& app_locale) { + bool first_email_found = false; + base::string16 first_email; + + for (const AutofillProfile* profile : profiles) { + base::string16 email_from_profile = GetLabelEmail(*profile, app_locale); + + if (!first_email_found) { + // Store the first email address whether it's empty or not because we + // consider "" and "hao.le@aol.com" to be different email addresses. + first_email_found = true; + first_email = email_from_profile; + } else if (email_from_profile != first_email) { + return false; + } + } + return true; +} + +bool HaveSamePhoneNumbers(const std::vector<AutofillProfile*>& profiles, + const std::string& app_locale) { + bool first_phone_found = false; + base::string16 first_phone; + + for (const AutofillProfile* profile : profiles) { + base::string16 phone_from_profile = GetLabelPhone(*profile, app_locale); + + if (!first_phone_found) { + // Store the first phone number whether it's empty or not because we + // consider "" and "(514) 873-1100" to be different phone numbers. + first_phone_found = true; + first_phone = phone_from_profile; + } else if (!(first_phone.empty() && phone_from_profile.empty()) && + !i18n::PhoneNumbersMatch(first_phone, phone_from_profile, + base::UTF16ToASCII(profile->GetInfo( + ADDRESS_HOME_COUNTRY, app_locale)), + app_locale)) { + return false; + } + } + return true; +} + } // namespace autofill
diff --git a/components/autofill/core/browser/label_formatter_utils.h b/components/autofill/core/browser/label_formatter_utils.h index 3ded23ba..f9d523c6 100644 --- a/components/autofill/core/browser/label_formatter_utils.h +++ b/components/autofill/core/browser/label_formatter_utils.h
@@ -103,8 +103,9 @@ // |profile|. If |focused_field_type| is a street address field, then returns // non-street-address data, e.g. Lowell, MA 01852. // -// If the focused type is not a street address field and if |form_has_street_ -// address| is true, then returns street-address data, e.g. 375 Merrimack St. +// If the focused type is not a street address field and if +// |form_has_street_address| is true, then returns street-address data, e.g. 375 +// Merrimack St. // // If the focused type is not a street address field and if the form does not // have a street address, then returns the parts of the address in the form @@ -163,6 +164,18 @@ base::string16 GetLabelPhone(const AutofillProfile& profile, const std::string& app_locale); +// Returns true if all |profiles| have the same email address. Note that the +// absence of an email address and an actual email address, e.g. +// joe.bray@aol.com, are considered different email addresses. +bool HaveSameEmailAddresses(const std::vector<AutofillProfile*>& profiles, + const std::string& app_locale); + +// Returns true if all |profiles| have the same phone number after +// normalization. Note that the absence of a phone number and an actual phone +// number, e.g. (401) 847-8720, are considered different phone numbers. +bool HaveSamePhoneNumbers(const std::vector<AutofillProfile*>& profiles, + const std::string& app_locale); + } // namespace autofill #endif // COMPONENTS_AUTOFILL_CORE_BROWSER_LABEL_FORMATTER_UTILS_H_
diff --git a/components/autofill/core/browser/label_formatter_utils_unittest.cc b/components/autofill/core/browser/label_formatter_utils_unittest.cc index c0383ae..806aac0 100644 --- a/components/autofill/core/browser/label_formatter_utils_unittest.cc +++ b/components/autofill/core/browser/label_formatter_utils_unittest.cc
@@ -4,8 +4,12 @@ #include "components/autofill/core/browser/label_formatter_utils.h" +#include "base/guid.h" +#include "base/strings/string16.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/autofill_test_utils.h" #include "components/grit/components_scaled_resources.h" #include "components/strings/grit/components_strings.h" #include "testing/gtest/include/gtest/gtest.h" @@ -92,4 +96,150 @@ ConstructLabelLine({name, phone, email})); } -} // namespace autofill \ No newline at end of file +TEST(LabelFormatterUtilsTest, + HaveSameEmailAddressesWithOneProfileAndNoEmailAddress) { + AutofillProfile profile = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile, "Maria", "Margaretha", "Kirch", + "mmkirch@gmx.de", "", "", "", "", "", "", "DE", ""); + EXPECT_TRUE(HaveSameEmailAddresses({&profile}, "de")); +} + +TEST(LabelFormatterUtilsTest, + HaveSameEmailAddressesWithOneProfileAndEmailAddress) { + AutofillProfile profile = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile, "Maria", "Margaretha", "Kirch", "", "", "", "", + "", "", "", "DE", ""); + EXPECT_TRUE(HaveSameEmailAddresses({&profile}, "de")); +} + +TEST(LabelFormatterUtilsTest, + HaveSameEmailAddressesWithProfilesAndNoEmailAddresses) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", "", "", "", + "", "", "", "", "DE", ""); + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", "", "", + "", "", "", "", "", "DE", ""); + EXPECT_TRUE(HaveSameEmailAddresses({&profile1, &profile2}, "de")); +} + +TEST(LabelFormatterUtilsTest, + HaveSameEmailAddressesWithProfilesAndSameEmailAddresses) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", + "mmkirch@gmx.de", "", "", "", "", "", "", "DE", ""); + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", + "mmkirch@gmx.de", "", "", "", "", "", "", "DE", ""); + EXPECT_TRUE(HaveSameEmailAddresses({&profile1, &profile2}, "de")); +} + +TEST(LabelFormatterUtilsTest, + HaveSameEmailAddressesWithProfilesAndDifferentNonEmptyEmailAddresses) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", + "mmkirch@gmx.de", "", "", "", "", "", "", "DE", ""); + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", + "mmw@gmail.com", "", "", "", "", "", "", "DE", ""); + EXPECT_FALSE(HaveSameEmailAddresses({&profile1, &profile2}, "de")); +} + +TEST(LabelFormatterUtilsTest, + HaveSameEmailAddressesWithProfilesAndNonEmptyAndEmptyEmailAddresses) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", + "mmkirch@gmx.de", "", "", "", "", "", "", "DE", ""); + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", "", "", + "", "", "", "", "", "DE", ""); + EXPECT_FALSE(HaveSameEmailAddresses({&profile1, &profile2}, "de")); + EXPECT_FALSE(HaveSameEmailAddresses({&profile2, &profile1}, "de")); +} + +TEST(LabelFormatterUtilsTest, + HaveSamePhoneNumbersWithOneProfileAndNoPhoneNumber) { + AutofillProfile profile = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile, "Maria", "Margaretha", "Kirch", "", "", "", "", + "", "", "", "DE", ""); + EXPECT_TRUE(HaveSamePhoneNumbers({&profile}, "de")); +} + +TEST(LabelFormatterUtilsTest, + HaveSamePhoneNumbersWithOneProfileAndPhoneNumber) { + AutofillProfile profile = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile, "Maria", "Margaretha", "Kirch", "", "", "", "", + "", "", "", "DE", "+49 30 4504-2823"); + EXPECT_TRUE(HaveSamePhoneNumbers({&profile}, "de")); +} + +TEST(LabelFormatterUtilsTest, + HaveSamePhoneNumbersWithProfilesAndNoPhoneNumber) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", "", "", "", + "", "", "", "", "DE", ""); + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", "", "", + "", "", "", "", "", "DE", ""); + EXPECT_TRUE(HaveSamePhoneNumbers({&profile1, &profile2}, "de")); +} + +TEST(LabelFormatterUtilsTest, + HaveSamePhoneNumbersWithProfilesAndSamePhoneNumbers) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", "", "", "", + "", "", "", "", "DE", "+49 30 4504-2823"); + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", "", "", + "", "", "", "", "", "DE", "4903045042823"); + AutofillProfile profile3 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile3, "Maria", "Margaretha", "Winckelmann", "", "", + "", "", "", "", "", "DE", "03045042823"); + EXPECT_TRUE(HaveSamePhoneNumbers({&profile1, &profile2, &profile3}, "de")); +} + +TEST(LabelFormatterUtilsTest, + HaveSamePhoneNumbersWithProfilesAndDifferentNonEmptyPhoneNumbers) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", "", "", "", + "", "", "", "", "DE", "+49 30 4504-2823"); + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", "", "", + "", "", "", "", "", "DE", "+49 221 22123828"); + EXPECT_FALSE(HaveSamePhoneNumbers({&profile1, &profile2}, "de")); +} + +TEST(LabelFormatterUtilsTest, + HaveSamePhoneNumbersWithProfilesAndNonEmptyAndEmptyPhoneNumbers) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", "", "", "", + "", "", "", "", "DE", "+49 30 4504-2823"); + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", "", "", + "", "", "", "", "", "DE", ""); + EXPECT_FALSE(HaveSamePhoneNumbers({&profile1, &profile2}, "de")); + EXPECT_FALSE(HaveSamePhoneNumbers({&profile2, &profile1}, "de")); +} + +} // namespace autofill
diff --git a/components/autofill/core/browser/phone_number_i18n.cc b/components/autofill/core/browser/phone_number_i18n.cc index 956eed00..ecfbe9a 100644 --- a/components/autofill/core/browser/phone_number_i18n.cc +++ b/components/autofill/core/browser/phone_number_i18n.cc
@@ -265,6 +265,8 @@ const base::string16& number_b, const std::string& raw_region, const std::string& app_locale) { + // TODO(crbug.com/953678): Maybe return true if two empty strings are given. + // Sanitize the provided |raw_region| before trying to use it for parsing. const std::string region = SanitizeRegion(raw_region, app_locale);
diff --git a/components/heap_profiling/heap_profiling_test_shim.cc b/components/heap_profiling/heap_profiling_test_shim.cc index bae0523..5c952f0 100644 --- a/components/heap_profiling/heap_profiling_test_shim.cc +++ b/components/heap_profiling/heap_profiling_test_shim.cc
@@ -32,7 +32,6 @@ const base::android::JavaParamRef<jstring>& mode, jboolean dynamically_start_profiling, const base::android::JavaParamRef<jstring>& stack_mode, - jboolean stream_samples, jboolean should_sample, jboolean sample_everything) { heap_profiling::TestDriver driver; @@ -42,7 +41,6 @@ options.stack_mode = heap_profiling::ConvertStringToStackMode( base::android::ConvertJavaStringToUTF8(stack_mode)); options.profiling_already_started = !dynamically_start_profiling; - options.stream_samples = stream_samples; options.should_sample = should_sample; options.sample_everything = sample_everything; return driver.RunTest(options);
diff --git a/components/heap_profiling/heap_profiling_test_shim.h b/components/heap_profiling/heap_profiling_test_shim.h index 558933c..134d548 100644 --- a/components/heap_profiling/heap_profiling_test_shim.h +++ b/components/heap_profiling/heap_profiling_test_shim.h
@@ -23,7 +23,6 @@ const base::android::JavaParamRef<jstring>& mode, jboolean dynamically_start_profiling, const base::android::JavaParamRef<jstring>& stack_mode, - jboolean stream_samples, jboolean should_sample, jboolean sample_everything);
diff --git a/components/heap_profiling/javatests/src/org/chromium/components/heap_profiling/HeapProfilingTestShim.java b/components/heap_profiling/javatests/src/org/chromium/components/heap_profiling/HeapProfilingTestShim.java index c7f788e..f55ceaf8 100644 --- a/components/heap_profiling/javatests/src/org/chromium/components/heap_profiling/HeapProfilingTestShim.java +++ b/components/heap_profiling/javatests/src/org/chromium/components/heap_profiling/HeapProfilingTestShim.java
@@ -23,9 +23,9 @@ * rather than native stacks. */ public boolean runTestForMode(String mode, boolean dynamicallyStartProfiling, String stackMode, - boolean streamSamples, boolean shouldSample, boolean sampleEverything) { + boolean shouldSample, boolean sampleEverything) { return nativeRunTestForMode(mNativeHeapProfilingTestShim, mode, dynamicallyStartProfiling, - stackMode, streamSamples, shouldSample, sampleEverything); + stackMode, shouldSample, sampleEverything); } /** @@ -43,6 +43,6 @@ private native long nativeInit(); private native void nativeDestroy(long nativeHeapProfilingTestShim); private native boolean nativeRunTestForMode(long nativeHeapProfilingTestShim, String mode, - boolean dynamicallyStartProfiling, String stackMode, boolean streamSamples, - boolean shouldSample, boolean sampleEverything); + boolean dynamicallyStartProfiling, String stackMode, boolean shouldSample, + boolean sampleEverything); }
diff --git a/components/heap_profiling/supervisor.cc b/components/heap_profiling/supervisor.cc index 57609f1..8406aa78 100644 --- a/components/heap_profiling/supervisor.cc +++ b/components/heap_profiling/supervisor.cc
@@ -60,26 +60,24 @@ void Supervisor::Start(content::ServiceManagerConnection* connection, base::OnceClosure closure) { - bool stream_samples = !IsInProcessModeEnabled(); Start(connection, GetModeForStartup(), GetStackModeForStartup(), - stream_samples, GetSamplingRateForStartup(), std::move(closure)); + GetSamplingRateForStartup(), std::move(closure)); } void Supervisor::Start(content::ServiceManagerConnection* connection, Mode mode, mojom::StackMode stack_mode, - bool stream_samples, uint32_t sampling_rate, base::OnceClosure closure) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK(!started_); base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO}) - ->PostTask(FROM_HERE, base::BindOnce(&Supervisor::StartServiceOnIOThread, - base::Unretained(this), - connection->GetConnector()->Clone(), - mode, stack_mode, stream_samples, - sampling_rate, std::move(closure))); + ->PostTask(FROM_HERE, + base::BindOnce(&Supervisor::StartServiceOnIOThread, + base::Unretained(this), + connection->GetConnector()->Clone(), mode, + stack_mode, sampling_rate, std::move(closure))); } Mode Supervisor::GetMode() { @@ -171,13 +169,12 @@ std::unique_ptr<service_manager::Connector> connector, Mode mode, mojom::StackMode stack_mode, - bool stream_samples, uint32_t sampling_rate, base::OnceClosure closure) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - controller_.reset(new Controller(std::move(connector), stack_mode, - stream_samples, sampling_rate)); + controller_.reset( + new Controller(std::move(connector), stack_mode, sampling_rate)); base::WeakPtr<Controller> controller_weak_ptr = controller_->GetWeakPtr(); base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI})
diff --git a/components/heap_profiling/supervisor.h b/components/heap_profiling/supervisor.h index fdaf4abb..4bd167c 100644 --- a/components/heap_profiling/supervisor.h +++ b/components/heap_profiling/supervisor.h
@@ -72,7 +72,6 @@ void Start(content::ServiceManagerConnection* connection, Mode mode, mojom::StackMode stack_mode, - bool stream_samples, uint32_t sampling_rate, base::OnceClosure callback); @@ -113,7 +112,6 @@ std::unique_ptr<service_manager::Connector> connector, Mode mode, mojom::StackMode stack_mode, - bool stream_samples, uint32_t sampling_rate, base::OnceClosure callback);
diff --git a/components/heap_profiling/test_driver.cc b/components/heap_profiling/test_driver.cc index d9f6ed9b..1bcedae 100644 --- a/components/heap_profiling/test_driver.cc +++ b/components/heap_profiling/test_driver.cc
@@ -711,8 +711,8 @@ ? (options_.sample_everything ? 2 : kSampleRate) : 1; Supervisor::GetInstance()->Start(connection, options_.mode, - options_.stack_mode, options_.stream_samples, - sampling_rate, std::move(start_callback)); + options_.stack_mode, sampling_rate, + std::move(start_callback)); return true; } @@ -764,8 +764,8 @@ ? (options_.sample_everything ? 2 : kSampleRate) : 1; Supervisor::GetInstance()->Start(connection, options_.mode, - options_.stack_mode, options_.stream_samples, - sampling_rate, std::move(start_callback)); + options_.stack_mode, sampling_rate, + std::move(start_callback)); run_loop->Run();
diff --git a/components/heap_profiling/test_driver.h b/components/heap_profiling/test_driver.h index 2cc761b..ebf13638 100644 --- a/components/heap_profiling/test_driver.h +++ b/components/heap_profiling/test_driver.h
@@ -49,11 +49,6 @@ // The stack profiling mode to test. mojom::StackMode stack_mode = mojom::StackMode::NATIVE_WITHOUT_THREAD_NAMES; - // Whether the client should stream samples as they are collected through - // the provided pipe. When false the samples are accumulated on the client - // side and can be retrieved later. - bool stream_samples = true; - // Whether the caller has already started profiling with the given mode. // When false, the test driver is responsible for starting profiling. bool profiling_already_started = false;
diff --git a/components/mirroring/service/mirror_settings.cc b/components/mirroring/service/mirror_settings.cc index 3c51c1e..14f337d 100644 --- a/components/mirroring/service/mirror_settings.cc +++ b/components/mirroring/service/mirror_settings.cc
@@ -21,17 +21,16 @@ constexpr base::TimeDelta kAnimatedPlayoutDelay = base::TimeDelta::FromMilliseconds(400); -// Minimum end-to-end latency. This allows cast streaming to adaptively lower -// latency in interactive streaming scenarios. -// TODO(miu): This was 120 before stable launch, but we got user feedback that -// this was causing audio drop-outs. So, we need to fix the Cast Streaming -// implementation before lowering this setting. +// Minimum end-to-end latency. constexpr base::TimeDelta kMinPlayoutDelay = base::TimeDelta::FromMilliseconds(400); -// Maximum end-to-end latency. +// Maximum end-to-end latency. Currently, this is kMinPlayoutDelay, effectively +// disabling adaptive latency control, because of audio playout regressions +// (b/32876644). +// TODO(https://crbug.com/openscreen/44): Re-enable in port to Open Screen. constexpr base::TimeDelta kMaxPlayoutDelay = - base::TimeDelta::FromMilliseconds(800); + base::TimeDelta::FromMilliseconds(400); constexpr int kAudioTimebase = 48000; constexpr int kVidoTimebase = 90000;
diff --git a/components/neterror/resources/offline.js b/components/neterror/resources/offline.js index de4b80dd..99c112b 100644 --- a/components/neterror/resources/offline.js +++ b/components/neterror/resources/offline.js
@@ -118,7 +118,7 @@ GRAVITY: 0.6, INITIAL_JUMP_VELOCITY: 12, INVERT_FADE_DURATION: 12000, - INVERT_DISTANCE: 100, + INVERT_DISTANCE: 700, MAX_BLINK_COUNT: 3, MAX_CLOUDS: 6, MAX_OBSTACLE_LENGTH: 3,
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc index eb722502..c1e692d 100644 --- a/components/omnibox/browser/autocomplete_controller.cc +++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -664,7 +664,9 @@ i->description.clear(); i->description_class.clear(); DCHECK(!i->keyword.empty()); - if (i->keyword != last_keyword || show_suffix_on_all_search_suggestions) { + if (show_suffix_on_all_search_suggestions || + (i->keyword != last_keyword && + !ShouldCurbKeywordDescriptions(i->keyword))) { const TemplateURL* template_url = i->GetTemplateURL(template_url_service_, false); if (template_url) { @@ -790,6 +792,12 @@ } } +bool AutocompleteController::ShouldCurbKeywordDescriptions( + const base::string16& keyword) { + return AutocompleteProvider::InExplicitExperimentalKeywordMode(input_, + keyword); +} + bool AutocompleteController::OnMemoryDump( const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* process_memory_dump) {
diff --git a/components/omnibox/browser/autocomplete_controller.h b/components/omnibox/browser/autocomplete_controller.h index 56899b6..bd0192d 100644 --- a/components/omnibox/browser/autocomplete_controller.h +++ b/components/omnibox/browser/autocomplete_controller.h
@@ -204,6 +204,11 @@ void StopHelper(bool clear_result, bool due_to_user_inactivity); + // Helper for UpdateKeywordDescriptions(). Returns whether curbing the keyword + // descriptions is enabled, and whether there is enough input to guarantee + // that the Omnibox is in keyword mode. + bool ShouldCurbKeywordDescriptions(const base::string16& keyword); + // MemoryDumpProvider: bool OnMemoryDump( const base::trace_event::MemoryDumpArgs& args,
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc index 0053538..1f7d33e 100644 --- a/components/omnibox/browser/autocomplete_match.cc +++ b/components/omnibox/browser/autocomplete_match.cc
@@ -229,7 +229,6 @@ return omnibox::kPageIcon; case Type::SEARCH_WHAT_YOU_TYPED: - case Type::SEARCH_HISTORY: case Type::SEARCH_SUGGEST: case Type::SEARCH_SUGGEST_ENTITY: case Type::SEARCH_SUGGEST_PERSONALIZED: @@ -241,6 +240,14 @@ case Type::CLIPBOARD_IMAGE: return vector_icons::kSearchIcon; + case Type::SEARCH_HISTORY: { + if (base::FeatureList::IsEnabled( + omnibox::kOmniboxSuggestionTransparencyOptions)) { + return omnibox::kClockIcon; + } + return vector_icons::kSearchIcon; + } + case Type::EXTENSION_APP_DEPRECATED: return omnibox::kExtensionAppIcon;
diff --git a/components/omnibox/browser/autocomplete_provider.cc b/components/omnibox/browser/autocomplete_provider.cc index ebdf86b..854de5e0 100644 --- a/components/omnibox/browser/autocomplete_provider.cc +++ b/components/omnibox/browser/autocomplete_provider.cc
@@ -13,6 +13,7 @@ #include "base/logging.h" #include "base/no_destructor.h" #include "base/strings/string_split.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/trace_event/memory_usage_estimator.h" #include "components/bookmarks/browser/bookmark_utils.h" @@ -240,3 +241,24 @@ url->erase(scheme_pos, prefix_end - scheme_pos); return (scheme_pos == 0) ? prefix_end : 0; } + +// static +bool AutocompleteProvider::InExplicitExperimentalKeywordMode( + const AutocompleteInput& input, + const base::string16& keyword) { + // It is important to this method that we determine if the user entered + // keyword mode intentionally, as we use this routine to e.g. filter + // all but keyword results. Currently we assume that the user entered + // keyword mode intentionally with all entry methods except with a + // space. However, if the user has typed a char past the space, we + // again assume keyword mode. + return OmniboxFieldTrial::IsExperimentalKeywordModeEnabled() && + input.prefer_keyword() && + base::StartsWith(input.text(), keyword, + base::CompareCase::SENSITIVE) && + ((input.keyword_mode_entry_method() != + metrics::OmniboxEventProto::SPACE_AT_END && + input.keyword_mode_entry_method() != + metrics::OmniboxEventProto::SPACE_IN_MIDDLE) || + input.text().size() > keyword.size() + 1); +}
diff --git a/components/omnibox/browser/autocomplete_provider.h b/components/omnibox/browser/autocomplete_provider.h index ee5d54a..ed0aa38 100644 --- a/components/omnibox/browser/autocomplete_provider.h +++ b/components/omnibox/browser/autocomplete_provider.h
@@ -279,6 +279,13 @@ // culling. static const size_t kMaxMatches; + // Used to determine if we're in keyword mode, if experimental keyword + // mode is enabled, and if we're confident that the user is intentionally + // (not accidentally) in keyword mode. Combined, this method returns + // whether the caller should perform steps that are only valid in this state. + static bool InExplicitExperimentalKeywordMode(const AutocompleteInput& input, + const base::string16& keyword); + protected: friend class base::RefCountedThreadSafe<AutocompleteProvider>; FRIEND_TEST_ALL_PREFIXES(BookmarkProviderTest, InlineAutocompletion);
diff --git a/components/omnibox/browser/builtin_provider.cc b/components/omnibox/browser/builtin_provider.cc index 6a35f7b..db7b32a 100644 --- a/components/omnibox/browser/builtin_provider.cc +++ b/components/omnibox/browser/builtin_provider.cc
@@ -12,6 +12,7 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "components/omnibox/browser/autocomplete_input.h" +#include "components/omnibox/browser/autocomplete_match_classification.h" #include "components/omnibox/browser/autocomplete_provider_client.h" #include "components/omnibox/browser/history_provider.h" #include "components/url_formatter/url_fixer.h" @@ -49,18 +50,20 @@ base::CompareCase::INSENSITIVE_ASCII); if (starting_about || base::StartsWith(kAbout, text, base::CompareCase::INSENSITIVE_ASCII)) { - ACMatchClassifications styles; // Highlight the input portion matching |embedderAbout|; or if the user has // input "about:" (with optional slashes), highlight the whole // |embedderAbout|. - bool highlight = starting_about || text.length() > kAboutSchemeLength; - styles.push_back(ACMatchClassification(0, highlight ? kMatch : kUrl)); - size_t offset = starting_about ? text.length() : embedderAbout.length(); - if (highlight) - styles.push_back(ACMatchClassification(offset, kUrl)); + TermMatches style_matches; + if (starting_about) + style_matches.emplace_back(0, 0, text.length()); + else if (text.length() > kAboutSchemeLength) + style_matches.emplace_back(0, 0, embedderAbout.length()); + ACMatchClassifications styles = + ClassifyTermMatches(style_matches, std::string::npos, kMatch, kUrl); // Include some common builtin URLs as the user types the scheme. for (base::string16 url : client_->GetBuiltinsToProvideAsUserTypes()) AddMatch(url, base::string16(), styles); + } else { // Match input about: or |embedderAbout| URL input against builtin URLs. GURL url = url_formatter::FixupURL(base::UTF16ToUTF8(text), std::string()); @@ -80,13 +83,11 @@ base::StartsWith(blank_host, host, base::CompareCase::INSENSITIVE_ASCII) && (url.path().length() <= 1) && !text_ends_with_slash) { - ACMatchClassifications styles; - styles.push_back(ACMatchClassification(0, kMatch)); base::string16 match = base::ASCIIToUTF16(url::kAboutBlankURL); - // Measure the length of the matching host after the "about:" scheme. const size_t corrected_length = kAboutSchemeLength + 1 + host.length(); - if (blank_host.length() > host.length()) - styles.push_back(ACMatchClassification(corrected_length, kUrl)); + TermMatches style_matches = {{0, 0, corrected_length}}; + ACMatchClassifications styles = + ClassifyTermMatches(style_matches, match.length(), kMatch, kUrl); AddMatch(match, match.substr(corrected_length), styles); } @@ -98,12 +99,10 @@ (i != builtins_.end()) && (matches_.size() < kMaxMatches); ++i) { if (base::StartsWith(*i, host_and_path, base::CompareCase::INSENSITIVE_ASCII)) { - ACMatchClassifications styles; - // Highlight |embedderAbout|, even for input "about:foo". - styles.push_back(ACMatchClassification(0, kMatch)); base::string16 match_string = embedderAbout + *i; - if (match_string.length() > match_length) - styles.push_back(ACMatchClassification(match_length, kUrl)); + TermMatches style_matches = {{0, 0, match_length}}; + ACMatchClassifications styles = ClassifyTermMatches( + style_matches, match_string.length(), kMatch, kUrl); // FixupURL() may have dropped a trailing slash on the user's input. // Ensure that in that case, we don't inline autocomplete unless the // autocompletion restores the slash. This prevents us from e.g.
diff --git a/components/omnibox/browser/search_provider.cc b/components/omnibox/browser/search_provider.cc index 1259510a..1f2a805 100644 --- a/components/omnibox/browser/search_provider.cc +++ b/components/omnibox/browser/search_provider.cc
@@ -1366,17 +1366,12 @@ bool SearchProvider::ShouldCurbDefaultSuggestions() const { // Only curb if the global experimental keyword feature is enabled, we're - // in keyword mode and the user selected the mode explicitly. For now, we - // consider entering keyword mode with spaces to be unintentional and all - // other methods as intentional. In this experimental mode, we don't want - // non-keyword suggestions if we're not confident that the user entered - // keyword mode explicitly. - return OmniboxFieldTrial::IsExperimentalKeywordModeEnabled() && - keyword_input_.prefer_keyword() && - keyword_input_.keyword_mode_entry_method() != - OmniboxEventProto::SPACE_AT_END && - keyword_input_.keyword_mode_entry_method() != - OmniboxEventProto::SPACE_IN_MIDDLE; + // in keyword mode and we believe the user selected the mode explicitly. + if (providers_.has_keyword_provider()) + return InExplicitExperimentalKeywordMode(input_, + providers_.keyword_provider()); + else + return false; } int SearchProvider::CalculateRelevanceForVerbatim() const {
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index fb70e47..0d23ec6 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -2006,7 +2006,7 @@ 'id': 525, 'caption': '''Restrict PIN printing mode''', 'tags': [], - 'desc': '''Restricts PIN printing mode. Unset policy is treated as no restriction. If the mode is unavailable this policy is ignored.''', + 'desc': '''Restricts PIN printing mode. Unset policy is treated as no restriction. If the mode is unavailable this policy is ignored. Note that PIN printing feature is enabled only for printers that use one of IPPS, USB or IPP-over-USB protocols ''', }, { 'name': 'PrintingAllowedPageSizes',
diff --git a/components/printing/browser/printer_capabilities.cc b/components/printing/browser/printer_capabilities.cc index 4f79764c..d3f1706f8 100644 --- a/components/printing/browser/printer_capabilities.cc +++ b/components/printing/browser/printer_capabilities.cc
@@ -58,6 +58,7 @@ base::Value GetPrinterCapabilitiesOnBlockingPoolThread( const std::string& device_name, const PrinterSemanticCapsAndDefaults::Papers& additional_papers, + bool has_secure_protocol, scoped_refptr<PrintBackend> print_backend) { base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, base::BlockingType::MAY_BLOCK); @@ -86,6 +87,11 @@ #endif info.papers.insert(info.papers.end(), additional_papers.begin(), additional_papers.end()); +#if defined(CHROMEOS) + if (!has_secure_protocol) + info.pin_supported = false; +#endif // defined(CHROMEOS) + return cloud_print::PrinterSemanticCapsAndDefaultsToCdd(info); } @@ -136,6 +142,7 @@ const std::string& device_name, const PrinterBasicInfo& basic_info, const PrinterSemanticCapsAndDefaults::Papers& additional_papers, + bool has_secure_protocol, scoped_refptr<PrintBackend> print_backend) { SCOPED_UMA_HISTOGRAM_TIMER("Printing.PrinterCapabilities"); base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, @@ -159,8 +166,9 @@ base::Value printer_info_capabilities(base::Value::Type::DICTIONARY); printer_info_capabilities.SetKey(kPrinter, std::move(printer_info)); printer_info_capabilities.SetKey( - kSettingCapabilities, GetPrinterCapabilitiesOnBlockingPoolThread( - device_name, additional_papers, print_backend)); + kSettingCapabilities, + GetPrinterCapabilitiesOnBlockingPoolThread( + device_name, additional_papers, has_secure_protocol, print_backend)); return printer_info_capabilities; }
diff --git a/components/printing/browser/printer_capabilities.h b/components/printing/browser/printer_capabilities.h index 698af12..d64566fa 100644 --- a/components/printing/browser/printer_capabilities.h +++ b/components/printing/browser/printer_capabilities.h
@@ -29,12 +29,13 @@ // for passage to the WebUI. The settings are obtained using |print_backend| if // it is provided. If |print_backend| is null, uses a new PrintBackend instance // with default settings. -// Data from |basic_info| and |additional_papers| are incorporated into the -// returned dictionary. +// Data from |basic_info|, |additional_papers| and |has_secure_protocol| are +// incorporated into the returned dictionary. base::Value GetSettingsOnBlockingPool( const std::string& device_name, const PrinterBasicInfo& basic_info, const PrinterSemanticCapsAndDefaults::Papers& additional_papers, + bool has_secure_protocol, scoped_refptr<PrintBackend> print_backend); } // namespace printing
diff --git a/components/printing/browser/printer_capabilities_unittest.cc b/components/printing/browser/printer_capabilities_unittest.cc index ec5b23a..446f8d5 100644 --- a/components/printing/browser/printer_capabilities_unittest.cc +++ b/components/printing/browser/printer_capabilities_unittest.cc
@@ -52,8 +52,9 @@ PrinterBasicInfo basic_info; PrinterSemanticCapsAndDefaults::Papers no_additional_papers; - base::Value settings_dictionary = GetSettingsOnBlockingPool( - printer_name, basic_info, no_additional_papers, nullptr); + base::Value settings_dictionary = + GetSettingsOnBlockingPool(printer_name, basic_info, no_additional_papers, + /* has_secure_protocol */ false, nullptr); ASSERT_FALSE(settings_dictionary.DictEmpty()); } @@ -69,7 +70,8 @@ print_backend()->AddValidPrinter(printer_name, std::move(caps)); base::Value settings_dictionary = GetSettingsOnBlockingPool( - printer_name, basic_info, no_additional_papers, print_backend()); + printer_name, basic_info, no_additional_papers, + /* has_secure_protocol */ false, print_backend()); // Verify settings were created. ASSERT_FALSE(settings_dictionary.DictEmpty()); @@ -98,7 +100,8 @@ print_backend()->AddValidPrinter(printer_name, nullptr); base::Value settings_dictionary = GetSettingsOnBlockingPool( - printer_name, basic_info, no_additional_papers, print_backend()); + printer_name, basic_info, no_additional_papers, + /* has_secure_protocol */ false, print_backend()); // Verify settings were created. ASSERT_FALSE(settings_dictionary.DictEmpty()); @@ -125,7 +128,8 @@ additional_papers.push_back({"bar", "vendor", {600, 600}}); base::Value settings_dictionary = GetSettingsOnBlockingPool( - printer_name, basic_info, additional_papers, print_backend()); + printer_name, basic_info, additional_papers, + /* has_secure_protocol */ false, print_backend()); // Verify settings were created. ASSERT_FALSE(settings_dictionary.DictEmpty()); @@ -182,4 +186,39 @@ EXPECT_EQ(600, height->GetInt()); } +#if defined(CHROMEOS) +TEST_F(PrinterCapabilitiesTest, HasNotSecureProtocol) { + std::string printer_name = "test_printer"; + PrinterBasicInfo basic_info; + PrinterSemanticCapsAndDefaults::Papers no_additional_papers; + bool has_secure_protocol = false; + + // Set a capability and add a valid printer. + auto caps = std::make_unique<PrinterSemanticCapsAndDefaults>(); + caps->pin_supported = true; + print_backend()->AddValidPrinter(printer_name, std::move(caps)); + + base::Value settings_dictionary = + GetSettingsOnBlockingPool(printer_name, basic_info, no_additional_papers, + has_secure_protocol, print_backend()); + + // Verify settings were created. + ASSERT_FALSE(settings_dictionary.DictEmpty()); + + // Verify there is a CDD with a printer entry. + const Value* cdd = settings_dictionary.FindKeyOfType(kSettingCapabilities, + Value::Type::DICTIONARY); + ASSERT_TRUE(cdd); + const Value* printer = cdd->FindKeyOfType(kPrinter, Value::Type::DICTIONARY); + ASSERT_TRUE(printer); + + // Verify that pin is not supported. + const Value* pin = printer->FindKeyOfType("pin", Value::Type::DICTIONARY); + ASSERT_TRUE(pin); + base::Optional<bool> pin_supported = pin->FindBoolKey("supported"); + ASSERT_TRUE(pin_supported.has_value()); + ASSERT_FALSE(pin_supported.value()); +} +#endif // defined(CHROMEOS) + } // namespace printing
diff --git a/components/services/heap_profiling/BUILD.gn b/components/services/heap_profiling/BUILD.gn index a319417..1856fba 100644 --- a/components/services/heap_profiling/BUILD.gn +++ b/components/services/heap_profiling/BUILD.gn
@@ -2,15 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//testing/libfuzzer/fuzzer_test.gni") - static_library("heap_profiling") { sources = [ "address.h", "allocation_event.cc", "allocation_event.h", - "allocation_tracker.cc", - "allocation_tracker.h", "backtrace.cc", "backtrace.h", "backtrace_storage.cc", @@ -21,29 +17,13 @@ "heap_profiling_service.h", "json_exporter.cc", "json_exporter.h", - "receiver.h", - "receiver_pipe.cc", - "receiver_pipe.h", - "receiver_pipe_win.cc", - "receiver_pipe_win.h", - "stream_parser.cc", - "stream_parser.h", - "stream_receiver.h", ] deps = [ "//base", "//components/services/heap_profiling/public/cpp", "//services/resource_coordinator/public/cpp:resource_coordinator_cpp", - "//third_party/zlib", ] - - if (is_posix) { - sources += [ - "receiver_pipe_posix.cc", - "receiver_pipe_posix.h", - ] - } } source_set("unit_tests") { @@ -51,7 +31,6 @@ sources = [ "backtrace_storage_unittest.cc", "json_exporter_unittest.cc", - "stream_parser_unittest.cc", ] deps = [ ":heap_profiling", @@ -60,15 +39,3 @@ "//testing/gtest", ] } - -fuzzer_test("profiling_fuzzer") { - sources = [ - "stream_fuzzer.cc", - ] - deps = [ - ":heap_profiling", - "//base", - ] - libfuzzer_options = [ "max_len = 64000" ] - dict = "stream_fuzzer.dict" -}
diff --git a/components/services/heap_profiling/DEPS b/components/services/heap_profiling/DEPS index dc1e98b5..180644f4 100644 --- a/components/services/heap_profiling/DEPS +++ b/components/services/heap_profiling/DEPS
@@ -2,5 +2,4 @@ "+components/services/heap_profiling/public", "+services/resource_coordinator/public", "+services/service_manager", - "+third_party/zlib/zlib.h", ]
diff --git a/components/services/heap_profiling/allocation_event.h b/components/services/heap_profiling/allocation_event.h index 3d3726a6..bf5c17f 100644 --- a/components/services/heap_profiling/allocation_event.h +++ b/components/services/heap_profiling/allocation_event.h
@@ -11,10 +11,12 @@ #include "components/services/heap_profiling/address.h" #include "components/services/heap_profiling/backtrace_storage.h" -#include "components/services/heap_profiling/public/cpp/stream.h" +#include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h" namespace heap_profiling { +using mojom::AllocatorType; + // This class is copyable and assignable. // // AllocationEvents can be uniquely identified by their address. Caveat: This is
diff --git a/components/services/heap_profiling/allocation_tracker.cc b/components/services/heap_profiling/allocation_tracker.cc deleted file mode 100644 index 01fe57c..0000000 --- a/components/services/heap_profiling/allocation_tracker.cc +++ /dev/null
@@ -1,123 +0,0 @@ -// 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. - -#include "components/services/heap_profiling/allocation_tracker.h" - -#include "base/bind.h" -#include "base/callback.h" -#include "base/json/string_escape.h" -#include "base/threading/thread_task_runner_handle.h" -#include "components/services/heap_profiling/backtrace_storage.h" - -namespace heap_profiling { - -AllocationTracker::AllocationTracker(CompleteCallback complete_cb, - BacktraceStorage* backtrace_storage) - : complete_callback_(std::move(complete_cb)), - backtrace_storage_(backtrace_storage) {} - -AllocationTracker::~AllocationTracker() { - for (auto& pair : registered_snapshot_callbacks_) { - RunnerSnapshotCallbackPair& rsc_pair = pair.second; - rsc_pair.first->PostTask( - FROM_HERE, - base::BindOnce(std::move(rsc_pair.second), false, AllocationCountMap(), - ContextMap(), AddressToStringMap())); - } - - std::vector<const Backtrace*> to_free; - to_free.reserve(live_allocs_.size()); - for (const auto& cur : live_allocs_) - to_free.push_back(cur.backtrace()); - backtrace_storage_->Free(to_free); -} - -void AllocationTracker::OnHeader(const StreamHeader& header) {} - -void AllocationTracker::OnAlloc(const AllocPacket& alloc_packet, - std::vector<Address>&& bt, - std::string&& context) { - // Compute the context ID for this allocation, 0 means no context. - int context_id = 0; - if (!context.empty()) { - // Escape the strings before saving them, to simplify exporting a heap dump. - std::string escaped_context; - base::EscapeJSONString(context, false /* put_in_quotes */, - &escaped_context); - - auto inserted_record = - context_.emplace(std::piecewise_construct, - std::forward_as_tuple(std::move(escaped_context)), - std::forward_as_tuple(next_context_id_)); - context_id = inserted_record.first->second; - if (inserted_record.second) - next_context_id_++; - } - - const Backtrace* backtrace = backtrace_storage_->Insert(std::move(bt)); - live_allocs_.emplace(alloc_packet.allocator, Address(alloc_packet.address), - alloc_packet.size, backtrace, context_id); -} - -void AllocationTracker::OnFree(const FreePacket& free_packet) { - AllocationEvent find_me(Address(free_packet.address)); - auto found = live_allocs_.find(find_me); - if (found != live_allocs_.end()) { - backtrace_storage_->Free(found->backtrace()); - live_allocs_.erase(found); - } -} - -void AllocationTracker::OnBarrier(const BarrierPacket& barrier_packet) { - RunnerSnapshotCallbackPair pair; - { - base::AutoLock lock(snapshot_lock_); - auto found = registered_snapshot_callbacks_.find(barrier_packet.barrier_id); - if (found == registered_snapshot_callbacks_.end()) { - DLOG(WARNING) << "Unexpected barrier"; - return; - } - pair = std::move(found->second); - registered_snapshot_callbacks_.erase(found); - } - - // Execute the callback outside of the lock. The arguments here must be - // copied. - pair.first->PostTask( - FROM_HERE, - base::BindOnce( - [](SnapshotCallback cb, AllocationCountMap counts, ContextMap context, - AddressToStringMap mapped_strings) { - std::move(cb).Run(true, std::move(counts), std::move(context), - mapped_strings); - }, - std::move(pair.second), AllocationEventSetToCountMap(live_allocs_), - context_, mapped_strings_)); -} - -void AllocationTracker::OnStringMapping( - const StringMappingPacket& string_mapping_packet, - const std::string& str) { - std::string dest; - - // Escape the strings before saving them, to simplify exporting a heap dump. - base::EscapeJSONString(str, false /* put_in_quotes */, &dest); - mapped_strings_[string_mapping_packet.address] = std::move(dest); -} - -void AllocationTracker::OnComplete() { - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, - std::move(complete_callback_)); -} - -void AllocationTracker::SnapshotOnBarrier( - uint32_t barrier_id, - scoped_refptr<base::SequencedTaskRunner> callback_runner, - SnapshotCallback callback) { - base::AutoLock lock(snapshot_lock_); - registered_snapshot_callbacks_[barrier_id] = - std::make_pair(std::move(callback_runner), std::move(callback)); -} - -} // namespace heap_profiling
diff --git a/components/services/heap_profiling/allocation_tracker.h b/components/services/heap_profiling/allocation_tracker.h deleted file mode 100644 index a479dbec..0000000 --- a/components/services/heap_profiling/allocation_tracker.h +++ /dev/null
@@ -1,98 +0,0 @@ -// 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. - -#ifndef COMPONENTS_SERVICES_HEAP_PROFILING_ALLOCATION_TRACKER_H_ -#define COMPONENTS_SERVICES_HEAP_PROFILING_ALLOCATION_TRACKER_H_ - -#include <map> -#include <unordered_map> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/sequenced_task_runner.h" -#include "base/synchronization/lock.h" -#include "components/services/heap_profiling/allocation_event.h" -#include "components/services/heap_profiling/backtrace_storage.h" -#include "components/services/heap_profiling/receiver.h" - -namespace heap_profiling { - -// Tracks live allocations in one process. This is an analogue to memory-infra -// allocation register and needs to be merged/deduped. -// -// This class is not threadsafe except as noted. -class AllocationTracker : public Receiver { - public: - using CompleteCallback = base::OnceClosure; - using ContextMap = std::map<std::string, int>; - using AddressToStringMap = std::unordered_map<uint64_t, std::string>; - - // Callback for taking an asynchronous snapshot. The first parameter is a - // success parameter. This class will always set it to true, but this is - // useful for calling code that must handle failure. - using SnapshotCallback = base::OnceCallback< - void(bool, AllocationCountMap, ContextMap, AddressToStringMap)>; - - AllocationTracker(CompleteCallback complete_cb, - BacktraceStorage* backtrace_storage); - ~AllocationTracker() override; - - void OnHeader(const StreamHeader& header) override; - void OnAlloc(const AllocPacket& alloc_packet, - std::vector<Address>&& bt, - std::string&& context) override; - void OnFree(const FreePacket& free_packet) override; - void OnBarrier(const BarrierPacket& barrier_packet) override; - void OnStringMapping(const StringMappingPacket& string_mapping_packet, - const std::string& str) override; - void OnComplete() override; - - // Registers the given snapshot closure to be executed when the given barrier - // ID is received from the process. This will only trigger for a barrier - // received after registration. - // - // This function is threadsafe. The callback will be executed on the given - // task runner. - void SnapshotOnBarrier( - uint32_t barrier_id, - scoped_refptr<base::SequencedTaskRunner> callback_runner, - SnapshotCallback callback); - - private: - CompleteCallback complete_callback_; - - // The snapshot callbacks are threadsafe and are protected by the lock. - base::Lock snapshot_lock_; - using RunnerSnapshotCallbackPair = - std::pair<scoped_refptr<base::SequencedTaskRunner>, SnapshotCallback>; - std::map<uint32_t, RunnerSnapshotCallbackPair> registered_snapshot_callbacks_; - - BacktraceStorage* backtrace_storage_; - - AddressToStringMap mapped_strings_; - - // Need to track all live objects. Since the free information doesn't have - // the metadata, we can't keep a map of counts indexed by just the metadata - // (which is all the trace JSON needs), but need to keep an index by address. - // - // This could be a two-level index, where one set of metadata is kept and - // addresses index into that. But a full copy of the metadata is about the - // same size as the internal map node required for this second index, with - // additional complexity. - AllocationEventSet live_allocs_; - - // The context strings are atoms. Since there are O(100's) of these, we do - // not bother to uniquify across all processes. This map contains the unique - // context strings for the current process, mapped to the unique ID for that - // context. This unique ID is stored in the allocation. This is optimized for - // insertion. When querying, a reverse index will need to be generated - ContextMap context_; - int next_context_id_ = 1; // 0 means no context. - - DISALLOW_COPY_AND_ASSIGN(AllocationTracker); -}; - -} // namespace heap_profiling - -#endif // COMPONENTS_SERVICES_HEAP_PROFILING_ALLOCATION_TRACKER_H_
diff --git a/components/services/heap_profiling/connection_manager.cc b/components/services/heap_profiling/connection_manager.cc index 0fbb4549..59aea38 100644 --- a/components/services/heap_profiling/connection_manager.cc +++ b/components/services/heap_profiling/connection_manager.cc
@@ -6,24 +6,10 @@ #include "base/bind.h" #include "base/json/string_escape.h" -#include "base/message_loop/message_loop.h" -#include "base/message_loop/message_loop_current.h" #include "base/metrics/histogram_macros.h" -#include "base/strings/stringprintf.h" #include "base/threading/sequenced_task_runner_handle.h" -#include "base/threading/thread.h" -#include "components/services/heap_profiling/allocation_tracker.h" #include "components/services/heap_profiling/json_exporter.h" #include "components/services/heap_profiling/public/cpp/client.h" -#include "components/services/heap_profiling/receiver_pipe.h" -#include "components/services/heap_profiling/stream_parser.h" -#include "mojo/public/cpp/system/buffer.h" -#include "mojo/public/cpp/system/platform_handle.h" -#include "third_party/zlib/zlib.h" - -#if defined(OS_WIN) -#include <io.h> -#endif namespace heap_profiling { @@ -68,29 +54,16 @@ }; struct ConnectionManager::Connection { - Connection(AllocationTracker::CompleteCallback complete_cb, - BacktraceStorage* backtrace_storage, - base::ProcessId pid, + Connection(CompleteCallback complete_cb, mojom::ProfilingClientPtr client, - scoped_refptr<ReceiverPipe> p, mojom::ProcessType process_type, uint32_t sampling_rate, - mojom::StackMode stack_mode, - bool stream_samples) - : thread(base::StringPrintf("Sender %lld thread", - static_cast<long long>(pid))), - client(std::move(client)), - pipe(p), + mojom::StackMode stack_mode) + : client(std::move(client)), process_type(process_type), stack_mode(stack_mode), - stream_samples(stream_samples), - tracker(std::move(complete_cb), backtrace_storage), - sampling_rate(sampling_rate) {} - - ~Connection() { - // The parser may outlive this class because it's refcounted, make sure no - // callbacks are issued. - parser->DisconnectReceivers(); + sampling_rate(sampling_rate) { + this->client.set_connection_error_handler(std::move(complete_cb)); } bool HeapDumpNeedsVmRegions() { @@ -99,18 +72,9 @@ stack_mode == mojom::StackMode::MIXED; } - base::Thread thread; - mojom::ProfilingClientPtr client; - scoped_refptr<ReceiverPipe> pipe; - scoped_refptr<StreamParser> parser; mojom::ProcessType process_type; mojom::StackMode stack_mode; - bool stream_samples; - - // Danger: This lives on the |thread| member above. The connection manager - // lives on the I/O thread, so accesses to the variable must be synchronized. - AllocationTracker tracker; // When sampling is enabled, allocations are recorded with probability (size / // sampling_rate) when size < sampling_rate. When size >= sampling_rate, the @@ -121,8 +85,7 @@ uint32_t sampling_rate = 1; }; -ConnectionManager::ConnectionManager() - : blocking_thread_("Blocking thread"), weak_factory_(this) { +ConnectionManager::ConnectionManager() : blocking_thread_("Blocking thread") { blocking_thread_.Start(); metrics_timer_.Start( FROM_HERE, base::TimeDelta::FromHours(24), @@ -132,7 +95,6 @@ void ConnectionManager::OnNewConnection(base::ProcessId pid, mojom::ProfilingClientPtr client, - mojo::ScopedHandle receiver_pipe_end, mojom::ProcessType process_type, mojom::ProfilingParamsPtr params) { base::AutoLock lock(connections_lock_); @@ -151,35 +113,15 @@ // when the user is attempting to manually start profiling for processes, so // we ignore this edge case. - scoped_refptr<ReceiverPipe> new_pipe = base::MakeRefCounted<ReceiverPipe>( - mojo::UnwrapPlatformHandle(std::move(receiver_pipe_end))); - - // The allocation tracker will call this on a background thread, so thunk - // back to the current thread with weak pointers. - AllocationTracker::CompleteCallback complete_cb = base::BindOnce( - &ConnectionManager::OnConnectionCompleteThunk, - base::ThreadTaskRunnerHandle::Get(), weak_factory_.GetWeakPtr(), pid); + CompleteCallback complete_cb = + base::BindOnce(&ConnectionManager::OnConnectionComplete, + weak_factory_.GetWeakPtr(), pid); auto connection = std::make_unique<Connection>( - std::move(complete_cb), &backtrace_storage_, pid, std::move(client), - new_pipe, process_type, params->sampling_rate, params->stack_mode, - params->stream_samples); - - base::Thread::Options options; - options.message_loop_type = base::MessageLoop::TYPE_IO; - connection->thread.StartWithOptions(options); - - connection->parser = base::MakeRefCounted<StreamParser>(&connection->tracker); - new_pipe->SetReceiver(connection->thread.task_runner(), connection->parser); - - connection->thread.task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&ReceiverPipe::StartReadingOnIOThread, new_pipe)); - - // Request the client start sending us data. + std::move(complete_cb), std::move(client), process_type, + params->sampling_rate, params->stack_mode); connection->client->StartProfiling(std::move(params)); - - connections_[pid] = std::move(connection); // Transfers ownership. + connections_[pid] = std::move(connection); } std::vector<base::ProcessId> ConnectionManager::GetConnectionPids() { @@ -219,16 +161,6 @@ } } -// static -void ConnectionManager::OnConnectionCompleteThunk( - scoped_refptr<base::SequencedTaskRunner> task_runner, - base::WeakPtr<ConnectionManager> connection_manager, - base::ProcessId pid) { - task_runner->PostTask(FROM_HERE, - base::BindOnce(&ConnectionManager::OnConnectionComplete, - connection_manager, pid)); -} - void ConnectionManager::DumpProcessesForTracing( bool strip_path_from_mapped_files, DumpProcessesForTracingCallback callback, @@ -253,25 +185,10 @@ for (auto& it : connections_) { base::ProcessId pid = it.first; Connection* connection = it.second.get(); - if (!connection->stream_samples) { - connection->client->RetrieveHeapProfile(base::BindOnce( - &ConnectionManager::HeapProfileRetrieved, weak_factory_.GetWeakPtr(), - tracking, pid, connection->process_type, strip_path_from_mapped_files, - connection->sampling_rate)); - continue; - } - int barrier_id = next_barrier_id_++; - - // Register for callback before requesting the dump so we don't race for the - // signal. The callback will be issued on the allocation tracker thread so - // need to thunk back to the I/O thread. - connection->tracker.SnapshotOnBarrier( - barrier_id, base::ThreadTaskRunnerHandle::Get(), - base::BindOnce(&ConnectionManager::DoDumpOneProcessForTracing, - weak_factory_.GetWeakPtr(), tracking, pid, - connection->process_type, strip_path_from_mapped_files, - connection->sampling_rate)); - connection->client->FlushMemlogPipe(barrier_id); + connection->client->RetrieveHeapProfile(base::BindOnce( + &ConnectionManager::HeapProfileRetrieved, weak_factory_.GetWeakPtr(), + tracking, pid, connection->process_type, strip_path_from_mapped_files, + connection->sampling_rate)); } } @@ -283,8 +200,8 @@ uint32_t sampling_rate, mojom::HeapProfilePtr profile) { AllocationCountMap counts; - AllocationTracker::ContextMap context_map; - AllocationTracker::AddressToStringMap string_map; + ContextMap context_map; + AddressToStringMap string_map; BacktraceStorage backtrace_storage; BacktraceStorage::Lock backtrace_storage_lock(&backtrace_storage); @@ -309,13 +226,8 @@ } const Backtrace* backtrace = backtrace_storage.Insert( std::vector<Address>(sample->stack.begin(), sample->stack.end())); - AllocatorType allocator = static_cast<AllocatorType>(sample->allocator); - if (allocator >= AllocatorType::kCount) { - success = false; - break; - } - AllocationEvent alloc(allocator, Address(0), sample->size, backtrace, - context_id); + AllocationEvent alloc(sample->allocator, Address(0), sample->size, + backtrace, context_id); ++counts[alloc]; } @@ -342,8 +254,8 @@ uint32_t sampling_rate, bool success, AllocationCountMap counts, - AllocationTracker::ContextMap context, - AllocationTracker::AddressToStringMap mapped_strings) { + ContextMap context, + AddressToStringMap mapped_strings) { // All code paths through here must issue the callback when waiting_responses // is 0 or the browser will wait forever for the dump. DCHECK(tracking->waiting_responses > 0);
diff --git a/components/services/heap_profiling/connection_manager.h b/components/services/heap_profiling/connection_manager.h index 580ccc750..c4baebe8 100644 --- a/components/services/heap_profiling/connection_manager.h +++ b/components/services/heap_profiling/connection_manager.h
@@ -5,31 +5,24 @@ #ifndef COMPONENTS_SERVICES_HEAP_PROFILING_CONNECTION_MANAGER_H_ #define COMPONENTS_SERVICES_HEAP_PROFILING_CONNECTION_MANAGER_H_ +#include <map> #include <string> +#include <unordered_map> #include <vector> #include "base/containers/flat_map.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "base/process/process_handle.h" #include "base/synchronization/lock.h" #include "base/threading/thread.h" #include "base/timer/timer.h" -#include "base/values.h" #include "build/build_config.h" #include "components/services/heap_profiling/allocation_event.h" -#include "components/services/heap_profiling/allocation_tracker.h" #include "components/services/heap_profiling/backtrace_storage.h" #include "components/services/heap_profiling/public/mojom/heap_profiling_service.mojom.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h" -namespace base { - -class SequencedTaskRunner; - -} // namespace base - namespace heap_profiling { using VmRegions = @@ -44,6 +37,9 @@ // This object is constructed on the UI thread, but the rest of the usage // (including deletion) is on the IO thread. class ConnectionManager { + using AddressToStringMap = std::unordered_map<uint64_t, std::string>; + using CompleteCallback = base::OnceClosure; + using ContextMap = std::map<std::string, int>; using DumpProcessesForTracingCallback = memory_instrumentation::mojom:: HeapProfiler::DumpProcessesForTracingCallback; @@ -76,7 +72,6 @@ void OnNewConnection(base::ProcessId pid, mojom::ProfilingClientPtr client, - mojo::ScopedHandle receiver_pipe_end, mojom::ProcessType process_type, mojom::ProfilingParamsPtr params); @@ -103,8 +98,8 @@ uint32_t sampling_rate, bool success, AllocationCountMap counts, - AllocationTracker::ContextMap context, - AllocationTracker::AddressToStringMap mapped_strings); + ContextMap context, + AddressToStringMap mapped_strings); // Notification that a connection is complete. Unlike OnNewConnection which // is signaled by the pipe server, this is signaled by the allocation tracker @@ -115,18 +110,8 @@ // Reports the ProcessTypes of the processes being profiled. void ReportMetrics(); - // These thunks post the request back to the given thread. - static void OnConnectionCompleteThunk( - scoped_refptr<base::SequencedTaskRunner> main_loop, - base::WeakPtr<ConnectionManager> connection_manager, - base::ProcessId process_id); - BacktraceStorage backtrace_storage_; - // Next ID to use for a barrier request. This is incremented for each use - // to ensure barrier IDs are unique. - uint32_t next_barrier_id_ = 1; - // The next ID to use when exporting a heap dump. size_t next_id_ = 1; @@ -144,7 +129,7 @@ base::Thread blocking_thread_; // Must be last. - base::WeakPtrFactory<ConnectionManager> weak_factory_; + base::WeakPtrFactory<ConnectionManager> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(ConnectionManager); };
diff --git a/components/services/heap_profiling/heap_profiling_service.cc b/components/services/heap_profiling/heap_profiling_service.cc index af70cfb..8d86ba7 100644 --- a/components/services/heap_profiling/heap_profiling_service.cc +++ b/components/services/heap_profiling/heap_profiling_service.cc
@@ -77,13 +77,11 @@ void HeapProfilingService::AddProfilingClient( base::ProcessId pid, mojom::ProfilingClientPtr client, - mojo::ScopedHandle pipe_receiver, mojom::ProcessType process_type, mojom::ProfilingParamsPtr params) { if (params->sampling_rate == 0) params->sampling_rate = 1; - connection_manager_.OnNewConnection(pid, std::move(client), - std::move(pipe_receiver), process_type, + connection_manager_.OnNewConnection(pid, std::move(client), process_type, std::move(params)); } @@ -94,26 +92,25 @@ void HeapProfilingService::DumpProcessesForTracing( bool strip_path_from_mapped_files, DumpProcessesForTracingCallback callback) { - if (!helper_) { - service_binding_.GetConnector()->BindInterface( - resource_coordinator::mojom::kServiceName, &helper_); - } - std::vector<base::ProcessId> pids = connection_manager_.GetConnectionPidsThatNeedVmRegions(); if (pids.empty()) { connection_manager_.DumpProcessesForTracing( strip_path_from_mapped_files, std::move(callback), VmRegions()); - } else { - // Need a memory map to make sense of the dump. The dump will be triggered - // in the memory map global dump callback. - helper_->GetVmRegionsForHeapProfiler( - pids, - base::BindOnce(&HeapProfilingService:: - OnGetVmRegionsCompleteForDumpProcessesForTracing, - weak_factory_.GetWeakPtr(), strip_path_from_mapped_files, - std::move(callback))); + return; } + + // Need a memory map to make sense of the dump. The dump will be triggered + // in the memory map global dump callback. + if (!helper_) { + service_binding_.GetConnector()->BindInterface( + resource_coordinator::mojom::kServiceName, &helper_); + } + helper_->GetVmRegionsForHeapProfiler( + pids, base::BindOnce(&HeapProfilingService:: + OnGetVmRegionsCompleteForDumpProcessesForTracing, + weak_factory_.GetWeakPtr(), + strip_path_from_mapped_files, std::move(callback))); } void HeapProfilingService::OnGetVmRegionsCompleteForDumpProcessesForTracing(
diff --git a/components/services/heap_profiling/heap_profiling_service.h b/components/services/heap_profiling/heap_profiling_service.h index 4d44db6..ea657c0 100644 --- a/components/services/heap_profiling/heap_profiling_service.h +++ b/components/services/heap_profiling/heap_profiling_service.h
@@ -46,7 +46,6 @@ // ProfilingService implementation. void AddProfilingClient(base::ProcessId pid, mojom::ProfilingClientPtr client, - mojo::ScopedHandle pipe_receiver, mojom::ProcessType process_type, mojom::ProfilingParamsPtr params) override; void GetProfiledPids(GetProfiledPidsCallback callback) override;
diff --git a/components/services/heap_profiling/json_exporter.cc b/components/services/heap_profiling/json_exporter.cc index 8d87039..e9565bb 100644 --- a/components/services/heap_profiling/json_exporter.cc +++ b/components/services/heap_profiling/json_exporter.cc
@@ -23,7 +23,7 @@ using StringTable = std::map<std::string, size_t>; constexpr uint32_t kAllocatorCount = - static_cast<uint32_t>(AllocatorType::kCount); + static_cast<uint32_t>(AllocatorType::kMaxValue) + 1; struct BacktraceNode { BacktraceNode(size_t string_id, size_t parent)
diff --git a/components/services/heap_profiling/json_exporter.h b/components/services/heap_profiling/json_exporter.h index 2357862d..9b3c58b2 100644 --- a/components/services/heap_profiling/json_exporter.h +++ b/components/services/heap_profiling/json_exporter.h
@@ -10,7 +10,6 @@ #include "base/values.h" #include "components/services/heap_profiling/allocation_event.h" -#include "components/services/heap_profiling/public/cpp/stream.h" #include "components/services/heap_profiling/public/mojom/heap_profiling_service.mojom.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
diff --git a/components/services/heap_profiling/public/cpp/BUILD.gn b/components/services/heap_profiling/public/cpp/BUILD.gn index 01439b40..cc786f4 100644 --- a/components/services/heap_profiling/public/cpp/BUILD.gn +++ b/components/services/heap_profiling/public/cpp/BUILD.gn
@@ -10,11 +10,8 @@ "controller.h", "sampling_profiler_wrapper.cc", "sampling_profiler_wrapper.h", - "sender_pipe.h", - "sender_pipe_win.cc", "settings.cc", "settings.h", - "stream.h", "switches.cc", "switches.h", ] @@ -30,16 +27,11 @@ "//services/service_manager/public/cpp", "//services/service_manager/sandbox", ] - - if (is_posix) { - sources += [ "sender_pipe_posix.cc" ] - } } source_set("unit_tests") { testonly = true sources = [ - "sender_pipe_unittest.cc", "switches_unittest.cc", ] deps = [
diff --git a/components/services/heap_profiling/public/cpp/client.cc b/components/services/heap_profiling/public/cpp/client.cc index 39cd6c1d..704f3733 100644 --- a/components/services/heap_profiling/public/cpp/client.cc +++ b/components/services/heap_profiling/public/cpp/client.cc
@@ -6,20 +6,12 @@ #include "base/allocator/allocator_interception_mac.h" #include "base/bind.h" -#include "base/command_line.h" -#include "base/files/platform_file.h" -#include "base/metrics/field_trial_params.h" #include "base/single_thread_task_runner.h" #include "base/task/post_task.h" #include "base/task/task_traits.h" #include "base/trace_event/malloc_dump_provider.h" #include "build/build_config.h" #include "components/services/heap_profiling/public/cpp/sampling_profiler_wrapper.h" -#include "components/services/heap_profiling/public/cpp/sender_pipe.h" -#include "components/services/heap_profiling/public/cpp/settings.h" -#include "components/services/heap_profiling/public/cpp/stream.h" -#include "mojo/public/cpp/system/platform_handle.h" -#include "services/service_manager/sandbox/switches.h" #if defined(OS_ANDROID) && BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && \ defined(OFFICIAL_BUILD) @@ -29,7 +21,6 @@ namespace heap_profiling { namespace { -const int kTimeoutDurationMs = 10000; #if defined(OS_ANDROID) && BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && \ defined(OFFICIAL_BUILD) @@ -46,25 +37,13 @@ } // namespace -Client::Client() - : started_profiling_(false), - sampling_profiler_(new SamplingProfilerWrapper()), - weak_factory_(this) {} +Client::Client() : sampling_profiler_(new SamplingProfilerWrapper()) {} Client::~Client() { if (!started_profiling_) return; - sampling_profiler_->StopProfiling(); - SamplingProfilerWrapper::FlushBuffersAndClosePipe(); - base::trace_event::MallocDumpProvider::GetInstance()->EnableMetrics(); - - // The allocator shim cannot be synchronously, consistently stopped. We leak - // the sender_pipe_, with the idea that very few future messages will - // be sent to it. This happens at shutdown, so resources will be reclaimed - // by the OS after the process is terminated. - sender_pipe_.release(); } void Client::BindToInterface(mojom::ProfilingClientRequest request) { @@ -72,29 +51,9 @@ } void Client::StartProfiling(mojom::ProfilingParamsPtr params) { - // Never allow profiling of the profiling process. That would cause deadlock. - std::string sandbox_type = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - service_manager::switches::kServiceSandboxType); - if (sandbox_type == service_manager::switches::kProfilingSandbox) - return; - if (started_profiling_) return; started_profiling_ = true; - - sender_pipe_.reset(new SenderPipe( - mojo::UnwrapPlatformHandle(std::move(params->sender_pipe)))); - - StreamHeader header; - header.signature = kStreamSignature; - SenderPipe::Result result = - sender_pipe_->Send(&header, sizeof(header), kTimeoutDurationMs); - if (result != SenderPipe::Result::kSuccess) { - sender_pipe_->Close(); - return; - } - base::trace_event::MallocDumpProvider::GetInstance()->DisableMetrics(); #if defined(OS_MACOSX) @@ -124,16 +83,12 @@ #endif } -void Client::FlushMemlogPipe(uint32_t barrier_id) { - SamplingProfilerWrapper::FlushPipe(barrier_id); -} - void Client::RetrieveHeapProfile(RetrieveHeapProfileCallback callback) { std::move(callback).Run(sampling_profiler_->RetrieveHeapProfile()); } void Client::StartProfilingInternal(mojom::ProfilingParamsPtr params) { - sampling_profiler_->StartProfiling(sender_pipe_.get(), std::move(params)); + sampling_profiler_->StartProfiling(std::move(params)); } } // namespace heap_profiling
diff --git a/components/services/heap_profiling/public/cpp/client.h b/components/services/heap_profiling/public/cpp/client.h index 23abac2..3254857 100644 --- a/components/services/heap_profiling/public/cpp/client.h +++ b/components/services/heap_profiling/public/cpp/client.h
@@ -8,12 +8,10 @@ #include "base/memory/weak_ptr.h" #include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/system/handle.h" namespace heap_profiling { class SamplingProfilerWrapper; -class SenderPipe; // The Client listens on the interface for a StartProfiling message. On // receiving the message, it begins profiling the current process. @@ -26,7 +24,6 @@ // mojom::ProfilingClient overrides: void StartProfiling(mojom::ProfilingParamsPtr params) override; - void FlushMemlogPipe(uint32_t barrier_id) override; void RetrieveHeapProfile(RetrieveHeapProfileCallback callback) override; void BindToInterface(mojom::ProfilingClientRequest request); @@ -42,12 +39,9 @@ // has a chance to figure out which one to keep. mojo::BindingSet<mojom::ProfilingClient> bindings_; - bool started_profiling_; - + bool started_profiling_{false}; std::unique_ptr<SamplingProfilerWrapper> sampling_profiler_; - std::unique_ptr<SenderPipe> sender_pipe_; - - base::WeakPtrFactory<Client> weak_factory_; + base::WeakPtrFactory<Client> weak_factory_{this}; }; } // namespace heap_profiling
diff --git a/components/services/heap_profiling/public/cpp/controller.cc b/components/services/heap_profiling/public/cpp/controller.cc index 72cda0fe..1b45cc92 100644 --- a/components/services/heap_profiling/public/cpp/controller.cc +++ b/components/services/heap_profiling/public/cpp/controller.cc
@@ -4,10 +4,8 @@ #include "components/services/heap_profiling/public/cpp/controller.h" -#include "components/services/heap_profiling/public/cpp/sender_pipe.h" #include "components/services/heap_profiling/public/cpp/settings.h" #include "components/services/heap_profiling/public/mojom/constants.mojom.h" -#include "mojo/public/cpp/system/platform_handle.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h" #include "services/resource_coordinator/public/mojom/service_constants.mojom.h" #include "services/service_manager/public/cpp/connector.h" @@ -16,12 +14,10 @@ Controller::Controller(std::unique_ptr<service_manager::Connector> connector, mojom::StackMode stack_mode, - bool stream_samples, uint32_t sampling_rate) : connector_(std::move(connector)), sampling_rate_(sampling_rate), stack_mode_(stack_mode), - stream_samples_(stream_samples), weak_factory_(this) { DCHECK_NE(sampling_rate, 0u); @@ -45,16 +41,11 @@ mojom::ProcessType process_type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - SenderPipe::PipePair pipes; - mojom::ProfilingParamsPtr params = mojom::ProfilingParams::New(); params->sampling_rate = sampling_rate_; - params->stream_samples = stream_samples_; - params->sender_pipe = mojo::WrapPlatformHandle(pipes.PassSender()); params->stack_mode = stack_mode_; - heap_profiling_service_->AddProfilingClient( - pid, std::move(client), mojo::WrapPlatformHandle(pipes.PassReceiver()), - process_type, std::move(params)); + heap_profiling_service_->AddProfilingClient(pid, std::move(client), + process_type, std::move(params)); } void Controller::GetProfiledPids(GetProfiledPidsCallback callback) {
diff --git a/components/services/heap_profiling/public/cpp/controller.h b/components/services/heap_profiling/public/cpp/controller.h index 6ea12588..4e9ba62 100644 --- a/components/services/heap_profiling/public/cpp/controller.h +++ b/components/services/heap_profiling/public/cpp/controller.h
@@ -42,7 +42,6 @@ // named |sampling_interval|. Controller(std::unique_ptr<service_manager::Connector> connector, mojom::StackMode stack_mode, - bool stream_samples, uint32_t sampling_rate); ~Controller(); @@ -71,7 +70,6 @@ // The same sampling rate and stack mode is used for each client. const uint32_t sampling_rate_ = 1; const mojom::StackMode stack_mode_; - const bool stream_samples_; SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory<Controller> weak_factory_;
diff --git a/components/services/heap_profiling/public/cpp/sampling_profiler_wrapper.cc b/components/services/heap_profiling/public/cpp/sampling_profiler_wrapper.cc index 01885d7a..3d7e99a3 100644 --- a/components/services/heap_profiling/public/cpp/sampling_profiler_wrapper.cc +++ b/components/services/heap_profiling/public/cpp/sampling_profiler_wrapper.cc
@@ -7,18 +7,12 @@ #include <unordered_set> #include <utility> -#include "base/atomicops.h" #include "base/debug/stack_trace.h" #include "base/lazy_instance.h" -#include "base/no_destructor.h" -#include "base/sampling_heap_profiler/poisson_allocation_sampler.h" #include "base/sampling_heap_profiler/sampling_heap_profiler.h" #include "base/synchronization/lock.h" -#include "base/threading/thread_local_storage.h" #include "base/trace_event/heap_profiler_event_filter.h" #include "base/trace_event/memory_dump_manager.h" -#include "components/services/heap_profiling/public/cpp/sender_pipe.h" -#include "components/services/heap_profiling/public/cpp/stream.h" using base::trace_event::AllocationContext; using base::trace_event::AllocationContextTracker; @@ -26,17 +20,6 @@ namespace heap_profiling { -// Allocation logging also requires use of base TLS, so we must also check that -// that is available. This means that allocations that occur after base TLS has -// been torn down will not be logged. -// TODO(alph): Get rid of the class. crbug.com/917476 -class ScopedAllowAlloc { - public: - static inline bool HasTLSBeenDestroyed() { - return UNLIKELY(base::ThreadLocalStorage::HasBeenDestroyed()); - } -}; - namespace { bool g_initialized_ = false; @@ -45,236 +28,13 @@ base::LazyInstance<scoped_refptr<base::TaskRunner>>::Leaky g_on_init_allocator_shim_task_runner_; -SenderPipe* g_sender_pipe = nullptr; - // In NATIVE stack mode, whether to insert stack names into the backtraces. bool g_include_thread_names = false; -// Prime since this is used like a hash table. Numbers of this magnitude seemed -// to provide sufficient parallelism to avoid lock overhead in ad-hoc testing. -constexpr int kNumSendBuffers = 17; - -// If writing to the SenderPipe ever takes longer than 10s, just give up. -constexpr int kTimeoutMs = 10000; - -// The allocator shim needs to retain some additional state for each thread. -struct ShimState { - // If we are using pseudo stacks, we need to inform the profiling service of - // the address to string mapping. To avoid a global lock, we keep a - // thread-local unordered_set of every address that has been sent from the - // thread in question. - std::unordered_set<const void*> sent_strings; -}; - -// Technically, this code could be called after Thread destruction and we would -// need to guard this with ThreadLocalStorage::HasBeenDestroyed(), but all calls -// to this are guarded behind ScopedAllowAlloc, which already makes the check. -base::ThreadLocalStorage::Slot& ShimStateTLS() { - static base::NoDestructor<base::ThreadLocalStorage::Slot> shim_state_tls( - [](void* shim_state) { delete static_cast<ShimState*>(shim_state); }); - return *shim_state_tls; -} - -// We don't need to worry about re-entrancy because PoissonAllocationSampler -// already guards against that. -ShimState* GetShimState() { - ShimState* state = static_cast<ShimState*>(ShimStateTLS().Get()); - if (!state) { - state = new ShimState(); - ShimStateTLS().Set(state); - } - return state; -} - -class SendBuffer { - public: - SendBuffer() : buffer_(new char[SenderPipe::kPipeSize]) {} - ~SendBuffer() { delete[] buffer_; } - - void Send(const void* data, size_t sz) { - base::AutoLock lock(lock_); - - if (used_ + sz > SenderPipe::kPipeSize) - SendCurrentBuffer(); - - memcpy(&buffer_[used_], data, sz); - used_ += sz; - } - - void Flush() { - base::AutoLock lock(lock_); - if (used_ > 0) - SendCurrentBuffer(); - } - - private: - void SendCurrentBuffer() { - SenderPipe::Result result = g_sender_pipe->Send(buffer_, used_, kTimeoutMs); - used_ = 0; - if (result == SenderPipe::Result::kError) { - SamplingProfilerWrapper::FlushBuffersAndClosePipe(); - } - if (result == SenderPipe::Result::kTimeout) { - SamplingProfilerWrapper::FlushBuffersAndClosePipe(); - // TODO(erikchen): Emit a histogram. https://crbug.com/777546. - } - } - - base::Lock lock_; - - char* buffer_; - size_t used_ = 0; - - DISALLOW_COPY_AND_ASSIGN(SendBuffer); -}; - -// It's safe to call Read() before Write(). Read() will either return nullptr or -// a valid SendBuffer. -class AtomicallyConsistentSendBufferArray { - public: - void Write(SendBuffer* buffer) { - base::subtle::Release_Store( - &send_buffers, reinterpret_cast<base::subtle::AtomicWord>(buffer)); - } - - SendBuffer* Read() { - return reinterpret_cast<SendBuffer*>( - base::subtle::Acquire_Load(&send_buffers)); - } - - private: - // This class is used as a static global. This will be linker-initialized to - // 0. - base::subtle::AtomicWord send_buffers; -}; - -// The API guarantees that Read() will either return a valid object or a -// nullptr. -AtomicallyConsistentSendBufferArray g_send_buffers; - -size_t HashAddress(const void* address) { - // The multiplicative hashing scheme from [Knuth 1998]. - // |a| is the first prime after 2^17. - const uintptr_t key = reinterpret_cast<uintptr_t>(address); - const uintptr_t a = 131101; - const uintptr_t shift = 15; - const uintptr_t h = (key * a) >> shift; - return h; -} - -// "address" is the address in question, which is used to select which send -// buffer to use. -void DoSend(const void* address, - const void* data, - size_t size, - SendBuffer* send_buffers) { - int bin_to_use = HashAddress(address) % kNumSendBuffers; - send_buffers[bin_to_use].Send(data, size); -} - -// Updates an existing in_memory buffer with frame data. If a frame contains a -// pointer to a cstring rather than an instruction pointer, and the profiling -// service has not yet been informed of that pointer -> cstring mapping, sends a -// StringMappingPacket. -class FrameSerializer { - public: - FrameSerializer(uint64_t* stack, - const void* address, - size_t initial_buffer_size, - SendBuffer* send_buffers) - : stack_(stack), - address_(address), - remaining_buffer_size_(initial_buffer_size), - send_buffers_(send_buffers) {} - - void AddAllFrames(const base::trace_event::Backtrace& backtrace) { - CHECK_LE(backtrace.frame_count, kMaxStackEntries); - size_t required_capacity = backtrace.frame_count * sizeof(uint64_t); - CHECK_LE(required_capacity, remaining_buffer_size_); - remaining_buffer_size_ -= required_capacity; - for (int i = base::checked_cast<int>(backtrace.frame_count) - 1; i >= 0; - --i) { - AddFrame(backtrace.frames[i]); - } - } - - void AddAllInstructionPointers(size_t frame_count, - const void* const* frames) { - CHECK_LE(frame_count, kMaxStackEntries); - size_t required_capacity = frame_count * sizeof(uint64_t); - CHECK_LE(required_capacity, remaining_buffer_size_); - remaining_buffer_size_ -= required_capacity; - // If there are too many frames, keep the ones furthest from main(). - for (size_t i = 0; i < frame_count; i++) - AddInstructionPointer(frames[i]); - } - - void AddCString(const char* c_string) { - // Using a TLS cache of sent_strings avoids lock contention on malloc, which - // would kill performance. - std::unordered_set<const void*>* sent_strings = - &GetShimState()->sent_strings; - - if (sent_strings->find(c_string) == sent_strings->end()) { - // No point in allowing arbitrarily long c-strings, which might cause pipe - // max length issues. Pick a reasonable length like 255. - static const size_t kMaxCStringLen = 255; - - // length does not include the null terminator. - size_t length = strnlen(c_string, kMaxCStringLen); - - char message[sizeof(StringMappingPacket) + kMaxCStringLen]; - StringMappingPacket* string_mapping_packet = - new (&message) StringMappingPacket(); - string_mapping_packet->address = reinterpret_cast<uint64_t>(c_string); - string_mapping_packet->string_len = length; - memcpy(message + sizeof(StringMappingPacket), c_string, length); - DoSend(address_, message, sizeof(StringMappingPacket) + length, - send_buffers_); - sent_strings->insert(c_string); - } - - AddInstructionPointer(c_string); - } - - size_t count() { return count_; } - - private: - void AddFrame(const base::trace_event::StackFrame& frame) { - if (frame.type == base::trace_event::StackFrame::Type::PROGRAM_COUNTER) { - AddInstructionPointer(frame.value); - return; - } - - AddCString(static_cast<const char*>(frame.value)); - } - - void AddInstructionPointer(const void* value) { - *stack_ = reinterpret_cast<uint64_t>(value); - ++stack_; - ++count_; - } - - // The next frame should be written to this memory location. There are both - // static and runtime checks to prevent buffer overrun. - static_assert( - base::trace_event::Backtrace::kMaxFrameCount < kMaxStackEntries, - "Ensure that pseudo-stack frame count won't exceed OOP HP frame buffer."); - uint64_t* stack_; - - // The number of frames that have been written to the stack. - size_t count_ = 0; - - const void* address_; - size_t remaining_buffer_size_; - SendBuffer* send_buffers_; -}; - } // namespace void InitTLSSlot() { base::SamplingHeapProfiler::Init(); - ignore_result(ShimStateTLS()); } // In order for pseudo stacks to work, trace event filtering must be enabled. @@ -299,8 +59,7 @@ filtering_trace_config, base::trace_event::TraceLog::FILTERING_MODE); } -void InitAllocationRecorder(SenderPipe* sender_pipe, - mojom::ProfilingParamsPtr params) { +void InitAllocationRecorder(mojom::ProfilingParamsPtr params) { // Must be done before hooking any functions that make stack traces. base::debug::EnableInProcessStackDumping(); @@ -324,57 +83,10 @@ AllocationContextTracker::SetCaptureMode(CaptureMode::NATIVE_STACK); break; } - - g_send_buffers.Write(new SendBuffer[kNumSendBuffers]); - g_sender_pipe = sender_pipe; -} - -void SamplingProfilerWrapper::FlushBuffersAndClosePipe() { - // This ShareBuffer array is leaked on purpose to avoid races on Stop. - g_send_buffers.Write(nullptr); - if (g_sender_pipe) - g_sender_pipe->Close(); } namespace { -void SerializeFramesFromAllocationContext(FrameSerializer* serializer, - const char** context) { - auto* tracker = AllocationContextTracker::GetInstanceForCurrentThread(); - if (!tracker) - return; - - AllocationContext allocation_context; - if (!tracker->GetContextSnapshot(&allocation_context)) - return; - - serializer->AddAllFrames(allocation_context.backtrace); - if (!*context) - *context = allocation_context.type_name; -} - -void SerializeFramesFromBacktrace(FrameSerializer* serializer, - const char** context) { - void* frames[kMaxStackEntries]; - size_t frames_count; - const void** first_frame = - const_cast<const void**>(base::SamplingHeapProfiler::CaptureStackTrace( - frames, kMaxStackEntries - 1, &frames_count)); - serializer->AddAllInstructionPointers(frames_count, first_frame); - - if (g_include_thread_names) { - const char* thread_name = base::SamplingHeapProfiler::CachedThreadName(); - serializer->AddCString(thread_name); - } - - if (!*context) { - const auto* tracker = - AllocationContextTracker::GetInstanceForCurrentThread(); - if (tracker) - *context = tracker->TaskContext(); - } -} - // Notifies the test clients that allocation hooks have been initialized. void AllocatorHooksHaveBeenInitialized() { base::AutoLock lock(g_on_init_allocator_shim_lock_.Get()); @@ -385,121 +97,20 @@ FROM_HERE, std::move(*g_on_init_allocator_shim_callback_.Pointer())); } -AllocatorType ConvertType(base::PoissonAllocationSampler::AllocatorType type) { - static_assert(static_cast<uint32_t>( - base::PoissonAllocationSampler::AllocatorType::kMax) == - static_cast<uint32_t>(AllocatorType::kCount), - "AllocatorType lengths do not match."); +mojom::AllocatorType ConvertType( + base::PoissonAllocationSampler::AllocatorType type) { switch (type) { case base::PoissonAllocationSampler::AllocatorType::kMalloc: - return AllocatorType::kMalloc; + return mojom::AllocatorType::kMalloc; case base::PoissonAllocationSampler::AllocatorType::kPartitionAlloc: - return AllocatorType::kPartitionAlloc; + return mojom::AllocatorType::kPartitionAlloc; case base::PoissonAllocationSampler::AllocatorType::kBlinkGC: - return AllocatorType::kOilpan; - default: - NOTREACHED(); - return AllocatorType::kMalloc; + return mojom::AllocatorType::kOilpan; } } } // namespace -// Creates allocation info record, populates it with current call stack, -// thread name, allocator type and sends out to the client. Safe to call this -// method after TLS is destroyed. -void SamplingProfilerWrapper::SampleAdded( - void* address, - size_t size, - size_t total, - base::PoissonAllocationSampler::AllocatorType type, - const char* context) { - // CaptureStack (on Android) and AllocationContext (all OSes) may use TLS. - // Bail out if it has been destroyed. - if (ScopedAllowAlloc::HasTLSBeenDestroyed()) - return; - - // The PoissonAllocationSampler that invokes this method guarantees - // non-reentrancy, i.e. no allocations made within the scope of SampleAdded - // will produce a sample. - DCHECK(base::PoissonAllocationSampler::ScopedMuteThreadSamples::IsMuted()); - SendBuffer* send_buffers = g_send_buffers.Read(); - if (!send_buffers) - return; - - constexpr size_t max_message_size = sizeof(AllocPacket) + - kMaxStackEntries * sizeof(uint64_t) + - kMaxContextLen; - static_assert(max_message_size < SenderPipe::kPipeSize, - "We can't have a message size that exceeds the pipe write " - "buffer size."); - char message[max_message_size]; - // TODO(ajwong) check that this is technically valid. - AllocPacket* alloc_packet = reinterpret_cast<AllocPacket*>(message); - - uint64_t* stack = reinterpret_cast<uint64_t*>(&message[sizeof(AllocPacket)]); - - FrameSerializer serializer( - stack, address, max_message_size - sizeof(AllocPacket), send_buffers); - - CaptureMode capture_mode = AllocationContextTracker::capture_mode(); - if (capture_mode == CaptureMode::PSEUDO_STACK || - capture_mode == CaptureMode::MIXED_STACK) { - SerializeFramesFromAllocationContext(&serializer, &context); - } else { - SerializeFramesFromBacktrace(&serializer, &context); - } - - size_t context_len = context ? strnlen(context, kMaxContextLen) : 0; - - alloc_packet->op = kAllocPacketType; - alloc_packet->allocator = ConvertType(type); - alloc_packet->address = (uint64_t)address; - alloc_packet->size = size; - alloc_packet->stack_len = static_cast<uint32_t>(serializer.count()); - alloc_packet->context_byte_len = static_cast<uint32_t>(context_len); - - char* message_end = message + sizeof(AllocPacket) + - alloc_packet->stack_len * sizeof(uint64_t); - if (context_len > 0) { - memcpy(message_end, context, context_len); - message_end += context_len; - } - DoSend(address, message, message_end - message, send_buffers); -} - -// Creates the record for free operation and sends it out to the client. Safe -// to call this method after TLS is destroyed. -void SamplingProfilerWrapper::SampleRemoved(void* address) { - DCHECK(base::PoissonAllocationSampler::ScopedMuteThreadSamples::IsMuted()); - SendBuffer* send_buffers = g_send_buffers.Read(); - if (!send_buffers) - return; - - FreePacket free_packet; - free_packet.op = kFreePacketType; - free_packet.address = (uint64_t)address; - - DoSend(address, &free_packet, sizeof(FreePacket), send_buffers); -} - -void SamplingProfilerWrapper::FlushPipe(uint32_t barrier_id) { - SendBuffer* send_buffers = g_send_buffers.Read(); - if (!send_buffers) - return; - for (int i = 0; i < kNumSendBuffers; i++) - send_buffers[i].Flush(); - - BarrierPacket barrier; - barrier.barrier_id = barrier_id; - SenderPipe::Result result = - g_sender_pipe->Send(&barrier, sizeof(barrier), kTimeoutMs); - if (result != SenderPipe::Result::kSuccess) { - FlushBuffersAndClosePipe(); - // TODO(erikchen): Emit a histogram. https://crbug.com/777546. - } -} - bool SetOnInitAllocatorShimCallbackForTesting( base::OnceClosure callback, scoped_refptr<base::TaskRunner> task_runner) { @@ -511,32 +122,20 @@ return false; } -void SamplingProfilerWrapper::StartProfiling(SenderPipe* sender_pipe, - mojom::ProfilingParamsPtr params) { +void SamplingProfilerWrapper::StartProfiling(mojom::ProfilingParamsPtr params) { size_t sampling_rate = params->sampling_rate; - stream_samples_ = params->stream_samples; - InitAllocationRecorder(sender_pipe, std::move(params)); - if (stream_samples_) { - auto* sampler = base::PoissonAllocationSampler::Get(); - sampler->SetSamplingInterval(sampling_rate); - sampler->AddSamplesObserver(this); - } else { - auto* profiler = base::SamplingHeapProfiler::Get(); - profiler->SetSamplingInterval(sampling_rate); - profiler->Start(); - } + InitAllocationRecorder(std::move(params)); + auto* profiler = base::SamplingHeapProfiler::Get(); + profiler->SetSamplingInterval(sampling_rate); + profiler->Start(); AllocatorHooksHaveBeenInitialized(); } void SamplingProfilerWrapper::StopProfiling() { - if (stream_samples_) - base::PoissonAllocationSampler::Get()->RemoveSamplesObserver(this); - else - base::SamplingHeapProfiler::Get()->Stop(); + base::SamplingHeapProfiler::Get()->Stop(); } mojom::HeapProfilePtr SamplingProfilerWrapper::RetrieveHeapProfile() { - DCHECK(!stream_samples_); auto* profiler = base::SamplingHeapProfiler::Get(); std::vector<base::SamplingHeapProfiler::Sample> samples = profiler->GetSamples(/*profile_id=*/0); @@ -548,8 +147,7 @@ std::unordered_set<const char*> thread_names; for (const auto& sample : samples) { auto mojo_sample = mojom::HeapProfileSample::New(); - mojo_sample->allocator = - static_cast<uint32_t>(ConvertType(sample.allocator)); + mojo_sample->allocator = ConvertType(sample.allocator); mojo_sample->size = sample.size; mojo_sample->context_id = reinterpret_cast<uintptr_t>(sample.context); mojo_sample->stack.reserve(sample.stack.size() +
diff --git a/components/services/heap_profiling/public/cpp/sampling_profiler_wrapper.h b/components/services/heap_profiling/public/cpp/sampling_profiler_wrapper.h index d6bff9c1..cf21721 100644 --- a/components/services/heap_profiling/public/cpp/sampling_profiler_wrapper.h +++ b/components/services/heap_profiling/public/cpp/sampling_profiler_wrapper.h
@@ -5,15 +5,10 @@ #ifndef COMPONENTS_SERVICES_HEAP_PROFILING_PUBLIC_CPP_SAMPLING_PROFILER_WRAPPER_H_ #define COMPONENTS_SERVICES_HEAP_PROFILING_PUBLIC_CPP_SAMPLING_PROFILER_WRAPPER_H_ -#include <vector> - -#include "base/sampling_heap_profiler/poisson_allocation_sampler.h" #include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h" namespace heap_profiling { -class SenderPipe; - // Initializes the TLS slot globally. This will be called early in Chrome's // lifecycle to prevent re-entrancy from occurring while trying to set up the // TLS slot, which is the entity that's supposed to prevent re-entrancy. @@ -29,32 +24,12 @@ // The class listens for allocation samples records the necessary attributes // and passes allocations down the pipeline. -class SamplingProfilerWrapper - : private base::PoissonAllocationSampler::SamplesObserver { +class SamplingProfilerWrapper { public: - void StartProfiling(SenderPipe* sender_pipe, - mojom::ProfilingParamsPtr params); + void StartProfiling(mojom::ProfilingParamsPtr params); void StopProfiling(); - // This method closes sender pipe. - static void FlushBuffersAndClosePipe(); - - // Ensures all send buffers are flushed. The given barrier ID is sent to the - // logging process so it knows when this operation is complete. - static void FlushPipe(uint32_t barrier_id); - mojom::HeapProfilePtr RetrieveHeapProfile(); - - private: - // base::PoissonAllocationSampler::SamplesObserver - void SampleAdded(void* address, - size_t size, - size_t total, - base::PoissonAllocationSampler::AllocatorType, - const char* context) override; - void SampleRemoved(void* address) override; - - bool stream_samples_ = false; }; } // namespace heap_profiling
diff --git a/components/services/heap_profiling/public/cpp/sender_pipe.h b/components/services/heap_profiling/public/cpp/sender_pipe.h deleted file mode 100644 index a84e8371..0000000 --- a/components/services/heap_profiling/public/cpp/sender_pipe.h +++ /dev/null
@@ -1,69 +0,0 @@ -// 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. - -#ifndef COMPONENTS_SERVICES_HEAP_PROFILING_PUBLIC_CPP_SENDER_PIPE_H_ -#define COMPONENTS_SERVICES_HEAP_PROFILING_PUBLIC_CPP_SENDER_PIPE_H_ - -#include "build/build_config.h" - -#include "base/files/platform_file.h" -#include "base/macros.h" -#include "base/synchronization/lock.h" -#include "mojo/public/cpp/platform/platform_handle.h" - -namespace heap_profiling { - -class SenderPipe { - public: - // 64k is a convenient pipe buffer size. - // On macOS, the default pipe buffer size is 16 * 1024, but grows to 64 * 1024 - // for large writes. See BIG_PIPE_SIZE. - // https://opensource.apple.com/source/xnu/xnu-1504.9.37/bsd/sys/pipe.h - // On Linux [since 2.6.11], the default pipe buffer size is 64 * 1024. See - // https://linux.die.net/man/7/pipe - // On Windows, the pipe buffer size is configurable. - static constexpr size_t kPipeSize = 64 * 1024; - - class PipePair { - public: - // Returns a pair of newly created pipes. Must be called from a privileged - // process. The sender-pipe is non-blocking and has a buffer size of - // |kPipeSize|. - PipePair(); - PipePair(PipePair&&); - mojo::PlatformHandle PassSender() { return std::move(sender_); } - mojo::PlatformHandle PassReceiver() { return std::move(receiver_); } - - private: - mojo::PlatformHandle sender_; - mojo::PlatformHandle receiver_; - DISALLOW_COPY_AND_ASSIGN(PipePair); - }; - - explicit SenderPipe(mojo::PlatformHandle handle); - ~SenderPipe(); - - enum class Result { kSuccess, kTimeout, kError }; - - // Attempts to atomically write all the |data| into the pipe. kError is - // returned on failure, kTimeout after |timeout_ms| milliseconds. - Result Send(const void* data, size_t sz, int timeout_ms); - - // Closes the underlying pipe. - void Close(); - - private: - base::ScopedPlatformFile file_; - - // All calls to Send() are wrapped in a Lock, since the size of the data might - // be larger than the maximum atomic write size of a pipe on Posix [PIPE_BUF]. - // On Windows, ::WriteFile() is not thread-safe. - base::Lock lock_; - - DISALLOW_COPY_AND_ASSIGN(SenderPipe); -}; - -} // namespace heap_profiling - -#endif // COMPONENTS_SERVICES_HEAP_PROFILING_PUBLIC_CPP_SENDER_PIPE_H_
diff --git a/components/services/heap_profiling/public/cpp/sender_pipe_posix.cc b/components/services/heap_profiling/public/cpp/sender_pipe_posix.cc deleted file mode 100644 index a6bb324b..0000000 --- a/components/services/heap_profiling/public/cpp/sender_pipe_posix.cc +++ /dev/null
@@ -1,107 +0,0 @@ -// 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. - -#include "components/services/heap_profiling/public/cpp/sender_pipe.h" - -#include <fcntl.h> -#include <poll.h> -#include <unistd.h> - -#include "base/logging.h" -#include "base/numerics/safe_conversions.h" -#include "base/posix/eintr_wrapper.h" -#include "base/strings/string_number_conversions.h" -#include "build/build_config.h" -#include "components/services/heap_profiling/public/cpp/stream.h" - -namespace heap_profiling { - -SenderPipe::PipePair::PipePair() { - // We create a pipe() rather than a socketpair(). On macOS, this causes writes - // to be much more performant. On Linux, this causes slight improvements. - // https://bugs.chromium.org/p/chromium/issues/detail?id=776435 - int fds[2]; - PCHECK(0 == pipe(fds)); - PCHECK(fcntl(fds[0], F_SETFL, O_NONBLOCK) == 0); - PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0); -#if defined(OS_MACOSX) - // On macOS, suppress SIGPIPE. On Linux, we must rely on the assumption that - // the SIGPIPE signal is ignored [which it is]. - PCHECK(fcntl(fds[0], F_SETNOSIGPIPE, 1) == 0); - PCHECK(fcntl(fds[1], F_SETNOSIGPIPE, 1) == 0); -#endif - receiver_ = mojo::PlatformHandle(base::ScopedFD(fds[0])); - sender_ = mojo::PlatformHandle(base::ScopedFD(fds[1])); -} - -SenderPipe::PipePair::PipePair(PipePair&& other) = default; - -SenderPipe::SenderPipe(mojo::PlatformHandle handle) : file_(handle.TakeFD()) {} - -SenderPipe::~SenderPipe() = default; - -SenderPipe::Result SenderPipe::Send(const void* data, - size_t sz, - int timeout_ms) { - base::AutoLock lock(lock_); - - // This can happen if Close() was called on another thread, while this thread - // was already waiting to call SenderPipe::Send(). - if (!file_.is_valid()) - return Result::kError; - - int size = base::checked_cast<int>(sz); - base::TimeTicks start_time; - while (size > 0) { - int r = HANDLE_EINTR(write(file_.get(), data, size)); - - // On success! - if (r != -1) { - DCHECK_LE(r, size); - size -= r; - data = static_cast<const char*>(data) + r; - continue; - } - - // An error is either irrecoverable, or an I/O delay. Wait at most - // timeout_ms seconds for the pipe to clear. - int cached_errno = errno; - if (cached_errno != EAGAIN && cached_errno != EWOULDBLOCK) - return Result::kError; - - // Set the start time, if it hasn't already been set. - base::TimeTicks now = base::TimeTicks::Now(); - if (start_time.is_null()) - start_time = now; - - // Calculate time left. - int64_t time_left_ms = - ((start_time + base::TimeDelta::FromMilliseconds(timeout_ms)) - now) - .InMilliseconds(); - if (time_left_ms <= 0) - return Result::kTimeout; - - // Wait for the pipe to be writeable. - struct pollfd pfd = {file_.get(), POLLOUT, 0}; - int poll_result = - HANDLE_EINTR(poll(&pfd, 1, static_cast<int>(time_left_ms))); - if (poll_result == 0) - return Result::kTimeout; - if (poll_result == -1) - return Result::kError; - - // If POLLOUT isn't returned, the pipe isn't writeable. - DCHECK_EQ(poll_result, 1); - if (!(pfd.revents & POLLOUT)) - return Result::kError; - } - return Result::kSuccess; -} - -void SenderPipe::Close() { - base::AutoLock lock(lock_); - file_.reset(); -} - -} // namespace heap_profiling
diff --git a/components/services/heap_profiling/public/cpp/sender_pipe_unittest.cc b/components/services/heap_profiling/public/cpp/sender_pipe_unittest.cc deleted file mode 100644 index b9ef5dc..0000000 --- a/components/services/heap_profiling/public/cpp/sender_pipe_unittest.cc +++ /dev/null
@@ -1,95 +0,0 @@ -// 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. - -#include "components/services/heap_profiling/public/cpp/sender_pipe.h" - -#include <vector> - -#include "build/build_config.h" -#include "mojo/public/cpp/platform/platform_handle.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_WIN) -#include <windows.h> -#endif - -namespace heap_profiling { -namespace { - -using Result = SenderPipe::Result; - -class SenderPipeTest : public testing::Test { - public: - void SetUp() override { - SenderPipe::PipePair pipes; - read_handle_ = pipes.PassReceiver(); - - sender_pipe_.reset(new SenderPipe(pipes.PassSender())); - - // A large buffer for both writing and reading. - buffer_.resize(64 * 1024); - } - - Result Write(int size) { return sender_pipe_->Send(buffer_.data(), size, 1); } - - void Read(int size) { -#if defined(OS_POSIX) || defined(OS_FUCHSIA) - ssize_t bytes_read = read(read_handle_.GetFD().get(), buffer_.data(), size); - ASSERT_EQ(size, bytes_read); -#else - OVERLAPPED overlapped; - DWORD bytes_read = 0; - memset(&overlapped, 0, sizeof(OVERLAPPED)); - BOOL result = ::ReadFile(read_handle_.GetHandle().Get(), buffer_.data(), - size, &bytes_read, &overlapped); - ASSERT_TRUE(result); - ASSERT_EQ(static_cast<DWORD>(size), bytes_read); -#endif - } - - private: - mojo::PlatformHandle read_handle_; - std::unique_ptr<SenderPipe> sender_pipe_; - std::vector<char> buffer_; -}; - -TEST_F(SenderPipeTest, TimeoutNoRead) { - // Writing 64k should not time out. - Result result = Write(64 * 1024); - ASSERT_EQ(Result::kSuccess, result); - - // Writing 64k more should time out, since the buffer size is 64k. - result = Write(64 * 1024); - ASSERT_EQ(Result::kTimeout, result); -} - -TEST_F(SenderPipeTest, TimeoutSmallRead) { - // Writing 64k should not time out. - Result result = Write(64 * 1024); - ASSERT_EQ(Result::kSuccess, result); - - // Read 32k out of the buffer. - Read(32 * 1024); - - // Writing 64k more should still time out, since the buffer size should be - // 64k. - result = Write(64 * 1024); - ASSERT_EQ(Result::kTimeout, result); -} - -TEST_F(SenderPipeTest, NoTimeout) { - // Writing 64k should not time out. - Result result = Write(64 * 1024); - ASSERT_EQ(Result::kSuccess, result); - - // Read 64k out of the buffer. - Read(64 * 1024); - - // Writing 64k should not time out. - result = Write(64 * 1024); - ASSERT_EQ(Result::kSuccess, result); -} - -} // namespace -} // namespace heap_profiling
diff --git a/components/services/heap_profiling/public/cpp/sender_pipe_win.cc b/components/services/heap_profiling/public/cpp/sender_pipe_win.cc deleted file mode 100644 index 4c137f70..0000000 --- a/components/services/heap_profiling/public/cpp/sender_pipe_win.cc +++ /dev/null
@@ -1,177 +0,0 @@ -// 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. - -#include "components/services/heap_profiling/public/cpp/sender_pipe.h" - -#include <windows.h> - -#include "base/logging.h" -#include "base/rand_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "components/services/heap_profiling/public/cpp/stream.h" - -namespace heap_profiling { - -namespace { - -// The documentation for ::WriteFileEx indicates that the last parameter is an -// OVERLAPPED*. But OVERLAPPED has no member to hold a void* context for -// SenderPipe, and without that, the callback must only use global -// variables. This is problematic. The example -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365601(v=vs.85).aspx -// instead uses a struct whose first member is an OVERLAPPED object, and passes -// a struct pointer to ::WriteFileEx. -struct OverlappedWriteContext { - OverlappedWriteContext() - : waiting_for_write(true), bytes_written(0), error(ERROR_SUCCESS) { - memset(&overlap, 0, sizeof(overlap)); - overlap.Offset = 0xFFFFFFFF; - overlap.OffsetHigh = 0xFFFFFFFF; - } - - // This must always be the first member. - OVERLAPPED overlap; - bool waiting_for_write; - DWORD bytes_written; - DWORD error; -}; - -static_assert(offsetof(OverlappedWriteContext, overlap) == 0, - "overlap must always be the first member."); - -// A global function called by ::WriteFileEx when the write has finished, or -// errored. -void WINAPI AsyncWriteFinishedGlobal(DWORD error, - DWORD bytes_written, - LPOVERLAPPED overlap) { - OverlappedWriteContext* context = - reinterpret_cast<OverlappedWriteContext*>(overlap); - context->waiting_for_write = false; - context->bytes_written = bytes_written; - context->error = error; -} - -} // namespace - -SenderPipe::PipePair::PipePair() { - std::wstring pipe_name = base::StringPrintf( - L"\\\\.\\pipe\\profiling.%u.%u.%I64u", GetCurrentProcessId(), - GetCurrentThreadId(), base::RandUint64()); - - HANDLE handle = CreateNamedPipe( - pipe_name.c_str(), - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, - 1, // Max instances. - kPipeSize, // Out buffer size. - kPipeSize, // In buffer size. - 5000, // Timeout in milliseconds for connecting the receiving pipe. Has - // nothing to do with Send() timeout. - nullptr); - PCHECK(handle != INVALID_HANDLE_VALUE); - receiver_ = mojo::PlatformHandle(base::win::ScopedHandle(handle)); - - // Allow the handle to be inherited by child processes. - SECURITY_ATTRIBUTES security_attributes; - security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES); - security_attributes.lpSecurityDescriptor = nullptr; - security_attributes.bInheritHandle = TRUE; - - handle = CreateFile( - pipe_name.c_str(), GENERIC_WRITE, - 0, // No sharing. - &security_attributes, OPEN_EXISTING, - SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED, - nullptr); - PCHECK(handle != INVALID_HANDLE_VALUE); - sender_ = mojo::PlatformHandle(base::win::ScopedHandle(handle)); - - // Since a client has connected, ConnectNamedPipe() should return zero and - // GetLastError() should return ERROR_PIPE_CONNECTED. - BOOL result = ConnectNamedPipe(receiver_.GetHandle().Get(), nullptr); - DWORD error = GetLastError(); - CHECK((result == 0) && (error == ERROR_PIPE_CONNECTED)); -} - -SenderPipe::PipePair::PipePair(PipePair&& other) = default; - -SenderPipe::SenderPipe(mojo::PlatformHandle handle) - : file_(handle.TakeHandle()) {} - -SenderPipe::~SenderPipe() {} - -SenderPipe::Result SenderPipe::Send(const void* data, - size_t size, - int timeout_ms) { - // The pipe is nonblocking. However, to ensure that messages on different - // threads are serialized and in order: - // 1) We grab a global lock. - // 2) We attempt to synchronously write, but with a timeout. On timeout - // or error, the SenderPipe is shut down. - base::AutoLock lock(lock_); - - // This can happen if Close() was called on another thread, while this thread - // was already waiting to call SenderPipe::Send(). - if (!file_.IsValid()) - return Result::kError; - - // Queue an asynchronous write. - OverlappedWriteContext context; - - // It's safe to use a raw pointer to |context|, since it will stay on the - // stack until ::SleepEx returns, at which point either the callback has - // finished, or will be cancelled. - BOOL write_result = ::WriteFileEx(file_.Get(), data, static_cast<DWORD>(size), - &context.overlap, AsyncWriteFinishedGlobal); - - // Check for errors. - if (!write_result) - return Result::kError; - - // The documentation for ::WriteFileEx - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365748(v=vs.85).aspx - // claims that we need to check GetLastError() even on success. This is - // incorrect. GetLastError() returns the error from the previous Windows - // library call. - - while (true) { - // The return code of ::SleepEx has multiple semantics. Do not replace this - // with PlatformThread::Sleep. - DWORD sleep_result = ::SleepEx(timeout_ms, TRUE); - - // Timeout reached. - if (sleep_result == 0) { - BOOL r = ::CancelIo(file_.Get()); - DCHECK_NE(0, r); - DWORD r2 = ::WaitForSingleObject(file_.Get(), INFINITE); - DCHECK_EQ(WAIT_OBJECT_0, r2); - return Result::kTimeout; - } - - // Unexpected error. - if (sleep_result != WAIT_IO_COMPLETION) - return Result::kError; - - // In the very rare case where this function returns from the completion of - // another async IO handler, just repeat the sleep duration. This allows us - // to avoid a call to base::TimeTicks::Now() in the common case. - if (context.waiting_for_write) - continue; - - if (context.error != ERROR_SUCCESS) - return Result::kError; - - // Partial writes should not be possible. - DCHECK_EQ(context.bytes_written, size); - return Result::kSuccess; - } -} - -void SenderPipe::Close() { - base::AutoLock lock(lock_); - file_.Close(); -} - -} // namespace heap_profiling
diff --git a/components/services/heap_profiling/public/cpp/settings.cc b/components/services/heap_profiling/public/cpp/settings.cc index 96b3a3ce..f569e80 100644 --- a/components/services/heap_profiling/public/cpp/settings.cc +++ b/components/services/heap_profiling/public/cpp/settings.cc
@@ -145,11 +145,6 @@ kDefaultSamplingRate); } -bool IsInProcessModeEnabled() { - return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - kMemlogInProcess) != kMemlogInProcessDisabled; -} - bool IsBackgroundHeapProfilingEnabled() { return base::FeatureList::IsEnabled(kOOPHeapProfilingFeature); }
diff --git a/components/services/heap_profiling/public/cpp/settings.h b/components/services/heap_profiling/public/cpp/settings.h index 6cb5cdd..1e5e8da 100644 --- a/components/services/heap_profiling/public/cpp/settings.h +++ b/components/services/heap_profiling/public/cpp/settings.h
@@ -59,7 +59,6 @@ // recorded every N bytes of allocated objects. uint32_t GetSamplingRateForStartup(); -bool IsInProcessModeEnabled(); bool IsBackgroundHeapProfilingEnabled(); // Exposed for testing.
diff --git a/components/services/heap_profiling/public/cpp/stream.h b/components/services/heap_profiling/public/cpp/stream.h deleted file mode 100644 index 8e01f80..0000000 --- a/components/services/heap_profiling/public/cpp/stream.h +++ /dev/null
@@ -1,92 +0,0 @@ -// 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. -// -// We use a custom stream format for performance, since we're potentially -// sending a packet for every malloc and free. - -#ifndef COMPONENTS_SERVICES_HEAP_PROFILING_PUBLIC_CPP_STREAM_H_ -#define COMPONENTS_SERVICES_HEAP_PROFILING_PUBLIC_CPP_STREAM_H_ - -#include <stdint.h> - -#include "build/build_config.h" - -namespace heap_profiling { - -// These values should be kept in sync with -// chrome/profiling/stream_fuzzer.dict to ensure efficient fuzzer -// coverage of the stream parser. -constexpr uint32_t kStreamSignature = 0xF6103B71; - -constexpr uint32_t kAllocPacketType = 0xF6103B72; -constexpr uint32_t kFreePacketType = 0xF6103B73; -constexpr uint32_t kBarrierPacketType = 0xF6103B74; -constexpr uint32_t kStringMappingPacketType = 0xF6103B75; - -constexpr uint32_t kMaxStackEntries = 256; -constexpr uint32_t kMaxContextLen = 256; - -// This should count up from 0 so it can be used to index into an array. -enum class AllocatorType : uint32_t { - kMalloc = 0, - kPartitionAlloc = 1, - kOilpan = 2, - kCount // Number of allocator types. -}; - -#pragma pack(push, 1) -struct StreamHeader { - uint32_t signature = kStreamSignature; -}; - -struct AllocPacket { - uint32_t op = kAllocPacketType; - - AllocatorType allocator; - - uint64_t address; - uint64_t size; - - // Number of stack entries following this header. - uint32_t stack_len; - - // Number of context bytes following the stack; - uint32_t context_byte_len; - - // Immediately followed by |stack_len| uint64_t addresses and - // |context_byte_len| bytes of context (not null terminated). -}; - -struct FreePacket { - uint32_t op = kFreePacketType; - - uint64_t address; -}; - -// A barrier packet is a way to synchronize with the sender to make sure all -// events are received up to a certain point. The barrier ID is just a number -// that can be used to uniquely identify these events. -struct BarrierPacket { - const uint32_t op = kBarrierPacketType; - - uint32_t barrier_id; -}; - -// Clients will sometimes use pointers to const strings in place of instruction -// addresses in AllocPackets. Prior to using such a pointer, the client should -// send a StringMappingPacket to inform the profiling service. -struct StringMappingPacket { - const uint32_t op = kStringMappingPacketType; - uint64_t address; - uint32_t string_len; - - // Immediately followed by |string_len| bytes of string (not null - // terminated). -}; - -#pragma pack(pop) - -} // namespace heap_profiling - -#endif // COMPONENTS_SERVICES_HEAP_PROFILING_PUBLIC_CPP_STREAM_H_
diff --git a/components/services/heap_profiling/public/cpp/switches.cc b/components/services/heap_profiling/public/cpp/switches.cc index 8f4a317..0d5a6e4 100644 --- a/components/services/heap_profiling/public/cpp/switches.cc +++ b/components/services/heap_profiling/public/cpp/switches.cc
@@ -6,10 +6,6 @@ namespace heap_profiling { -const char kMemlogInProcess[] = "memlog-in-process"; -const char kMemlogInProcessEnabled[] = "on"; -const char kMemlogInProcessDisabled[] = "off"; - const char kMemlogMode[] = "memlog"; const char kMemlogModeAll[] = "all"; const char kMemlogModeAllRenderers[] = "all-renderers";
diff --git a/components/services/heap_profiling/public/cpp/switches.h b/components/services/heap_profiling/public/cpp/switches.h index 12d5326..8cf4cea 100644 --- a/components/services/heap_profiling/public/cpp/switches.h +++ b/components/services/heap_profiling/public/cpp/switches.h
@@ -18,10 +18,6 @@ extern const char kMemlogModeUtilityAndBrowser[]; extern const char kMemlogModeUtilitySampling[]; -extern const char kMemlogInProcess[]; -extern const char kMemlogInProcessEnabled[]; -extern const char kMemlogInProcessDisabled[]; - extern const char kMemlogSamplingRate[]; extern const char kMemlogSamplingRate10KB[]; extern const char kMemlogSamplingRate50KB[];
diff --git a/components/services/heap_profiling/public/mojom/heap_profiling_client.mojom b/components/services/heap_profiling/public/mojom/heap_profiling_client.mojom index 6a9607776..33efeeed 100644 --- a/components/services/heap_profiling/public/mojom/heap_profiling_client.mojom +++ b/components/services/heap_profiling/public/mojom/heap_profiling_client.mojom
@@ -20,18 +20,16 @@ MIXED }; +// Type of the allocator responsible for the allocation sample. +enum AllocatorType { + kMalloc, + kPartitionAlloc, + kOilpan +}; + // A wrapper for parameters that affect each client's implementation of // profiling. struct ProfilingParams { - // When |stream_samples| is true the samples are streamed through the - // provided |sender_pipe|. Otherwise, the samples are stored on - // the client side during recording and can be retrieved using - // |ProfilingClient.RetrieveHeapProfile| method. - bool stream_samples; - - // The client should record allocations into |memlog_sender_pipe|. - handle sender_pipe; - // |stack_mode| refers to the type of data that should be recorded for each // allocation. StackMode stack_mode; @@ -46,7 +44,7 @@ // A single memory allocation sample. struct HeapProfileSample { // Allocator type. - uint32 allocator; + AllocatorType allocator; // The size in bytes accounted for the sample. uint64 size; @@ -81,10 +79,5 @@ // There is currently no mechanism to stop recording allocations. StartProfiling(ProfilingParams params); - // Flushes the memlog pipe associated with this client. A barrier packet is - // set over the memlog pipe with the given identifier. This allows the - // receiver to synchronize with the flush. - FlushMemlogPipe(uint32 barrier_id); - RetrieveHeapProfile() => (HeapProfile profile); };
diff --git a/components/services/heap_profiling/public/mojom/heap_profiling_service.mojom b/components/services/heap_profiling/public/mojom/heap_profiling_service.mojom index d349b7f..e8e0ff60 100644 --- a/components/services/heap_profiling/public/mojom/heap_profiling_service.mojom +++ b/components/services/heap_profiling/public/mojom/heap_profiling_service.mojom
@@ -24,15 +24,8 @@ // // The "client" interface will be for the instrumented process. It allows the // profiling process to talk to the new process. - // - // Both ends of a platform-specific pipe to read memlog trace data from is - // passed in. The sender end will be forwarded to the client process. - // - // |stack_mode| refers to the type of stacks that the client should record for - // allocations. AddProfilingClient(mojo_base.mojom.ProcessId pid, ProfilingClient client, - handle memlog_pipe_receiver, ProcessType process_type, - ProfilingParams params); + ProcessType process_type, ProfilingParams params); // Returns the pids of all profiled processes. GetProfiledPids() => (array<mojo_base.mojom.ProcessId> pids);
diff --git a/components/services/heap_profiling/receiver.h b/components/services/heap_profiling/receiver.h deleted file mode 100644 index 332d0d90..0000000 --- a/components/services/heap_profiling/receiver.h +++ /dev/null
@@ -1,35 +0,0 @@ -// 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. - -#ifndef COMPONENTS_SERVICES_HEAP_PROFILING_RECEIVER_H_ -#define COMPONENTS_SERVICES_HEAP_PROFILING_RECEIVER_H_ - -#include <vector> - -#include "base/memory/ref_counted.h" -#include "components/services/heap_profiling/address.h" -#include "components/services/heap_profiling/public/cpp/stream.h" - -namespace heap_profiling { - -// A log receiver is a sink for parsed allocation events. See also -// StreamReceiver which is for the unparsed data blocks. -class Receiver { - public: - virtual ~Receiver() {} - - virtual void OnHeader(const StreamHeader& header) = 0; - virtual void OnAlloc(const AllocPacket& alloc_packet, - std::vector<Address>&& stack, - std::string&& context) = 0; - virtual void OnFree(const FreePacket& free_packet) = 0; - virtual void OnBarrier(const BarrierPacket& barrier_packet) = 0; - virtual void OnStringMapping(const StringMappingPacket& string_mapping_packet, - const std::string& str) = 0; - virtual void OnComplete() = 0; -}; - -} // namespace heap_profiling - -#endif // COMPONENTS_SERVICES_HEAP_PROFILING_RECEIVER_H_
diff --git a/components/services/heap_profiling/receiver_pipe.cc b/components/services/heap_profiling/receiver_pipe.cc deleted file mode 100644 index 1d383c5..0000000 --- a/components/services/heap_profiling/receiver_pipe.cc +++ /dev/null
@@ -1,38 +0,0 @@ -// 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. - -#include "components/services/heap_profiling/receiver_pipe.h" - -#include "base/bind.h" -#include "base/task_runner.h" -#include "components/services/heap_profiling/stream_receiver.h" - -namespace heap_profiling { - -ReceiverPipeBase::ReceiverPipeBase(mojo::PlatformHandle handle) - : handle_(std::move(handle)) {} - -ReceiverPipeBase::~ReceiverPipeBase() = default; - -void ReceiverPipeBase::SetReceiver(scoped_refptr<base::TaskRunner> task_runner, - scoped_refptr<StreamReceiver> receiver) { - receiver_task_runner_ = std::move(task_runner); - receiver_ = receiver; -} - -void ReceiverPipeBase::ReportError() { - handle_.reset(); -} - -void ReceiverPipeBase::OnStreamDataThunk( - scoped_refptr<base::TaskRunner> pipe_task_runner, - std::unique_ptr<char[]> data, - size_t size) { - if (!receiver_->OnStreamData(std::move(data), size)) { - pipe_task_runner->PostTask( - FROM_HERE, base::BindOnce(&ReceiverPipeBase::ReportError, this)); - } -} - -} // namespace heap_profiling
diff --git a/components/services/heap_profiling/receiver_pipe.h b/components/services/heap_profiling/receiver_pipe.h deleted file mode 100644 index d0e56150..0000000 --- a/components/services/heap_profiling/receiver_pipe.h +++ /dev/null
@@ -1,61 +0,0 @@ -// 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. - -#ifndef COMPONENTS_SERVICES_HEAP_PROFILING_RECEIVER_PIPE_H_ -#define COMPONENTS_SERVICES_HEAP_PROFILING_RECEIVER_PIPE_H_ - -#include "base/memory/ref_counted.h" -#include "build/build_config.h" -#include "mojo/public/cpp/platform/platform_handle.h" - -namespace base { -class TaskRunner; -} - -namespace heap_profiling { - -class StreamReceiver; - -// Base class for the platform-specific receiver pipes. Since there is only -// ever one actual implementation of this in the system, those implementations -// are called "ReceiverPipe" and the common functions are not -// virtual. This class is just for the shared implementation. -class ReceiverPipeBase : public base::RefCountedThreadSafe<ReceiverPipeBase> { - public: - void SetReceiver(scoped_refptr<base::TaskRunner> task_runner, - scoped_refptr<StreamReceiver> receiver); - - protected: - friend class base::RefCountedThreadSafe<ReceiverPipeBase>; - - explicit ReceiverPipeBase(mojo::PlatformHandle handle); - virtual ~ReceiverPipeBase(); - - // Callback that indicates an error has occurred and the connection should - // be closed. May be called more than once in an error condition. - void ReportError(); - - // Called on the receiver task runner's thread to call the OnStreamData - // function and post the error back to the pipe on the correct thread if one - // occurs. - void OnStreamDataThunk(scoped_refptr<base::TaskRunner> pipe_task_runner, - std::unique_ptr<char[]> data, - size_t size); - - scoped_refptr<base::TaskRunner> receiver_task_runner_; - scoped_refptr<StreamReceiver> receiver_; - - mojo::PlatformHandle handle_; -}; - -} // namespace heap_profiling - -// Define the platform-specific specialization. -#if defined(OS_WIN) -#include "components/services/heap_profiling/receiver_pipe_win.h" -#else -#include "components/services/heap_profiling/receiver_pipe_posix.h" -#endif - -#endif // COMPONENTS_SERVICES_HEAP_PROFILING_RECEIVER_PIPE_H_
diff --git a/components/services/heap_profiling/receiver_pipe_posix.cc b/components/services/heap_profiling/receiver_pipe_posix.cc deleted file mode 100644 index c8cb80b8..0000000 --- a/components/services/heap_profiling/receiver_pipe_posix.cc +++ /dev/null
@@ -1,72 +0,0 @@ -// 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. - -#include "components/services/heap_profiling/receiver_pipe_posix.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/message_loop/message_loop_current.h" -#include "base/posix/eintr_wrapper.h" -#include "base/threading/thread.h" -#include "build/build_config.h" -#include "components/services/heap_profiling/public/cpp/sender_pipe.h" -#include "components/services/heap_profiling/receiver_pipe.h" -#include "components/services/heap_profiling/stream_receiver.h" - -namespace heap_profiling { - -ReceiverPipe::ReceiverPipe(mojo::PlatformHandle handle) - : ReceiverPipeBase(std::move(handle)), - controller_(FROM_HERE), - read_buffer_(new char[SenderPipe::kPipeSize]) {} - -ReceiverPipe::~ReceiverPipe() {} - -void ReceiverPipe::StartReadingOnIOThread() { - base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor( - handle_.GetFD().get(), true, base::MessagePumpForIO::WATCH_READ, - &controller_, this); - OnFileCanReadWithoutBlocking(handle_.GetFD().get()); -} - -void ReceiverPipe::OnFileCanReadWithoutBlocking(int fd) { - ssize_t bytes_read = 0; - do { - bytes_read = HANDLE_EINTR( - read(handle_.GetFD().get(), read_buffer_.get(), SenderPipe::kPipeSize)); - if (bytes_read > 0) { - receiver_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&ReceiverPipe::OnStreamDataThunk, this, - base::MessageLoopCurrent::Get()->task_runner(), - std::move(read_buffer_), - static_cast<size_t>(bytes_read))); - read_buffer_.reset(new char[SenderPipe::kPipeSize]); - return; - } else if (bytes_read == 0) { - // Other end closed the pipe. - controller_.StopWatchingFileDescriptor(); - DCHECK(receiver_task_runner_); - receiver_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&StreamReceiver::OnStreamComplete, receiver_)); - return; - } else { - if (errno != EAGAIN && errno != EWOULDBLOCK) { - controller_.StopWatchingFileDescriptor(); - PLOG(ERROR) << "Problem reading socket."; - DCHECK(receiver_task_runner_); - receiver_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&StreamReceiver::OnStreamComplete, receiver_)); - } - } - } while (bytes_read > 0); -} - -void ReceiverPipe::OnFileCanWriteWithoutBlocking(int fd) { - NOTREACHED(); -} - -} // namespace heap_profiling
diff --git a/components/services/heap_profiling/receiver_pipe_posix.h b/components/services/heap_profiling/receiver_pipe_posix.h deleted file mode 100644 index 30f0a2fd..0000000 --- a/components/services/heap_profiling/receiver_pipe_posix.h +++ /dev/null
@@ -1,41 +0,0 @@ -// 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. - -#ifndef COMPONENTS_SERVICES_HEAP_PROFILING_RECEIVER_PIPE_POSIX_H_ -#define COMPONENTS_SERVICES_HEAP_PROFILING_RECEIVER_PIPE_POSIX_H_ - -#include <string> - -#include "base/files/platform_file.h" -#include "base/macros.h" -#include "base/message_loop/message_pump_for_io.h" -#include "build/build_config.h" -#include "components/services/heap_profiling/receiver_pipe.h" - -namespace heap_profiling { - -class ReceiverPipe : public ReceiverPipeBase, - public base::MessagePumpForIO::FdWatcher { - public: - explicit ReceiverPipe(mojo::PlatformHandle handle); - - // Must be called on the IO thread. - void StartReadingOnIOThread(); - - private: - ~ReceiverPipe() override; - - // MessagePumpForIO::FdWatcher implementation. - void OnFileCanReadWithoutBlocking(int fd) override; - void OnFileCanWriteWithoutBlocking(int fd) override; - - base::MessagePumpForIO::FdWatchController controller_; - std::unique_ptr<char[]> read_buffer_; - - DISALLOW_COPY_AND_ASSIGN(ReceiverPipe); -}; - -} // namespace heap_profiling - -#endif // COMPONENTS_SERVICES_HEAP_PROFILING_RECEIVER_PIPE_POSIX_H_
diff --git a/components/services/heap_profiling/receiver_pipe_win.cc b/components/services/heap_profiling/receiver_pipe_win.cc deleted file mode 100644 index d2945bdd..0000000 --- a/components/services/heap_profiling/receiver_pipe_win.cc +++ /dev/null
@@ -1,85 +0,0 @@ -// 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. - -#include "components/services/heap_profiling/receiver_pipe_win.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/message_loop/message_loop_current.h" -#include "base/strings/string16.h" -#include "base/strings/utf_string_conversions.h" -#include "base/threading/thread.h" -#include "components/services/heap_profiling/public/cpp/sender_pipe.h" -#include "components/services/heap_profiling/receiver_pipe.h" -#include "components/services/heap_profiling/stream_receiver.h" - -namespace heap_profiling { - -ReceiverPipe::ReceiverPipe(mojo::PlatformHandle handle) - : ReceiverPipeBase(std::move(handle)), - read_buffer_(new char[SenderPipe::kPipeSize]) { - ZeroOverlapped(); -} - -ReceiverPipe::~ReceiverPipe() = default; - -void ReceiverPipe::StartReadingOnIOThread() { - base::MessageLoopCurrentForIO::Get()->RegisterIOHandler( - handle_.GetHandle().Get(), this); - ReadUntilBlocking(); -} - -void ReceiverPipe::ReadUntilBlocking() { - // TODO(brettw) note that the IO completion callback will always be issued, - // even for sync returns of ReadFile. If there is a lot of data ready to be - // read, it would be nice to process them all in this loop rather than having - // to go back to the message loop for each block, but that will require - // different IOContext structures for each one. - DWORD bytes_read = 0; - ZeroOverlapped(); - - DCHECK(!read_outstanding_); - read_outstanding_ = this; - if (!::ReadFile(handle_.GetHandle().Get(), read_buffer_.get(), - SenderPipe::kPipeSize, &bytes_read, &context_.overlapped)) { - if (GetLastError() == ERROR_IO_PENDING) { - return; - } else { - if (receiver_) { - receiver_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&StreamReceiver::OnStreamComplete, receiver_)); - } - return; - } - } -} - -void ReceiverPipe::ZeroOverlapped() { - memset(&context_.overlapped, 0, sizeof(OVERLAPPED)); -} - -void ReceiverPipe::OnIOCompleted(base::MessagePumpForIO::IOContext* context, - DWORD bytes_transfered, - DWORD error) { - // Note: any crashes with this on the stack are likely a result of destroying - // a relevant class while there is I/O pending. - DCHECK(read_outstanding_); - // Clear |read_outstanding_| but retain the reference to keep ourself alive - // until this function returns. - scoped_refptr<ReceiverPipe> self(std::move(read_outstanding_)); - - if (bytes_transfered && receiver_) { - receiver_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&ReceiverPipe::OnStreamDataThunk, this, - base::MessageLoopCurrent::Get()->task_runner(), - std::move(read_buffer_), - static_cast<size_t>(bytes_transfered))); - read_buffer_.reset(new char[SenderPipe::kPipeSize]); - } - ReadUntilBlocking(); -} - -} // namespace heap_profiling
diff --git a/components/services/heap_profiling/receiver_pipe_win.h b/components/services/heap_profiling/receiver_pipe_win.h deleted file mode 100644 index 603f603..0000000 --- a/components/services/heap_profiling/receiver_pipe_win.h +++ /dev/null
@@ -1,53 +0,0 @@ -// 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. - -#ifndef COMPONENTS_SERVICES_HEAP_PROFILING_RECEIVER_PIPE_WIN_H_ -#define COMPONENTS_SERVICES_HEAP_PROFILING_RECEIVER_PIPE_WIN_H_ - -#include <windows.h> - -#include <string> - -#include "base/files/platform_file.h" -#include "base/macros.h" -#include "base/message_loop/message_pump_win.h" -#include "base/strings/string16.h" -#include "build/build_config.h" -#include "components/services/heap_profiling/receiver_pipe.h" - -namespace heap_profiling { - -class ReceiverPipe : public ReceiverPipeBase, - public base::MessagePumpForIO::IOHandler { - public: - explicit ReceiverPipe(mojo::PlatformHandle handle); - - // Must be called on the IO thread. - void StartReadingOnIOThread(); - - private: - ~ReceiverPipe() override; - - void ReadUntilBlocking(); - void ZeroOverlapped(); - - // IOHandler implementation. - void OnIOCompleted(base::MessagePumpForIO::IOContext* context, - DWORD bytes_transfered, - DWORD error) override; - - base::MessagePumpForIO::IOContext context_; - - // Used to keep |this| live while awaiting IO completion, which is required - // to avoid premature destruction during shutdown. - scoped_refptr<ReceiverPipe> read_outstanding_; - - std::unique_ptr<char[]> read_buffer_; - - DISALLOW_COPY_AND_ASSIGN(ReceiverPipe); -}; - -} // namespace heap_profiling - -#endif // COMPONENTS_SERVICES_HEAP_PROFILING_RECEIVER_PIPE_WIN_H_
diff --git a/components/services/heap_profiling/stream_fuzzer.cc b/components/services/heap_profiling/stream_fuzzer.cc deleted file mode 100644 index cf73ca9a..0000000 --- a/components/services/heap_profiling/stream_fuzzer.cc +++ /dev/null
@@ -1,49 +0,0 @@ -// 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. - -#include "base/logging.h" -#include "components/services/heap_profiling/receiver.h" -#include "components/services/heap_profiling/stream_parser.h" - -#include <utility> - -struct Environment { - Environment() { - // Disable noisy logging as per "libFuzzer in Chrome" documentation: - // testing/libfuzzer/getting_started.md#Disable-noisy-error-message-logging. - logging::SetMinLogLevel(logging::LOG_FATAL); - } -}; - -namespace heap_profiling { -namespace { - -class DummyReceiver : public Receiver { - void OnHeader(const StreamHeader& header) override {} - void OnAlloc(const AllocPacket& alloc_packet, - std::vector<Address>&& stack, - std::string&& context) override {} - void OnFree(const FreePacket& free_packet) override {} - void OnBarrier(const BarrierPacket& barrier_packet) override {} - void OnComplete() override {} - void OnStringMapping(const StringMappingPacket& string_mapping_packet, - const std::string& str) override {} -}; - -} // namespace -} // namespace heap_profiling - -// Entry point for LibFuzzer. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - // Initialize environment once. - static Environment env; - - heap_profiling::DummyReceiver receiver; - scoped_refptr<heap_profiling::StreamParser> parser( - new heap_profiling::StreamParser(&receiver)); - std::unique_ptr<char[]> stream_data(new char[size]); - memcpy(stream_data.get(), data, size); - parser->OnStreamData(std::move(stream_data), size); - return 0; -}
diff --git a/components/services/heap_profiling/stream_fuzzer.dict b/components/services/heap_profiling/stream_fuzzer.dict deleted file mode 100644 index 7accea7..0000000 --- a/components/services/heap_profiling/stream_fuzzer.dict +++ /dev/null
@@ -1,6 +0,0 @@ -# These values are obtained from components/services/heap_profiling/stream.h. -stream_signature="\xF6\x10\x3B\x71" -alloc_packet="\xF6\x10\x3B\x72" -free_packet="\xF6\x10\x3B\x73" -barrier_packet="\xF6\x10\x3B\x74" -string_mapping_packet="\xF6\x10\x3B\x75"
diff --git a/components/services/heap_profiling/stream_parser.cc b/components/services/heap_profiling/stream_parser.cc deleted file mode 100644 index 9fc8a427..0000000 --- a/components/services/heap_profiling/stream_parser.cc +++ /dev/null
@@ -1,243 +0,0 @@ -// 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. - -#include "components/services/heap_profiling/stream_parser.h" - -#include <algorithm> - -#include "base/containers/stack_container.h" -#include "base/strings/stringprintf.h" -#include "components/services/heap_profiling/address.h" -#include "components/services/heap_profiling/backtrace.h" -#include "components/services/heap_profiling/public/cpp/stream.h" - -namespace heap_profiling { - -StreamParser::Block::Block(std::unique_ptr<char[]> d, size_t s) - : data(std::move(d)), size(s) {} - -StreamParser::Block::Block(Block&& other) noexcept = default; - -StreamParser::Block::~Block() = default; - -StreamParser::StreamParser(Receiver* receiver) : receiver_(receiver) {} - -StreamParser::~StreamParser() {} - -void StreamParser::DisconnectReceivers() { - base::AutoLock lock(lock_); - receiver_ = nullptr; -} - -bool StreamParser::OnStreamData(std::unique_ptr<char[]> data, size_t sz) { - base::AutoLock l(lock_); - if (!receiver_ || error_) - return false; - - blocks_.emplace_back(std::move(data), sz); - - if (!received_header_) { - ReadStatus status = ParseHeader(); - if (status == READ_NO_DATA) - return true; // Wait for more data. - if (status == READ_ERROR) { - SetErrorState(); - return false; - } - received_header_ = true; - } - - while (true) { - uint32_t msg_type; - if (!PeekBytes(sizeof(msg_type), &msg_type)) - return true; // Not enough data for a message type field. - - ReadStatus status; - switch (msg_type) { - case kAllocPacketType: - status = ParseAlloc(); - break; - case kFreePacketType: - status = ParseFree(); - break; - case kBarrierPacketType: - status = ParseBarrier(); - break; - case kStringMappingPacketType: - status = ParseStringMapping(); - break; - default: - // Invalid message type. - status = READ_ERROR; - break; - } - - if (status == READ_NO_DATA) - return true; // Wait for more data. - if (status == READ_ERROR) { - SetErrorState(); - return false; - } - // Success, loop around for more data. - } -} - -void StreamParser::OnStreamComplete() { - base::AutoLock l(lock_); - if (receiver_) - receiver_->OnComplete(); -} - -bool StreamParser::AreBytesAvailable(size_t count) const { - size_t used = 0; - size_t current_block_offset = block_zero_offset_; - for (auto it = blocks_.begin(); it != blocks_.end() && used < count; ++it) { - used += it->size - current_block_offset; - current_block_offset = 0; - } - return used >= count; -} - -bool StreamParser::PeekBytes(size_t count, void* dest) const { - char* dest_char = static_cast<char*>(dest); - size_t used = 0; - - size_t current_block_offset = block_zero_offset_; - for (const auto& block : blocks_) { - size_t in_current_block = block.size - current_block_offset; - size_t to_copy = std::min(count - used, in_current_block); - - memcpy(&dest_char[used], &block.data[current_block_offset], to_copy); - used += to_copy; - - // All subsequent blocks start reading at offset 0. - current_block_offset = 0; - } - return used == count; -} - -bool StreamParser::ReadBytes(size_t count, void* dest) { - if (!PeekBytes(count, dest)) - return false; - ConsumeBytes(count); - return true; -} - -void StreamParser::ConsumeBytes(size_t count) { - DCHECK(AreBytesAvailable(count)); - while (count > 0) { - size_t bytes_left_in_block = blocks_.front().size - block_zero_offset_; - if (bytes_left_in_block > count) { - // Still data left in this block; - block_zero_offset_ += count; - return; - } - - // Current block is consumed. - blocks_.pop_front(); - block_zero_offset_ = 0; - count -= bytes_left_in_block; - } -} - -StreamParser::ReadStatus StreamParser::ParseHeader() { - StreamHeader header; - if (!ReadBytes(sizeof(StreamHeader), &header)) - return READ_NO_DATA; - - if (header.signature != kStreamSignature) { - return READ_ERROR; - } - - receiver_->OnHeader(header); - return READ_OK; -} - -StreamParser::ReadStatus StreamParser::ParseAlloc() { - // Read the packet. Can't commit the read until the stack is read and - // that has to be done below. - AllocPacket alloc_packet; - if (!PeekBytes(sizeof(AllocPacket), &alloc_packet)) - return READ_NO_DATA; - - // Validate data. - if (alloc_packet.stack_len > kMaxStackEntries || - alloc_packet.context_byte_len > kMaxContextLen || - alloc_packet.allocator >= AllocatorType::kCount) { - return READ_ERROR; - } - - std::vector<Address> stack; - stack.resize(alloc_packet.stack_len); - size_t stack_byte_size = sizeof(Address) * alloc_packet.stack_len; - - if (!AreBytesAvailable(sizeof(AllocPacket) + stack_byte_size + - alloc_packet.context_byte_len)) - return READ_NO_DATA; - - // Everything will fit, mark header consumed. - ConsumeBytes(sizeof(AllocPacket)); - - // Read stack. - if (!stack.empty()) - ReadBytes(stack_byte_size, stack.data()); - - // Read context. - std::string context; - context.resize(alloc_packet.context_byte_len); - if (alloc_packet.context_byte_len) - ReadBytes(alloc_packet.context_byte_len, &context[0]); - - receiver_->OnAlloc(alloc_packet, std::move(stack), std::move(context)); - return READ_OK; -} - -StreamParser::ReadStatus StreamParser::ParseFree() { - FreePacket free_packet; - if (!ReadBytes(sizeof(FreePacket), &free_packet)) - return READ_NO_DATA; - - receiver_->OnFree(free_packet); - return READ_OK; -} - -StreamParser::ReadStatus StreamParser::ParseBarrier() { - BarrierPacket barrier_packet; - if (!ReadBytes(sizeof(BarrierPacket), &barrier_packet)) - return READ_NO_DATA; - - receiver_->OnBarrier(barrier_packet); - return READ_OK; -} - -StreamParser::ReadStatus StreamParser::ParseStringMapping() { - StringMappingPacket string_mapping_packet; - if (!PeekBytes(sizeof(StringMappingPacket), &string_mapping_packet)) - return READ_NO_DATA; - - if (!AreBytesAvailable(sizeof(StringMappingPacket) + - string_mapping_packet.string_len)) - return READ_NO_DATA; - - // Everything will fit, mark header consumed. - ConsumeBytes(sizeof(StringMappingPacket)); - - // Treat the incoming characters as an opaque blob. It should not contain null - // characters but a malicious attacker could change that. - std::string str; - - str.resize(string_mapping_packet.string_len); - ReadBytes(string_mapping_packet.string_len, &str[0]); - - receiver_->OnStringMapping(string_mapping_packet, str); - return READ_OK; -} - -void StreamParser::SetErrorState() { - LOG(ERROR) << "StreamParser parsing error"; - error_ = true; - receiver_->OnComplete(); -} - -} // namespace heap_profiling
diff --git a/components/services/heap_profiling/stream_parser.h b/components/services/heap_profiling/stream_parser.h deleted file mode 100644 index 8438b6d..0000000 --- a/components/services/heap_profiling/stream_parser.h +++ /dev/null
@@ -1,92 +0,0 @@ -// 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. - -#ifndef COMPONENTS_SERVICES_HEAP_PROFILING_STREAM_PARSER_H_ -#define COMPONENTS_SERVICES_HEAP_PROFILING_STREAM_PARSER_H_ - -#include "base/callback.h" -#include "base/containers/circular_deque.h" -#include "base/macros.h" -#include "base/synchronization/lock.h" -#include "components/services/heap_profiling/receiver.h" -#include "components/services/heap_profiling/stream_receiver.h" - -namespace heap_profiling { - -// Parses a memory stream. Refcounted via StreamReceiver. -class StreamParser : public StreamReceiver { - public: - // Both receivers must either outlive this class or live until - // DisconnectReceivers is called. - explicit StreamParser(Receiver* receiver); - - // For tear-down, resets both receivers so they will not be called. - void DisconnectReceivers(); - - // StreamReceiver implementation. - bool OnStreamData(std::unique_ptr<char[]> data, size_t sz) override; - void OnStreamComplete() override; - - base::Lock* GetLock() { return &lock_; } - - // Returns true if this stream has encountered a fatal parse error. - bool has_error() const { return error_; } - - private: - struct Block { - Block(std::unique_ptr<char[]> d, size_t s); - Block(Block&& other) noexcept; - ~Block(); - - std::unique_ptr<char[]> data; - size_t size; - }; - - enum ReadStatus { - READ_OK, // Read OK. - READ_ERROR, // Fatal error, don't send more data. - READ_NO_DATA // Not enough data, try again when we get more - }; - - ~StreamParser() override; - - // Returns true if the given number of bytes are available now. - bool AreBytesAvailable(size_t count) const; - - // Returns false if not enough bytes are available. On failure, the dest - // buffer will be in an undefined state (it may be written partially). - bool PeekBytes(size_t count, void* dest) const; - bool ReadBytes(size_t count, void* dest); - void ConsumeBytes(size_t count); // Bytes must be available. - - ReadStatus ParseHeader(); - ReadStatus ParseAlloc(); - ReadStatus ParseFree(); - ReadStatus ParseBarrier(); - ReadStatus ParseStringMapping(); - - void SetErrorState(); - - // Not owned by this class. - Receiver* receiver_; - - base::circular_deque<Block> blocks_; - - bool received_header_ = false; - bool error_ = false; - - // Current offset into blocks_[0] of the next packet to process. - size_t block_zero_offset_ = 0; - - // This lock must be acquired anytime the stream is being parsed. This - // prevents concurrent access to data structures used by both the parser and - // the memory dumper. - base::Lock lock_; - - DISALLOW_COPY_AND_ASSIGN(StreamParser); -}; - -} // namespace heap_profiling - -#endif // COMPONENTS_SERVICES_HEAP_PROFILING_STREAM_PARSER_H_
diff --git a/components/services/heap_profiling/stream_parser_unittest.cc b/components/services/heap_profiling/stream_parser_unittest.cc deleted file mode 100644 index e2e7f7d..0000000 --- a/components/services/heap_profiling/stream_parser_unittest.cc +++ /dev/null
@@ -1,272 +0,0 @@ -// 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. - -#include "components/services/heap_profiling/stream_parser.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace heap_profiling { - -namespace { - -void SendData(const scoped_refptr<StreamParser>& parser, - const void* data, - size_t size) { - std::unique_ptr<char[]> heap(new char[size]); - memcpy(heap.get(), data, size); - parser->OnStreamData(std::move(heap), size); -} - -void SendHeader(scoped_refptr<StreamParser>& parser) { - StreamHeader header; - SendData(parser, &header, sizeof(StreamHeader)); -} - -class TestReceiver : public Receiver { - public: - TestReceiver() { - // Make our saved header invalid so we can't confuse the locally - // initialized one with a valid one that's received. - header_.signature = 0; - last_barrier_.barrier_id = - std::numeric_limits<decltype(last_barrier_.barrier_id)>::max(); - } - - bool got_header() const { return got_header_; } - const StreamHeader& header() const { return header_; } - void OnHeader(const StreamHeader& header) override { - ASSERT_FALSE(got_header_); // Don't expect more than one. - got_header_ = true; - header_ = header; - } - - int alloc_count() const { return alloc_count_; } - const AllocPacket& last_alloc() const { return last_alloc_; } - const std::vector<Address>& last_alloc_stack() const { - return last_alloc_stack_; - } - const std::string& last_alloc_context() const { return last_alloc_context_; } - void OnAlloc(const AllocPacket& alloc_packet, - std::vector<Address>&& stack, - std::string&& context) override { - alloc_count_++; - last_alloc_ = alloc_packet; - last_alloc_stack_ = std::move(stack); - last_alloc_context_ = std::move(context); - } - - int free_count() const { return free_count_; } - const FreePacket& last_free() const { return last_free_; } - void OnFree(const FreePacket& free_packet) override { - free_count_++; - last_free_ = free_packet; - } - - int barrier_count() const { return barrier_count_; } - const BarrierPacket& last_barrier() const { return last_barrier_; } - void OnBarrier(const BarrierPacket& barrier) override { - barrier_count_++; - last_barrier_.barrier_id = barrier.barrier_id; - } - - int string_mapping_count() const { return string_mapping_count_; } - const StringMappingPacket& last_string_mapping() const { - return last_string_mapping_; - } - const char* last_raw_string() const { return last_raw_string_.c_str(); } - - void OnStringMapping(const StringMappingPacket& string_mapping, - const std::string& str) override { - string_mapping_count_++; - memcpy(&last_string_mapping_, &string_mapping, sizeof(StringMappingPacket)); - last_raw_string_ = str; - } - - bool got_complete() const { return got_complete_; } - void OnComplete() override { - ASSERT_FALSE(got_complete_); // Don't expect more than one. - got_complete_ = true; - } - - private: - bool got_header_ = false; - StreamHeader header_; - - int alloc_count_ = 0; - AllocPacket last_alloc_; - std::vector<Address> last_alloc_stack_; - std::string last_alloc_context_; - - int free_count_ = 0; - FreePacket last_free_; - - int barrier_count_ = 0; - BarrierPacket last_barrier_; - - int string_mapping_count_ = 0; - StringMappingPacket last_string_mapping_; - std::string last_raw_string_; - - bool got_complete_ = false; -}; - -} // namespace - -TEST(StreamParser, NormalHeader) { - TestReceiver receiver; - scoped_refptr<StreamParser> parser(new StreamParser(&receiver)); - - // Should work to send in two packets. - StreamHeader header; - size_t first_size = sizeof(StreamHeader) / 2; - SendData(parser, &header, first_size); - EXPECT_FALSE(receiver.got_header()); - SendData(parser, &reinterpret_cast<char*>(&header)[first_size], - sizeof(StreamHeader) - first_size); - EXPECT_TRUE(receiver.got_header()); - EXPECT_FALSE(receiver.got_complete()); - - parser->OnStreamComplete(); - EXPECT_TRUE(receiver.got_complete()); -} - -TEST(StreamParser, BadHeader) { - TestReceiver receiver; - scoped_refptr<StreamParser> parser(new StreamParser(&receiver)); - - StreamHeader header; - header.signature = 15; - SendData(parser, &header, sizeof(StreamHeader)); - EXPECT_FALSE(receiver.got_header()); - EXPECT_TRUE(receiver.got_complete()); - EXPECT_TRUE(parser->has_error()); -} - -TEST(StreamParser, GoodAlloc) { - TestReceiver receiver; - scoped_refptr<StreamParser> parser(new StreamParser(&receiver)); - SendHeader(parser); - - constexpr size_t kStackSize = 4; - uint64_t stack[kStackSize] = {0x1, 0x2, 0x3, 0x4}; - - std::string context("hello"); - - AllocPacket alloc; - alloc.allocator = AllocatorType::kMalloc; - alloc.address = 0x87654321; - alloc.size = 128; - alloc.stack_len = kStackSize; - alloc.context_byte_len = static_cast<uint32_t>(context.size()); - - SendData(parser, &alloc, sizeof(AllocPacket)); - EXPECT_EQ(0, receiver.alloc_count()); - SendData(parser, stack, sizeof(uint64_t) * kStackSize); - ASSERT_EQ(0, receiver.alloc_count()); - SendData(parser, context.data(), context.size()); - ASSERT_EQ(1, receiver.alloc_count()); - - EXPECT_EQ(alloc.allocator, receiver.last_alloc().allocator); - EXPECT_EQ(alloc.address, receiver.last_alloc().address); - EXPECT_EQ(alloc.size, receiver.last_alloc().size); - EXPECT_EQ(alloc.stack_len, receiver.last_alloc().stack_len); - EXPECT_EQ(context, receiver.last_alloc_context()); - - ASSERT_EQ(4u, receiver.last_alloc_stack().size()); - EXPECT_EQ(stack[0], receiver.last_alloc_stack()[0].value); - EXPECT_EQ(stack[1], receiver.last_alloc_stack()[1].value); - EXPECT_EQ(stack[2], receiver.last_alloc_stack()[2].value); - EXPECT_EQ(stack[3], receiver.last_alloc_stack()[3].value); -} - -TEST(StreamParser, AllocBigStack) { - TestReceiver receiver; - scoped_refptr<StreamParser> parser(new StreamParser(&receiver)); - SendHeader(parser); - - AllocPacket alloc; - alloc.allocator = AllocatorType::kMalloc; - alloc.address = 0x87654321; - alloc.size = 128; - alloc.stack_len = 10000; // Too large a stack. - alloc.context_byte_len = 0; - - SendData(parser, &alloc, sizeof(AllocPacket)); - - // Even though no stack was sent, the alloc header with the too-large stack - // should have triggered an error. - EXPECT_EQ(0, receiver.alloc_count()); - EXPECT_TRUE(receiver.got_complete()); -} - -TEST(StreamParser, AllocBigContext) { - TestReceiver receiver; - scoped_refptr<StreamParser> parser(new StreamParser(&receiver)); - SendHeader(parser); - - AllocPacket alloc; - alloc.allocator = AllocatorType::kMalloc; - alloc.address = 0x87654321; - alloc.size = 128; - alloc.stack_len = 0; // Too large a stack. - alloc.context_byte_len = 10000; - - SendData(parser, &alloc, sizeof(AllocPacket)); - - // Even though no stack or context was sent, the alloc header with the - // too-large stack should have triggered an error. - EXPECT_EQ(0, receiver.alloc_count()); - EXPECT_TRUE(receiver.got_complete()); -} - -TEST(StreamParser, GoodFree) { - TestReceiver receiver; - scoped_refptr<StreamParser> parser(new StreamParser(&receiver)); - SendHeader(parser); - - FreePacket fr; - fr.address = 0x87654321; - - SendData(parser, &fr, sizeof(FreePacket)); - EXPECT_EQ(1, receiver.free_count()); - - EXPECT_EQ(fr.address, receiver.last_free().address); -} - -TEST(StreamParser, Barrier) { - TestReceiver receiver; - scoped_refptr<StreamParser> parser(new StreamParser(&receiver)); - SendHeader(parser); - - constexpr uint32_t barrier_id = 0x12345678; - - BarrierPacket b; - b.barrier_id = barrier_id; - - SendData(parser, &b, sizeof(BarrierPacket)); - EXPECT_EQ(1, receiver.barrier_count()); - - EXPECT_EQ(barrier_id, receiver.last_barrier().barrier_id); -} - -TEST(StreamParser, StringMapping) { - TestReceiver receiver; - scoped_refptr<StreamParser> parser(new StreamParser(&receiver)); - SendHeader(parser); - - const std::string kDummyText = "kDummyText"; - - StringMappingPacket p; - p.address = 0x1234; - p.string_len = static_cast<uint32_t>(kDummyText.size()); - SendData(parser, &p, sizeof(StringMappingPacket)); - SendData(parser, kDummyText.data(), kDummyText.size()); - - EXPECT_EQ(1, receiver.string_mapping_count()); - EXPECT_EQ(p.address, receiver.last_string_mapping().address); - EXPECT_EQ(p.string_len, receiver.last_string_mapping().string_len); - EXPECT_EQ(kDummyText, receiver.last_raw_string()); -} - -} // namespace heap_profiling
diff --git a/components/services/heap_profiling/stream_receiver.h b/components/services/heap_profiling/stream_receiver.h deleted file mode 100644 index 4c511eb..0000000 --- a/components/services/heap_profiling/stream_receiver.h +++ /dev/null
@@ -1,35 +0,0 @@ -// 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. - -#ifndef COMPONENTS_SERVICES_HEAP_PROFILING_STREAM_RECEIVER_H_ -#define COMPONENTS_SERVICES_HEAP_PROFILING_STREAM_RECEIVER_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" - -namespace heap_profiling { - -// A stream receiver is a sink for unparsed bytes. See also LogReceiver. -class StreamReceiver : public base::RefCountedThreadSafe<StreamReceiver> { - public: - StreamReceiver() {} - - // Returns true on success, false on unrecoverable error. The implementation - // should be able to handle calls after an error has been reported (some - // cross-thread calls may have been dispatched before the flag propagates). - virtual bool OnStreamData(std::unique_ptr<char[]> data, size_t sz) = 0; - - // Indicates the connection has been closed. - virtual void OnStreamComplete() = 0; - - protected: - friend class base::RefCountedThreadSafe<StreamReceiver>; - virtual ~StreamReceiver() {} -}; - -} // namespace heap_profiling - -#endif // COMPONENTS_SERVICES_HEAP_PROFILING_STREAM_RECEIVER_H_
diff --git a/components/test/data/autofill/heuristics/input/017_checkout_advanceautoparts.com.html b/components/test/data/autofill/heuristics/input/017_checkout_advanceautoparts.com.html index cf51d6b4..627dffc 100644 --- a/components/test/data/autofill/heuristics/input/017_checkout_advanceautoparts.com.html +++ b/components/test/data/autofill/heuristics/input/017_checkout_advanceautoparts.com.html
@@ -11,16 +11,16 @@ - + <!-- Start LivePersonTagConfig.jspf --> -<!-- End LivePersonTagConfig.jspf --> +<!-- End LivePersonTagConfig.jspf --> </head> <body> -<h3>Returning Customer</h3> +<h3>Returning Customer</h3> <form name="logonForm" method="post" action="/webapp/wcs/stores/servlet/BillShipLogon"> <input type="hidden" name="action" value="login"> <input type="hidden" name="storeId" value="10151"> @@ -33,12 +33,12 @@ <tr> <th><label>Email Address:</label></th> <td colspan="2"> - <input type="text" name="logonId" id="logonId" size="30" value="" tabindex="1" autocomplete="off" /></td> + <input type="text" name="logonId" id="logonId" size="30" value="" tabindex="1" /></td> </tr> <tr> <th><label>Password:</label></th> <td> - <input type="password" name="logonPassword" id="logonPassword" size="20" tabindex="2" autocomplete="off" /></td> + <input type="password" name="logonPassword" id="logonPassword" size="20" tabindex="2" /></td> <td><a href="https://shop.advanceautoparts.com/webapp/wcs/stores/servlet/ForgotPasswordView?storeId=10151&catalogId=10051&langId=-1&userType=G&userState=&userId=69626587" class="small-red" tabindex="3">I forgot my password</a></td> </tr> <tr> @@ -74,9 +74,9 @@ <input type="hidden" name="shipDayPhone" value=""> <input type="hidden" name="shipNightPhone" value=""> <input type="hidden" name="shippingMode" value="40501"> -<!-- Guest user and page loaded for the first time. --> +<!-- Guest user and page loaded for the first time. --> <input type="hidden" name="billAddressId" value=""> -<input type="hidden" name="shipAddressId" value=""> +<input type="hidden" name="shipAddressId" value=""> <table cellpadding="0" cellspacing="0" width="100%" style="padding:0 20px;"> <tr> <td valign="top" width="49%" id="bill-form"> @@ -87,9 +87,9 @@ Make shipping the same as my billing address </p> <h4>Use form below for your billing address:</h4> -<table cellpadding="2" cellspacing="0"> +<table cellpadding="2" cellspacing="0"> <tr> -<th class="required-text">* required fields</th> +<th class="required-text">* required fields</th> </tr> <tr> <th><span class="required-text">*</span>First Name:</th> @@ -118,7 +118,7 @@ </tr> <tr> <th></th> -<td>(Military Customers, enter APO/FPO/DPO for city)</td> +<td>(Military Customers, enter APO/FPO/DPO for city)</td> </tr> <input type="hidden" name="billCountry" value="US"> <tr> @@ -238,7 +238,7 @@ <h4>Add a new shipping address:</h4> <table> <tr> -<th class="required-text">* required fields</th> +<th class="required-text">* required fields</th> </tr> <tr> <th>*First Name:</th> @@ -342,12 +342,12 @@ <tr> <th>*Day Phone:</th> <td>(<input type="text" name="shipDayPhonePart1" maxlength="3" size="3" tabindex="124" value="" title="shipDayPhonePart1">)<input type="text" name="shipDayPhonePart2" maxlength="3" size="3" tabindex="125" value="" title="shipDayPhonePart2"> - <input type="text" name="shipDayPhonePart3" maxlength="4" size="4" tabindex="126" value="" title="shipDayPhonePart3"></td> + <input type="text" name="shipDayPhonePart3" maxlength="4" size="4" tabindex="126" value="" title="shipDayPhonePart3"></td> </tr> <tr> <th>Night Phone:</th> <td>(<input type="text" name="shipNightPhonePart1" maxlength="3" size="3" tabindex="127" value="" title="shipNightPhonePart1">)<input type="text" name="shipNightPhonePart2" maxlength="3" size="3" tabindex="128" value="" title="shipNightPhonePart2"> - <input type="text" name="shipNightPhonePart3" maxlength="4" size="4" tabindex="129" value="" title="shipNightPhonePart3"></td> + <input type="text" name="shipNightPhonePart3" maxlength="4" size="4" tabindex="129" value="" title="shipNightPhonePart3"></td> </tr> </table> </div> @@ -356,7 +356,7 @@ When the shipping address is different from the billing address, your order may be subject to further verification delays. For questions regarding billing and shipping address please <a href="https://shop.advanceautoparts.com/webapp/wcs/stores/servlet/content_contactus___" target="_blank" tabindex="126"> contact us -</a>. +</a>. </p> </td> </tr> @@ -370,10 +370,10 @@ <td> </td> <td valign="top"> <br/> -<input type="image" src="#" property="submitButton" tabindex="150" value="Continue to Step 2 >>" class="button" id="shipBill"/> +<input type="image" src="#" property="submitButton" tabindex="150" value="Continue to Step 2 >>" class="button" id="shipBill"/> </td> </tr> -</table> +</table> </form>
diff --git a/components/test/data/autofill/heuristics/input/018_checkout_ae.com.html b/components/test/data/autofill/heuristics/input/018_checkout_ae.com.html index be606f5..9f02204 100644 --- a/components/test/data/autofill/heuristics/input/018_checkout_ae.com.html +++ b/components/test/data/autofill/heuristics/input/018_checkout_ae.com.html
@@ -27,7 +27,7 @@ <label for="tl_myAccount_username" class="sm_label">Secure account sign in</label> <input value="Email Address" maxlength="60" type="text" class="in_field js_defaultAsLabel" name="logonUsername" id="tl_myAccount_username"> <input value=" " type="hidden" name="_D:logonUsername"> -<input value="password" autocomplete="off" maxlength="15" type="password" class="in_field js_defaultAsLabel" name="logonPassword" id="tl_myAccount_password"> +<input value="password" maxlength="15" type="password" class="in_field js_defaultAsLabel" name="logonPassword" id="tl_myAccount_password"> <input value=" " type="hidden" name="_D:logonPassword"> <a href="https://www.ae.com/web/myaccount/password_assistance.jsp" id="tl_myAccount_forgot">Forgot Password?</a> <input value="Sign In" type="submit" class="sm_bttn" name="/atg/userprofiling/ProfileFormHandler.login" id="tl_myAccount_submit"> @@ -39,8 +39,8 @@ - - + + <form action="http://www.ae.com/web/storelocator/storeResult.jsp?_DARGS=/web/global/nav/f_nav_findstore.jsp.storelocatorFid" name="storelocator" method="post" id="storelocator"> <input value="UTF-8" type="hidden" name="_dyncharset"> </input> @@ -64,8 +64,8 @@ - - + + <form action="https://www.ae.com/web/wishlist/nav/f_wishlist_access.jsp?_DARGS=/web/global/nav/f_nav_wishlist.jsp.form_wlloginFid" name="TNwishlistloginform" method="post" id="form_wllogin"> <input value="UTF-8" type="hidden" name="_dyncharset"> </input> @@ -80,7 +80,7 @@ <label for="tl_wishlist_email" class="sm_label">Access your wish list</label> <input value="Email" maxlength="60" type="text" class="in_field js_defaultAsLabel" name="username" id="tl_wishlist_email"> <input value=" " type="hidden" name="_D:username"> -<input value="Password" autocomplete="off" type="password" class="in_field js_defaultAsLabel" name="password" id="tl_wishlist_password"> +<input value="Password" type="password" class="in_field js_defaultAsLabel" name="password" id="tl_wishlist_password"> <input value=" " type="hidden" name="_D:password"> <a href="https://www.ae.com/web/myaccount/password_assistance.jsp" id="tl_wishlist_forgot">Forgot Password?</a> <input value="Sign In" type="submit" class="sm_bttn" name="/atg/userprofiling/ProfileFormHandler.login" id="tl_wishlist_submit"> @@ -90,7 +90,7 @@ </form> - + <form action="http://www.ae.com/web/wishlist/search_wishlist.jsp?_DARGS=/web/global/nav/f_nav_wishlist.jsp.form_glsearchFid" name="TNwishlistsearchform" method="post" id="form_glsearch"> <input value="UTF-8" type="hidden" name="_dyncharset"> </input> @@ -497,13 +497,13 @@ </span> </label> <div class="checkoutInputLeft"> -<input type="text" name="giftNumEntry" id="giftNumEntry" class="checkoutInput giftNumEntryField" value="" maxlength="19" autocomplete="off" /> +<input type="text" name="giftNumEntry" id="giftNumEntry" class="checkoutInput giftNumEntryField" value="" maxlength="19" /> </div> </div> <div class="inputLabelHolder"> <label for="pinNumEntry">PIN:</label> <div class="checkoutInputLeft"> -<input type="text" autocomplete="off" name="pinNumEntry" id="pinNumEntry" class="checkoutInput pinNumEntryField" value="" maxlength="4" autocomplete="off" /> +<input type="text" name="pinNumEntry" id="pinNumEntry" class="checkoutInput pinNumEntryField" value="" maxlength="4" /> </div> </div> <input value="Add Card" width="79" type="image" class="addGCbtn" src="#" name="/aeo/commerce/order/checkout/AeoGiftCardPaymentHandler.applyGiftCard" id="applyGiftCardBtn"> @@ -586,7 +586,7 @@ <div id="ccNumberHolderCCField" class="inputLabelHolder"> <label for="ccNumberCCField">Card Number:</label> <div class="checkoutInputLeft"> -<input type="text" name="ccNumber" id="ccNumberCCField" size="30" maxlength="16" value="" class="checkoutInput" autocomplete="off"/> +<input type="text" name="ccNumber" id="ccNumberCCField" size="30" maxlength="16" value="" class="checkoutInput"/> </div> </div> <div id="expDateCCField" class="inputLabelHolder"> @@ -648,7 +648,7 @@ </span> </label> <div class="checkoutInputLeft"> -<input type="text" name="ccSecCode" id="ccSecCodeCCField" size="4" maxlength="4" value="" class="checkoutInput" autocomplete="off"/> +<input type="text" name="ccSecCode" id="ccSecCodeCCField" size="4" maxlength="4" value="" class="checkoutInput"/> </div> </div> </div> @@ -838,7 +838,7 @@ </span> </label> <div class="checkoutInputLeft"> -<input type="text" name="SSN" size="4" maxlength="4" value="" id="SSNBMLField" class="checkoutInput" autocomplete="off" /> +<input type="text" name="SSN" size="4" maxlength="4" value="" id="SSNBMLField" class="checkoutInput" /> </div> </div> <div style="clear:both;"> @@ -1790,7 +1790,7 @@ </span> </label> <div style="float: left;" class="checkoutInputLeft"> -<input value="" autocomplete="off" maxlength="25" type="text" class="checkoutInput" size="25" name="CouponCode" id="discountCodeField"> +<input value="" maxlength="25" type="text" class="checkoutInput" size="25" name="CouponCode" id="discountCodeField"> <input value=" " type="hidden" name="_D:CouponCode"> </div> <div style="float: left;">
diff --git a/components/test/data/autofill/heuristics/input/023_checkout_gamestop.com.html b/components/test/data/autofill/heuristics/input/023_checkout_gamestop.com.html index fc007af77..e6816c0 100644 --- a/components/test/data/autofill/heuristics/input/023_checkout_gamestop.com.html +++ b/components/test/data/autofill/heuristics/input/023_checkout_gamestop.com.html
@@ -21,13 +21,13 @@ </head> <body > - - - - + + + + <div class="baseContent"> - <form name="aspnetForm" method="post" action="/Orders/OrderShippingAddress.aspx?ct=guest" language="javascript" autocomplete="off" id="aspnetForm"> + <form name="aspnetForm" method="post" action="/Orders/OrderShippingAddress.aspx?ct=guest" language="javascript" id="aspnetForm"> <div> <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" /> <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" /> @@ -65,10 +65,10 @@ - - - + + + <div class="wrap"> <div class="site container_24"> <div id="mainHeader" class="header" style="background: #FFFFFF url(/common/css/gamestopdotcom/images/gslogo.png) no-repeat 13px 19px;"> @@ -77,13 +77,13 @@ <div class="toplinks"><a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_lnkStoreLocator" href="/StoreLocator.aspx">Find a Store</a>|<a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_lnkStoreEvents" href="/gs/gamestopevents">Events</a>|<a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_lnkWeeklyAd" href="/weeklyad">Weekly Ad</a>|<a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_lnkGiftCards" href="/Catalog/Gifts.aspx">Gift Cards</a>|<a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_lnkOrderHistory" href="/Profiles/OrderTrackingLogin.aspx">Order History</a>|<a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_lnkWishList" href="/Profiles/WishList.aspx">Wish List</a> </div> <div class="accessbox" id="header_auth_state"> - <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_lblGreeting">Welcome, Guest!</span> - + <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_lblGreeting">Welcome, Guest!</span> + <a href='/Profiles/Login.aspx?ReturnUrl=/Orders/OrderShippingAddress.aspx?ct=guest' id='header_auth_actions' rel='nofollow'>Log In / Register</a> - + </div> <div class="primenav"> - + <a href='/xbox360' id='xbox360_link' class="navLink">Xbox 360</a> <div id='xbox360_mega' class="mega_menu"> <div class="mega_menu_col menu_col_hot" Style="display:inline"> @@ -95,163 +95,163 @@ <div class="mega_menu_col menu_col_genres" Style="display:inline"> <h3>Xbox 360 Games</h3> <ul id="menu_xbox_genres" class="menu_genres"> - + <li> <a href='/browse/xbox-360?nav=1385'> All </a> </li> - + <li> <a href='/browse/xbox-360/3d?nav=1385-1a3'> 3D </a> </li> - + <li> <a href='/browse/xbox-360/action?nav=1385-56'> Action </a> </li> - + <li> <a href='/browse/xbox-360/add-ons?nav=1385-18a'> Add-ons </a> </li> - + <li> <a href='/browse/xbox-360/casual?nav=1385-d4'> Casual </a> </li> - + <li> <a href='/browse/xbox-360/fighting?nav=1385-69'> Fighting </a> </li> - + <li> <a href='/browse/xbox-360/kinect?nav=1385-19d'> Kinect </a> </li> - + <li> <a href='/browse/xbox-360/movies-tv?nav=1385-c6'> Movies & TV </a> </li> - + <li> <a href='/browse/xbox-360/music-party?nav=1385-be'> Music & Party </a> </li> - + <li> <a href='/browse/xbox-360/puzzle-cards?nav=1385-63'> Puzzle & Cards </a> </li> - + <li> <a href='/browse/xbox-360/role-playing?nav=1385-6a'> Role-Playing </a> </li> - + <li> <a href='/browse/xbox-360/shooter?nav=1385-65'> Shooter </a> </li> - + <li> <a href='/browse/xbox-360/simulation?nav=1385-67'> Simulation </a> </li> - + <li> <a href='/browse/xbox-360/sports?nav=1385-66'> Sports </a> </li> - + <li> <a href='/browse/xbox-360/strategy?nav=1385-68'> Strategy </a> </li> - + <li> <a href='/browse/xbox-360/strategy-guides?nav=1385-c8'> Strategy Guides </a> </li> - + </ul> </div> <div class="mega_menu_col menu_col_deals" Style="display:inline"> <div Style="display:inline"> <h3>Xbox 360 Deals</h3> <ul id="menu_xbox_deals" class="menu_deals"> - + <li> <a href='/browse/xbox-360?nav=1385-162'> Price Drop </a> </li> - + <li> <a href='/browse/xbox-360?nav=1385-d3'> Under $20 </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>Shop by ESRB</h3> <ul id="menu_xbox_esrb" class="menu_esrb"> - + <li> <a href='/browse/xbox-360?nav=1385-33' class='mm_everyone'> Everyone </a> </li> - + <li> <a href='/browse/xbox-360?nav=1385-38' class='mm_everyone_plus'> Everyone 10+ </a> </li> - + <li> <a href='/browse/xbox-360?nav=1385-34' class='mm_teen'> Teen </a> </li> - + <li> <a href='/browse/xbox-360?nav=1385-35' class='mm_mature'> Mature </a> </li> - + <li> <a href='/browse/xbox-360?nav=1385-36' class='mm_rating_pending'> Rating Pending </a> </li> - + </ul> </div> </div> @@ -259,79 +259,79 @@ <div Style="display:inline"> <h3>Xbox 360 Hardware</h3> <ul id="menu_xbox_hardware" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/xbox-360/systems?nav=1385-c4'> Game Systems </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>Xbox 360 Accessories</h3> <ul id="menu_xbox_accessories" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/xbox-360/accessories/batteries-chargers?nav=1385-a5'> Batteries & Chargers </a> </li> - + <li> <a href='/browse/xbox-360/accessories/cables-adaptors?nav=1385-73'> Cables & Adaptors </a> </li> - + <li> <a href='/browse/xbox-360/accessories/controllers?nav=1385-74'> Controllers </a> </li> - + <li> <a href='/browse/xbox-360/accessories/cooling-systems?nav=1385-a2'> Cooling Systems </a> </li> - + <li> <a href='/browse/xbox-360/systems?nav=1385-c4'> Game Systems </a> </li> - + <li> <a href='/browse/xbox-360/accessories/headsets-mics?nav=1385-7b'> Headsets & Mics </a> </li> - + <li> <a href='/browse/xbox-360/accessories/memory-cards?nav=1385-75'> Memory Cards </a> </li> - + <li> <a href='/browse/xbox-360/accessories/repair-cleaning?nav=1385-a6'> Repair & Cleaning </a> </li> - + <li> <a href='/browse/xbox-360/accessories/storage-cases?nav=1385-77'> Storage & Cases </a> </li> - + </ul> </div> <a href='/browse/xbox-360?nav=1385' class="menu_see_all">See All Xbox 360 →</a> </div> </div> - + <a href='/ps3' id='ps3_link' class="navLink">PS3</a> <div id='ps3_mega' class="mega_menu"> <div class="mega_menu_col menu_col_hot" Style="display:inline"> @@ -343,163 +343,163 @@ <div class="mega_menu_col menu_col_genres" Style="display:inline"> <h3>PlayStation 3 Games</h3> <ul id="menu_xbox_genres" class="menu_genres"> - + <li> <a href='/browse/playstation-3?nav=138d'> All </a> </li> - + <li> <a href='/browse/playstation-3/3d?nav=138d-1a3'> 3D </a> </li> - + <li> <a href='/browse/playstation-3/action?nav=138d-56'> Action </a> </li> - + <li> <a href='/browse/playstation-3/add-ons?nav=138d-18a'> Add-ons </a> </li> - + <li> <a href='/browse/playstation-3/casual?nav=138d-d4'> Casual </a> </li> - + <li> <a href='/browse/playstation-3/fighting?nav=138d-69'> Fighting </a> </li> - + <li> <a href='/browse/playstation-3/move?nav=138d-19e'> Move </a> </li> - + <li> <a href='/browse/playstation-3/movies-tv?nav=138d-c6'> Movies & TV </a> </li> - + <li> <a href='/browse/playstation-3/music-party?nav=138d-be'> Music & Party </a> </li> - + <li> <a href='/browse/playstation-3/puzzle-cards?nav=138d-63'> Puzzle & Cards </a> </li> - + <li> <a href='/browse/playstation-3/role-playing?nav=138d-6a'> Role-Playing </a> </li> - + <li> <a href='/browse/playstation-3/shooter?nav=138d-65'> Shooter </a> </li> - + <li> <a href='/browse/playstation-3/simulation?nav=138d-67'> Simulation </a> </li> - + <li> <a href='/browse/playstation-3/sports?nav=138d-66'> Sports </a> </li> - + <li> <a href='/browse/playstation-3/strategy?nav=138d-68'> Strategy </a> </li> - + <li> <a href='/browse/playstation-3/strategy-guides?nav=138d-c8'> Strategy Guides </a> </li> - + </ul> </div> <div class="mega_menu_col menu_col_deals" Style="display:inline"> <div Style="display:inline"> <h3>PlayStation 3 Deals</h3> <ul id="menu_xbox_deals" class="menu_deals"> - + <li> <a href='/browse/playstation-3?nav=138d-162'> Price Drop </a> </li> - + <li> <a href='/browse/playstation-3?nav=138d-d3'> Under $20 </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>Shop by ESRB</h3> <ul id="menu_xbox_esrb" class="menu_esrb"> - + <li> <a href='/browse/playstation-3?nav=138d-33' class='mm_everyone'> Everyone </a> </li> - + <li> <a href='/browse/playstation-3?nav=138d-38' class='mm_everyone_plus'> Everyone 10+ </a> </li> - + <li> <a href='/browse/playstation-3?nav=138d-34' class='mm_teen'> Teen </a> </li> - + <li> <a href='/browse/playstation-3?nav=138d-35' class='mm_mature'> Mature </a> </li> - + <li> <a href='/browse/playstation-3?nav=138d-36' class='mm_rating_pending'> Rating Pending </a> </li> - + </ul> </div> </div> @@ -507,91 +507,91 @@ <div Style="display:inline"> <h3>PlayStation 3 Hardware</h3> <ul id="menu_xbox_hardware" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/playstation-3/systems?nav=138d-c4'> Game Systems </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>PlayStation 3 Accessories</h3> <ul id="menu_xbox_accessories" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/playstation-3/accessories/batteries-chargers?nav=138d-a5'> Batteries & Chargers </a> </li> - + <li> <a href='/browse/playstation-3/accessories/cables-adaptors?nav=138d-73'> Cables & Adaptors </a> </li> - + <li> <a href='/browse/playstation-3/accessories/cameras?nav=138d-a0'> Cameras </a> </li> - + <li> <a href='/browse/playstation-3/accessories/controllers?nav=138d-74'> Controllers </a> </li> - + <li> <a href='/browse/playstation-3/accessories/faceplates-skins?nav=138d-a4'> Faceplates & Skins </a> </li> - + <li> <a href='/browse/playstation-3/systems?nav=138d-c4'> Game Systems </a> </li> - + <li> <a href='/browse/playstation-3/accessories/headsets-mics?nav=138d-7b'> Headsets & Mics </a> </li> - + <li> <a href='/browse/playstation-3/accessories/keyboard-mousepads?nav=138d-82'> Keyboard & Mousepads </a> </li> - + <li> <a href='/browse/playstation-3/accessories/memory-cards?nav=138d-75'> Memory Cards </a> </li> - + <li> <a href='/browse/playstation-3/accessories/repair-cleaning?nav=138d-a6'> Repair & Cleaning </a> </li> - + <li> <a href='/browse/playstation-3/accessories/storage-cases?nav=138d-77'> Storage & Cases </a> </li> - + </ul> </div> <a href='/browse/playstation-3?nav=138d' class="menu_see_all">See All PS3 →</a> </div> </div> - + <a href='/wii' id='wii_link' class="navLink">Wii</a> <div id='wii_mega' class="mega_menu"> <div class="mega_menu_col menu_col_hot" Style="display:inline"> @@ -603,176 +603,176 @@ <div class="mega_menu_col menu_col_genres" Style="display:inline"> <h3>Nintendo Wii Games</h3> <ul id="menu_xbox_genres" class="menu_genres"> - + <li> <a href='/browse/nintendo-wii?nav=138a'> All </a> </li> - + <li> <a href='/browse/nintendo-wii/action?nav=138a-56'> Action </a> </li> - + <li> <a href='/browse/nintendo-wii/balance-board?nav=138a-1a0'> Balance Board </a> </li> - + <li> <a href='/browse/nintendo-wii/casual?nav=138a-d4'> Casual </a> </li> - + <li> <a href='/browse/nintendo-wii/educational?nav=138a-c3'> Educational </a> </li> - + <li> <a href='/browse/nintendo-wii/fighting?nav=138a-69'> Fighting </a> </li> - + <li> <a href='/browse/nintendo-wii/motionplus?nav=138a-1a1'> MotionPlus </a> </li> - + <li> <a href='/browse/nintendo-wii/move?nav=138a-19e'> Move </a> </li> - + <li> <a href='/browse/nintendo-wii/movies-tv?nav=138a-c6'> Movies & TV </a> </li> - + <li> <a href='/browse/nintendo-wii/music-party?nav=138a-be'> Music & Party </a> </li> - + <li> <a href='/browse/nintendo-wii/puzzle-cards?nav=138a-63'> Puzzle & Cards </a> </li> - + <li> <a href='/browse/nintendo-wii/role-playing?nav=138a-6a'> Role-Playing </a> </li> - + <li> <a href='/browse/nintendo-wii/shooter?nav=138a-65'> Shooter </a> </li> - + <li> <a href='/browse/nintendo-wii/simulation?nav=138a-67'> Simulation </a> </li> - + <li> <a href='/browse/nintendo-wii/sports?nav=138a-66'> Sports </a> </li> - + <li> <a href='/browse/nintendo-wii/strategy?nav=138a-68'> Strategy </a> </li> - + <li> <a href='/browse/nintendo-wii/strategy-guides?nav=138a-c8'> Strategy Guides </a> </li> - + </ul> </div> <div class="mega_menu_col menu_col_deals" Style="display:inline"> <div Style="display:inline"> <h3>Nintendo Wii Deals</h3> <ul id="menu_xbox_deals" class="menu_deals"> - + <li> <a href='/browse/nintendo-wii?nav=138a-162'> Price Drop </a> </li> - + <li> <a href='/browse/nintendo-wii?nav=138a-d3'> Under $20 </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>Shop by ESRB</h3> <ul id="menu_xbox_esrb" class="menu_esrb"> - + <li> <a href='/browse/nintendo-wii?nav=138a-39' class='mm_early_childhood'> Early Childhood </a> </li> - + <li> <a href='/browse/nintendo-wii?nav=138a-33' class='mm_everyone'> Everyone </a> </li> - + <li> <a href='/browse/nintendo-wii?nav=138a-38' class='mm_everyone_plus'> Everyone 10+ </a> </li> - + <li> <a href='/browse/nintendo-wii?nav=138a-34' class='mm_teen'> Teen </a> </li> - + <li> <a href='/browse/nintendo-wii?nav=138a-35' class='mm_mature'> Mature </a> </li> - + <li> <a href='/browse/nintendo-wii?nav=138a-36' class='mm_rating_pending'> Rating Pending </a> </li> - + </ul> </div> </div> @@ -780,79 +780,79 @@ <div Style="display:inline"> <h3>Nintendo Wii Hardware</h3> <ul id="menu_xbox_hardware" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/nintendo-wii/systems?nav=138a-c4'> Game Systems </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>Nintendo Wii Accessories</h3> <ul id="menu_xbox_accessories" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/nintendo-wii/accessories/batteries-chargers?nav=138a-a5'> Batteries & Chargers </a> </li> - + <li> <a href='/browse/nintendo-wii/accessories/cables-adaptors?nav=138a-73'> Cables & Adaptors </a> </li> - + <li> <a href='/browse/nintendo-wii/accessories/controllers?nav=138a-74'> Controllers </a> </li> - + <li> <a href='/browse/nintendo-wii/accessories/faceplates-skins?nav=138a-a4'> Faceplates & Skins </a> </li> - + <li> <a href='/browse/nintendo-wii/systems?nav=138a-c4'> Game Systems </a> </li> - + <li> <a href='/browse/nintendo-wii/accessories/headsets-mics?nav=138a-7b'> Headsets & Mics </a> </li> - + <li> <a href='/browse/nintendo-wii/accessories/memory-cards?nav=138a-75'> Memory Cards </a> </li> - + <li> <a href='/browse/nintendo-wii/accessories/repair-cleaning?nav=138a-a6'> Repair & Cleaning </a> </li> - + <li> <a href='/browse/nintendo-wii/accessories/storage-cases?nav=138a-77'> Storage & Cases </a> </li> - + </ul> </div> <a href='/browse/nintendo-wii?nav=138a' class="menu_see_all">See All Wii →</a> </div> </div> - + <a href='/3ds' id='3ds_link' class="navLink">3DS</a> <div id='3ds_mega' class="mega_menu"> <div class="mega_menu_col menu_col_hot" Style="display:inline"> @@ -864,133 +864,133 @@ <div class="mega_menu_col menu_col_genres" Style="display:inline"> <h3>Nintendo 3DS Games</h3> <ul id="menu_xbox_genres" class="menu_genres"> - + <li> <a href='/browse/nintendo-3ds?nav=131a2'> All </a> </li> - + <li> <a href='/browse/nintendo-3ds/action?nav=131a2-56'> Action </a> </li> - + <li> <a href='/browse/nintendo-3ds/casual?nav=131a2-d4'> Casual </a> </li> - + <li> <a href='/browse/nintendo-3ds/fighting?nav=131a2-69'> Fighting </a> </li> - + <li> <a href='/browse/nintendo-3ds/music-party?nav=131a2-be'> Music & Party </a> </li> - + <li> <a href='/browse/nintendo-3ds/puzzle-cards?nav=131a2-63'> Puzzle & Cards </a> </li> - + <li> <a href='/browse/nintendo-3ds/role-playing?nav=131a2-6a'> Role-Playing </a> </li> - + <li> <a href='/browse/nintendo-3ds/shooter?nav=131a2-65'> Shooter </a> </li> - + <li> <a href='/browse/nintendo-3ds/simulation?nav=131a2-67'> Simulation </a> </li> - + <li> <a href='/browse/nintendo-3ds/sports?nav=131a2-66'> Sports </a> </li> - + <li> <a href='/browse/nintendo-3ds/strategy-guides?nav=131a2-c8'> Strategy Guides </a> </li> - + </ul> </div> <div class="mega_menu_col menu_col_deals" Style="display:inline"> <div Style="display:inline"> <h3>Nintendo 3DS Deals</h3> <ul id="menu_xbox_deals" class="menu_deals"> - + <li> <a href='/browse/nintendo-3ds?nav=131a2-162'> Price Drop </a> </li> - + <li> <a href='/browse/nintendo-3ds?nav=131a2-d3'> Under $20 </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>Shop by ESRB</h3> <ul id="menu_xbox_esrb" class="menu_esrb"> - + <li> <a href='/browse/nintendo-3ds?nav=131a2-33' class='mm_everyone'> Everyone </a> </li> - + <li> <a href='/browse/nintendo-3ds?nav=131a2-38' class='mm_everyone_plus'> Everyone 10+ </a> </li> - + <li> <a href='/browse/nintendo-3ds?nav=131a2-34' class='mm_teen'> Teen </a> </li> - + <li> <a href='/browse/nintendo-3ds?nav=131a2-35' class='mm_mature'> Mature </a> </li> - + <li> <a href='/browse/nintendo-3ds?nav=131a2-36' class='mm_rating_pending'> Rating Pending </a> </li> - + </ul> </div> </div> @@ -998,49 +998,49 @@ <div Style="display:inline"> <h3>Nintendo 3DS Hardware</h3> <ul id="menu_xbox_hardware" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/nintendo-3ds/systems?nav=131a2-c4'> Game Systems </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>Nintendo 3DS Accessories</h3> <ul id="menu_xbox_accessories" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/nintendo-3ds/accessories/batteries-chargers?nav=131a2-a5'> Batteries & Chargers </a> </li> - + <li> <a href='/browse/nintendo-3ds/systems?nav=131a2-c4'> Game Systems </a> </li> - + <li> <a href='/browse/nintendo-3ds/accessories/repair-cleaning?nav=131a2-a6'> Repair & Cleaning </a> </li> - + <li> <a href='/browse/nintendo-3ds/accessories/storage-cases?nav=131a2-77'> Storage & Cases </a> </li> - + </ul> </div> <a href='/browse/nintendo-3ds?nav=131a2' class="menu_see_all">See All 3DS →</a> </div> </div> - + <a href='/ds' id='ds_link' class="navLink">DS</a> <div id='ds_mega' class="mega_menu"> <div class="mega_menu_col menu_col_hot" Style="display:inline"> @@ -1052,158 +1052,158 @@ <div class="mega_menu_col menu_col_genres" Style="display:inline"> <h3>Nintendo DS Games</h3> <ul id="menu_xbox_genres" class="menu_genres"> - + <li> <a href='/browse/nintendo-ds?nav=1386'> All </a> </li> - + <li> <a href='/browse/nintendo-ds/action?nav=1386-56'> Action </a> </li> - + <li> <a href='/browse/nintendo-ds/casual?nav=1386-d4'> Casual </a> </li> - + <li> <a href='/browse/nintendo-ds/educational?nav=1386-c3'> Educational </a> </li> - + <li> <a href='/browse/nintendo-ds/fighting?nav=1386-69'> Fighting </a> </li> - + <li> <a href='/browse/nintendo-ds/movies-tv?nav=1386-c6'> Movies & TV </a> </li> - + <li> <a href='/browse/nintendo-ds/music-party?nav=1386-be'> Music & Party </a> </li> - + <li> <a href='/browse/nintendo-ds/puzzle-cards?nav=1386-63'> Puzzle & Cards </a> </li> - + <li> <a href='/browse/nintendo-ds/role-playing?nav=1386-6a'> Role-Playing </a> </li> - + <li> <a href='/browse/nintendo-ds/shooter?nav=1386-65'> Shooter </a> </li> - + <li> <a href='/browse/nintendo-ds/simulation?nav=1386-67'> Simulation </a> </li> - + <li> <a href='/browse/nintendo-ds/sports?nav=1386-66'> Sports </a> </li> - + <li> <a href='/browse/nintendo-ds/strategy?nav=1386-68'> Strategy </a> </li> - + <li> <a href='/browse/nintendo-ds/strategy-guides?nav=1386-c8'> Strategy Guides </a> </li> - + </ul> </div> <div class="mega_menu_col menu_col_deals" Style="display:inline"> <div Style="display:inline"> <h3>Nintendo DS Deals</h3> <ul id="menu_xbox_deals" class="menu_deals"> - + <li> <a href='/browse/nintendo-ds?nav=1386-162'> Price Drop </a> </li> - + <li> <a href='/browse/nintendo-ds?nav=1386-d3'> Under $20 </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>Shop by ESRB</h3> <ul id="menu_xbox_esrb" class="menu_esrb"> - + <li> <a href='/browse/nintendo-ds?nav=1386-39' class='mm_early_childhood'> Early Childhood </a> </li> - + <li> <a href='/browse/nintendo-ds?nav=1386-33' class='mm_everyone'> Everyone </a> </li> - + <li> <a href='/browse/nintendo-ds?nav=1386-38' class='mm_everyone_plus'> Everyone 10+ </a> </li> - + <li> <a href='/browse/nintendo-ds?nav=1386-34' class='mm_teen'> Teen </a> </li> - + <li> <a href='/browse/nintendo-ds?nav=1386-35' class='mm_mature'> Mature </a> </li> - + <li> <a href='/browse/nintendo-ds?nav=1386-36' class='mm_rating_pending'> Rating Pending </a> </li> - + </ul> </div> </div> @@ -1211,79 +1211,79 @@ <div Style="display:inline"> <h3>Nintendo DS Hardware</h3> <ul id="menu_xbox_hardware" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/nintendo-ds/systems?nav=1386-c4'> Game Systems </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>Nintendo DS Accessories</h3> <ul id="menu_xbox_accessories" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/nintendo-ds/accessories/batteries-chargers?nav=1386-a5'> Batteries & Chargers </a> </li> - + <li> <a href='/browse/nintendo-ds/accessories/cables-adaptors?nav=1386-73'> Cables & Adaptors </a> </li> - + <li> <a href='/browse/nintendo-ds/accessories/cheat-systems?nav=1386-a1'> Cheat Systems </a> </li> - + <li> <a href='/browse/nintendo-ds/accessories/controllers?nav=1386-74'> Controllers </a> </li> - + <li> <a href='/browse/nintendo-ds/accessories/faceplates-skins?nav=1386-a4'> Faceplates & Skins </a> </li> - + <li> <a href='/browse/nintendo-ds/systems?nav=1386-c4'> Game Systems </a> </li> - + <li> <a href='/browse/nintendo-ds/accessories/headsets-mics?nav=1386-7b'> Headsets & Mics </a> </li> - + <li> <a href='/browse/nintendo-ds/accessories/memory-cards?nav=1386-75'> Memory Cards </a> </li> - + <li> <a href='/browse/nintendo-ds/accessories/storage-cases?nav=1386-77'> Storage & Cases </a> </li> - + </ul> </div> <a href='/browse/nintendo-ds?nav=1386' class="menu_see_all">See All DS →</a> </div> </div> - + <a href='/psp' id='psp_link' class="navLink">PSP</a> <div id='psp_mega' class="mega_menu"> <div class="mega_menu_col menu_col_hot" Style="display:inline"> @@ -1295,157 +1295,157 @@ <div class="mega_menu_col menu_col_genres" Style="display:inline"> <h3>Sony PSP Games</h3> <ul id="menu_xbox_genres" class="menu_genres"> - + <li> <a href='/browse/sony-psp?nav=1388'> All </a> </li> - + <li> <a href='/browse/sony-psp/action?nav=1388-56'> Action </a> </li> - + <li> <a href='/browse/sony-psp/add-ons?nav=1388-18a'> Add-ons </a> </li> - + <li> <a href='/browse/sony-psp/casual?nav=1388-d4'> Casual </a> </li> - + <li> <a href='/browse/sony-psp/educational?nav=1388-c3'> Educational </a> </li> - + <li> <a href='/browse/sony-psp/fighting?nav=1388-69'> Fighting </a> </li> - + <li> <a href='/browse/sony-psp/movies-tv?nav=1388-c6'> Movies & TV </a> </li> - + <li> <a href='/browse/sony-psp/music-party?nav=1388-be'> Music & Party </a> </li> - + <li> <a href='/browse/sony-psp/puzzle-cards?nav=1388-63'> Puzzle & Cards </a> </li> - + <li> <a href='/browse/sony-psp/role-playing?nav=1388-6a'> Role-Playing </a> </li> - + <li> <a href='/browse/sony-psp/shooter?nav=1388-65'> Shooter </a> </li> - + <li> <a href='/browse/sony-psp/simulation?nav=1388-67'> Simulation </a> </li> - + <li> <a href='/browse/sony-psp/sports?nav=1388-66'> Sports </a> </li> - + <li> <a href='/browse/sony-psp/strategy?nav=1388-68'> Strategy </a> </li> - + <li> <a href='/browse/sony-psp/strategy-guides?nav=1388-c8'> Strategy Guides </a> </li> - + </ul> </div> <div class="mega_menu_col menu_col_deals" Style="display:inline"> <div Style="display:inline"> <h3>Sony PSP Deals</h3> <ul id="menu_xbox_deals" class="menu_deals"> - + <li> <a href='/browse/sony-psp?nav=1388-162'> Price Drop </a> </li> - + <li> <a href='/browse/sony-psp?nav=1388-d3'> Under $20 </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>Shop by ESRB</h3> <ul id="menu_xbox_esrb" class="menu_esrb"> - + <li> <a href='/browse/sony-psp?nav=1388-33' class='mm_everyone'> Everyone </a> </li> - + <li> <a href='/browse/sony-psp?nav=1388-38' class='mm_everyone_plus'> Everyone 10+ </a> </li> - + <li> <a href='/browse/sony-psp?nav=1388-34' class='mm_teen'> Teen </a> </li> - + <li> <a href='/browse/sony-psp?nav=1388-35' class='mm_mature'> Mature </a> </li> - + <li> <a href='/browse/sony-psp?nav=1388-36' class='mm_rating_pending'> Rating Pending </a> </li> - + </ul> </div> </div> @@ -1453,67 +1453,67 @@ <div Style="display:inline"> <h3>Sony PSP Hardware</h3> <ul id="menu_xbox_hardware" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/sony-psp/systems?nav=1388-c4'> Game Systems </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>Sony PSP Accessories</h3> <ul id="menu_xbox_accessories" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/sony-psp/accessories/batteries-chargers?nav=1388-a5'> Batteries & Chargers </a> </li> - + <li> <a href='/browse/sony-psp/accessories/cables-adaptors?nav=1388-73'> Cables & Adaptors </a> </li> - + <li> <a href='/browse/sony-psp/accessories/faceplates-skins?nav=1388-a4'> Faceplates & Skins </a> </li> - + <li> <a href='/browse/sony-psp/systems?nav=1388-c4'> Game Systems </a> </li> - + <li> <a href='/browse/sony-psp/accessories/headsets-mics?nav=1388-7b'> Headsets & Mics </a> </li> - + <li> <a href='/browse/sony-psp/accessories/memory-cards?nav=1388-75'> Memory Cards </a> </li> - + <li> <a href='/browse/sony-psp/accessories/storage-cases?nav=1388-77'> Storage & Cases </a> </li> - + </ul> </div> <a href='/browse/sony-psp?nav=1388' class="menu_see_all">See All PSP →</a> </div> </div> - + <a href='/pcgames' id='pc_link' class="navLink">PC</a> <div id='pc_mega' class="mega_menu"> <div class="mega_menu_col menu_col_hot" Style="display:inline"> @@ -1525,170 +1525,170 @@ <div class="mega_menu_col menu_col_genres" Style="display:inline"> <h3>PC Games</h3> <ul id="menu_xbox_genres" class="menu_genres"> - + <li> <a href='/browse/pc?nav=138c'> All </a> </li> - + <li> <a href='/browse/pc/action?nav=138c-56'> Action </a> </li> - + <li> <a href='/browse/pc/casual?nav=138c-d4'> Casual </a> </li> - + <li> <a href='/browse/pc/educational?nav=138c-c3'> Educational </a> </li> - + <li> <a href='/browse/pc/fighting?nav=138c-69'> Fighting </a> </li> - + <li> <a href='/browse/pc/movies-tv?nav=138c-c6'> Movies & TV </a> </li> - + <li> <a href='/browse/pc/music-party?nav=138c-be'> Music & Party </a> </li> - + <li> <a href='/browse/pc/pc-hardware?nav=138c-186'> PC Hardware </a> </li> - + <li> <a href='/browse/pc/productivity?nav=138c-c7'> Productivity </a> </li> - + <li> <a href='/browse/pc/puzzle-cards?nav=138c-63'> Puzzle & Cards </a> </li> - + <li> <a href='/browse/pc/role-playing?nav=138c-6a'> Role-Playing </a> </li> - + <li> <a href='/browse/pc/shooter?nav=138c-65'> Shooter </a> </li> - + <li> <a href='/browse/pc/simulation?nav=138c-67'> Simulation </a> </li> - + <li> <a href='/browse/pc/sports?nav=138c-66'> Sports </a> </li> - + <li> <a href='/browse/pc/strategy?nav=138c-68'> Strategy </a> </li> - + <li> <a href='/browse/pc/strategy-guides?nav=138c-c8'> Strategy Guides </a> </li> - + </ul> </div> <div class="mega_menu_col menu_col_deals" Style="display:inline"> <div Style="display:inline"> <h3>PC Deals</h3> <ul id="menu_xbox_deals" class="menu_deals"> - + <li> <a href='/browse/pc?nav=138c-162'> Price Drop </a> </li> - + <li> <a href='/browse/pc?nav=138c-d3'> Under $20 </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>Shop by ESRB</h3> <ul id="menu_xbox_esrb" class="menu_esrb"> - + <li> <a href='/browse/pc?nav=138c-39' class='mm_early_childhood'> Early Childhood </a> </li> - + <li> <a href='/browse/pc?nav=138c-33' class='mm_everyone'> Everyone </a> </li> - + <li> <a href='/browse/pc?nav=138c-38' class='mm_everyone_plus'> Everyone 10+ </a> </li> - + <li> <a href='/browse/pc?nav=138c-34' class='mm_teen'> Teen </a> </li> - + <li> <a href='/browse/pc?nav=138c-35' class='mm_mature'> Mature </a> </li> - + <li> <a href='/browse/pc?nav=138c-36' class='mm_rating_pending'> Rating Pending </a> </li> - + </ul> </div> </div> @@ -1696,67 +1696,67 @@ <div Style="display:inline"> <h3>PC Hardware</h3> <ul id="menu_xbox_hardware" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/pc/systems?nav=138c-c4'> Game Systems </a> </li> - + </ul> </div> <div Style="display:inline"> <h3>PC Accessories</h3> <ul id="menu_xbox_accessories" class="menu_hardware_and_accessories"> - + <li> <a href='/browse/pc/accessories/cables-adaptors?nav=138c-73'> Cables & Adaptors </a> </li> - + <li> <a href='/browse/pc/accessories/controllers?nav=138c-74'> Controllers </a> </li> - + <li> <a href='/browse/pc/systems?nav=138c-c4'> Game Systems </a> </li> - + <li> <a href='/browse/pc/accessories/headsets-mics?nav=138c-7b'> Headsets & Mics </a> </li> - + <li> <a href='/browse/pc/accessories/keyboard-mousepads?nav=138c-82'> Keyboard & Mousepads </a> </li> - + <li> <a href='/browse/pc/accessories/repair-cleaning?nav=138c-a6'> Repair & Cleaning </a> </li> - + <li> <a href='/browse/pc/accessories/storage-cases?nav=138c-77'> Storage & Cases </a> </li> - + </ul> </div> <a href='/browse/pc?nav=138c' class="menu_see_all">See All PC →</a> </div> </div> - + <a href="/browse/search.aspx" id="all_link" class="navLink">More</a> <div id="all_mega" class="mega_menu"> <ul id="menu_all"> @@ -1777,11 +1777,11 @@ <div class="clear"></div> <div class="secondary_nav"> <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_searchbox" class="searchbox grid_8"> - + <input name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$cHeader$searchtext" type="text" maxlength="50" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_searchtext" class="searchtext" /> <input type="submit" name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$cHeader$searchbutton" value="Search" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_searchbutton" class="searchbutton" /> - - + + </div> <ul id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_Ul1" class="featurelinks grid_9 alpha"> <li><a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_lnkDownloads" href="/downloads"><strong>Downloads</strong>Games & Add-Ons</a></li> @@ -1789,7 +1789,7 @@ <li><a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_lnkTradeIns" href="/tradeins"><strong>Trade-Ins</strong>Great Offers</a></li> <li class="highlight"><a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cHeader_lnkDeals" href="/deals"><strong>Deals</strong>Current Sales</a></li> </ul> - + <div class="cardbox grid_7"> <div class="cardbox_guest"> @@ -1810,11 +1810,11 @@ <td width="815" valign="top" align="left" class="stdcopy"> <div id="content"> <div id="checkout_main"> - - + + <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_ucCheckoutHeaderControl_pnlProgressBar" class="hdr_progbar" style="background-image:url(/common/gui/header_checkout_n.gif);"> - + <input type="image" name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$ucCheckoutHeaderControl$ibtnStepOne" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_ucCheckoutHeaderControl_ibtnStepOne" class="noBorder" src="#" style="border-width:0px;" /> <input type="image" name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$ucCheckoutHeaderControl$ibtnStepTwo" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_ucCheckoutHeaderControl_ibtnStepTwo" disabled="disabled" class="noBorder" src="#" style="border-width:0px;" /> <input type="image" name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$ucCheckoutHeaderControl$ibtnStepThree" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_ucCheckoutHeaderControl_ibtnStepThree" disabled="disabled" class="noBorder" src="#" style="border-width:0px;" /> @@ -1836,19 +1836,19 @@ <br /> <br /> - - - + + + All fields are required unless noted. - + <br /> <br /> <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_upShippingAddressDetails"> - - - - - + + + + + <style type="text/css"> .address-label @@ -1857,14 +1857,14 @@ font-size:11px; font-weight:bold; height:16px; - width:160px; + width:160px; } </style> <table width="500" cellspacing="0" cellpadding="2" border="0"> - - - + + + <tr> <td width="150" height="30" valign="middle" align="right" class="stdcopy"> <label id="firstNameLbl" for="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_textFirstName" class="address-label"> First Name: @@ -1900,7 +1900,7 @@ <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_valNameLengthLast" style="color:Red;display:none;">First and last name can not exceed 34 characters.<br /></span> </td> </tr> - + <tr> <td width="150" height="30" valign="middle" align="right" class="stdcopy"> <label id="address1Lbl" for="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_textAddressLine1" class="address-label"> @@ -1908,7 +1908,7 @@ </label> </td> <td width="10" height="30"><img src="#" border="0" width="10" height="1"></td> - <td width="380" height="30" valign="middle" align="left" colspan="3" class="stdcopy"> + <td width="380" height="30" valign="middle" align="left" colspan="3" class="stdcopy"> <input name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$AddressDetails$AddressDetails$textAddressLine1" type="text" maxlength="32" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_textAddressLine1" class="formfields" style="width:240px; height:18px;" /> <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_valAddress" style="color:Red;visibility:hidden;">Required field.</span> <input type="hidden" name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$AddressDetails$AddressDetails$ValidatorCalloutExtender3_ClientState" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_ValidatorCalloutExtender3_ClientState" /> @@ -2247,15 +2247,15 @@ </td> <td width="10" height="30"><img src="#" border="0" width="10" height="1"></td> <td width="380" height="30" valign="middle" align="left" colspan="3" class="stdcopy"> - <input name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$AddressDetails$AddressDetails$textPhoneNumberDaytime" type="text" maxlength="14" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_textPhoneNumberDaytime" class="formfields" style="width:170px; height:18px;" /> + <input name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$AddressDetails$AddressDetails$textPhoneNumberDaytime" type="text" maxlength="14" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_textPhoneNumberDaytime" class="formfields" style="width:170px; height:18px;" /> <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_lblPhoneFormat" class="smallcopy" style="font-weight:normal;font-style:italic;">(ie: 5551234567)</span> <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_PhoneRequiredValidator" style="color:Red;display:none;">Required field.</span> <input type="hidden" name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$AddressDetails$AddressDetails$ValidatorCalloutExtender4_ClientState" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_ValidatorCalloutExtender4_ClientState" /> <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_valPhoneFormat" style="color:Red;display:none;">Invalid format.</span> </td> </tr> - - + + <tr> <td width="110" height="30" valign="middle" align="right" class="stdcopy"> <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_lblEmailAddress" style="display:inline-block;font-size:11px;font-weight:bold;height:16px;width:120px;">Purchaser's Email:</span> @@ -2263,40 +2263,40 @@ <td width="10" height="30"><img src="#" border="0" width="10" height="1"></td> <td width="380" height="30" valign="middle" align="left" colspan="3" class="stdcopy"> <input name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$AddressDetails$AddressDetails$txtEmailAddress" type="text" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_txtEmailAddress" class="formfields" style="width:170px; height:18px;" /> - <img src="#" height="5" width="2" border="0"> + <img src="#" height="5" width="2" border="0"> <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_rfvEmailAddress" style="color:Red;display:none;">Required field.</span><input type="hidden" name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$AddressDetails$AddressDetails$ValidatorCalloutExtender11_ClientState" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_ValidatorCalloutExtender11_ClientState" /><span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_revEmailAddress" style="color:Red;display:none;">Invalid format.</span><input type="hidden" name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$AddressDetails$AddressDetails$ValidatorCalloutExtender12_ClientState" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_ValidatorCalloutExtender12_ClientState" /><a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_lnkWhyEmailAddress" tabindex="1000" style="text-decoration:underline;height:18px;">Why?</a><div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_popWhyEmailAddress_pnlPopup" style="display:none;z-index:15000;"> - + <table cellpadding="0" cellspacing="0" style="padding:0; margin:0px; border-collapse:collapse"> <tr> <td id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_popWhyEmailAddress_tdTopImage" colspan="3" style="padding:0; margin:0px"> - + </td> - + </tr> <tr> <td valign="top" style="padding:0; margin:0px"><img id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_popWhyEmailAddress_imgLeftArrow" src="#" style="border-width:0px;margin-top:5px;" /></td> <td style="padding:0; margin:0px"> <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_popWhyEmailAddress_pnlContent" class="pnlContent" style="width:210px;background:#ccc; padding:10px; border:#999 1px solid; color:#333; float: left;"> - + <a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_popWhyEmailAddress_lnkClosePopup" style="font-size: 11px; float:right">Close</a> - + <div style="margin:5px; width:200px"> <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_popWhyEmailAddress_whyEmailDescriptionLabel">Your email address is needed to keep you updated about your order.</span> </div> - - + + </div> </td> <td valign="top" style="padding:0; margin:0px"></td> </tr> <tr> <td id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_popWhyEmailAddress_tdBottomImage" colspan="3" style="padding:0; margin:0px"> - + </td> - + </tr> </table> - + </div> @@ -2321,73 +2321,73 @@ <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_AddressDetails_AddressDetails_lblWeeklyAddOffer">Sign up for our weekly ad, exclusive offers and more.</span> </td> </tr> - - + + </table> <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_pnlPopup" style="display:none;z-index:15000;"> - + <table cellpadding="0" cellspacing="0" style="padding:0; margin:0px; border-collapse:collapse"> <tr> <td id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_tdTopImage" colspan="3" style="padding:0; margin:0px"> - + </td> - + </tr> <tr> <td valign="top" style="padding:0; margin:0px"><img id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_imgLeftArrow" src="#" style="border-width:0px;margin-top:15px;" /></td> <td style="padding:0; margin:0px"> <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_pnlContent" class="overlay_pickup"> - + <a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_lnkClosePopup" style="font-size: 11px; float:right">Close</a> - - + + <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_upErrorMessage"> - + <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_MainValidationSummary" class="error_msg" style="color:Red;width:470px;display:none;"> </div> - + </div> - - + + <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_AddressTypeHeaderForValidationLabel" class="hdr_overlay">Shipping Address</span> <div id="Div1"></div> - + <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_upShippingAddresses"> - + <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_lblShippingAddressHeader" class="hdr_overlay">Choose a shipping address:</span> <div id="spacer_line_overlay"></div> - + <div id="spacer"></div> <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_pgrShippingAddresses"></span> - + </div> - + <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_upNewAddress"> - - - - - + + + + + <div id="spacer_line_overlay"></div> - + <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_lblNewShippingAddress" class="hdr_overlay"> Or enter a new shipping address: </span> - + <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_ValidationSummary1" class="error_msg" style="color:Red;width:465px;display:none;"> </div> <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_InputOverlayPanel" class="input_overlay"> - - + + <style type="text/css"> .address-label @@ -2396,13 +2396,13 @@ font-size:11px; font-weight:bold; height:16px; - width:160px; + width:160px; } </style> <table width="500" cellspacing="0" cellpadding="2" border="0"> - - + + <tr> <td width="150" height="30" valign="middle" align="right" class="stdcopy"> <label id="firstNameLbl" for="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_AddressDetails1_textFirstName" class="address-label"> First Name: @@ -2438,7 +2438,7 @@ <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_AddressDetails1_valNameLengthLast" style="color:Red;display:none;">First and last name can not exceed 34 characters.<br /></span> </td> </tr> - + <tr> <td width="150" height="30" valign="middle" align="right" class="stdcopy"> <label id="address1Lbl" for="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_AddressDetails1_textAddressLine1" class="address-label"> @@ -2446,7 +2446,7 @@ </label> </td> <td width="10" height="30"><img src="#" border="0" width="10" height="1"></td> - <td width="380" height="30" valign="middle" align="left" colspan="3" class="stdcopy"> + <td width="380" height="30" valign="middle" align="left" colspan="3" class="stdcopy"> <input name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$aspShippingAddress$popAddressSelection$AddressDetails1$textAddressLine1" type="text" maxlength="32" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_AddressDetails1_textAddressLine1" class="formfields" style="width:240px; height:18px;" /> <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_AddressDetails1_valAddress" style="color:Red;visibility:hidden;">Required field.</span> <input type="hidden" name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$aspShippingAddress$popAddressSelection$AddressDetails1$ValidatorCalloutExtender3_ClientState" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_AddressDetails1_ValidatorCalloutExtender3_ClientState" /> @@ -2785,57 +2785,57 @@ </td> <td width="10" height="30"><img src="#" border="0" width="10" height="1"></td> <td width="380" height="30" valign="middle" align="left" colspan="3" class="stdcopy"> - <input name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$aspShippingAddress$popAddressSelection$AddressDetails1$textPhoneNumberDaytime" type="text" maxlength="14" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_AddressDetails1_textPhoneNumberDaytime" class="formfields" style="width:170px; height:18px;" /> + <input name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$aspShippingAddress$popAddressSelection$AddressDetails1$textPhoneNumberDaytime" type="text" maxlength="14" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_AddressDetails1_textPhoneNumberDaytime" class="formfields" style="width:170px; height:18px;" /> <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_AddressDetails1_lblPhoneFormat" class="smallcopy" style="font-weight:normal;font-style:italic;">(ie: 5551234567)</span> <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_AddressDetails1_PhoneRequiredValidator" style="color:Red;display:none;">Required field.</span> <input type="hidden" name="ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$aspShippingAddress$popAddressSelection$AddressDetails1$ValidatorCalloutExtender4_ClientState" id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_AddressDetails1_ValidatorCalloutExtender4_ClientState" /> <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_AddressDetails1_valPhoneFormat" style="color:Red;display:none;">Invalid format.</span> </td> </tr> - + </table> - + <a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_btnSubmitShippingAddress" > <img src='../Common/GUI/btn_checkout_shipaddr.gif' class="centerImage" style="border:0"/> </a> - - - + + + </div> - - + + </div> - - - - + + + + </div> </td> <td valign="top" style="padding:0; margin:0px"></td> </tr> <tr> <td id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_aspShippingAddress_popAddressSelection_tdBottomImage" colspan="3" style="padding:0; margin:0px"> - + </td> - + </tr> </table> - + </div> - - + + </div> <div id="nav_group"> <table> - + <tr> <td></td> <td align="right" style="width:25px"> @@ -2845,7 +2845,7 @@ <img src="#" border="0" width="10" height="1"><span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_lblSameAsBillingAddress" class="stdcopy" style="font-weight:bold;">My Billing Address and Shipping Address are the same.</span> </td> </tr> - + <tr> <td colspan="2"> <img src="#" border="0" width="50" height="10"> @@ -2854,7 +2854,7 @@ <tr> <td> <div id="nav_msg"> - + <!--[if lte IE 7]> @@ -2867,74 +2867,74 @@ <img src="#" id="img_lockicon_nav" /> -<span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_PrivacyMessageCtl1_lblPrivacyPolicyMessage">We are committed to protecting your privacy. All transactions are secure. For more information, please read our </span> <a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_PrivacyMessageCtl1_lbtnPrivacyPolicy" tabindex="-1" class="sub_link" >privacy policy</a>. +<span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_PrivacyMessageCtl1_lblPrivacyPolicyMessage">We are committed to protecting your privacy. All transactions are secure. For more information, please read our </span> <a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_PrivacyMessageCtl1_lbtnPrivacyPolicy" tabindex="-1" class="sub_link" >privacy policy</a>. <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_PrivacyMessageCtl1_popEditAddress_pnlPopup" style="display:none;z-index:15000;"> - + <table cellpadding="0" cellspacing="0" style="padding:0; margin:0px; border-collapse:collapse"> <tr> <td id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_PrivacyMessageCtl1_popEditAddress_tdTopImage" colspan="3" style="padding:0; margin:0px" align="center"> <img id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_PrivacyMessageCtl1_popEditAddress_imgTopArrow" src="#" align="absbottom" style="border-width:0px;" /> </td> - + </tr> <tr> <td valign="top" style="padding:0; margin:0px"></td> <td style="padding:0; margin:0px"> <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_PrivacyMessageCtl1_popEditAddress_pnlContent" class="pnlContent" style="background:#ccc; padding:10px; border:#999 1px solid; color:#333; float: left;"> - + <a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_PrivacyMessageCtl1_popEditAddress_lnkClosePopup" style="font-size: 11px; float:right">Close</a> - + <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_PrivacyMessageCtl1_popEditAddress_lblPrivacyPolicyHeader" class="hdr_overlay"> Privacy Policy: </span><br /> - + <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_PrivacyMessageCtl1_popEditAddress_lblPrivacyPolicy" class="privacy_group_overlay"> - Last updated: January 9, 2007<br /><br /> - - Gamestop.com is aware of your concerns about use of your personal information. We attempt to use and share personal information that we collect online carefully and sensibly. This notice describes our privacy policy. By visiting + Last updated: January 9, 2007<br /><br /> + + Gamestop.com is aware of your concerns about use of your personal information. We attempt to use and share personal information that we collect online carefully and sensibly. This notice describes our privacy policy. By visiting Gamestop.com, you are accepting the practices described in this privacy notice.<br /><br /> - - Our online privacy policy applies only to information that we collect from customers online who visit - Gamestop.com; it does not apply to any information collected at our retail stores and outlets. This website contains links to other websites. - Gamestop.com is not responsible for the privacy practices or the content of such other websites.<br /><br /> - - In this document, the word "computer" means any device used to connect to - Gamestop.com, including, but not limited to, mobile devices.<br /><br /> - + + Our online privacy policy applies only to information that we collect from customers online who visit + Gamestop.com; it does not apply to any information collected at our retail stores and outlets. This website contains links to other websites. + Gamestop.com is not responsible for the privacy practices or the content of such other websites.<br /><br /> + + In this document, the word "computer" means any device used to connect to + Gamestop.com, including, but not limited to, mobile devices.<br /><br /> + <b>We Gather the Following Personal Information About Customers:</b><br /><br /> - - <b>Information That You Give Us: </b>We receive and store any information you enter on our website or that you give us in any other way. You can choose not to provide certain information, but this will limit your ability to purchase products offered on the website, or to take advantage of some of our features for website customers.<br /><br /> - + + <b>Information That You Give Us: </b>We receive and store any information you enter on our website or that you give us in any other way. You can choose not to provide certain information, but this will limit your ability to purchase products offered on the website, or to take advantage of some of our features for website customers.<br /><br /> + When you place an order with us, your contact information is used to communicate related information, such as order and shipment confirmation, release date changes and requests for more information to facilitate the processing of your order. You may opt-out of these communications by canceling your order.<br /><br /> - - + + We use customer contact information from the account form to customize future shopping for you, to improve our website and stores, and, if you choose, to send you information about our company and to inform you of sales and special offers. If, after receiving a non-order related email, you do not want to receive such emails in the future, you can notify us, by clicking on the "unsubscribe" link attached to each email.<br /><br /> - - We obtain information about you when you search, buy, participate in a contest or questionnaire, communicate with customer service, or otherwise contact us or post information on the website. For example, you provide information when you search for a product; place an order through - Gamestop.com or provide information to update or create your account with us (you may have more than one account if you have used more than one e-mail address when shopping with us); communicate with us by phone, e-mail, or otherwise; complete a questionnaire or a contest entry form; create any wish or gift list; participate in any forums or discussion areas or product reviews; or create any alerts or other email notification services we may offer now or in the future. The information collected typically includes your name, address, and phone numbers; credit card information; people to whom purchases have been shipped, including addresses and phone number; content of reviews you may provide; e-mails to us; and any other personal information that you provide to us or post on the website.<br /><br /> - - <b>We occasionally run our own email surveys</b> and we ask visitors for contact, demographic and technical information. We use contact data from our surveys to send users information about our company. This information is also used to contact visitors to learn more about specific problems they might have reported or to give them rewards, if such a reward program is part of the survey. The demographic information is used to learn more about the types of people who visit our site.<br /><br /> - + + We obtain information about you when you search, buy, participate in a contest or questionnaire, communicate with customer service, or otherwise contact us or post information on the website. For example, you provide information when you search for a product; place an order through + Gamestop.com or provide information to update or create your account with us (you may have more than one account if you have used more than one e-mail address when shopping with us); communicate with us by phone, e-mail, or otherwise; complete a questionnaire or a contest entry form; create any wish or gift list; participate in any forums or discussion areas or product reviews; or create any alerts or other email notification services we may offer now or in the future. The information collected typically includes your name, address, and phone numbers; credit card information; people to whom purchases have been shipped, including addresses and phone number; content of reviews you may provide; e-mails to us; and any other personal information that you provide to us or post on the website.<br /><br /> + + <b>We occasionally run our own email surveys</b> and we ask visitors for contact, demographic and technical information. We use contact data from our surveys to send users information about our company. This information is also used to contact visitors to learn more about specific problems they might have reported or to give them rewards, if such a reward program is part of the survey. The demographic information is used to learn more about the types of people who visit our site.<br /><br /> + <b>We run contests on our site in which we ask visitors for contact information</b> (such as their email address). We use this information to contact the winners. We may share contest information entered on our website with our business and marketing partners.<br /><br /> - + <b>We allow customers to post reviews</b> and to allow visitors to communicate information on products. When posting a review, you can optionally display your name, an alias, or remain anonymous. However, if you disclose personally identifiable information in your review, that information is public information and may increase your chance of receiving unsolicited email. You should use discretion when disclosing information on-line.<br /><br /> - - - <b>Automatic Collection of Information:</b> If you purchase any products online, or have any other interaction with our website, we will receive and store information that you provide or that is generated by your actions. For example, like many websites, we use "cookies," which are placed on your computer (explained in more detail below), to remember your name and the contents of your shopping cart. This allows you to leave our site, come back later, and still have the contents of your shopping cart intact. It also lets us personalize your experience at - Gamestop.com, tailoring the content to your interests. A number of companies offer utilities designed to help you visit websites anonymously, but if you use these utilities, it may limit your ability to use personalized features that we offer.<br /><br /> - + + + <b>Automatic Collection of Information:</b> If you purchase any products online, or have any other interaction with our website, we will receive and store information that you provide or that is generated by your actions. For example, like many websites, we use "cookies," which are placed on your computer (explained in more detail below), to remember your name and the contents of your shopping cart. This allows you to leave our site, come back later, and still have the contents of your shopping cart intact. It also lets us personalize your experience at + Gamestop.com, tailoring the content to your interests. A number of companies offer utilities designed to help you visit websites anonymously, but if you use these utilities, it may limit your ability to use personalized features that we offer.<br /><br /> + The information we receive or can determine from your interaction with our website includes your Internet (IP) address; login and password information; e-mail address; web browser type and version; operating system and computer platform; purchase history, which we may aggregate with similar information from other customers; the full Uniform Resource Locator (URL) clickstream to, through, and from our website, including date and time; cookie number; products you viewed or searched for; areas of our website you visited; and the phone number you used to call our toll-free number. We also may log the length of time of your visit and the number of times you visit and purchase from us. We assign you a unique internal identifier to help keep track of your future visits.<br /><br /> - - <b>E-mail Communications:</b> We provide email links on our "Customer Services" page that allow you to contact us directly with any questions or comments you may have. We may receive a confirmation when you open any e-mail that we send to you, if your computer supports such capabilities. If you send us any email, we will retain such email and your email address for response. We also may compare our customer list to lists received from other companies, in an effort to avoid sending unnecessary or duplicate messages to you.<br /><br /> - + + <b>E-mail Communications:</b> We provide email links on our "Customer Services" page that allow you to contact us directly with any questions or comments you may have. We may receive a confirmation when you open any e-mail that we send to you, if your computer supports such capabilities. If you send us any email, we will retain such email and your email address for response. We also may compare our customer list to lists received from other companies, in an effort to avoid sending unnecessary or duplicate messages to you.<br /><br /> + <b>Information from Other Sources:</b> If we receive any information about you from other sources, we may add it to our account information. For example, if we receive a list of subscribers to a gaming publication, and we note that you are a subscriber, we may include that information in the account information that we store about you. Other examples of information we receive from other sources include updated delivery and address information from our carriers or other third parties, which we use to correct our records; account information, purchase or redemption information, and page-view information from business partners who operate their own websites or for which we provide any services; search term and search result information from searches conducted through the website; and credit history information from credit bureaus, which we use to help prevent and detect fraud.<br /><br /> - - <b>An Explanation of "Cookies"</b><br /><br /> - Cookies are alphanumeric identifiers that are placed by us on your computer's storage system through your web browser to enable our systems to recognize your browser when you make future visits to our website, and to store certain information (such as items placed in your shopping cart) between visits.<br /><br /> - + + <b>An Explanation of "Cookies"</b><br /><br /> + Cookies are alphanumeric identifiers that are placed by us on your computer's storage system through your web browser to enable our systems to recognize your browser when you make future visits to our website, and to store certain information (such as items placed in your shopping cart) between visits.<br /><br /> + You can stop your computer from storing cookies if you want to. Most browsers will tell you how to prevent your browser from accepting new cookies, how to have the browser notify you when you receive a new cookie, or how to disable cookies altogether. You should look in the "help" area shown on your browser's toolbar. Because cookies allow you to have the benefit of our personalized features, we recommend that you leave them turned on. You MUST have cookies enabled in order to checkout on our website.<br /><br /> - - + + <b>Sharing of Information<br /> <br /> Tournaments: @@ -2942,39 +2942,39 @@ <b><br /> <br /> Sharing with Third Parties.</b> We may share customer information that we collect with third parties. Usually, this information will be shared with a third party that has relationship with us as a business partner or marketing partner. (See information on Third Party Relationships below.) Also, we may use the information that you provide us, or that we collect about you, in connection with the promotion of our products and services and those of our affiliates. It is not our policy to sell or rent lists of our website customers to unaffiliated third parties.<br /><br /> - - <b>Sharing with our Contractors.</b> We also may employ other companies and individuals to perform functions on our behalf. Examples include order fulfillment, package delivery, postal mail and e-mail communications, customer lists management, data analysis, marketing assistance, credit card processing, and customer relationship management. These companies and individuals have access to personal information needed to perform their functions, but they are not permitted to use such information for other purposes without our permission.<br /><br /> - + + <b>Sharing with our Contractors.</b> We also may employ other companies and individuals to perform functions on our behalf. Examples include order fulfillment, package delivery, postal mail and e-mail communications, customer lists management, data analysis, marketing assistance, credit card processing, and customer relationship management. These companies and individuals have access to personal information needed to perform their functions, but they are not permitted to use such information for other purposes without our permission.<br /><br /> + <b>Promotional Offers May be Sent to You.</b> We may send you offers on behalf of our company or other businesses, or permit other businesses that we are working with to send you offers, if we believe that you may be interested in receiving these offers. If, after receiving a non-order related email, you do not want to receive such emails in the future, you can notify us, by clicking on the "unsubscribe" link attached to each email.<br /><br /> - - + + <b>Sale or Acquisition of Business Units. </b>As we continue to develop our business, we may buy or sell business divisions or companies, we may merge or combine with another company, or our company itself, or all or a significant part of its assets, may be acquired by another company. In such transactions, customer information generally is one of the transferred and shared business assets. The information transferred and shared remains subject to the promises made in any pre-existing privacy notice (unless, of course, the customer has agreed to be subject to new privacy notice terms). <br /><br /> - - <b>Legal Requirements and Protection of - Gamestop.com and Others.</b> We may decide to release your account and other personal information if we believe release is appropriate or necessary to comply with the law, to enforce or apply our website terms of use and other agreements, or to protect the rights, property, or safety of + + <b>Legal Requirements and Protection of + Gamestop.com and Others.</b> We may decide to release your account and other personal information if we believe release is appropriate or necessary to comply with the law, to enforce or apply our website terms of use and other agreements, or to protect the rights, property, or safety of Gamestop.com, our users, or others. This information may be released or exchanged with other companies and organizations to protect against fraud, or for credit risk reduction. We will cooperate with law enforcement and judicial authorities, and we may provide personally identifiable information to appropriate government authorities upon receipt of a subpoena or court order, or to cooperate with a law enforcement investigation. We will fully cooperate with law enforcement agencies in identifying those who use our services for illegal activities. We also reserve the right to report to law enforcement agencies activities that we in good faith believe to be illegal. We undertake no obligation or duty to release such information, however, unless we are required to do so under applicable law.<br /><br /> - - <b>Other Circumstances.</b> If we want to share personal information other than as permitted or described above, we will notify you, and you may choose to instruct us not to share the information.<br /><br /> - + + <b>Other Circumstances.</b> If we want to share personal information other than as permitted or described above, we will notify you, and you may choose to instruct us not to share the information.<br /><br /> + <b>Third Party Relationships</b><br /><br /> - + <b>We have several types of third-party relationships.</b><ul> - - <li>We offer an affiliate program through a third-party affiliate manager. This program allows other websites to earn money by directing people (through links) to our website. If you sign up as an affiliate, your contact information (website address and related information, email address, mailing and payment addresses, and contact information) is sent to the third-party affiliate manager who activates your affiliate status and pays you based on the sales you generate for + + <li>We offer an affiliate program through a third-party affiliate manager. This program allows other websites to earn money by directing people (through links) to our website. If you sign up as an affiliate, your contact information (website address and related information, email address, mailing and payment addresses, and contact information) is sent to the third-party affiliate manager who activates your affiliate status and pays you based on the sales you generate for Gamestop.com. You may apply for this program using an Affiliate Program application. The Affiliate Program area is clearly labeled, and your information is never collected or shared unless you also fill out an Affiliate Program application.</li> <li>We work with business partners to provide you access to their products and services. For example, our website includes a link to www.alienware.com. Any information you supply upon entering the www.alienware.com site is collected by Alienware.</li> <li>We link to third-party surveys. When you complete a purchase, you are often invited to participate in a survey to rate your experience. The survey is conducted by a third party (and is identified as such) who shares all of the survey information with us, including your email address if you specify it in the survey. We use this information to gauge which areas of our service need improving.</li> <li>If you order from us after visiting Sony's Playstation.com web site we will forward your PlayStation Underground registration number to Sony along with any information regarding the products you have purchased.</li> </ul> <br /><br /> - - <b>Security of Information Stored by Us</b><br /><br /> - During transmission of information by you to our website, we use Secure Sockets Layer (SSL) software, which encrypts information you input. We reveal only the first two and last two digits of your credit card number when confirming an order, but we have to transmit the entire credit card number to the credit card processor or company during order processing.<br /><br /> - - To the extent that you use our website, and connect to us through your computer, anyone with access to your computer may be able to access our website and conduct transactions in your name. We have no ability to know who has access to your computer, or to your credit card information, or who you have authorized to use such computer or information. Persons with access to your computer may be able to view any private or stored account information or other information that you have given to us. Accordingly, you are responsible for any transactions that are made in your name by someone who has access to your computer or your credit card number. It is important for you to protect against unauthorized access to any login or password information, and to your computer.<br /><br /> - + + <b>Security of Information Stored by Us</b><br /><br /> + During transmission of information by you to our website, we use Secure Sockets Layer (SSL) software, which encrypts information you input. We reveal only the first two and last two digits of your credit card number when confirming an order, but we have to transmit the entire credit card number to the credit card processor or company during order processing.<br /><br /> + + To the extent that you use our website, and connect to us through your computer, anyone with access to your computer may be able to access our website and conduct transactions in your name. We have no ability to know who has access to your computer, or to your credit card information, or who you have authorized to use such computer or information. Persons with access to your computer may be able to view any private or stored account information or other information that you have given to us. Accordingly, you are responsible for any transactions that are made in your name by someone who has access to your computer or your credit card number. It is important for you to protect against unauthorized access to any login or password information, and to your computer.<br /><br /> + <b>You May Access, Change or Modify Your Personal Information</b><br /><br /> - + If you have purchased from us or created an account, our site provides you the opportunity to review, correct, or update your account information. You can do this by:<ol> <li>Accessing Gamestop.com and clicking on the "My Account" link.</li> <li>Sending mail to the following postal address:</li> @@ -2982,7 +2982,7 @@ <table id="table1" border="0"> <tbody><tr> <td>Gamestop.com Customer Service<br /> - + 625 Westport Parkway<br /> Grapevine, TX 76051</td> </tr> @@ -2990,30 +2990,30 @@ </center> <li>Calling the following telephone number: 1-800-883-8895</li> </ol> - + <br /><br /> - + <b>Your Right to Choose (Opt-Out)</b><br /><br /> You always may choose not to provide information. Obviously, if you choose not to provide necessary information, we may not be able to process your orders or inquiries. If we permit you to update any information that we store about you, we may keep a copy of the previous information for our records.<br /><br /> - + If, after receiving a non-order related email, you do not want to receive such emails in the future, you can notify us, by clicking on the "unsubscribe" link attached to each email. - + <br /><br /> - + <b>We May Change These Terms</b><br /><br /> - Whether or not you have viewed our terms and conditions of use of this website, or this privacy notice, and whether or not you have chosen to not receive notices from us, those terms and notices will still govern your use of - Gamestop.com. We may update or change our terms of use and this privacy notice at any time and from time to time, as we determine is appropriate. It is your responsibility to review them for changes.<br /><br /> - + Whether or not you have viewed our terms and conditions of use of this website, or this privacy notice, and whether or not you have chosen to not receive notices from us, those terms and notices will still govern your use of + Gamestop.com. We may update or change our terms of use and this privacy notice at any time and from time to time, as we determine is appropriate. It is your responsibility to review them for changes.<br /><br /> + <b>Use of Our Website by Children </b> - - <br /><br /> - - Gamestop.com does not sell products for purchase by children. We sell children's products for purchase by adults. If you are under 18, you may use - Gamestop.com only with the involvement of a parent or guardian. - - <br /><br /> - + + <br /><br /> + + Gamestop.com does not sell products for purchase by children. We sell children's products for purchase by adults. If you are under 18, you may use + Gamestop.com only with the involvement of a parent or guardian. + + <br /><br /> + <b>Terms and Conditions of Use, Notices, and Revisions</b><br /><br /> If you choose to visit our website, your visit and any dispute over privacy is subject to this privacy notice and our Terms and Conditions of Use, including limitations on damages, arbitration of disputes, and application of the law of the Commonwealth of Pennsylvania. If you have any concerns or questions about this privacy statement, the practices of this site, or your dealings with this website, you can contact: <center> @@ -3021,32 +3021,32 @@ <tbody><tr> <td>Gamestop.com Customer Service<br /> 625 Westport Parkway<br /> - + Grapevine, TX 76051</td> </tr> </tbody></table> </center> <br /><br /> - - As is the case with any business, our business changes over time, and our privacy notice and the Terms and Conditions of Use also will change. We may e-mail reminders of our notices and conditions. You should frequently check our website to see recent changes to these terms and policies. Unless stated otherwise, our current privacy notice applies to all information that we have about you and your account.<br /><br /> - - <b>Related Practices and Information</b><br /><br /> + + As is the case with any business, our business changes over time, and our privacy notice and the Terms and Conditions of Use also will change. We may e-mail reminders of our notices and conditions. You should frequently check our website to see recent changes to these terms and policies. Unless stated otherwise, our current privacy notice applies to all information that we have about you and your account.<br /><br /> + + <b>Related Practices and Information</b><br /><br /> Terms and Conditions of Use may be found by <a href="/gs/help/disclaimer.aspx">clicking here.</a> </span> - - + + </div> </td> <td valign="top" style="padding:0; margin:0px"></td> </tr> <tr> <td id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_MainContentPlaceHolder_PrivacyMessageCtl1_popEditAddress_tdBottomImage" colspan="3" style="padding:0; margin:0px" align="center"> - + </td> - + </tr> </table> - + </div> @@ -3060,10 +3060,10 @@ </div> </div> - + <style type="text/css"> - .modalBackground + .modalBackground { background-color:Gray; filter:alpha(opacity=70); @@ -3072,33 +3072,33 @@ </style> <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_Loading_UpdateProgress1" style="display:none;"> - + <div id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_Loading_pnlLoading" style="text-align:center; width:150px; background-color:White; border:solid 1px #333333; padding:10px;"> - + <span id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_Loading_lblPleaseWait" class="boldcopy">Please wait....</span> <br /> <img id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_mainContentPlaceHolder_Loading_Image1" src="#" style="border-width:0px;" /> - + </div> - + </div> - - - + + + </div> <br /><img src="#" height="15" width="15" border="0"> </td> <td width="145" valign="top"> <table width="145" border="0" cellpadding="0" cellspacing="0"> - + </table> - + </td> - </tr> + </tr> </table> </div></div> - + <div class="clear"></div> <div id="footer" > <div id="footerContainer" class="container_24"> @@ -3143,14 +3143,14 @@ </ul> </div> <div id="footer_powerup" class="grid_5"> - + <h3>PowerUp Rewards™</h3> <ul style="margin-bottom:16px"> <li><a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cFooter_lnkPowerUpBenefits" href="http://www.poweruprewards.com/Home/Benefits" target="_blank">Why It Rocks</a></li> <li><a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cFooter_lnkPowerUpFAQ" href="http://www.poweruprewards.com/Home/FAQ" target="_blank">FAQs</a></li> <li><a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cFooter_lnkPowerUpDeals" href="/gs/landing/powerup">What Is It</a></li> </ul> - + <h3 style="background-image: url(/common/css/gamestopdotcom/images/EdgeCardIconFooter.png);">Trade Card</h3> <ul> <li><a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cFooter_lnkEdgeCard" href="/gs/help/Edge_Card.aspx">Card Help</a></li> @@ -3173,23 +3173,23 @@ <li><a id="ctl00_ctl00_ctl00_BaseContentPlaceHolder_cFooter_lnkDisclaimer" href="/gs/help/disclaimer.aspx">Conditions of Use</a></li> <li></li> </ul> - - + + </div> </div> - - - + + + <!-- START OF Google Analytics Tracking Code --> <!-- END OF Google Analytics Tracking Code --> - - + + @@ -3209,15 +3209,15 @@ </form> </div> - - - - - - - + + + + + + + </body> </html> <span></span>
diff --git a/components/test/data/autofill/heuristics/input/026_checkout_ikea.com.html b/components/test/data/autofill/heuristics/input/026_checkout_ikea.com.html index c40c1a6a..b31a8f6f 100644 --- a/components/test/data/autofill/heuristics/input/026_checkout_ikea.com.html +++ b/components/test/data/autofill/heuristics/input/026_checkout_ikea.com.html
@@ -1,42 +1,42 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml"> + +<html xmlns="http://www.w3.org/1999/xhtml"> <head> - <title>IKEA | Billing Address</title> - + <title>IKEA | Billing Address</title> + <meta name="IRWStats.pageType" content="Checkout" /> <meta name="IRWStats.category" content="Checkout"/> <meta name="IRWStats.subCategory" content="billing and shipping"/> <meta name="IRWStats.categoryLocal" content="Checkout"/> <meta name="IRWStats.subCategoryLocal" content="Billing and Shipping - step 1"/> <meta name="IRWStats.internalPageType" content="ecom-step1" /> - - + + <meta name="IRWStats.memberSignupStart" content="yes" /> <meta name="IRWStats.checkoutStart" content="yes" /> - + <meta name="IRWStats.checkoutGuest" content="yes" /> - + <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" /> </head> -<body> +<body> - <form name="signup_checkout_private" id="signup_checkout_private" action="IrwProceedFromBillingAddressView" method="post" autocomplete="off"> + <form name="signup_checkout_private" id="signup_checkout_private" action="IrwProceedFromBillingAddressView" method="post"> <input type="hidden" name="authToken" value="376866552%2cfe3%2bU3t3PF7ZxkOL%2fZ%2fIadn8at4%3d" id="signup_authToken_In_Register_1"/> - <input type="hidden" name="orderId" value="70854417"/> + <input type="hidden" name="orderId" value="70854417"/> <input type="hidden" name="storeId" value="12" /> <input type="hidden" name="langId" value="-1" /> <input type="hidden" name="lateAddressEdit" value="false" /> - + <input type="hidden" name="business" value="0"> - + <input type="hidden" name="validationMode" value="newCustomer"> - + <div id="signupErrorTier"></div> - + <div id="billingBox"><!-- begin billing address --> <div class="halfBox"><!-- column 1 --> @@ -44,21 +44,21 @@ <div id="firstName_label" class="formLabel"><label for="firstName">First Name:</label></div> <div> <div id="firstName_input" class="formInput"><input type="text" name="firstName" id="signup_checkout_private_firstName" value="" maxlength="15"></div> - - <div class="formError"></div> - + + <div class="formError"></div> + <div class="clearBox"> </div> </div> </div> - + <div id="lastName_field" class="formField"> <div id="lastName_label" class="formLabel"><label for="lastName">Last Name:</label></div> <div> <div id="lastName_input" class="formInput"><input type="text" name="lastName" id="signup_checkout_private_lastName" value="" maxlength="30"></div> - - <div class="formError"></div> - + + <div class="formError"></div> + <div class="clearBox"> </div> </div> @@ -68,267 +68,267 @@ <div id="address1_label" class="formLabel"><label for="address1">Address 1:</label></div> <div> <div id="address1_input" class="formInput"><input type="text" name="address1" id="signup_checkout_private_address1" value="" maxlength="30"></div> - - <div class="formError"></div> - + + <div class="formError"></div> + <div class="clearBox"> </div> </div> </div> - - - <div id="address2_field" class="formField"> + + + <div id="address2_field" class="formField"> <div id="address2_label" class="formLabel"><label for="address2">Address 2:<span class="optional"> (Optional)</span></label></div> <div> <div id="address2_input" class="formInput"><input type="text" name="address2" id="signup_checkout_private_address2" value="" maxlength="30"></div> - - <div class="formError"></div> - + + <div class="formError"></div> + <div class="clearBox"> </div> </div> </div> - + <div id="state_field" class="formField"> <div id="state_label" class="formLabel"><label for="state">State:</label></div> <div> <div id="state_input" class="formInput"> <select id="signup_checkout_private_state" name="state"> <option value="">Choose state</option> - + <option value="AL">Alabama</option> - + <option value="AK">Alaska</option> - + <option value="AZ">Arizona</option> - + <option value="AR">Arkansas</option> - + <option value="CA">California</option> - + <option value="CO">Colorado</option> - + <option value="CT">Connecticut</option> - + <option value="DE">Delaware</option> - + <option value="DC">District Of Columbia</option> - + <option value="FL">Florida</option> - + <option value="GA">Georgia</option> - + <option value="ID">Idaho</option> - + <option value="IL">Illinois</option> - + <option value="IN">Indiana</option> - + <option value="IA">Iowa</option> - + <option value="HI">Hawaii</option> - + <option value="KS">Kansas</option> - + <option value="KY">Kentucky</option> - + <option value="LA">Louisiana</option> - + <option value="ME">Maine</option> - + <option value="MD">Maryland</option> - + <option value="MA">Massachusetts</option> - + <option value="MI">Michigan</option> - + <option value="MN">Minnesota</option> - + <option value="MS">Mississippi</option> - + <option value="MO">Missouri</option> - + <option value="MT">Montana</option> - + <option value="NE">Nebraska</option> - + <option value="NV">Nevada</option> - + <option value="NH">New Hampshire</option> - + <option value="NJ">New Jersey</option> - + <option value="NM">New Mexico</option> - + <option value="NY">New York</option> - + <option value="NC">North Carolina</option> - + <option value="ND">North Dakota</option> - + <option value="OH">Ohio</option> - + <option value="OK">Oklahoma</option> - + <option value="OR">Oregon</option> - + <option value="PA">Pennsylvania</option> - + <option value="RI">Rhode Island</option> - + <option value="SC">South Carolina</option> - + <option value="SD">South Dakota</option> - + <option value="TN">Tennessee</option> - + <option value="TX">Texas</option> - + <option value="UT">Utah</option> - + <option value="VT">Vermont</option> - + <option value="VA">Virginia</option> - + <option value="WA">Washington</option> - + <option value="WV">West Virginia</option> - + <option value="WI">Wisconsin</option> - + <option value="WY">Wyoming</option> - - </select> + + </select> </div> - - <div class="formError"></div> - + + <div class="formError"></div> + <div class="clearBox"> </div> </div> </div> - + <div id="zipCode_field" class="formField"> <div id="zipCode_label" class="formLabel"><label for="zipCode">Zip Code:</label></div> <div> <div id="zipCode_input" class="formInput"> <input type="text" size="10" name="zipCode" id="signup_checkout_private_zipCode" value="" maxlength="8"> - + </div> - - <div class="formError"></div> - + + <div class="formError"></div> + <div class="clearBox"> </div> </div> <div id="zipCode_sample" class="formSample">Example: 55555</div> </div> - + <div id="city_field" class="formField"> <div id="city_label" class="formLabel"><label for="city">City:</label></div> <div> <div id="city_input" class="formInput"><input type="text" name="city" id="signup_checkout_private_city" value="" maxlength="30"></div> - - <div class="formError"></div> - + + <div class="formError"></div> + <div class="clearBox"> </div> </div> </div> - + <input type="hidden" name="country" value="US"> - - + + <div id="email1_field" class="formField"> <div id="email1_label" class="formLabel"><label for="email1">Email:</label></div> <div> <div id="email1_input" class="formInput"><input style="-moz-user-select: none;" type="text" name="email1" value="" maxlength="60" id="signup_checkout_private_email1"></div> - - <div class="formError"></div> - + + <div class="formError"></div> + <div class="clearBox"> </div> </div> <div id="email1_sample" class="formSample">Example: xx@xxx.xx</div> </div> - - + + <div id="email1retype_field" class="formField"> <div id="email1retype_label" class="formLabel"><label for="email1retype">Re-type Email:</label></div> <div> <div id="email1retype_input" class="formInput"><input style="-moz-user-select: none;" type="text" name="email1retype" value="" maxlength="60" id="signup_checkout_private_email1retype"></div> - - <div class="formError"></div> - + + <div class="formError"></div> + <div class="clearBox"> </div> </div> </div> - + <div id="phone1_field" class="formField"> <div id="phone1_label" class="formLabel"><label for="phone1">Primary Tel Number:</label></div> <div> <div id="phone1_input" class="formInput hasExt"> <input type="text" size="8" name="phone1" id="signup_checkout_private_phone1" value="" maxlength="15"> - + <label for="phone1ext"> <span class="formText" id="phone1ext_text">Ext:</span><span class="optional"> (Optional)</span> </label> <input type="text" size="2" name="phone1ext" id="signup_checkout_private_phone1ext" value="" maxlength="10"> - + </div> - - <div class="formError"></div> - + + <div class="formError"></div> + <div class="clearBox"> </div> </div> <div id="phone1_sample" class="formSample">Example: 2155551212</div> </div> - + <div id="phone2_field" class="formField"> <div id="phone2_label" class="formLabel"><label for="phone2">Alternative Number:</label></div> <div> <div id="phone2_input" class="formInput hasExt"> <input type="text" size="8" name="phone2" id="signup_checkout_private_phone2" value="" maxlength="15"> - + <label for="phone2ext"> <span class="formText" id="phone2ext_text">Ext:</span><span class="optional"> (Optional)</span> </label> <input type="text" size="2" name="phone2ext" id="signup_checkout_private_phone2ext" value="" maxlength="10"> - + </div> - - <div class="formError"></div> - + + <div class="formError"></div> + <div class="clearBox"> </div> </div> </div> - + <div id="fax1_field" class="formField"> <div id="fax1_label" class="formLabel"><label for="fax1">Fax Number:<span class="optional"> (Optional)</span></label></div> <div> <div id="fax1_input" class="formInput hasExt"> <input type="text" size="8" name="fax1" id="signup_checkout_private_fax1" value="" maxlength="20"> - + <label for="fax1ext"> <span class="formText" id="fax1ext_text">Ext:</span><span class="optional"> (Optional)</span> </label> <input type="text" size="2" name="fax1ext" id="signup_checkout_private_fax1ext" value="" maxlength=""> - + </div> - - <div class="formError"></div> - + + <div class="formError"></div> + <div class="clearBox"> </div> </div> </div> - + </div> <!-- end column 1 --> - + <div class="clearBox"> </div> </div> <!-- end billing address --> </div><!-- end boxContent --> @@ -352,16 +352,16 @@ </div><!-- end boxContent --> </div><!-- end tier6 / privacy policy --> <div id="tier7"><!-- final links and continue button --> <div class="boxContent"> - - - + + + <noscript> <div class="buttonContainer"><a ><div class="buttonLeft"> </div><div class="buttonCaption"><input type="submit" name="submitButton_IrwAddressDetails" value="Save & Continue" /></div><div class="buttonRight"> </div></a></div> </noscript> - <div style="clear:both; font-size:0px;"> </div> + <div style="clear:both; font-size:0px;"> </div> </div> <!-- end boxContent --> - </div> <!-- end teir7 / final links and continue button --> - </form> + </div> <!-- end teir7 / final links and continue button --> + </form> </body> </html>
diff --git a/components/test/data/autofill/heuristics/input/027_checkout_jcrew.com.html b/components/test/data/autofill/heuristics/input/027_checkout_jcrew.com.html index 452cebb..49124cc 100644 --- a/components/test/data/autofill/heuristics/input/027_checkout_jcrew.com.html +++ b/components/test/data/autofill/heuristics/input/027_checkout_jcrew.com.html
@@ -1,7 +1,7 @@ <!-- BEGIN MBOX INCLUDE --> - + <!-- END MBOX INCLUDE --> <!-- Upgraded to BM 9.0.3.3.1 --> @@ -28,7 +28,7 @@ <head> <title>J.Crew > </title> <!-- page meta tags --> - + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <!--name of css file will be a folder attribute--> <meta http-equiv="Expires" content="Sun, 28 Dec 1997 09:32:45 GMT" /> @@ -53,7 +53,7 @@ <input type="hidden" name="bmPrevTemplate" value="/checkout/addShippingAddress.jsp"> <table height="35px" cellspacing="0" border="0"> <tr valign="middle"> - <td align="right"><input type="hidden" name="bmText" value="searchTerm"><input type="text" class="search_box" name="searchTerm" id='searchTerm' maxlength="40" size="25" value="search keyword or item #" secure="false" autocomplete="off"></td> + <td align="right"><input type="hidden" name="bmText" value="searchTerm"><input type="text" class="search_box" name="searchTerm" id='searchTerm' maxlength="40" size="25" value="search keyword or item #" secure="false"></td> <td align="right" style="padding-left: 2px;"><input type="hidden" name="bmImage" value="findIt.x"><input type="hidden" name="bmImage" value="findIt.y"><input type="hidden" name="bmImage" value="findIt"><input type="image" name="findIt" src="#" border="0" style="cursor:hand;" alt="go" ></td> </tr> </table> @@ -73,7 +73,7 @@ <input type="hidden" name="bmUID" value="1307070130815"> <input type="hidden" name="bmIsForm" value="true"> <input type="hidden" name="bmPrevTemplate" value="/checkout/addShippingAddress.jsp"> - + <!-- this is the START of shopping bag pop-up--> <div style="position:absolute;top:110px;width:291;display:none;z-index:20;" id="persistShoppingBag" name="persistShoppingBag"> @@ -122,14 +122,14 @@ <div id="qaspopDiv" class="formErrorcopy" style="display:none">Your address does not match with what is provided by the US Postal Service. To update it <a href ="#" >click here</a>.</div></td> </tr> <tr> - <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">country *</td> + <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">country *</td> </tr> <tr> <td valign="top" class="generalcopydkgrey"><input type="hidden" name="bmSingle" value="ADDRESS<>country_cd"><input type="hidden" name="bmRequired" value="ADDRESS<>country_cd"><select tabindex="1" id="country" name="ADDRESS<>country_cd" onchange="javascript:submitAddressForm('refresh');" style="width:280"> <option value="US">United States</option> <option value="CA">Canada</option> <option value="JP">Japan</option> -</select></td> +</select></td> </tr> <!--<tr> <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">alias</td> @@ -138,10 +138,10 @@ <td valign="top" class="generalcopydkgrey"><input type="text" name="ADDRESS<>label" id="alias" size="27" /></td> </tr>--> <tr> - <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">first name *</td> + <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">first name *</td> </tr> <tr> - <td valign="top" class="generalcopydkgrey"><input type="hidden" name="bmText" value="ADDRESS<>firstName"><input type="hidden" name="bmRequired" value="ADDRESS<>firstName"><input type="text" tabindex="2" name="ADDRESS<>firstName" id="firstName" style="width:280"/></td> + <td valign="top" class="generalcopydkgrey"><input type="hidden" name="bmText" value="ADDRESS<>firstName"><input type="hidden" name="bmRequired" value="ADDRESS<>firstName"><input type="text" tabindex="2" name="ADDRESS<>firstName" id="firstName" style="width:280"/></td> </tr> <!--<tr> <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">middle name</td> @@ -150,17 +150,17 @@ <td valign="top" class="generalcopydkgrey"><input type="text" name="ADDRESS<>middleName" id="middleName" size="27" /></td> </tr>--> <tr> - <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">last name *</td> + <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">last name *</td> </tr> <tr> - <td valign="top" class="generalcopydkgrey"><input type="hidden" name="bmText" value="ADDRESS<>lastName"><input type="hidden" name="bmRequired" value="ADDRESS<>lastName"><input type="text" tabindex="3" name="ADDRESS<>lastName" id="lastName" style="width:280"/></td> + <td valign="top" class="generalcopydkgrey"><input type="hidden" name="bmText" value="ADDRESS<>lastName"><input type="hidden" name="bmRequired" value="ADDRESS<>lastName"><input type="text" tabindex="3" name="ADDRESS<>lastName" id="lastName" style="width:280"/></td> </tr> <tr> - <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">company/care of</td> + <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">company/care of</td> </tr> <tr> - <td valign="top" class="generalcopydkgrey"><input type="hidden" name="bmText" value="ADDRESS<>address3"><input tabindex="4" type="text" name="ADDRESS<>address3" style="width:280"/></td> - </tr> + <td valign="top" class="generalcopydkgrey"><input type="hidden" name="bmText" value="ADDRESS<>address3"><input tabindex="4" type="text" name="ADDRESS<>address3" style="width:280"/></td> + </tr> <tr> <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;" colspan="2">address line 1 *</td> </tr> @@ -173,18 +173,18 @@ <tr> <td valign="top" class="generalcopydkgrey" colspan="2"><input type="hidden" name="bmText" value="ADDRESS<>address2"><input type="text" tabindex="6" name="ADDRESS<>address2" id="address2" style="width:280"/></td> </tr> - <tr> + <tr> <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">city *</td> </tr> <tr> <td valign="top" class="generalcopydkgrey"><input type="hidden" name="bmText" value="ADDRESS<>city"><input type="hidden" name="bmRequired" value="ADDRESS<>city"><input type="text" tabindex="7" name="ADDRESS<>city" id="city" style="width:280"/></td> </tr> <tr> - <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">state/province *</td> + <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">state/province *</td> </tr> <tr> <td valign="top" class="generalcopydkgrey"> - + <!-- show drop-down if statelist exists (US/CA) --> <input type="hidden" name="bmSingle" value="ADDRESS<>state_cd"><input type="hidden" name="bmRequired" value="ADDRESS<>state_cd"><select tabindex="8" id="state" name="ADDRESS<>state_cd" style="width:280"> <option value="">Choose a value</option> @@ -249,22 +249,22 @@ <option value="WY">Wyoming</option> <option value="WA">Washington</option> <option value="DC">Washington, D.C.</option> -</select><input type="hidden" name="bmDynamic" value="ADDRESS<>state_cd:AL:AK:AS:AA:AE:AP:AZ:AR:CA:CO:CT:DE:FL:GA:GU:HI:ID:IL:IN:IA:KS:KY:LA:ME:MD:MA:MI:MN:MS:MO:MT:NE:NV:NH:NJ:NM:NY:NC:ND:MP:OH:OK:OR:PW:PA:PR:RI:SC:SD:TN:TX:UM:UT:VT:VI:VA:WV:WI:WY:WA:DC:"> - +</select><input type="hidden" name="bmDynamic" value="ADDRESS<>state_cd:AL:AK:AS:AA:AE:AP:AZ:AR:CA:CO:CT:DE:FL:GA:GU:HI:ID:IL:IN:IA:KS:KY:LA:ME:MD:MA:MI:MN:MS:MO:MT:NE:NV:NH:NJ:NM:NY:NC:ND:MP:OH:OK:OR:PW:PA:PR:RI:SC:SD:TN:TX:UM:UT:VT:VI:VA:WV:WI:WY:WA:DC:"> + </td> </tr> <tr> - <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">zip code *</td> + <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">zip code *</td> </tr> - <tr> + <tr> <td valign="top" class="generalcopydkgrey"><input type="hidden" name="bmText" value="ADDRESS<>postal"><input type="hidden" name="bmRequired" value="ADDRESS<>postal"><input type="text" tabindex="9" name="ADDRESS<>postal" id="zipCode" size="12"/></td> </tr> <tr> - <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">phone number (numbers only) *</td> + <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">phone number (numbers only) *</td> </tr> <tr> <td valign="top" class="generalcopydkgrey"><input type="hidden" name="bmText" value="ADDRESS<>phone"><input type="hidden" name="bmRequired" value="ADDRESS<>phone"><input type="text" tabindex="10" name="ADDRESS<>phone" id="phoneNum" style="width:280"/><!-- <input type="text" tabindex="11" name="ADDRESS<>ATR_phone_ext" id="phoneNum" size="6" required="false" />--></td> - </tr> + </tr> <tr> <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;" colspan="2">note: you will be able to add more<br>addresses and ship your order to multiple<br>addresses on the next page<br /><br /></td> </tr> @@ -286,37 +286,37 @@ <tr> <td valign="top" class="generalcopydkgrey" style="padding-top:5px; padding-bottom:3px;">you will be asked to enter gift card information<br>on the billing page<br /><br /></td> </tr>--> - + <input type="hidden" name="bmEditable" value="qasVerificationDone"><input type="hidden" name="bmHidden" value="qasVerificationDone"><input type="hidden" id="qasVerificationDone" name="qasVerificationDone" value="no"/> <input type="hidden" name="bmEditable" value="isQasDone"><input type="hidden" name="bmHidden" value="isQasDone"><input type="hidden" id="isQasDone" name="isQasDone" value="no"/> - + </table> <!-- end new shipping address --> </td> <td width="3" bgcolor="#ffffff"><img src="#" height="3" /></td> <td align="center" width="258" valign="top"> - + <table width="310" align="center" cellpadding="0" cellspacing="0" border="0"> <tr> <td class="orderTableTitleWhite" height="25" width="258"> <!-- show label only in case of guest user --> - + create an account (optional) - + </td> </tr> </table> <table width="310" align="center" cellpadding="0" cellspacing="0" border="0" height="265" style="border-left:1px solid #bdbdbd;border-right:1px solid #bdbdbd;border-bottom:1px solid #bdbdbd;"> <tr> <td valign="top" class="generalcopydkgrey" style="padding-top:5px;"> - + <!-- show these messages only in case of guest user --> <b>don't forget to register.</b> <br />Please note: We've recently enhanced our check-out process. To make sure your records are as up to date as possible, you may be asked to create a new account with your information. Your updates will be securely stored and you won't have to enter your information again. - + </td> </tr> - + <!-- register a guest user --> <tr> <td valign="top" class="generalcopydkgrey">create password</td> @@ -336,10 +336,10 @@ <tr> <td valign="top" class="generalcopydkgrey" style="padding-top:5px;"><input type="hidden" name="bmText" value="anonPasswordHint"><input tabindex="14" type="text" name="anonPasswordHint" id="passwordHint" size="27"/></td> </tr> - + <!-- end register a guest user --> </table> - + <table cellspacing="0" cellpadding="0" border="0" align="center" width="310" height="43" class="topRowBC"> <tr> <td align="right"> @@ -347,7 +347,7 @@ <a ><img tabindex="15" id="continueCheckout" src="#" border="0" /></a> </td> </tr> - </table> + </table> </td> </tr> </table>
diff --git a/components/test/data/autofill/heuristics/input/046_register_bestbuy.com.html b/components/test/data/autofill/heuristics/input/046_register_bestbuy.com.html index 04da388..a00359e 100644 --- a/components/test/data/autofill/heuristics/input/046_register_bestbuy.com.html +++ b/components/test/data/autofill/heuristics/input/046_register_bestbuy.com.html
@@ -8,7 +8,7 @@ <meta http-equiv="pragma" content="no-cache"> </head> <body> - + <form action="/site/olspage.jsp" name="frmSearch" method="GET"> @@ -88,16 +88,16 @@ </tr></table> <span class="Body-Small"> <div style="margin-top:6px;"> -<b>*E-Mail Address</b><br><input value="" autocomplete="off" maxlength="50" type="text" style="width:300px;" size="35" name="TxtEmail"><input value=" " type="hidden" name="_D:TxtEmail"> <br> +<b>*E-Mail Address</b><br><input value="" maxlength="50" type="text" style="width:300px;" size="35" name="TxtEmail"><input value=" " type="hidden" name="_D:TxtEmail"> <br> </div> <div style="margin-top:6px;"> -<b>*Retype E-Mail Address</b><br><input value="" autocomplete="off" maxlength="50" type="text" style="width:300px;" size="35" name="TxtEmailConfirm"><input value=" " type="hidden" name="_D:TxtEmailConfirm"> <br> +<b>*Retype E-Mail Address</b><br><input value="" maxlength="50" type="text" style="width:300px;" size="35" name="TxtEmailConfirm"><input value=" " type="hidden" name="_D:TxtEmailConfirm"> <br> </div> <div style="margin-top:6px;"> -<!-- fl6 --><strong>*Password</strong> (6 to 30 characters. At least one number.)<br><input value="" autocomplete="off" maxlength="30" type="password" style="width:150px;" size="25" name="PwdPassword"><input value=" " type="hidden" name="_D:PwdPassword"> <br> +<!-- fl6 --><strong>*Password</strong> (6 to 30 characters. At least one number.)<br><input value="" maxlength="30" type="password" style="width:150px;" size="25" name="PwdPassword"><input value=" " type="hidden" name="_D:PwdPassword"> <br> </div> <div style="margin-top:6px;"> -<!-- fl8 --><strong>*Retype Password</strong> (must match exactly)<br><input value="" autocomplete="off" maxlength="30" type="password" style="width:150px;" size="25" name="PwdPasswordConfirm"><input value=" " type="hidden" name="_D:PwdPasswordConfirm"> <br> +<!-- fl8 --><strong>*Retype Password</strong> (must match exactly)<br><input value="" maxlength="30" type="password" style="width:150px;" size="25" name="PwdPasswordConfirm"><input value=" " type="hidden" name="_D:PwdPasswordConfirm"> <br> </div> <div style="margin-top:6px;"> <b>*ZIP Code</b><br><input value="" maxlength="5" type="text" style="width:150px;" size="25" name="TxtPostalCode"><input value=" " type="hidden" name="_D:TxtPostalCode"><input value="" type="hidden" name="TxtShipPostalCode"><input value=" " type="hidden" name="_D:TxtShipPostalCode"><input value="" type="hidden" name="TxtBillPostalCode"><input value=" " type="hidden" name="_D:TxtBillPostalCode"><br>
diff --git a/components/test/data/autofill/heuristics/input/055_register_imdb.com.html b/components/test/data/autofill/heuristics/input/055_register_imdb.com.html index a87c20b9..45dcc9f 100644 --- a/components/test/data/autofill/heuristics/input/055_register_imdb.com.html +++ b/components/test/data/autofill/heuristics/input/055_register_imdb.com.html
@@ -36,7 +36,7 @@ <option value="vi">Videos</option> <option value="qu">Quotes</option> <option value="bi">Bios</option> -<option value="pl">Plots</option></select><input id="navbar-query" name="q" type="text" value="" autocomplete="off"> <button class="nb_primary" type="submit">Go</button><noscript>  <a href="/search/">More</a> +<option value="pl">Plots</option></select><input id="navbar-query" name="q" type="text" value=""> <button class="nb_primary" type="submit">Go</button><noscript>  <a href="/search/">More</a> </noscript> <div id="navbar-suggestionsearch"></div> </div>
diff --git a/components/test/data/autofill/heuristics/input/057_register_live.com.html b/components/test/data/autofill/heuristics/input/057_register_live.com.html index ddf67d1..0a64f0a 100644 --- a/components/test/data/autofill/heuristics/input/057_register_live.com.html +++ b/components/test/data/autofill/heuristics/input/057_register_live.com.html
@@ -9,7 +9,7 @@ -<form id="SignUpForm" method="post" action="" autocomplete="off" > +<form id="SignUpForm" method="post" action="" > <div class="helparea"> <div id="cmembernamelive" class="row"> @@ -22,7 +22,7 @@ Working...</p> <label for="imembernamelive"> Windows Live ID: - + </label> <div id="memnamecont"> <input id="imembernamelive" name="imembernamelive" type="text" maxlength="64" value="" ><span id="mnat">@</span><select id="idomain" name="idomain" ><option value="hotmail.com">hotmail.com</option> @@ -70,16 +70,16 @@ </div> </div> </div> - + <div id="chkavail"> <button id="ichkavailbutton" type="button" title="Check availability" > Check availability</button> </div> - + <p id="easilinkctr" class="linkinline"> <a id="ieasiswitch" href="#" > Or use your own email address</a></p> - + </div> <div class="helppop"> <div id="membernamelivehelp" class="helpctr"> @@ -105,7 +105,7 @@ <input id="imembernameeasi" name="imembernameeasi" class="inputhint" type="text" maxlength="112" value="Example: someone@example.com" ><br><p id="livelinkctr" class="linkinline"> <a id="iliveswitch" href="#" > Or get a Windows Live email address</a></p> - + </div> <div class="helppop"> <div id="membernameeasihelp" class="helpctr"> @@ -184,7 +184,7 @@ </div> <div class="helparea"> - + <div class="row"> <p id="iFirstNameError" class="error"> </p> @@ -199,7 +199,7 @@ Last name:</label> <input id="iLastName" name="iLastName" type="text" maxlength="40" value="" ><br> </div> - + <div class="helppop"> <div id="namehelp" class="helpctr"> </div> @@ -239,39 +239,39 @@ <div class="helparea"> <div id="iHipHolder" > - + <input type="hidden" id="WLX_HIP_V3_CONTAINER_wlxsignup" name="WLX_HIP_V3_CONTAINER" value="wlxsignup"><div style="width:265px" id="WLX_HIP_CONTR_wlxsignup"> <div id="WLX_HIP_ERR_NOTIF" class="UI_NotificationBar ErrorHigh" style="display:none "></div> - - - + + + <div id="WLX_HIP_CTL_wlxsignup" style="display:inline"> <img src="#" alt="Loading...">   Loading... - + </div> - + <div id="WLX_HIP_CTL_ERRLoad_wlxsignup" style="display:none"> <div class="UI_NotificationBar ErrorHigh" style=" "> We weren't able to load the challenge. Please click <a href="#" >here</a> to try again. </div> </div> - - <div id="WLX_HIP_SCRIPT_wlxsignup" style="display:inline"> - + + <div id="WLX_HIP_SCRIPT_wlxsignup" style="display:inline"> + </div> - + <input type="hidden" id="WLX_HIP_FLID_wlxsignup" name="WLX_HIP_FLID_wlxsignup" value="5b722ad1-5304-4838-9285-cbb91ce3b66c"><input type="hidden" id="WLX_HIP_FLHASH_wlxsignup" name="WLX_HIP_FLHASH_wlxsignup" value="KE4AFQnappbqtw++CPqy"><input type="hidden" id="WLX_HIP_SOL_wlxsignup" name="WLX_HIP_SOL_wlxsignup" value=""><input type="hidden" id="WLX_HIP_FRAME_wlxsignup" name="WLX_HIP_FRAME_wlxsignup" value=""><input type="hidden" id="WLX_HIP_CHLG_wlxsignup" name="WLX_HIP_CHLG_wlxsignup" value=""> </div> - + <div style="display:none; width:265px;" id="WLX_HIP_CONTR_wlxsignup_DISABLED"> <div id="WLX_HIP_ERR_DISABLED" class="UI_NotificationBar ErrorHigh" style=" "> <span>Only one challenge can be displayed at a time and an additional challenge has been opened on this page. Please complete that challenge before continuing.</span> </div> </div> - - + + <p id="iHIPError" style="display:none;"> </p> </div> @@ -292,7 +292,7 @@ <div class="topbotrow"> <div class="bluebar">  </div> - + <div id="tou"> Clicking <strong>I accept</strong> means that you agree to the <a target="_new" href="http://g.msn.com/0TO_/enus">Microsoft service agreement</a> and <a target="_new" href="http://g.msn.com/2privacy/enus">privacy statement</a>. <span id="iOptinEmailAgreement" class=""> You also agree to receive email from Windows Live, Bing, and MSN with service updates, special offers, and survey invitations. You can unsubscribe at any time.</span> @@ -300,7 +300,7 @@ <div id="createbuttons"> <button type="submit" title="I accept" > I accept</button> - + </div> <div id="creatingacct" class="hide"> <p>
diff --git a/components/test/data/autofill/heuristics/input/062_register_newegg.com.html b/components/test/data/autofill/heuristics/input/062_register_newegg.com.html index 2550ed1f..e3edcfd 100644 --- a/components/test/data/autofill/heuristics/input/062_register_newegg.com.html +++ b/components/test/data/autofill/heuristics/input/062_register_newegg.com.html
@@ -28,7 +28,7 @@ <td rowspan="2" id="haQuickSearchLabel"></td> <td rowspan="2" id="haQuickSearchTextbox"> <label for="haQuickSearchBox"><span style="display:none;">Search site</span></label> - <input id="haQuickSearchBox" name="Description" tabindex="1" title="Search site" maxlength="50" value="" type="text" autocomplete="off"><br><div id="autofilledview"></div> + <input id="haQuickSearchBox" name="Description" tabindex="1" title="Search site" maxlength="50" value="" type="text"><br><div id="autofilledview"></div> </td> <td rowspan="2" id="haQuickSearchSubmit"><input type="image" src="#" alt="Go search" tabindex="2" class="csp"></td> <td id="haQuickSearchInfoTab"> @@ -52,7 +52,7 @@ <form name="customer" method="post" action="https://secure.newegg.com/NewMyAccount/AccountRegistration.aspx"> - <input name="action" type="hidden" value="Add"><input name="nextpage" type="hidden" value=""><h2>Newegg ID and Password</h2> + <input name="action" type="hidden" value="Add"><input name="nextpage" type="hidden" value=""><h2>Newegg ID and Password</h2> <div class="acn tbk"> <p>Please enter the following information, and keep a record of it. You will need this information to log onto your Newegg.com account. </p> @@ -77,10 +77,10 @@ <li class="clear"> </ul> </div> - + <h2>Billing Information</h2> <div class="acn tbk"> - <p>This address must match the address that your monthly credit card statement or monthly bank statement is sent to. If this condition is not met, your order will not be processed. To prevent unnecessary delays, please verify that your billing address matches the address on your statement before ordering. + <p>This address must match the address that your monthly credit card statement or monthly bank statement is sent to. If this condition is not met, your order will not be processed. To prevent unnecessary delays, please verify that your billing address matches the address on your statement before ordering. </p> <ul class="noBorder"> <li class="w25"><label for="FirstName">First Name*</label></li> @@ -220,15 +220,15 @@ <div id="ShippingInfo" style="display:none"> <h2>Shipping Information</h2> <div class="acn tbk"> - Newegg.com does not ship to international addresses or P.O. Boxes. Please allow 1 additional business day to verify an alternate ship-to address. Shipping to a + Newegg.com does not ship to international addresses or P.O. Boxes. Please allow 1 additional business day to verify an alternate ship-to address. Shipping to a -verifiable billing address is much safer and consequently applicable orders will be approved for shipment quicker.<br><br>If your shipping and billing +verifiable billing address is much safer and consequently applicable orders will be approved for shipment quicker.<br><br>If your shipping and billing -addresses differ, additional information is required to help Newegg.com verify the validity of your payment and the shipping destination.<br><br>Immediately contact +addresses differ, additional information is required to help Newegg.com verify the validity of your payment and the shipping destination.<br><br>Immediately contact -your card issuer and have your shipping address added as an authorized alternate ship-to location in your account's memo or notes field. We will contact your +your card issuer and have your shipping address added as an authorized alternate ship-to location in your account's memo or notes field. We will contact your -card issuer using the bank telephone number you provided during the checkout procedure so that we may verify and authenticate your information to deter +card issuer using the bank telephone number you provided during the checkout procedure so that we may verify and authenticate your information to deter fraudulent activity. <input type="hidden" name="isCa" value="N"><ul class="noBorder"> @@ -497,14 +497,14 @@ <li class="clear"> </ul> </div> - + <h2>Subscriptions </h2> <p>You may change these settings at any time in 'My Account' > 'Subscriptions'</p> <p> <input type="checkbox" id="newsletter" name="Spam" value="1" tabindex="8" checked><label for="newsletter" class="desc"> Sign me up for exclusive newsletter deals, sweepstakes, and 24-hour sales only available to subscribers - + </label> </p> @@ -515,20 +515,20 @@ <input type="hidden" name="SMSStatus" value=""></p> <h2>Newegg Address Checker</h2> - <p>Ensure we can generate a valid shipping label so your order's shipment is not delayed. + <p>Ensure we can generate a valid shipping label so your order's shipment is not delayed. <a >Verify address now</a>. </p> <div class="btnBlk"> <br><br><a class="btnOn" >Submit Registration</a>  </div> - - - + + + <p>Newegg.com is the sole owner of the information collected on this site. We will not sell,share,or rent this information to any outside parties, except as outlined in the privacy policy. </p> </form> - - + + @@ -536,7 +536,7 @@ <form action="http://www.newegg.com/Info/TrackOrder.aspx" method="get" id="trackOrder" name="trackOrder"> <label for="TrackingNumber">Track My Order</label> - <p class="vam"> + <p class="vam"> <input name="TrackingNumber" id="TrackingNumber" title="Tracking Number" type="text" value="Tracking Number" ><a class="noline"><img src="#" alt="Track Order" style="border:0;" width="25" height="19" class="vam"></a> </p> </form>
diff --git a/components/test/data/autofill/heuristics/input/063_register_officedepot.com.html b/components/test/data/autofill/heuristics/input/063_register_officedepot.com.html index f588f38..8217d685 100644 --- a/components/test/data/autofill/heuristics/input/063_register_officedepot.com.html +++ b/components/test/data/autofill/heuristics/input/063_register_officedepot.com.html
@@ -13,7 +13,7 @@ <body id="registration"> <form name="storeLocatorForm" method="get" action="http://www.officedepot.com/setStoreZip.do"> -<span style="display:none"><input type="hidden" name="fkey" value="ZBOQ8Sp5mFecc34vd2jp8wl"></span> +<span style="display:none"><input type="hidden" name="fkey" value="ZBOQ8Sp5mFecc34vd2jp8wl"></span> <input type="text" name="zip" maxlength="7" size="7" autocomplete="" value="" id="zip"><input type="hidden" name="requestor" value="header" id="requestor"><input type="hidden" name="switchDeliveryToPickup" value="false"><input type="hidden" name="inventoryLocationUpdatable" value="true"><span class="search"><input type="submit" name="find" id="find" class="button" value="Go"></span> <div class="clear"></div> </form> @@ -24,7 +24,7 @@ -<form name="storeLocatorForm" method="post" action="http://www.officedepot.com/account/deliveryPickupModeSet.do" autocomplete="off"> +<form name="storeLocatorForm" method="post" action="http://www.officedepot.com/account/deliveryPickupModeSet.do"> <span style="display:none"><input type="hidden" name="fkey" value="ZBOQ8Sp5mFecc34vd2jp8wl"></span> <input type="hidden" name="inventoryLocationUpdatable" value="true"><input type="hidden" name="switchDeliveryToPickup" value="true"><input type="hidden" name="requestor" value="/home.do"><ul> <li class="radio"> @@ -45,23 +45,23 @@ <form name="refinementForm" method="get" action="http://www.officedepot.com/catalog/search.do" autocomplete="false"> -<span style="display:none"><input type="hidden" name="fkey" value="ZBOQ8Sp5mFecc34vd2jp8wl"></span> - +<span style="display:none"><input type="hidden" name="fkey" value="ZBOQ8Sp5mFecc34vd2jp8wl"></span> + <div id="suggestSearchOn"></div> - + <table id="searchBox" cellspacing="0"><tr> <th><label for="searchField">Search</label></th> <td id="sfInput"> <div id="predictSearchFlyout" class="overlayContainer"> - <input type="text" name="Ntt" id="mainSearchField" maxlength="100" tabindex="1" class="input focus" autocomplete="off" value=""><div class="overlayObj"> + <input type="text" name="Ntt" id="mainSearchField" maxlength="100" tabindex="1" class="input focus" value=""><div class="overlayObj"> <div id="predictSearchList"> <div class="loading-light"></div> <table class="predictsearchresults"><tr> <td class="suggestions"><p class="note">Search Suggestions</p></td> </tr></table> </div> - </div> - </div> + </div> + </div> </td> <td><div class="search"><input type="submit" tabindex="2" value="Go" class="button" title="Search"></div></td> </tr></table> @@ -77,16 +77,16 @@ -<form name="registrationForm" method="post" action="/account/registrationRouter.do" autocomplete="off"> +<form name="registrationForm" method="post" action="/account/registrationRouter.do"> <span style="display:none"><input type="hidden" name="fkey" value="ZBOQ8Sp5mFecc34vd2jp8wl"></span> <div id="m02"> - - + + <div id="registrationBody"> - - + + <div id="registrationMessage"> - + @@ -95,10 +95,10 @@ <h2 class="modStyle1">Before you begin...</h2> <div class="moduleStructContent"> <p class="intro"> - Please note that if you can answer "yes" to any of the following questions, you may not need to fill out this registration form. Simply click on the link that applies and you'll be taken to the appropriate page. If none of these links seem relevant, we can still search for a previous account set up for you. Please enter your primary email address and we'll email your existing login information. - </p> - - + Please note that if you can answer "yes" to any of the following questions, you may not need to fill out this registration form. Simply click on the link that applies and you'll be taken to the appropriate page. If none of these links seem relevant, we can still search for a previous account set up for you. Please enter your primary email address and we'll email your existing login information. + </p> + + <ul class="listOfLinks splitLinks"> <li class=""><a href="/account/existingUSANonExemptDisplay.do">Do you shop with us by phone or fax?</a></li> <li><a href="/account/existingUSAExemptDisplay.do">Do you already have an account number?</a></li> @@ -111,15 +111,15 @@ - </div> - - - - - + </div> + + + + + <div class="section"> <div class="oCol1of2 first"> - + @@ -131,41 +131,41 @@ <div id="reg_billingInfo" class="moduleStruct"> <h2 class="modStyle1">Billing Information</h2> - + <div class="moduleStructContent"> - - + + <p class="required"> <label> - + <em>*</em> Indicates required field </label> </p> - - + + <p class="note"> - - </p> - - + + </p> + + <p class="note"> - + Please provide your billing address exactly as it appears on your credit card. - - + + </p> - - - - - - - <div id="billing_addr"> - - - - - + + + + + + + <div id="billing_addr"> + + + + + <div class="address editable"> <ol class="column1"> <li class="firstName required"> @@ -262,54 +262,46 @@ </ol> <input type="hidden" name="addrsForm[0].country" value="USA" id="country-0"> </div> - - - + + + </div> - - - - - - + + + + + + <input type="hidden" name="billingEmailPreferences.emailHtml" value="true"><div class="prefs tight"> - - - + + + <input type="hidden" name="billingEmailPreferences.optInSelected" value="false"> </div> - - + + </div> </div> - - - + + + <div id="reg_paymentInfo" class="moduleStruct"> <h2 class="modStyle1">Payment Info (optional)</h2> <div class="moduleStructContent"> - - - - - - - - @@ -319,10 +311,18 @@ - - - - + + + + + + + + + + + + @@ -330,44 +330,42 @@ <div id="billto_PaymentInfo"> - - - - + + + + <p class="note"> Expedite your checkout process for future orders by allowing us to validate the credit card details below. Rest assured we will never save your CID.<br><br></p> - - - - - + + + + + <table class="form" cellspacing="0"> <thead><tr class="paymentSectionHeader first"> <td class="radio"> - - - + + + <input type="hidden" name="paymentFormInfo.tenderType" value="CR"> </td> <th colspan="2"> - + <label for="tenderRadioCR" class="gen_vkg_cclabel"> <b>Credit Card</b> </label> - - + + </th> </tr></thead> <tr class="tenderInfoCR paymentOptionContent"> <td></td> <td colspan="2"> - - + + <div id="noPreauthedCard"> - - @@ -376,21 +374,23 @@ - - - - - + + + + + + + <ul id="creditCardFields"> <li class="SelectCreditCard"> - - + + <label> <span>Credit Card Type:</span> </label> - - + + <span id="creditCardList"> <select name="paymentFormInfo.creditCardType"><option value=" " selected>(Select your card type)</option> <option value="AM">American Express</option> @@ -400,68 +400,68 @@ <option value="SR">Office Depot Credit Card</option> <option value="WV">Worklife Rewards Visa</option></select></span> </li> - - - + + + <li> - - + + <label> <span> Credit Card Number: - - + + </span> </label> - - - + + + <span> - - + + <input type="text" name="paymentFormInfo.creditCardNumber" maxlength="20" size="20" autocomplete="" value=""></span> - - - - + + + + <input type="hidden" name="paymentFormInfo.creditCardIsPreauthed" value="false"> </li> - + <li class="ccMessage"> <label><span></span></label> <span class="note"> Please enter your credit card # without spaces or dashes (i.e. 00000000000) </span> </li> - - - + + + <li class="payOptDates"> <ul> <li class="poStartDate"> - + <span class="pppExpDate"> - + </span> </li> - + <li class="poExpDate"> - - + + <label class="ccExpDateTitle"> - + <span>Expiration Date:</span> - - - </label> - - - + + + </label> + + + <span class="pppExpDate"> - - - + + + <select name="paymentFormInfo.creditCardExpMonth"><option value=" " selected>--</option> <option value="01">01</option> <option value="02">02</option> @@ -475,7 +475,7 @@ <option value="10">10</option> <option value="11">11</option> <option value="12">12</option></select><span>/</span> - + <select name="paymentFormInfo.creditCardExpYear"><option value="-1" selected>--</option> <option value="11">2011</option> <option value="12">2012</option> @@ -499,61 +499,61 @@ <option value="30">2030</option></select><span> (mm/yyyy) </span> - - - - - + + + + + </span> </li> - - <li class="poIssueDate"> - - - + + <li class="poIssueDate"> + + + <span class="poDateFields"> - - + + </span> </li> - + </ul> </li> - - - + + + <input type="hidden" name="paymentFormInfo.cidPreAuthFeature" value="true"><li class="secNumTitle"> <label class="cvv"> <span>CID<br></span> </label> <span> - <input type="text" name="paymentFormInfo.creditCardCvv" maxlength="4" size="4" autocomplete="off" value=""></span> - + <input type="text" name="paymentFormInfo.creditCardCvv" maxlength="4" size="4" value=""></span> + </li> - - - - + + + + <!----> - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + </ul> </div> -<!-- end credit card entry form (noPreath) --> - +<!-- end credit card entry form (noPreath) --> + </td> </tr> </table> @@ -562,7 +562,7 @@ </table> <div id="loadingCards" class="loading hidden"></div> </div> - + @@ -572,13 +572,13 @@ </div> </div> - + </div> - - + + <div class="oCol1of2"> - - + + @@ -598,14 +598,14 @@ <h2 class="modStyle1">Shipping Information</h2> <div class="moduleStructContent"> <p id="checkSameAs"> - + <input type="checkbox" name="sameAsBilling" value="on" checked id="sameAsBilling1" class="input1"><label> Same as Billing </label> - - </p> - - + + </p> + + <div class="intro"> <p class="note"> Currently Office Depot is unable to process orders online for delivery to APO/FPO, PO Box, and export addresses. Please @@ -613,17 +613,17 @@ for additional ordering options </p> </div> - - - + + + <div class="address editable shipToAddressHideShow"> <p class="required"> <label> - + <em>*</em> Indicates required field </label> - </p> - + </p> + <ol class="column1"> <li class="firstName required"> <label for="firstName-2"><span><em class="star">*</em>First Name:</span></label><span><input type="text" name="addrsForm[2].firstName" maxlength="30" size="30" autocomplete="" value="" id="firstName-2"></span> @@ -716,42 +716,42 @@ </ol> <input type="hidden" name="addrsForm[2].country" value="USA" id="country-2"> </div> - - - - - - + + + + + + <input type="hidden" name="shippingEmailPreferences.emailHtml" value="true"><p class="prefs tight"> - - - + + + <input type="hidden" name="shippingEmailPreferences.optInSelected" value="true"></p> - - - - + + + + </div> </div> - - - - - - - - + + + + + + + + @@ -763,55 +763,55 @@ <h2 class="modStyle1">Create Your Login and Password</h2> <div class="moduleStructContent"> - + <p class="required"> <label> <em>*</em> Indicates required field </label> </p> - + <table id="createLogin" class="form" cellspacing="0"> <tr> <td class="label"> <label class="required"> - - + + <em class="star">*</em>Login Name: - - - - + + + + </label> </td> <td class="input required"> - + <input type="text" name="loginForm.loginName" maxlength="100" size="30" autocomplete="" value="" class="textfield"><img class="star" src="#"><span class="note">We recommend you use your email address.</span> - - - + + + </td> </tr> <tr> <td class="label"><label class="required"> - - - + + + <em class="star">*</em>Password: - - - + + + </label></td> <td class="input required"> <input type="password" name="loginForm.password" maxlength="10" size="30" value="" class="textfield"><img class="star" src="#"><span class="note">must be at least 6 characters</span> </td> - + </tr> <tr> <td class="label"><label class="required"> - + <em class="star">*</em>Password Confirm: - - + + </label></td> <td class="input required"> <input type="password" name="loginForm.passwordConfirm" maxlength="10" size="30" value="" class="textfield"><img class="star" src="#"><span class="note">retype your password</span> @@ -822,57 +822,57 @@ <td class="check" colspan="2"> <input type="checkbox" name="loginForm.autoLogin" value="on" class="checkboxfield"><label>Log me in automatically<br><span class="note">(Cookies must be enabled)</span></label> </td> - + </tr> </table> </div> - + </div> - + </div> - + </div> - - - - - - - - - - - + + + + + + + + + + + <div class="actions section"> <ul class="buttonwrapper"> <li> - - - <div class="b1"> + + + <div class="b1"> <input type="submit" value=" Create Account" name="cmd_registration" class="button" title=" Create Account"> </div> - - - - - + + + + + </li> </ul> </div> <input type="hidden" name="displayedForm" value="true"><input type="hidden" name="linked" value="false"><input type="hidden" name="billToID" value=""><input type="hidden" name="requestFromPage" value="true"><input type="hidden" name="fromShoppingCartPage" value="false"><input type="hidden" name="registrationExceptionInfo.billToId" value=""><input type="hidden" name="registrationExceptionInfo.shipToSeq" value=""><input type="hidden" name="registrationExceptionInfo.lastUser" value=""><input type="hidden" name="registrationExceptionInfo.billingEmailCreated" value="false"><input type="hidden" name="registrationExceptionInfo.shippingEmailCreated" value="false"><input type="hidden" name="registrationExceptionInfo.userCreated" value="false"><input type="hidden" name="registrationExceptionInfo.contactId" value=""><input type="hidden" name="customLabelsPermissionsForm.requestor" value="_registrationRequestor_"> </div> -</div> -</form> +</div> +</form>
diff --git a/components/test/data/autofill/heuristics/input/070_register_signup.live.com.html b/components/test/data/autofill/heuristics/input/070_register_signup.live.com.html index 705c988..b756517a 100644 --- a/components/test/data/autofill/heuristics/input/070_register_signup.live.com.html +++ b/components/test/data/autofill/heuristics/input/070_register_signup.live.com.html
@@ -9,7 +9,7 @@ <body> -<form id="SignUpForm" method="post" action="" autocomplete="off" > +<form id="SignUpForm" method="post" action="" > <div class="helparea"> <div id="cmembernamelive" class="row hide"> @@ -22,7 +22,7 @@ Working...</p> <label for="imembernamelive"> Windows Live ID: - + </label> <div id="memnamecont"> <input id="imembernamelive" name="imembernamelive" type="text" maxlength="64" value="" > @@ -79,17 +79,17 @@ </div> </div> </div> - + <div id="chkavail"> <button id="ichkavailbutton" type="button" title="Check availability" > Check availability</button> </div> - + <p id="easilinkctr" class="linkinline"> <a id="ieasiswitch" href="#" > Or use your own email address</a> </p> - + </div> <div class="helppop"> <div id="membernamelivehelp" class="helpctr"> @@ -118,7 +118,7 @@ <a id="iliveswitch" href="#" > Or get a Windows Live email address</a> </p> - + </div> <div class="helppop"> <div id="membernameeasihelp" class="helpctr"> @@ -209,7 +209,7 @@ </div> <div class="helparea"> - + <div class="row"> <p id="iFirstNameError" class="error"> </p> @@ -226,7 +226,7 @@ <input id="iLastName" name="iLastName" type="text" maxlength="40" value="" > <br> </div> - + <div class="helppop"> <div id="namehelp" class="helpctr"> </div> @@ -269,45 +269,45 @@ <div class="helparea"> <div id="iHipHolder" > - + <input type="hidden" id="WLX_HIP_V3_CONTAINER_wlxsignup" name="WLX_HIP_V3_CONTAINER" value="wlxsignup"> <div style="width:265px" id="WLX_HIP_CONTR_wlxsignup"> <div id="WLX_HIP_ERR_NOTIF" class="UI_NotificationBar ErrorHigh" style="display:none "> </div> - - - + + + <div id="WLX_HIP_CTL_wlxsignup" style="display:inline"> <img src="#" alt="Loading...">   Loading... - + </div> - + <div id="WLX_HIP_CTL_ERRLoad_wlxsignup" style="display:none"> <div class="UI_NotificationBar ErrorHigh" style=" "> We weren't able to load the challenge. Please click <a href="#" >here</a> to try again. </div> </div> - - <div id="WLX_HIP_SCRIPT_wlxsignup" style="display:inline"> - + + <div id="WLX_HIP_SCRIPT_wlxsignup" style="display:inline"> + </div> - + <input type="hidden" id="WLX_HIP_FLID_wlxsignup" name="WLX_HIP_FLID_wlxsignup" value="5c0e8279-83c7-45bf-a5f5-5b12b0826d40"> <input type="hidden" id="WLX_HIP_FLHASH_wlxsignup" name="WLX_HIP_FLHASH_wlxsignup" value="xz4jYIhR2TRqpH47G9Ex"> <input type="hidden" id="WLX_HIP_SOL_wlxsignup" name="WLX_HIP_SOL_wlxsignup" value=""> <input type="hidden" id="WLX_HIP_FRAME_wlxsignup" name="WLX_HIP_FRAME_wlxsignup" value=""> <input type="hidden" id="WLX_HIP_CHLG_wlxsignup" name="WLX_HIP_CHLG_wlxsignup" value=""> </div> - + <div style="display:none; width:265px;" id="WLX_HIP_CONTR_wlxsignup_DISABLED"> <div id="WLX_HIP_ERR_DISABLED" class="UI_NotificationBar ErrorHigh" style=" "> <span>Only one challenge can be displayed at a time and an additional challenge has been opened on this page. Please complete that challenge before continuing.</span> </div> </div> - - + + <p id="iHIPError" style="display:none;"> </p> </div> @@ -330,7 +330,7 @@ <div class="topbotrow"> <div class="bluebar">  </div> - + <div id="tou"> Clicking <strong>I accept</strong> means that you agree to the <a target="_new" href="http://g.msn.com/0TO_/enus">Microsoft service agreement</a> and <a target="_new" href="http://g.msn.com/2privacy/enus">privacy statement</a>. <span id="iOptinEmailAgreement" class=""> You also agree to receive email from Windows Live, Bing, and MSN with service updates, special offers, and survey invitations. You can unsubscribe at any time.</span> @@ -338,7 +338,7 @@ <div id="createbuttons"> <button type="submit" title="I accept" > I accept</button> - + </div> <div id="creatingacct" class="hide"> <p>
diff --git a/components/test/data/autofill/heuristics/input/077_register_yahoo.com.html b/components/test/data/autofill/heuristics/input/077_register_yahoo.com.html index dda14ead..abb31e7 100644 --- a/components/test/data/autofill/heuristics/input/077_register_yahoo.com.html +++ b/components/test/data/autofill/heuristics/input/077_register_yahoo.com.html
@@ -13,7 +13,7 @@ <div class="row " id="fullnameFld"> <label class="label" for="name">Name</label> <div class="collection" id="name"> - <input type="text" title="First Name" name="firstname" id="firstname" value="" size="32" maxlength="32" class="" autocomplete="off"><input type="text" title="Last Name" name="secondname" id="secondname" value="" size="32" maxlength="32" class="" autocomplete="off"> + <input type="text" title="First Name" name="firstname" id="firstname" value="" size="32" maxlength="32" class=""><input type="text" title="Last Name" name="secondname" id="secondname" value="" size="32" maxlength="32" class=""> </div> <div class="msgContainer"> <div class="icon"></div> @@ -32,11 +32,11 @@ <p id="genderFldMsg"></p> </div> </div> - + <div class="row " id="dobFld"> - <label class="label" for="birthdategroup">Birthday</label> + <label class="label" for="birthdategroup">Birthday</label> <div class="collection" id="birthdategroup" title="Birthday"> - + <select title="- Select Month -" name="mm" id="mm" class=""><option value="" selected>- Select Month -</option> <option value="1">January</option> <option value="2">February</option> @@ -49,7 +49,7 @@ <option value="9">September</option> <option value="10">October</option> <option value="11">November</option> -<option value="12">December</option></select><input title="Day" type="text" name="dd" id="dd" value="" size="32" maxlength="32" class="dateInput" autocomplete="off"><input title="Year" type="text" name="yyyy" id="yyyy" value="" size="32" maxlength="32" class="dateInput" autocomplete="off"> +<option value="12">December</option></select><input title="Day" type="text" name="dd" id="dd" value="" size="32" maxlength="32" class="dateInput"><input title="Year" type="text" name="yyyy" id="yyyy" value="" size="32" maxlength="32" class="dateInput"> </div> <div class="msgContainer"> <div class="icon"></div> @@ -57,7 +57,7 @@ </div> </div> <div class="row " id="countryFld"> - <label class="label" for="country">Country</label> + <label class="label" for="country">Country</label> <div class="collection"> <select class="" id="country" name="country"><option value="">Select One</option> <option value="af">Afghanistan</option> @@ -311,9 +311,9 @@ </div> </div> <div class="row " id="zipcodeFld"> - <label class="label" for="postalcode">Postal Code</label> + <label class="label" for="postalcode">Postal Code</label> <div class="collection"> - <input type="text" name="postalcode" id="postalcode" value="" size="16" maxlength="16" class="" autocomplete="off"> + <input type="text" name="postalcode" id="postalcode" value="" size="16" maxlength="16" class=""> </div> <div class="msgContainer"> <div class="icon"></div> @@ -322,14 +322,14 @@ </div> </fieldset> <fieldset class="fieldsCollection"> -<div class="dotline"></div> +<div class="dotline"></div> <legend> Select an ID and password</legend> <div class="row " id="yahooIdFld"> - <label class="label" for="yahooid">Yahoo! ID and Email</label> + <label class="label" for="yahooid">Yahoo! ID and Email</label> <div class="collection"> <span id="choosenyid">@</span> <a href="#" id="changeyid"> Change</a> - <input type="text" name="yahooid" id="yahooid" value="" size="32" maxlength="32" class="" autocomplete="off"><span id="at">@</span> + <input type="text" name="yahooid" id="yahooid" value="" size="32" maxlength="32" class=""><span id="at">@</span> <select name="domain" id="domain" class=""><option value="yahoo.com">yahoo.com</option> <option value="ymail.com">ymail.com</option> <option value="rocketmail.com">rocketmail.com</option></select><input type="button" id="yidHelperBtn" class="graybtn" value="Check"> @@ -355,7 +355,7 @@ </div> <div class="row " id="passwordFld"> <!----> - <label class="label" for="password">Password</label> + <label class="label" for="password">Password</label> <div class="collection"> <input type="password" name="password" id="password" value="" size="32" maxlength="32" class=""><div id="meter_tag"> <h3 id="passwordGuidence" style="display: block;">Password Strength</h3> @@ -372,7 +372,7 @@ <div class="example hidden" id="password_example">Capitalization matters. Use 6 to 32 characters, and don't use your name or Yahoo! ID.</div> </div> <div class="row " id="confPasswordFld"> - <label class="label" for="passwordconfirm">Re-type Password</label> + <label class="label" for="passwordconfirm">Re-type Password</label> <div class="collection"> <input type="password" name="passwordconfirm" id="passwordconfirm" value="" size="32" maxlength="32" class=""> </div> @@ -383,12 +383,12 @@ </div> </fieldset> <fieldset class="fieldsCollection"> -<div class="dotline"></div> +<div class="dotline"></div> <legend>In case you forget your ID or password...</legend> <div class="row " id="altEmailFld"> - <label class="label" for="altemail">Alternate Email (optional)</label> + <label class="label" for="altemail">Alternate Email (optional)</label> <div class="collection"> - <input type="text" name="altemail" id="altemail" value="" size="96" maxlength="96" class="" autocomplete="off"> + <input type="text" name="altemail" id="altemail" value="" size="96" maxlength="96" class=""> </div> <div class="msgContainer"> <div class="icon"></div> @@ -396,7 +396,7 @@ </div> </div> <div class="row " id="secureQuestionFld"> - <label class="label" for="secquestion">Secret Question 1</label> + <label class="label" for="secquestion">Secret Question 1</label> <div class="collection"> <select class="" id="secquestion" name="secquestion"><option value="" selected>- Select One -</option> <option value="What is the first name of your favorite uncle?">What is the first name of your favorite uncle?</option> @@ -415,9 +415,9 @@ </div> </div> <div class="row hidden " id="customSecureQuestionFld1"> - <label class="label" for="customsecquestion1">Specify Your Question</label> + <label class="label" for="customsecquestion1">Specify Your Question</label> <div class="collection"> - <input type="text" name="customsecquestion1" id="customsecquestion1" value="" size="32" maxlength="100" class="" autocomplete="off"> + <input type="text" name="customsecquestion1" id="customsecquestion1" value="" size="32" maxlength="100" class=""> </div> <div class="msgContainer"> <div class="icon"></div> @@ -425,18 +425,18 @@ </div> </div> <div class="row " id="secureAnswerFld"> - <label class="label" for="secquestionanswer">Your Answer</label> + <label class="label" for="secquestionanswer">Your Answer</label> <div class="collection"> - <input type="text" name="secquestionanswer" id="secquestionanswer" value="" size="32" maxlength="32" class="" autocomplete="off"> + <input type="text" name="secquestionanswer" id="secquestionanswer" value="" size="32" maxlength="32" class=""> </div> <div class="msgContainer"> <div class="icon"></div> <p id="secureAnswerFldMsg"></p> </div> - <div class="example hidden" id="secquestionanswer_example">Use 4 characters or more — not case sensitive.</div> + <div class="example hidden" id="secquestionanswer_example">Use 4 characters or more — not case sensitive.</div> </div> <div class="row " id="secureQuestionFld2"> - <label class="label" for="secquestion2">Secret Question 2</label> + <label class="label" for="secquestion2">Secret Question 2</label> <div class="collection"> <select class="" id="secquestion2" name="secquestion2"><option value="" selected>- Select One -</option> <option value="Where did you spend your childhood summers?">Where did you spend your childhood summers?</option> @@ -464,9 +464,9 @@ </div> </div> <div class="row hidden " id="customSecureQuestionFld2"> - <label class="label" for="customsecquestion2">Specify Your Question</label> + <label class="label" for="customsecquestion2">Specify Your Question</label> <div class="collection"> - <input type="text" name="customsecquestion2" id="customsecquestion2" value="" size="32" maxlength="100" class="" autocomplete="off"> + <input type="text" name="customsecquestion2" id="customsecquestion2" value="" size="32" maxlength="100" class=""> </div> <div class="msgContainer"> <div class="icon"></div> @@ -474,24 +474,24 @@ </div> </div> <div class="row " id="secureAnswerFld2"> - <label class="label" for="secquestionanswer2">Your Answer</label> + <label class="label" for="secquestionanswer2">Your Answer</label> <div class="collection"> - <input type="text" name="secquestionanswer2" id="secquestionanswer2" value="" size="32" maxlength="32" class="" autocomplete="off"> + <input type="text" name="secquestionanswer2" id="secquestionanswer2" value="" size="32" maxlength="32" class=""> </div> <div class="msgContainer"> <div class="icon"></div> <p id="secureAnswerFld2Msg"></p> </div> - <div class="example hidden" id="secquestionanswer2_example">Use 4 characters or more — not case sensitive.</div> + <div class="example hidden" id="secquestionanswer2_example">Use 4 characters or more — not case sensitive.</div> </div> - + </fieldset> <fieldset id="fldsetCaptchaTos" class="fieldsCollection"> -<div class="dotline"></div> +<div class="dotline"></div> <div class="row " id="captchaFld"> - <label class="label" id="captchalabel" for="cword"> Type the code shown</label> + <label class="label" id="captchalabel" for="cword"> Type the code shown</label> <div class="collection"> - <input type="text" name="cword" id="cword" value="" size="10" maxlength="10" class="" autocomplete="off"><a id="captchaSwitchButton" style="display:inline-block"><input type="button" id="caswitchurl" value="Need audio assistance ?"></a> + <input type="text" name="cword" id="cword" value="" size="10" maxlength="10" class=""><a id="captchaSwitchButton" style="display:inline-block"><input type="button" id="caswitchurl" value="Need audio assistance ?"></a> </div> <div class="msgContainer"> <div class="icon"></div> @@ -509,9 +509,9 @@ <input type="button" class="captchaRefreshBtn" id="captchaShuffleLink" value="Try a new code"> </div> <div id="audioCaptcha"></div> - <input type="hidden" name="cdata" id="cdata" value="ivRVCuJZFeknqCyHkKNmeTl62CunyRdoQ02mSZwUnMimw_MogxAy5wMWcsE1bqrkfyVrNDXf741nNdKurp6tkzZMbggAto9lYnEJ2A--"><input type="hidden" name="cadata" id="cadata" value="4Qw8KOJZFelJlKD0sr9J_fwUhkzMvtQdrTFbugv1IYlla_l1litwL9Eha0fplyQHAnt8vAjI4woNlInFVXcIYFQIYqHxK1U7Huo-"><input type="hidden" name="captchaVersion" id="captchaVersion" value="4"><input type="hidden" name="showc" value="1"><input type="hidden" name="tos_agreed" id="tos_agreed_o_0" value="y"><div class="multipleRows"> + <input type="hidden" name="cdata" id="cdata" value="ivRVCuJZFeknqCyHkKNmeTl62CunyRdoQ02mSZwUnMimw_MogxAy5wMWcsE1bqrkfyVrNDXf741nNdKurp6tkzZMbggAto9lYnEJ2A--"><input type="hidden" name="cadata" id="cadata" value="4Qw8KOJZFelJlKD0sr9J_fwUhkzMvtQdrTFbugv1IYlla_l1litwL9Eha0fplyQHAnt8vAjI4woNlInFVXcIYFQIYqHxK1U7Huo-"><input type="hidden" name="captchaVersion" id="captchaVersion" value="4"><input type="hidden" name="showc" value="1"><input type="hidden" name="tos_agreed" id="tos_agreed_o_0" value="y"><div class="multipleRows"> <p id="disclaimer">By clicking the “Create My Account” button below, I certify that I have read and agree to the <a href="http://docs.yahoo.com/info/terms/" id="lnk_reg_tos" title="Terms of Service" target="_blank">Yahoo! Terms of Service</a>, <a href="http://privacy.yahoo.com/" id="lnk_reg_privacy" title="Privacy Policy" target="_blank"> Yahoo! Privacy Policy </a> and <a target="_blank" href="http://info.yahoo.com/legal/us/yahoo/mail/atos.html">Communication Terms of Service</a>, and to receive account related communications from Yahoo! electronically. Yahoo! <a href="http://info.yahoo.com/privacy/us/yahoo/mail/betafaq/details.html" id="lnk_reg_scanning" title="Mail Beta FAQ" target="_blank">automatically identifies</a> items such as words, links, people, and subjects from your Yahoo! communications services to deliver product features and relevant advertising.</p> - + <input type="submit" name="IAgreeBtn" id="IAgreeBtn" value="Create My Account" title="" border="0"> </div> </fieldset>
diff --git a/components/test/data/autofill/heuristics/input/081_crbug_64569.html b/components/test/data/autofill/heuristics/input/081_crbug_64569.html index 677e3cc..4806434d 100644 --- a/components/test/data/autofill/heuristics/input/081_crbug_64569.html +++ b/components/test/data/autofill/heuristics/input/081_crbug_64569.html
@@ -2,7 +2,7 @@ <!-- saved from url=(0049)https://www.threadless.com/cart/step/billing-info --> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:og="http://opengraphprotocol.org/schema/" xmlns:fb="http://www.facebook.com/2008/fbml" version="XHTML+RDFa 1.0" class="wf-kulturistaweb1kulturistaweb2-n4-active wf-kulturistaweb1kulturistaweb2-i4-active wf-futurapt1futurapt2-n7-active wf-futurapt1futurapt2-n8-active wf-ronniacondensed1ronniacondensed2-n7-active wf-active"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> --> - + <form method="post" id="checkoutForm" action="./three.com_files/three.com.html" name="cartform"> <div class="section radio"> <h2>Payment Type</h2> @@ -19,9 +19,9 @@ <div class="col"> <p>We accept Visa, Mastercard, Discover, American Express, and PayPal.</p> </div> - </div> - - <div id="billing_inner_container"> + </div> + + <div id="billing_inner_container"> <div class="section"> <h2>Enter your credit card information</h2> <div id="card_info" class="col"> @@ -38,7 +38,7 @@ <span class="guide"> (no dashes or spaces) </span> - <input id="" name="ccNumber" maxlength="16" type="text" autocomplete="off" class="long"> + <input id="" name="ccNumber" maxlength="16" type="text" class="long"> </p> <p class="pair"> @@ -52,38 +52,38 @@ <div class="card_security"> <p> <label>Security code</label> - <input id="" name="ccSecurity" type="text" maxlength="4" autocomplete="off" class="short"> + <input id="" name="ccSecurity" type="text" maxlength="4" class="short"> </p> <div class="card_guide"> <h3>Where do I find it?</h3> <h4>Visa & Mastercard:</h4> - <p><img src="#" width="80" height="43"><span>3-digit code</span></p> + <p><img src="#" width="80" height="43"><span>3-digit code</span></p> <h4>American Express:</h4> <p><img src="#" width="80" height="43"><span>4-digit code</span></p> </div><!-- END .card_guide --> </div><!-- END #card_security --> </div><!-- END #card_info --> </div><!-- END .section --> - - + + <div class="section"> - <h2>Enter your credit card billing address</h2> + <h2>Enter your credit card billing address</h2> <div id="billing_address" class="col"> - <p class="checkbox"> + <p class="checkbox"> <input type="checkbox" name="sameinfo" onclick="toggleInfo();"><label>Same as shipping address?</label> </p> - + <p class="mini_col"> <label>First name</label> <input type="text" class="medium" maxlength="60" id="" name="addrFirstName" value=""> </p> - + <p class="mini_col"> <label>Last name</label> <input type="text" class="medium" maxlength="60" id="" name="addrLastName" value=""> </p> - + <p> <label>Address</label> <span class="guide"> @@ -91,7 +91,7 @@ </span> <input type="text" class="long" maxlength="50" id="" name="addrStreet1" value=""> </p> - + <p> <label>Address 2</label> <span class="guide"> @@ -99,12 +99,12 @@ </span> <input type="text" class="long" id="" maxlength="50" name="addrStreet2" value=""> </p> - + <p> <label>City</label> <input type="text" class="long" id="" maxlength="50" name="addrCity" size="20" value=""> </p> - + <p class="mini_col one"> <label>State</label> <select name="addrState"><option value=" ">None</option> @@ -191,17 +191,17 @@ <option value="VIC">VIC</option> <option value="WA">WA</option> </select> </p> - + <p class="mini_col two"> <label>Postal code</label> <input type="text" class="short" maxlength="50" id="" name="addrZip" size="10" value=""> </p> - + <p> <label>Country</label> Algeria </p> </div><!-- END #billing_address --> - + <div id="billing_faqs" class="col"> <h3>Can shipping and billing addresses be different?</h3> <p>As long as the billing and shipping addresses are in the same country, you can use different billing and shipping addresses.</p> @@ -222,11 +222,11 @@ </p> </form><!-- END form --> </div><!-- END billing_container --> - + </div><!-- END .main_left_4 m_r_20 --> <!-- </div>where is this opening div ? --> <div class="main_left_2"> - + <div id="cart_right_top"></div> <div class="step_image"> @@ -245,32 +245,32 @@ <br> <div class="cart_right"> - + <div class="m_b_10 cart_header_faq"> In your cart <a href="https://www.threadless.com/cart"><img src="#" align="absmiddle"></a></div> - + <div class="f_14"><a href="https://www.threadless.com/product/3016/Hugs_Keep_Us_Alive">Hugs Keep Us Alive!</a></div> - <div class="m_b_10 grey">(1) Large Silver Guys Tee</div> - - + <div class="m_b_10 grey">(1) Large Silver Guys Tee</div> + + <br> <div class="b_t_dotted m_b_20"></div> - + <div class="m_b_10 cart_header_faq"> Order summary</div> - + <div class="grey m_b_5">Item(s) cost: <span class="arial">$20.00</span></div> <div class="grey m_b_5">Shipping cost: <span class="arial">$9.00</span></div> <div class="grey m_b_5">Tax: <span class="arial">$0.00</span></div> <div class="b_t_dotted m_b_5"></div> <div class="f_14 m_b_5">Subtotal: <span class="arial">$29.00</span></div> - + <div class="b_t_dotted m_b_10"></div> - - + + <div class="cart_header_faq m_b_10"> Total cost: <span class="arial">$29.00</span> </div> <div class="grey">The total cost is the amount that will be charged to you.</div> - + </div> </div> <div class="clear_both"></div> @@ -279,7 +279,7 @@ </div><!-- END .contentMain --> - + <!-- included by footer.tpl and bot.tpl --> <div class="footer_container"> <footer> @@ -304,9 +304,9 @@ <li><a href="https://www.threadless.com/partners">Partners</a></li> <li><a href="http://www.society6.com/shop/collection/threadless?curator=skaw&utm_source=threadless&utm_medium=text&utm_content=footer&utm_campaign=collection" class="window" target="_blank">Threadless Collection</a></li> <li><a href="https://www.threadless.com/shop/clearance" class="ups">Clearance</a></li> - </ul> + </ul> </section><!-- END .shop --> - + <section class="participate"> <h3><a href="https://www.threadless.com/submissions">Participate</a></h3> <ul> @@ -317,9 +317,9 @@ <li><a href="https://www.threadless.com/gallery">Tee-riffic Photos </a></li> <li><a href="https://www.threadless.com/bt/year,2010">The Bestee Awards</a></li> <li><a href="https://www.threadless.com/live">Threadless Live</a></li> - </ul> + </ul> </section><!-- END .participate --> - + <section class="community"> <h3><a href="https://www.threadless.com/blogs">Community</a></h3> <ul> @@ -327,13 +327,13 @@ <li><a href="https://www.threadless.com/tv">Tee-V</a></li> <li><a href="https://www.threadless.com/artists">Artist Programs</a></li> <li><a href="https://www.threadless.com/interviews">Designer Interviews</a></li> - <li><a href="https://www.threadless.com/sightings">Threadspotting</a></li> + <li><a href="https://www.threadless.com/sightings">Threadspotting</a></li> <li><a href="https://www.threadless.com/streetteam">Street Team</a></li> <li><a href="http://www.meetup.com/Threadless/" class="window" target="_blank">Meetups</a></li> - - </ul> + + </ul> </section><!-- END .community --> - + <section class="info"> <h3><a href="https://www.threadless.com/news">Info</a></h3> <ul> @@ -343,7 +343,7 @@ <li><a href="https://www.threadless.com/wholesale/">Wholesale</a></li> <li><a href="https://www.threadless.com/jobs">Jobs</a></li> <li><a href="https://www.threadless.com/contact">Contact Us</a></li> - </ul> + </ul> </section><!-- END .info --> <section class="contact vcard"> @@ -359,5 +359,5 @@ <div style="display: none"> <img src="#" alt="Loading..." title=""> Submitting… </div> -</form> +</form> </body></html>
diff --git a/components/test/data/autofill/heuristics/input/083_crbug_87517.html b/components/test/data/autofill/heuristics/input/083_crbug_87517.html index e33cbe3b..382fad25 100644 --- a/components/test/data/autofill/heuristics/input/083_crbug_87517.html +++ b/components/test/data/autofill/heuristics/input/083_crbug_87517.html
@@ -42,7 +42,7 @@ Company<br> <input name="company" value="" type="text" size="36" maxlength="100" tabindex="3"><br> Address 1 <span>*</span><br> - <input name="dadd1" id="dadd1" value="" type="text" size="36" maxlength="155" tabindex="4" autocomplete="off"><br> + <input name="dadd1" id="dadd1" value="" type="text" size="36" maxlength="155" tabindex="4"><br> Address 2<br> <input name="dadd2" id="dadd2" type="text" value="" size="36" maxlength="155" tabindex="5"><br> City / State / Zip <span>*</span><br> @@ -1126,9 +1126,9 @@ </option> </select><br> Credit Card Number <span>*</span><br> - <input name="ccard" type="text" value="" size="25" maxlength="25" tabindex="32" autocomplete="off"><br> + <input name="ccard" type="text" value="" size="25" maxlength="25" tabindex="32"><br> CSC Number <span>* <a href="#">What Is This?</a></span><br> - <input tabindex="33" name="csc" type="text" value="" size="25" maxlength="4" autocomplete="off"><br> + <input tabindex="33" name="csc" type="text" value="" size="25" maxlength="4"><br> Expiration Date <span>*</span><br> Month <select name="ExpMon" tabindex="34"> <option value="1">
diff --git a/components/test/data/autofill/heuristics/input/087_crbug_98286.html b/components/test/data/autofill/heuristics/input/087_crbug_98286.html index f39da962..7c746b9a 100644 --- a/components/test/data/autofill/heuristics/input/087_crbug_98286.html +++ b/components/test/data/autofill/heuristics/input/087_crbug_98286.html
@@ -134,7 +134,7 @@ <span id="lblCardNumber">*Card number:</span> </td> <td class="CellAccent1" colspan="2"> - <input name="txtCreditCardNumber" type="text" size="20" id="txtCreditCardNumber" title="Card number, Required" autocomplete="off" class="StandardCell" /> + <input name="txtCreditCardNumber" type="text" size="20" id="txtCreditCardNumber" title="Card number, Required" class="StandardCell" /> </td> </tr><!-- Display Expiration Date --> <tr>
diff --git a/components/test/data/autofill/heuristics/input/092_checkout_alaskaair.com.html b/components/test/data/autofill/heuristics/input/092_checkout_alaskaair.com.html index 8f5d5e9..51137a5 100644 --- a/components/test/data/autofill/heuristics/input/092_checkout_alaskaair.com.html +++ b/components/test/data/autofill/heuristics/input/092_checkout_alaskaair.com.html
@@ -4,10 +4,10 @@ <title>Checkout: Review and Payment - Alaska Airlines</title> <meta name="keywords" content="checkout review payment"> <meta name="description" content="Review your itinerary and purchase"> - + <meta http-equiv="X-UA-Compatible" content="IE=9"> - + </head> <body> @@ -24,7 +24,7 @@ <label for="Password" >Password</label> <a id="forgotPasswordLink" title="Help Retrieving Password" tabindex="6" href="https://www.alaskaair.com/myaccount/forgotcredentials/password" onclick="if(s_gi){var s=s_gi('alaskacom');s.linkTrackVars='prop16';s.linkTrackEvents='None';s.prop16='MyAccount:Forgot Password';s.tl(this,'o','MyAccount:Forgot Password');s.prop16='';}as.authentication.forgotPassword(this.href);return false;" >Forgot Password?</a> </div> - <div> <input id="Password" maxlength="50" tabindex="2" name="Password" type="password" autocomplete="off" value=""></div> + <div> <input id="Password" maxlength="50" tabindex="2" name="Password" type="password" value=""></div> </div> <div> <div><label for="jumpToSelection"><span >Jump To </span>Section</label></div> @@ -58,7 +58,7 @@ </form> <form id="PaymentForm" action="https://www.alaskaair.com/booking/payment" method="post" autocorrect="off" onsubmit="ShowInterstitial();"> - + <fieldset id="CheckOutData" style="display:none;"> <input type="hidden" id="BookingStateWrapper" name="BookingStateWrapper" value="4622B99E-EFBA-4e3b-9AE0-9C19EC60C045|001|gAAI1UhDFCpWUJrQB3m3YVTUuh/0tBYvUVGEWS3otj341fjTjMutNT5Eglh1UhWzJQLkW4NCl9q4UE1BY10rLG2gXUAdJy69/KnStAdlTqJTzW49hXbbzRykHOQPKEF2dPaG5GyxqthU7bh2LJKFQ1tT76PgqX08rPjUu3+/vjsQNvioZBvTGervYv+CCuYsEiiz3U/PYJI9GQsyB4GavY9GEZ2GSYloWTPMkRvbGMIk2OgAirvJngq6ymK2YxiGVeWqNAPkf0BKSpF6qQCSTj6drfhAWPEwaCMq8j4FBPyupUnrF9QwZcxdTnYgtSTkbdJqYvhCxyJmYOrGRjlLXW1xrl8ga98xNV9Odlts7yFYPTyqU+/NrSqtfSr2MlGQprOH65XiZKxMJoSs5X1kmu6/rE5tbSCVce0HXos9H7julgWhFFkX0LMpmu7Bot8c0zlVo9ibGtalHeNflOD5ESMA3QVTvgrpzd0oEdPYpz7dTsQey3Jd0OC1OJ6+dJ7RGlwcgyC18QoDY34Tbd+ZLicG6LHp/emU6odpDiHPyPBLobnyDrhTBw3g7mk6e1W6dhHuXhdE469Eo+xTeqCBAIUuE0mhPtzxBAntDvvIbq/2BdiRDchk1NPvRDD2HxvNdCukURNtL005AUrisClqZX2fTuI+bRyeovCCDdzonooo1lcO3N8zorOHcHizkYbYf4rrYBcH1dnUk8Hz4NVjPN9eZukeWLXY5fnqJh2uTxA6I8gK7/0ymxVmmy1tI/UoigBOoSlub8Lqy9I61AWAiXhPAgb48Th6RaaSXbC4bww/0KMhXcAuzEJVY458R2ukS6TMXCaPYOR1E+4c9xv/KMsDfEi0hu/pELXxTtCYMwjHzE0kS4mnt/Z+3iCqt+DsQt/TFbAg1Nxi4iGYOmZGuMNX/xMmE5DIPZ1lc0H7YFqc1A5S+wMcrwn5woHLmyAiN7n/HGjRnJWLHB/qI5fRYBgqMmnAuVw4jyOKuXEFcY+dIjLVQ51HALpft/j46tfmll2GB2wmwNqJleUGD8lHdjjEjXOJBLBypukggl31txwsY9HGtRxyCuf63fGL5NtDmHwdXjyK1khEii+w3nYLDI9aq65YIVBW4wYBDhwHHg9QlqfC8DKW5txnFEQG7qW5fdpPWdKw9PEeCQzdq3hLWMQsL0UdUrWx9B357vVvmiSM4dN0j//dt1kK94wNsr6BMchqbKZfkPJmegooKlBQER3pWnmnnidmcSIKq8QvoIsaLSzk5GdwXshdW/Sr7fH94dNvMfY7nrOjUaMOUG7g81KaFuuNU9w1Uubc79DzJNxcX8aWD1LxU1SzLZmzrLXDAoX2aGg3F+75KsnojifGi7YQU+4+bL/xvlkNBwx9YPl2zOHRBqcU/x6Bgurry2nmyUESCX9hOIug9DmI/8XBXoX1SZARdYjDuR9ISzQQoWWgxoTWku3O4SiSQiVfuI9DN5dZbLOnLyvutBuubXE1HCfM4MTaXXBZmPA+tPwWDmFum/3NOl4gXihBvYQx36kWq8owl+maqawi1jsPFrowJhAt+8o46TGurs5OxfmBhjyZ8FDlxpIeLEJ+fa1xBhB3s2ivbfJfni8AiapH5rbV/hsTfokL+0Fd2OYMNysYws+w0z7Hxv0yK+Wv5ipIRvxvPTzOKh3YaciQIdwGI8wYa/hZtD0ew4SQaJWqurygtRRYXCWS0hX09tiDEuyUrZgekrnXvahPrX4wjCJZ/D6TaCaIsCaIOGTpPVEARQ1f+SZYpdjosg+iejdTbaB29/pvOjETMO8jm1nbfg3DeJI+MlAaxz5o7itTUywYgixJcbk5+J5D9PObKeWa3j23Y5T00mahCGBkFC2VKqYxSOQxd35zSmgfecXsiyrY8aRlE0Gm3eb1zTOIqqVNXyM8KxFFI7b/yIZGQL8iU5M3E6z17AkGyMROfbYKFEJRsmmqUzdFZkC1qw3sF5Fl8ejr+9SesbzXxjaIMLyKMTIBcWAS6LyOJX0W0DF4O+MgMaO7Z8sKuk9T6ks1CGy0B2ubKNNxWrTljgzAv+OBCQuyThtJ7OCqso1dXDi/tcYslPhwiElNYC5tzJ0aTDjd+tVw2RLmtCqJsBF3tiuU+qbhN5DsbQVf1dvtPc7w0JamOk3ny9Q5gmE/5+SOqgs4zhCRr08wKMkS0qFJId0LWHEUEKT9C5rpSBiJnuz28ZthSsWc+RgjYF7fGEP5Z0emXTw45zhdO6rMlW1uUCk8NNboEHum7zLPsZuRAwCMRB0pz0t/TGGJUoqp4JEehQ48maD8EZTnAwfJjZPrG2djeE5hODDjF19zJAkWxxlmxwvwTtIBuV2rLIRzfD+XKI2wUP2H3S6PLFZDGLoV2Z38r2sBB4KWiy+YeNfWRWpEKnrbgK6UQOORwcCGupdO6nkC4rRKRRzh6D1z7WHljihqPo2bNxl5EpDSpxO+w5uShEN10JBHqnCm1urU4frWF+VB2FBTCFCKNVxtbwJd0IgKx73w3c62BceI6WVSM34qBqyrfblZf56/UMGS/DJ4V/6EIolp5ytfMmHozDwRsAbysZnSPBYcetAUbOhfWREggt+kSOczq7/fyM5FjTzePIPBzwiWjefKTXqfiEIRR6w8DRJXLxkHpKEZBmmDp7Jv9wdsXBDW7WKajcH/PWZcW9lWjAmFDqP5F1fYf0l80lhQysUFIj4I+PJRqiSjdTq9tNAgSG4l8eEKJvdvSEWA4yzh2GlNQuJnOgC0979ARPaTGYd2ch08GUpb6IbkRjnVCwAWMVGN9REv9+0e9bm3bfbdi66VTy3Nri0PEzzsk8kD/cUabv8Bkh+n+4Fhcm/i15nPCbQdj0pXMBjP2CYUyj10apxoeh5m7G3gHpqWIRldxiWKzbB+N1KEXcVi+FUmlioJV3ljWL4+e1PnpFjLSF2zTBNdppHr8pRDk7fq24iq+28yQ3xqq4RuAqeX3oJ8Kixip6rs3Ntjsek3dLLta1Bb2ZS302dI1RZaNApyP6a4jMjKXyEsChBW4XdsVLziJ86y/hn10qFuZIbnR+flxAAqRJ2B7UBIkXI44bxmKQRR0rDRAk+3v15PlzlNMpyNmALcamwYybWxbhQQlx8Rt2ie0vYUf4cXto7m55P3GDf2pYWNVA6sRSk/WpRJz36N9Ux4dQSirjOuQcCvIelSrO2xLjDmlggAEy3/A7NTf/RIZSfzHfF2mDKWSq3zOduk0+KyFaaDVaYJypz1+GWnlRZKyEtc0iceTAGhApLC/ODGJD3bM/uKC88izO8UG9CMO9qlgEjhw2AWQ3gCUBtwYbLfXfXrM7gklYSNqFBXmMt1G4W4lahC7Begxdagz+Z2sNofoB/gxTq8m+IUYLr4PLFdwrcU9y93uBRc6GExgAggGcHAYC5sb2gz5jHjKMm6h1vr2O30ECjmCkmtwI6alfMTFtYU40xKjs/kliNNA9ZWZRWZdHyeD+eDwzjPfo8IepHWyWvgtYNTwJK/RL+2Hj+6aPVS/tA4Jm0sOOOkj8ApF+yg3nVE64JGnYLu6kw73dERWa+WKZcWobe097ilu5IIfXWqOFLIa/qeofi45QHOD7aQLK+BE9o9Ch6NeMF7S5dUFCd7fnGZ16a6IwRHm/WqnAI5ZvHGXAZEY0o/4zpALleNEonXFUdDb/ARfTYlrXMt9ncg6kyaccI8w296gV3FekcS7l+Y7o+uUrqaok3qC0k60tRwZMGysYg+ujsMkZFfgxdL6j5ur0Yq6dmjDD+oHL7DiBXXyrYtCYyMAwTV76X0BAWDTbEHTmwXxDD/r5Beq6iIZuFSd1wNW8Xm52wvEC0+wgiWPHavaV/2VXkeYb4uSr+icDRHfPMyfLveNCM3uEIG7wlNRJghni/lXRAJVGI4mXGfwTZXSVqHJ4UpfwBlUnGeXQa8pw6SD3PreY8znKeDAwqKDPBEJChwt/TMAqkJ+wrIRSMkPduEbI4D8yGc3IeHY6qcMVAVfhJPIDSgqrI53lp3xr34OFHxt1WNL2o2+MNie4nhJQHTMf3vMN4ls3Ckibsk4usX/UFRh7VKbUSr5yjuNckQOW3gZIVtzVUb6yT1Z8YS0PAlsCHeqHiqmFdBxS1dWNC3Spu3zsy9GQeSj3sNiJthdZUfFb/h/Aylak5mLFof3MBUQUWW3eIuhwAGmLqNdlk0uNVkPQSGp8lGG80zPl9Ak4hV8zyYfkUEGaxlWXtKmeTRlzwQ4t6oI9tSpU6/zGqrTkRyGNQ2fzo20Zmz0N/rcilDVla8DldZwaZ4TVdOJZ2zS5+xF7Dj3mPbjTtZCLJ4OQSogQXkwrZUZwQPlt7s8DOztkdEJMamq+JB9ORz0ni327WRwl4GUFnHHZ7nd8aXSqWSLJdCZ9to+/AP9IboVoKvfx7Hgw7+Z/rR8fB/TI5l6hO2fXviYIbuRg9/Hrie17/liRx8noFy7uEPRFBnUAQnhtsEAHsPObLbCTRZWfWN/WgC0zrKVZgayGhWcyRsQHECL9CUXYmSCAgSbjiIj6dXKNpSkHxrW6zaCIBPjtnHgNmlciaAHRK+wTW+Ly2Kv+LusE4sWqocctcUR8fdG/Xa9++EOxc8TzZLoO85Rc510yMjURkm97ez80LIoaolo5XSNU7+iyI36GqA6VmHSexuejb0iCpHCSEkSQNiPC5Xqko9AjeY3JcbRhKmDL+B6N5XbtoSw0AQTT0zGxYkfkCo3AAxzQHBwiHjSNSMvTliDASkJ8fsqqmpZx2mGKi7y9deyqIrcdC9ZgUgYjZcFP+1t586MDgc53zPgvCVqciWsE+9ZQtS73AFtIBZlfrQ0SQyKI+44WmFfrIHfwMc9lXxQiw1yIaAkfTKJr7sqL/iuM58ZscUDxy9s4fd43zWFkT1EmAaVTgMVOLygNekGv3++9UUpmgIPSpXTwyx6NeIg5WLpBzAwdfx0Tk/YkrMhfqyB9XR/DBnQt573tXuYUPbakPQs2vZ2d/xopddACC6MPEHxovoFTKPujV4RypsYCRKpCfdGHZFEVlaQ0AifGL2uWSPS6yv0B0MKVfrD01M9ovpyND+wVRfpjTadgpBPfXyIpT/1fwYxY9jfjTf5/UWTH42/Jge+jQ+emXwxDZJIg9y68q70/gdVnSmGHbfyZFkCumI3o8v7SOItZNJ5aGsjj2TQkDvvqs2OmPiCvbKrUrpQg/Eja5cMd1HNwK8zmhY1NTf19ybvth0Cb4QJBz2Yg3XW2JJ9hNCvF7b2h+arKFAbfFfGZkCSbsJ9OUcBkMzZFKIsAml/zs8Fn63EcSYh4fRffJ+28C/+T1AE944qhGedWXDPCbYyH82QXt71o2bFfsQIpYzwhU/MnNFuSXwWjaH7MZpGajbXjnMTO+pZGob1E4mmBo2sRW6r0YmDmmpVx1FwJORmn5qRzMsc7SZtt0wZwHHTcYccx8="> <input type="hidden" id="CheckOutStepOutModelEncrypted" name="CheckOutStepOutModelEncrypted" value="4622B99E-EFBA-4e3b-9AE0-9C19EC60C045|001|gACQ/3rP7u6M5T8GW1/CPbflZiQojPuPrNA/b5za3tARQx7TKsUu0HdpDzxvRp0AlAgUmlKyRMiOrkpiUJnFnSQu0IdyLBHyiigPKuWepRhCh/Zl94I+VQuHaMciZK/WDzVDs0B/FRL/htO/AC0TwmnDZHPVBpvF6lIedEP3dUxCNpGh5MDE1trbn2jA7n89AkL8h9GpXbdPVpTj1kA3kBVKOpUMeQAY+zrKGpWtcRWOt0D9r0uK1G9q25j65f8zW3s="> @@ -70,18 +70,18 @@ </fieldset> <input type="hidden" id="CheckOutExpirationTimestamp" name="CheckOutExpirationTimestamp" value="4622B99E-EFBA-4e3b-9AE0-9C19EC60C045|001|gAAMNRi2osGYk5V/c8UTIB0gHGadgVirNlPPFaaWQxHx2ZamRVkuty4Nfrv8eO+iX/90dgSnbDBUyhD5dnedv58Nf7sht4BwkgoCaz/oZgwbHh+OFNYq3Nnv7n96/7zVPO4QZH/qlAsDe7hxuJYjYr5plfdfATz4e/VH2RX6Yy+nqyy1X+eDPXWC4sRE+6WbokJqmIFpx+soxxtVQbfKpCqkjJVZxVOEzkTQQASIKyunctA24AwTtBkPOu3Rc8SxZ1iZgv+fnsJfRyCr0aAUq196"> - + <div style="margin-bottom: 10px;"> <span >*</span> Required</div> - + <div id="TRAVELERDETAILS" style="padding-top: 15px;"> <h2> Traveler Information</h2> - + <table> - <thead> + <thead> <tr> - + <th style="width:280px; font-weight:bold; font-size:1.17em;padding-bottom:0.83em; color:#00245A;">Traveler</th> <th style="width:200px; font-weight:bold; font-size:1.17em;padding-bottom:0.83em; color:#00245A;">Seats</th> <th style="width:275px; font-weight:bold; font-size:1.17em;padding-bottom:0.83em; color:#00245A;">Services Requested</th> @@ -89,10 +89,10 @@ </tr> </thead> <tbody> - - + + <tr> - + <td> <div id="TravelerInfo" style="margin-right:15px;"> @@ -100,33 +100,33 @@ <div style="float:left;"> <!-- mp_trans_disable_start --> Shorty Nge - + <!-- mp_trans_disable_end --> </div> - <div ></div> - + <div ></div> + <div style="float:left; width:53px; text-align:right"><abbr title="Mileage Plan Number">MP#</abbr>: </div> <div style="float:left;"> None entered </div> - <div ></div> + <div ></div> </div> </td> <td style="text-align:left"> <div id="Seats"> No Seats - + </div> </td> - + <td> <div id="AdditionalServices" style="margin-right:15px;"> - + None requested - + </div> </td> @@ -134,88 +134,88 @@ <!----> <div id="EasyBizCustomFields" style="width:150px;" > <!--margin-right:15px;--> - - - + + + </div> - <input id="TravelerDetails_Travelers_0__PassengerId" name="TravelerDetails.Travelers[0].PassengerId" type="hidden" value="0"> + <input id="TravelerDetails_Travelers_0__PassengerId" name="TravelerDetails.Travelers[0].PassengerId" type="hidden" value="0"> </td> </tr> <tr> - + <td colspan="4" style="line-height:.5em;"> </td> - + </tr> - + </tbody> </table> - + <div ></div> <hr style="margin-top:5px;"> </div> - + <h2> Flights</h2> <input id="OptOutOfAutoUpgrade_ShowOptOut" name="OptOutOfAutoUpgrade.ShowOptOut" type="hidden" value="False"> <div style="margin-bottom: 5px;"> - -<table style="width:680px;float:left;"> + +<table style="width:680px;float:left;"> <tbody><tr> - + <th style="width:280px;">Flight</th> <th style="width:200px;">Departs</th> <th style="width:200px;">Arrives</th> </tr> <tr> <td colspan="3" > - + </td> </tr> - + <tr> - + <td> <div> - - + + <span> - + <!-- mp_trans_disable_start -->American<!-- mp_trans_disable_end --> 160 - + (Alaska 1852) - + </span> - + <div >Operated by <!-- mp_trans_disable_start -->American Airlines<!-- mp_trans_disable_end --></div> - + <div >Check in with <!-- mp_trans_disable_start -->American Airlines<!-- mp_trans_disable_end --></div> - + </div> - -<div style="margin-bottom:4px;"> + +<div style="margin-bottom:4px;"> <span > Coach (G) </span> - - + + <span aria-hidden="true">|</span> -Nonstop +Nonstop <span > <span aria-hidden="true">|</span> <a href="javascript://Show Flight Details" onclick="showFlightDetails($(this), '1');" data-track-link="%7B%22section%22%3A%22flights%22%2C%22linkName%22%3A%22details%22%7D">Details</a> </span> - + </div> - + <div> <div id="FlightDetailInfo_1" style="display: none;"> <h2 style="padding-bottom:2px;">Details for Flights</h2> - + <div > <div > @@ -227,14 +227,14 @@ </div> <div > - Depart + Depart <!-- mp_trans_disable_start -->Los Angeles, CA (LAX)<!-- mp_trans_disable_end --> </div> <div > <span > 6:50 - <strong><abbr>am</abbr></strong>, + <strong><abbr>am</abbr></strong>, <abbr title="Wednesday">Wed</abbr>, <abbr title="November">Nov</abbr> 12 </span> </div> @@ -246,13 +246,13 @@ <div > </div> <div > - Arrive + Arrive <!-- mp_trans_disable_start -->San Francisco (SFO)<!-- mp_trans_disable_end --> </div> <div > <span > 8:10 - <strong><abbr>am</abbr></strong>, + <strong><abbr>am</abbr></strong>, <abbr title="Wednesday">Wed</abbr>, <abbr title="November">Nov</abbr> 12 </span> </div> @@ -275,13 +275,13 @@ % cancelled: n/a </li> - </ul> + </ul> </div> <div > <ul > <li> - Duration: + Duration: 1h<span >ours</span> 20m<span >inutes</span> </li> @@ -290,19 +290,19 @@ </li> </ul> </div> - + </div> <div style="padding-bottom: 5px; line-height: 10px; padding-left: 0px; padding-right: 0px; padding-top: 5px;"> <div style="background-color: #999999; height: 1px;"> </div> </div> - + <div > <div >Performance data is based on previous month.</div> </div> </div> - </div> + </div> </td> <td> <!-- mp_trans_disable_start -->Los Angeles, CA (LAX) <!-- mp_trans_disable_end --><br> @@ -310,70 +310,70 @@ </td> <td> <!-- mp_trans_disable_start -->San Francisco (SFO)<!-- mp_trans_disable_end --><br> - + <strong>8:10 <abbr>am</abbr></strong> <abbr title="Wednesday">Wed</abbr>, <abbr title="November">Nov</abbr> 12 - </td> + </td> </tr> - - + + <tr> - + <td colspan="3"> - - <a href="javascript://About Distance" onclick="showDistanceLB($(this));">Distance</a>: + + <a href="javascript://About Distance" onclick="showDistanceLB($(this));">Distance</a>: 337 <abbr title="miles">mi</abbr> - <span aria-hidden="true">|</span> + <span aria-hidden="true">|</span> Duration: 1h<span >ours</span> 20m<span >inutes</span> - + </td> </tr> - - + + <tr><td colspan="3"><div style="width:650px;padding-bottom:0;"></div></td></tr> - + <tr> - + <td> <div> - - + + <span> - + <!-- mp_trans_disable_start -->American<!-- mp_trans_disable_end --> 2378 - + (Alaska 1873) - + </span> - + <div >Operated by <!-- mp_trans_disable_start -->American Airlines<!-- mp_trans_disable_end --></div> - + <div >Check in with <!-- mp_trans_disable_start -->American Airlines<!-- mp_trans_disable_end --></div> - + </div> - -<div style="margin-bottom:4px;"> + +<div style="margin-bottom:4px;"> <span > Coach (G) </span> - - + + <span aria-hidden="true">|</span> -Nonstop +Nonstop <span > <span aria-hidden="true">|</span> <a href="javascript://Show Flight Details" onclick="showFlightDetails($(this), '2');" data-track-link="%7B%22section%22%3A%22flights%22%2C%22linkName%22%3A%22details%22%7D">Details</a> </span> - + </div> - + <div> <div id="FlightDetailInfo_2" style="display: none;"> <h2 style="padding-bottom:2px;">Details for Flights</h2> - + <div > <div > @@ -385,14 +385,14 @@ </div> <div > - Depart + Depart <!-- mp_trans_disable_start -->San Francisco (SFO)<!-- mp_trans_disable_end --> </div> <div > <span > 12:40 - <strong><abbr>pm</abbr></strong>, + <strong><abbr>pm</abbr></strong>, <abbr title="Tuesday">Tue</abbr>, <abbr title="November">Nov</abbr> 18 </span> </div> @@ -404,13 +404,13 @@ <div > </div> <div > - Arrive + Arrive <!-- mp_trans_disable_start -->Los Angeles, CA (LAX)<!-- mp_trans_disable_end --> </div> <div > <span > 2:00 - <strong><abbr>pm</abbr></strong>, + <strong><abbr>pm</abbr></strong>, <abbr title="Tuesday">Tue</abbr>, <abbr title="November">Nov</abbr> 18 </span> </div> @@ -433,13 +433,13 @@ % cancelled: n/a </li> - </ul> + </ul> </div> <div > <ul > <li> - Duration: + Duration: 1h<span >ours</span> 20m<span >inutes</span> </li> @@ -448,19 +448,19 @@ </li> </ul> </div> - + </div> <div style="padding-bottom: 5px; line-height: 10px; padding-left: 0px; padding-right: 0px; padding-top: 5px;"> <div style="background-color: #999999; height: 1px;"> </div> </div> - + <div > <div >Performance data is based on previous month.</div> </div> </div> - </div> + </div> </td> <td> <!-- mp_trans_disable_start -->San Francisco (SFO) <!-- mp_trans_disable_end --><br> @@ -468,43 +468,43 @@ </td> <td> <!-- mp_trans_disable_start -->Los Angeles, CA (LAX)<!-- mp_trans_disable_end --><br> - + <strong>2:00 <abbr>pm</abbr></strong> <abbr title="Tuesday">Tue</abbr>, <abbr title="November">Nov</abbr> 18 - </td> + </td> </tr> - - + + <tr> - + <td colspan="3"> - - <a href="javascript://About Distance" onclick="showDistanceLB($(this));">Distance</a>: + + <a href="javascript://About Distance" onclick="showDistanceLB($(this));">Distance</a>: 337 <abbr title="miles">mi</abbr> - <span aria-hidden="true">|</span> + <span aria-hidden="true">|</span> Duration: 1h<span >ours</span> 20m<span >inutes</span> - + </td> </tr> - - - + + + </tbody></table> <div > <div> - <h4 style="margin:0;">Total Price for 1 Traveler</h4> + <h4 style="margin:0;">Total Price for 1 Traveler</h4> </div> <div > <span >$152.20</span> - - + + <div ></div> - + <div style="padding-top:3px;padding-bottom:5px;"><a href="javascript:void(0);" onclick="showFareAndTaxes($(this))">Taxes, Fees and Charges</a></div> - + <div id="divFareAndTaxesLB" style="display:none;overflow:auto;max-height:480px;"> <h2>Taxes, Fees and Charges</h2> - + <style type="text/css"> #divFareAndTaxes {width:400px;line-height:18px;margin-top:15px;} #divFareAndTaxes div.header1 {width:400px;background-color:#E2EEFF;font-weight:bold;} @@ -572,21 +572,21 @@ <div ></div> </div> <div ></div> - + <div >Each ticket and any booking or change fees will be a separate charge on your credit card statement.</div> </div> <div style="padding-top:5px;"> - -</div> + +</div> <div style="padding-top:10px;"> - + </div> - - + + @@ -602,10 +602,10 @@ </div> - + <div style="display: none;"> <div style="margin-top:10px;"></div> - + <div style="margin-bottom:0.83em;"> <h2 style="display:inline;margin-right:5px;">Trip Protection By Allianz Travel Insurance</h2> <a href="javascript:void(0);" onclick="showRemoveTripInsurance(this);">Remove</a> @@ -614,20 +614,20 @@ <div > <div > <h4>Name</h4> - + <div> <!-- mp_trans_disable_start -->Shorty Nge - + <!-- mp_trans_disable_end --> </div> - - </div> + + </div> <div > - </div> + </div> <div > - </div> + </div> <div ></div> </div> <div > @@ -636,23 +636,23 @@ </div> <div ></div> - </div> + </div> <div > - + <div> <div id="grandTotalLeftColumn" style="width:57%; float:left;"> - + </div> <div id="grandTotalRightColumn" style="width:43%; float:right; text-align:right;"> <div style="display:block;padding-right:10px;"> - + <div> <div style="width:40%;float:left;text-align:right;"><h4 style="margin-bottom:5px;display:inline-block;">Total Due Now</h4></div><div style="width:60%;float:left;text-align:left;"><h4 style="display:inline-block;"> <span id="divTotalDueNowAmount">$152.20 USD</span></h4></div> <div ></div> </div> - + <div> <a id="ShowCurrencyConverterLink" href="https://www.alaskaair.com/booking/addons#">Currency Converter</a> @@ -668,7 +668,7 @@ <h1>Error Encountered</h1> <div > <p>We are unable to complete your transaction at this time. Please try again.</p> - <p>If this problem continues use the "Contact Us" page to send the code listed below, + <p>If this problem continues use the "Contact Us" page to send the code listed below, or call us at 1-800-654-5669, Monday-Friday 8:00 a.m. - 5:45 p.m. (PT) and Saturday 8:00 a.m. - 5:00 p.m. (PT).</p> </div> </div> @@ -678,7 +678,7 @@ <a href="https://www.alaskaair.com/Shopping/CurrencyConverter/GetContents" id="CurrencyContentsURL" style="display: none;">.</a></div> <div ></div> </div> - + </div> <div ></div> </div> @@ -693,9 +693,9 @@ <h4 id="priceSummaryHeading" style="padding-top: 4px;"><a href="javascript://Show/hide section">PRICE SUMMARY</a></h4> </div> <div id="priceSummaryContent" > - + <div style="padding-bottom:18px;"> - + <table cellspacing="0"> <thead> @@ -703,11 +703,11 @@ <th> </th> <th>Fare</th><th>Taxes, Fees and Charges</th> <th>Total</th> - + </tr> </thead> <tbody> - + <tr> <td> Airfare for <!-- mp_trans_disable_start -->Shorty Nge <!-- mp_trans_disable_end -->: @@ -715,16 +715,16 @@ <td>$115.34</td><td>$36.86</td> <td>$152.20</td> </tr> - + <tr id="trTripInsuranceBreakdown" style="display: none;"> - <td>Trip Protection for 1 + <td>Trip Protection for 1 Traveler :</td> <td> </td><td> </td> <td id="tdTripInsuranceBreakdown">$0.00</td> </tr> - + <tr><td colspan="4" >Total Due Now: <span id="spFareSummaryAmount">$152.20</span></td></tr> - + </tbody> </table> @@ -732,7 +732,7 @@ <div ></div> <div id="taxesFees" style="text-align:left; display:none;font-weight:normal;"> - + <div id="TaxesAndFeesSub" style="min-height:500px;"></div> </div> <div id="fareExplanations" style="font-weight:normal;text-align:left; display:none;"></div> @@ -743,23 +743,23 @@ <div style="margin-left: -20px; width: 973px;"> </div> <!-- These ShowHeader flags look for Reissue and Government Fare--> - + <h2> My Wallet / Certificates / Gift Cards </h2> - + <div id="MYWALLETCHECKBOX"> - + <!--TODO: THis should only show when logged in but funds as disabled ... for not AS/QX--> - + <div > <a title="Why can't I use these funds?" href="javascript:void(0);" onclick="showWhyCantUseFundsTip(this);return false;"> Why can't I use these funds?</a></div> - + <div style="float: left; margin-right: 5px; vertical-align: middle;"> <input disabled="disabled" id="MyWalletInformation_UseMyWalletFunds" name="MyWalletInformation.UseMyWalletFunds" type="checkbox" value="true"><input name="MyWalletInformation.UseMyWalletFunds" type="hidden" value="false"></div> <div style="vertical-align: middle;"> <label for="MyWalletInformation_UseMyWalletFunds">Use My Wallet Funds</label></div> - + <div style="margin-left: 24px;"> <a title="My Wallet Terms and Conditions" href="javascript:void(0);" onclick="showMyWalletTerms(this);return false;">Terms and Conditions</a> </div> @@ -767,23 +767,23 @@ </div> </div> <input id="MyWalletInformation_ShowCheckbox" name="MyWalletInformation.ShowCheckbox" type="hidden" value="True"> - + <div id="GIFTCARDSANDCERTIFICATESCHECKBOX"> - + <div style="float: left; margin-right: 5px; vertical-align: middle;"> <input disabled="disabled" id="GiftCardsAndCertificatesInformation_UseGiftCardsOrCertificates" name="GiftCardsAndCertificatesInformation.UseGiftCardsOrCertificates" type="checkbox" value="true"><input name="GiftCardsAndCertificatesInformation.UseGiftCardsOrCertificates" type="hidden" value="false"></div> <div style="float: left; vertical-align: middle;"> <label for="GiftCardsAndCertificatesInformation_UseGiftCardsOrCertificates">Use Certificates or Gift Cards (not deposited in a My Wallet account)</label></div> - + <div > </div> </div> <input id="GiftCardsAndCertificatesInformation_ShowCheckbox" name="GiftCardsAndCertificatesInformation.ShowCheckbox" type="hidden" value="True"> <div id="GIFTCARDSANDCERTIFICATES" style="display: none;"> - + </div> <div id="GIFTCARDSANDCERTIFICATESSUMMARY"> - + </div> <input id="GiftCardsAndCertificatesInformation_ShowGiftCardOrCertificateEntries" name="GiftCardsAndCertificatesInformation.ShowGiftCardOrCertificateEntries" type="hidden" value="False"> <input id="GiftCardsAndCertificatesInformation_ShowGiftCardsOrCertificates" name="GiftCardsAndCertificatesInformation.ShowGiftCardsOrCertificates" type="hidden" value="False"> @@ -792,13 +792,13 @@ <input id="MyWalletInformation_ShowMyWalletSummaryAndDetail" name="MyWalletInformation.ShowMyWalletSummaryAndDetail" type="hidden" value="False"> <input id="MyWalletInformation_GrandTotalAmountToCollect" name="MyWalletInformation.GrandTotalAmountToCollect" type="hidden" value="0"> </div> - + <div id="CREDITCARDANDTIPBOX"> <div > </div> - + <hr > - + <div id="CREDITCARD"> <h2> Credit Card Information</h2> <!--Show Booking Engine Credit Card Error here--> @@ -815,9 +815,9 @@ <div id="BILLINGCREDITCARDENTRY"> <!--Billing Credit Card Error--> <!-- For error messages that need to bubble from within the validation method, instead of for a specific form element -- example -- credit card doesn't validate---> - + <!--Card Types--> - + <div id="CardTypesSelected"> <div id="CardTypesSelectedLabel" >Card Type<span >*</span></div> <div> @@ -830,17 +830,17 @@ <div > </div> <!--Card Number--> - + <div id="CardNumberLabel"><label for="CreditCardInformation_BillingCreditCardEntry_CardNumber">Card Number</label><span >*</span></div> <div id="CardNumber"> <!-- mp_trans_disable_start --> -<input autocomplete="off" id="CreditCardInformation_BillingCreditCardEntry_CardNumber" maxlength="24" name="CreditCardInformation.BillingCreditCardEntry.CardNumber" type="text" value=""> <!-- mp_trans_disable_end --> +<input id="CreditCardInformation_BillingCreditCardEntry_CardNumber" maxlength="24" name="CreditCardInformation.BillingCreditCardEntry.CardNumber" type="text" value=""> <!-- mp_trans_disable_end --> </div> <div > </div> <!--Generic Expiration Date Errors--> - - + + <div> Expiration<span >*</span></div> <div id="ExpirationMonths" style="float: left; padding-right: 10px;"> @@ -883,7 +883,7 @@ <div > </div> <!--Name on Card--> - + <div id="CardPersonNameLabel"><label for="CreditCardInformation_BillingCreditCardEntry_CardPersonName">Name on Card</label><span >*</span></div> <div id="CardPersonName"> <!-- mp_trans_disable_start --> @@ -907,7 +907,7 @@ <div > </div> <!--Countries--> - + <div id="CountriesLabel"><label for="CreditCardInformation_BillingAddressEntry_Countries_Selected">Country</label><span >*</span></div> <div id="Countries"> <!-- mp_trans_disable_start --> @@ -1156,14 +1156,14 @@ </div> <div > </div> - + <div id="Address1Label"><label for="CreditCardInformation_BillingAddressEntry_Address1">Address</label><span >*</span></div> <div id="Address1" style="margin-bottom: 5px;"> <!-- mp_trans_disable_start --> <input id="CreditCardInformation_BillingAddressEntry_Address1" maxlength="29" name="CreditCardInformation.BillingAddressEntry.Address1" size="27" type="text" value=""> <!-- mp_trans_disable_end --> </div> - + <div id="Address2Label"> <span ><label for="CreditCardInformation_BillingAddressEntry_Address2">Address Line 2</label></span> </div> @@ -1175,7 +1175,7 @@ <div > </div> <!--City--> - + <div id="CityLabel"><label for="CreditCardInformation_BillingAddressEntry_City">City</label><span >*</span></div> <div id="City"> <!-- mp_trans_disable_start --> @@ -1185,7 +1185,7 @@ <div > </div> <div id="USSTATES" style="display: block;"> - + <div><label for="CreditCardInformation_BillingAddressEntry_USStates_Selected">State/Province</label><span >*</span></div> <div> <!-- mp_trans_disable_start --> @@ -1259,7 +1259,7 @@ </div> </div> <div id="CASTATES" style="display: none;"> - + <div><label for="CreditCardInformation_BillingAddressEntry_CAStates_Selected">State/Province</label><span >*</span></div> <div> <!-- mp_trans_disable_start --> @@ -1282,7 +1282,7 @@ </div> </div> <div id="MXSTATES" style="display: none;"> - + <div><label for="CreditCardInformation_BillingAddressEntry_MXStates_Selected">State/Province</label><span >*</span></div> <div> <!-- mp_trans_disable_start --> @@ -1324,7 +1324,7 @@ </div> </div> <div id="OTHERSTATES" style="display: none;"> - + <div><label for="CreditCardInformation_BillingAddressEntry_OtherStates_Selected">State/Province</label><span >*</span></div> <div> <!-- mp_trans_disable_start --> @@ -1335,7 +1335,7 @@ <div > </div> <div id="POSTALCODE"> - + <div><label for="CreditCardInformation_BillingAddressEntry_PostalCode">Zip/Postal Code</label><span >*</span></div> <div> <!-- mp_trans_disable_start --> @@ -1358,7 +1358,7 @@ <div > </div> <!--Country Code--> - + <div id="CountryCodeLabel"><label for="CreditCardInformation_BillingPhoneNumberEntry_CountryCode_Selected">Country Code</label><span >*</span></div> <div id="CountryCode"> <!-- mp_trans_disable_start --> @@ -1606,7 +1606,7 @@ </div> <div > </div> - + <div id="PhoneNumberLabel"><label for="CreditCardInformation_BillingPhoneNumberEntry_Number">Phone (with area code)</label><span >*</span></div> <div id="PhoneNumber"> <!-- mp_trans_disable_start --> @@ -1628,18 +1628,18 @@ </div> <!--TipBox--> <div style="float: left;"> - + </div> </div> <hr > - + <div > </div> - + <div > </div> - + <div id="BOAFCOFFERPAYMENT" > <div > <div style="position: absolute;"> @@ -1674,28 +1674,28 @@ <ul style="margin-top:0;"><li>Reimburses non-refundable, prepaid expenses up to the cost of your ticket(s) if you cancel your trip</li><li>Covers emergency medical / dental and emergency medical transportation while traveling</li><li>Helps with trip interruption, lost or damaged baggage, baggage delay, and additional travel delay costs </li></ul>Terms, conditions and exclusions apply, <a id="WASCInsuranceOfferBODYHref0" href="https://gateway.americas.allianz-assistance.com/TC/ALA/TP_6.html" target="_blank" onclick="window.open('https://gateway.americas.allianz-assistance.com/TC/ALA/TP_6.html','OPTION', 'width=580,height=550,resizable=yes,menubar=no,status=no,scrollbars=yes,toolbar=no,directories=no,location=no'); return false;">learn more.</a></div> </div> <div > - - + + <div > <input type="radio" id="TripInsurance_QuoteID657566350481481886" name="TripInsurance.QuoteID" value="657566350481481886" onclick="SetTripInsurancePrice(21.0)"> <label for="TripInsurance_QuoteID657566350481481886" title="Yes, add trip protection for a total of $21.00. "> <strong>Yes,</strong> add trip protection for a total of <strong>$21.00</strong>. </label> </div> - + <div > <input type="radio" id="TripInsurance_QuoteID657566350481481887" name="TripInsurance.QuoteID" value="657566350481481887" onclick="SetTripInsurancePrice(0.00)"> <label for="TripInsurance_QuoteID657566350481481887" title="No, I choose not to protect my purchase."> No, I choose not to protect my purchase.</label> </div> - + </div> - + <div id="TripInsurance_Disclaimer" style="clear: both; margin: 15px 10px 0px 0px;"> <div >You will see a separate charge for Allianz Travel Insurance on your credit card. Commercial accounts, UATP cards, gift cards, certificates and My Wallet funds are not valid forms of payment.</div></div> - + <div id="TripInsurance_Footer" style="clear: both; margin-top: 15px;"> "It's wise to always consider a travel protection plan to cover your trip costs from the unexpected." – <em>Frommer's, Feb 2014</em><br><br>Product available to residents of all states except: WA. <br>Plans underwritten by Jefferson Insurance Company or BCS Insurance Company. </div> - + </div> </div> @@ -1706,17 +1706,17 @@ <div ></div> <hr id="hrLine" > - + </div> - + <div id="tripInsuranceCreditCardSection" style="display: none;"> - + <div ></div> - - + + <div ></div> <div > - Commercial accounts, UATP cards, gift cards, certificates and My Wallet funds are not valid forms of payment for trip protection. Please select an additional credit card or call Allianz Travel Insurance directly at 800-496-6593. + Commercial accounts, UATP cards, gift cards, certificates and My Wallet funds are not valid forms of payment for trip protection. Please select an additional credit card or call Allianz Travel Insurance directly at 800-496-6593. </div> <!--Show Booking Engine Credit Card Error here--> <!--Non Ticket Credit Card Error--> @@ -1725,32 +1725,32 @@ <div ></div> <div id="Ancillary_NotSignedIn_CreditCard"> - + <div id="BILLINGCREDITCARDENTRY" style="float:left;"> <!--Billing Credit Card Error--> <!-- For error messages that need to bubble from within the validation method, instead of for a specific form element -- example -- credit card doesn't validate---> - + <!--Card Types--> - + <div id="CardTypesSelected"> <div id="CardTypesSelectedLabel" >Card Type</div> - <div> + <div> <input id="AncillaryCreditCardInformation_BillingCreditCardEntry_CardTypes_Selected" name="AncillaryCreditCardInformation.BillingCreditCardEntry.CardTypes_Selected" type="hidden" value="CreditCard"> <label> - </div> + </div> </div> <div ></div> <!--Card Number--> - + <div id="CardNumberLabel"><label for="AncillaryCreditCardInformation_BillingCreditCardEntry_CardNumber">Card Number</label><span >*</span></div> <div id="CardNumber"> <!-- mp_trans_disable_start --> -<input autocomplete="off" id="AncillaryCreditCardInformation_BillingCreditCardEntry_CardNumber" maxlength="24" name="AncillaryCreditCardInformation.BillingCreditCardEntry.CardNumber" type="text" value=""> <!-- mp_trans_disable_end --> +<input id="AncillaryCreditCardInformation_BillingCreditCardEntry_CardNumber" maxlength="24" name="AncillaryCreditCardInformation.BillingCreditCardEntry.CardNumber" type="text" value=""> <!-- mp_trans_disable_end --> </div> <div ></div> <!--Generic Expiration Date Errors--> - - + + <div>Expiration<span >*</span></div> <div id="ExpirationMonths" style="float: left; padding-right: 10px;"> <!-- mp_trans_disable_start --> @@ -1791,24 +1791,24 @@ </div> <div ></div> <!--Name on Card--> - + <div id="CardPersonNameLabel"><label for="AncillaryCreditCardInformation_BillingCreditCardEntry_CardPersonName">Name on Card</label><span >*</span></div> <div id="CardPersonName"> <!-- mp_trans_disable_start --> <input id="AncillaryCreditCardInformation_BillingCreditCardEntry_CardPersonName" maxlength="38" name="AncillaryCreditCardInformation.BillingCreditCardEntry.CardPersonName" size="41" type="text" value=""> <!-- mp_trans_disable_end --> </div> - </div> + </div> <div > <div > <div style="float: left"> <h5 >Billing Address</h5> - </div> + </div> <div ></div> <div > <!--Countries--> - + <div id="CountriesLabel"><label for="AncillaryCreditCardInformation_BillingAddressEntry_Countries_Selected">Country</label><span >*</span></div> <div id="Countries"> <!-- mp_trans_disable_start --> @@ -2056,14 +2056,14 @@ <!-- mp_trans_disable_end --> </div> <div ></div> - + <div id="Address1Label"><label for="AncillaryCreditCardInformation_BillingAddressEntry_Address1">Address</label><span >*</span></div> <div id="Address1" style="margin-bottom: 5px;"> <!-- mp_trans_disable_start --> <input id="AncillaryCreditCardInformation_BillingAddressEntry_Address1" maxlength="29" name="AncillaryCreditCardInformation.BillingAddressEntry.Address1" size="27" type="text" value=""> <!-- mp_trans_disable_end --> </div> - + <div id="Address2Label"> <span ><label for="AncillaryCreditCardInformation_BillingAddressEntry_Address2">Address Line 2</label></span> </div> @@ -2072,19 +2072,19 @@ <input id="AncillaryCreditCardInformation_BillingAddressEntry_Address2" maxlength="29" name="AncillaryCreditCardInformation.BillingAddressEntry.Address2" size="27" type="text" value=""> <!-- mp_trans_disable_end --> </div> - </div> + </div> <div > <!--City--> - + <div id="CityLabel"><label for="AncillaryCreditCardInformation_BillingAddressEntry_City">City</label><span >*</span></div> <div id="City"> <!-- mp_trans_disable_start --> <input id="AncillaryCreditCardInformation_BillingAddressEntry_City" maxlength="28" name="AncillaryCreditCardInformation.BillingAddressEntry.City" size="27" type="text" value=""> <!-- mp_trans_disable_end --> - </div> - <div ></div> + </div> + <div ></div> <div id="ANCILLARY_USSTATES" style="display: block;"> - + <div><label for="AncillaryCreditCardInformation_BillingAddressEntry_USStates_Selected">State/Province</label><span >*</span></div> <div> <!-- mp_trans_disable_start --> @@ -2158,7 +2158,7 @@ </div> </div> <div id="ANCILLARY_CASTATES" style="display: none;"> - + <div><label for="AncillaryCreditCardInformation_BillingAddressEntry_CAStates_Selected">State/Province</label><span >*</span></div> <div> <!-- mp_trans_disable_start --> @@ -2181,7 +2181,7 @@ </div> </div> <div id="ANCILLARY_MXSTATES" style="display: none;"> - + <div><label for="AncillaryCreditCardInformation_BillingAddressEntry_MXStates_Selected">State/Province</label><span >*</span></div> <div> <!-- mp_trans_disable_start --> @@ -2223,7 +2223,7 @@ </div> </div> <div id="ANCILLARY_OTHERSTATES" style="display: none;"> - + <div><label for="AncillaryCreditCardInformation_BillingAddressEntry_OtherStates_Selected">State/Province</label><span >*</span></div> <div> <!-- mp_trans_disable_start --> @@ -2233,14 +2233,14 @@ </div> <div ></div> <div id="POSTALCODE"> - + <div><label for="AncillaryCreditCardInformation_BillingAddressEntry_PostalCode">Zip/Postal Code</label><span >*</span></div> <div> <!-- mp_trans_disable_start --> <input id="AncillaryCreditCardInformation_BillingAddressEntry_PostalCode" maxlength="10" name="AncillaryCreditCardInformation.BillingAddressEntry.PostalCode" type="text" value=""> <!-- mp_trans_disable_end --> - </div> - </div> + </div> + </div> </div> <div ></div> <div > @@ -2248,7 +2248,7 @@ <h5 >Card Holder Phone Number</h5> </div> <!--Country Code--> - + <div id="CountryCodeLabel"><label for="AncillaryCreditCardInformation_BillingPhoneNumberEntry_CountryCode_Selected">Country Code</label><span >*</span></div> <div id="CountryCode"> <!-- mp_trans_disable_start --> @@ -2493,12 +2493,12 @@ <option value="263">Zimbabwe (+263)</option> </select> <!-- mp_trans_disable_end --> - </div> + </div> </div> <div > <div ></div> <div> - + <div id="PhoneNumberLabel"><label for="AncillaryCreditCardInformation_BillingPhoneNumberEntry_Number">Phone (with area code)</label><span >*</span></div> <div id="PhoneNumber"> <!-- mp_trans_disable_start --> @@ -2521,43 +2521,43 @@ <div id="SecurityCodeTip" style="display: none; height: 440px;"></div> </div> - - + + <hr > </div> - + <div > </div> <div id="RULESANDRESTRICTIONS"> <h2>Rules and Restrictions</h2> - + <strong>Flight</strong> - + <div id="divRuleLightBox" style="display:none;overflow:auto;height:510px;"></div> -<div id="fareRules"> +<div id="fareRules"> <div style="clear:left;"> - <div style="padding-top:5px;padding-right:5px;"> + <div style="padding-top:5px;padding-right:5px;"> <ul> - - <li>This fare is <b>nonrefundable</b>.</li> - - <li>Reservations require immediate purchase and may not be held. Fares and availability are subject to change without notice until purchased.</li> - - <li>If travel has not yet commenced, you may make one change to this itinerary <b>OR</b> cancel and refund to original form of payment with no fee within 24 hours of original purchase.</li> - - <li>Changes to this itinerary are subject to additional fare and taxes. A fee of $125 USD per person will also be assessed. Change fees are waived for travel wholly within the State of Alaska on flights operated by Alaska Airlines and Horizon Air, and for all MVP® Gold members.</li> - - <li><a href="javascript://Show All Rules" data-track-link="%7B%22section%22%3A%22rulesandrestrictions%22%2C%22linkName%22%3A%22viewallrarerules%22%7D" onclick="showAllRules($(this),'7', 'Standard');return false;" title="View All Fare Rules" alt="View All Fare Rules">View all fare rules</a></li> - + + <li>This fare is <b>nonrefundable</b>.</li> + + <li>Reservations require immediate purchase and may not be held. Fares and availability are subject to change without notice until purchased.</li> + + <li>If travel has not yet commenced, you may make one change to this itinerary <b>OR</b> cancel and refund to original form of payment with no fee within 24 hours of original purchase.</li> + + <li>Changes to this itinerary are subject to additional fare and taxes. A fee of $125 USD per person will also be assessed. Change fees are waived for travel wholly within the State of Alaska on flights operated by Alaska Airlines and Horizon Air, and for all MVP® Gold members.</li> + + <li><a href="javascript://Show All Rules" data-track-link="%7B%22section%22%3A%22rulesandrestrictions%22%2C%22linkName%22%3A%22viewallrarerules%22%7D" onclick="showAllRules($(this),'7', 'Standard');return false;" title="View All Fare Rules" alt="View All Fare Rules">View all fare rules</a></li> + </ul> </div> </div> - + <div id="AllRulesContainer" style="display:none;"> <iframe id="AllRulesFrame" src="javascript:void(0);" width="560" height="210" frameborder="0"></iframe> <a id="AllRulesUrl" style="display:none;" href="https://www.alaskaair.com/Shopping/SSL/FareRules.aspx?view=0"></a> - </div> + </div> <div id="DiscountCodeTermsContainer" style="display:none;"> <iframe id="DiscountCodeTermsFrame" src="javascript:false;" width="565" height="500" frameborder="0"></iframe> <a id="DiscountCodeTermsUrl" style="display:none;" href="https://www.alaskaair.com/shared/tips/AboutDiscountCodes.aspx?view=0"></a> @@ -2566,12 +2566,12 @@ <a id="ContractFareURL" style="display:none;" href="https://easybiz.alaskaair.com/ContractFareInfo?section=popup&lightbox=true"></a> <a id="umnrRulesURL" style="display:none;" href="https://www.alaskaair.com/content/travel-info/policies/children-traveling-alone/children-alone-lightbox.aspx"></a> <a id="standByRulesURL" style="display:none;" href="https://www.alaskaair.com/content/travel-info/at-the-airport/same-day-flight-changes/standby-rules/standby-rules-lightbox.aspx"></a> - + <div id="AllRulesLB" style="display:none;overflow:auto;"> <style type="text/css">ul.discs li {list-style-type:disc;}</style> <h2 style="margin-bottom:0.83em;"></h2> <ul > - + </ul> </div> @@ -2593,12 +2593,12 @@ <div id="divTripInsuranceRules" style="display: none;"> <strong>Add-ons</strong> <ul> - + <li>Trip Protection Terms and Conditions apply.</li> - + </ul> </div> - + <!--TODO: there still needs to be work on getting the umnr light box to show data, I modeled it after views/cart/farerules.ascx but there still needs to be work done. See Vinnie or Holly for help--> <input id="UMNRRules_ShowUMNRRules" name="UMNRRules.ShowUMNRRules" type="hidden" value="False"> @@ -2612,7 +2612,7 @@ <div id="WebsiteTermsOfUse" style="display: none; height: 520px; width: 560px; overflow: auto;"></div> <input type="submit" id="PurchaseButton" name="purchase" value="PURCHASE" title="PURCHASE"> - + </div> </div> <div > @@ -2639,7 +2639,7 @@ <input type="hidden" id="ReturnFromStepoutId" name="ReturnFromStepoutId" value=""> <input type="hidden" id="ReturnFromStepoutItem" name="ReturnFromStepoutItem" value=""> <input type="hidden" id="ReturnFromStepoutType" name="ReturnFromStepoutType" value=""> - + <input type="hidden" id="PaymentType" name="PaymentType" value="creditcard"> <input id="TripInsuranceVisibility" name="TripInsuranceVisibility" type="hidden" value="False"> <input id="TripInsuranceCreditCardVisible" name="TripInsuranceCreditCardVisible" type="hidden" value="False">
diff --git a/components/test/data/autofill/heuristics/input/093_checkout_m_walmart.com.html b/components/test/data/autofill/heuristics/input/093_checkout_m_walmart.com.html index 0ba0e9c..e9f387c 100644 --- a/components/test/data/autofill/heuristics/input/093_checkout_m_walmart.com.html +++ b/components/test/data/autofill/heuristics/input/093_checkout_m_walmart.com.html
@@ -6,13 +6,13 @@ <input autocorrect="off" name="lastName" type="text" id="txt884" placeholder="Last name" ></div> <div data-view-cid="view885" data-view-name="checkout/address-form" data-model-cid="c886" data-view-helper-restore="view"><div ><label for="txt889">Address</label> -<input autocomplete="off" autocorrect="off" name="address[street1]" type="text" id="txt889" placeholder="Address" ></div> +<input autocorrect="off" name="address[street1]" type="text" id="txt889" placeholder="Address" ></div> <div ><label for="txt890">Address line 2 (optional)</label> -<input autocomplete="off" autocorrect="off" name="address[street2]" type="text" id="txt890" placeholder="Address line 2 (optional)" ></div> +<input autocorrect="off" name="address[street2]" type="text" id="txt890" placeholder="Address line 2 (optional)" ></div> <div ><label for="txt891">ZIP code</label> <input maxlength="10" name="address[zip]" type="tel" id="txt891" placeholder="ZIP code" ></div> <div ><label for="txt892">City</label> -<input autocomplete="off" autocorrect="off" field name="address[city]" type="text" id="txt892" placeholder="City" ></div> +<input autocorrect="off" field name="address[city]" type="text" id="txt892" placeholder="City" ></div> <div data-view-cid="view893" data-view-name="location/state-selector" data-view-helper-restore="view"><label for="view893_state">State</label> <select id="view893_state" name="address[state]"> <option value=""> State </option> @@ -20,10 +20,10 @@ </select> </div> -<input type="hidden" name="address[country]"> +<input type="hidden" name="address[country]"> <div ><label for="txt894">Phone number</label> -<input autocomplete="off" maxlength="20" type="tel" name="phoneNumber" id="txt894" placeholder="Phone number"></div> +<input maxlength="20" type="tel" name="phoneNumber" id="txt894" placeholder="Phone number"></div> </div> </div></div></div> </div>
diff --git a/components/test/data/autofill/heuristics/input/101_checkout_m_bestbuy.com.html b/components/test/data/autofill/heuristics/input/101_checkout_m_bestbuy.com.html index 76f5edb..52d5227 100644 --- a/components/test/data/autofill/heuristics/input/101_checkout_m_bestbuy.com.html +++ b/components/test/data/autofill/heuristics/input/101_checkout_m_bestbuy.com.html
@@ -47,7 +47,7 @@ <input type="hidden" name="existCardType" value="NEW"> -<input name="_D:selCreditCardType" value=" " type="hidden"><select name="selCreditCardType" onchange="onCreditCardChange();"><option value="">Choose Card +<input name="_D:selCreditCardType" value=" " type="hidden"><select name="selCreditCardType" onchange="onCreditCardChange();"><option value="">Choose Card </option><option value="Visa">Visa </option><option value="MasterCard">MasterCard </option><option value="AmericanExpress">American Express @@ -62,7 +62,7 @@ <label>Card Number</label> -<input maxlength="17" name="cardNumber" value="" type="tel" autocomplete="off"><input name="_D:cardNumber" value=" " type="hidden"> +<input maxlength="17" name="cardNumber" value="" type="tel"><input name="_D:cardNumber" value=" " type="hidden"> @@ -137,7 +137,7 @@ <label>Security Code</label> -<input maxlength="4" name="securityCode" value="" type="tel" autocomplete="off"><input name="_D:securityCode" value=" " type="hidden"><br> +<input maxlength="4" name="securityCode" value="" type="tel"><input name="_D:securityCode" value=" " type="hidden"><br> <p >Last 3 numbers on back (for most cards)</p> @@ -159,7 +159,7 @@ -<!-- 1218908771407 --> +<!-- 1218908771407 --> <!--Session Encoding Start--> <div id="tmx_profile_tags"> <p style="background:url(https://tmx.bestbuy.com/fp/clear.png?org_id=ummqowa2&session_id=f3a7e75093e1c1da71f7ff4047732f4d72649fdf136ded64fba35256bbadea76&m=1)"></p> @@ -222,44 +222,44 @@ <div id="redeem-gift-open" > <label >Card Number or Code</label> -<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> -<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"><img src="https://img-ssl.bbystatic.com/BestBuy_US/mobile/images/gift-card-back.jpg" alt="Gift Card"> +<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> +<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"><img src="https://img-ssl.bbystatic.com/BestBuy_US/mobile/images/gift-card-back.jpg" alt="Gift Card"> <div id="add-giftCard-content1" > <label >Card Number or Code</label> -<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> -<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> +<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> +<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> <div id="add-giftCard-content2" > <label >Card Number or Code</label> -<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> -<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> +<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> +<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> <div id="add-giftCard-content3" > <label >Card Number or Code</label> -<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> -<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> +<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> +<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> <div id="add-giftCard-content4" > <label >Card Number or Code</label> -<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> -<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> +<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> +<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> <div id="add-giftCard-content5" > <label >Card Number or Code</label> -<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> -<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> +<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> +<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> <div id="add-giftCard-content6" > <label >Card Number or Code</label> -<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> -<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> +<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> +<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> <div id="add-giftCard-content7" > <label >Card Number or Code</label> -<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> -<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> +<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> +<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> <div id="add-giftCard-content8" > <label >Card Number or Code</label> -<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> -<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> +<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> +<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> <div id="add-giftCard-content9" > <label >Card Number or Code</label> -<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> -<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> +<input maxlength="16" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCNumber" value=" " type="hidden"><label >Security Code</label> +<input maxlength="4" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value="" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.SVCCID" value=" " type="hidden"></div> <div > <button id="add-giftCard" >+ Add Another</button> </div> @@ -286,9 +286,9 @@ <label>Member ID</label> -<input id="memberNo" maxlength="17" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.rwzCertMemberNumbers" value="" onkeypress="return numOnly(event);" type="tel" autocomplete="off" size="5"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.rwzCertMemberNumbers" value=" " type="hidden"> +<input id="memberNo" maxlength="17" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.rwzCertMemberNumbers" value="" onkeypress="return numOnly(event);" type="tel" size="5"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.rwzCertMemberNumbers" value=" " type="hidden"> <label>Certificate Number <span >Last 10 digits</span></label> -<input id="certName" maxlength="15" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.rwzCertNumbers" value="" onkeypress="return numOnly(event);" type="tel" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.rwzCertNumbers" value=" " type="hidden"> +<input id="certName" maxlength="15" name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.rwzCertNumbers" value="" onkeypress="return numOnly(event);" type="tel"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.rwzCertNumbers" value=" " type="hidden"> <h4>Amount</h4> <p>The value of your reward certificates may not be greater than your order total, before tax and shipping. </p> @@ -311,18 +311,18 @@ <label >Code</label> -<input name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value="" type="text" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value=" " type="hidden"><div id="add-promoCode-content1" > +<input name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value="" type="text"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value=" " type="hidden"><div id="add-promoCode-content1" > <label >Code</label> -<input name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value="" type="text" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value=" " type="hidden"></div> +<input name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value="" type="text"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value=" " type="hidden"></div> <div id="add-promoCode-content2" > <label >Code</label> -<input name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value="" type="text" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value=" " type="hidden"></div> +<input name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value="" type="text"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value=" " type="hidden"></div> <div id="add-promoCode-content3" > <label >Code</label> -<input name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value="" type="text" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value=" " type="hidden"></div> +<input name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value="" type="text"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value=" " type="hidden"></div> <div id="add-promoCode-content4" > <label >Code</label> -<input name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value="" type="text" autocomplete="off"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value=" " type="hidden"></div> +<input name="/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value="" type="text"><input name="_D:/bestbuy/digiterra/commerce/order/formhandler/CheckoutPaymentFormHandler.digitalDiscountsIds" value=" " type="hidden"></div> <div > <button id="add-promoCode" >+ Add Another</button> </div>
diff --git a/components/test/data/autofill/heuristics/input/102_checkout_m_macys.com.html b/components/test/data/autofill/heuristics/input/102_checkout_m_macys.com.html index 06758207..5f4b159 100644 --- a/components/test/data/autofill/heuristics/input/102_checkout_m_macys.com.html +++ b/components/test/data/autofill/heuristics/input/102_checkout_m_macys.com.html
@@ -1,5 +1,5 @@ <!-- Cropped from m.macys.com/chkout/payment --> -<form id="paymentVB" novalidate="novalidate" action="https://m.macys.com/chkout/payment/continuecheckout" method="post" autocomplete="off"> +<form id="paymentVB" novalidate="novalidate" action="https://m.macys.com/chkout/payment/continuecheckout" method="post"> <img src="https://www.macys.com/sns/web20/assets/img/checkout/loading.gif" alt="loading icon" /> </div --> <div id="mainWrapper"> @@ -48,7 +48,7 @@ <label for="paymentCardNumber" id="ariaCreditCardNo" > card number: </label> -<input id="paymentCardNumber" name="creditCard.cardNumber" aria-labelledby="ariaCreditCardNo" aria-required="true" maxlength="20 " type="tel" value="" autocomplete="off"> +<input id="paymentCardNumber" name="creditCard.cardNumber" aria-labelledby="ariaCreditCardNo" aria-required="true" maxlength="20 " type="tel" value=""> </div> <input id="maskedCreditCardNumber" name="creditCard.maskedCreditCardNumber" aria-hidden="true" type="hidden" value=""><div id="paymentCardExpirationDate" > <div id="label-container-1"><label for="paymentCardExpMonth" id="ariaCreditCardExpMonth"> @@ -86,16 +86,16 @@ <option aria-selected="false" value="2023" id="ariaSelectFieldId32">2023</option></select></div></div> <div id="paymentCardSecurityCode" > <div id="label-container-4"><label for="paymentCardSecCode" id="ariaCreditCardSecurityCode"> -please enter security code: +please enter security code: </label></div> <input id="paymentCardSecCode" name="creditCard.securityCode" pattern="[0-9]*" aria-labelledby="ariaCreditCardSecurityCode" aria-required="true" type="tel" value="" maxlength="4"><a id="whatThis" href="javascript:void(0);" tabindex="0" title="security code help"></a> -<div id="yui_3_8_1_8_1414183143751_292" style="left: -161px; top: 22px; z-index: 5;"><span id="secCodeHintText" aria-hidden="true"><div ><span id="yui_3_8_1_8_1414183143751_359"><button type="button" id="yui_3_8_1_8_1414183143751_298" >Close</button></span></div> +<div id="yui_3_8_1_8_1414183143751_292" style="left: -161px; top: 22px; z-index: 5;"><span id="secCodeHintText" aria-hidden="true"><div ><span id="yui_3_8_1_8_1414183143751_359"><button type="button" id="yui_3_8_1_8_1414183143751_298" >Close</button></span></div> <span> <img src="https://m.macys.com/sns/web20/assets/img/cvvicon.png" alt="cvv icon"> Enter the 3-digit number on the back of your card. American Express® cardholders use the 4-digit number on the front of the card. -</span> -</span></div> +</span> +</span></div> </div> <a id="debitLink" href="/sns/content/debitAuthorization.jsp">Paying with a debit card?</a> </div> @@ -264,7 +264,7 @@ <label for="email" id="ariaEmailAdds">email address:</label> <span id="ariaEmailDescription">Please enter your email address</span> <input id="email" name="user.profile.email" pattern="^[\w\.\-\_\+]+@([\w\-]+\.)+[a-zA-Z]{2,10}$" aria-labelledby="ariaEmailAdds" type="email" aria-describedby="ariaEmailDescription" value="" maxlength="75"> -</div> +</div> <div > <label for="confirmEmail">Confirm email address:</label> <span id="ariaConfirmEmailDescription">Please Re enter your email address</span> @@ -275,7 +275,7 @@ <span id="ariaPasswordDescription">Please enter password</span> <input id="password" name="user.profile.password" pattern="^[a-zA-Z0-9]+" aria-labelledby="ariaPassword" aria-required="true" maxlength="16" aria-describedby="ariaPasswordDescription" type="password" value=""> </div> -<div > +<div > <label for="cpassword" id="ariaRePassword">Confirm password:</label> <span id="ariaRePasswordDescription">Please re-enter password</span> <input id="cpassword" name="user.profile.confirmPassword" pattern="^[a-zA-Z0-9]+" aria-labelledby="ariaRePassword" aria-required="true" maxlength="16" aria-describedby="ariaRePasswordDescription" type="password" value=""> @@ -283,7 +283,7 @@ <div id="birthday"> <div id="label-container-4"><label id="ariaBirthday" for="birthday_month">Birthdate:</label></div> -<div > +<div > <select id="birthday_month" name="user.profile.month" aria-labelledby="ariaBirthday" aria-required="true" aria-activedescendant="ariaSelectFieldId96"><option aria-selected="true" value="-1" id="ariaSelectFieldId96">Month</option> <option aria-selected="false" value="01" id="ariaSelectFieldId97">January</option> <option aria-selected="false" value="02" id="ariaSelectFieldId98">February</option> @@ -427,7 +427,7 @@ <div > <input id="emailUpdates" name="user.profile.subscriptionInfo.emailSalesEvents" aria-labelledby="ariaEmailUpdates" type="checkbox" value="true" checked="" aria-checked="true"><input type="hidden" name="_user.profile.subscriptionInfo.emailSalesEvents" value="on"><label id="ariaEmailUpdates" for="emailUpdates">Yes, send me email updates from Macy’s.com about the latest trends, products and promotions online and in-store.</label> <br > -</div> +</div> <div > <input id="savePaymentDetails" name="user.savePaymentDetails" type="checkbox" value="true" aria-checked="false"><input type="hidden" name="_user.savePaymentDetails" value="on"><label id="savePaymentInfo" for="savePaymentDetails">Yes, save payment information to my Macy's profile.</label> <br >
diff --git a/components/test/data/autofill/heuristics/input/103_checkout_peapod.com.html b/components/test/data/autofill/heuristics/input/103_checkout_peapod.com.html index 7e278ec..eb3eb42 100644 --- a/components/test/data/autofill/heuristics/input/103_checkout_peapod.com.html +++ b/components/test/data/autofill/heuristics/input/103_checkout_peapod.com.html
@@ -1,4 +1,4 @@ -<form method="POST" action="/checkoutBillingInfoFrame.jhtml?_DARGS=/checkoutBillingInfoFrame.jhtml" name="CheckoutBillingInformation"> +<form method="POST" action="/checkoutBillingInfoFrame.jhtml?_DARGS=/checkoutBillingInfoFrame.jhtml" name="CheckoutBillingInformation"> <!-- <setvalue bean="CheckoutRegistrationHandler.submitSuccessURL" value="processShowRegistrationNextPage.jhtml"> --> <table border="0" width="100%" cellpadding="0" cellspacing="0"> <tbody><tr> @@ -109,7 +109,7 @@ </tr> <tr> <td colspan="3"> </td> -</tr> +</tr> <tr> <td nowrap=""><div align="right">Title:</div></td> <td colspan="2"> @@ -200,7 +200,7 @@ <tbody><tr> <td >To secure your account, we require all customers to have a valid credit card on file. When it comes time to pay for your order, you will be able to choose to pay with a credit or debit card.<br><br></td> <td valign="top"> -<a href="javascript:vrsn_splash()" tabindex="-1"><img name="seal" border="true" src="https://seal.websecurity.norton.com/getseal?at=0&sealid=1&dn=www.peapod.com&lang=en" oncontextmenu="return false;" alt="Click to Verify - This site has chosen an SSL Certificate to improve Web site security"></a> +<a href="javascript:vrsn_splash()" tabindex="-1"><img name="seal" border="true" src="https://seal.websecurity.norton.com/getseal?at=0&sealid=1&dn=www.peapod.com&lang=en" oncontextmenu="return false;" alt="Click to Verify - This site has chosen an SSL Certificate to improve Web site security"></a> </td> </tr> </tbody></table> @@ -212,7 +212,7 @@ <tbody><tr> <td valign="top"><img src="https://www.peapod.com/c/QK/QKLIM.gif" border="0" bgcolor="white" name="verisign"></td> <td > </td> -<td >We use SSL encryption to protect your personal information, including your credit card information.<br></td> +<td >We use SSL encryption to protect your personal information, including your credit card information.<br></td> </tr> </tbody></table> </td> @@ -243,7 +243,7 @@ <td colspan="2"> <table border="0" cellpadding="0" cellspacing="0" bgcolor="white" width="100%"> <tbody><tr> -<td nowrap=""><input maxlength="16" autocomplete="off" name="cardNum" id="creditCardNumber" size="24" type="TEXT" value="" onfocus="return !showInfoBoxII('cardNumberHelp', event, 1 );"><input type="hidden" name="_D:cardNum" value=" "></td> +<td nowrap=""><input maxlength="16" name="cardNum" id="creditCardNumber" size="24" type="TEXT" value="" onfocus="return !showInfoBoxII('cardNumberHelp', event, 1 );"><input type="hidden" name="_D:cardNum" value=" "></td> <td> <a href="#" tabindex="-1" onclick="return !showInfoBoxII('cardNumberHelp', event);"><img src="https://www.peapod.com/c/C5/C5NC5.gif" width="21" height="21" border="0" alt="Help on entering your credit card number"></a> <input id="ccNum" type="HIDDEN" value="" name="/peapod/handler/iditarod/CheckoutRegistrationHandler.ccNum"><input type="hidden" name="_D:/peapod/handler/iditarod/CheckoutRegistrationHandler.ccNum" value=" "> <input id="cvv" type="HIDDEN" value="" name="/peapod/handler/iditarod/CheckoutRegistrationHandler.cvv"><input type="hidden" name="_D:/peapod/handler/iditarod/CheckoutRegistrationHandler.cvv" value=" "> @@ -261,14 +261,14 @@ </tr> <!-- card id number --> <tr> -<td align="RIGHT" nowrap="">Security Code:</td> +<td align="RIGHT" nowrap="">Security Code:</td> <td align="left"> <table cellspacing="0" cellpadding="0"> <tbody><tr> -<td align="left"><input maxlength="4" name="cid" id="creditCardCid" size="4" autocomplete="off" type="TEXT" value="" onfocus="return !showInfoBoxII('CardIdNumberHelp', event, 1 );"><input type="hidden" name="_D:cid" value=" "> <a href="#" tabindex="-1" class="popupLink" onclick="return !showInfoBoxII('CardIdNumberHelp', event);"><img src="https://www.peapod.com/c/C5/C5NC5.gif" title="Help on entering your Security Code" width="21" height="21" border="0"></a></td> +<td align="left"><input maxlength="4" name="cid" id="creditCardCid" size="4" type="TEXT" value="" onfocus="return !showInfoBoxII('CardIdNumberHelp', event, 1 );"><input type="hidden" name="_D:cid" value=" "> <a href="#" tabindex="-1" class="popupLink" onclick="return !showInfoBoxII('CardIdNumberHelp', event);"><img src="https://www.peapod.com/c/C5/C5NC5.gif" title="Help on entering your Security Code" width="21" height="21" border="0"></a></td> <!-- red arrow looks bad <img src="bean:Image.URL[11405]" border=0></td> --> </tr> -<!-- displayed at top +<!-- displayed at top <tr> <td align="left" > <droplet bean="Switch"> @@ -325,7 +325,7 @@ <td colspan="2"> <table border="0" cellpadding="0" cellspacing="0" bgcolor="white" width="100%"> <tbody><tr><td nowrap=""> -<input maxlength="20" autocomplete="off" name="cardName" size="20" type="TEXT" value="Shorty Nge" onfocus="return !showInfoBoxII('cardNameHelp', event, 1 );"><input type="hidden" name="_D:cardName" value=" "> +<input maxlength="20" name="cardName" size="20" type="TEXT" value="Shorty Nge" onfocus="return !showInfoBoxII('cardNameHelp', event, 1 );"><input type="hidden" name="_D:cardName" value=" "> </td> <!-- <valueof bean="CheckoutRegistrationHandler.billFirstName"></valueof> <valueof bean="CheckoutRegistrationHandler.billMiddleInitial"></valueof> <valueof bean="CheckoutRegistrationHandler.billLastName"></valueof></td> @@ -344,7 +344,7 @@ <td> </td> <td> </td> </tr> -</tbody></table> +</tbody></table> </td> <td width="15" valign="top"><img src="https://www.peapod.com/c/2Z/2ZAEE.gif" width="15" height="15"></td> <td valign="top">
diff --git a/components/test/data/autofill/heuristics/input/106_checkout_m_amazon.com.html b/components/test/data/autofill/heuristics/input/106_checkout_m_amazon.com.html index 50f8611f..e37d4987 100644 --- a/components/test/data/autofill/heuristics/input/106_checkout_m_amazon.com.html +++ b/components/test/data/autofill/heuristics/input/106_checkout_m_amazon.com.html
@@ -69,7 +69,7 @@ - <span class="a-dropdown-container"><select name="enterAddressCountryCode" autocomplete="off" data-a-native-class="enterAddressFormField" id="enterAddressCountryCode" class="a-native-dropdown enterAddressFormField"><option class="a-prompt" value="">Country: </option> + <span class="a-dropdown-container"><select name="enterAddressCountryCode" data-a-native-class="enterAddressFormField" id="enterAddressCountryCode" class="a-native-dropdown enterAddressFormField"><option class="a-prompt" value="">Country: </option> <option value="AF">Afghanistan</option> <option value="AX">Aland Islands</option> <option value="AL">Albania</option> @@ -330,7 +330,7 @@ - <span class="a-dropdown-container"><select name="AddressType" autocomplete="off" id="AddressType" class="a-native-dropdown a-spacing-base"> + <span class="a-dropdown-container"><select name="AddressType" id="AddressType" class="a-native-dropdown a-spacing-base"> <option value="OTH" selected="">Select your preference</option> <option value="RES">Yes, deliver on weekends</option> <option value="COM">No, don’t deliver on weekends</option> @@ -438,9 +438,9 @@ <div class="a-input-text-group a-spacing-base"> - <div data-account-name="" data-testid="" class="a-input-text-wrapper first-child"><input type="text" id="ccName" autocomplete="off" placeholder="Name on card" name="name"></div> + <div data-account-name="" data-testid="" class="a-input-text-wrapper first-child"><input type="text" id="ccName" placeholder="Name on card" name="name"></div> <span class="a-declarative" data-action="check-card-type" data-check-card-type="{"url":"/gp/buy/payselect/handlers/get-credit-card-type.html","type":"cc"}"> - <div data-testid="" class="a-input-text-wrapper last-child"><input type="tel" id="addCreditCardNumber" autocomplete="off" placeholder="Card number" name="addCreditCardNumber"></div> + <div data-testid="" class="a-input-text-wrapper last-child"><input type="tel" id="addCreditCardNumber" placeholder="Card number" name="addCreditCardNumber"></div> </span> </div> <div class="a-row a-spacing-small"> @@ -450,7 +450,7 @@ <div class="a-column a-span6 card-date"> -<span class="a-dropdown-container"><select name="month" autocomplete="off" id="ccMonth" class="a-native-dropdown"> +<span class="a-dropdown-container"><select name="month" id="ccMonth" class="a-native-dropdown"> <option value="1"> 01 </option> @@ -495,7 +495,7 @@ <div class="a-column a-span6 card-date a-span-last"> -<span class="a-dropdown-container"><select name="year" autocomplete="off" id="ccYear" class="a-native-dropdown"> +<span class="a-dropdown-container"><select name="year" id="ccYear" class="a-native-dropdown"> <option value="2014" selected=""> 2014 </option>
diff --git a/components/test/data/autofill/heuristics/input/107_checkout_m_apple.com.html b/components/test/data/autofill/heuristics/input/107_checkout_m_apple.com.html index 8c92dc6..d502a2a 100644 --- a/components/test/data/autofill/heuristics/input/107_checkout_m_apple.com.html +++ b/components/test/data/autofill/heuristics/input/107_checkout_m_apple.com.html
@@ -1,10 +1,10 @@ -<form id="payment-method-form" action="javascript:void(0);" class="step-mode edit clearfix payment-method-box" autocomplete="off" __parametersid="parameters_315"> +<form id="payment-method-form" action="javascript:void(0);" class="step-mode edit clearfix payment-method-box" __parametersid="parameters_315"> <div id="payment-form-nav" class="form-tab-nav"> <div id="coherent_id_767"> <ul class="clearfix" id="coherent_id_768"> <li class="first" id="coherent_id_769"> <button type="button" id="payment-credit-content-tab" class=" current"><span id="coherent_id_770">Debit/Credit Card</span></button> </li> <li id="coherent_id_771"> <button type="button" id="payment-giftcard-content-tab" class=""><span id="coherent_id_772">Apple Store Gift Card</span></button> </li> </ul> </div> </div> <div id="payment-form-horizontal-nav"> <div tabindex="-1" class="clearfix payment-mode" id="payment-credit-content"> <div class="gs grid-1of2" id="coherent_id_773"> <div id="payment-credit-user" class="substep user-form-block"> <div class="shipping-info-link" id="payment-credit-user-copy-from-shipping"> <button type="button" class="form-option text-action" id="payment-credit-user-copy-from-shipping-button"> <em id="coherent_id_774">Same as shipping <span class="a11y" id="coherent_id_775">(Billing Contact, Billing Address)</span> </em> </button> </div> <div id="payment-credit-user-address"> <fieldset class="US first user-form-fieldset" id="coherent_id_776"> <legend class="label" id="coherent_id_777">Billing Contact </legend> <div class="user-contact fieldset-content" id="payment-credit-user-address-contact_section"> <div class="mbs" id="coherent_id_778"> <span class="editing" id="payment-credit-user-address-nameLines-0-prf"></span> <span class="firstName-field field-with-placeholder" id="coherent_id_779"> <label for="payment-credit-user-address-firstName" class="placeholder" id="coherent_id_780"> <span id="coherent_id_781">First Name</span> </label><input name="payment-credit-user-address-firstName" type="text" size="10" maxlength="14" id="payment-credit-user-address-firstName" class="" aria-invalid="false"> </span> <span class="lastName-field field-with-placeholder" id="coherent_id_782"> <label for="payment-credit-user-address-lastName" class="placeholder" id="coherent_id_783"> <span id="coherent_id_784">Last Name</span> </label><input name="payment-credit-user-address-lastName" type="text" size="10" maxlength="20" id="payment-credit-user-address-lastName" class="" aria-invalid="false"> </span> </div> <div class="mbs" id="coherent_id_785"> <span class="editing" id="payment-credit-user-address-contactLines-0-prf"></span> <span class="daytimePhoneAreaCode-field field-with-placeholder" id="coherent_id_786"> <label for="payment-credit-user-address-daytimePhoneAreaCode" class="placeholder" id="coherent_id_787"> <span id="coherent_id_788">Area Code</span> </label><input name="payment-credit-user-address-daytimePhoneAreaCode" type="tel" size="3" maxlength="3" class="kp-tel" id="payment-credit-user-address-daytimePhoneAreaCode" aria-invalid="false"> </span> <span class="daytimePhone-field field-with-placeholder" id="coherent_id_789"> <label for="payment-credit-user-address-daytimePhone" class="placeholder" id="coherent_id_790"> <span id="coherent_id_791">Primary Phone</span> </label><input name="payment-credit-user-address-daytimePhone" type="tel" size="8" maxlength="8" class="kp-tel" id="payment-credit-user-address-daytimePhone" aria-invalid="false"> </span> </div> <div class="mbs" id="coherent_id_792"> <span class="editing" id="payment-credit-user-address-contactLines-1-prf"></span> <span class="eveningPhoneAreaCode-field field-with-placeholder" id="coherent_id_793"> <label for="payment-credit-user-address-eveningPhoneAreaCode" class="placeholder" id="coherent_id_794"> <span id="coherent_id_795">Area Code</span> </label><input name="payment-credit-user-address-eveningPhoneAreaCode" type="tel" size="3" maxlength="3" class="kp-tel" id="payment-credit-user-address-eveningPhoneAreaCode" aria-invalid="false"> </span> <span class="eveningPhone-field field-with-placeholder" id="coherent_id_796"> <label for="payment-credit-user-address-eveningPhone" class="placeholder" id="coherent_id_797"> <span id="coherent_id_798">Alternate Phone (optional)</span> </label><input name="payment-credit-user-address-eveningPhone" type="tel" size="8" maxlength="8" class="kp-tel" id="payment-credit-user-address-eveningPhone" aria-invalid="false"> </span> </div> <div class="mbs" id="coherent_id_799"> <span class="editing" id="payment-credit-user-address-contactLines-2-prf"></span> <span class="emailAddress-field field-with-placeholder" id="coherent_id_800"> <label for="payment-credit-user-address-emailAddress" class="placeholder" id="coherent_id_801"> <span id="coherent_id_802">Email Address</span> </label><input name="payment-credit-user-address-emailAddress" type="email" size="35" maxlength="50" class="kp-email" id="payment-credit-user-address-emailAddress" aria-invalid="false"> </span> </div> </div> </fieldset> <fieldset class="US user-form-fieldset" id="coherent_id_803"> <legend class="label" id="coherent_id_804">Billing Address </legend> <div class="user-address fieldset-content" id="payment-credit-user-address-address_section"> <div class="mbs" id="coherent_id_805"> <span class="editing" id="payment-credit-user-address-addressLines-0-prf"></span> <span class="companyName-field field-with-placeholder" id="coherent_id_806"> <label for="payment-credit-user-address-companyName" class="placeholder" id="coherent_id_807"> <span id="coherent_id_808">Company Name (optional)</span> </label><input name="payment-credit-user-address-companyName" type="text" size="35" maxlength="35" id="payment-credit-user-address-companyName" class="" aria-invalid="false"> </span> </div> <div class="mbs" id="coherent_id_809"> <span class="editing" id="payment-credit-user-address-addressLines-1-prf"></span> <span class="street-field field-with-placeholder" id="coherent_id_810"> <label for="payment-credit-user-address-street" class="placeholder" id="coherent_id_811"> <span id="coherent_id_812">Street Address</span> </label><input name="payment-credit-user-address-street" type="text" size="20" maxlength="30" id="payment-credit-user-address-street" class="" aria-invalid="false"> </span> </div> <div class="mbs" id="coherent_id_813"> <span class="editing" id="payment-credit-user-address-addressLines-2-prf"></span> <span class="street2-field field-with-placeholder" id="coherent_id_814"> <label for="payment-credit-user-address-street2" class="placeholder" id="coherent_id_815"> <span id="coherent_id_816">Apt. or Suite (optional)</span> </label><input name="payment-credit-user-address-street2" type="text" size="20" maxlength="30" id="payment-credit-user-address-street2" class="" aria-invalid="false"> </span> </div> <div class="mbs" id="coherent_id_817"> <span class="editing" id="payment-credit-user-address-addressLines-3-prf"></span> <p id="coherent_id_818"> </p><div class="clearfix" id="payment-credit-user-address-lookup"> <span class="city-state-fields prompt" id="coherent_id_819"> Enter ZIP for City and State </span> <span style="display: none;" class="city-state-fields fields" id="coherent_id_820"> <span class="city-field field-with-placeholder" id="coherent_id_821"> <label for="payment-credit-user-address-city" class="placeholder" id="coherent_id_822"> <span id="coherent_id_823">City</span> </label><input name="payment-credit-user-address-city" type="text" size="10" maxlength="30" id="payment-credit-user-address-city" class="" aria-invalid="false"> </span> <span class="state-field field-with-placeholder" id="coherent_id_824"> <label for="payment-credit-user-address-state" class="placeholder" id="coherent_id_825"> <span id="coherent_id_826">State</span> </label><input name="payment-credit-user-address-state" type="text" size="2" maxlength="2" id="payment-credit-user-address-state" class="" aria-invalid="false"> </span> </span> <span class="postalCode-field field-with-placeholder" id="coherent_id_827"> <label for="payment-credit-user-address-postalCode" class="placeholder" id="coherent_id_828"> <span id="coherent_id_829">ZIP Code</span> </label><input name="payment-credit-user-address-postalCode" type="text" size="5" maxlength="10" id="payment-credit-user-address-postalCode" class="" aria-invalid="false"> </span> <span style="display: none;" class="city-state-fields select" id="coherent_id_830"> <label for="payment-credit-user-address-lookup-options" class="a11y" id="coherent_id_831"> City / State: </label> <select id="payment-credit-user-address-lookup-options"></select> </span> </div> <p id="coherent_id_832"></p> </div> <div class="optional-multicol" id="coherent_id_833"> <span class="country-field field-with-placeholder first" id="coherent_id_834"><span id="payment-credit-user-address-country"></span></span> </div> </div> </fieldset> </div> </div> <div id="payment-credit-extended-fields" class="extended-fields"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_835"> <div id="payment-credit-method" class="substep user-form-block"> <fieldset id="coherent_id_836"> <legend class="a11y" id="coherent_id_837">Payment Method</legend> <div tabindex="-1" role="group" id="payment-credit-method-cc0"> <fieldset class="US first" id="coherent_id_838"> <legend class="a11y" id="coherent_id_839">First Card</legend> <p class="paymethod" id="coherent_id_840">Payment Method</p> <div class="payment-method-form" id="coherent_id_841"> <ul class="card-types detector mbl" id="payment-credit-method-cc0-type"> <li class="VISA first card" id="coherent_id_842"> <span id="coherent_id_843">Visa</span> </li> <li class="MASTERCARD card" id="coherent_id_844"> <span id="coherent_id_845">Mastercard</span> </li> <li class="AMERICAN_EXPRESS card" id="coherent_id_846"> <span id="coherent_id_847">American Express</span> </li> <li class="DISCOVER last card" id="coherent_id_848"> <span id="coherent_id_849">Discover</span> </li> </ul> <div class="mbm" id="coherent_id_850"> <span class="cardNumber-field field-with-placeholder" id="coherent_id_851"> <label for="payment-credit-method-cc0-cardNumber" class="placeholder" id="coherent_id_852"> <span id="coherent_id_853">Card Number</span> </label><input type="text" class="kp-num" id="payment-credit-method-cc0-cardNumber" maxlength="16" aria-invalid="false"> </span> <div class="security-code" id="coherent_id_854"> <span class="securityCode-field field-with-placeholder" id="payment-credit-method-cc0-payment-security-code"> <label for="payment-credit-method-cc0-security-code" class="placeholder" id="coherent_id_855"> <span id="coherent_id_856">Card code</span> </label><input type="text" class="kp-num" id="payment-credit-method-cc0-security-code" maxlength="4" aria-invalid="false" name="null"> <span rel="security-code-help" class="whats-this right top" id="coherent_id_642"> <a href="#" tabindex="0" class="toggle tooltip-toggle" aria-describedby="coherent_id_643" id="coherent_id_857">What's This?</a> <span class=" hide ovl" id="coherent_id_643" aria-hidden="true" role="tooltip"> <h4 id="coherent_id_858">Where to find your Security Code</h4> <h5 class="cvv_card visa" id="coherent_id_859">Visa/Mastercard/Discover</h5> <span class="a11y" id="coherent_id_860">For American Express cards, the security code is the last 4 digits on the front of the card. It is separate from the actual credit card number.</span> <h5 class="cvv_card amex" id="coherent_id_861">American Express</h5> <span class="a11y" id="coherent_id_862">For Visa, Mastercard, or Discover cards, the security code can be found on the back of the card. It is the last 3 digits, typically found to the right of the signature strip.</span> </span> </span> </span> </div> <br id="coherent_id_863"> </div> <div class="optional-multicol clearfix mbm" id="payment-credit-method-cc0-payment-expiry-fields"> <span class="first" id="coherent_id_864"> <span class="label" id="coherent_id_865"> Expires </span> <span class="expirationMonth-field" id="coherent_id_866"> <label for="payment-credit-method-cc0-expirationMonth" class="a11y" id="coherent_id_867">Credit card expiration month</label> <select id="payment-credit-method-cc0-expirationMonth" name="payment-credit-method-cc0-expirationMonth" class=""><option value="WONoSelectionString" id="coherent_id_644" class="first">Month</option> <option value="01" id="coherent_id_645" class="">01</option> <option value="02" id="coherent_id_646" class="">02</option> <option value="03" id="coherent_id_647" class="">03</option> <option value="04" id="coherent_id_648" class="">04</option> <option value="05" id="coherent_id_649" class="">05</option> <option value="06" id="coherent_id_650" class="">06</option> <option value="07" id="coherent_id_651" class="">07</option> <option value="08" id="coherent_id_652" class="">08</option> <option value="09" id="coherent_id_653" class="">09</option> <option value="10" id="coherent_id_654" class="">10</option> <option value="11" id="coherent_id_655" class="">11</option> <option value="12" id="coherent_id_656" class="last">12</option></select> </span> <span class="expirationYear-field" id="coherent_id_868"> <label for="payment-credit-method-cc0-expirationYear" class="a11y" id="coherent_id_869">Credit card expiration year</label> <select id="payment-credit-method-cc0-expirationYear" name="payment-credit-method-cc0-expirationYear" class=""><option value="WONoSelectionString" id="coherent_id_657" class="first">Year</option> <option value="2014" id="coherent_id_658" class="">2014</option> <option value="2015" id="coherent_id_659" class="">2015</option> <option value="2016" id="coherent_id_660" class="">2016</option> <option value="2017" id="coherent_id_661" class="">2017</option> <option value="2018" id="coherent_id_662" class="">2018</option> <option value="2019" id="coherent_id_663" class="">2019</option> <option value="2020" id="coherent_id_664" class="">2020</option> <option value="2021" id="coherent_id_665" class="">2021</option> <option value="2022" id="coherent_id_666" class="">2022</option> <option value="2023" id="coherent_id_667" class="">2023</option> <option value="2024" id="coherent_id_668" class="">2024</option> <option value="2025" id="coherent_id_669" class="">2025</option> <option value="2026" id="coherent_id_670" class="">2026</option> <option value="2027" id="coherent_id_671" class="">2027</option> <option value="2028" id="coherent_id_672" class="">2028</option> <option value="2029" id="coherent_id_673" class="">2029</option> <option value="2030" id="coherent_id_674" class="">2030</option> <option value="2031" id="coherent_id_675" class="">2031</option> <option value="2032" id="coherent_id_676" class="">2032</option> <option value="2033" id="coherent_id_677" class="">2033</option> <option value="2034" id="coherent_id_678" class="last">2034</option></select> </span> </span> </div> <div id="payment-credit-method-cc0-installments"></div> </div> </fieldset> </div> </fieldset> <p class="text-actions" id="coherent_id_870"> <span id="coherent_id_871"><button type="button" class="text-action" id="payment-credit-add-cc"><em id="coherent_id_872">Pay with two debit / credit cards</em></button></span> </p> </div> <div class="substep promo-banner-align" id="coherent_id_873"> <div id="payment-form-astro" class="form-astro"> <div class="promo-banner" id="coherent_id_874"> <a id="financing-promo-payment" href="#payment-form-astro"> <img class="ir" src="https://store.storeimages.cdn-apple.com/4146/as-images.apple.com/is/image/AppleInc/aos/published/images/h/ol/holiday2012/checkout/holiday2012-checkout-financing-offers?wid=672&hei=174&fmt=jpeg&qlt=80&op_sharpen=0&resMode=bicub&op_usm=0.5,0.5,0,0&iccEmbed=0&layer=comp&.v=1400775019109" alt="Financing offers. 6,12, and 18 month options available" width="336" height="87" data-scale-params-1="wid=336&hei=87&fmt=jpeg&qlt=95&op_sharpen=0&resMode=bicub&op_usm=0.5,0.5,0,0&iccEmbed=0&layer=comp&.v=1400775019109" id="coherent_id_875"> </a> </div> </div> </div> </div> </div> <div id="payment-educationloan-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div id="payment-educationloan-errors" class="payment-loan-errors"></div> <div class="gs grid-1of2" id="coherent_id_876"> <div id="payment-educationloan-loanfields" style="border-right: 1px solid #D5D5D5" class="user-form-block substep"></div> <div id="payment-educationloan-user" style="border-right: 1px solid #D5D5D5" class="user-form-block substep"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_877"> <div id="payment-educationloan-method" class="substep payment-method"></div> <div class="substep" id="coherent_id_878"> </div> </div> <div id="payment-educationloan-extended-fields" class="extended-fields"></div> </div> <div id="payment-giftcard-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div id="payment-giftcard-errors"></div> <div class="gs grid-1of2" id="coherent_id_879"> <div id="payment-giftcard-user" class="user-form-block substep"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_880"> <div id="payment-giftcard-method" class="substep payment-method"></div> <div class="substep" id="coherent_id_881"> </div> </div> <div id="payment-giftcard-extended-fields" class="extended-fields"></div> </div> <div id="payment-financing-content" style="display: none;" tabindex="-1" class="user-form-block clearfix payment-mode"></div> <div id="payment-bml-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div id="payment-bml-errors"></div> <div class="gs grid-1of2" id="coherent_id_882"> <div id="payment-bml-user" class="user-form-block substep"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_883"> <div id="payment-bml-method" class="substep"></div> </div> <div id="payment-bml-extended-fields" class="extended-fields"></div> </div> <div id="payment-paypal-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div id="payment-paypal-errors"></div> <div class="gs grid-1of2" id="coherent_id_884"> <div id="payment-paypal-user" class="user-form-block substep"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_885"> <div id="payment-paypal-method" class="substep"></div> </div> <div id="payment-paypal-extended-fields" class="extended-fields"></div> </div> <div id="payment-ideal-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div id="payment-ideal-errors"></div> <div class="gs grid-1of2" id="coherent_id_886"> <div id="payment-ideal-user" class="user-form-block substep"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_887"> <div id="payment-ideal-method" class="substep"></div> </div> <div id="payment-ideal-extended-fields" class="extended-fields"></div> </div> <div id="payment-wire-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div id="payment-wire-errors"></div> <div class="gs grid-1of2" id="coherent_id_888"> <div id="payment-wire-user" class="user-form-block substep"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_889"> <div id="payment-wire-method" class="substep"></div> </div> <div id="payment-wire-extended-fields" class="extended-fields"></div> </div> <div id="payment-cheque-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div id="payment-cheque-errors"></div> <div class="gs grid-1of2" id="coherent_id_890"> <div id="payment-cheque-user" class="user-form-block substep"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_891"> <div id="payment-cheque-method" class="substep"></div> </div> <div class="payment-cheque-extended-fields" id="coherent_id_892"></div> </div> <div id="payment-lease-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div id="payment-lease-errors"></div> <div class="gs grid-1of2" id="coherent_id_893"> <div id="payment-lease-user" class="user-form-block substep"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_894"> <div id="payment-lease-method" class="substep"></div> </div> <div id="payment-lease-extended-fields" class="extended-fields"></div> </div> <div id="payment-loan-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div id="payment-loan-errors" class="payment-loan-errors"></div> <div class="gs grid-1of2" id="coherent_id_895"> <div id="payment-loan-user" class="user-form-block substep"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_896"> <div id="payment-loan-method" class="substep"></div> </div> <div id="payment-loan-extended-fields" class="extended-fields"></div> </div> <div id="payment-cashcheck-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div id="payment-cashcheck-errors"></div> <div class="gs grid-1of2" id="coherent_id_897"> <div id="payment-cashcheck-user" class="substep user-form-block"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_898"> <div id="payment-cashcheck-method" class="substep"></div> </div> <div id="payment-cashcheck-extended-fields" class="extended-fields"></div> </div> <div id="payment-socexternal-content" style="display: none;" tabindex="-1" class="celarfix payment-mode"> <div id="payment-socexternal-errors"></div> <div class="gs grid-1of2" id="coherent_id_899"> <div id="payment-socexternal-user" class="substep user-form-block"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_900"> <div id="payment-socexternal-method" class="substep"></div> </div> <div id="payment-socexternal-extended-fields" class="extended-fields"></div> </div> <div id="payment-socinternal-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div id="payment-socinternal-errors"></div> <div class="gs grid-1of2" id="coherent_id_901"> <div id="payment-socinternal-user" class="substep user-form-block"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_902"> <div id="payment-socinternal-method" class="substep"></div> </div> <div id="payment-socinternal-extended-fields" class="extended-fields"></div> </div> <div id="payment-boleto-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div class="gs grid-1of2" id="coherent_id_903"> <div id="payment-boleto-user" class="substep user-form-block"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_904"> <div id="payment-boleto-method" class="substep"></div> </div> <div id="payment-boleto-extended-fields" class="extended-fields"></div> </div> <div id="payment-atm-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div id="payment-atm-errors"></div> <div class="gs grid-1of2" id="coherent_id_905"> <div id="payment-atm-user" class="substep user-form-block"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_906"> <div id="payment-atm-method" class="substep"></div> </div> <div id="payment-atm-extended-fields" class="extended-fields"></div> </div> <div id="payment-counterservice-content" style="display: none;" tabindex="-1" class="clearfix payment-mode"> <div id="payment-counterservice-errors"></div> <div class="gs grid-1of2" id="coherent_id_907"> <div id="payment-counterservice-user" class="substep user-form-block"></div> </div> <div class="gs grid-1of2 gs-last" id="coherent_id_908"> <div id="payment-counterservice-method" class="substep"></div> </div> <div id="payment-counterservice-extended-fields" class="extended-fields"></div> </div> <div id="payment-step-defaults" class="ptm"> </div> </div> <div id="payment-form-options" class="payment-form-options"></div> - + <div id="payment-form-vertical-nav" class="payment-form-options"></div> - + </form>
diff --git a/components/test/data/autofill/heuristics/input/110_checkout_harryanddavid.com.html b/components/test/data/autofill/heuristics/input/110_checkout_harryanddavid.com.html index a5efb99..e45aa56 100644 --- a/components/test/data/autofill/heuristics/input/110_checkout_harryanddavid.com.html +++ b/components/test/data/autofill/heuristics/input/110_checkout_harryanddavid.com.html
@@ -1,73 +1,73 @@ <form id="editAddressForm_45381448" name="editAddressForm" > <input type="hidden" name="idx" value="45381448"> - + <input type="hidden" name="orderItemId" value="45381448"> - + <input type="hidden" name="countryOptIn" id="countryOptIn2" value="US"> - + <input type="hidden" name="orderId" value="14146734"> - + <div id="addressSection1_45381448" > <div > - + <div > <div ></div> <div > - <input type="checkbox" id="chkBusinessAddress_45381448" name="typeOfAddress" value="H" onclick="addressHelper.addressTypeSelected('45381448');"><label for="chkBusinessAddress_45381448">Business address</label> + <input type="checkbox" id="chkBusinessAddress_45381448" name="typeOfAddress" value="H" onclick="addressHelper.addressTypeSelected('45381448');"><label for="chkBusinessAddress_45381448">Business address</label> </div> </div> <div >Required field <span >*</span></div> </div> - + <div > - + <div id="title_45381448" > - + <div > <div >Title</div> <div > - <select id="personTitle_45381448" name="personTitle" dojoattachpoint="focusNode,valueNode,textbox,comboNode,containerNode" dojoattachevent="onchange: _selectOption" autocomplete="off" tabindex="0" widgetid="personTitle_45381448"><option value="" id="personTitle_45381448ph" >- Select Title -</option> - + <select id="personTitle_45381448" name="personTitle" dojoattachpoint="focusNode,valueNode,textbox,comboNode,containerNode" dojoattachevent="onchange: _selectOption" tabindex="0" widgetid="personTitle_45381448"><option value="" id="personTitle_45381448ph" >- Select Title -</option> + <option value="MR/MRS">MR/MRS</option> - + <option value="MR/MS">MR/MS</option> - + <option value="MRS">MRS</option> - + <option value="MR">MR</option> - + <option value="DR">DR</option> - + <option value="MS">MS</option> - + <option value="DR/MR">DR/MR</option> - + <option value="DR/MRS">DR/MRS</option> - + <option value="MISS">MISS</option> - + </select> </div> </div> - + </div> - - - <div dojotype="dojo.data.ItemFileReadStore" id="relationStore_45381448" jsid="relationStore_45381448" clearonclose="true" url="/gifts/store/BECAjaxIncludeView?storeId=10455&includePage=Snippets/LookupDataJSON.jsp&lookupIdentifier=lookup-relationship"></div> - - + + + <div dojotype="dojo.data.ItemFileReadStore" id="relationStore_45381448" jsid="relationStore_45381448" clearonclose="true" url="/gifts/store/BECAjaxIncludeView?storeId=10455&includePage=Snippets/LookupDataJSON.jsp&lookupIdentifier=lookup-relationship"></div> + + <div > <div >Relationship</div> <div > - <select id="recipientRelation_45381448" name="recipientRelation" dojoattachpoint="focusNode,valueNode,textbox,comboNode,containerNode" dojoattachevent="onchange: _selectOption" autocomplete="off" tabindex="0" widgetid="recipientRelation_45381448"><option value="0" id="recipientRelation_45381448ph" >- Select Relationship -</option><option value="MOM">Mom</option><option value="DAD">Dad</option><option value="SIS">Sister</option><option value="BRO">Brother</option><option value="HUS">Husband</option><option value="WIF">Wife</option><option value="GPT">Grandparent</option><option value="DAU">Daughter</option><option value="SON">Son</option><option value="ORE">Other Relative</option><option value="SEL">Myself</option><option value="FND">Friend</option><option value="BFD">Boyfriend</option><option value="GFD">Girlfriend</option><option value="CWK">Co-worker</option><option value="CLI">Client</option><option value="PTR">Partner</option><option value="OTR">Other</option></select> + <select id="recipientRelation_45381448" name="recipientRelation" dojoattachpoint="focusNode,valueNode,textbox,comboNode,containerNode" dojoattachevent="onchange: _selectOption" tabindex="0" widgetid="recipientRelation_45381448"><option value="0" id="recipientRelation_45381448ph" >- Select Relationship -</option><option value="MOM">Mom</option><option value="DAD">Dad</option><option value="SIS">Sister</option><option value="BRO">Brother</option><option value="HUS">Husband</option><option value="WIF">Wife</option><option value="GPT">Grandparent</option><option value="DAU">Daughter</option><option value="SON">Son</option><option value="ORE">Other Relative</option><option value="SEL">Myself</option><option value="FND">Friend</option><option value="BFD">Boyfriend</option><option value="GFD">Girlfriend</option><option value="CWK">Co-worker</option><option value="CLI">Client</option><option value="PTR">Partner</option><option value="OTR">Other</option></select> </div> </div> - </div> - + </div> + <div id="businessAddressArea_45381448" > - + <div > <div >Company name<span >*</span></div> <div > @@ -85,9 +85,9 @@ <input type="hidden" name="organizationNameSave" value=""> <input type="hidden" name="businessTitleSave" value=""> </div> - + <div id="homeAddressArea_45381448" > - + <div > <div >First Name<span >*</span></div> <div > @@ -104,8 +104,8 @@ <input type="hidden" name="firstNameSave" value=""> <input type="hidden" name="lastNameSave" value=""> - - + + <div > <div >Additional info</div> <div > @@ -114,11 +114,11 @@ </div> </div> - + <div ></div> - - <div > - + + <div > + <div > <div >Street address<span >*</span></div> <div > @@ -134,13 +134,13 @@ </div> </div> - - <div > - + + <div > + <div > <div >Country<span >*</span></div> <div > - <select id="country_45381448" name="country" dojoattachpoint="focusNode,valueNode,textbox,comboNode,containerNode" dojoattachevent="onchange: _selectOption" autocomplete="off" tabindex="0" required="" widgetid="country_45381448"><option value="US">United States</option><option value="CA">Canada</option><option value="AG">Antigua and Barbuda</option><option value="AW">Aruba</option><option value="AU">Australia</option><option value="AT">Austria</option><option value="BS">Bahamas</option><option value="BB">Barbados</option><option value="BE">Belgium</option><option value="BZ">Belize</option><option value="BM">Bermuda</option><option value="BT">Bhutan</option><option value="BN">Brunei</option><option value="CK">Cook Islands</option><option value="CR">Costa Rica</option><option value="CZ">Czech Republic</option><option value="FJ">Fiji</option><option value="FI">Finland</option><option value="FR">France</option><option value="DE">Germany</option><option value="GI">Gibraltar</option><option value="VA">Holy See</option><option value="HK">Hong Kong S.A.R. of China</option><option value="HU">Hungary</option><option value="JP">Japan</option><option value="JO">Jordan</option><option value="KR">Korea, South</option><option value="KW">Kuwait</option><option value="LI">Liechtenstein</option><option value="LT">Lithuania</option><option value="LU">Luxembourg</option><option value="MO">Macau S.A.R. of China</option><option value="MV">Maldives</option><option value="MR">Mauritania</option><option value="MU">Mauritius</option><option value="MD">Moldova</option><option value="NL">Netherlands</option><option value="NZ">New Zealand</option><option value="NO">Norway</option><option value="OM">Oman</option><option value="PA">Panama</option><option value="PY">Paraguay</option><option value="PL">Poland</option><option value="QA">Qatar</option><option value="RO">Romania</option><option value="SM">San Marino</option><option value="SC">Seychelles</option><option value="SG">Singapore</option><option value="SI">Slovenia</option><option value="ZA">South Africa</option><option value="SE">Sweden</option><option value="CH">Switzerland</option><option value="TW">Taiwan</option><option value="TH">Thailand</option><option value="TR">Turkey</option><option value="AE">United Arab Emirates</option><option value="GB">United Kingdom</option><option value="VE">Venezuela</option></select> + <select id="country_45381448" name="country" dojoattachpoint="focusNode,valueNode,textbox,comboNode,containerNode" dojoattachevent="onchange: _selectOption" tabindex="0" required="" widgetid="country_45381448"><option value="US">United States</option><option value="CA">Canada</option><option value="AG">Antigua and Barbuda</option><option value="AW">Aruba</option><option value="AU">Australia</option><option value="AT">Austria</option><option value="BS">Bahamas</option><option value="BB">Barbados</option><option value="BE">Belgium</option><option value="BZ">Belize</option><option value="BM">Bermuda</option><option value="BT">Bhutan</option><option value="BN">Brunei</option><option value="CK">Cook Islands</option><option value="CR">Costa Rica</option><option value="CZ">Czech Republic</option><option value="FJ">Fiji</option><option value="FI">Finland</option><option value="FR">France</option><option value="DE">Germany</option><option value="GI">Gibraltar</option><option value="VA">Holy See</option><option value="HK">Hong Kong S.A.R. of China</option><option value="HU">Hungary</option><option value="JP">Japan</option><option value="JO">Jordan</option><option value="KR">Korea, South</option><option value="KW">Kuwait</option><option value="LI">Liechtenstein</option><option value="LT">Lithuania</option><option value="LU">Luxembourg</option><option value="MO">Macau S.A.R. of China</option><option value="MV">Maldives</option><option value="MR">Mauritania</option><option value="MU">Mauritius</option><option value="MD">Moldova</option><option value="NL">Netherlands</option><option value="NZ">New Zealand</option><option value="NO">Norway</option><option value="OM">Oman</option><option value="PA">Panama</option><option value="PY">Paraguay</option><option value="PL">Poland</option><option value="QA">Qatar</option><option value="RO">Romania</option><option value="SM">San Marino</option><option value="SC">Seychelles</option><option value="SG">Singapore</option><option value="SI">Slovenia</option><option value="ZA">South Africa</option><option value="SE">Sweden</option><option value="CH">Switzerland</option><option value="TW">Taiwan</option><option value="TH">Thailand</option><option value="TR">Turkey</option><option value="AE">United Arab Emirates</option><option value="GB">United Kingdom</option><option value="VE">Venezuela</option></select> </div> </div> @@ -150,13 +150,13 @@ <div id="widget_city_45381448" role="presentation" widgetid="city_45381448"><div ><input value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div ><input data-dojo-attach-point="textbox,focusNode" autocomplete="on" name="city" type="text" tabindex="0" id="city_45381448" maxlength="40" size="35" aria-invalid="true" aria-required="true" value=""></div></div> </div> </div> - + <div id="stateZipSection_45381448" > - + <div > <div >State<span >*</span></div> <div > - <select id="state_45381448" name="state" dojoattachpoint="focusNode,valueNode,textbox,comboNode,containerNode" dojoattachevent="onchange: _selectOption" autocomplete="off" tabindex="0" required="" widgetid="state_45381448"><option value="" id="state_45381448ph" disabled="" >- Select a State -</option> + <select id="state_45381448" name="state" dojoattachpoint="focusNode,valueNode,textbox,comboNode,containerNode" dojoattachevent="onchange: _selectOption" tabindex="0" required="" widgetid="state_45381448"><option value="" id="state_45381448ph" disabled="" >- Select a State -</option> <option value="AL">Alabama</option><option value="AK">Alaska</option><option value="AS">American Samoa</option><option value="AZ">Arizona</option><option value="AR">Arkansas</option><option value="AA">Armed Forces Americas (AA)</option><option value="AE">Armed Forces Europe (AE)</option><option value="AP">Armed Forces Pacific (AP)</option><option value="CA">California</option><option value="CO">Colorado</option><option value="CT">Connecticut</option><option value="DE">Delaware</option><option value="DC">District of Columbia</option><option value="FM">Federated States of Micronesia</option><option value="FL">Florida</option><option value="GA">Georgia</option><option value="GU">Guam</option><option value="HI">Hawaii</option><option value="ID">Idaho</option><option value="IL">Illinois</option><option value="IN">Indiana</option><option value="IA">Iowa</option><option value="KS">Kansas</option><option value="KY">Kentucky</option><option value="LA">Louisiana</option><option value="ME">Maine</option><option value="MH">Marshall Islands</option><option value="MD">Maryland</option><option value="MA">Massachusetts</option><option value="MI">Michigan</option><option value="MN">Minnesota</option><option value="MS">Mississippi</option><option value="MO">Missouri</option><option value="MT">Montana</option><option value="NE">Nebraska</option><option value="NV">Nevada</option><option value="NH">New Hampshire</option><option value="NJ">New Jersey</option><option value="NM">New Mexico</option><option value="NY">New York</option><option value="NC">North Carolina</option><option value="ND">North Dakota</option><option value="MP">Northern Mariana Islands</option><option value="OH">Ohio</option><option value="OK">Oklahoma</option><option value="OR">Oregon</option><option value="PW">Palau</option><option value="PA">Pennsylvania</option><option value="PR">Puerto Rico</option><option value="RI">Rhode Island</option><option value="SC">South Carolina</option><option value="SD">South Dakota</option><option value="TN">Tennessee</option><option value="TX">Texas</option><option value="VI">U.S. Virgin Islands</option><option value="UT">Utah</option><option value="VT">Vermont</option><option value="VA">Virginia</option><option value="WA">Washington</option><option value="WV">West Virginia</option><option value="WI">Wisconsin</option><option value="WY">Wyoming</option></select> </div> </div> @@ -170,12 +170,12 @@ </div> </div> - - <div > - - + + <div > + + <div > - + <div > <div >Phone number</div> <div > @@ -184,7 +184,7 @@ </div> <div id="phoneExtArea_45381448" > - + <div > <div >Ext</div> <div > @@ -193,39 +193,39 @@ </div> </div> - + <div > <div ></div> <div >Recommended for PO Box and wine deliveries</div> </div> - </div> + </div> </div> - - <div > - + + <div > + <div > <div ></div> <div > <input type="checkbox" id="rbCellPhoneYes" name="phone1Type" value="C"><label for="rbCellPhoneYes">Cell phone</label> </div> </div> - + </div> - - + + </div> - - + + <div > <div id="emailArea_45381448" > - + <div id="emailAreaMsg_45381448" > <div >Required field <span >*</span></div> <div > <span >To save your billing address,</span> please provide an email address where we can contact you with order updates and information. </div> </div> - + <div > <div >Email address<span >*</span></div> <div > @@ -236,37 +236,37 @@ <div > <div >Confirm email address<span >*</span></div> <div > - - <div id="widget_logonId_45381448" role="presentation" widgetid="logonId_45381448"><div ><input value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div ><input data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="logonId" type="text" tabindex="0" id="logonId_45381448" aria-required="true" aria-invalid="true" maxlength="100" size="35" value=""></div></div> + + <div id="widget_logonId_45381448" role="presentation" widgetid="logonId_45381448"><div ><input value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div ><input data-dojo-attach-point="textbox,focusNode" name="logonId" type="text" tabindex="0" id="logonId_45381448" aria-required="true" aria-invalid="true" maxlength="100" size="35" value=""></div></div> </div> </div> </div> </div> - - + + <div id="addressSection2_45381448" > - - - </div> + + + </div> </form> <form id="orderPaymentForm" name="orderPaymentForm" method="post"> <input type="hidden" name="langId" value="-1"> - <input type="hidden" name="orderId" value="14146734"> - <input type="hidden" name="notifyOrderSubmitted" value="0"> + <input type="hidden" name="orderId" value="14146734"> + <input type="hidden" name="notifyOrderSubmitted" value="0"> <input type="hidden" id="billtoAddressId" name="billtoAddressId" value=""> <input type="hidden" name="hiddenPromoCode" value="" id="hiddenPromoCode"> <input type="hidden" name="hiddenCoupon" value="" id="hiddenCoupon"> <input type="hidden" name="previousOptIn" id="previousOptIn" value="yes"> <input type="hidden" name="hiddenOptIn" id="hiddenOptIn2" value="yes"> <input type="hidden" name="countryOptIn" id="countryOptIn2" value="US"> - -<a name="anchor_payment"></a> + +<a name="anchor_payment"></a> <div dojotype="bec.order.payment.PaymentMethod" id="paymentMethod" jsid="paymentMethod" paypalpreauth="false" paypaltabletremove="false" expresscheckout="false" errormessage="Payment information is missing or invalid." orderid="14146734" widgetid="paymentMethod"> <input type="hidden" name="policyId" value="" dojoattachpoint="policyId"> - <input type="hidden" name="payMethodId" value="" dojoattachpoint="payMethodId"> + <input type="hidden" name="payMethodId" value="" dojoattachpoint="payMethodId"> <input type="hidden" name="isPIAddNeeded" value="N"> <input type="hidden" name="valueFromProfileOrder" value="Y"> <input type="hidden" name="account" id="account"> @@ -274,13 +274,13 @@ <input type="hidden" name="remainingAmount" value="0.00"> <input type="hidden" name="DoExpressCheckout_ErrorCode" value=""> <input type="hidden" name="DoAuthorization_ErrorCode" value=""> - <input type="hidden" name="tabletDomain" value=""> - + <input type="hidden" name="tabletDomain" value=""> + <div id="paymentMethodSection" dojoattachpoint="paymentMethodSection"> - - <div dojotype="bec.data.ItemFileReadStore" id="paymentMethodStore" jsid="paymentMethodStore" clearonclose="true" url="/gifts/store/BECAjaxIncludeView?storeId=10455&includePage=ShoppingArea/CheckoutSection/Billing/PaymentMethods/AvailablePaymentMethodsJSON.jsp&orderId=14146734"></div> - - + + <div dojotype="bec.data.ItemFileReadStore" id="paymentMethodStore" jsid="paymentMethodStore" clearonclose="true" url="/gifts/store/BECAjaxIncludeView?storeId=10455&includePage=ShoppingArea/CheckoutSection/Billing/PaymentMethods/AvailablePaymentMethodsJSON.jsp&orderId=14146734"></div> + + <div dojotype="dijit.layout.ContentPane" id="payment2Section" dojoattachpoint="payment2Section" title="" role="group" widgetid="payment2Section"><!-- BEGIN: GiftCard.jsp --> <input type="hidden" name="gc_expire_month" value="12"> <input type="hidden" name="gc_expire_year" value="2014"> @@ -289,35 +289,35 @@ <div id="giftCardSection" dojoattachpoint="giftCardSection" > <div > <span >Redeem a Gift Card</span> - </div> + </div> <div > If your order exceeds your Gift Card balance, please enter additional payment information. - </div> + </div> <div > <div >Gift Card Number</div> - <div dojoattachpoint="_wrapper" widgetid="gcAccount"><div id="widget_gcAccount" role="presentation"><div ><input value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div ><input data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="GiftCardNumber" type="text" tabindex="0" id="gcAccount" size="22" maxlength="20" aria-invalid="true" value=""></div></div> + <div dojoattachpoint="_wrapper" widgetid="gcAccount"><div id="widget_gcAccount" role="presentation"><div ><input value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div ><input data-dojo-attach-point="textbox,focusNode" name="GiftCardNumber" type="text" tabindex="0" id="gcAccount" size="22" maxlength="20" aria-invalid="true" value=""></div></div> <input type="hidden" name="GiftCardBrand" id="GiftCardBrand" value="" dojoattachpoint="_cardType"></div> </div> - + <div > <div >PIN*</div> - <div id="widget_gcPin" role="presentation" widgetid="gcPin"><div ><input value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div ><input data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="GiftCardPin" type="text" tabindex="0" id="gcPin" size="6" maxlength="4" aria-invalid="true" aria-required="true" value=""></div></div> + <div id="widget_gcPin" role="presentation" widgetid="gcPin"><div ><input value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div ><input data-dojo-attach-point="textbox,focusNode" name="GiftCardPin" type="text" tabindex="0" id="gcPin" size="6" maxlength="4" aria-invalid="true" aria-required="true" value=""></div></div> </div> - + <div > <a href="#checkGiftCardBalance" onclick="return false;" dojoattachevent="onclick: showGiftCardBalancePopup"> Check Gift Card Balance - </a> - </div> - + </a> + </div> + <div >*scratch off the covered section on the card back or for an eGift card, refer to your email.</div> </div> </div> - - + + <div >Payment Method:</div> - - + + <div dojotype="dijit.layout.ContentPane" id="payment3Section" dojoattachpoint="payment3Section" title="" role="group" widgetid="payment3Section"><!-- BEGIN: PayPal.jsp --> <div id="paypal-section" > @@ -335,11 +335,11 @@ <div id="payment1Section" > <div dojotype="dijit.layout.ContentPane" id="paymentInput" dojoattachpoint="paymentInput" title="" role="group" widgetid="paymentInput"><!-- BEGIN: CreditCard.jsp --> <div > - + <div > <div role="presentation" widgetid="paymentType-CC"><input name="paymentType" type="radio" data-dojo-attach-point="focusNode" data-dojo-attach-event="onclick:_onClick" value="on" tabindex="0" id="paymentType-CC" aria-checked="true"></div> </div> - + <div > <label for="paymentType-CC" ><div id="cardTypeImg" ></div></label> </div> @@ -347,22 +347,22 @@ <div id="paymentCreditCard" dojoattachpoint="paymentCreditCard" > <div > <div >Card Number</div> - <div dojoattachpoint="_wrapper" widgetid="clearTextAccount"><div id="widget_clearTextAccount" role="presentation"><div ><input value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div ><input data-dojo-attach-point="textbox,focusNode" autocomplete="off" type="text" tabindex="0" id="clearTextAccount" size="23" maxlength="30" aria-required="false" aria-invalid="true" value=""></div></div> -<input type="hidden" name="cc_brand" id="cc_brand" value="" dojoattachpoint="_cardType"></div> - + <div dojoattachpoint="_wrapper" widgetid="clearTextAccount"><div id="widget_clearTextAccount" role="presentation"><div ><input value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div ><input data-dojo-attach-point="textbox,focusNode" type="text" tabindex="0" id="clearTextAccount" size="23" maxlength="30" aria-required="false" aria-invalid="true" value=""></div></div> +<input type="hidden" name="cc_brand" id="cc_brand" value="" dojoattachpoint="_cardType"></div> + </div> <div > <div >Expiration Date</div> <div dojotype="bec.data.ItemFileReadStore" id="expirationMonths" jsid="expirationMonths" clearonclose="true" data="bec.order.payment.Expiration.getMonths()"></div> - <select id="expire_month" name="expire_month" dojoattachpoint="focusNode,valueNode,textbox,comboNode,containerNode" dojoattachevent="onchange: _selectOption" autocomplete="off" tabindex="0" required="" widgetid="expire_month"><option value="" id="expire_monthph" disabled="" >- Month -</option><option value="01">01 - Jan</option><option value="02">02 - Feb</option><option value="03">03 - Mar</option><option value="04">04 - Apr</option><option value="05">05 - May</option><option value="06">06 - Jun</option><option value="07">07 - Jul</option><option value="08">08 - Aug</option><option value="09">09 - Sep</option><option value="10">10 - Oct</option><option value="11">11 - Nov</option><option value="12">12 - Dec</option></select> - + <select id="expire_month" name="expire_month" dojoattachpoint="focusNode,valueNode,textbox,comboNode,containerNode" dojoattachevent="onchange: _selectOption" tabindex="0" required="" widgetid="expire_month"><option value="" id="expire_monthph" disabled="" >- Month -</option><option value="01">01 - Jan</option><option value="02">02 - Feb</option><option value="03">03 - Mar</option><option value="04">04 - Apr</option><option value="05">05 - May</option><option value="06">06 - Jun</option><option value="07">07 - Jul</option><option value="08">08 - Aug</option><option value="09">09 - Sep</option><option value="10">10 - Oct</option><option value="11">11 - Nov</option><option value="12">12 - Dec</option></select> + <div dojotype="bec.data.ItemFileReadStore" id="expirationYears" jsid="expirationYears" clearonclose="true" data="bec.order.payment.Expiration.getYears({min: new Date(), displayYears: 12})"></div> - <select id="expire_year" name="expire_year" dojoattachpoint="focusNode,valueNode,textbox,comboNode,containerNode" dojoattachevent="onchange: _selectOption" autocomplete="off" tabindex="0" required="" widgetid="expire_year"><option value="" id="expire_yearph" disabled="" >- Year -</option><option value="2014">2014</option><option value="2015">2015</option><option value="2016">2016</option><option value="2017">2017</option><option value="2018">2018</option><option value="2019">2019</option><option value="2020">2020</option><option value="2021">2021</option><option value="2022">2022</option><option value="2023">2023</option><option value="2024">2024</option><option value="2025">2025</option></select> - </div> -</div> + <select id="expire_year" name="expire_year" dojoattachpoint="focusNode,valueNode,textbox,comboNode,containerNode" dojoattachevent="onchange: _selectOption" tabindex="0" required="" widgetid="expire_year"><option value="" id="expire_yearph" disabled="" >- Year -</option><option value="2014">2014</option><option value="2015">2015</option><option value="2016">2016</option><option value="2017">2017</option><option value="2018">2018</option><option value="2019">2019</option><option value="2020">2020</option><option value="2021">2021</option><option value="2022">2022</option><option value="2023">2023</option><option value="2024">2024</option><option value="2025">2025</option></select> + </div> +</div> <!-- END: CreditCard.jsp --></div> </div> - </div> + </div> </div> <!-- BEGIN Partner Feed PartnerFeedOrderPaymentForm --><!-- END Partner Feed PartnerFeedOrderPaymentForm --> </form>
diff --git a/components/test/data/autofill/heuristics/input/112_checkout_m_llbean.com.html b/components/test/data/autofill/heuristics/input/112_checkout_m_llbean.com.html index 830b474..50676744 100644 --- a/components/test/data/autofill/heuristics/input/112_checkout_m_llbean.com.html +++ b/components/test/data/autofill/heuristics/input/112_checkout_m_llbean.com.html
@@ -1,10 +1,10 @@ <head><title>L.L.Bean Secure Checkout:</title></head> -<form id="stepShippingForm" name="stepShippingForm" class="formElements container_12" autocomplete="off"> +<form id="stepShippingForm" name="stepShippingForm" class="formElements container_12"> <div> <div><select id="shipPersonTitle" name="_1_personTitle" selectedtitle=""> <option value="" selected="selected">Title (optional)</option> <option value="Mr."> Mr.</option> <option value="Mrs."> Mrs.</option> <option value="Ms."> Ms.</option> <option value="Dr."> Dr.</option> <option value="Sir"> Sir</option> </select> </div> -<div><label for="shipFirstName">First Name </label><input value="" id="shipFirstName" maxlength="20" name="_1_firstName" type="text" autocomplete="off" autocapitalize="on" autocorrect="off"> <span></span><div></div></div> -<div><label for="shipMiddleName">Middle Name<span>(optional)</span> </label><input value="" id="shipMiddleName" maxlength="20" name="_1_middleName" type="text" autocomplete="off" autocapitalize="on" autocorrect="off"> <span></span> <div></div></div> -<div><label for="shipLastName">Last Name </label><input value="" id="shipLastName" maxlength="20" name="_1_lastName" type="text" autocomplete="off" autocapitalize="on" autocorrect="off"> <span></span><div></div> </div> +<div><label for="shipFirstName">First Name </label><input value="" id="shipFirstName" maxlength="20" name="_1_firstName" type="text" autocapitalize="on" autocorrect="off"> <span></span><div></div></div> +<div><label for="shipMiddleName">Middle Name<span>(optional)</span> </label><input value="" id="shipMiddleName" maxlength="20" name="_1_middleName" type="text" autocapitalize="on" autocorrect="off"> <span></span> <div></div></div> +<div><label for="shipLastName">Last Name </label><input value="" id="shipLastName" maxlength="20" name="_1_lastName" type="text" autocapitalize="on" autocorrect="off"> <span></span><div></div> </div> <div aria-labelledby="shipGenderLabel" role="radiogroup"> <div>Gender (optional) </div> <div><input value="M" id="shipMale" selectedval="" name="_1_gender" type="radio"> <span> Male</span> </div> <div> <input value="F" id="shipFemale" name="_1_gender" type="radio"> <span> Female</span> </div> <div></div> </div> <div id="shippingAddress"> <div>Country</div> <div> USA & Territories </div> <div> <input myclass="" type="submit" value="Edit" name="un_jtt_editCountry_shipCountry" data-sel="shipCountry" data-id="un_editCountry"> </div> <div></div> <select id="shipCountry" name="_1_country"> <option value=""> Please Select </option> <option value="" disabled="disabled"></option> <option value="USA" selected="selected"> USA & Territories </option> <option value="CAN"> Canada </option> <option value="JPN" code="81"> Japan </option> <option value="" disabled="disabled">Other International</option> <option value="ALB" code="355"> Albania</option> <option value="DZA" code="213"> Algeria</option> <option value="AND" code="376"> Andorra</option> <option value="AGO" code="244"> Angola</option> <option value="AIA" code="1"> Anguilla</option> <option value="ATA" code="672"> Antarctica</option> <option value="ATG" code="1"> Antigua and Barbuda</option> <option value="ARG" code="54"> Argentina</option> <option value="AMN" code="374"> Armenia</option> <option value="ABW" code="297"> Aruba</option> <option value="AUS" code="61"> Australia</option> <option value="AUT" code="43"> Austria</option> <option value="AJN" code="994"> Azerbaijan</option> <option value="BHS" code="1"> Bahamas, The</option> <option value="BHR" code="973"> Bahrain</option> <option value="BGD" code="880"> Bangladesh</option> <option value="BRB" code="1"> Barbados</option> <option value="BYE" code="375"> Belarus</option> <option value="BEL" code="32"> Belgium</option> <option value="BLZ" code="501"> Belize</option> <option value="BEN" code="229"> Benin</option> <option value="BMU" code="1"> Bermuda</option> <option value="BTN" code="975"> Bhutan</option> <option value="BOL" code="591"> Bolivia</option> <option value="BKH" code="387"> Bosnia and Herzegovina</option> <option value="BWA" code="267"> Botswana</option> <option value="BVT"> Bouvet Island</option> <option value="BRA" code="55"> Brazil</option> <option value="IOT" code="246"> British Indian Ocean Territory</option> <option value="VGB" code="1"> British Virgin Islands</option> <option value="BRN" code="673"> Brunei Darussalam</option> <option value="BGR" code="359"> Bulgaria</option> <option value="BFA" code="226"> Burkina Faso</option> <option value="BDI" code="257"> Burundi</option> <option value="CBA" code="855"> Cambodia</option> <option value="CMR" code="237"> Cameroon</option> <option value="CPV" code="238"> Cape Verde</option> <option value="CYM" code="1"> Cayman Islands</option> <option value="CAF" code="236"> Central African Republic</option> <option value="TCD" code="235"> Chad</option> <option value="CHL" code="56"> Chile</option> <option value="CHN" code="86"> China, Peoples Republic of</option> <option value="CXR" code="61"> Christmas Island</option> <option value="CCK" code="61"> Cocos (Keeling) Islands</option> <option value="COL" code="57"> Colombia</option> <option value="COM" code="269"> Comoros</option> <option value="ZAR" code="243"> Congo, Democratic Republic of the</option> <option value="COG" code="243"> Congo, Republic of the</option> <option value="COK" code="682"> Cook Islands</option> <option value="CRI" code="506"> Costa Rica</option> <option value="CIV" code="225"> Cote D'ivoire</option> <option value="HRC" code="385"> Croatia</option> <option value="CYP" code="357"> Cyprus</option> <option value="EZR" code="420"> Czech Republic</option> <option value="DNK" code="45"> Denmark</option> <option value="DJI" code="253"> Djibouti</option> <option value="DMA" code="1"> Dominica</option> <option value="DOM" code="1"> Dominican Republic</option> <option value="TMP" code="670"> East Timor</option> <option value="ECU" code="593"> Ecuador</option> <option value="EGY" code="20"> Egypt</option> <option value="DLS" code="503"> El Salvador</option> <option value="ENG" code="44"> England</option> <option value="GNQ" code="240"> Equatorial Guinea</option> <option value="ERI" code="291"> Eritrea</option> <option value="ENA" code="372"> Estonia</option> <option value="ETH" code="251"> Ethiopia</option> <option value="FRO" code="298"> Faeroe Islands</option> <option value="FLK" code="500"> Falkland Islands</option> <option value="FJI" code="679"> Fiji</option> <option value="FIN" code="358"> Finland</option> <option value="FRA" code="33"> France</option> <option value="GUF" code="594"> French Guiana</option> <option value="PYF" code="689"> French Polynesia</option> <option value="ATF" code="262"> French Southern and Antartic Lands</option> <option value="GAB" code="241"> Gabon</option> <option value="GHA" code="233"> Ghana</option> <option value="GMB" code="220"> Gambia</option> <option value="GGA" code="995"> Georgia, Republic of</option> <option value="GMY" code="49"> Germany</option> <option value="GIB" code="350"> Gibraltar</option> <option value="GRC" code="30"> Greece</option> <option value="GRL" code="299"> Greenland</option> <option value="GRD" code="1"> Grenada</option> <option value="GLP" code="590"> Guadeloupe</option> <option value="GTM" code="502"> Guatemala</option> <option value="GKI" code="44"> Guernsey Channel Islands Great Britain</option> <option value="GIN" code="224"> Guinea</option> <option value="GNB" code="245"> Guinea-Bissau</option> <option value="GUY" code="592"> Guyana</option> <option value="HTI" code="509"> Haiti</option> <option value="HMD"> Heard Islands and Mcdonald Islands</option> <option value="HND" code="504"> Honduras</option> <option value="HKG" code="852"> Hong Kong</option> <option value="HUN" code="36"> Hungary</option> <option value="ISL" code="354"> Iceland</option> <option value="IND" code="91"> India</option> <option value="IDN" code="62"> Indonesia</option> <option value="IRL" code="353"> Ireland</option> <option value="IOM" code="44"> Isle of Man</option> <option value="ISR" code="972"> Israel</option> <option value="ITA" code="39"> Italy</option> <option value="JAM" code="1"> Jamaica</option> <option value="JEB" code="44"> Jersey Channel Islands Great Britain</option> <option value="JOR" code="962"> Jordan</option> <option value="KZN" code="7"> Kazakhstan</option> <option value="KEN" code="254"> Kenya</option> <option value="KIR" code="686"> Kiribati</option> <option value="KOR" code="82"> Korea, Republic of</option> <option value="KWT" code="965"> Kuwait</option> <option value="KGZ" code="996"> Kyrgyzstan</option> <option value="LAO" code="856"> Laos</option> <option value="LGA" code="371"> Latvia</option> <option value="LBN" code="961"> Lebanon</option> <option value="LSO" code="266"> Lesotho</option> <option value="LIE" code="423"> Liechtenstein</option> <option value="LHN" code="370"> Lithuania</option> <option value="LUX" code="352"> Luxembourg</option> <option value="MAC" code="853"> Macau</option> <option value="MKA" code="389"> Macedonia</option> <option value="MDG" code="261"> Madagascar</option> <option value="MWI" code="265"> Malawi</option> <option value="MYS" code="60"> Malaysia</option> <option value="MDV" code="960"> Maldives</option> <option value="MLI" code="223"> Mali</option> <option value="MLT" code="356"> Malta</option> <option value="MTQ" code="596"> Martinique</option> <option value="MRT" code="222"> Mauritania</option> <option value="MUS" code="230"> Mauritius</option> <option value="XYO" code="262"> Mayotte</option> <option value="MEX" code="52"> Mexico</option> <option value="MDA" code="373"> Moldova</option> <option value="MCO" code="377"> Monaco</option> <option value="MNG" code="976"> Mongolia</option> <option value="MWO" code="382"> Montenegro</option> <option value="MSR" code="1"> Montserrat</option> <option value="MAR" code="212"> Morocco</option> <option value="MOZ" code="258"> Mozambique</option> <option value="BUR" code="95"> Myanmar</option> <option value="NAM" code="264"> Namibia</option> <option value="NRU" code="674"> Nauru</option> <option value="NPL" code="977"> Nepal</option> <option value="ANT" code="599"> Netherlands Antilles</option> <option value="NLD" code="31"> Netherlands, The</option> <option value="NCL" code="687"> New Caledonia</option> <option value="NZL" code="64"> New Zealand</option> <option value="NIC" code="505"> Nicaragua</option> <option value="NER" code="227"> Niger</option> <option value="NUI" code="683"> Niue</option> <option value="NDI" code="44"> Northern Ireland</option> <option value="NOR" code="47"> Norway</option> <option value="OMN" code="968"> Oman</option> <option value="PAK" code="92"> Pakistan</option> <option value="PAN" code="507"> Panama, Republic of</option> <option value="PNG" code="675"> Papua New Guinea</option> <option value="PRY" code="595"> Paraguay</option> <option value="PER" code="51"> Peru</option> <option value="PHL" code="63"> Philippines</option> <option value="PCN" code="870"> Pitcairn Islands</option> <option value="POL" code="48"> Poland</option> <option value="PRT" code="351"> Portugal</option> <option value="QAT" code="974"> Qatar</option> <option value="REU" code="262"> Reunion</option> <option value="ROM" code="40"> Romania</option> <option value="RSS" code="7"> Russia</option> <option value="RWA" code="250"> Rwanda</option> <option value="SHN" code="290"> Saint Helena</option> <option value="KNA" code="1"> Saint Kitts and Nevis</option> <option value="LCA" code="1"> Saint Lucia</option> <option value="SPM" code="508"> Saint Pierre and Miquelon</option> <option value="SMR" code="378"> San Marino</option> <option value="STP" code="239"> Sao Tome and Principe</option> <option value="SAU" code="966"> Saudi Arabia</option> <option value="SWL" code="44"> Scotland</option> <option value="SEN" code="221"> Senegal</option> <option value="SSB" code="381"> Serbia-Montenegro</option> <option value="SYC" code="248"> Seychelles</option> <option value="SGP" code="65"> Singapore, Republic of</option> <option value="LOV" code="421"> Slovakia</option> <option value="SIV" code="386"> Slovenia</option> <option value="SLB" code="677"> Solomon Islands</option> <option value="ZAF" code="27"> South Africa, Republic of</option> <option value="ESP" code="34"> Spain</option> <option value="LKA" code="94"> Sri Lanka</option> <option value="VCT" code="1"> St Vincent and The Grenadines</option> <option value="SUR" code="597"> Suriname</option> <option value="SWZ" code="268"> Swaziland</option> <option value="SWE" code="46"> Sweden</option> <option value="CHE" code="41"> Switzerland</option> <option value="TWN" code="886"> Taiwan</option> <option value="TIJ" code="992"> Tajikistan</option> <option value="TZA" code="255"> Tanzania</option> <option value="THA" code="66"> Thailand</option> <option value="TGO" code="228"> Togo</option> <option value="TKL" code="690"> Tokelau</option> <option value="TON" code="676"> Tonga</option> <option value="TTO" code="1"> Trinidad and Tobago</option> <option value="TUN" code="216"> Tunisia</option> <option value="TUR" code="90"> Turkey</option> <option value="TXS" code="993"> Turkmenistan</option> <option value="TCA" code="1"> Turks and Caicos Islands</option> <option value="TUV" code="688"> Tuvalu</option> <option value="UGA" code="256"> Uganda</option> <option value="UPN" code="380"> Ukraine</option> <option value="ARE" code="971"> United Arab Emirates</option> <option value="UMI"> United States Minor Outlying Islands</option> <option value="URY" code="598"> Uruguay</option> <option value="UZB" code="998"> Uzbekistan</option> <option value="VUT" code="678"> Vanuatu</option> <option value="VAT" code="39"> Vatican City</option> <option value="VEN" code="58"> Venezuela</option> <option value="VNM" code="84"> Vietnam</option> <option value="WWS" code="44"> Wales</option> <option value="WLF" code="681"> Wallis and Futuna</option> <option value="ESH" code="212"> Western Sahara</option> <option value="WSM" code="685"> Western Samoa</option> <option value="YMN" code="967"> Yemen</option> <option value="ZMB" code="260"> Zambia</option> <option value="ZWE" code="263"> Zimbabwe</option> </select> <span></span> <div> <input id="un_changecountry_shipCountry" myclass="" value="Apply" name="un_jtt_changeCountry_shipCountry" type="submit" onclick=""> </div> </div> <div> <label for="shipJPNPostal"><span> <img alt="" src="/skassets/v201412111959p/images/japan_postal.png"></span>Postal Code </label><input value="" id="shipJPNPostal" maxlength="10" name="_1_JPNPostal" type="text"> <span></span> <div></div> </div>
diff --git a/components/test/data/autofill/heuristics/input/114_cc_checkout_wayfair.com.html b/components/test/data/autofill/heuristics/input/114_cc_checkout_wayfair.com.html index 0cba1e2..f0cb1b3 100644 --- a/components/test/data/autofill/heuristics/input/114_cc_checkout_wayfair.com.html +++ b/components/test/data/autofill/heuristics/input/114_cc_checkout_wayfair.com.html
@@ -235,7 +235,7 @@ Card number* </div> <div class="inputtxt"> - <input type="text" class="js-credit-card-input js-credit-card-number creditcardinput js-cursorfocus" size="25" maxlength="20" data-blank-error-message="Please enter your credit card number" name="credit_card[card_number]" id="card_number" value="" autocomplete="Off"> + <input type="text" class="js-credit-card-input js-credit-card-number creditcardinput js-cursorfocus" size="25" maxlength="20" data-blank-error-message="Please enter your credit card number" name="credit_card[card_number]" id="card_number" value=""> </div> <div class="errorcontain js-error-container"><span class="js-new-card-error">Please enter your credit card number</span></div> </div> @@ -362,7 +362,7 @@ </div> <div class="inputtxt display_table"> <div class="display_table_cell"> - <input type="text" class="js-credit-card-input js-credit-card-security-code creditcardsm" size="4" maxlength="4" data-blank-error-message="Please enter CVV2 code" name="credit_card[security_code]" value="" id="security_code" autocomplete="Off"> + <input type="text" class="js-credit-card-input js-credit-card-security-code creditcardsm" size="4" maxlength="4" data-blank-error-message="Please enter CVV2 code" name="credit_card[security_code]" value="" id="security_code"> </div> <div class="display_table_cell"> <div class="indented ltbodytext note"> @@ -380,7 +380,7 @@ Name on card* </div> <div class="inputtxt"> - <input type="text" class="js-credit-card-input js-credit-card-name creditcardinput" size="25" maxlength="50" name="credit_card[card_holder_name]" data-blank-error-message="Please enter the name on the card" id="OrCardholderName" value="Homer Simpson" autocomplete="Off"> + <input type="text" class="js-credit-card-input js-credit-card-name creditcardinput" size="25" maxlength="50" name="credit_card[card_holder_name]" data-blank-error-message="Please enter the name on the card" id="OrCardholderName" value="Homer Simpson"> </div> <div class="errorcontain js-error-container"> @@ -845,4 +845,4 @@ <div class="modal_overlay hidden-node"></div><div class="wf-modal-overlay" style="display: none;"></div><div style="display:none;"><img src="https://www.wayfair.com/__ssobj/track?event=CheckoutPayment&value=&x=1454516744893-3" height="1" width="1" border="0" id="SS.IMG63907550"></div><div style="display:none;"><img src="https://www.wayfair.com/__ssobj/track?event=credit_card_error_credit_card%5Bcard_number%5D&value=&x=1454516747290-3" height="1" width="1" border="0" id="SS.IMG63907550"></div> </body> -</html> \ No newline at end of file +</html>
diff --git a/components/test/data/autofill/heuristics/input/117_cc_checkout_macys.com.html b/components/test/data/autofill/heuristics/input/117_cc_checkout_macys.com.html index 95833d7..2c52782 100644 --- a/components/test/data/autofill/heuristics/input/117_cc_checkout_macys.com.html +++ b/components/test/data/autofill/heuristics/input/117_cc_checkout_macys.com.html
@@ -222,7 +222,7 @@ <div class="row" id="rc-payment-card-number-row"> <div class="small-14 small-offset-1 medium-10 columns"> <label for="rc-payment-card-number">Card number</label> - <input type="text" maxlength="20" pattern="\d*" name="creditCard.cardNumber" id="rc-payment-card-number" value="" autocomplete="off" autocorrect="off" aria-required="true" title="overall type: CREDIT_CARD_NUMBER + <input type="text" maxlength="20" pattern="\d*" name="creditCard.cardNumber" id="rc-payment-card-number" value="" autocorrect="off" aria-required="true" title="overall type: CREDIT_CARD_NUMBER server type: CREDIT_CARD_NUMBER heuristic type: CREDIT_CARD_NUMBER field signature: 2117159926 @@ -318,7 +318,7 @@ <div class="row" id="rc-payment-scode-row"> <div class="small-4 small-offset-1 large-3 columns end"> - <input type="text" name="fake-password" id="rc-fake-password" class="hidden" autocomplete="off" style="display: none;" title="overall type: CREDIT_CARD_VERIFICATION_CODE + <input type="text" name="fake-password" id="rc-fake-password" class="hidden" style="display: none;" title="overall type: CREDIT_CARD_VERIFICATION_CODE server type: NO_SERVER_DATA heuristic type: CREDIT_CARD_VERIFICATION_CODE field signature: 3761992124 @@ -628,7 +628,7 @@ <div class="small-14 small-offset-1 medium-10 columns"> <label for="rc-payment-phone">Phone number</label> - <input type="text" maxlength="14" pattern="\d*" name="billingAddress.phone" id="rc-payment-phone" value="" autocorrect="off" aria-required="true" autocomplete="off" title="overall type: PHONE_HOME_CITY_AND_NUMBER + <input type="text" maxlength="14" pattern="\d*" name="billingAddress.phone" id="rc-payment-phone" value="" autocorrect="off" aria-required="true" title="overall type: PHONE_HOME_CITY_AND_NUMBER server type: PHONE_HOME_CITY_AND_NUMBER heuristic type: PHONE_HOME_WHOLE_NUMBER field signature: 2467847771
diff --git a/components/test/data/autofill/heuristics/input/123_bug_459132.html b/components/test/data/autofill/heuristics/input/123_bug_459132.html index d23dbbb..574a4fa 100644 --- a/components/test/data/autofill/heuristics/input/123_bug_459132.html +++ b/components/test/data/autofill/heuristics/input/123_bug_459132.html
@@ -1,11 +1,11 @@ <form data-dojo-attach-point="containerNode" data-dojo-attach-event="onreset:_onReset,onsubmit:_onSubmit" name="FeedbackForm" lang="en" action="https://www.lufthansa.com/online/portal/lh/de/help_contact/feedback/!ut/p/c5/04_SB8K8xLLM9MSSzPy8xBz9CP0os3hHg2B_U3d350DfMA9jA0czF5OgUFNLC9MAU6B8JE75gAADYnQb4ACOhHR76Uel5-QnAV0ZDnI3bne4mOKXB7kTJI_HJX4e-bmp-gW5oRGVwZ66AI5DSgQ!/dl3/d3/L0lJSklna2tra2tra25wQSEvb013d0FBQVlnQUNFSVFRaUtVUXhnb1lCem5KUUZnQSEvNEJuNHNvMFZnTGE5Mmd6a0xLQnl3ZyEhLzZfQTBTTzVHR0NRTVZIMzBBNkQ0UlU1OTg1UDUvN19BMFNPNUdHQ1FNVkgzMEE2RDRSVTU5MEkwMS9zYS5GZWVkYmFja0lucHV0QWN0aW9uL25vcm1hbC9EZWZhdWx0/?l=en&cid=18002&action=FeedbackInputAction&command=sumbitForm&p=LH&s=DE&l=en&cid=18002&action=FeedbackInputAction&command=sumbitForm&p=LH&s=DE" id="fb_form" method="post" widgetid="fb_form"> - + <!-- Hidden input to disable content header portlet--> <input type="hidden" name="formSubmitted" value="true"> <input type="hidden" value="" name="formtype" id="formTypeInput"> <input type="hidden" name="isFlynet" value="false"> <input type="hidden" name="categoryId" id="categoryId" value=""> - + <div id="fb_mod_personal" class="lh_fbMargin clearfix"> <div class="fieldwrapper wide"> <h1>Your personal data</h1> @@ -23,14 +23,14 @@ <div class="cl"> <div class="fieldwrapper"> <label for="firstname" class="firstname">First name</label> - <div id="firstname"><div class="dijit dijitReset dijitInline dijitLeft fb_protect firstname dijitTextBox dijitValidationTextBox dijitTextBoxError dijitValidationTextBoxError dijitError" id="widget_firstname" role="presentation" widgetid="firstname"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="FirstName_1" type="text" tabindex="0" id="firstname" aria-required="true" maxlength="50" value="" aria-invalid="true"></div></div></div> + <div id="firstname"><div class="dijit dijitReset dijitInline dijitLeft fb_protect firstname dijitTextBox dijitValidationTextBox dijitTextBoxError dijitValidationTextBoxError dijitError" id="widget_firstname" role="presentation" widgetid="firstname"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" name="FirstName_1" type="text" tabindex="0" id="firstname" aria-required="true" maxlength="50" value="" aria-invalid="true"></div></div></div> </div> </div> - + <div class="cl"> <div class="fieldwrapper"> <label for="lastname" class="lastname">Last name</label> - <div id="lastname"><div class="dijit dijitReset dijitInline dijitLeft fb_protect lastname dijitTextBox dijitValidationTextBox dijitTextBoxIncomplete dijitValidationTextBoxIncomplete dijitIncomplete" id="widget_lastname" role="presentation" widgetid="lastname"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="LastName_1" type="text" tabindex="0" id="lastname" aria-required="true" maxlength="50" value="" aria-invalid="false"></div></div></div> + <div id="lastname"><div class="dijit dijitReset dijitInline dijitLeft fb_protect lastname dijitTextBox dijitValidationTextBox dijitTextBoxIncomplete dijitValidationTextBoxIncomplete dijitIncomplete" id="widget_lastname" role="presentation" widgetid="lastname"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" name="LastName_1" type="text" tabindex="0" id="lastname" aria-required="true" maxlength="50" value="" aria-invalid="false"></div></div></div> </div> </div> </div> @@ -39,24 +39,24 @@ <div class="cl"> <div class="fieldwrapper"> <label for="email" class="email">Email</label> - <div id="email"><div class="dijit dijitReset dijitInline dijitLeft fb_protect email dijitTextBox dijitValidationTextBox dijitTextBoxIncomplete dijitValidationTextBoxIncomplete dijitIncomplete dijitTextBoxFocused dijitValidationTextBoxFocused dijitTextBoxIncompleteFocused dijitValidationTextBoxIncompleteFocused dijitIncompleteFocused dijitFocused" id="widget_email" role="presentation" widgetid="email"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="Email_1" type="text" tabindex="0" id="email" aria-required="true" value="" aria-invalid="false"></div></div></div> + <div id="email"><div class="dijit dijitReset dijitInline dijitLeft fb_protect email dijitTextBox dijitValidationTextBox dijitTextBoxIncomplete dijitValidationTextBoxIncomplete dijitIncomplete dijitTextBoxFocused dijitValidationTextBoxFocused dijitTextBoxIncompleteFocused dijitValidationTextBoxIncompleteFocused dijitIncompleteFocused dijitFocused" id="widget_email" role="presentation" widgetid="email"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" name="Email_1" type="text" tabindex="0" id="email" aria-required="true" value="" aria-invalid="false"></div></div></div> </div> </div> - + <div class="cl"> <div class="fieldwrapper"> <label for="r_email" class="email">Re-enter email</label> - <div id="r_email"><div class="dijit dijitReset dijitInline dijitLeft dijitTextBox dijitValidationTextBox fb_protect email" id="widget_r_email" role="presentation" widgetid="r_email"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="rEmail_1" type="text" tabindex="0" id="r_email" aria-required="true" value="" aria-invalid="false"></div></div></div> + <div id="r_email"><div class="dijit dijitReset dijitInline dijitLeft dijitTextBox dijitValidationTextBox fb_protect email" id="widget_r_email" role="presentation" widgetid="r_email"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" name="rEmail_1" type="text" tabindex="0" id="r_email" aria-required="true" value="" aria-invalid="false"></div></div></div> </div> </div> - + </div> - + <div class="subtpl clear"> <div class="cl"> <div class="fieldwrapper"> <label for="mam_number" class="mam_number">Miles & More number <span class="optional"><span> </span>optional</span></label> - <div id="mam_number"><div class="dijit dijitReset dijitInline dijitLeft dijitTextBox dijitValidationTextBox fb_protect mam_number" id="widget_mam_number" role="presentation" widgetid="mam_number"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="MamNumber_1" type="text" tabindex="0" id="mam_number" maxlength="15" value="" aria-invalid="false"></div></div></div> + <div id="mam_number"><div class="dijit dijitReset dijitInline dijitLeft dijitTextBox dijitValidationTextBox fb_protect mam_number" id="widget_mam_number" role="presentation" widgetid="mam_number"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" name="MamNumber_1" type="text" tabindex="0" id="mam_number" maxlength="15" value="" aria-invalid="false"></div></div></div> </div> </div> </div> @@ -66,20 +66,20 @@ <div class="cl w50 firstColumn"> <h1>What can we do for you?</h1> <table class="dijit dijitReset dijitInline dijitLeft dijitDownArrowButton fb_protect cat_select1 dijitSelectFixedWidth dijitValidationTextBoxFixedWidth dijitSelect dijitValidationTextBox dijitSelectIncomplete dijitValidationTextBoxIncomplete dijitIncomplete" data-dojo-attach-point="_buttonNode,tableNode,focusNode,_popupStateNode" cellspacing="0" cellpadding="0" role="listbox" aria-haspopup="true" tabindex="0" id="CAT_SELECT_1" aria-required="true" widgetid="CAT_SELECT_1" aria-expanded="false" aria-invalid="true" style="-webkit-user-select: none; display: block; width: auto; font-size: 14px; padding: 1px 0px 1px 10px; margin: 10px 0px 0px;"><tbody role="presentation"><tr role="presentation"><td class="dijitReset dijitStretch dijitButtonContents" role="presentation"><div class="dijitReset dijitInputField dijitButtonText" data-dojo-attach-point="containerNode,textDirNode" role="presentation"><span role="option" class="dijitReset dijitInline dijitSelectLabel dijitValidationTextBoxLabel ">Please select a category</span></div><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><input type="hidden" name="Category_1" data-dojo-attach-point="valueNode" value=" " aria-hidden="true"></td><td class="dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer" data-dojo-attach-point="titleNode" role="presentation"><input class="dijitReset dijitInputField dijitArrowButtonInner" value="â–¼ " type="text" tabindex="-1" readonly="readonly" role="presentation"></td></tr></tbody></table></div> - + <div class="cr w50 secondColumn"> <p class="x-hidden"> <iframe src="" id="iInterceptor"></iframe> - </p> - </div> + </p> + </div> </div> <div class="selectorQuestion fb_borderSeperator x-hidden clear"></div> </div> - + <div id="fb_mod_dynamicWrapper" class="lh_fbMargin x-hidden"> <h1>Please fill in more detailed information</h1> - - + + <div id="fb_mod_cstm_wrp" class="fb_borderSeperator x-hidden"> <div id="fb_mod_address" class="x-hidden"> <div class="fieldwrapper wide"> @@ -92,7 +92,7 @@ <div id="street_name"></div> </div> </div> - + <div class="cl"> <div class="fieldwrapper"> <label for="street_no" class="street_no">Number</label> @@ -100,7 +100,7 @@ </div> </div> </div> - + <div class="subtpl clear"> <div class="cl"> <div class="fieldwrapper"> @@ -108,22 +108,22 @@ <div id="zip"></div> </div> </div> - + <div class="cl"> <div class="fieldwrapper"> <label for="city" class="city">City</label> - <div id="city"></div> + <div id="city"></div> </div> </div> </div> - + <div class="subtpl"> <div class="fieldwrapper"> - <label for="address_details" class="addressDetails">Additional address line <span class="optional"><span> </span>optional</span></label> + <label for="address_details" class="addressDetails">Additional address line <span class="optional"><span> </span>optional</span></label> <div id="address_details"></div> </div> </div> - + <div class="subtpl"> <div class="cl"> <div class="fieldwrapper"> @@ -131,7 +131,7 @@ <div id="country"></div> </div> </div> - <div class="cl"> + <div class="cl"> <div class="fieldwrapper x-hidden"> <label for="regions" class="regions">State / Region</label> <div id="regions"> </div> @@ -139,7 +139,7 @@ </div> </div> </div> - <div id="fb_mod_phone" class="x-hidden"> + <div id="fb_mod_phone" class="x-hidden"> <div class="subtpl clear"> <label for="phone" class="phone">Telephone</label> <div class="cl"> @@ -153,18 +153,18 @@ </div> </div> <div class="cl"> - <div class="fieldwrapper wide"> + <div class="fieldwrapper wide"> <div id="phone_number"></div> </div> </div> </div> -</div> - +</div> + <div id="fb_mod_customer2" class="x-hidden fb_borderSeperator"> <div class="fieldwrapper wide"> <h3 class="pi_containerSubline">Personal data of customer <a href="#" id="passenger2" class="fb_removePassenger"><span>Remove</span></a></h3> </div> - + <div class="subtpl"> <div class="fieldwrapper"> <div id="adressChkBox2"> @@ -172,7 +172,7 @@ </div> </div> </div> - + <div class="subtpl clear"> <div class="fieldwrapper"> <label for="title2" class="title">Title</label> @@ -187,7 +187,7 @@ <div id="firstname2"></div> </div> </div> - + <div class="cl"> <div class="fieldwrapper"> <label for="lastname2" class="lastname">Last name</label> @@ -208,11 +208,11 @@ <div class="fieldwrapper"> <label for="r_email2" class="email">Re-enter email</label> <div id="r_email2"></div> - </div> - </div> + </div> + </div> </div> - - <div class="subtpl clear"> + + <div class="subtpl clear"> <div class="cl"> <div class="fieldwrapper"> <label for="mam_number2" class="mam_number">Miles & More number</label> @@ -228,7 +228,7 @@ <div id="street_name2"></div> </div> </div> - + <div class="cl"> <div class="fieldwrapper"> <label for="street_no2" class="street_no">Number</label> @@ -258,7 +258,7 @@ <div id="address_details2"></div> </div> </div> - + <div class="subtpl"> <div class="cl"> <div class="fieldwrapper"> @@ -266,7 +266,7 @@ <div id="country2"></div> </div> </div> - <div class="cl"> + <div class="cl"> <div class="fieldwrapper x-hidden"> <label for="regions2">State / Region</label> <div id="regions2"> </div> @@ -275,10 +275,10 @@ </div> <div class="subtpl clear"> - <label for="phone2" class="phone">Telephone</label> + <label for="phone2" class="phone">Telephone</label> <div class="cl"> <div class="fieldwrapper"> - <div id="phone_country2" class="cl"></div> + <div id="phone_country2" class="cl"></div> </div> </div> <div class="cl"> @@ -287,18 +287,18 @@ </div> </div> <div class="cl"> - <div class="fieldwrapper"> + <div class="fieldwrapper"> <div id="phone_number2" class="cl"></div> </div> </div> </div> </div> - + <div id="fb_mod_customer3" class="x-hidden fb_borderSeperator"> <div class="fieldwrapper wide"> <h3 class="pi_containerSubline">Personal data of customer <a href="#" id="passenger3" class="fb_removePassenger"><span>Remove</span></a></h3> </div> - + <div class="subtpl"> <div class="fieldwrapper"> <div id="adressChkBox3"> @@ -306,7 +306,7 @@ </div> </div> </div> - + <div class="subtpl clear"> <div class="fieldwrapper"> <label for="title3" class="title">Title</label> @@ -321,7 +321,7 @@ <div id="firstname3"></div> </div> </div> - + <div class="cl"> <div class="fieldwrapper"> <label for="lastname3" class="lastname">Last name</label> @@ -342,11 +342,11 @@ <div class="fieldwrapper"> <label for="r_email3" class="email">Re-enter email</label> <div id="r_email3"></div> - </div> - </div> + </div> + </div> </div> - - <div class="subtpl clear"> + + <div class="subtpl clear"> <div class="cl"> <div class="fieldwrapper"> <label for="mam_number3" class="mam_number">Miles & More number</label> @@ -362,7 +362,7 @@ <div id="street_name3"></div> </div> </div> - + <div class="cl"> <div class="fieldwrapper"> <label for="street_no3" class="street_no">Number</label> @@ -392,7 +392,7 @@ <div id="address_details3"></div> </div> </div> - + <div class="subtpl"> <div class="cl"> <div class="fieldwrapper"> @@ -400,7 +400,7 @@ <div id="country3"></div> </div> </div> - <div class="cl"> + <div class="cl"> <div class="fieldwrapper x-hidden"> <label for="regions3">State / Region</label> <div id="regions3"> </div> @@ -409,10 +409,10 @@ </div> <div class="subtpl clear"> - <label for="phone3" class="phone">Telephone</label> + <label for="phone3" class="phone">Telephone</label> <div class="cl"> <div class="fieldwrapper"> - <div id="phone_country3" class="cl"></div> + <div id="phone_country3" class="cl"></div> </div> </div> <div class="cl"> @@ -421,23 +421,23 @@ </div> </div> <div class="cl"> - <div class="fieldwrapper"> + <div class="fieldwrapper"> <div id="phone_number3" class="cl"></div> </div> </div> </div> </div> - + <div id="addCustomer"></div> - </div> - - + </div> + + <div id="fb_mod_prm"> <div id="fb_mod_flightDetails" class="lh_fbMargin fb_borderSeperator x-hidden"> <div class="fieldwrapper wide"> <h3 class="pi_containerSubline">Flight information</h3> </div> - + <div class="subtpl"> <div class="cl"> <div class="fieldwrapper"> @@ -445,15 +445,15 @@ <div id="fd_FileKey"></div> </div> </div> - + <div class="cl"> <div class="fieldwrapper"> <label for="fd_flight_number" class="flight_number">Flight number</label> <span class="flight_number_prefix">LH</span> <div id="fd_FlightNumber"></div> </div> - </div> + </div> </div> - + <div class="subtpl clear"> <div class="cl"> <div class="fieldwrapper wide"> @@ -476,7 +476,7 @@ <div class="fieldwrapper wide"> <h3 class="pi_containerSubline">Please choose the appropriate option</h3> </div> - + <div class="subtpl"> <div class="cl"> <div class="fieldwrapper"> @@ -488,7 +488,7 @@ <div class="subtpl"> <div class="cl"> <div class="fieldwrapper"> - <div id="at_Staircases"></div> + <div id="at_Staircases"></div> <label for="at_staircases_radio" class="fb_radio">I can walk short and long distances, but I have difficulties with stairs</label> </div> </div> @@ -514,7 +514,7 @@ <div class="subtpl"> <div class="cl"> <div class="fieldwrapper"> - <div id="dt_Deaf"></div> + <div id="dt_Deaf"></div> <label for="dt_deaf_chkbox" class="fb_radio">I am deaf or have a severe hearing impairment</label> </div> </div> @@ -527,7 +527,7 @@ </div> </div> </div> -</div> +</div> <div id="fb_mod_companionReasons" class="lh_fbMargin fb_borderSeperator x-hidden"> <div class="subtpl"> <div class="cl"> @@ -540,24 +540,24 @@ <div class="subtpl"> <div class="cl"> <div class="fieldwrapper wide"> - <div id="cr_Pr"></div> + <div id="cr_Pr"></div> <label for="cr_pr_radio" class="fb_radio">I need to travel in companionship of a dog due to psychological reasons</label> </div> </div> </div> -</div> +</div> <div class="subtpl"> <div class="cr"> - <div id="fd_reset" class="x-hidden"></div> + <div id="fd_reset" class="x-hidden"></div> </div> </div> </div> - <div id="fb_mod_pir" class="lh_fbMargin fb_borderSeperator x-hidden"> + <div id="fb_mod_pir" class="lh_fbMargin fb_borderSeperator x-hidden"> <div class="fieldwrapper wide"> <h3 class="pi_containerSubline">Property Irregularity Report Number (PIR)</h3> </div> - + <div class="subtpl"> <div class="cl"> <div class="fieldwrapper wide"> @@ -586,7 +586,7 @@ <div id="airline"></div> </div> </div> - + <div class="cl"> <div class="fieldwrapper"> <label for="flight_number" class="flight_number">Flight number</label> <span class="flight_number_prefix"></span> @@ -604,8 +604,8 @@ <div class="subtpl clear"> <div class="fieldwrapper wide aa-link"> - <label for="f-originName0" class="origin">Origin</label> - <input type="text" autocomplete="off" id="f-originName0" name="originName"> + <label for="f-originName0" class="origin">Origin</label> + <input type="text" id="f-originName0" name="originName"> <input type="hidden" id="f-originCode0" name="originCode"> <a href="#" id="lnk-origin" data-dojo-type="lh.widget.AirportAtlas" data-dojo-props="fieldId:'f-originName0',hiddenFieldId:'f-originCode0',url:'/dlvutils/AirportAtlasApplication?app=FB&selected=DE&lang=en',serviceUrl:'/dlvutils/AirportAtlasApplication', app:'FB', language:'en'"> <span class="airport-dir"> </span> @@ -618,8 +618,8 @@ <div class="subtpl clear"> <div class="fieldwrapper wide aa-link"> - <label for="f-destinationName0">Destination</label> - <input type="text" autocomplete="off" id="f-destinationName0" name="destinationName"> + <label for="f-destinationName0">Destination</label> + <input type="text" id="f-destinationName0" name="destinationName"> <input type="hidden" id="f-destinationCode0" name="destinationCode"> <a href="#" id="lnk-destination" data-dojo-type="lh.widget.AirportAtlas" data-dojo-props="fieldId:'f-destinationName0',hiddenFieldId:'f-destinationCode0',url:'/dlvutils/AirportAtlasApplication?app=FB&lang=en',serviceUrl:'/dlvutils/AirportAtlasApplication', app:'FB', language:'en'"> <span class="airport-dir"> </span> @@ -639,10 +639,10 @@ <div class="fbRadioWrapper"> <div class="fieldwrapper wide"> <label for="ticket_no" class="marginLeft">Ticket number</label> - <div id="ticket_no"></div> - </div> + <div id="ticket_no"></div> + </div> </div> - + <div class="fbRadioWrapper"> <div class="fieldwrapper wide"> <label for="file_key" class="marginLeft">File key</label> @@ -663,9 +663,9 @@ <label for="refundTicketCheckbox" class="customerChk">Refund entire ticket</label> </div> </div> - </div> + </div> </div> - + <div class="subtpl"> <div class="cl"> <div class="fieldwrapper"> @@ -674,7 +674,7 @@ </div> </div> </div> - + <div class="subtpl"> <div class="cl"> <div class="fieldwrapper wide"> @@ -682,7 +682,7 @@ <div id="refund_file_key"></div> </div> </div> - + <div class="cl"> <div class="fieldwrapper wide"> <label for="ticket_no_lh" class="ticket_no_lh">Ticket number</label> @@ -690,7 +690,7 @@ </div> </div> </div> - + <div class="subtpl x-hidden"> <div class="cl"> <div class="fieldwrapper wide"> @@ -702,10 +702,10 @@ </div> <div id="fb_mod_bank" class="lh_fbMargin fb_borderSeperator x-hidden"> <div class="fieldwrapper wide"> - <h3 class="pi_containerSubline">Bank account information<a class="infoMessage" id="bank_toolTip1" href="javascript:void(0);"> </a></h3> + <h3 class="pi_containerSubline">Bank account information<a class="infoMessage" id="bank_toolTip1" href="javascript:void(0);"> </a></h3> <div connectid="bank_toolTip1" dojotype="dijit.Tooltip" showdelay="250" label="Please enter your bank account information" class="dijitTooltipData" id="dijit_Tooltip_5" lang="en" widgetid="dijit_Tooltip_5"> </div> </div> - + <div class="subtpl"> <div class="cl"> <div class="fieldwrapper"> @@ -728,7 +728,7 @@ <div id="iban"></div> </div> </div> - + <div class="cl"> <div class="fieldwrapper wide"> <label for="bic">SWIFT/BIC code</label> @@ -738,10 +738,10 @@ </div> </div> <div id="fb_mod_technial" class="lh_fbMargin fb_borderSeperator x-hidden"> - <div class="fieldwrapper wide"> + <div class="fieldwrapper wide"> <h3 class="pi_containerSubline">Technical information</h3> </div> - + <div class="subtpl"> <div class="cl"> <div class="fieldwrapper wide"> @@ -749,7 +749,7 @@ <div id="browser"></div> </div> </div> - + <div class="cl"> <div class="fieldwrapper wide"> <label for="os">Operating system</label> @@ -762,7 +762,7 @@ <div class="fieldwrapper wide"> <h3 class="pi_containerSubline">Feedback ID</h3> </div> - + <div class="subtpl"> <div class="fieldwrapper wide"> <label for="feedbackId">Please enter your feedback ID</label> @@ -778,24 +778,24 @@ <div id="comment"></div> </div> </div> - - - </div> - - <input type="hidden" class="x-fup-hd-filename" name="FileName_1" id="attach_filename_1" value=""> - <input type="hidden" class="x-fup-hd-filename" name="FileName_2" id="attach_filename_2" value=""> - <input type="hidden" class="x-fup-hd-filename" name="FileName_3" id="attach_filename_3" value=""> - <input type="hidden" class="x-fup-hd-filename" name="FileName_4" id="attach_filename_4" value=""> - <input type="hidden" class="x-fup-hd-filename" name="FileName_5" id="attach_filename_5" value=""> - <input type="hidden" class="x-fup-hd-filename" name="FileName_6" id="attach_filename_6" value=""> <br> - - <input type="hidden" class="x-fup-hd-fileid" name="FileId_1" id="attach_fileid_1" value=""> - <input type="hidden" class="x-fup-hd-fileid" name="FileId_2" id="attach_fileid_2" value=""> - <input type="hidden" class="x-fup-hd-fileid" name="FileId_3" id="attach_fileid_3" value=""> - <input type="hidden" class="x-fup-hd-fileid" name="FileId_4" id="attach_fileid_4" value=""> - <input type="hidden" class="x-fup-hd-fileid" name="FileId_5" id="attach_fileid_5" value=""> + + </div> + + + <input type="hidden" class="x-fup-hd-filename" name="FileName_1" id="attach_filename_1" value=""> + <input type="hidden" class="x-fup-hd-filename" name="FileName_2" id="attach_filename_2" value=""> + <input type="hidden" class="x-fup-hd-filename" name="FileName_3" id="attach_filename_3" value=""> + <input type="hidden" class="x-fup-hd-filename" name="FileName_4" id="attach_filename_4" value=""> + <input type="hidden" class="x-fup-hd-filename" name="FileName_5" id="attach_filename_5" value=""> + <input type="hidden" class="x-fup-hd-filename" name="FileName_6" id="attach_filename_6" value=""> <br> + + <input type="hidden" class="x-fup-hd-fileid" name="FileId_1" id="attach_fileid_1" value=""> + <input type="hidden" class="x-fup-hd-fileid" name="FileId_2" id="attach_fileid_2" value=""> + <input type="hidden" class="x-fup-hd-fileid" name="FileId_3" id="attach_fileid_3" value=""> + <input type="hidden" class="x-fup-hd-fileid" name="FileId_4" id="attach_fileid_4" value=""> + <input type="hidden" class="x-fup-hd-fileid" name="FileId_5" id="attach_fileid_5" value=""> <input type="hidden" class="x-fup-hd-fileid" name="FileId_6" id="attach_fileid_6" value=""> - + </form>
diff --git a/components/test/data/autofill/heuristics/input/127_bug_463986.html b/components/test/data/autofill/heuristics/input/127_bug_463986.html index 4f4b63f..ebd2d6c 100644 --- a/components/test/data/autofill/heuristics/input/127_bug_463986.html +++ b/components/test/data/autofill/heuristics/input/127_bug_463986.html
@@ -1,4 +1,4 @@ -<form method="POST" id="frontendForm" name="frontendForm" action="http://foo.com"><input value="DEFAULT" id="frontendDisplayMode" type="hidden"><input value="false" id="acceptIbanBic" type="hidden"><input value="en" type="HIDDEN" id="frontendLanguage" name="frontendLanguage"><input autocomplete="off" value="VISA" type="HIDDEN" id="accountBrand" name="accountBrand"><input type="HIDDEN" id="selectedLayer" name="selectedLayer" value="default"><input type="HIDDEN" id="paymentType" name="paymentType" value="DB"><table align="center" width="100%"><tbody><tr><td><div style="display: none;" align="center" name="loading" id="loading"></div><div style="display: block;" name="defaultData" id="defaultData"><table border="0"><tbody><tr><td><table border="0" id="defaultPaymentTable"><tbody><tr id="userInfoBlock"><td class="frm_box"><table><tbody><tr id="salutationRow"><td style="width:170px;height:16px;">Salutation and Given Name +<form method="POST" id="frontendForm" name="frontendForm" action="http://foo.com"><input value="DEFAULT" id="frontendDisplayMode" type="hidden"><input value="false" id="acceptIbanBic" type="hidden"><input value="en" type="HIDDEN" id="frontendLanguage" name="frontendLanguage"><input value="VISA" type="HIDDEN" id="accountBrand" name="accountBrand"><input type="HIDDEN" id="selectedLayer" name="selectedLayer" value="default"><input type="HIDDEN" id="paymentType" name="paymentType" value="DB"><table align="center" width="100%"><tbody><tr><td><div style="display: none;" align="center" name="loading" id="loading"></div><div style="display: block;" name="defaultData" id="defaultData"><table border="0"><tbody><tr><td><table border="0" id="defaultPaymentTable"><tbody><tr id="userInfoBlock"><td class="frm_box"><table><tbody><tr id="salutationRow"><td style="width:170px;height:16px;">Salutation and Given Name </td><td style="width:222px;"><select id="salutation" name="salutation" style="width:60px;" size="1"><option title="---" selected="" value="NONE">---</option><option title="Mr." value="MR">Mr.</option><option title="Mrs." value="MRS">Mrs.</option><option title="Ms." value="MS">Ms.</option> </select> @@ -18,24 +18,24 @@ </select></td></tr></tbody></table></td></tr><tr class="paymentContainer" id="creditCard"><td class="frm_box"><div name="ccBlock" id="ccBlock"><table><tbody><tr><td><table border="0" id="cardPane"><tbody><tr id="cardTypeRow"><td style="width:170px;height:16px;">Card Brand</td><td style="width:222px;"><select id="accountBrandDropDown" name="accountBrandDropDown" onchange="brandChanged()" style="width:120px;" size="1"><option title="Visa" selected="" value="VISA">Visa</option> </select><img alt="" src="images/visa_mc.gif"></td></tr><tr id="cardNumberRow"><td style="width:170px;height:16px">Card Number -</td><td style="width:222px;"><input autocomplete="off" onblur="updateCardNumber()" value="" style="width:200px;" maxlength="20" type="TEXT" id="cardNumber" name="cardNumber"></td></tr><tr id="cardOwnerRow"><td style="width:170px;height:16px;">Card holder +</td><td style="width:222px;"><input onblur="updateCardNumber()" value="" style="width:200px;" maxlength="20" type="TEXT" id="cardNumber" name="cardNumber"></td></tr><tr id="cardOwnerRow"><td style="width:170px;height:16px;">Card holder </td><td style="width:222px;"><input onblur="updateCardHolder()" value="" style="width:200px;" maxlength="50" type="TEXT" id="ccHolder" name="ccHolder"></td></tr><tr id="cpfNumber" style="display: none;"><td style="width:170px;height:16px;"> CPF/CNPJ </td><td style="width:222px;"><input value="" style="width:200px;" maxlength="50" type="TEXT" id="identificationValue" name="identificationValue"><input value="TAXSTATEMENT" name="identificationPaper" type="hidden"></td></tr><tr id="expiryDateRow"><td style="width:170px;height:16px;">Expiration Date</td><td style="width:222px;"><select id="accountExpiryMonth" name="accountExpiryMonth" onchange="expirationDateChanged();" size="1" style="width:100px; "><option value="-">-</option><option value="1">01</option><option value="2">02</option><option value="3">03</option><option value="4">04</option><option value="5">05</option><option value="6">06</option><option value="7">07</option><option value="8">08</option><option value="9">09</option><option value="10">10</option><option value="11">11</option><option value="12">12</option></select><select id="accountExpiryYear" name="accountExpiryYear" onchange="expirationDateChanged();" size="1" style="width:100px; -"><option value="-">-</option><option value="2015">2015</option><option value="2016">2016</option><option value="2017">2017</option><option value="2018">2018</option><option value="2019">2019</option><option value="2020">2020</option><option value="2021">2021</option><option value="2022">2022</option><option value="2023">2023</option><option value="2024">2024</option><option value="2025">2025</option><option value="2026">2026</option></select></td></tr><tr valign="top" id="cvdRow"><td style="width:170px;">Verification Number <span id="verificationcode_mandatory">*</span></td><td style="width:222px;"><input autocomplete="off" onblur="updateCvv()" value="" style="width:100px;" maxlength="4" type="TEXT" id="accountVerification" name="accountVerification"><br><a href="javascript:learnMoreCVD();">Where do I find the verification number?</a></td></tr></tbody></table></td></tr></tbody></table></div></td></tr><tr class="paymentContainer" id="debitCard" style="display: none;"><td class="frm_box"><div name="dcBlock" id="dcBlock"><table><tbody><tr><td><table border="0" id="cardPane"><tbody><tr id="cardTypeRow"><td style="width:170px;height:16px;">Card Brand</td><td style="width:222px;"><select id="accountBrandDropDown" name="accountBrandDropDown" onchange="brandChanged()" style="width:120px;" size="1"> +"><option value="-">-</option><option value="2015">2015</option><option value="2016">2016</option><option value="2017">2017</option><option value="2018">2018</option><option value="2019">2019</option><option value="2020">2020</option><option value="2021">2021</option><option value="2022">2022</option><option value="2023">2023</option><option value="2024">2024</option><option value="2025">2025</option><option value="2026">2026</option></select></td></tr><tr valign="top" id="cvdRow"><td style="width:170px;">Verification Number <span id="verificationcode_mandatory">*</span></td><td style="width:222px;"><input onblur="updateCvv()" value="" style="width:100px;" maxlength="4" type="TEXT" id="accountVerification" name="accountVerification"><br><a href="javascript:learnMoreCVD();">Where do I find the verification number?</a></td></tr></tbody></table></td></tr></tbody></table></div></td></tr><tr class="paymentContainer" id="debitCard" style="display: none;"><td class="frm_box"><div name="dcBlock" id="dcBlock"><table><tbody><tr><td><table border="0" id="cardPane"><tbody><tr id="cardTypeRow"><td style="width:170px;height:16px;">Card Brand</td><td style="width:222px;"><select id="accountBrandDropDown" name="accountBrandDropDown" onchange="brandChanged()" style="width:120px;" size="1"> </select></td></tr><tr id="cardNumberRow"><td style="width:170px;height:16px">Card Number -</td><td style="width:222px;"><input autocomplete="off" onblur="updateCardNumber()" value="" style="width:200px;" maxlength="20" type="TEXT" id="cardNumber" name="cardNumber"></td></tr><tr id="cardOwnerRow"><td style="width:170px;height:16px;">Card holder +</td><td style="width:222px;"><input onblur="updateCardNumber()" value="" style="width:200px;" maxlength="20" type="TEXT" id="cardNumber" name="cardNumber"></td></tr><tr id="cardOwnerRow"><td style="width:170px;height:16px;">Card holder </td><td style="width:222px;"><input onblur="updateCardHolder()" value="" style="width:200px;" maxlength="50" type="TEXT" id="ccHolder" name="ccHolder"></td></tr><tr id="expiryDateRow"><td style="width:170px;height:16px;">Expiration Date</td><td style="width:222px;"><select id="accountExpiryMonth" name="accountExpiryMonth" onchange="expirationDateChanged();" size="1" style="width:100px; "><option value="-">-</option><option value="1">01</option><option value="2">02</option><option value="3">03</option><option value="4">04</option><option value="5">05</option><option value="6">06</option><option value="7">07</option><option value="8">08</option><option value="9">09</option><option value="10">10</option><option value="11">11</option><option value="12">12</option></select><select id="accountExpiryYear" name="accountExpiryYear" onchange="expirationDateChanged();" size="1" style="width:100px; -"><option value="-">-</option><option value="2015">2015</option><option value="2016">2016</option><option value="2017">2017</option><option value="2018">2018</option><option value="2019">2019</option><option value="2020">2020</option><option value="2021">2021</option><option value="2022">2022</option><option value="2023">2023</option><option value="2024">2024</option><option value="2025">2025</option><option value="2026">2026</option></select></td></tr><tr valign="top" id="cvdRow"><td style="width:170px;">Verification Number <span id="verificationcode_mandatory">*</span></td><td style="width:222px;"><input autocomplete="off" onblur="updateCvv()" value="" style="width:100px;" maxlength="4" type="TEXT" id="accountVerification" name="accountVerification"><br><a href="javascript:learnMoreCVD();">Where do I find the verification number?</a></td></tr></tbody></table></td></tr></tbody></table></div></td></tr><tr class="paymentContainer" id="mergedCreditDebitCard" style="display: none;"><td class="frm_box"><div name="mergedCcDcBlock" id="mergedCcDcBlock"><table><tbody><tr><td><table border="0" id="cardPane"><tbody><tr id="cardTypeRow"><td style="width:170px;height:16px;">Card Brand</td><td style="width:222px;"><select id="accountBrandDropDown" name="accountBrandDropDown" onchange="brandChanged()" style="width:120px;" size="1"><option title="Visa" selected="" value="VISA">Visa</option> +"><option value="-">-</option><option value="2015">2015</option><option value="2016">2016</option><option value="2017">2017</option><option value="2018">2018</option><option value="2019">2019</option><option value="2020">2020</option><option value="2021">2021</option><option value="2022">2022</option><option value="2023">2023</option><option value="2024">2024</option><option value="2025">2025</option><option value="2026">2026</option></select></td></tr><tr valign="top" id="cvdRow"><td style="width:170px;">Verification Number <span id="verificationcode_mandatory">*</span></td><td style="width:222px;"><input onblur="updateCvv()" value="" style="width:100px;" maxlength="4" type="TEXT" id="accountVerification" name="accountVerification"><br><a href="javascript:learnMoreCVD();">Where do I find the verification number?</a></td></tr></tbody></table></td></tr></tbody></table></div></td></tr><tr class="paymentContainer" id="mergedCreditDebitCard" style="display: none;"><td class="frm_box"><div name="mergedCcDcBlock" id="mergedCcDcBlock"><table><tbody><tr><td><table border="0" id="cardPane"><tbody><tr id="cardTypeRow"><td style="width:170px;height:16px;">Card Brand</td><td style="width:222px;"><select id="accountBrandDropDown" name="accountBrandDropDown" onchange="brandChanged()" style="width:120px;" size="1"><option title="Visa" selected="" value="VISA">Visa</option> </select><img alt="" src="images/visa_mc.gif"></td></tr><tr id="cardNumberRow"><td style="width:170px;height:16px">Card Number -</td><td style="width:222px;"><input autocomplete="off" onblur="updateCardNumber()" value="" style="width:200px;" maxlength="20" type="TEXT" id="cardNumber" name="cardNumber"></td></tr><tr id="cardOwnerRow"><td style="width:170px;height:16px;">Card holder +</td><td style="width:222px;"><input onblur="updateCardNumber()" value="" style="width:200px;" maxlength="20" type="TEXT" id="cardNumber" name="cardNumber"></td></tr><tr id="cardOwnerRow"><td style="width:170px;height:16px;">Card holder </td><td style="width:222px;"><input onblur="updateCardHolder()" value="" style="width:200px;" maxlength="50" type="TEXT" id="ccHolder" name="ccHolder"></td></tr><tr id="expiryDateRow"><td style="width:170px;height:16px;">Expiration Date</td><td style="width:222px;"><select id="accountExpiryMonth" name="accountExpiryMonth" onchange="expirationDateChanged();" size="1" style="width:100px; "><option value="-">-</option><option value="1">01</option><option value="2">02</option><option value="3">03</option><option value="4">04</option><option value="5">05</option><option value="6">06</option><option value="7">07</option><option value="8">08</option><option value="9">09</option><option value="10">10</option><option value="11">11</option><option value="12">12</option></select><select id="accountExpiryYear" name="accountExpiryYear" onchange="expirationDateChanged();" size="1" style="width:100px; -"><option value="-">-</option><option value="2015">2015</option><option value="2016">2016</option><option value="2017">2017</option><option value="2018">2018</option><option value="2019">2019</option><option value="2020">2020</option><option value="2021">2021</option><option value="2022">2022</option><option value="2023">2023</option><option value="2024">2024</option><option value="2025">2025</option><option value="2026">2026</option></select></td></tr><tr valign="top" id="cvdRow"><td style="width:170px;">Verification Number <span id="verificationcode_mandatory">*</span></td><td style="width:222px;"><input autocomplete="off" onblur="updateCvv()" value="" style="width:100px;" maxlength="4" type="TEXT" id="accountVerification" name="accountVerification"><br><a href="javascript:learnMoreCVD();">Where do I find the verification number?</a></td></tr></tbody></table></td></tr></tbody></table></div></td></tr><tr class="paymentContainer" id="directDebit" style="display: none;"><td class="frm_box"><div id="ddBlock" name="ddBlock"><table><tbody><tr><td><table border="0" cellspacing="0" cellpadding="0"><tbody><tr id="bankAccountCountryRow"><td style="width:170px;height:16px;">Country</td><td style="width:222px;"><select id="accountCountry" name="accountCountry" onchange="ddCountryChanged()" style="width:200px;" size="1"> +"><option value="-">-</option><option value="2015">2015</option><option value="2016">2016</option><option value="2017">2017</option><option value="2018">2018</option><option value="2019">2019</option><option value="2020">2020</option><option value="2021">2021</option><option value="2022">2022</option><option value="2023">2023</option><option value="2024">2024</option><option value="2025">2025</option><option value="2026">2026</option></select></td></tr><tr valign="top" id="cvdRow"><td style="width:170px;">Verification Number <span id="verificationcode_mandatory">*</span></td><td style="width:222px;"><input onblur="updateCvv()" value="" style="width:100px;" maxlength="4" type="TEXT" id="accountVerification" name="accountVerification"><br><a href="javascript:learnMoreCVD();">Where do I find the verification number?</a></td></tr></tbody></table></td></tr></tbody></table></div></td></tr><tr class="paymentContainer" id="directDebit" style="display: none;"><td class="frm_box"><div id="ddBlock" name="ddBlock"><table><tbody><tr><td><table border="0" cellspacing="0" cellpadding="0"><tbody><tr id="bankAccountCountryRow"><td style="width:170px;height:16px;">Country</td><td style="width:222px;"><select id="accountCountry" name="accountCountry" onchange="ddCountryChanged()" style="width:200px;" size="1"> </select></td></tr><tr id="bankAccountOwnerRow"><td style="width:170px;height:16px;">Account holder @@ -60,10 +60,10 @@ </select><span id="klarnaLogo"><img style="display:none" src="images/klarna_invoice.png" class="klarnaLogo" id="klarnaInvoiceLogo"><img style="display:none" src="images/klarna_installments.png" class="klarnaLogo" id="klarnaInstallmentsLogo"></span></td></tr><tr style="display:none" id="klarnaTerms"><td style="width:170px;height:16px;"></td><td style="width:222px;"><a id="klarnaInvoiceTerms" href="https://cdn.klarna.com/1.0/shared/content/legal/terms/EID//invoice?fee=0" onclick="window.open('https://cdn.klarna.com/1.0/shared/content/legal/terms/EID//invoice?fee=0','villkor_','width=600,height=550,scrollbars=no'); return false;"> -Klarna Invoice +Klarna Invoice </a><a id="klarnaInstallmentsTerms" href="https://cdn.klarna.com/1.0/shared/content/legal/terms/EID//account?fee=0" onclick="window.open('https://cdn.klarna.com/1.0/shared/content/legal/terms/EID//account?fee=0','villkor_','width=600,height=550,scrollbars=no'); return false;"> -Klarna Account +Klarna Account </a></td></tr><tr id="vaIdRow"><td style="width:170px;height:16px;">Username / Id </td><td style="width:222px;"><input value="" style="width:200px;" maxlength="100" type="TEXT" id="virtualAccountId" name="virtualAccountId"></td></tr></tbody></table></div></td></tr><tr class="paymentContainer" id="userAccount" style="display: none;"><td class="frm_box"><div id="uaBlock" name="uaBlock"><table border="0"><tbody><tr id="uaBrandRow"><td style="width:170px;height:16px;">Provider </td><td style="width:222px;"><select id="userAccountBrand" name="userAccountBrand" onchange="uaBrandChanged()" style="width:200px;" size="1"> @@ -75,7 +75,7 @@ </select></td></tr><tr id="otInstituteBlock" style="display: none;"><td style="width:170px;height:16px;">Bank</td><td style="width:222px;"><select size="1" style="width:200px;" id="onlineTransferInstitute" name="onlineTransferInstitute"><option value="ACHSECUR">ACHSecur</option></select></td></tr><tr id="otAccountBlock"><td style="width:170px;height:16px;">Account No. -</td><td style="width:222px;"><input autocomplete="off" value="" style="width:200px;" maxlength="50" type="TEXT" id="otAccountNumber" onblur="otAccountNumberChanged()" name="otAccountNumber"></td></tr><tr id="otBankcodeBlock"><td style="width:170px;height:16px;">Bank Code +</td><td style="width:222px;"><input value="" style="width:200px;" maxlength="50" type="TEXT" id="otAccountNumber" onblur="otAccountNumberChanged()" name="otAccountNumber"></td></tr><tr id="otBankcodeBlock"><td style="width:170px;height:16px;">Bank Code </td><td style="width:222px;"><input value="" style="width:200px;" maxlength="50" type="TEXT" onblur="otBankCodeChanged()" id="otBankCode" name="otBankCode"></td></tr></tbody></table></div></td></tr></tbody></table></td></tr><tr id="notMandatoryRow"><td>* Optional Information</td></tr><tr height="5px" id="spacer4"><td></td></tr></tbody></table><table width="100%" border="0"><tbody><tr></tr><tr><td>
diff --git a/components/test/data/autofill/heuristics/input/130_bug_465576.html b/components/test/data/autofill/heuristics/input/130_bug_465576.html index 809a019..f4d59198 100644 --- a/components/test/data/autofill/heuristics/input/130_bug_465576.html +++ b/components/test/data/autofill/heuristics/input/130_bug_465576.html
@@ -40,7 +40,7 @@ <div class="js-cardInfoEdit"> <label class="nsg-form--label" for="creditCardNumber">Card Number<b class="nsg-form--required"> *</b></label> <div class="col-2"> - <input class="nsg-form--input" placeholder="" id="creditCardNumber" name="creditCardNumber" type="number" min="0" inputmode="numeric" pattern="[0-9]*" maxlength="19" value="" autocomplete="off"> + <input class="nsg-form--input" placeholder="" id="creditCardNumber" name="creditCardNumber" type="number" min="0" inputmode="numeric" pattern="[0-9]*" maxlength="19" value=""> </div> </div> </div> @@ -100,7 +100,7 @@ <p class="cvNumberHelp"> <a class="cardSecurityModal" href="#">Where do I find this?</a> </p> - <input class="nsg-form--input" autocomplete="off" autocorrect="off" placeholder="" type="number" min="0" inputmode="numeric" pattern="[0-9]*" maxlength="6" id="cvNumber" name="cvNumber" value=""> + <input class="nsg-form--input" autocorrect="off" placeholder="" type="number" min="0" inputmode="numeric" pattern="[0-9]*" maxlength="6" id="cvNumber" name="cvNumber" value=""> </div> <div class="form-row checkout"> <div class="col">
diff --git a/components/test/data/autofill/heuristics/input/131_bug_465587.html b/components/test/data/autofill/heuristics/input/131_bug_465587.html index fa2e0fc..e9840c1 100644 --- a/components/test/data/autofill/heuristics/input/131_bug_465587.html +++ b/components/test/data/autofill/heuristics/input/131_bug_465587.html
@@ -60,19 +60,19 @@ <label for="user_card_name" class="large">Credit Card Type</label> <input name="_D:/bodybuilding/commerce/order/purchase/CardPaymentInfoFormHandler.billingInfo.creditCard.creditCardType" value=" " type="hidden"><select id="creditCardType" name="/bodybuilding/commerce/order/purchase/CardPaymentInfoFormHandler.billingInfo.creditCard.creditCardType" class="validate"><option value="discover">Discover</option><option value="americanExpress">American Express</option><option value="masterCard">MasterCard</option><option value="jcb">JCB</option><option selected="selected" value="visa">Visa</option></select><label for="user_card_holder_name" class="large">Cardholder Name</label> <input id="orbitalId" name="/bodybuilding/commerce/order/purchase/CardPaymentInfoFormHandler.billingInfo.creditCard.orbitalProfileId" value="" class="validate" type="hidden"><input name="_D:/bodybuilding/commerce/order/purchase/CardPaymentInfoFormHandler.billingInfo.creditCard.orbitalProfileId" value=" " type="hidden"><div class="status-div"> - <input id="cardHolderName" maxlength="40" name="cardholder" value="" class="validate" autocomplete="off" type="text"><input name="_D:cardholder" value=" " type="hidden"></div> + <input id="cardHolderName" maxlength="40" name="cardholder" value="" class="validate" type="text"><input name="_D:cardholder" value=" " type="hidden"></div> <input name="/bodybuilding/commerce/order/purchase/CardPaymentInfoFormHandler.validateSuccessURL" value="/store/commerce/billing/validateCart.jsp" class="validate" type="hidden"><input name="_D:/bodybuilding/commerce/order/purchase/CardPaymentInfoFormHandler.validateSuccessURL" value=" " type="hidden"><input name="/bodybuilding/commerce/order/purchase/CardPaymentInfoFormHandler.validateErrorURL" value="/store/commerce/billing/validateCart.jsp" class="validate" type="hidden"><input name="_D:/bodybuilding/commerce/order/purchase/CardPaymentInfoFormHandler.validateErrorURL" value=" " type="hidden"><div class="status-div"> <label for="user_card_number" class="large"> Credit Card Number</label> - <span class="border-wrapper"><input style="padding-top: 2px;" autocomplete="off" maxlength="16" id="cardnumber" data-name="cardnumber" type="text"></span> + <span class="border-wrapper"><input style="padding-top: 2px;" maxlength="16" id="cardnumber" data-name="cardnumber" type="text"></span> </div> <label for="user_card_expiration_month" class="large">Expiration Date</label> <div class="status-div"> <input name="_D:/bodybuilding/commerce/order/purchase/CardPaymentInfoFormHandler.billingInfo.creditCard.expirationMonth" value=" " type="hidden"><select id="creditCardMonth" name="/bodybuilding/commerce/order/purchase/CardPaymentInfoFormHandler.billingInfo.creditCard.expirationMonth" class="cc-ex-select validate"><option value="01">01</option><option value="02">02</option><option value="03">03</option><option value="04">04</option><option value="05">05</option><option value="06">06</option><option value="07">07</option><option value="08">08</option><option value="09">09</option><option value="10">10</option><option value="11">11</option><option value="12">12</option></select><input name="_D:/bodybuilding/commerce/order/purchase/CardPaymentInfoFormHandler.billingInfo.creditCard.expirationYear" value=" " type="hidden"><select id="creditCardYear" name="/bodybuilding/commerce/order/purchase/CardPaymentInfoFormHandler.billingInfo.creditCard.expirationYear" class="cc-ex-select validate"><option value="2015">2015</option><option value="2016">2016</option><option value="2017">2017</option><option value="2018">2018</option><option value="2019">2019</option><option value="2020">2020</option><option value="2021">2021</option><option value="2022">2022</option><option value="2023">2023</option><option value="2024">2024</option><option value="2025">2025</option></select></div> <div class="status-div"> <label for="user_card_cvv2" class="large">CVC/CVV</label> - <span class="border-wrapper"><input id="secureid" type="text" autocomplete="off" class="dontclear" data-name="sid"></span> + <span class="border-wrapper"><input id="secureid" type="text" class="dontclear" data-name="sid"></span> </div> <div class="cvv_icon"></div> <p class="cvv-help-text"><em class="bb-gray5">Please enter the CVC/CVV code on the back of your card to ensure security.</em></p>
diff --git a/components/test/data/autofill/heuristics/input/132_bug_469012.html b/components/test/data/autofill/heuristics/input/132_bug_469012.html index 3830bb4..2ac2f7b 100644 --- a/components/test/data/autofill/heuristics/input/132_bug_469012.html +++ b/components/test/data/autofill/heuristics/input/132_bug_469012.html
@@ -174,7 +174,7 @@ <label for="postal_code"><span id="zip_title_span">ZIP Code</span><span class="requiredText">*</span> </label> - <input type="text" name="zip" id="postal_code" size="35" autocapitalize="off" autocomplete="off"> + <input type="text" name="zip" id="postal_code" size="35" autocapitalize="off"> </div> <div class="formline"> <label for="country">Country
diff --git a/components/test/data/autofill/heuristics/input/133_bug_469472.html b/components/test/data/autofill/heuristics/input/133_bug_469472.html index 9609ee7..f581e34 100644 --- a/components/test/data/autofill/heuristics/input/133_bug_469472.html +++ b/components/test/data/autofill/heuristics/input/133_bug_469472.html
@@ -3,7 +3,7 @@ <div id="fieldrowCCNumber" class="opened"> <p class="group"> <label for="cc_number"><span class="labelText"><span class="label" id="labelChange">Debit or Prepaid gift card number</span></span></label> - <span class="field restricted"><input type="text" id="cc_number" autocomplete="off" maxlength="19" class="restricted large" name="cc_number" value=""></span> + <span class="field restricted"><input type="text" id="cc_number" maxlength="19" class="restricted large" name="cc_number" value=""></span> </p> <p id="prepaidgiftMsgGroup" class="group hide"> <span class="prepaidAlertContainer"> @@ -70,7 +70,7 @@ <span class="accessAid">For American Express, it's the four digits on the front of the card.For MasterCard, Visa or Discover, it's the last three digits in the signature area on the back of your card.</span> </a> </label> - <span class="field restricted"><input type="text" id="cvv2_number" autocomplete="off" maxlength="4" class="restricted small" name="cvv2_number" value=""></span> + <span class="field restricted"><input type="text" id="cvv2_number" maxlength="4" class="restricted small" name="cvv2_number" value=""></span> </p> <div class="balloonCallout jsHide accessAid" id="cvv2_number_panel"> <p class="amexCSCHelpTxt show">
diff --git a/components/test/data/autofill/heuristics/input/135_bug_471831.html b/components/test/data/autofill/heuristics/input/135_bug_471831.html index e976141..7e34344 100644 --- a/components/test/data/autofill/heuristics/input/135_bug_471831.html +++ b/components/test/data/autofill/heuristics/input/135_bug_471831.html
@@ -38,7 +38,7 @@ <select id="cc-exp-month" x-autocompletetype="cc-exp-month" autocompletetype="cc-exp-month" autocorrect="off" spellcheck="off" autocapitalize="off" tabindex="-1" style="position: absolute; left: -10000px;"><option>Month</option><option value="01">January</option><option value="02">February</option><option value="03">March</option><option value="04">April</option><option value="05">May</option><option value="06">June</option><option value="07">July</option><option value="08">August</option><option value="09">September</option><option value="10">October</option><option value="11">November</option><option value="12">December</option></select> </div> <div class="cardCVCInput input right bottom"> - <input class="control" id="cc-csc" type="tel" autocomplete="off" autocorrect="off" spellcheck="off" autocapitalize="off" placeholder="CVC" maxlength="4"> + <input class="control" id="cc-csc" type="tel" autocorrect="off" spellcheck="off" autocapitalize="off" placeholder="CVC" maxlength="4"> <div class="svg icon" style="width: 30px; height: 30px;"> </div> </div>
diff --git a/components/test/data/autofill/heuristics/input/136_bug_497850.html b/components/test/data/autofill/heuristics/input/136_bug_497850.html index a49d730..606d3af 100644 --- a/components/test/data/autofill/heuristics/input/136_bug_497850.html +++ b/components/test/data/autofill/heuristics/input/136_bug_497850.html
@@ -98,7 +98,7 @@ <td colspan="2"> <div class="formlistitem"> <span id="ctl01_ctl00_MainContentRegion_MainRegion_ctl00_ipcPayment_lblCcNumber" class="formlabel">Card number</span><br> - <input name="ctl01$ctl00$MainContentRegion$MainRegion$ctl00$ipcPayment$txtCcNumber" type="text" id="ctl01_ctl00_MainContentRegion_MainRegion_ctl00_ipcPayment_txtCcNumber" class="textbox" autocomplete="off"> + <input name="ctl01$ctl00$MainContentRegion$MainRegion$ctl00$ipcPayment$txtCcNumber" type="text" id="ctl01_ctl00_MainContentRegion_MainRegion_ctl00_ipcPayment_txtCcNumber" class="textbox"> </div> </td> </tr> @@ -106,7 +106,7 @@ <td> <div class="formlistitem"> <span id="ctl01_ctl00_MainContentRegion_MainRegion_ctl00_ipcPayment_lblCcHolder" class="formlabel">Card holder name</span><br> - <input name="ctl01$ctl00$MainContentRegion$MainRegion$ctl00$ipcPayment$txtCcHolder" type="text" id="ctl01_ctl00_MainContentRegion_MainRegion_ctl00_ipcPayment_txtCcHolder" class="textbox" autocomplete="off"> + <input name="ctl01$ctl00$MainContentRegion$MainRegion$ctl00$ipcPayment$txtCcHolder" type="text" id="ctl01_ctl00_MainContentRegion_MainRegion_ctl00_ipcPayment_txtCcHolder" class="textbox"> </div> </td> <td> @@ -155,7 +155,7 @@ <div id="ctl01_ctl00_MainContentRegion_MainRegion_ctl00_ipcPayment_pnlCcCvc" class="formlistitem"> <span id="ctl01_ctl00_MainContentRegion_MainRegion_ctl00_ipcPayment_lblCcCvc" class="formlabel">Verification Code (CVC)</span><br> - <input name="ctl01$ctl00$MainContentRegion$MainRegion$ctl00$ipcPayment$txtCcCvc" type="text" maxlength="4" id="ctl01_ctl00_MainContentRegion_MainRegion_ctl00_ipcPayment_txtCcCvc" class="textboxcvc" autocomplete="off"> <a href="#" onclick="InfoWindow = window.open('/us/infourl/infoidnorwegiancvcinfo/', 'InfoWindow', 'width=600,height=750,resizable=1,scrollbars=1,location=0,menubar=0,status=0,toolbar=0'); InfoWindow.focus(); return false;">What is CVC? >></a> + <input name="ctl01$ctl00$MainContentRegion$MainRegion$ctl00$ipcPayment$txtCcCvc" type="text" maxlength="4" id="ctl01_ctl00_MainContentRegion_MainRegion_ctl00_ipcPayment_txtCcCvc" class="textboxcvc"> <a href="#" onclick="InfoWindow = window.open('/us/infourl/infoidnorwegiancvcinfo/', 'InfoWindow', 'width=600,height=750,resizable=1,scrollbars=1,location=0,menubar=0,status=0,toolbar=0'); InfoWindow.focus(); return false;">What is CVC? >></a> </div>
diff --git a/components/test/data/autofill/heuristics/input/137_bug_555010.html b/components/test/data/autofill/heuristics/input/137_bug_555010.html index bf026a09..3afb021 100644 --- a/components/test/data/autofill/heuristics/input/137_bug_555010.html +++ b/components/test/data/autofill/heuristics/input/137_bug_555010.html
@@ -1,6 +1,6 @@ <HTML> <HEAD> - <meta name="viewport" content="width=320, user-scalable=no, initial-scale=1.0, maximum-scale=1.0" /> + <meta name="viewport" content="width=320, user-scalable=no, initial-scale=1.0, maximum-scale=1.0" /> <meta http-equiv="x-ua-compatible" content="IE=edge" > <title>Office Supplies, Technology, Ink Much More | Staples - add checkout tag because url is inaccessible from test</title> <meta name="title" content="Office Supplies, Technology, Ink Much More | Staples" /> @@ -79,7 +79,7 @@ <div class="cls_skClearBut"></div> </div> <div class="cls_skCOShipAptBldg"> - <input id="id_skCOShipAptBldg" class="cls_skInputTxt cls_skInputOptionalTxt cls_skApartment scInput" scvalue="apartment" scinput="input" fieldtype="aptbldg" placeholder="Apt/Bldg (optional)" event="shipping apt/suite" tabindex="3" maxlength="35" autocomplete="off" type="text"> + <input id="id_skCOShipAptBldg" class="cls_skInputTxt cls_skInputOptionalTxt cls_skApartment scInput" scvalue="apartment" scinput="input" fieldtype="aptbldg" placeholder="Apt/Bldg (optional)" event="shipping apt/suite" tabindex="3" maxlength="35" type="text"> <div class="cls_skClearBut"></div> </div> </div> @@ -91,7 +91,7 @@ <div class="cls_skStorePickUpBtnTxt"></div> </div> <div id="id_skShipInputPhone" class="cls_skInput"> - <input id="id_skCOPhoneno" class="cls_skInputTxt cls_skCOPhoneno cls_skPhoneNo scTrack scInput" sctype="scInput" scvalue="editphone" scinput="input" maxlength="16" fieldtype="phnumber" placeholder="Phone" event="shipping phone number" tabindex="4" autocomplete="off" type="tel"> + <input id="id_skCOPhoneno" class="cls_skInputTxt cls_skCOPhoneno cls_skPhoneNo scTrack scInput" sctype="scInput" scvalue="editphone" scinput="input" maxlength="16" fieldtype="phnumber" placeholder="Phone" event="shipping phone number" tabindex="4" type="tel"> <div class="cls_skClearBut"></div> </div> <div id="id_skShipInputEmail" class="cls_skInput"> @@ -104,13 +104,13 @@ <div class="cls_skCrditCardImg"></div> <div class="cls_skCOCreditCardCont"> <label class="cls_skAstrickSymbol">*</label> - <input id="id_skCOCreditCard" class="cls_skInputTxt cls_skCreditCardNo cls_skCreditCard scTrack scInput" sctype="scInput" scvalue="creditcard" scinput="input" maxlength="19" fieldtype="cardNumber" event="card number" placeholder="1234 5647 8901 2345" tabindex="6" name="cardNumber" autocomplete="off" type="tel"> + <input id="id_skCOCreditCard" class="cls_skInputTxt cls_skCreditCardNo cls_skCreditCard scTrack scInput" sctype="scInput" scvalue="creditcard" scinput="input" maxlength="19" fieldtype="cardNumber" event="card number" placeholder="1234 5647 8901 2345" tabindex="6" name="cardNumber" type="tel"> </div> <div class="cls_skCOCreditYrMnthCont"> - <input class="cls_skInputTxt cls_skCreditYrMth cls_skCreditCard scInput" scvalue="month/year" scinput="input" fieldtype="mnthYr" placeholder="EXP" event="expire month/year" tabindex="7" name="expirationMonth" autocomplete="off" type="tel"> + <input class="cls_skInputTxt cls_skCreditYrMth cls_skCreditCard scInput" scvalue="month/year" scinput="input" fieldtype="mnthYr" placeholder="EXP" event="expire month/year" tabindex="7" name="expirationMonth" type="tel"> </div> <div class="cls_skCOCreditCcv"> - <input class="cls_skInputTxt cls_skCreditCcv cls_skCreditCard scInput" scvalue="CVV" scinput="input" maxlength="4" fieldtype="cvv" placeholder="CVV" event="card id" tabindex="8" name="cvv" autocomplete="off" type="tel"> + <input class="cls_skInputTxt cls_skCreditCcv cls_skCreditCard scInput" scvalue="CVV" scinput="input" maxlength="4" fieldtype="cvv" placeholder="CVV" event="card id" tabindex="8" name="cvv" type="tel"> </div> <div class="cls_skClearBut"></div> </div> @@ -138,11 +138,11 @@ <div id="id_skBillInputAddress" class="cls_skInput"> <div class="cls_skAddressWrapper"> <div class="cls_skCOShipAddress cls_skAddressCont"> - <input id="id_skCOShipAddress" class="cls_skInputTxt cls_skAddress cls_skBillToAddress scTrack scInput" sctype="scInput" scvalue="baddress" scinput="input" fieldtype="address" placeholder="Billing Address" event="billing address" tabindex="10" maxlength="128" autocomplete="off" type="text"> + <input id="id_skCOShipAddress" class="cls_skInputTxt cls_skAddress cls_skBillToAddress scTrack scInput" sctype="scInput" scvalue="baddress" scinput="input" fieldtype="address" placeholder="Billing Address" event="billing address" tabindex="10" maxlength="128" type="text"> <div class="cls_skClearBut"></div> </div> <div class="cls_skCOShipAptBldg"> - <input id="id_skCOShipAptBldg" class="cls_skInputTxt cls_skInputOptionalTxt cls_skApartment scInput" scvalue="apartment" scinput="input" fieldtype="aptbldg" placeholder="Apt/Bldg (optional)" event="billing apt/suite" tabindex="11" maxlength="35" autocomplete="off" type="text"> + <input id="id_skCOShipAptBldg" class="cls_skInputTxt cls_skInputOptionalTxt cls_skApartment scInput" scvalue="apartment" scinput="input" fieldtype="aptbldg" placeholder="Apt/Bldg (optional)" event="billing apt/suite" tabindex="11" maxlength="35" type="text"> <div class="cls_skClearBut"></div> </div> </div> @@ -167,11 +167,11 @@ </div> <div class="cls_skInput"> <div class="cls_skCOShipAddress cls_skAddressCont"> - <input id="id_skCOShipAddress" class="cls_skInputTxt cls_skAddress scTrack scInput" scvalue="address" scinput="input" fieldtype="address" placeholder="Address" event="shipping address" tabindex="10" maxlength="128" autocomplete="off" type="text"> + <input id="id_skCOShipAddress" class="cls_skInputTxt cls_skAddress scTrack scInput" scvalue="address" scinput="input" fieldtype="address" placeholder="Address" event="shipping address" tabindex="10" maxlength="128" type="text"> <div class="cls_skClearBut"></div> </div> <div class="cls_skCOShipAptBldg"> - <input id="id_skCOShipAptBldg" class="cls_skInputTxt cls_skInputOptionalTxt cls_skApartment scInput" scvalue="apartment" scinput="input" fieldtype="aptbldg" placeholder="Apt/Bldg (optional)" event="shipping apt/suite" tabindex="11" maxlength="35" autocomplete="off" type="text"> + <input id="id_skCOShipAptBldg" class="cls_skInputTxt cls_skInputOptionalTxt cls_skApartment scInput" scvalue="apartment" scinput="input" fieldtype="aptbldg" placeholder="Apt/Bldg (optional)" event="shipping apt/suite" tabindex="11" maxlength="35" type="text"> <div class="cls_skClearBut"></div> </div> </div> @@ -195,13 +195,13 @@ <div class="cls_skCrditCardImg"></div> <div class="cls_skCOCreditCardCont"> <label class="cls_skAstrickSymbol">*</label> - <input id="id_skManageCreditCard" class="cls_skInputTxt cls_skCreditCardNo cls_skCreditCard scTrack scInput" scvalue="editcardno" scinput="input" maxlength="19" fieldtype="cardNumber" placeholder="1234 5647 8901 2345" tabindex="6" name="cardNumber" autocomplete="off" type="tel"> + <input id="id_skManageCreditCard" class="cls_skInputTxt cls_skCreditCardNo cls_skCreditCard scTrack scInput" scvalue="editcardno" scinput="input" maxlength="19" fieldtype="cardNumber" placeholder="1234 5647 8901 2345" tabindex="6" name="cardNumber" type="tel"> </div> <div class="cls_skCOCreditYrMnthCont"> - <input class="cls_skInputTxt cls_skCreditYrMth cls_skCreditCard scInput" scvalue="month/year" scinput="input" fieldtype="mnthYr" placeholder="EXP" tabindex="7" name="expirationMonth" autocomplete="off" type="tel"> + <input class="cls_skInputTxt cls_skCreditYrMth cls_skCreditCard scInput" scvalue="month/year" scinput="input" fieldtype="mnthYr" placeholder="EXP" tabindex="7" name="expirationMonth" type="tel"> </div> <div class="cls_skCOCreditCcv"> - <input class="cls_skInputTxt cls_skCreditCcv cls_skCreditCard scInput" scvalue="CVV" scinput="input" maxlength="4" fieldtype="cvv" placeholder="CVV" tabindex="8" name="cvv" autocomplete="off" type="tel"> + <input class="cls_skInputTxt cls_skCreditCcv cls_skCreditCard scInput" scvalue="CVV" scinput="input" maxlength="4" fieldtype="cvv" placeholder="CVV" tabindex="8" name="cvv" type="tel"> </div> <div class="cls_skClearBut"></div> </div> @@ -220,7 +220,7 @@ <div class="cls_skClearBut"></div> </div> <div id="id_skAltPUInputPhone" class="cls_skInput"> - <input id="id_skAltPUPhoneno" class="cls_skInputTxt cls_skCOPhoneno cls_skPhoneNo scInput" scvalue="phone" scinput="input" maxlength="16" fieldtype="phnumber" placeholder="Phone" tabindex="2" autocomplete="off" type="tel"> + <input id="id_skAltPUPhoneno" class="cls_skInputTxt cls_skCOPhoneno cls_skPhoneNo scInput" scvalue="phone" scinput="input" maxlength="16" fieldtype="phnumber" placeholder="Phone" tabindex="2" type="tel"> <div class="cls_skClearBut"></div> </div> <div id="id_skAltPUInputEmail" class="cls_skInput">
diff --git a/components/test/data/autofill/heuristics/input/138_cc_checkout_united.com.html b/components/test/data/autofill/heuristics/input/138_cc_checkout_united.com.html index 883ae9c0..05adb2f 100644 --- a/components/test/data/autofill/heuristics/input/138_cc_checkout_united.com.html +++ b/components/test/data/autofill/heuristics/input/138_cc_checkout_united.com.html
@@ -2,7 +2,7 @@ <div id="divCard0" style="display:"> <div class="form-row"> - <div class="form-group card-type"><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="CreditCardViewModels[0].CardTypeCode" data-valmsg-replace="true"></span><div class="selector fixedWidth" id="uniform-CreditCardViewModels_0__CardTypeCode"><span aria-hidden="true" style="-webkit-user-select: none;"></span><label class="ifl" for="CreditCardViewModels_0__CardTypeCode" style="opacity: 1;">Select card type<em aria-hidden="true" class="rqrd">*</em></label><select aria-label="Select card type" aria-required="true" autocomplete="off" data-val="true" data-val-required="Please select a Card type.<!--EC:V2-->" id="CreditCardViewModels_0__CardTypeCode" name="CreditCardViewModels[0].CardTypeCode" class="preproc"><option selected="selected" value=""></option> + <div class="form-group card-type"><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="CreditCardViewModels[0].CardTypeCode" data-valmsg-replace="true"></span><div class="selector fixedWidth" id="uniform-CreditCardViewModels_0__CardTypeCode"><span aria-hidden="true" style="-webkit-user-select: none;"></span><label class="ifl" for="CreditCardViewModels_0__CardTypeCode" style="opacity: 1;">Select card type<em aria-hidden="true" class="rqrd">*</em></label><select aria-label="Select card type" aria-required="true" data-val="true" data-val-required="Please select a Card type.<!--EC:V2-->" id="CreditCardViewModels_0__CardTypeCode" name="CreditCardViewModels[0].CardTypeCode" class="preproc"><option selected="selected" value=""></option> <option value="VI">MileagePlus Visa</option> <option value="VI">Visa</option> <option value="JC">JCB</option> @@ -14,8 +14,8 @@ </select></div></div> </div> <div class="form-row"> - <div class="form-group card-number"><label class="ifl" for="CreditCardViewModels_0__CardNumber">Card number<em aria-hidden="true" class="rqrd">*</em></label><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="CreditCardViewModels[0].CardNumber" data-valmsg-replace="true"></span><input aria-required="true" autocomplete="off" data-privacy="no-capture" data-val="true" data-val-length="The field Card number must be a string with a maximum length of 20." data-val-length-max="20" data-val-regex="Please provide a valid debit or credit card number.<!--EC:CC98-->" data-val-regex-pattern="[13456]{1}[0-9 ]{1,}" data-val-required="Please provide a valid debit or credit card number.<!--EC:CC98-->" id="CreditCardViewModels_0__CardNumber" maxlength="20" name="CreditCardViewModels[0].CardNumber" type="text" value=""></div> - + <div class="form-group card-number"><label class="ifl" for="CreditCardViewModels_0__CardNumber">Card number<em aria-hidden="true" class="rqrd">*</em></label><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="CreditCardViewModels[0].CardNumber" data-valmsg-replace="true"></span><input aria-required="true" data-privacy="no-capture" data-val="true" data-val-length="The field Card number must be a string with a maximum length of 20." data-val-length-max="20" data-val-regex="Please provide a valid debit or credit card number.<!--EC:CC98-->" data-val-regex-pattern="[13456]{1}[0-9 ]{1,}" data-val-required="Please provide a valid debit or credit card number.<!--EC:CC98-->" id="CreditCardViewModels_0__CardNumber" maxlength="20" name="CreditCardViewModels[0].CardNumber" type="text" value=""></div> + <input type="text" class="hidden"><input type="password" class="hidden"> <input id="CreditCardViewModels_0__EncryptedCardNumber" name="CreditCardViewModels[0].EncryptedCardNumber" type="hidden" value=""> <input id="CreditCardViewModels_0__CardNumberLast4Digits" name="CreditCardViewModels[0].CardNumberLast4Digits" type="hidden" value=""> @@ -24,7 +24,7 @@ <input id="CreditCardViewModels_0__ErrorNumber" name="CreditCardViewModels[0].ErrorNumber" type="hidden" value=""> </div> <div class="form-row"> - <div class="form-group date-month"><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="CreditCardViewModels[0].ExpMonth" data-valmsg-replace="true"></span><div class="selector fixedWidth" id="uniform-CreditCardViewModels_0__ExpMonth"><span aria-hidden="true" style="-webkit-user-select: none;"></span><label class="ifl" for="CreditCardViewModels_0__ExpMonth">Expiration month<em aria-hidden="true" class="rqrd">*</em></label><select aria-label="Expiration month" aria-required="true" autocomplete="off" data-val="true" data-val-number="The field Expiration month must be a number." data-val-required="Please select an Expiration month.<!--EC:V13-->" id="CreditCardViewModels_0__ExpMonth" name="CreditCardViewModels[0].ExpMonth" class="preproc"><option selected="selected" value=""></option> + <div class="form-group date-month"><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="CreditCardViewModels[0].ExpMonth" data-valmsg-replace="true"></span><div class="selector fixedWidth" id="uniform-CreditCardViewModels_0__ExpMonth"><span aria-hidden="true" style="-webkit-user-select: none;"></span><label class="ifl" for="CreditCardViewModels_0__ExpMonth">Expiration month<em aria-hidden="true" class="rqrd">*</em></label><select aria-label="Expiration month" aria-required="true" data-val="true" data-val-number="The field Expiration month must be a number." data-val-required="Please select an Expiration month.<!--EC:V13-->" id="CreditCardViewModels_0__ExpMonth" name="CreditCardViewModels[0].ExpMonth" class="preproc"><option selected="selected" value=""></option> <option value="1">01 - January</option> <option value="2">02 - February</option> <option value="3">03 - March</option> @@ -38,7 +38,7 @@ <option value="11">11 - November</option> <option value="12">12 - December</option> </select></div></div> - <div class="form-group card-exp-year"><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="CreditCardViewModels[0].ExpYear" data-valmsg-replace="true"></span><div class="selector fixedWidth" id="uniform-CreditCardViewModels_0__ExpYear"><span aria-hidden="true" style="-webkit-user-select: none;"></span><label class="ifl" for="CreditCardViewModels_0__ExpYear">Year<em aria-hidden="true" class="rqrd">*</em></label><select aria-label="Year" aria-required="true" autocomplete="off" data-val="true" data-val-number="The field Expiration year must be a number." data-val-required="Please select an Expiration year.<!--EC:V13-->" id="CreditCardViewModels_0__ExpYear" name="CreditCardViewModels[0].ExpYear" class="preproc"><option selected="selected" value=""></option> + <div class="form-group card-exp-year"><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="CreditCardViewModels[0].ExpYear" data-valmsg-replace="true"></span><div class="selector fixedWidth" id="uniform-CreditCardViewModels_0__ExpYear"><span aria-hidden="true" style="-webkit-user-select: none;"></span><label class="ifl" for="CreditCardViewModels_0__ExpYear">Year<em aria-hidden="true" class="rqrd">*</em></label><select aria-label="Year" aria-required="true" data-val="true" data-val-number="The field Expiration year must be a number." data-val-required="Please select an Expiration year.<!--EC:V13-->" id="CreditCardViewModels_0__ExpYear" name="CreditCardViewModels[0].ExpYear" class="preproc"><option selected="selected" value=""></option> <option value="2016">2016</option> <option value="2017">2017</option> <option value="2018">2018</option> @@ -52,7 +52,7 @@ <option value="2026">2026</option> </select></div></div> <div id="divCreditCardSecurityCode0" class="form-groupset"> - <div class="form-group card-security-code"><label class="ifl" for="CreditCardViewModels_0__SecurityCode">Security code<em aria-hidden="true" class="rqrd">*</em></label><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="CreditCardViewModels[0].SecurityCode" data-valmsg-replace="true"></span><input aria-required="true" autocomplete="off" data-privacy="no-capture" data-val="true" data-val-length="The field Security code must be a string with a maximum length of 4." data-val-length-max="4" data-val-regex="Please enter a valid Security code.<!--EC:V15-->" data-val-regex-pattern="[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ,///-]{3,}" data-val-required="Please enter a Security code.<!--EC:V1-->" id="CreditCardViewModels_0__SecurityCode" maxlength="4" name="CreditCardViewModels[0].SecurityCode" type="password" value=""></div> + <div class="form-group card-security-code"><label class="ifl" for="CreditCardViewModels_0__SecurityCode">Security code<em aria-hidden="true" class="rqrd">*</em></label><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="CreditCardViewModels[0].SecurityCode" data-valmsg-replace="true"></span><input aria-required="true" data-privacy="no-capture" data-val="true" data-val-length="The field Security code must be a string with a maximum length of 4." data-val-length-max="4" data-val-regex="Please enter a valid Security code.<!--EC:V15-->" data-val-regex-pattern="[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ,///-]{3,}" data-val-required="Please enter a Security code.<!--EC:V1-->" id="CreditCardViewModels_0__SecurityCode" maxlength="4" name="CreditCardViewModels[0].SecurityCode" type="password" value=""></div> <button type="button" class="icon-tooltip-large-clear-bg tool-tip-security-code" data-toggle="tooltip" data-tooltip-style="default" tabindex="0" data-hasqtip="3" oldtitle="What's a security code?" title=""><span class="visuallyhidden">About credit card security code</span></button> <div class="tip-security-code"> <div class="tip-security-code-default"> @@ -190,13 +190,13 @@ </div> </div> - + <div id="other-fop-section" style=""> <div class="form-row section-other-fop" id="other_fop_list" style="display: none;"> <label for="OtherFOPType" class="visuallyhidden">Form of payment</label> <div class="selector fixedWidth" id="uniform-OtherFOPType"><span aria-hidden="true" style="-webkit-user-select: none;">Not Selected</span><select class="ddlotherfop preproc" data-cartid="83029498-98C8-4043-AA9B-106E1F89C4BF" data-fopurl="https://www.united.com/ual/en/us/flight-search/book-a-flight/billinginfo/getotherfops/rev" id="OtherFOPType" name="OtherFOPType"><option hideoptions="" value="">Not Selected</option><option hideoptions="" value="VCO">Visa Checkout</option><option hideoptions="PAS, AAC" value="CASH">Cash</option><option hideoptions="PAS, AAC" value="CHECK">Online check</option><option hideoptions="" value="PP">PayPal</option><option hideoptions="" value="BML">PayPal Credit</option></select></div> - + <a href="https://www.united.com/web/en-US/content/booking/flight/whatIsBML.aspx" target="_blank" class="info-link" id="BML-info-link">What is PayPal Credit?</a> <a href="https://www.united.com/web/en-US/content/booking/flight/whatispaypal.aspx" target="_blank" class="info-link" id="PayPal-info-link">What is PayPal?</a> </div> @@ -425,7 +425,7 @@ <div id="customerEmail"></div> <div class="form-row" style="margin-top: 12px; display: none"> <div id="divWalletCCSecurityCode" class="form-groupset" style="display: none; visibility: hidden"> - <div class="form-group card-security-code"><label class="ifl" for="WalletCCSecurityCode">Security code</label><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="WalletCCSecurityCode" data-valmsg-replace="true"></span><input autocomplete="off" data-privacy="no-capture" id="WalletCCSecurityCode" maxlength="4" name="WalletCCSecurityCode" type="password" value=""></div> + <div class="form-group card-security-code"><label class="ifl" for="WalletCCSecurityCode">Security code</label><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="WalletCCSecurityCode" data-valmsg-replace="true"></span><input data-privacy="no-capture" id="WalletCCSecurityCode" maxlength="4" name="WalletCCSecurityCode" type="password" value=""></div> <button type="button" class="icon-tooltip-large-clear-bg tool-tip-security-code" data-toggle="tooltip" data-tooltip-style="default" tabindex="0" data-hasqtip="4" oldtitle="What's a security code?" title=""><span class="visuallyhidden">About credit card security code</span></button> <div class="tip-security-code"> <div class="tip-security-code-default"> @@ -461,7 +461,7 @@ <div id="divcashoptions"> <fieldset class="section-cash-type form-group" style="display: none;"> <p>If you plan to pay with cash, your reservation will be held until midnight CT on Wed, Mar 02, 2016 and must be purchased by that time or the reservation will be released for another customer to purchase.</p> - + <legend>Select where you will complete your cash purchase <small class="rqrd" aria-hidden="true">(*Required)</small></legend> <h4 class="legend">Select where you will complete your cash purchase <small class="rqrd" aria-hidden="true">(*Required)</small></h4> <div class="form-group group-type-radio group-type-radio-cash"> @@ -473,8 +473,8 @@ </fieldset> </div> - - + + <div id="BMLInfo" class="booking-content" style="display: none;"> @@ -794,10 +794,10 @@ <div class="group-label"> </div> <div class="form-group"><label class="ifl" for="BmlModel_DobYear">YYYY<em aria-hidden="true" class="rqrd">*</em></label><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="BmlModel.DobYear" data-valmsg-replace="true"></span><input length="4" aria-required="true" data-val="true" data-val-range="Date of Birth year cannot be greater than cuurent year." data-val-range-max="2014" data-val-range-min="1880" data-val-required="Please enter a YYYY.<!--EC:V1-->" id="BmlModel_DobYear" name="BmlModel.DobYear" type="text" value=""></div> </div> - + <div class="form-group ssn-last-four"> <div class="group-label">Social Security Number<em class="rqrd" aria-hidden="true">*</em></div> - <span class="ssn-hash">#### - ### -</span> <div class="form-group"><label class="ifl" for="BmlModel_SocialSN">Last 4 digits<em aria-hidden="true" class="rqrd">*</em></label><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="BmlModel.SocialSN" data-valmsg-replace="true"></span><input aria-required="true" autocomplete="off" data-privacy="no-capture" data-val="true" data-val-regex="Invalid Social Security Number - last 4 digits" data-val-regex-pattern="^\d{4}$" data-val-required="Last 4 digits" id="BmlModel_SocialSN" name="BmlModel.SocialSN" type="text" value=""></div> + <span class="ssn-hash">#### - ### -</span> <div class="form-group"><label class="ifl" for="BmlModel_SocialSN">Last 4 digits<em aria-hidden="true" class="rqrd">*</em></label><span aria-hidden="true" class="field-validation-valid" data-valmsg-for="BmlModel.SocialSN" data-valmsg-replace="true"></span><input aria-required="true" data-privacy="no-capture" data-val="true" data-val-regex="Invalid Social Security Number - last 4 digits" data-val-regex-pattern="^\d{4}$" data-val-required="Last 4 digits" id="BmlModel_SocialSN" name="BmlModel.SocialSN" type="text" value=""></div> </div> </div> <p>You must read the E-Sign consent of the Terms and Conditions listed below prior to checking the following box: <a href="https://www.united.com/web/en-US/content/booking/flight/FNGENP36.pdf" target="_blank">See E-Sign printer-friendly version</a></p> @@ -873,4 +873,4 @@ </fieldset> </div> </div> -<input id="CartId" name="CartId" type="hidden" value="83029498-98C8-4043-AA9B-106E1F89C4BF"><input id="PageError" name="PageError" type="hidden" value="False"><input id="TripInsurancePurchased" name="TripInsurancePurchased" type="hidden" value="False"><input id="AdditionalData" name="AdditionalData" type="hidden" value=""></form> \ No newline at end of file +<input id="CartId" name="CartId" type="hidden" value="83029498-98C8-4043-AA9B-106E1F89C4BF"><input id="PageError" name="PageError" type="hidden" value="False"><input id="TripInsurancePurchased" name="TripInsurancePurchased" type="hidden" value="False"><input id="AdditionalData" name="AdditionalData" type="hidden" value=""></form>
diff --git a/components/test/data/autofill/heuristics/input/141_checkout_cc_keurig.com.html b/components/test/data/autofill/heuristics/input/141_checkout_cc_keurig.com.html index a57a7b8..c705416 100644 --- a/components/test/data/autofill/heuristics/input/141_checkout_cc_keurig.com.html +++ b/components/test/data/autofill/heuristics/input/141_checkout_cc_keurig.com.html
@@ -1,5 +1,5 @@ - <form id="silentOrderPostForm" name="silentOrderPostForm" class="payment-container checkoutProcess clearfix" action="/checkout/multi/sop-response" method="POST" onsubmit="usb2cCmCreateConversionEventTagPaypal()" autocomplete="off"> + <form id="silentOrderPostForm" name="silentOrderPostForm" class="payment-container checkoutProcess clearfix" action="/checkout/multi/sop-response" method="POST" onsubmit="usb2cCmCreateConversionEventTagPaypal()"> <div class="fields" id="cardForm" style="display:block"> <p class="italic smallCopy reqFields"> @@ -53,7 +53,7 @@ <option value="004">Discover</option> <option value="001">Visa</option> <option value="002">Mastercard</option> - </select><div class="chosen-container chosen-container-single chosen-container-single-nosearch" style="width: 247px;" title="" id="card_cardType_chosen"><a class="chosen-single" tabindex="-1"><span>Please select a card type</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" readonly=""></div><ul class="chosen-results"></ul></div></div> + </select><div class="chosen-container chosen-container-single chosen-container-single-nosearch" style="width: 247px;" title="" id="card_cardType_chosen"><a class="chosen-single" tabindex="-1"><span>Please select a card type</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" readonly=""></div><ul class="chosen-results"></ul></div></div> </div> @@ -84,7 +84,7 @@ <option value="10">10</option> <option value="11">11</option> <option value="12">12</option> - </select><div class="chosen-container chosen-container-single" style="width: 150px;" title="" id="ExpiryMonth_chosen"><a class="chosen-single" tabindex="-1"><span>Month</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off"></div><ul class="chosen-results"></ul></div></div> + </select><div class="chosen-container chosen-container-single" style="width: 150px;" title="" id="ExpiryMonth_chosen"><a class="chosen-single" tabindex="-1"><span>Month</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text"></div><ul class="chosen-results"></ul></div></div> </div> </div> <div id="" class="expYear clearfix"> @@ -102,7 +102,7 @@ <option value="2024">2024</option> <option value="2025">2025</option> <option value="2026">2026</option> - </select><div class="chosen-container chosen-container-single" style="width: 150px;" title="" id="ExpiryYear_chosen"><a class="chosen-single" tabindex="-1"><span>Year</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off"></div><ul class="chosen-results"></ul></div></div> + </select><div class="chosen-container chosen-container-single" style="width: 150px;" title="" id="ExpiryYear_chosen"><a class="chosen-single" tabindex="-1"><span>Year</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text"></div><ul class="chosen-results"></ul></div></div> </div> </div> @@ -128,4 +128,4 @@ </div> <span id="submit_silentOrderPostForm_Checkout" class="btn-box btn-orange continue">CONTINUE TO REVIEW ORDER</span> - </form> \ No newline at end of file + </form>
diff --git a/components/test/data/autofill/heuristics/input/142_cc_checkout_netaporter.com.html b/components/test/data/autofill/heuristics/input/142_cc_checkout_netaporter.com.html index 10f0a45..b2bb9d6 100644 --- a/components/test/data/autofill/heuristics/input/142_cc_checkout_netaporter.com.html +++ b/components/test/data/autofill/heuristics/input/142_cc_checkout_netaporter.com.html
@@ -77,7 +77,7 @@ <label for="card_number">Card Number*</label> </td> <td> - <input type="tel" name="cardNumber" size="35" class="text form-field" id="card_number" value="" autocomplete="off" placeholder=""> + <input type="tel" name="cardNumber" size="35" class="text form-field" id="card_number" value="" placeholder=""> </td> </tr> @@ -109,7 +109,7 @@ <label for="security_number">Security Number*</label> </td> <td> - <input type="tel" name="cVSNumber" maxlength="4" size="3" id="security_number" class="security_number" autocomplete="off" placeholder=""> + <input type="tel" name="cVSNumber" maxlength="4" size="3" id="security_number" class="security_number" placeholder=""> <a id="cc-security-link" class="text-link" onclick="launchPopUp( this.href, 455, 350); return false;" href="http://www.net-a-porter.com/am/content.nap?page=Card-Security-Code&pgForward=popup" title="What is the security number?"> What is this? </a> @@ -177,4 +177,4 @@ </div> <input type="submit" name="_eventId_processPayment" id="processPayment" class="inlineright primary-button" value="Purchase Now"> </div> -</form> \ No newline at end of file +</form>
diff --git a/components/test/data/autofill/heuristics/input/148_payment_dickblick.com.html b/components/test/data/autofill/heuristics/input/148_payment_dickblick.com.html index 740ae11..224dab3 100644 --- a/components/test/data/autofill/heuristics/input/148_payment_dickblick.com.html +++ b/components/test/data/autofill/heuristics/input/148_payment_dickblick.com.html
@@ -334,7 +334,7 @@ <div id="unbxdSearch" class="unbxdNew unbxdSearchBarContainer unbxdSearch"> <div id="unbxdSearchContainer" class="unbxdSearchContainer unbxd-yui-skin-sam"> - <input type="text" id="unbxd_q" class="unbxd_q" name="unbxd_q" value="enter keyword or item number..." autocomplete="off" data-search-url="/search"> + <input type="text" id="unbxd_q" class="unbxd_q" name="unbxd_q" value="enter keyword or item number..." data-search-url="/search"> <img id="unbxdSubmit" class="unbxdHeaderSearchButton" alt="search" src="https://cdn.dick-blick.com/images/header/search-magnifier_optimized.png"> <input type="hidden" name="unbxd_x" value="0"> <input type="hidden" name="unbxd_y" value="0"> @@ -539,7 +539,7 @@ <li> - <input id="rdbCreditCardPaymentMethod" type="radio" name="paymentMethod" value="CreditCard" autocomplete="off" checked="checked"> + <input id="rdbCreditCardPaymentMethod" type="radio" name="paymentMethod" value="CreditCard" checked="checked"> <label for="rdbCreditCardPaymentMethod">Credit Card</label> <img src="/DesktopModules/BlickCheckout/Content/images/accepted-credit-cards.gif" alt="We accept Discover, MasterCard, Visa, American Express, Diners Club, and JCB credit cards"> <div class="paymentOptionFields creditCardFields" style="display: block;"> @@ -598,7 +598,7 @@ <li> - <input id="rdbPaypalPaymentMethod" type="radio" name="paymentMethod" value="PayPal" autocomplete="off"> + <input id="rdbPaypalPaymentMethod" type="radio" name="paymentMethod" value="PayPal"> <label for="rdbPaypalPaymentMethod">PayPal</label> <img src="/DesktopModules/BlickCheckout/Content/images/paypal.gif" style="vertical-align: middle" alt="Use PayPal for payment ..."> <div class="paymentOptionFields paypalFields" style="display: none;"> @@ -607,7 +607,7 @@ </li> <li> - <input id="rdbCheckOrMoneyPaymentMethod" type="radio" name="paymentMethod" value="CheckOrMoneyOrder" autocomplete="off"> + <input id="rdbCheckOrMoneyPaymentMethod" type="radio" name="paymentMethod" value="CheckOrMoneyOrder"> <label for="rdbCheckOrMoneyPaymentMethod">Check or Money Order</label> <div class="paymentOptionFields checkOrMoneyOrderFields" style="display: none;"> <p> @@ -626,7 +626,7 @@ <fieldset> <legend>What is your billing address?</legend> <span class="inputField checkboxField"> - <input type="checkbox" id="UseShippingAddressAsBillingAddress" name="UseShippingAddressAsBillingAddress" value="true" autocomplete="off"> + <input type="checkbox" id="UseShippingAddressAsBillingAddress" name="UseShippingAddressAsBillingAddress" value="true"> <label for="UseShippingAddressAsBillingAddress">My billing address is the same as my shipping address</label> </span> <input data-val="true" data-val-required="The IsBillingAddressInternational field is required." id="IsBillingAddressInternational" name="IsBillingAddressInternational" type="hidden" value="false"> @@ -644,7 +644,7 @@ </span> <span class="inputField textboxField local international" style="display: block;"> <label for="BillingAddressCompanyName">School or Company Name:</label> - <input autocomplete="off" data-val="true" data-val-length="The company name can not be longer than 32 characters." data-val-length-max="32" data-val-length-min="1" id="BillingAddressCompanyName" maxlength="32" name="BillingAddressCompanyName" type="text" value=""> + <input data-val="true" data-val-length="The company name can not be longer than 32 characters." data-val-length-max="32" data-val-length-min="1" id="BillingAddressCompanyName" maxlength="32" name="BillingAddressCompanyName" type="text" value=""> <span class="field-validation-valid" data-valmsg-for="BillingAddressCompanyName" data-valmsg-replace="true"></span> </span> <span class="inputField required textboxField local international" style="display: block;"> @@ -659,7 +659,7 @@ </span> <span class="inputField textboxField local international" style="display: block;"> <label for="BillingAddressStreetLine2">Street Address Line 2 (optional):</label> - <input autocomplete="off" data-val="true" data-val-length="The street line 2 can not be longer than 32 characters." data-val-length-max="32" data-val-length-min="1" data-val-regex="The street line 2 seems to be invalid." data-val-regex-pattern="^[^#]*$" id="BillingAddressStreetLine2" maxlength="32" name="BillingAddressStreetLine2" type="text" value=""> + <input data-val="true" data-val-length="The street line 2 can not be longer than 32 characters." data-val-length-max="32" data-val-length-min="1" data-val-regex="The street line 2 seems to be invalid." data-val-regex-pattern="^[^#]*$" id="BillingAddressStreetLine2" maxlength="32" name="BillingAddressStreetLine2" type="text" value=""> <span class="field-validation-valid" data-valmsg-for="BillingAddressStreetLine2" data-valmsg-replace="true"></span> </span> <span class="inputField required textboxField local international clear" style="display: block;"> @@ -1459,7 +1459,7 @@ <input name="ScrollTop" type="hidden" id="ScrollTop"> - <input name="__dnnVariable" type="hidden" id="__dnnVariable" autocomplete="off" value="`{`trackLinks`:`false`,`__scdoff`:`1`,`sf_siteRoot`:`/`,`sf_tabId`:`112`,`evoq_TabId`:`112`,`evoq_PageLanguage`:`en-US`,`evoq_ContentItemId`:`-1`,`evoq_UrlReferrer`:``,`evoq_UrlPath`:`https%3a%2f%2flocalhost%3a91%2fv2%2fcheckout%3fstep%3dBillingAndContact`,`evoq_UrlQuery`:`%3fTabId%3d112%26%26step%3dBillingAndContact`,`evoq_ContentItemReferrer`:`-1`,`evoq_PersonalizedUrlReferrer`:`-1`,`evoq_DisableAnalytics`:`False`}"> + <input name="__dnnVariable" type="hidden" id="__dnnVariable" value="`{`trackLinks`:`false`,`__scdoff`:`1`,`sf_siteRoot`:`/`,`sf_tabId`:`112`,`evoq_TabId`:`112`,`evoq_PageLanguage`:`en-US`,`evoq_ContentItemId`:`-1`,`evoq_UrlReferrer`:``,`evoq_UrlPath`:`https%3a%2f%2flocalhost%3a91%2fv2%2fcheckout%3fstep%3dBillingAndContact`,`evoq_UrlQuery`:`%3fTabId%3d112%26%26step%3dBillingAndContact`,`evoq_ContentItemReferrer`:`-1`,`evoq_PersonalizedUrlReferrer`:`-1`,`evoq_DisableAnalytics`:`False`}"> <input name="__RequestVerificationToken" type="hidden" value="PzQGtYX8iLgyVtfNpR1BB-QgIIphkolapsEHDSIjVpyzxIv89iZnENurvJv75X251pHHXg2"> </form><div class="unbxd-as-wrapper" style="position: absolute; display: none;"></div> <!--CDF(Javascript|/js/dnncore.js)--><!--CDF(Javascript|/js/dnn.modalpopup.js)--><!--CDF(Css|/Resources/Shared/stylesheets/dnndefault/7.0.0/default.css)--><!--CDF(Css|/Portals/_default/skins/blickecommerce/skin.css)--><!--CDF(Css|/DesktopModules/BlickCheckout/module.css)--><!--CDF(Css|/DesktopModules/BlickCheckout/module.css)--><!--CDF(Css|/DesktopModules/BlickCartSubtotal/module.css)--><!--CDF(Css|/DesktopModules/BlickCartSubtotal/module.css)--><!--CDF(Css|/Portals/0/portal.css)--><!--CDF(Javascript|/js/dnn.js)--><!--CDF(Javascript|/js/dnn.servicesframework.js)--><!--CDF(Javascript|/Resources/libraries/jQuery/01_09_01/jquery.js)--><!--CDF(Javascript|/Resources/libraries/jQuery-UI/01_11_03/jquery-ui.js)-->
diff --git a/components/test/data/autofill/heuristics/input/151_ticketmaster.com.html b/components/test/data/autofill/heuristics/input/151_ticketmaster.com.html index faa7a20..2f1a98b 100644 --- a/components/test/data/autofill/heuristics/input/151_ticketmaster.com.html +++ b/components/test/data/autofill/heuristics/input/151_ticketmaster.com.html
@@ -65,7 +65,7 @@ - <div id="payment-options-component"><div data-reactid=".5"><ul class="payment delimited-list" data-reactid=".5.1"><li class="delimited-list__item" id="credit-card" data-reactid=".5.1.0"><div class="credit-card" data-reactid=".5.1.0.0"><button type="button" class="nfb-button payment__header payment__header--expanded" aria-expanded="true" data-event-category="RCO" data-event-action="Credit Card Section" data-event-label="Paul McCartney" data-reactid=".5.1.0.0.0"><div class="split-content" data-reactid=".5.1.0.0.0.1"><div class="split-content__primary" data-reactid=".5.1.0.0.0.1.0"><h2 class="heading-secondary" data-event-category="RCO" data-event-action="Credit Card Section" data-event-label="Paul McCartney" data-reactid=".5.1.0.0.0.1.0.0">Credit / Debit Card</h2></div><div class="split-content__secondary" data-reactid=".5.1.0.0.0.1.1"><div class="payment__card-logos" data-reactid=".5.1.0.0.0.1.1.0"><svg class="payment__card-logo credit-card__amex-logo" data-reactid=".5.1.0.0.0.1.1.0.0"><use xlink:href="#icon-amex"></use></svg></div><svg class="icon-chevron expando-chevron__close" data-event-category="RCO" data-event-action="Credit Card Chevron" data-event-label="Paul McCartney" data-reactid=".5.1.0.0.0.1.1.1"><use xlink:href="#icon-chevron"></use></svg></div></div></button><div class="payment__main-content" data-reactid=".5.1.0.0.1"><div class="credit-card__billing-form" data-reactid=".5.1.0.0.1.1"><ul class="delimited-list" data-reactid=".5.1.0.0.1.1.0"><li class="delimited-list__item mb10" data-reactid=".5.1.0.0.1.1.0.0"><div class="heading-wrapper" data-reactid=".5.1.0.0.1.1.0.0.0"><div class="heading-wrapper__left" data-reactid=".5.1.0.0.1.1.0.0.0.0"><h3 class="heading-tertiary" data-reactid=".5.1.0.0.1.1.0.0.0.0.0">Add New Card</h3></div><div class="heading-wrapper__right" data-reactid=".5.1.0.0.1.1.0.0.0.1"><span class="alt-copy" data-reactid=".5.1.0.0.1.1.0.0.0.1.0"><span class="checkout__heading-required" data-reactid=".5.1.0.0.1.1.0.0.0.1.0.0">*</span><span data-reactid=".5.1.0.0.1.1.0.0.0.1.0.1"> </span><span data-reactid=".5.1.0.0.1.1.0.0.0.1.0.2">Required</span></span></div><span data-reactid=".5.1.0.0.1.1.0.0.0.2"></span></div><div class="billing__form" data-reactid=".5.1.0.0.1.1.0.0.1"><div data-reactid=".5.1.0.0.1.1.0.0.1.0"><div class="bordered-input-group billing__card-number" data-reactid=".5.1.0.0.1.1.0.0.1.0.0"><div data-reactid=".5.1.0.0.1.1.0.0.1.0.0.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.0.1.0.0.0.0"><label class="bordered-input-group__label" for="cc-num" data-reactid=".5.1.0.0.1.1.0.0.1.0.0.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.0.1.0.0.0.0.0.0">Card Number</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.0.1.0.0.0.0.0.1"> *</span></label><input aria-required="true" autocomplete="cc-number" class="bordered-input-group__text-field" id="cc-num" name="new_credit_card_number" type="tel" value="" data-reactid=".5.1.0.0.1.1.0.0.1.0.0.0.0.1"></div></div></div><div class="bordered-input-group billing__card-type" data-reactid=".5.1.0.0.1.1.0.0.1.0.1"><div class="dropdown bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0"><label class="bordered-input-group__label" for="card-type" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.0"><span data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.0.0">Card Type</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.0.1"> *</span></label><select aria-required="true" autocomplete="cc-type" class="bordered-input-group__dropdown" id="card-type" name="new_credit_card_type_id" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.1"><option value="" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.1.$0"></option><option value="100" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.1.$1">American Express</option></select><svg class="dropdown__icon-chevron" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.2"><use xlink:href="#icon-chevron"></use></svg></div></div></div><div class="billing__card-expiration bordered-input-group" data-reactid=".5.1.0.0.1.1.0.0.1.1"><div class="billing__card-month" data-reactid=".5.1.0.0.1.1.0.0.1.1.0"><div class="dropdown bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0"><label class="bordered-input-group__label" for="cc-exp-month" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.0.0">Exp Month</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.0.1"> *</span></label><select aria-required="true" autocomplete="cc-exp-month" class="bordered-input-group__dropdown" id="cc-exp-month" name="new_credit_card_expire_month" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1"><option value="" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$0"></option><option value="1" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$1">1</option><option value="2" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$2">2</option><option value="3" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$3">3</option><option value="4" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$4">4</option><option value="5" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$5">5</option><option value="6" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$6">6</option><option value="7" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$7">7</option><option value="8" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$8">8</option><option value="9" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$9">9</option><option value="10" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$10">10</option><option value="11" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$11">11</option><option value="12" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$12">12</option></select><svg class="dropdown__icon-chevron" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.2"><use xlink:href="#icon-chevron"></use></svg></div></div><div class="billing__card-year" data-reactid=".5.1.0.0.1.1.0.0.1.1.1"><div class="dropdown bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0"><label class="bordered-input-group__label" for="cc-exp-year" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.0"><span data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.0.0">Exp Year</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.0.1"> *</span></label><select aria-required="true" autocomplete="cc-exp-year" class="bordered-input-group__dropdown" id="cc-exp-year" name="new_credit_card_expire_year" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1"><option value="" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$0"></option><option value="2018" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$1">2018</option><option value="2019" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$2">2019</option><option value="2020" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$3">2020</option><option value="2021" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$4">2021</option><option value="2022" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$5">2022</option><option value="2023" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$6">2023</option><option value="2024" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$7">2024</option><option value="2025" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$8">2025</option><option value="2026" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$9">2026</option><option value="2027" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$10">2027</option><option value="2028" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$11">2028</option></select><svg class="dropdown__icon-chevron" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.2"><use xlink:href="#icon-chevron"></use></svg></div></div></div><div class="billing__card-cvv-container" data-reactid=".5.1.0.0.1.1.0.0.1.2"><div class="billing__card-cvv" data-bdd="billing-form-cvv" data-reactid=".5.1.0.0.1.1.0.0.1.2.0"><div class="cvv-input__container bordered-input-group" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0"><div class="cvv-input__input" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0"><div data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0.0.0"><label class="bordered-input-group__label" for="cc-security-code" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0.0.0.0.0">Security Code</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0.0.0.0.1"> *</span></label><input data-bdd="new-credit-card-cin" aria-required="true" autocomplete="off" class="bordered-input-group__text-field" id="cc-security-code" name="new_credit_card_cin" type="password" value="" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0.0.0.1"></div></div></div><div class="cvv-input__tooltip" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1"><span class="info-tooltip__container-inline" data-bdd="ccp_container_tooltip" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0"><span class="is-clickable info-tooltip__info-icon-padding" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.0"><button type="button" class="info-tooltip__info-icon" title="More Information" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.0.0"><span class="info-tooltip__helper-text" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.0.0.0">Enter your credit card CIN number</span></button></span><span class="info-tooltip__container-hidden" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1"><div style="top: 14px; left: 45px;" class="info-tooltip info-tooltip__container info-tooltip__content-tooltip" data-bdd="ccp_content_tooltip" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0"><div class="" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0.0"><div class="info-tooltip__content" aria-live="polite" role="alert" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0.0.0"><div data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0.0.0.0"><div class="cvv-input__cvv-cc-cin" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0.0.0.0.0"><svg class="icon-credit-card" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0.0.0.0.0.0"><use xlink:href="#icon-credit-card"></use></svg></div><span data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0.0.0.0.1">Please enter your 3 digit Card ID Number</span></div></div></div></div><div style="top: 14px; left: 45px;" class="info-tooltip__arrow-right" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.1"></div></span></span></div></div></div></div><input type="hidden" name="mop_id" value="" data-reactid=".5.1.0.0.1.1.0.0.1.3"></div></li><li class="delimited-list__item" data-reactid=".5.1.0.0.1.1.0.1"><div class="heading-wrapper" data-reactid=".5.1.0.0.1.1.0.1.0"><h4 class="heading-tertiary" data-reactid=".5.1.0.0.1.1.0.1.0.0">Billing Address</h4><div class="billing__change-delivery" data-reactid=".5.1.0.0.1.1.0.1.0.1"><a href="javascript:document.changeDeliveryMethod.submit();" data-bdd="change-delivery-method" data-event-category="RCO" data-event-action="Update Delivery Link, Add New Card" data-event-label="Paul McCartney" data-reactid=".5.1.0.0.1.1.0.1.0.1.0">Outside the US? Update delivery</a></div></div><div class="billing__form" data-reactid=".5.1.0.0.1.1.0.1.1"><input type="hidden" name="country_id" value="36" data-reactid=".5.1.0.0.1.1.0.1.1.0"><div class="billing__first-name bordered-input-group" data-reactid=".5.1.0.0.1.1.0.1.1.1"><div data-reactid=".5.1.0.0.1.1.0.1.1.1.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.1.0.0"><label class="bordered-input-group__label" for="cc_first_name" data-reactid=".5.1.0.0.1.1.0.1.1.1.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.1.0.0.0.0">First Name</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.1.0.0.0.1"> *</span></label><input aria-required="true" autocomplete="billing given-name" class="bordered-input-group__text-field" id="cc_first_name" name="first_name" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.1.0.0.1"></div></div></div><div class="billing__last-name bordered-input-group" data-reactid=".5.1.0.0.1.1.0.1.1.2"><div data-reactid=".5.1.0.0.1.1.0.1.1.2.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.2.0.0"><label class="bordered-input-group__label" for="cc_last_name" data-reactid=".5.1.0.0.1.1.0.1.1.2.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.2.0.0.0.0">Last Name</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.2.0.0.0.1"> *</span></label><input aria-required="true" autocomplete="billing family-name" class="bordered-input-group__text-field" id="cc_last_name" name="last_name" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.2.0.0.1"></div></div></div><div class="bordered-input-group billing__address1" data-reactid=".5.1.0.0.1.1.0.1.1.3"><div data-reactid=".5.1.0.0.1.1.0.1.1.3.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.3.0.0"><label class="bordered-input-group__label" for="cc_address1" data-reactid=".5.1.0.0.1.1.0.1.1.3.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.3.0.0.0.0">Address</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.3.0.0.0.1"> *</span></label><input aria-required="true" autocomplete="billing address-line1" class="bordered-input-group__text-field" id="cc_address1" name="address1" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.3.0.0.1"></div></div></div><div class="bordered-input-group billing__unit-ca" data-reactid=".5.1.0.0.1.1.0.1.1.4"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.4.0"><label class="bordered-input-group__label" for="cc-unit" data-reactid=".5.1.0.0.1.1.0.1.1.4.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.4.0.0.0">Unit #</span></label><input class="bordered-input-group__text-field" id="cc-unit" name="unit" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.4.0.1"></div></div><div class="bordered-input-group billing__address2-ca" data-reactid=".5.1.0.0.1.1.0.1.1.5"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.5.0"><label class="bordered-input-group__label" for="cc_address2" data-reactid=".5.1.0.0.1.1.0.1.1.5.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.5.0.0.0">Address Line 2</span></label><input autocomplete="billing address-line2" class="bordered-input-group__text-field" id="cc_address2" name="address2" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.5.0.1"></div></div><div class="bordered-input-group billing__city-ca" data-reactid=".5.1.0.0.1.1.0.1.1.6"><div data-reactid=".5.1.0.0.1.1.0.1.1.6.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.6.0.0"><label class="bordered-input-group__label" for="cc_city" data-reactid=".5.1.0.0.1.1.0.1.1.6.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.6.0.0.0.0">City</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.6.0.0.0.1"> *</span></label><input aria-required="true" autocomplete="billing address-level2" class="bordered-input-group__text-field" id="cc_city" name="city" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.6.0.0.1"></div></div></div><div class="billing__country bordered-input-group" data-reactid=".5.1.0.0.1.1.0.1.1.7"><div data-reactid=".5.1.0.0.1.1.0.1.1.7.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.7.0.0"><label class="bordered-input-group__label" for="cc_country" data-reactid=".5.1.0.0.1.1.0.1.1.7.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.7.0.0.0.0">Country</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.7.0.0.0.1"> *</span></label><input disabled="" aria-required="true" class="bordered-input-group__text-field" id="cc_country" name="country" type="text" value="Canada" data-reactid=".5.1.0.0.1.1.0.1.1.7.0.0.1"><svg class="bordered-input-group__icon-success" data-reactid=".5.1.0.0.1.1.0.1.1.7.0.0.2"><use xlink:href="#icon-check"></use></svg></div></div></div><div class="bordered-input-group bordered-input-group billing__state-ca" data-reactid=".5.1.0.0.1.1.0.1.1.8"><div class="dropdown bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.8.0"><label class="bordered-input-group__label" for="cc_state_id" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.8.0.0.0">Province</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.0.1"> *</span></label><select aria-required="true" autocomplete="billing address-level1" class="bordered-input-group__dropdown" id="cc_state_id" name="state_id" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1"><option value="" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$0"></option><option value="66" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$1">Alberta</option><option value="67" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$2">British Columbia</option><option value="68" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$3">Manitoba</option><option value="69" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$4">New Brunswick</option><option value="70" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$5">Newfoundland</option><option value="71" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$6">Northwest Territories</option><option value="72" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$7">Nova Scotia</option><option value="73" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$8">Nunavut</option><option value="74" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$9">Ontario</option><option value="75" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$10">Prince Edward Island</option><option value="76" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$11">Quebec</option><option value="77" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$12">Saskatchewan</option><option value="78" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$13">Yukon</option></select><svg class="dropdown__icon-chevron" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.2"><use xlink:href="#icon-chevron"></use></svg></div></div><div class="bordered-input-group billing__postal-code-ca" data-reactid=".5.1.0.0.1.1.0.1.1.9"><div data-reactid=".5.1.0.0.1.1.0.1.1.9.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.9.0.0"><label class="bordered-input-group__label" for="cc_postal_code" data-reactid=".5.1.0.0.1.1.0.1.1.9.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.9.0.0.0.0">Postal Code</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.9.0.0.0.1"> *</span></label><input aria-required="true" autocomplete="billing postal-code" class="bordered-input-group__text-field" id="cc_postal_code" name="postal_code" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.9.0.0.1"></div></div></div><div class="bordered-input-group billing__phone1" data-reactid=".5.1.0.0.1.1.0.1.1.b"><div data-reactid=".5.1.0.0.1.1.0.1.1.b.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.b.0.0"><label class="bordered-input-group__label" for="cc_phone1" data-reactid=".5.1.0.0.1.1.0.1.1.b.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.b.0.0.0.0">Phone</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.b.0.0.0.1"> *</span></label><input placeholder="p. ex. 416-555-1212" aria-required="true" autocomplete="billing tel" class="bordered-input-group__text-field" id="cc_phone1" name="evening_phone" type="tel" value="" data-reactid=".5.1.0.0.1.1.0.1.1.b.0.0.1"></div></div></div><div class="bordered-input-group billing__phone2" data-reactid=".5.1.0.0.1.1.0.1.1.c"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.c.0"><label class="bordered-input-group__label" for="cc_phone2" data-reactid=".5.1.0.0.1.1.0.1.1.c.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.c.0.0.0">Alternate Phone</span></label><input autocomplete="billing tel" class="bordered-input-group__text-field" id="cc_phone2" name="mobile_phone" type="tel" value="" data-reactid=".5.1.0.0.1.1.0.1.1.c.0.1"></div></div></div><div class="billing__save-my-card-wrapper" data-reactid=".5.1.0.0.1.1.0.1.2"><label for="store_payment" data-reactid=".5.1.0.0.1.1.0.1.2.0"><input class="billing__checkbox" id="store_payment" name="store_payment" type="checkbox" data-event-category="RCO" data-event-action="Store my card for faster checkout next time checkbox, Add New Card" data-event-label="Paul McCartney" checked="" data-reactid=".5.1.0.0.1.1.0.1.2.0.0"><span class="billing__checkbox-content" data-reactid=".5.1.0.0.1.1.0.1.2.0.1"><span data-event-category="RCO" data-event-action="Store my card for faster checkout next time checkbox, Add New Card" data-event-label="Paul McCartney" data-reactid=".5.1.0.0.1.1.0.1.2.0.1.0">Store my card for faster checkout next time.</span><span data-reactid=".5.1.0.0.1.1.0.1.2.0.1.1"> </span></span></label></div><span data-reactid=".5.1.0.0.1.1.0.1.3"></span><input type="hidden" name="vv_region_id" value="" data-reactid=".5.1.0.0.1.1.0.1.5"><input type="hidden" name="new_payment" value="1" data-reactid=".5.1.0.0.1.1.0.1.6"><input type="hidden" name="new_payment_type" value="CC" data-reactid=".5.1.0.0.1.1.0.1.7"></li></ul></div></div></div></li></ul></div></div> + <div id="payment-options-component"><div data-reactid=".5"><ul class="payment delimited-list" data-reactid=".5.1"><li class="delimited-list__item" id="credit-card" data-reactid=".5.1.0"><div class="credit-card" data-reactid=".5.1.0.0"><button type="button" class="nfb-button payment__header payment__header--expanded" aria-expanded="true" data-event-category="RCO" data-event-action="Credit Card Section" data-event-label="Paul McCartney" data-reactid=".5.1.0.0.0"><div class="split-content" data-reactid=".5.1.0.0.0.1"><div class="split-content__primary" data-reactid=".5.1.0.0.0.1.0"><h2 class="heading-secondary" data-event-category="RCO" data-event-action="Credit Card Section" data-event-label="Paul McCartney" data-reactid=".5.1.0.0.0.1.0.0">Credit / Debit Card</h2></div><div class="split-content__secondary" data-reactid=".5.1.0.0.0.1.1"><div class="payment__card-logos" data-reactid=".5.1.0.0.0.1.1.0"><svg class="payment__card-logo credit-card__amex-logo" data-reactid=".5.1.0.0.0.1.1.0.0"><use xlink:href="#icon-amex"></use></svg></div><svg class="icon-chevron expando-chevron__close" data-event-category="RCO" data-event-action="Credit Card Chevron" data-event-label="Paul McCartney" data-reactid=".5.1.0.0.0.1.1.1"><use xlink:href="#icon-chevron"></use></svg></div></div></button><div class="payment__main-content" data-reactid=".5.1.0.0.1"><div class="credit-card__billing-form" data-reactid=".5.1.0.0.1.1"><ul class="delimited-list" data-reactid=".5.1.0.0.1.1.0"><li class="delimited-list__item mb10" data-reactid=".5.1.0.0.1.1.0.0"><div class="heading-wrapper" data-reactid=".5.1.0.0.1.1.0.0.0"><div class="heading-wrapper__left" data-reactid=".5.1.0.0.1.1.0.0.0.0"><h3 class="heading-tertiary" data-reactid=".5.1.0.0.1.1.0.0.0.0.0">Add New Card</h3></div><div class="heading-wrapper__right" data-reactid=".5.1.0.0.1.1.0.0.0.1"><span class="alt-copy" data-reactid=".5.1.0.0.1.1.0.0.0.1.0"><span class="checkout__heading-required" data-reactid=".5.1.0.0.1.1.0.0.0.1.0.0">*</span><span data-reactid=".5.1.0.0.1.1.0.0.0.1.0.1"> </span><span data-reactid=".5.1.0.0.1.1.0.0.0.1.0.2">Required</span></span></div><span data-reactid=".5.1.0.0.1.1.0.0.0.2"></span></div><div class="billing__form" data-reactid=".5.1.0.0.1.1.0.0.1"><div data-reactid=".5.1.0.0.1.1.0.0.1.0"><div class="bordered-input-group billing__card-number" data-reactid=".5.1.0.0.1.1.0.0.1.0.0"><div data-reactid=".5.1.0.0.1.1.0.0.1.0.0.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.0.1.0.0.0.0"><label class="bordered-input-group__label" for="cc-num" data-reactid=".5.1.0.0.1.1.0.0.1.0.0.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.0.1.0.0.0.0.0.0">Card Number</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.0.1.0.0.0.0.0.1"> *</span></label><input aria-required="true" autocomplete="cc-number" class="bordered-input-group__text-field" id="cc-num" name="new_credit_card_number" type="tel" value="" data-reactid=".5.1.0.0.1.1.0.0.1.0.0.0.0.1"></div></div></div><div class="bordered-input-group billing__card-type" data-reactid=".5.1.0.0.1.1.0.0.1.0.1"><div class="dropdown bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0"><label class="bordered-input-group__label" for="card-type" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.0"><span data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.0.0">Card Type</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.0.1"> *</span></label><select aria-required="true" autocomplete="cc-type" class="bordered-input-group__dropdown" id="card-type" name="new_credit_card_type_id" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.1"><option value="" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.1.$0"></option><option value="100" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.1.$1">American Express</option></select><svg class="dropdown__icon-chevron" data-reactid=".5.1.0.0.1.1.0.0.1.0.1.0.2"><use xlink:href="#icon-chevron"></use></svg></div></div></div><div class="billing__card-expiration bordered-input-group" data-reactid=".5.1.0.0.1.1.0.0.1.1"><div class="billing__card-month" data-reactid=".5.1.0.0.1.1.0.0.1.1.0"><div class="dropdown bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0"><label class="bordered-input-group__label" for="cc-exp-month" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.0.0">Exp Month</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.0.1"> *</span></label><select aria-required="true" autocomplete="cc-exp-month" class="bordered-input-group__dropdown" id="cc-exp-month" name="new_credit_card_expire_month" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1"><option value="" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$0"></option><option value="1" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$1">1</option><option value="2" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$2">2</option><option value="3" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$3">3</option><option value="4" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$4">4</option><option value="5" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$5">5</option><option value="6" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$6">6</option><option value="7" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$7">7</option><option value="8" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$8">8</option><option value="9" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$9">9</option><option value="10" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$10">10</option><option value="11" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$11">11</option><option value="12" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.1.$12">12</option></select><svg class="dropdown__icon-chevron" data-reactid=".5.1.0.0.1.1.0.0.1.1.0.0.2"><use xlink:href="#icon-chevron"></use></svg></div></div><div class="billing__card-year" data-reactid=".5.1.0.0.1.1.0.0.1.1.1"><div class="dropdown bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0"><label class="bordered-input-group__label" for="cc-exp-year" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.0"><span data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.0.0">Exp Year</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.0.1"> *</span></label><select aria-required="true" autocomplete="cc-exp-year" class="bordered-input-group__dropdown" id="cc-exp-year" name="new_credit_card_expire_year" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1"><option value="" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$0"></option><option value="2018" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$1">2018</option><option value="2019" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$2">2019</option><option value="2020" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$3">2020</option><option value="2021" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$4">2021</option><option value="2022" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$5">2022</option><option value="2023" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$6">2023</option><option value="2024" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$7">2024</option><option value="2025" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$8">2025</option><option value="2026" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$9">2026</option><option value="2027" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$10">2027</option><option value="2028" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.1.$11">2028</option></select><svg class="dropdown__icon-chevron" data-reactid=".5.1.0.0.1.1.0.0.1.1.1.0.2"><use xlink:href="#icon-chevron"></use></svg></div></div></div><div class="billing__card-cvv-container" data-reactid=".5.1.0.0.1.1.0.0.1.2"><div class="billing__card-cvv" data-bdd="billing-form-cvv" data-reactid=".5.1.0.0.1.1.0.0.1.2.0"><div class="cvv-input__container bordered-input-group" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0"><div class="cvv-input__input" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0"><div data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0.0.0"><label class="bordered-input-group__label" for="cc-security-code" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0.0.0.0.0">Security Code</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0.0.0.0.1"> *</span></label><input data-bdd="new-credit-card-cin" aria-required="true" class="bordered-input-group__text-field" id="cc-security-code" name="new_credit_card_cin" type="password" value="" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.0.0.0.1"></div></div></div><div class="cvv-input__tooltip" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1"><span class="info-tooltip__container-inline" data-bdd="ccp_container_tooltip" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0"><span class="is-clickable info-tooltip__info-icon-padding" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.0"><button type="button" class="info-tooltip__info-icon" title="More Information" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.0.0"><span class="info-tooltip__helper-text" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.0.0.0">Enter your credit card CIN number</span></button></span><span class="info-tooltip__container-hidden" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1"><div style="top: 14px; left: 45px;" class="info-tooltip info-tooltip__container info-tooltip__content-tooltip" data-bdd="ccp_content_tooltip" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0"><div class="" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0.0"><div class="info-tooltip__content" aria-live="polite" role="alert" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0.0.0"><div data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0.0.0.0"><div class="cvv-input__cvv-cc-cin" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0.0.0.0.0"><svg class="icon-credit-card" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0.0.0.0.0.0"><use xlink:href="#icon-credit-card"></use></svg></div><span data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.0.0.0.0.1">Please enter your 3 digit Card ID Number</span></div></div></div></div><div style="top: 14px; left: 45px;" class="info-tooltip__arrow-right" data-reactid=".5.1.0.0.1.1.0.0.1.2.0.0.1.0.1.1"></div></span></span></div></div></div></div><input type="hidden" name="mop_id" value="" data-reactid=".5.1.0.0.1.1.0.0.1.3"></div></li><li class="delimited-list__item" data-reactid=".5.1.0.0.1.1.0.1"><div class="heading-wrapper" data-reactid=".5.1.0.0.1.1.0.1.0"><h4 class="heading-tertiary" data-reactid=".5.1.0.0.1.1.0.1.0.0">Billing Address</h4><div class="billing__change-delivery" data-reactid=".5.1.0.0.1.1.0.1.0.1"><a href="javascript:document.changeDeliveryMethod.submit();" data-bdd="change-delivery-method" data-event-category="RCO" data-event-action="Update Delivery Link, Add New Card" data-event-label="Paul McCartney" data-reactid=".5.1.0.0.1.1.0.1.0.1.0">Outside the US? Update delivery</a></div></div><div class="billing__form" data-reactid=".5.1.0.0.1.1.0.1.1"><input type="hidden" name="country_id" value="36" data-reactid=".5.1.0.0.1.1.0.1.1.0"><div class="billing__first-name bordered-input-group" data-reactid=".5.1.0.0.1.1.0.1.1.1"><div data-reactid=".5.1.0.0.1.1.0.1.1.1.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.1.0.0"><label class="bordered-input-group__label" for="cc_first_name" data-reactid=".5.1.0.0.1.1.0.1.1.1.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.1.0.0.0.0">First Name</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.1.0.0.0.1"> *</span></label><input aria-required="true" autocomplete="billing given-name" class="bordered-input-group__text-field" id="cc_first_name" name="first_name" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.1.0.0.1"></div></div></div><div class="billing__last-name bordered-input-group" data-reactid=".5.1.0.0.1.1.0.1.1.2"><div data-reactid=".5.1.0.0.1.1.0.1.1.2.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.2.0.0"><label class="bordered-input-group__label" for="cc_last_name" data-reactid=".5.1.0.0.1.1.0.1.1.2.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.2.0.0.0.0">Last Name</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.2.0.0.0.1"> *</span></label><input aria-required="true" autocomplete="billing family-name" class="bordered-input-group__text-field" id="cc_last_name" name="last_name" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.2.0.0.1"></div></div></div><div class="bordered-input-group billing__address1" data-reactid=".5.1.0.0.1.1.0.1.1.3"><div data-reactid=".5.1.0.0.1.1.0.1.1.3.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.3.0.0"><label class="bordered-input-group__label" for="cc_address1" data-reactid=".5.1.0.0.1.1.0.1.1.3.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.3.0.0.0.0">Address</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.3.0.0.0.1"> *</span></label><input aria-required="true" autocomplete="billing address-line1" class="bordered-input-group__text-field" id="cc_address1" name="address1" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.3.0.0.1"></div></div></div><div class="bordered-input-group billing__unit-ca" data-reactid=".5.1.0.0.1.1.0.1.1.4"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.4.0"><label class="bordered-input-group__label" for="cc-unit" data-reactid=".5.1.0.0.1.1.0.1.1.4.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.4.0.0.0">Unit #</span></label><input class="bordered-input-group__text-field" id="cc-unit" name="unit" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.4.0.1"></div></div><div class="bordered-input-group billing__address2-ca" data-reactid=".5.1.0.0.1.1.0.1.1.5"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.5.0"><label class="bordered-input-group__label" for="cc_address2" data-reactid=".5.1.0.0.1.1.0.1.1.5.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.5.0.0.0">Address Line 2</span></label><input autocomplete="billing address-line2" class="bordered-input-group__text-field" id="cc_address2" name="address2" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.5.0.1"></div></div><div class="bordered-input-group billing__city-ca" data-reactid=".5.1.0.0.1.1.0.1.1.6"><div data-reactid=".5.1.0.0.1.1.0.1.1.6.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.6.0.0"><label class="bordered-input-group__label" for="cc_city" data-reactid=".5.1.0.0.1.1.0.1.1.6.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.6.0.0.0.0">City</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.6.0.0.0.1"> *</span></label><input aria-required="true" autocomplete="billing address-level2" class="bordered-input-group__text-field" id="cc_city" name="city" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.6.0.0.1"></div></div></div><div class="billing__country bordered-input-group" data-reactid=".5.1.0.0.1.1.0.1.1.7"><div data-reactid=".5.1.0.0.1.1.0.1.1.7.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.7.0.0"><label class="bordered-input-group__label" for="cc_country" data-reactid=".5.1.0.0.1.1.0.1.1.7.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.7.0.0.0.0">Country</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.7.0.0.0.1"> *</span></label><input disabled="" aria-required="true" class="bordered-input-group__text-field" id="cc_country" name="country" type="text" value="Canada" data-reactid=".5.1.0.0.1.1.0.1.1.7.0.0.1"><svg class="bordered-input-group__icon-success" data-reactid=".5.1.0.0.1.1.0.1.1.7.0.0.2"><use xlink:href="#icon-check"></use></svg></div></div></div><div class="bordered-input-group bordered-input-group billing__state-ca" data-reactid=".5.1.0.0.1.1.0.1.1.8"><div class="dropdown bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.8.0"><label class="bordered-input-group__label" for="cc_state_id" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.8.0.0.0">Province</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.0.1"> *</span></label><select aria-required="true" autocomplete="billing address-level1" class="bordered-input-group__dropdown" id="cc_state_id" name="state_id" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1"><option value="" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$0"></option><option value="66" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$1">Alberta</option><option value="67" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$2">British Columbia</option><option value="68" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$3">Manitoba</option><option value="69" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$4">New Brunswick</option><option value="70" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$5">Newfoundland</option><option value="71" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$6">Northwest Territories</option><option value="72" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$7">Nova Scotia</option><option value="73" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$8">Nunavut</option><option value="74" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$9">Ontario</option><option value="75" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$10">Prince Edward Island</option><option value="76" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$11">Quebec</option><option value="77" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$12">Saskatchewan</option><option value="78" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.1.$13">Yukon</option></select><svg class="dropdown__icon-chevron" data-reactid=".5.1.0.0.1.1.0.1.1.8.0.2"><use xlink:href="#icon-chevron"></use></svg></div></div><div class="bordered-input-group billing__postal-code-ca" data-reactid=".5.1.0.0.1.1.0.1.1.9"><div data-reactid=".5.1.0.0.1.1.0.1.1.9.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.9.0.0"><label class="bordered-input-group__label" for="cc_postal_code" data-reactid=".5.1.0.0.1.1.0.1.1.9.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.9.0.0.0.0">Postal Code</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.9.0.0.0.1"> *</span></label><input aria-required="true" autocomplete="billing postal-code" class="bordered-input-group__text-field" id="cc_postal_code" name="postal_code" type="text" value="" data-reactid=".5.1.0.0.1.1.0.1.1.9.0.0.1"></div></div></div><div class="bordered-input-group billing__phone1" data-reactid=".5.1.0.0.1.1.0.1.1.b"><div data-reactid=".5.1.0.0.1.1.0.1.1.b.0"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.b.0.0"><label class="bordered-input-group__label" for="cc_phone1" data-reactid=".5.1.0.0.1.1.0.1.1.b.0.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.b.0.0.0.0">Phone</span><span class="input-group__required" data-reactid=".5.1.0.0.1.1.0.1.1.b.0.0.0.1"> *</span></label><input placeholder="p. ex. 416-555-1212" aria-required="true" autocomplete="billing tel" class="bordered-input-group__text-field" id="cc_phone1" name="evening_phone" type="tel" value="" data-reactid=".5.1.0.0.1.1.0.1.1.b.0.0.1"></div></div></div><div class="bordered-input-group billing__phone2" data-reactid=".5.1.0.0.1.1.0.1.1.c"><div class="bordered-input-group__container" data-reactid=".5.1.0.0.1.1.0.1.1.c.0"><label class="bordered-input-group__label" for="cc_phone2" data-reactid=".5.1.0.0.1.1.0.1.1.c.0.0"><span data-reactid=".5.1.0.0.1.1.0.1.1.c.0.0.0">Alternate Phone</span></label><input autocomplete="billing tel" class="bordered-input-group__text-field" id="cc_phone2" name="mobile_phone" type="tel" value="" data-reactid=".5.1.0.0.1.1.0.1.1.c.0.1"></div></div></div><div class="billing__save-my-card-wrapper" data-reactid=".5.1.0.0.1.1.0.1.2"><label for="store_payment" data-reactid=".5.1.0.0.1.1.0.1.2.0"><input class="billing__checkbox" id="store_payment" name="store_payment" type="checkbox" data-event-category="RCO" data-event-action="Store my card for faster checkout next time checkbox, Add New Card" data-event-label="Paul McCartney" checked="" data-reactid=".5.1.0.0.1.1.0.1.2.0.0"><span class="billing__checkbox-content" data-reactid=".5.1.0.0.1.1.0.1.2.0.1"><span data-event-category="RCO" data-event-action="Store my card for faster checkout next time checkbox, Add New Card" data-event-label="Paul McCartney" data-reactid=".5.1.0.0.1.1.0.1.2.0.1.0">Store my card for faster checkout next time.</span><span data-reactid=".5.1.0.0.1.1.0.1.2.0.1.1"> </span></span></label></div><span data-reactid=".5.1.0.0.1.1.0.1.3"></span><input type="hidden" name="vv_region_id" value="" data-reactid=".5.1.0.0.1.1.0.1.5"><input type="hidden" name="new_payment" value="1" data-reactid=".5.1.0.0.1.1.0.1.6"><input type="hidden" name="new_payment_type" value="CC" data-reactid=".5.1.0.0.1.1.0.1.7"></li></ul></div></div></div></li></ul></div></div> <div id="billing-legal-text"><noscript data-reactid=".9"></noscript></div> <div class="disclaimer-container"> <p class="legal-copy">By continuing past this page, you agree to our <a href="http://www.ticketmaster.com/h/terms.html?tm_link=_terms" target="_blank" class="set-gtm-label" data-event-category="RCO" data-event-action="Terms of Use Link" data-event-label="Paul McCartney">Terms of Use</a>.</p> </div> <div id="billing-cta-bottom" class="billing__cta-bottom"><button id="billing_cta_bottom" class="button button--cta order-summary__cta-button" type="submit" data-event-category="RCO" data-event-action="Place Order Button" data-event-label="Paul McCartney" data-event-value="410.5" data-reactid=".4"><svg class="icon-lock billing__lock-icon" data-event-category="RCO" data-event-action="Place Order Button" data-event-label="Paul McCartney" data-event-value="410.5" data-reactid=".4.0"><use xlink:href="#icon-lock"></use></svg><span data-event-category="RCO" data-event-action="Place Order Button" data-event-label="Paul McCartney" data-event-value="410.5" data-reactid=".4.1">Place Order</span></button></div> </div> @@ -117,10 +117,10 @@ <div id="accept-continue"></div> </form> </div> - <form action="/checkout/order" method="POST" name="changeDeliveryMethod" autocomplete="off"> + <form action="/checkout/order" method="POST" name="changeDeliveryMethod"> <input type="hidden" name="v" value="btXdB7rvCWLDciEmL2_7f49bzn2y2yTl_IKlSpJrnfQ8k09bSpkvmgjTKpWOODYWl2KZJIulUu1uPgEeE-mmHrtc4rGKhvjdZb0y8Yw8UQ7nyGhIhwJmnbanFiAlgLmhpEZCLpcgPamyVcg0LpXvMZDKfIE18UbtNr7NsrN7o18txax3-JggP4Wj6BbqFXU"> </form> - <form action="/checkout/order" method="POST" name="handleWavesErrors" autocomplete="off"> + <form action="/checkout/order" method="POST" name="handleWavesErrors"> <input type="hidden" name="v" value="snQAt2E0ASBhctV2pvh8QK7cNmXR7fOPvTJuL0pWYZuyJp3Ntcd5K40MbaacVI4rEj3_k9LDLnStczjTmg6IFX0azWTDxhuDcx91qtScEsIPCf4vHTwiKeTgPnF-MoEYAO97H6v1vfxpkXQpddf721e7lBRuvRlSIBeb5lc2XqNl9H39gli7l-pgE3RIyiS5"> <input type="hidden" name="code"> <input type="hidden" name="message">
diff --git a/components/test/data/autofill/heuristics/input/156_buyAlbum_bandcamp.com_price.html b/components/test/data/autofill/heuristics/input/156_buyAlbum_bandcamp.com_price.html index 45606dee..dc4917d 100644 --- a/components/test/data/autofill/heuristics/input/156_buyAlbum_bandcamp.com_price.html +++ b/components/test/data/autofill/heuristics/input/156_buyAlbum_bandcamp.com_price.html
@@ -20,7 +20,7 @@ Name your price: </label> <span > <span >$</span> - <input id="userPrice" size="6" value="" autocomplete="off" type="text"> + <input id="userPrice" size="6" value="" type="text"> <span > <span > <span >USD</span>
diff --git a/components/ui_devtools/views/overlay_agent_mac.mm b/components/ui_devtools/views/overlay_agent_mac.mm index 61307f0..308f91b 100644 --- a/components/ui_devtools/views/overlay_agent_mac.mm +++ b/components/ui_devtools/views/overlay_agent_mac.mm
@@ -70,6 +70,7 @@ protocol::Response OverlayAgentMac::disable() { if (is_pretarget_handler_) RemovePreTargetHandler(); + hideHighlight(); dom_agent()->RemoveObserver(this); return OverlayAgentViews::disable(); }
diff --git a/components/ukm/ios/features.cc b/components/ukm/ios/features.cc index ff2a1f03..8e6d8746 100644 --- a/components/ukm/ios/features.cc +++ b/components/ukm/ios/features.cc
@@ -5,4 +5,4 @@ #import "components/ukm/ios/features.h" const base::Feature kUmaCellular{"UmaCellular", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/components/viz/common/quads/shared_quad_state.h b/components/viz/common/quads/shared_quad_state.h index c339d46c..647fd470 100644 --- a/components/viz/common/quads/shared_quad_state.h +++ b/components/viz/common/quads/shared_quad_state.h
@@ -66,13 +66,6 @@ float opacity; SkBlendMode blend_mode; int sorting_context_id; - // An internal flag used only in the SurfaceAggregator and the - // OverlayProcessor. If set to true surface's compositor frame was updated in - // current aggregation, and if set to false the surface has not changed since - // the previous frame. It can be used for underlay optimization when the quads - // on top are not damaged. SetAll() doesn't update this flag. It has to be set - // sepaerately. - bool has_surface_damage = false; // An internal flag used only by the SurfaceAggregator to decide whether to // merge quads for a surface into their target render pass. It is a // performance optimization by avoiding render passes as much as possible.
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index e6423fca..bc3f8a7ee 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -479,7 +479,10 @@ } if (enable_vulkan) { - deps += [ "//gpu/vulkan/init" ] + deps += [ + "//gpu/vulkan:test_support", + "//gpu/vulkan/init", + ] } }
diff --git a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc index 8cb1476..028eea78 100644 --- a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc +++ b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc
@@ -107,6 +107,14 @@ params->display_private = MakeRequestAssociatedWithDedicatedPipe(&display_private_); params->display_client = display_client_.BindInterfacePtr().PassInterface(); + + // Since the RootCompositorFrameSink doesn't get replaced on each fuzzer + // iteration, ensure that only one frame is pending at a time and that begin + // frames are decoupled from frame rate (otherwise bugs can occur when the + // frame rate is slower than the length of the fuzzer iterations). + // TODO(kylechar): Stop sending begin frames back to clients. + params->disable_frame_rate_limit = true; + return params; }
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc index ee90219..dbdd22a7 100644 --- a/components/viz/service/display/overlay_unittest.cc +++ b/components/viz/service/display/overlay_unittest.cc
@@ -255,7 +255,6 @@ SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState(); shared_state->opacity = 1.f; - shared_state->has_surface_damage = true; return pass; }
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc index 81464ed..00ff891f7 100644 --- a/components/viz/service/display/renderer_pixeltest.cc +++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -1079,11 +1079,14 @@ cc::FuzzyPixelOffByOneComparator(true))); } -TYPED_TEST(GLCapableRendererPixelTest, SolidColorBlend) { +// TODO(backer): Blending is not correct for SkiaRenderer +// (https://crbug.com/953284) +TYPED_TEST(GLCapableRendererPixelTest, DISABLED_SolidColorBlend) { gfx::Rect rect(this->device_viewport_size_); int id = 1; std::unique_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect); + pass->has_transparent_background = false; SharedQuadState* shared_state = CreateTestSharedQuadState( gfx::Transform(), rect, pass.get(), gfx::RRectF()); @@ -1108,7 +1111,7 @@ EXPECT_TRUE(this->RunPixelTest( &pass_list, base::FilePath(FILE_PATH_LITERAL("dark_grey.png")), - cc::FuzzyPixelOffByOneComparator(true))); + cc::FuzzyPixelOffByOneComparator(/*discard_alpha=*/true))); } // TODO(crbug.com/924369): SkiaRenderer should not ignore the color matrix on @@ -1791,16 +1794,14 @@ TEST_P(VideoGLRendererPixelHiLoTest, SimpleYUVRect) { SimpleYUVRect(); } -// TODO(crbug.com/936822): Enable this test. -TEST_P(VideoSkiaRendererPixelHiLoTest, DISABLED_SimpleYUVRect) { +TEST_P(VideoSkiaRendererPixelHiLoTest, SimpleYUVRect) { SimpleYUVRect(); } TEST_P(VideoGLRendererPixelHiLoTest, ClippedYUVRect) { ClippedYUVRect(); } -// TODO(crbug.com/936822): Enable this test. -TEST_P(VideoSkiaRendererPixelHiLoTest, DISABLED_ClippedYUVRect) { +TEST_P(VideoSkiaRendererPixelHiLoTest, ClippedYUVRect) { ClippedYUVRect(); } @@ -3184,6 +3185,7 @@ gfx::Transform transform_to_root; std::unique_ptr<RenderPass> pass = CreateTestRenderPass(id, rect, transform_to_root); + pass->has_transparent_background = false; gfx::Transform hole_quad_to_target_transform; hole_quad_to_target_transform.Translate(50, 50); @@ -3208,7 +3210,7 @@ EXPECT_TRUE(this->RunPixelTest( &pass_list, base::FilePath(FILE_PATH_LITERAL("force_anti_aliasing_off.png")), - cc::ExactPixelComparator(false))); + cc::ExactPixelComparator(/*discard_alpha=*/true))); } // This test tests that forcing anti-aliasing off works as expected for @@ -3266,7 +3268,7 @@ EXPECT_TRUE(this->RunPixelTest( &pass_list, base::FilePath(FILE_PATH_LITERAL("force_anti_aliasing_off.png")), - cc::ExactPixelComparator(false))); + cc::ExactPixelComparator(/*discard_alpha=*/true))); } // This test tests that forcing anti-aliasing off works as expected for @@ -3302,6 +3304,7 @@ gfx::Transform transform_to_root; std::unique_ptr<RenderPass> pass = CreateTestRenderPass(id, rect, transform_to_root); + pass->has_transparent_background = false; bool swizzle_contents = true; bool contents_premultiplied = true; @@ -3334,7 +3337,7 @@ EXPECT_TRUE(this->RunPixelTest( &pass_list, base::FilePath(FILE_PATH_LITERAL("force_anti_aliasing_off.png")), - cc::ExactPixelComparator(false))); + cc::ExactPixelComparator(/*discard_alpha=*/true))); } // This test tests that forcing anti-aliasing off works as expected while @@ -3347,17 +3350,24 @@ gfx::Transform transform_to_root; std::unique_ptr<RenderPass> pass = CreateTestRenderPass(id, rect, transform_to_root); + pass->has_transparent_background = false; CreateTestAxisAlignedQuads(rect, 0x800000FF, 0x8000FF00, true, true, pass.get()); + SharedQuadState* background_quad_state = CreateTestSharedQuadState( + gfx::Transform(), rect, pass.get(), gfx::RRectF()); + auto* background_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + background_quad->SetNew(background_quad_state, rect, rect, SK_ColorBLACK, + false); + RenderPassList pass_list; pass_list.push_back(std::move(pass)); EXPECT_TRUE(this->RunPixelTest( &pass_list, base::FilePath(FILE_PATH_LITERAL("translucent_quads_no_aa.png")), - cc::ExactPixelComparator(false))); + cc::ExactPixelComparator(/*discard_alpha=*/true))); } // Trilinear filtering is only supported in the gl renderer.
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index d9282995..aad1496 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -1489,12 +1489,12 @@ layout(ctype=float) in uniform half multiplier; void main(inout half4 color) { - color.rgb -= offset; - color.rgb *= multiplier; - // un-premultiply alpha if (color.a > 0) color.rgb /= color.a; + + color.rgb -= offset; + color.rgb *= multiplier; )"; const char* ftr = R"( // premultiply alpha
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc index 0237d951..b65c2e6 100644 --- a/components/viz/service/display/surface_aggregator.cc +++ b/components/viz/service/display/surface_aggregator.cc
@@ -414,7 +414,6 @@ } referenced_surfaces_.insert(surface_id); - bool has_surface_damage = !IsSurfaceFrameIndexSameAsPrevious(surface); // TODO(vmpstr): provider check is a hack for unittests that don't set up a // resource provider. std::unordered_map<ResourceId, ResourceId> empty_map; @@ -469,9 +468,8 @@ CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, surface->GetActiveFrame().device_scale_factor(), child_to_parent_map, gfx::Transform(), ClipData(), - copy_pass.get(), surface_id, has_surface_damage, - RoundedCornerInfo(), occluding_damage_rect, - occluding_damage_rect_valid); + copy_pass.get(), surface_id, RoundedCornerInfo(), + occluding_damage_rect, occluding_damage_rect_valid); // If the render pass has copy requests, or should be cached, or has // moving-pixel filters, or in a moving-pixel surface, we should damage the @@ -523,9 +521,8 @@ CopyQuadsToPass(quads, last_pass.shared_quad_state_list, surface->GetActiveFrame().device_scale_factor(), child_to_parent_map, surface_transform, quads_clip, - dest_pass, surface_id, has_surface_damage, - rounded_corner_info, occluding_damage_rect, - occluding_damage_rect_valid); + dest_pass, surface_id, rounded_corner_info, + occluding_damage_rect, occluding_damage_rect_valid); } else { auto* shared_quad_state = CopyAndScaleSharedQuadState( source_sqs, scaled_quad_to_target_transform, target_transform, @@ -535,8 +532,8 @@ gfx::ScaleToEnclosingRect(source_sqs->visible_quad_layer_rect, layer_to_content_scale_x, layer_to_content_scale_y), - clip_rect, dest_pass, has_surface_damage, rounded_corner_info, - occluding_damage_rect, occluding_damage_rect_valid); + clip_rect, dest_pass, rounded_corner_info, occluding_damage_rect, + occluding_damage_rect_valid); gfx::Rect scaled_rect(gfx::ScaleToEnclosingRect( source_rect, layer_to_content_scale_x, layer_to_content_scale_y)); @@ -568,11 +565,11 @@ // surface specified so create a SolidColorDrawQuad with the default // background color. SkColor background_color = surface_quad->default_background_color; - auto* shared_quad_state = CopySharedQuadState( - surface_quad->shared_quad_state, target_transform, clip_rect, dest_pass, - /*has_surface_damage*/ true, rounded_corner_info, - /*occluding_damage_rect*/ gfx::Rect(), - /*occluding_damage_rect_valid*/ false); + auto* shared_quad_state = + CopySharedQuadState(surface_quad->shared_quad_state, target_transform, + clip_rect, dest_pass, rounded_corner_info, + /*occluding_damage_rect*/ gfx::Rect(), + /*occluding_damage_rect_valid*/ false); auto* solid_color_quad = dest_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); @@ -614,7 +611,7 @@ primary_shared_quad_state, primary_shared_quad_state->quad_to_target_transform, target_transform, right_gutter_rect, right_gutter_rect, clip_rect, dest_pass, - /*has_surface_damage*/ true, rounded_corner_info, + rounded_corner_info, /*occluding_damage_rect*/ gfx::Rect(), /*occluding_damage_rect_valid*/ false); @@ -633,7 +630,7 @@ primary_shared_quad_state, primary_shared_quad_state->quad_to_target_transform, target_transform, bottom_gutter_rect, bottom_gutter_rect, clip_rect, dest_pass, - /*has_surface_damage*/ true, rounded_corner_info, + rounded_corner_info, /*occluding_damage_rect*/ gfx::Rect(), /*occluding_damage_rect_valid*/ false); @@ -690,15 +687,14 @@ const gfx::Transform& target_transform, const ClipData& clip_rect, RenderPass* dest_render_pass, - bool has_surface_damage, const RoundedCornerInfo& rounded_corner_info, const gfx::Rect& occluding_damage_rect, bool occluding_damage_rect_valid) { return CopyAndScaleSharedQuadState( source_sqs, source_sqs->quad_to_target_transform, target_transform, source_sqs->quad_layer_rect, source_sqs->visible_quad_layer_rect, - clip_rect, dest_render_pass, has_surface_damage, rounded_corner_info, - occluding_damage_rect, occluding_damage_rect_valid); + clip_rect, dest_render_pass, rounded_corner_info, occluding_damage_rect, + occluding_damage_rect_valid); } SharedQuadState* SurfaceAggregator::CopyAndScaleSharedQuadState( @@ -709,7 +705,6 @@ const gfx::Rect& visible_quad_layer_rect, const ClipData& clip_rect, RenderPass* dest_render_pass, - bool has_surface_damage, const RoundedCornerInfo& rounded_corner_info, const gfx::Rect& occluding_damage_rect, bool occluding_damage_rect_valid) { @@ -733,7 +728,6 @@ *rounded_corner_info.bounds, new_clip_rect.rect, new_clip_rect.is_clipped, source_sqs->are_contents_opaque, source_sqs->opacity, source_sqs->blend_mode, source_sqs->sorting_context_id); - shared_quad_state->has_surface_damage = has_surface_damage; shared_quad_state->is_fast_rounded_corner = rounded_corner_info.is_fast_rounded_corner; if (occluding_damage_rect_valid) { @@ -752,7 +746,6 @@ const ClipData& clip_rect, RenderPass* dest_pass, const SurfaceId& surface_id, - bool has_surface_damage, const RoundedCornerInfo& parent_rounded_corner_info, const gfx::Rect& occluding_damage_rect, bool occluding_damage_rect_valid) { @@ -817,7 +810,7 @@ } const SharedQuadState* dest_shared_quad_state = CopySharedQuadState( quad->shared_quad_state, target_transform, clip_rect, dest_pass, - has_surface_damage, new_rounded_corner_info, occluding_damage_rect, + new_rounded_corner_info, occluding_damage_rect, occluding_damage_rect_valid); last_copied_source_shared_quad_state = quad->shared_quad_state; @@ -893,9 +886,6 @@ if (!valid_surfaces_.count(surface->surface_id())) return; - // No changes in the target surface if it's the same as the previous frame - // This information will be used later in overlay processing. - bool has_surface_damage = !IsSurfaceFrameIndexSameAsPrevious(surface); // TODO(vmpstr): provider check is a hack for unittests that don't set up a // resource provider. std::unordered_map<ResourceId, ResourceId> empty_map; @@ -931,9 +921,8 @@ CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, frame.device_scale_factor(), child_to_parent_map, gfx::Transform(), ClipData(), copy_pass.get(), - surface->surface_id(), has_surface_damage, - RoundedCornerInfo(), occluding_damage_rect, - occluding_damage_rect_valid); + surface->surface_id(), RoundedCornerInfo(), + occluding_damage_rect, occluding_damage_rect_valid); // If the render pass has copy requests, or should be cached, or has // moving-pixel filters, or in a moving-pixel surface, we should damage the
diff --git a/components/viz/service/display/surface_aggregator.h b/components/viz/service/display/surface_aggregator.h index ffacddf..14604f1 100644 --- a/components/viz/service/display/surface_aggregator.h +++ b/components/viz/service/display/surface_aggregator.h
@@ -151,7 +151,6 @@ const gfx::Transform& target_transform, const ClipData& clip_rect, RenderPass* dest_render_pass, - bool has_surface_damage, const RoundedCornerInfo& rounded_corner_info, const gfx::Rect& occluding_damage_rect, bool occluding_damage_rect_valid); @@ -164,7 +163,6 @@ const gfx::Rect& visible_quad_layer_rect, const ClipData& clip_rect, RenderPass* dest_render_pass, - bool has_surface_damage, const RoundedCornerInfo& rounded_corner_info, const gfx::Rect& occluding_damage_rect, bool occluding_damage_rect_valid); @@ -178,7 +176,6 @@ const ClipData& clip_rect, RenderPass* dest_pass, const SurfaceId& surface_id, - bool has_surface_damage, const RoundedCornerInfo& rounded_corner_info, const gfx::Rect& occluding_damage_rect, bool occluding_damage_rect_valid);
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc index 599a005a..6c6a17a 100644 --- a/components/viz/service/display/surface_aggregator_unittest.cc +++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -5158,98 +5158,5 @@ EXPECT_EQ(1u, aggregated_pass_list[2]->quad_list.size()); } } - -TEST_F(SurfaceAggregatorValidSurfaceTest, NoDamageIfNoFrameChange) { - // child surface - std::vector<Quad> child_surface_quads = { - Quad::SolidColorQuad(SK_ColorRED, gfx::Rect(SurfaceSize()))}; - std::vector<Pass> child_surface_passes = { - Pass(child_surface_quads, 1, SurfaceSize())}; - - CompositorFrame child_surface_frame = MakeEmptyCompositorFrame(); - AddPasses(&child_surface_frame.render_pass_list, child_surface_passes, - &child_surface_frame.metadata.referenced_surfaces); - - ParentLocalSurfaceIdAllocator allocator; - allocator.GenerateId(); - LocalSurfaceId child_local_surface_id = - allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(); - SurfaceId child_surface_id(child_sink_->frame_sink_id(), - child_local_surface_id); - child_sink_->SubmitCompositorFrame(child_local_surface_id, - std::move(child_surface_frame)); - - // root surface - std::vector<Quad> root_surface_quads = { - Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id), - SK_ColorWHITE, gfx::Rect(SurfaceSize()), - /*stretch_content_to_fill_bounds=*/false, - /*ignores_input_event=*/false), - Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(SurfaceSize()))}; - - std::vector<Pass> root_passes = {Pass(root_surface_quads, 1, SurfaceSize())}; - - CompositorFrame root_frame = MakeEmptyCompositorFrame(); - AddPasses(&root_frame.render_pass_list, root_passes, - &root_frame.metadata.referenced_surfaces); - - SurfaceId root_surface_id(root_sink_->frame_sink_id(), - root_local_surface_id_); - root_sink_->SubmitCompositorFrame(root_local_surface_id_, - std::move(root_frame)); - // The first frame - both root and child surfaces cause damages - CompositorFrame aggregated_frame = - aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); - - auto* root_render_pass = aggregated_frame.render_pass_list[0].get(); - auto* root_surface_quad_sqs = root_render_pass->shared_quad_state_list.back(); - auto* child_surface_quad_sqs = - root_render_pass->shared_quad_state_list.front(); - - ASSERT_EQ(1u, aggregated_frame.render_pass_list.size()); - ASSERT_EQ(2u, root_render_pass->shared_quad_state_list.size()); - EXPECT_EQ(true, root_surface_quad_sqs->has_surface_damage); - EXPECT_EQ(true, child_surface_quad_sqs->has_surface_damage); - - // The second frame - only root surface changed - CompositorFrame root_frame2 = MakeEmptyCompositorFrame(); - AddPasses(&root_frame2.render_pass_list, root_passes, - &root_frame2.metadata.referenced_surfaces); - - root_sink_->SubmitCompositorFrame(root_local_surface_id_, - std::move(root_frame2)); - - CompositorFrame aggregated_frame2 = - aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); - - auto* root_render_pass2 = aggregated_frame2.render_pass_list[0].get(); - auto* root_surface_quad_sqs2 = - root_render_pass2->shared_quad_state_list.back(); - auto* child_surface_quad_sqs2 = - root_render_pass2->shared_quad_state_list.front(); - - EXPECT_EQ(true, root_surface_quad_sqs2->has_surface_damage); - EXPECT_EQ(false, child_surface_quad_sqs2->has_surface_damage); - - // The third frame - only child surface changed - CompositorFrame child_surface_frame3 = MakeEmptyCompositorFrame(); - AddPasses(&child_surface_frame3.render_pass_list, child_surface_passes, - &child_surface_frame3.metadata.referenced_surfaces); - child_sink_->SubmitCompositorFrame(child_local_surface_id, - std::move(child_surface_frame3)); - - CompositorFrame aggregated_frame3 = - aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement()); - - auto* root_render_pass3 = aggregated_frame3.render_pass_list[0].get(); - auto* root_surface_quad_sqs3 = - root_render_pass3->shared_quad_state_list.back(); - auto* child_surface_quad_sqs3 = - root_render_pass3->shared_quad_state_list.front(); - - EXPECT_EQ(false, root_surface_quad_sqs3->has_surface_damage); - EXPECT_EQ(true, child_surface_quad_sqs3->has_surface_damage); -} - } // namespace } // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.cc b/components/viz/service/display_embedder/skia_output_device_offscreen.cc index e976bb2..19779ec9 100644 --- a/components/viz/service/display_embedder/skia_output_device_offscreen.cc +++ b/components/viz/service/display_embedder/skia_output_device_offscreen.cc
@@ -28,15 +28,23 @@ float device_scale_factor, const gfx::ColorSpace& color_space, bool has_alpha) { - image_info_ = SkImageInfo::Make( - size.width(), size.height(), - has_alpha_ ? kRGBA_8888_SkColorType : kRGB_888x_SkColorType, - has_alpha_ ? kPremul_SkAlphaType : kOpaque_SkAlphaType); + // Some Vulkan drivers do not support kRGB_888x_SkColorType. Always use + // kRGBA_8888_SkColorType instead and initialize surface to opaque alpha. + image_info_ = + SkImageInfo::Make(size.width(), size.height(), kRGBA_8888_SkColorType, + has_alpha_ ? kPremul_SkAlphaType : kOpaque_SkAlphaType); draw_surface_ = SkSurface::MakeRenderTarget( gr_context_, SkBudgeted::kNo, image_info_, 0 /* sampleCount */, capabilities_.flipped_output_surface ? kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin, nullptr /* surfaceProps */); + DCHECK(!!draw_surface_); + + // Initialize alpha channel to opaque. + if (!has_alpha_) { + auto* canvas = draw_surface_->getCanvas(); + canvas->clear(SkColorSetARGB(255, 0, 0, 0)); + } } gfx::SwapResponse SkiaOutputDeviceOffscreen::PostSubBuffer(
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc index cb3b02f..0cabcc1 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -342,7 +342,13 @@ yuva_sizes[i].set(metadata.size.width(), metadata.size.height()); auto& image_context = promise_image_cache_[metadata.resource_id]; if (!image_context) { - image_context = std::make_unique<ImageContext>(metadata); + // color_space is ignored by makeYUVAPromiseTexture below. Passing nullptr + // removes some LOG spam. + image_context = std::make_unique<ImageContext>( + metadata.mailbox_holder.mailbox, metadata.size, + metadata.resource_format, nullptr /* color_space */, + metadata.alpha_type, metadata.origin, + metadata.mailbox_holder.sync_token); } if (image_context->sync_token.HasData()) { resource_sync_tokens_.push_back(image_context->sync_token);
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc index 3592f08..22d3b35 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
@@ -33,11 +33,14 @@ #if BUILDFLAG(ENABLE_VULKAN) #include "gpu/vulkan/init/vulkan_factory.h" +#include "gpu/vulkan/tests/native_window.h" #include "gpu/vulkan/vulkan_implementation.h" #endif namespace viz { +const gfx::Rect kSurfaceRect(0, 0, 100, 100); + static void ExpectEquals(SkBitmap actual, SkBitmap expected) { EXPECT_EQ(actual.dimensions(), expected.dimensions()); auto expected_url = cc::GetPNGDataUrl(expected); @@ -45,7 +48,7 @@ EXPECT_TRUE(actual_url == expected_url); } -class SkiaOutputSurfaceImplTest : public testing::Test { +class SkiaOutputSurfaceImplTest : public testing::TestWithParam<bool> { public: void CheckSyncTokenOnGpuThread(const gpu::SyncToken& sync_token); void CopyRequestCallbackOnGpuThread(const SkColor output_color, @@ -57,7 +60,8 @@ SkiaOutputSurfaceImplTest() : output_surface_client_(std::make_unique<cc::FakeOutputSurfaceClient>()), wait_(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED) {} + base::WaitableEvent::InitialState::NOT_SIGNALED), + on_screen_(GetParam()) {} inline void SetUp() override { SetUpSkiaOutputSurfaceImpl(); } void TearDown() override; void BlockMainThread(); @@ -88,6 +92,7 @@ std::unique_ptr<cc::FakeOutputSurfaceClient> output_surface_client_; std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_; base::WaitableEvent wait_; + const bool on_screen_; }; void SkiaOutputSurfaceImplTest::BlockMainThread() { @@ -196,9 +201,18 @@ BlockMainThread(); // Set up the SkiaOutputSurfaceImpl. + gpu::SurfaceHandle surface_handle_ = gpu::kNullSurfaceHandle; + if (on_screen_) { +#if BUILDFLAG(ENABLE_VULKAN) && defined(USE_X11) + surface_handle_ = gpu::CreateNativeWindow(kSurfaceRect); +#else + // TODO(backer): Support other platforms. + NOTREACHED(); +#endif + } output_surface_ = std::make_unique<SkiaOutputSurfaceImpl>( - gpu_service_.get(), gpu::kNullSurfaceHandle, - UpdateVSyncParametersCallback(), RendererSettings()); + gpu_service_.get(), surface_handle_, UpdateVSyncParametersCallback(), + RendererSettings()); output_surface_->BindToClient(output_surface_client_.get()); } @@ -232,10 +246,18 @@ UnblockMainThread(); } -TEST_F(SkiaOutputSurfaceImplTest, SubmitPaint) { - const gfx::Rect surface_rect(0, 0, 100, 100); - output_surface_->Reshape(surface_rect.size(), 1, gfx::ColorSpace(), true, - false); +INSTANTIATE_TEST_SUITE_P(SkiaOutputSurfaceImplTest, + SkiaOutputSurfaceImplTest, +#if BUILDFLAG(ENABLE_VULKAN) && defined(USE_X11) + ::testing::Values(false, true) +#else + ::testing::Values(false) +#endif +); + +TEST_P(SkiaOutputSurfaceImplTest, SubmitPaint) { + output_surface_->Reshape(kSurfaceRect.size(), 1, gfx::ColorSpace(), + false /* has_alpha */, false /* use_stencil */); SkCanvas* root_canvas = output_surface_->BeginPaintCurrentFrame(); SkPaint paint; const SkColor output_color = SK_ColorRED; @@ -266,9 +288,9 @@ color_space)); request->set_result_task_runner(gpu_thread_->task_runner()); copy_output::RenderPassGeometry geometry; - geometry.result_bounds = surface_rect; + geometry.result_bounds = kSurfaceRect; geometry.result_selection = output_rect; - geometry.sampling_bounds = surface_rect; + geometry.sampling_bounds = kSurfaceRect; if (is_vulkan_enabled()) { // No flipping because Skia handles all co-ordinate transformation on the
diff --git a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc index 9955da0..382a986 100644 --- a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc +++ b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
@@ -1580,39 +1580,34 @@ } // This test verifies that CompositorFrames submitted to a surface referenced -// by a parent CompositorFrame as a fallback will be rejected and ACK'ed -// immediately. +// by a parent CompositorFrame as a fallback will be ACK'ed immediately. TEST_F(SurfaceSynchronizationTest, FallbackSurfacesClosed) { const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1); // This is the fallback child surface that the parent holds a reference to. const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1); // This is the primary child surface that the parent wants to block on. const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink1, 2); + const SurfaceId arbitrary_id = MakeSurfaceId(kChildFrameSink2, 3); - // child_support1 submits a CompositorFrame without any dependencies. - // DidReceiveCompositorFrameAck should call on immediate activation. - // However, resources will not be returned because this frame is a candidate - // for display. - TransferableResource resource; - resource.id = 1337; - resource.format = ALPHA_8; - resource.filter = 1234; - resource.size = gfx::Size(1234, 5678); - std::vector<ReturnedResource> returned_resources = - TransferableResource::ReturnResources({resource}); + SendNextBeginFrame(); - EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck( - Eq(std::vector<ReturnedResource>()))); + // child_support1 submits a CompositorFrame with unresolved dependencies. + // DidReceiveCompositorFrameAck should not be called because the frame hasn't + // activated yet. + EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0); child_support1().SubmitCompositorFrame( child_id1.local_surface_id(), - MakeCompositorFrame(empty_surface_ids(), empty_surface_ranges(), - {resource}, MakeDefaultDeadline())); - EXPECT_FALSE(child_surface1()->has_deadline()); + MakeCompositorFrame({arbitrary_id}, + {SurfaceRange(base::nullopt, arbitrary_id)}, {}, + MakeDefaultDeadline())); + EXPECT_TRUE(child_surface1()->has_deadline()); + EXPECT_TRUE(child_surface1()->HasPendingFrame()); + EXPECT_FALSE(child_surface1()->HasActiveFrame()); testing::Mock::VerifyAndClearExpectations(&support_client_); - // The parent is blocked on |child_id2| and references |child_id1|. The - // surface corresponding to |child_id1| will not accept new CompositorFrames - // while the parent CompositorFrame is blocked. + // The parent is blocked on |child_id2| and references |child_id1|. + // |child_id1| should immediately activate and the ack must be sent. + EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)); parent_support().SubmitCompositorFrame( parent_id1.local_surface_id(), MakeCompositorFrame({child_id2}, {SurfaceRange(child_id1, child_id2)}, @@ -1621,43 +1616,22 @@ EXPECT_TRUE(parent_surface()->has_deadline()); EXPECT_TRUE(parent_surface()->HasPendingFrame()); EXPECT_FALSE(parent_surface()->HasActiveFrame()); - - // Resources will be returned immediately because |child_id1|'s surface is - // closed. - TransferableResource resource2; - resource2.id = 1246; - resource2.format = ALPHA_8; - resource2.filter = 1357; - resource2.size = gfx::Size(8765, 4321); - std::vector<ReturnedResource> returned_resources2 = - TransferableResource::ReturnResources({resource2}); - EXPECT_CALL(support_client_, - DidReceiveCompositorFrameAck(Eq(returned_resources2))); - child_support1().SubmitCompositorFrame( - child_id1.local_surface_id(), - MakeCompositorFrame(empty_surface_ids(), empty_surface_ranges(), - {resource2}, MakeDefaultDeadline())); + EXPECT_FALSE(child_surface1()->HasPendingFrame()); + EXPECT_TRUE(child_surface1()->HasActiveFrame()); testing::Mock::VerifyAndClearExpectations(&support_client_); - // Advance BeginFrames to trigger a deadline. This activates the - // CompositorFrame submitted to the parent. - for (int i = 0; i < 3; ++i) { - SendNextBeginFrame(); - EXPECT_TRUE(parent_surface()->has_deadline()); - } + // Any further CompositorFrames sent to |child_id1| will also activate + // immediately so that the child can submit another frame and catch up with + // the parent. SendNextBeginFrame(); - EXPECT_FALSE(parent_surface()->has_deadline()); - EXPECT_FALSE(parent_surface()->HasPendingFrame()); - EXPECT_TRUE(parent_surface()->HasActiveFrame()); - - // Resources will be returned immediately because |child_id1|'s surface is - // closed forever. - EXPECT_CALL(support_client_, - DidReceiveCompositorFrameAck(Eq(returned_resources2))); + EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)); child_support1().SubmitCompositorFrame( child_id1.local_surface_id(), - MakeCompositorFrame(empty_surface_ids(), empty_surface_ranges(), - {resource2}, MakeDefaultDeadline())); + MakeCompositorFrame({arbitrary_id}, + {SurfaceRange(base::nullopt, arbitrary_id)}, {}, + MakeDefaultDeadline())); + EXPECT_FALSE(child_surface1()->HasPendingFrame()); + EXPECT_TRUE(child_surface1()->HasActiveFrame()); testing::Mock::VerifyAndClearExpectations(&support_client_); }
diff --git a/components/viz/service/surfaces/surface.cc b/components/viz/service/surfaces/surface.cc index 0e77d14a..f16d0a1 100644 --- a/components/viz/service/surfaces/surface.cc +++ b/components/viz/service/surfaces/surface.cc
@@ -41,6 +41,8 @@ "Surface", this, "surface_info", surface_info.ToString()); allocation_group_->RegisterSurface(this); + is_fallback_ = + allocation_group_->GetLastReference().IsNewerThan(surface_id()); } Surface::~Surface() { @@ -89,31 +91,6 @@ surface_client_->UnrefResources(resources); } -void Surface::RejectCompositorFramesToFallbackSurfaces() { - for (const SurfaceRange& surface_range : - GetPendingFrame().metadata.referenced_surfaces) { - // Only close the fallback surface if it exists, has a different - // LocalSurfaceId than the primary surface but has the same FrameSinkId - // as the primary surface. - if (!surface_range.start() || - surface_range.start() == surface_range.end() || - surface_range.start()->frame_sink_id() != - surface_range.end().frame_sink_id()) { - continue; - } - Surface* fallback_surface = - surface_manager_->GetLatestInFlightSurface(surface_range); - - // A misbehaving client may report a non-existent surface ID as a - // |referenced_surface|. In that case, |surface| would be nullptr, and - // there is nothing to do here. - if (fallback_surface && - fallback_surface->surface_id() != surface_range.end()) { - fallback_surface->Close(); - } - } -} - void Surface::UpdateSurfaceReferences() { const base::flat_set<SurfaceId>& existing_referenced_surfaces = surface_manager_->GetSurfacesReferencedByParent(surface_id()); @@ -202,8 +179,10 @@ ActivatePendingFrame(base::nullopt); } -void Surface::Close() { - closed_ = true; +void Surface::SetIsFallbackAndMaybeActivate() { + is_fallback_ = true; + if (HasPendingFrame()) + ActivatePendingFrameForDeadline(base::nullopt); } bool Surface::QueueFrame( @@ -218,9 +197,6 @@ return false; } - if (closed_) - return true; - is_latency_info_taken_ = false; if (active_frame_data_ || pending_frame_data_) @@ -255,7 +231,6 @@ } else { pending_frame_data_ = FrameData(std::move(frame), frame_index, std::move(presented_callback)); - RejectCompositorFramesToFallbackSurfaces(); // If the deadline is in the past, then the CompositorFrame will activate // immediately. @@ -481,14 +456,18 @@ FrameDeadline Surface::ResolveFrameDeadline( const CompositorFrame& current_frame) { + // Fallback surfaces should activate immediately so that the client receives + // the ack and can submit a frame to the primary surface. + if (is_fallback_) + return FrameDeadline::MakeZero(); + // If there is an embedder of this surface that has already activated, that // means the embedder doesn't wish to block on this surface, i.e. either it // had a zero deadline or its deadline has already passed. If we don't have an // active frame already, active this frame immediately so we have something to // show. if (!HasActiveFrame() && - allocation_group_->GetLastActiveReference().IsSameOrNewerThan( - surface_id())) { + allocation_group_->GetLastActiveReference() == surface_id()) { return FrameDeadline::MakeZero(); }
diff --git a/components/viz/service/surfaces/surface.h b/components/viz/service/surfaces/surface.h index 2f8d332..38cb28f 100644 --- a/components/viz/service/surfaces/surface.h +++ b/components/viz/service/surfaces/surface.h
@@ -238,6 +238,13 @@ // Called when this surface's activation no longer has to block on the parent. void ResetBlockActivationOnParent(); + // Notifies that this surface is no longer the primary surface of the + // embedder. All future CompositorFrames will activate as soon as they arrive + // and if a pending frame currently exists it will immediately activate as + // well. This allows the client to not wait for acks from the fallback + // surfaces and be able to submit to the primary surface. + void SetIsFallbackAndMaybeActivate(); + private: struct FrameData { FrameData(CompositorFrame&& frame, @@ -256,20 +263,11 @@ PresentedCallback presented_callback; }; - // Rejects CompositorFrames submitted to surfaces referenced from this - // CompositorFrame as fallbacks. This saves some CPU cycles to allow - // children to catch up to the parent. - void RejectCompositorFramesToFallbackSurfaces(); - // Updates surface references of the surface using the referenced // surfaces from the most recent CompositorFrame. // Modifies surface references stored in SurfaceManager. void UpdateSurfaceReferences(); - // Called to prevent additional CompositorFrames from being accepted into this - // surface. Once a Surface is closed, it cannot accept CompositorFrames again. - void Close(); - // Updates the set of allocation groups referenced by the active frame. Calls // RegisterEmbedder and UnregisterEmbedder on the allocation groups as // appropriate. @@ -314,7 +312,6 @@ base::Optional<FrameData> pending_frame_data_; base::Optional<FrameData> active_frame_data_; - bool closed_ = false; bool seen_first_frame_activation_ = false; bool seen_first_surface_embedding_ = false; bool seen_first_surface_dependency_ = false; @@ -344,6 +341,8 @@ // surface to let us know. base::flat_set<SurfaceAllocationGroup*> blocking_allocation_groups_; + bool is_fallback_ = false; + bool is_latency_info_taken_ = false; SurfaceAllocationGroup* const allocation_group_;
diff --git a/components/viz/service/surfaces/surface_allocation_group.cc b/components/viz/service/surfaces/surface_allocation_group.cc index a61c55b..9613fa3 100644 --- a/components/viz/service/surfaces/surface_allocation_group.cc +++ b/components/viz/service/surfaces/surface_allocation_group.cc
@@ -241,7 +241,17 @@ auto it = FindLatestSurfaceUpTo(surface_id); if (it == surfaces_.end()) return; + // Notify that |*it| is now embedded. This might unblock |*it| if it was + // blocked due to child throttling. (*it)->OnSurfaceDependencyAdded(); + // If |surface_id| does not exist yet, notify the surface immediately prior to + // it that it is a fallback. This might activate the surface immediately + // because fallback surfaces never block. + if ((*it)->surface_id() != surface_id) + (*it)->SetIsFallbackAndMaybeActivate(); + // Since child throttling allows up to two unembedded surfaces, the surface + // immediately after |it| should not be throttled even if it is not embedded + // yet. ++it; if (it == surfaces_.end()) return;
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 41b3e41..9d8f8c5 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -1953,10 +1953,8 @@ ResetExpectedProcess(); - if (expected_process == nullptr) { - expected_render_process_host_id_ = ChildProcessHost::kInvalidUniqueID; + if (expected_process == nullptr) return; - } // Keep track of the speculative RenderProcessHost and tell it to expect a // navigation to |site_url_|.
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc index 5cb04c8b..40c93088 100644 --- a/content/browser/frame_host/render_frame_host_manager.cc +++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -72,6 +72,45 @@ url.scheme() == url::kDataScheme; } +// Helper function to determine whether a navigation from |current_rfh| to +// |dest_url| should swap BrowsingInstances to ensure that |dest_url| ends up +// in a dedicated process. This is the case when |dest_url| has an origin that +// was just isolated dynamically, where leaving the navigation in the current +// BrowsingInstance would leave |dest_url| without a dedicated process, since +// dynamic origin isolation applies only to future BrowsingInstances. In the +// common case where |current_rfh| is a main frame, and there are no scripting +// references to it from other windows, it is safe to swap BrowsingInstances to +// ensure the new isolated origin takes effect. Note that this applies even to +// same-site navigations, as well as to renderer-initiated navigations. +bool ShouldSwapBrowsingInstancesForDynamicIsolation( + RenderFrameHostImpl* current_rfh, + const GURL& dest_url) { + // Only main frames are eligible to swap BrowsingInstances. + if (!current_rfh->frame_tree_node()->IsMainFrame()) + return false; + + // Skip cases when there are other windows that might script this one. + SiteInstanceImpl* current_instance = current_rfh->GetSiteInstance(); + if (current_instance->GetRelatedActiveContentsCount() > 1u) + return false; + + // Check whether |dest_url| would require a dedicated process if we left it + // in the current BrowsingInstance. If so, there's no need to swap + // BrowsingInstances. + if (SiteInstanceImpl::DoesSiteRequireDedicatedProcess( + current_instance->GetIsolationContext(), dest_url)) { + return false; + } + + // Finally, check whether |dest_url| would require a dedicated process if we + // were to swap to a fresh BrowsingInstance. To check this, use a new + // IsolationContext, rather than current_instance->GetIsolationContext(). + IsolationContext future_isolation_context( + current_instance->GetBrowserContext()); + return SiteInstanceImpl::DoesSiteRequireDedicatedProcess( + future_isolation_context, dest_url); +} + } // namespace RenderFrameHostManager::RenderFrameHostManager(FrameTreeNode* frame_tree_node, @@ -1020,6 +1059,18 @@ if (current_is_view_source_mode != new_is_view_source_mode) return true; + // If the target URL's origin was dynamically isolated, and the isolation + // wouldn't apply in the current BrowsingInstance, see if this navigation can + // safely swap to a new BrowsingInstance where this isolation would take + // effect. This helps protect sites that have just opted into process + // isolation, ensuring that the next navigation (e.g., a form submission + // after user has typed in a password) can utilize a dedicated process when + // possible (e.g., when there are no existing script references). + if (ShouldSwapBrowsingInstancesForDynamicIsolation(render_frame_host_.get(), + new_effective_url)) { + return true; + } + return false; } @@ -1521,6 +1572,14 @@ if (rfh->GetSiteInstance()->GetSiteURL().SchemeIs(kGuestScheme)) return false; + // Attempt a transfer if |dest_url|'s origin was dynamically isolated, and + // this navigation is eligible to perform a BrowsingInstance swap to ensure + // that |dest_url| is placed into a dedicated process. This is important to + // check before IsCurrentlySameSite() below, since in this case we might swap + // BrowsingInstances even for same-site navigations. + if (ShouldSwapBrowsingInstancesForDynamicIsolation(rfh, dest_url)) + return true; + // TODO(nasko, nick): These following --site-per-process checks are // overly simplistic. Update them to match all the cases // considered by DetermineSiteInstanceForURL.
diff --git a/content/browser/isolated_origin_browsertest.cc b/content/browser/isolated_origin_browsertest.cc index 538fb56..b85bc74 100644 --- a/content/browser/isolated_origin_browsertest.cc +++ b/content/browser/isolated_origin_browsertest.cc
@@ -1641,6 +1641,14 @@ Shell* shell3 = CreateBrowser(); EXPECT_TRUE(NavigateToURL(shell3, foo_url)); + // Create window.open popups in all three windows, which would prevent a + // BrowsingInstance swap on renderer-initiated navigations to newly isolated + // origins in these windows. + OpenPopup(shell(), foo_url, ""); + OpenPopup(shell2, GURL(url::kAboutBlankURL), ""); + OpenPopup(shell3, embedded_test_server()->GetURL("baz.com", "/title1.html"), + ""); + // Start isolating bar.com. GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title2.html")); auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); @@ -1953,6 +1961,188 @@ child->current_frame_host()->GetProcess()); } +// Check that a dynamically added isolated origin can take effect on the next +// main frame navigation by forcing a BrowsingInstance swap, in the case that +// there are no script references to the frame being navigated. +IN_PROC_BROWSER_TEST_F(DynamicIsolatedOriginTest, ForceBrowsingInstanceSwap) { + // This test is designed to run without strict site isolation. + if (AreAllSitesIsolatedForTesting()) + return; + + // Navigate to a non-isolated page with a cross-site iframe. The frame + // shouldn't be in an OOPIF. + GURL foo_url(embedded_test_server()->GetURL( + "foo.com", "/cross_site_iframe_factory.html?foo.com(bar.com)")); + EXPECT_TRUE(NavigateToURL(shell(), foo_url)); + FrameTreeNode* root = web_contents()->GetFrameTree()->root(); + FrameTreeNode* child = root->child_at(0); + scoped_refptr<SiteInstance> first_instance = + root->current_frame_host()->GetSiteInstance(); + EXPECT_EQ(first_instance, child->current_frame_host()->GetSiteInstance()); + EXPECT_EQ(root->current_frame_host()->GetProcess(), + child->current_frame_host()->GetProcess()); + auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); + EXPECT_EQ(GURL(), + policy->GetOriginLock(first_instance->GetProcess()->GetID())); + + // Start isolating foo.com. + BrowserContext* context = shell()->web_contents()->GetBrowserContext(); + policy->AddIsolatedOrigins({url::Origin::Create(foo_url)}, context); + + // Try navigating to another foo URL. + GURL foo2_url(embedded_test_server()->GetURL( + "foo.com", "/cross_site_iframe_factory.html?foo.com(baz.com)")); + EXPECT_TRUE(NavigateToURL(shell(), foo2_url)); + + // Verify that this navigation ended up in a dedicated process, and that we + // swapped BrowsingInstances in the process. + scoped_refptr<SiteInstance> second_instance = + root->current_frame_host()->GetSiteInstance(); + EXPECT_NE(first_instance, second_instance); + EXPECT_FALSE(first_instance->IsRelatedSiteInstance(second_instance.get())); + EXPECT_NE(first_instance->GetProcess(), second_instance->GetProcess()); + EXPECT_EQ(GURL("http://foo.com"), + policy->GetOriginLock(second_instance->GetProcess()->GetID())); + + // The frame on that page should now be an OOPIF. + child = root->child_at(0); + EXPECT_NE(second_instance, child->current_frame_host()->GetSiteInstance()); + EXPECT_NE(root->current_frame_host()->GetProcess(), + child->current_frame_host()->GetProcess()); +} + +// Same as the test above, but using a renderer-initiated navigation. Check +// that a dynamically added isolated origin can take effect on the next main +// frame navigation by forcing a BrowsingInstance swap, in the case that there +// are no script references to the frame being navigated. +IN_PROC_BROWSER_TEST_F(DynamicIsolatedOriginTest, + ForceBrowsingInstanceSwap_RendererInitiated) { + // This test is designed to run without strict site isolation. + if (AreAllSitesIsolatedForTesting()) + return; + + // Navigate to a foo.com page. + GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html")); + EXPECT_TRUE(NavigateToURL(shell(), foo_url)); + FrameTreeNode* root = web_contents()->GetFrameTree()->root(); + scoped_refptr<SiteInstance> first_instance = + root->current_frame_host()->GetSiteInstance(); + EXPECT_FALSE(first_instance->RequiresDedicatedProcess()); + auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); + EXPECT_EQ(GURL(), + policy->GetOriginLock(first_instance->GetProcess()->GetID())); + + // Set a sessionStorage value, to sanity check that foo.com's session storage + // will still be accessible after the BrowsingInstance swap. + EXPECT_TRUE(ExecJs(root, "window.sessionStorage['foo'] = 'bar';")); + + // Start isolating foo.com. + BrowserContext* context = shell()->web_contents()->GetBrowserContext(); + policy->AddIsolatedOrigins({url::Origin::Create(foo_url)}, context); + + // Do a renderer-initiated navigation to another foo URL. + GURL foo2_url(embedded_test_server()->GetURL( + "foo.com", "/cross_site_iframe_factory.html?foo.com(baz.com)")); + EXPECT_TRUE(NavigateToURLFromRenderer(shell(), foo2_url)); + + // Verify that this navigation ended up in a dedicated process, and that we + // swapped BrowsingInstances in the process. + scoped_refptr<SiteInstance> second_instance = + root->current_frame_host()->GetSiteInstance(); + EXPECT_NE(first_instance, second_instance); + EXPECT_FALSE(first_instance->IsRelatedSiteInstance(second_instance.get())); + EXPECT_NE(first_instance->GetProcess(), second_instance->GetProcess()); + EXPECT_EQ(GURL("http://foo.com"), + policy->GetOriginLock(second_instance->GetProcess()->GetID())); + + // The frame on that page should be an OOPIF. + FrameTreeNode* child = root->child_at(0); + EXPECT_NE(second_instance, child->current_frame_host()->GetSiteInstance()); + EXPECT_NE(root->current_frame_host()->GetProcess(), + child->current_frame_host()->GetProcess()); + + // Verify that the isolated foo.com page can still access session storage set + // by the previous foo.com page. + EXPECT_EQ("bar", EvalJs(root, "window.sessionStorage['foo']")); +} + +IN_PROC_BROWSER_TEST_F(DynamicIsolatedOriginTest, + DontForceBrowsingInstanceSwapWhenScriptReferencesExist) { + // This test is designed to run without strict site isolation. + if (AreAllSitesIsolatedForTesting()) + return; + + // Navigate to a page that won't be in a dedicated process. + GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html")); + EXPECT_TRUE(NavigateToURL(shell(), foo_url)); + FrameTreeNode* root = web_contents()->GetFrameTree()->root(); + scoped_refptr<SiteInstance> first_instance = + root->current_frame_host()->GetSiteInstance(); + EXPECT_FALSE(first_instance->RequiresDedicatedProcess()); + + // Start isolating foo.com. + BrowserContext* context = shell()->web_contents()->GetBrowserContext(); + auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); + policy->AddIsolatedOrigins({url::Origin::Create(foo_url)}, context); + + // Open a popup. + GURL popup_url(embedded_test_server()->GetURL("a.com", "/title1.html")); + OpenPopup(shell(), popup_url, ""); + + // Try navigating the main frame to another foo URL. + GURL foo2_url(embedded_test_server()->GetURL("foo.com", "/title2.html")); + EXPECT_TRUE(NavigateToURLFromRenderer(shell(), foo2_url)); + + // This navigation should not end up in a dedicated process. The popup + // should prevent the BrowsingInstance swap heuristic from applying, since it + // should still be able to communicate with the opener after the navigation. + EXPECT_EQ(first_instance, root->current_frame_host()->GetSiteInstance()); + EXPECT_FALSE(first_instance->RequiresDedicatedProcess()); + EXPECT_EQ(GURL(), + policy->GetOriginLock(first_instance->GetProcess()->GetID())); +} + +// This test ensures that when a page becomes isolated in the middle of +// creating and navigating a new window, the new window prevents a +// BrowsingInstance swap. +IN_PROC_BROWSER_TEST_F( + DynamicIsolatedOriginTest, + DontForceBrowsingInstanceSwapWithPendingNavigationInNewWindow) { + // This test is designed to run without strict site isolation. + if (AreAllSitesIsolatedForTesting()) + return; + + // Navigate to a page that won't be in a dedicated process. + GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html")); + EXPECT_TRUE(NavigateToURL(shell(), foo_url)); + FrameTreeNode* root = web_contents()->GetFrameTree()->root(); + scoped_refptr<SiteInstance> first_instance = + root->current_frame_host()->GetSiteInstance(); + EXPECT_FALSE(first_instance->RequiresDedicatedProcess()); + + // Open and start navigating a popup to a URL that never finishes loading. + GURL popup_url(embedded_test_server()->GetURL("a.com", "/hung")); + EXPECT_TRUE(ExecuteScript(root, JsReplace("window.open($1);", popup_url))); + + // Start isolating foo.com. + BrowserContext* context = shell()->web_contents()->GetBrowserContext(); + auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); + policy->AddIsolatedOrigins({url::Origin::Create(foo_url)}, context); + + // Navigate the main frame to another foo URL. + GURL foo2_url(embedded_test_server()->GetURL("foo.com", "/title2.html")); + EXPECT_TRUE(NavigateToURLFromRenderer(shell(), foo2_url)); + + // This navigation should not end up in a dedicated process. The pending + // navigation in the popup should prevent the BrowsingInstance swap heuristic + // from applying, since it should still be able to communicate with the + // opener after the navigation. + EXPECT_EQ(first_instance, root->current_frame_host()->GetSiteInstance()); + EXPECT_FALSE(first_instance->RequiresDedicatedProcess()); + EXPECT_EQ(GURL(), + policy->GetOriginLock(first_instance->GetProcess()->GetID())); +} + // This class allows intercepting the BroadcastChannelProvider::ConnectToChannel // method and changing the |origin| parameter before passing the call to the // real implementation of BroadcastChannelProvider.
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 3a68a60..34e46c4 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -12656,8 +12656,17 @@ EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value()); } +// Flaky on Android. http://crbug.com/951513 +#if defined(OS_ANDROID) +#define MAYBE_EffectiveTouchActionPropagatesAcrossNestedFrames \ + DISABLED_EffectiveTouchActionPropagatesAcrossNestedFrames +#else +#define MAYBE_EffectiveTouchActionPropagatesAcrossNestedFrames \ + EffectiveTouchActionPropagatesAcrossNestedFrames +#endif + IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest, - EffectiveTouchActionPropagatesAcrossNestedFrames) { + MAYBE_EffectiveTouchActionPropagatesAcrossNestedFrames) { GURL main_url(embedded_test_server()->GetURL( "a.com", "/cross_site_iframe_factory.html?a(b(c))")); EXPECT_TRUE(NavigateToURL(shell(), main_url));
diff --git a/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc b/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc index 725df9a..c4d58eb 100644 --- a/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc +++ b/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc
@@ -17,10 +17,13 @@ #include "mojo/public/cpp/bindings/binding.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "services/service_manager/public/cpp/connector.h" +#include "services/video_capture/public/cpp/mock_producer.h" #include "services/video_capture/public/mojom/constants.mojom.h" #include "services/video_capture/public/mojom/device_factory.mojom.h" #include "services/video_capture/public/mojom/device_factory_provider.mojom.h" #include "services/video_capture/public/mojom/devices_changed_observer.mojom.h" +#include "services/video_capture/public/mojom/producer.mojom.h" +#include "services/video_capture/public/mojom/video_source_provider.mojom.h" #include "services/video_capture/public/mojom/virtual_device.mojom.h" namespace content { @@ -36,6 +39,14 @@ namespace { +enum class ServiceApi { kSingleClient, kMultiClient }; +enum class VirtualDeviceType { kSharedMemory, kTexture }; + +struct TestParams { + ServiceApi api_to_use; + VirtualDeviceType device_type; +}; + static const char kVideoCaptureHtmlFile[] = "/media/video_capture_test.html"; static const char kEnumerateVideoCaptureDevicesAndVerify[] = "enumerateVideoCaptureDevicesAndVerifyCount(%d)"; @@ -53,6 +64,7 @@ // enumerated devices changes correspondingly. class WebRtcVideoCaptureServiceEnumerationBrowserTest : public ContentBrowserTest, + public testing::WithParamInterface<TestParams>, public video_capture::mojom::DevicesChangedObserver { public: WebRtcVideoCaptureServiceEnumerationBrowserTest() @@ -64,12 +76,23 @@ void ConnectToService() { connector_->BindInterface(video_capture::mojom::kServiceName, &provider_); - provider_->ConnectToDeviceFactory(mojo::MakeRequest(&factory_)); video_capture::mojom::DevicesChangedObserverPtr observer; devices_changed_observer_binding_.Bind(mojo::MakeRequest(&observer)); - factory_->RegisterVirtualDevicesChangedObserver( - std::move(observer), - false /*raise_event_if_virtual_devices_already_present*/); + switch (GetParam().api_to_use) { + case ServiceApi::kSingleClient: + provider_->ConnectToDeviceFactory(mojo::MakeRequest(&factory_)); + factory_->RegisterVirtualDevicesChangedObserver( + std::move(observer), + false /*raise_event_if_virtual_devices_already_present*/); + break; + case ServiceApi::kMultiClient: + provider_->ConnectToVideoSourceProvider( + mojo::MakeRequest(&video_source_provider_)); + video_source_provider_->RegisterVirtualDevicesChangedObserver( + std::move(observer), + false /*raise_event_if_virtual_devices_already_present*/); + break; + } } void AddVirtualDevice(const std::string& device_id) { @@ -80,10 +103,46 @@ base::RunLoop wait_loop; closure_to_be_called_on_devices_changed_ = wait_loop.QuitClosure(); - video_capture::mojom::TextureVirtualDevicePtr virtual_device; - factory_->AddTextureVirtualDevice(info, mojo::MakeRequest(&virtual_device)); - virtual_devices_by_id_.insert( - std::make_pair(device_id, std::move(virtual_device))); + switch (GetParam().device_type) { + case VirtualDeviceType::kSharedMemory: { + video_capture::mojom::SharedMemoryVirtualDevicePtr virtual_device; + video_capture::mojom::ProducerPtr producer; + auto mock_producer = std::make_unique<video_capture::MockProducer>( + mojo::MakeRequest(&producer)); + switch (GetParam().api_to_use) { + case ServiceApi::kSingleClient: + factory_->AddSharedMemoryVirtualDevice( + info, std::move(producer), false, + mojo::MakeRequest(&virtual_device)); + break; + case ServiceApi::kMultiClient: + video_source_provider_->AddSharedMemoryVirtualDevice( + info, std::move(producer), false, + mojo::MakeRequest(&virtual_device)); + break; + } + shared_memory_devices_by_id_.insert(std::make_pair( + device_id, std::make_pair(std::move(virtual_device), + std::move(mock_producer)))); + break; + } + case VirtualDeviceType::kTexture: { + video_capture::mojom::TextureVirtualDevicePtr virtual_device; + switch (GetParam().api_to_use) { + case ServiceApi::kSingleClient: + factory_->AddTextureVirtualDevice( + info, mojo::MakeRequest(&virtual_device)); + break; + case ServiceApi::kMultiClient: + video_source_provider_->AddTextureVirtualDevice( + info, mojo::MakeRequest(&virtual_device)); + break; + } + texture_devices_by_id_.insert( + std::make_pair(device_id, std::move(virtual_device))); + break; + } + } // Wait for confirmation from the service. wait_loop.Run(); } @@ -91,13 +150,22 @@ void RemoveVirtualDevice(const std::string& device_id) { base::RunLoop wait_loop; closure_to_be_called_on_devices_changed_ = wait_loop.QuitClosure(); - virtual_devices_by_id_.erase(device_id); + switch (GetParam().device_type) { + case VirtualDeviceType::kSharedMemory: + shared_memory_devices_by_id_.erase(device_id); + break; + case VirtualDeviceType::kTexture: + texture_devices_by_id_.erase(device_id); + break; + } + // Wait for confirmation from the service. wait_loop.Run(); } void DisconnectFromService() { factory_ = nullptr; + video_source_provider_ = nullptr; provider_ = nullptr; } @@ -160,7 +228,11 @@ std::unique_ptr<service_manager::Connector> connector_; std::map<std::string, video_capture::mojom::TextureVirtualDevicePtr> - virtual_devices_by_id_; + texture_devices_by_id_; + std::map<std::string, + std::pair<video_capture::mojom::SharedMemoryVirtualDevicePtr, + std::unique_ptr<video_capture::MockProducer>>> + shared_memory_devices_by_id_; private: mojo::Binding<video_capture::mojom::DevicesChangedObserver> @@ -168,12 +240,13 @@ base::test::ScopedFeatureList scoped_feature_list_; video_capture::mojom::DeviceFactoryProviderPtr provider_; video_capture::mojom::DeviceFactoryPtr factory_; + video_capture::mojom::VideoSourceProviderPtr video_source_provider_; base::OnceClosure closure_to_be_called_on_devices_changed_; DISALLOW_COPY_AND_ASSIGN(WebRtcVideoCaptureServiceEnumerationBrowserTest); }; -IN_PROC_BROWSER_TEST_F(WebRtcVideoCaptureServiceEnumerationBrowserTest, +IN_PROC_BROWSER_TEST_P(WebRtcVideoCaptureServiceEnumerationBrowserTest, SingleAddedVirtualDeviceGetsEnumerated) { Initialize(); ConnectToService(); @@ -187,7 +260,7 @@ DisconnectFromService(); } -IN_PROC_BROWSER_TEST_F(WebRtcVideoCaptureServiceEnumerationBrowserTest, +IN_PROC_BROWSER_TEST_P(WebRtcVideoCaptureServiceEnumerationBrowserTest, RemoveVirtualDeviceAfterItHasBeenEnumerated) { Initialize(); ConnectToService(); @@ -204,7 +277,7 @@ DisconnectFromService(); } -IN_PROC_BROWSER_TEST_F( +IN_PROC_BROWSER_TEST_P( WebRtcVideoCaptureServiceEnumerationBrowserTest, MAYBE_AddingAndRemovingVirtualDeviceTriggersMediaElementOnDeviceChange) { Initialize(); @@ -224,4 +297,13 @@ DisconnectFromService(); } +INSTANTIATE_TEST_SUITE_P( + , + WebRtcVideoCaptureServiceEnumerationBrowserTest, + ::testing::Values( + TestParams{ServiceApi::kSingleClient, VirtualDeviceType::kSharedMemory}, + TestParams{ServiceApi::kSingleClient, VirtualDeviceType::kTexture}, + TestParams{ServiceApi::kMultiClient, VirtualDeviceType::kSharedMemory}, + TestParams{ServiceApi::kMultiClient, VirtualDeviceType::kTexture})); + } // namespace content
diff --git a/content/common/cursors/webcursor.cc b/content/common/cursors/webcursor.cc index 1babc47..ba08cf1 100644 --- a/content/common/cursors/webcursor.cc +++ b/content/common/cursors/webcursor.cc
@@ -14,7 +14,7 @@ using blink::WebCursorInfo; -constexpr int kMaxImageSize = 1024; +constexpr int kMaxSize = 1024; namespace content { @@ -32,11 +32,11 @@ } WebCursor::WebCursor(const CursorInfo& info) : info_(info) { - CHECK(IsReasonableScale(info.image_scale_factor)) << info.image_scale_factor; - CHECK_LE(info.custom_image.width(), kMaxImageSize); - CHECK_LE(info.custom_image.height(), kMaxImageSize); - CHECK_LE(info.custom_image.width() / info.image_scale_factor, kMaxImageSize); - CHECK_LE(info.custom_image.height() / info.image_scale_factor, kMaxImageSize); + DCHECK(IsReasonableScale(info.image_scale_factor)) << info.image_scale_factor; + DCHECK_LE(info.custom_image.width(), kMaxSize); + DCHECK_LE(info.custom_image.height(), kMaxSize); + DCHECK_LE(info.custom_image.width() / info.image_scale_factor, kMaxSize); + DCHECK_LE(info.custom_image.height() / info.image_scale_factor, kMaxSize); ClampHotspot(); } @@ -61,9 +61,9 @@ if (!IPC::ParamTraits<SkBitmap>::Read(m, iter, &bitmap)) return false; - if (bitmap.width() > kMaxImageSize || bitmap.height() > kMaxImageSize || - bitmap.width() / scale > kMaxImageSize || - bitmap.height() / scale > kMaxImageSize) { + if (bitmap.width() > kMaxSize || bitmap.height() > kMaxSize || + bitmap.width() / scale > kMaxSize || + bitmap.height() / scale > kMaxSize) { return false; } }
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 19db0b6c..25dd5f5 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -82,7 +82,6 @@ "//third_party/blink/public/mojom:android_mojo_bindings_java", "//third_party/blink/public/mojom:mojom_core_java", "//third_party/blink/public/mojom:mojom_platform_java", - "//third_party/blink/public/mojom:speech_recognition_error_code_java", "//third_party/jsr-305:jsr_305_javalib", "//ui/android:ui_java", "//ui/gfx/geometry/mojo:mojo_java",
diff --git a/content/test/data/accessibility/event/add-hidden-attribute-expected-win.txt b/content/test/data/accessibility/event/add-hidden-attribute-expected-win.txt index 4b87b52..2c3b971 100644 --- a/content/test/data/accessibility/event/add-hidden-attribute-expected-win.txt +++ b/content/test/data/accessibility/event/add-hidden-attribute-expected-win.txt
@@ -1,3 +1,3 @@ -EVENT_OBJECT_HIDE on <div#item3> role=ROLE_SYSTEM_LISTITEM name="Item 3" PosInSet=3 SetSize=3 +EVENT_OBJECT_HIDE on <div#item3> role=ROLE_SYSTEM_LISTITEM name="Item 3" EVENT_OBJECT_REORDER on <div> role=ROLE_SYSTEM_LIST SetSize=2 IA2_EVENT_TEXT_REMOVED on <div> role=ROLE_SYSTEM_LIST SetSize=2 old_text={'<obj>' start=2 end=3}
diff --git a/content/test/data/accessibility/event/add-hidden-attribute-subtree-expected-win.txt b/content/test/data/accessibility/event/add-hidden-attribute-subtree-expected-win.txt index c7a7def..60c866202 100644 --- a/content/test/data/accessibility/event/add-hidden-attribute-subtree-expected-win.txt +++ b/content/test/data/accessibility/event/add-hidden-attribute-subtree-expected-win.txt
@@ -1,3 +1,3 @@ -EVENT_OBJECT_HIDE on <li#item3> role=ROLE_SYSTEM_LISTITEM PosInSet=3 SetSize=3 +EVENT_OBJECT_HIDE on <li#item3> role=ROLE_SYSTEM_LISTITEM EVENT_OBJECT_REORDER on <ul> role=ROLE_SYSTEM_LIST SetSize=2 IA2_EVENT_TEXT_REMOVED on <ul> role=ROLE_SYSTEM_LIST SetSize=2 old_text={'<obj>' start=2 end=3}
diff --git a/content/test/data/accessibility/event/remove-child-expected-win.txt b/content/test/data/accessibility/event/remove-child-expected-win.txt index 4b87b52..2c3b971 100644 --- a/content/test/data/accessibility/event/remove-child-expected-win.txt +++ b/content/test/data/accessibility/event/remove-child-expected-win.txt
@@ -1,3 +1,3 @@ -EVENT_OBJECT_HIDE on <div#item3> role=ROLE_SYSTEM_LISTITEM name="Item 3" PosInSet=3 SetSize=3 +EVENT_OBJECT_HIDE on <div#item3> role=ROLE_SYSTEM_LISTITEM name="Item 3" EVENT_OBJECT_REORDER on <div> role=ROLE_SYSTEM_LIST SetSize=2 IA2_EVENT_TEXT_REMOVED on <div> role=ROLE_SYSTEM_LIST SetSize=2 old_text={'<obj>' start=2 end=3}
diff --git a/content/test/fuzzer/BUILD.gn b/content/test/fuzzer/BUILD.gn index ea09651..ef82ef8 100644 --- a/content/test/fuzzer/BUILD.gn +++ b/content/test/fuzzer/BUILD.gn
@@ -163,6 +163,7 @@ "//net:test_support", ] dict = "//content/test/data/fuzzer_dictionaries/merkle_integrity_source_stream_fuzzer.dict" + environment_variables = [ "AFL_DRIVER_DONT_DEFER=1" ] } proto_library("appcache_fuzzer_proto") {
diff --git a/device/gamepad/gamepad_pad_state_provider.h b/device/gamepad/gamepad_pad_state_provider.h index fe1e9a0..3ac6476f 100644 --- a/device/gamepad/gamepad_pad_state_provider.h +++ b/device/gamepad/gamepad_pad_state_provider.h
@@ -36,7 +36,8 @@ GAMEPAD_SOURCE_TEST, GAMEPAD_SOURCE_WIN_XINPUT, GAMEPAD_SOURCE_WIN_RAW, - kMaxValue = GAMEPAD_SOURCE_WIN_RAW, + GAMEPAD_SOURCE_WIN_MR, + kMaxValue = GAMEPAD_SOURCE_WIN_MR, }; struct PadState {
diff --git a/device/vr/isolated_gamepad_data_fetcher.cc b/device/vr/isolated_gamepad_data_fetcher.cc index 36a89985..a849068f 100644 --- a/device/vr/isolated_gamepad_data_fetcher.cc +++ b/device/vr/isolated_gamepad_data_fetcher.cc
@@ -24,6 +24,11 @@ return true; #endif +#if BUILDFLAG(ENABLE_WINDOWS_MR) + if (id == device::mojom::XRDeviceId::WINDOWS_MIXED_REALITY_ID) + return true; +#endif + return false; } @@ -40,6 +45,11 @@ return GAMEPAD_SOURCE_OCULUS; #endif +#if BUILDFLAG(ENABLE_WINDOWS_MR) + if (id == device::mojom::XRDeviceId::WINDOWS_MIXED_REALITY_ID) + return GAMEPAD_SOURCE_WIN_MR; +#endif + NOTREACHED(); return GAMEPAD_SOURCE_NONE; } @@ -206,7 +216,7 @@ // could be confusing here. if (this->source() == GAMEPAD_SOURCE_OPENVR) { swprintf(dest.id, Gamepad::kIdLengthCap, L"OpenVR Gamepad"); - } else { + } else if (this->source() == GAMEPAD_SOURCE_OCULUS) { if (dest.hand == GamepadHand::kLeft) { swprintf(dest.id, Gamepad::kIdLengthCap, L"Oculus Touch (Left)"); } else if (dest.hand == GamepadHand::kRight) { @@ -214,6 +224,16 @@ } else { swprintf(dest.id, Gamepad::kIdLengthCap, L"Oculus Remote"); } + } else if (this->source() == GAMEPAD_SOURCE_WIN_MR) { + if (dest.hand == GamepadHand::kLeft) { + swprintf(dest.id, Gamepad::kIdLengthCap, + L"Windows Mixed Reality (Left)"); + } else if (dest.hand == GamepadHand::kRight) { + swprintf(dest.id, Gamepad::kIdLengthCap, + L"Windows Mixed Reality (Right)"); + } else { + swprintf(dest.id, Gamepad::kIdLengthCap, L"Windows Mixed Reality"); + } } TRACE_COUNTER1(
diff --git a/device/vr/windows_mixed_reality/mixed_reality_input_helper.cc b/device/vr/windows_mixed_reality/mixed_reality_input_helper.cc index d60c207..9b8fa92 100644 --- a/device/vr/windows_mixed_reality/mixed_reality_input_helper.cc +++ b/device/vr/windows_mixed_reality/mixed_reality_input_helper.cc
@@ -18,6 +18,8 @@ #include "base/win/core_winrt_util.h" #include "base/win/scoped_hstring.h" #include "base/win/typed_event_handler.h" +#include "device/gamepad/public/cpp/gamepads.h" +#include "device/vr/public/mojom/isolated_xr_service.mojom.h" #include "ui/gfx/transform.h" #include "ui/gfx/transform_util.h" @@ -39,6 +41,7 @@ using ABI::Windows::Perception::IPerceptionTimestamp; using ABI::Windows::Perception::People::IHeadPose; using ABI::Windows::Perception::Spatial::ISpatialCoordinateSystem; +using ABI::Windows::UI::Input::Spatial::ISpatialInteractionControllerProperties; using ABI::Windows::UI::Input::Spatial::ISpatialInteractionManager; using ABI::Windows::UI::Input::Spatial::ISpatialInteractionSource; using ABI::Windows::UI::Input::Spatial::ISpatialInteractionSource2; @@ -50,6 +53,7 @@ using ABI::Windows::UI::Input::Spatial::ISpatialInteractionSourceLocation3; using ABI::Windows::UI::Input::Spatial::ISpatialInteractionSourceProperties; using ABI::Windows::UI::Input::Spatial::ISpatialInteractionSourceState; +using ABI::Windows::UI::Input::Spatial::ISpatialInteractionSourceState2; using ABI::Windows::UI::Input::Spatial::ISpatialPointerInteractionSourcePose; using ABI::Windows::UI::Input::Spatial::ISpatialPointerInteractionSourcePose2; using ABI::Windows::UI::Input::Spatial::ISpatialPointerPose; @@ -64,16 +68,271 @@ SpatialInteractionSourceEventArgs*> SpatialInteractionSourceEventHandler; +ParsedInputState::ParsedInputState() {} +ParsedInputState::~ParsedInputState() {} +ParsedInputState::ParsedInputState(ParsedInputState&& other) = default; + namespace { -gfx::Transform CreateTransform(WFN::Vector3 position, - WFN::Quaternion rotation) { +constexpr double kDeadzoneMinimum = 0.1; + +void AddButton(mojom::XRGamepadPtr& gamepad, ButtonData* data) { + if (data) { + auto button = mojom::XRGamepadButton::New(); + button->pressed = data->pressed; + button->touched = data->touched; + button->value = data->value; + + gamepad->buttons.push_back(std::move(button)); + } else { + gamepad->buttons.push_back(mojom::XRGamepadButton::New()); + } +} + +// These methods are only called for the thumbstick and touchpad, which both +// have an X and Y. +void AddAxes(mojom::XRGamepadPtr& gamepad, ButtonData data) { + gamepad->axes.push_back( + std::fabs(data.x_axis) < kDeadzoneMinimum ? 0 : data.x_axis); + gamepad->axes.push_back( + std::fabs(data.y_axis) < kDeadzoneMinimum ? 0 : data.y_axis); +} + +void AddButtonAndAxes(mojom::XRGamepadPtr& gamepad, ButtonData data) { + AddButton(gamepad, &data); + AddAxes(gamepad, data); +} + +std::vector<float> ConvertToVector(GamepadVector vector) { + return {vector.x, vector.y, vector.z}; +} + +std::vector<float> ConvertToVector(GamepadQuaternion quat) { + return {quat.x, quat.y, quat.z, quat.w}; +} + +mojom::VRPosePtr ConvertToVRPose(GamepadPose gamepad_pose) { + if (!gamepad_pose.not_null) + return nullptr; + + auto pose = mojom::VRPose::New(); + if (gamepad_pose.orientation.not_null) + pose->orientation = ConvertToVector(gamepad_pose.orientation); + + if (gamepad_pose.position.not_null) + pose->position = ConvertToVector(gamepad_pose.position); + + if (gamepad_pose.angular_velocity.not_null) + pose->angularVelocity = ConvertToVector(gamepad_pose.angular_velocity); + + if (gamepad_pose.linear_velocity.not_null) + pose->linearVelocity = ConvertToVector(gamepad_pose.linear_velocity); + + if (gamepad_pose.angular_acceleration.not_null) + pose->angularAcceleration = + ConvertToVector(gamepad_pose.angular_acceleration); + + if (gamepad_pose.linear_acceleration.not_null) + pose->linearAcceleration = + ConvertToVector(gamepad_pose.linear_acceleration); + + return pose; +} + +GamepadQuaternion ConvertToGamepadQuaternion(WFN::Quaternion quat) { + GamepadQuaternion gamepad_quaternion; + gamepad_quaternion.not_null = true; + gamepad_quaternion.x = quat.X; + gamepad_quaternion.y = quat.Y; + gamepad_quaternion.z = quat.Z; + gamepad_quaternion.w = quat.W; + return gamepad_quaternion; +} + +GamepadVector ConvertToGamepadVector(WFN::Vector3 vec3) { + GamepadVector gamepad_vector; + gamepad_vector.not_null = true; + gamepad_vector.x = vec3.X; + gamepad_vector.y = vec3.Y; + gamepad_vector.z = vec3.Z; + return gamepad_vector; +} + +mojom::XRGamepadPtr GetWebVRGamepad(ParsedInputState input_state) { + auto gamepad = mojom::XRGamepad::New(); + // This matches the order of button trigger events from Edge. Note that we + // use the polled button state for select here. Voice (which we cannot get + // via polling), lacks enough data to be considered a "Gamepad", and if we + // used eventing the pressed state may be inconsistent. + AddButtonAndAxes(gamepad, input_state.button_data[ButtonName::kThumbstick]); + AddButton(gamepad, &input_state.button_data[ButtonName::kSelect]); + AddButton(gamepad, &input_state.button_data[ButtonName::kGrip]); + AddButton(gamepad, nullptr); // Nothing seems to trigger this button in Edge. + AddButtonAndAxes(gamepad, input_state.button_data[ButtonName::kTouchpad]); + + gamepad->pose = ConvertToVRPose(input_state.gamepad_pose); + gamepad->hand = input_state.source_state->description->handedness; + gamepad->controller_id = input_state.source_state->source_id; + gamepad->can_provide_position = true; + gamepad->can_provide_orientation = true; + gamepad->timestamp = base::TimeTicks::Now(); + + return gamepad; +} + +// Note that since this is built by polling, and so eventing changes are not +// accounted for here. +std::unordered_map<ButtonName, ButtonData> ParseButtonState( + ComPtr<ISpatialInteractionSourceState> source) { + if (!source) + return {}; + + ComPtr<ISpatialInteractionSourceState2> source_state; + HRESULT hr = source.As(&source_state); + DCHECK(SUCCEEDED(hr)); + + std::unordered_map<ButtonName, ButtonData> button_map; + boolean bool_val; + DOUBLE double_val; + + ButtonData data = button_map[ButtonName::kSelect]; + hr = source_state->get_IsSelectPressed(&bool_val); + DCHECK(SUCCEEDED(hr)); + data.pressed = bool_val; + data.touched = bool_val; + + hr = source_state->get_SelectPressedValue(&double_val); + DCHECK(SUCCEEDED(hr)); + data.value = double_val; + button_map[ButtonName::kSelect] = data; + + data = button_map[ButtonName::kGrip]; + hr = source_state->get_IsGrasped(&bool_val); + DCHECK(SUCCEEDED(hr)); + data.pressed = bool_val; + data.touched = bool_val; + data.value = bool_val ? 1.0 : 0.0; + button_map[ButtonName::kGrip] = data; + + ComPtr<ISpatialInteractionControllerProperties> controller_properties; + hr = source_state->get_ControllerProperties(&controller_properties); + + // Controller Properties only exist for motion controllers + if (FAILED(hr) || !controller_properties) + return button_map; + + data = button_map[ButtonName::kThumbstick]; + hr = controller_properties->get_IsThumbstickPressed(&bool_val); + DCHECK(SUCCEEDED(hr)); + data.pressed = bool_val; + data.touched = bool_val; + data.value = bool_val ? 1.0 : 0.0; + + hr = controller_properties->get_ThumbstickX(&double_val); + DCHECK(SUCCEEDED(hr)); + data.x_axis = double_val; + + hr = controller_properties->get_ThumbstickY(&double_val); + DCHECK(SUCCEEDED(hr)); + data.y_axis = double_val; + button_map[ButtonName::kThumbstick] = data; + + data = button_map[ButtonName::kTouchpad]; + hr = controller_properties->get_IsTouchpadPressed(&bool_val); + DCHECK(SUCCEEDED(hr)); + data.pressed = bool_val; + data.value = bool_val ? 1.0 : 0.0; + + hr = controller_properties->get_IsTouchpadTouched(&bool_val); + DCHECK(SUCCEEDED(hr)); + data.touched = bool_val; + + // Touchpad must be touched if it is pressed + if (data.pressed && !data.touched) + data.touched = true; + + if (data.touched) { + hr = controller_properties->get_TouchpadX(&double_val); + DCHECK(SUCCEEDED(hr)); + data.x_axis = double_val; + + hr = controller_properties->get_TouchpadY(&double_val); + DCHECK(SUCCEEDED(hr)); + data.y_axis = double_val; + } + + button_map[ButtonName::kTouchpad] = data; + + return button_map; +} + +template <class T> +bool TryGetValue(ComPtr<IReference<T>> val_ref, T* out_val) { + if (!val_ref) + return false; + + HRESULT hr = val_ref->get_Value(out_val); + DCHECK(SUCCEEDED(hr)); + + return true; +} + +GamepadPose GetGamepadPose(ComPtr<ISpatialInteractionSourceLocation> location) { + GamepadPose gamepad_pose; + if (!location) + return gamepad_pose; + + ComPtr<IReference<WFN::Vector3>> vec3_ref; + WFN::Vector3 vec3; + HRESULT hr = location->get_Position(&vec3_ref); + DCHECK(SUCCEEDED(hr)); + if (TryGetValue(vec3_ref, &vec3)) { + gamepad_pose.not_null = true; + gamepad_pose.position = ConvertToGamepadVector(vec3); + } + + hr = location->get_Velocity(&vec3_ref); + DCHECK(SUCCEEDED(hr)); + if (TryGetValue(vec3_ref, &vec3)) { + gamepad_pose.not_null = true; + gamepad_pose.linear_velocity = ConvertToGamepadVector(vec3); + } + + ComPtr<ISpatialInteractionSourceLocation2> loc2; + hr = location.As(&loc2); + DCHECK(SUCCEEDED(hr)); + + ComPtr<IReference<WFN::Quaternion>> quat_ref; + WFN::Quaternion quat; + hr = loc2->get_Orientation(&quat_ref); + DCHECK(SUCCEEDED(hr)); + if (TryGetValue(quat_ref, &quat)) { + gamepad_pose.not_null = true; + gamepad_pose.orientation = ConvertToGamepadQuaternion(quat); + } + + ComPtr<ISpatialInteractionSourceLocation3> loc3; + hr = location.As(&loc3); + DCHECK(SUCCEEDED(hr)); + + hr = loc3->get_AngularVelocity(&vec3_ref); + DCHECK(SUCCEEDED(hr)); + if (TryGetValue(vec3_ref, &vec3)) { + gamepad_pose.not_null = true; + gamepad_pose.angular_velocity = ConvertToGamepadVector(vec3); + } + + return gamepad_pose; +} + +gfx::Transform CreateTransform(GamepadVector position, + GamepadQuaternion rotation) { gfx::DecomposedTransform decomposed_transform; - decomposed_transform.translate[0] = position.X; - decomposed_transform.translate[1] = position.Y; - decomposed_transform.translate[2] = position.Z; + decomposed_transform.translate[0] = position.x; + decomposed_transform.translate[1] = position.y; + decomposed_transform.translate[2] = position.z; decomposed_transform.quaternion = - gfx::Quaternion(rotation.X, rotation.Y, rotation.Z, rotation.W); + gfx::Quaternion(rotation.x, rotation.y, rotation.z, rotation.w); return gfx::ComposeTransform(decomposed_transform); } @@ -86,34 +345,14 @@ if (!location_in_origin) return false; - ComPtr<IReference<WFN::Vector3>> pos_ref; - HRESULT hr = location_in_origin->get_Position(&pos_ref); - DCHECK(SUCCEEDED(hr)); + auto gamepad_pose = GetGamepadPose(location_in_origin); - if (!pos_ref) + if (!(gamepad_pose.not_null && gamepad_pose.position.not_null && + gamepad_pose.orientation.not_null)) return false; - WFN::Vector3 pos; - hr = pos_ref->get_Value(&pos); - DCHECK(SUCCEEDED(hr)); - - ComPtr<ISpatialInteractionSourceLocation2> location_in_origin2; - hr = location_in_origin.As(&location_in_origin2); - if (FAILED(hr)) - return false; - - ComPtr<IReference<WFN::Quaternion>> quat_ref; - hr = location_in_origin2->get_Orientation(&quat_ref); - DCHECK(SUCCEEDED(hr)); - - if (!quat_ref) - return false; - - WFN::Quaternion quat; - hr = quat_ref->get_Value(&quat); - DCHECK(SUCCEEDED(hr)); - - *origin_from_grip = CreateTransform(pos, quat); + *origin_from_grip = + CreateTransform(gamepad_pose.position, gamepad_pose.orientation); return true; } @@ -182,7 +421,8 @@ DCHECK(SUCCEEDED(hr)); } - gfx::Transform origin_from_pointer = CreateTransform(pos, rot); + gfx::Transform origin_from_pointer = CreateTransform( + ConvertToGamepadVector(pos), ConvertToGamepadQuaternion(rot)); *grip_from_pointer = (grip_from_origin * origin_from_pointer); return true; } @@ -279,19 +519,18 @@ if (FAILED(source_states->GetAt(i, &state))) continue; - mojom::XRInputSourceStatePtr source_state = - LockedParseWindowsSourceState(state, origin); + auto parsed_source_state = LockedParseWindowsSourceState(state, origin); - if (source_state) - input_states.push_back(std::move(source_state)); + if (parsed_source_state.source_state) + input_states.push_back(std::move(parsed_source_state.source_state)); } for (unsigned int i = 0; i < pending_voice_states_.size(); i++) { - mojom::XRInputSourceStatePtr source_state = + auto parsed_source_state = LockedParseWindowsSourceState(pending_voice_states_[i], origin); - if (source_state) - input_states.push_back(std::move(source_state)); + if (parsed_source_state.source_state) + input_states.push_back(std::move(parsed_source_state.source_state)); } pending_voice_states_.clear(); @@ -299,12 +538,47 @@ return input_states; } -mojom::XRInputSourceStatePtr -MixedRealityInputHelper::LockedParseWindowsSourceState( +mojom::XRGamepadDataPtr MixedRealityInputHelper::GetWebVRGamepadData( + ComPtr<ISpatialCoordinateSystem> origin, + ComPtr<IPerceptionTimestamp> timestamp) { + auto ret = mojom::XRGamepadData::New(); + + if (!timestamp || !origin || !EnsureSpatialInteractionManager()) + return ret; + + ComPtr<IVectorView<SpatialInteractionSourceState*>> source_states; + if (FAILED(spatial_interaction_manager_->GetDetectedSourcesAtTimestamp( + timestamp.Get(), &source_states))) + return ret; + + unsigned int size; + HRESULT hr = source_states->get_Size(&size); + DCHECK(SUCCEEDED(hr)); + + base::AutoLock scoped_lock(lock_); + + for (unsigned int i = 0; i < size; i++) { + ComPtr<ISpatialInteractionSourceState> state; + if (FAILED(source_states->GetAt(i, &state))) + continue; + + auto parsed_source_state = LockedParseWindowsSourceState(state, origin); + + // If we have a grip, then we should have enough data. + if (parsed_source_state.source_state && + parsed_source_state.source_state->grip) + ret->gamepads.push_back(GetWebVRGamepad(std::move(parsed_source_state))); + } + + return ret; +} + +ParsedInputState MixedRealityInputHelper::LockedParseWindowsSourceState( ComPtr<ISpatialInteractionSourceState> state, ComPtr<ISpatialCoordinateSystem> origin) { + ParsedInputState input_state; if (!(state && origin)) - return nullptr; + return input_state; ComPtr<ISpatialInteractionSource> source; HRESULT hr = state->get_Source(&source); @@ -320,7 +594,7 @@ (source_kind == SourceKind::SpatialInteractionSourceKind_Voice); if (!(is_controller || is_voice)) - return nullptr; + return input_state; // Note that if this is from voice input, we're not supposed to send up the // "grip" position, so this will be left as identity and let us still use @@ -328,22 +602,25 @@ // item unaffected. gfx::Transform origin_from_grip; if (is_controller) { + input_state.button_data = ParseButtonState(state); ComPtr<ISpatialInteractionSourceProperties> props; hr = state->get_Properties(&props); DCHECK(SUCCEEDED(hr)); ComPtr<ISpatialInteractionSourceLocation> location_in_origin; if (FAILED(props->TryGetLocation(origin.Get(), &location_in_origin)) || !location_in_origin) - return nullptr; + return input_state; if (!TryGetGripFromLocation(location_in_origin, &origin_from_grip)) - return nullptr; + return input_state; + + input_state.gamepad_pose = GetGamepadPose(location_in_origin); } gfx::Transform grip_from_pointer; if (!TryGetPointerOffset(state, source, origin, origin_from_grip, &grip_from_pointer)) - return nullptr; + return input_state; // Now that we know we have tracking for the object, we'll start building. device::mojom::XRInputSourceStatePtr source_state = @@ -379,7 +656,7 @@ ComPtr<ISpatialInteractionSource3> source3; hr = source.As(&source3); if (FAILED(hr)) - return nullptr; + return input_state; Handedness handedness; hr = source3->get_Handedness(&handedness); @@ -392,7 +669,9 @@ source_state->description = std::move(description); - return source_state; + input_state.source_state = std::move(source_state); + + return input_state; } HRESULT MixedRealityInputHelper::OnSourcePressed(
diff --git a/device/vr/windows_mixed_reality/mixed_reality_input_helper.h b/device/vr/windows_mixed_reality/mixed_reality_input_helper.h index 94ff67b..f9a3bf2 100644 --- a/device/vr/windows_mixed_reality/mixed_reality_input_helper.h +++ b/device/vr/windows_mixed_reality/mixed_reality_input_helper.h
@@ -12,9 +12,36 @@ #include <vector> #include "base/synchronization/lock.h" +#include "device/gamepad/public/cpp/gamepads.h" +#include "device/vr/public/mojom/isolated_xr_service.mojom.h" #include "device/vr/public/mojom/vr_service.mojom.h" namespace device { +struct ButtonData { + bool pressed; + bool touched; + double value; + + double x_axis; + double y_axis; +}; + +enum class ButtonName { + kSelect, + kGrip, + kTouchpad, + kThumbstick, +}; + +struct ParsedInputState { + mojom::XRInputSourceStatePtr source_state; + std::unordered_map<ButtonName, ButtonData> button_data; + GamepadPose gamepad_pose; + ParsedInputState(); + ~ParsedInputState(); + ParsedInputState(ParsedInputState&& other); +}; + class MixedRealityInputHelper { public: MixedRealityInputHelper(HWND hwnd); @@ -25,12 +52,18 @@ Microsoft::WRL::ComPtr<ABI::Windows::Perception::IPerceptionTimestamp> timestamp); + mojom::XRGamepadDataPtr GetWebVRGamepadData( + Microsoft::WRL::ComPtr< + ABI::Windows::Perception::Spatial::ISpatialCoordinateSystem> origin, + Microsoft::WRL::ComPtr<ABI::Windows::Perception::IPerceptionTimestamp> + timestamp); + void Dispose(); private: bool EnsureSpatialInteractionManager(); - mojom::XRInputSourceStatePtr LockedParseWindowsSourceState( + ParsedInputState LockedParseWindowsSourceState( Microsoft::WRL::ComPtr< ABI::Windows::UI::Input::Spatial::ISpatialInteractionSourceState> state,
diff --git a/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc b/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc index 46fa4c8..de3dbcea 100644 --- a/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc +++ b/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc
@@ -75,6 +75,8 @@ kAcquireCurrentStage = 1, kStationaryReferenceCreation = 2, kGetTransformBetweenOrigins = 3, + kGamepadMissingTimestamp = 4, + kGamepadMissingOrigin = 5, }; void TraceError(ErrorLocation location, HRESULT hr) { @@ -495,8 +497,17 @@ } mojom::XRGamepadDataPtr MixedRealityRenderLoop::GetNextGamepadData() { - // Not yet implemented. - return nullptr; + if (!timestamp_) { + TraceError(ErrorLocation::kGamepadMissingTimestamp, E_UNEXPECTED); + return nullptr; + } + + if (!origin_) { + TraceError(ErrorLocation::kGamepadMissingOrigin, E_UNEXPECTED); + return nullptr; + } + + return input_helper_->GetWebVRGamepadData(origin_, timestamp_); } struct EyeToWorldDecomposed {
diff --git a/extensions/browser/api/app_window/app_window_api.cc b/extensions/browser/api/app_window/app_window_api.cc index 6c167ed..cad9b18 100644 --- a/extensions/browser/api/app_window/app_window_api.cc +++ b/extensions/browser/api/app_window/app_window_api.cc
@@ -190,8 +190,7 @@ content::RenderFrameHost* existing_frame = existing_window->web_contents()->GetMainFrame(); int frame_id = MSG_ROUTING_NONE; - if (render_frame_host()->GetProcess()->GetID() == - existing_frame->GetProcess()->GetID()) { + if (source_process_id() == existing_frame->GetProcess()->GetID()) { frame_id = existing_frame->GetRoutingID(); } @@ -374,8 +373,7 @@ create_params.show_on_lock_screen = true; } - create_params.creator_process_id = - render_frame_host()->GetProcess()->GetID(); + create_params.creator_process_id = source_process_id(); AppWindow* app_window = nullptr; if (action_type == api::app_runtime::ACTION_TYPE_NONE) {
diff --git a/extensions/browser/api/declarative/declarative_api.cc b/extensions/browser/api/declarative/declarative_api.cc index 7bb6107..6fa9f7b3 100644 --- a/extensions/browser/api/declarative/declarative_api.cc +++ b/extensions/browser/api/declarative/declarative_api.cc
@@ -21,8 +21,6 @@ #include "base/values.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "extensions/browser/api/declarative/rules_registry_service.h" #include "extensions/browser/api/extensions_api_client.h" @@ -159,7 +157,6 @@ return RespondNow(Error("Missing webview permission")); } - int embedder_process_id = render_frame_host()->GetProcess()->GetID(); RecordUMA(event_name); bool from_web_view = web_view_instance_id != 0; @@ -175,7 +172,7 @@ event_name = event_name.substr(found); rules_registry_id = WebViewGuest::GetOrGenerateRulesRegistryID( - embedder_process_id, web_view_instance_id); + source_process_id(), web_view_instance_id); } // The following call will return a NULL pointer for apps_shell, but should
diff --git a/extensions/browser/api/file_system/file_system_api.cc b/extensions/browser/api/file_system/file_system_api.cc index 2c6e0cbd..1ce53a3 100644 --- a/extensions/browser/api/file_system/file_system_api.cc +++ b/extensions/browser/api/file_system/file_system_api.cc
@@ -30,8 +30,6 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "extensions/browser/api/extensions_api_client.h" @@ -241,8 +239,8 @@ base::FilePath file_path; std::string error; if (!app_file_handler_util::ValidateFileEntryAndGetPath( - filesystem_name, filesystem_path, - render_frame_host()->GetProcess()->GetID(), &file_path, &error)) { + filesystem_name, filesystem_path, source_process_id(), &file_path, + &error)) { return RespondNow(Error(error)); } @@ -294,8 +292,7 @@ const std::string& id_override, base::DictionaryValue* result) { GrantedFileEntry file_entry = app_file_handler_util::CreateFileEntry( - browser_context(), extension(), - render_frame_host()->GetProcess()->GetID(), path, is_directory_); + browser_context(), extension(), source_process_id(), path, is_directory_); base::ListValue* entries; bool success = result->GetList("entries", &entries); DCHECK(success); @@ -330,8 +327,8 @@ std::string error; if (!app_file_handler_util::ValidateFileEntryAndGetPath( - filesystem_name, filesystem_path, - render_frame_host()->GetProcess()->GetID(), &path_, &error)) { + filesystem_name, filesystem_path, source_process_id(), &path_, + &error)) { return RespondNow(Error(error)); } @@ -375,8 +372,8 @@ content::ChildProcessSecurityPolicy* policy = content::ChildProcessSecurityPolicy::GetInstance(); - int renderer_id = render_frame_host()->GetProcess()->GetID(); - bool is_writable = policy->CanReadWriteFileSystem(renderer_id, filesystem_id); + bool is_writable = + policy->CanReadWriteFileSystem(source_process_id(), filesystem_id); return RespondNow(OneArgument(std::make_unique<base::Value>(is_writable))); } @@ -803,8 +800,8 @@ EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &filesystem_path)); std::string error; if (!app_file_handler_util::ValidateFileEntryAndGetPath( - filesystem_name, filesystem_path, - render_frame_host()->GetProcess()->GetID(), &path, &error)) { + filesystem_name, filesystem_path, source_process_id(), &path, + &error)) { return RespondNow(Error(error)); }
diff --git a/extensions/browser/api/guest_view/extension_view/extension_view_internal_api.cc b/extensions/browser/api/guest_view/extension_view/extension_view_internal_api.cc index 8ac08dc..5110afa 100644 --- a/extensions/browser/api/guest_view/extension_view/extension_view_internal_api.cc +++ b/extensions/browser/api/guest_view/extension_view/extension_view_internal_api.cc
@@ -9,8 +9,6 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "components/crx_file/id_util.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/common/stop_find_action.h" @@ -26,8 +24,7 @@ std::string* error) { int instance_id = 0; EXTENSION_FUNCTION_PRERUN_VALIDATE(args_->GetInteger(0, &instance_id)); - guest_ = ExtensionViewGuest::From(render_frame_host()->GetProcess()->GetID(), - instance_id); + guest_ = ExtensionViewGuest::From(source_process_id(), instance_id); return guest_ != nullptr; }
diff --git a/extensions/browser/api/guest_view/guest_view_internal_api.cc b/extensions/browser/api/guest_view/guest_view_internal_api.cc index 27decab..93e72c6 100644 --- a/extensions/browser/api/guest_view/guest_view_internal_api.cc +++ b/extensions/browser/api/guest_view/guest_view_internal_api.cc
@@ -11,8 +11,6 @@ #include "components/guest_view/browser/guest_view_manager.h" #include "components/guest_view/browser/guest_view_manager_delegate.h" #include "components/guest_view/common/guest_view_constants.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "extensions/browser/api/extensions_api_client.h" #include "extensions/common/api/guest_view_internal.h" #include "extensions/common/permissions/permissions_data.h" @@ -90,8 +88,8 @@ std::unique_ptr<guest_view_internal::DestroyGuest::Params> params( guest_view_internal::DestroyGuest::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); - GuestViewBase* guest = GuestViewBase::From( - render_frame_host()->GetProcess()->GetID(), params->instance_id); + GuestViewBase* guest = + GuestViewBase::From(source_process_id(), params->instance_id); if (!guest) return RespondNow(Error(kUnknownErrorDoNotUse)); guest->Destroy(true); @@ -108,8 +106,8 @@ std::unique_ptr<guest_view_internal::SetSize::Params> params( guest_view_internal::SetSize::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); - GuestViewBase* guest = GuestViewBase::From( - render_frame_host()->GetProcess()->GetID(), params->instance_id); + GuestViewBase* guest = + GuestViewBase::From(source_process_id(), params->instance_id); if (!guest) return RespondNow(Error(kUnknownErrorDoNotUse));
diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc index 5cdea65..a83cb1f 100644 --- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc +++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
@@ -18,7 +18,6 @@ #include "components/crash/core/common/crash_key.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/stop_find_action.h" @@ -275,8 +274,7 @@ // TODO(780728): Remove crash key once the cause of the kill is known. static crash_reporter::CrashKeyString<128> name_key("webview-function"); crash_reporter::ScopedCrashKeyString name_key_scope(&name_key, name()); - guest_ = WebViewGuest::From(render_frame_host()->GetProcess()->GetID(), - instance_id); + guest_ = WebViewGuest::From(source_process_id(), instance_id); if (!guest_) { *error = "Could not find guest"; return false; @@ -435,8 +433,8 @@ WebViewInternalExecuteCodeFunction::GetScriptExecutor(std::string* error) { if (!render_frame_host() || !render_frame_host()->GetProcess()) return nullptr; - WebViewGuest* guest = WebViewGuest::From( - render_frame_host()->GetProcess()->GetID(), guest_instance_id_); + WebViewGuest* guest = + WebViewGuest::From(source_process_id(), guest_instance_id_); if (!guest) return nullptr; @@ -456,8 +454,8 @@ WebUIURLFetcher::WebUILoadFileCallback callback) { if (!render_frame_host() || !render_frame_host()->GetProcess()) return false; - WebViewGuest* guest = WebViewGuest::From( - render_frame_host()->GetProcess()->GetID(), guest_instance_id_); + WebViewGuest* guest = + WebViewGuest::From(source_process_id(), guest_instance_id_); if (!guest || host_id().type() != HostID::WEBUI) return false; @@ -465,8 +463,8 @@ GURL file_url(owner_base_url.Resolve(file_src)); url_fetcher_ = std::make_unique<WebUIURLFetcher>( - render_frame_host()->GetProcess()->GetID(), - render_frame_host()->GetRoutingID(), file_url, std::move(callback)); + source_process_id(), render_frame_host()->GetRoutingID(), file_url, + std::move(callback)); url_fetcher_->Start(); return true; } @@ -531,9 +529,8 @@ WebViewContentScriptManager::Get(browser_context()); DCHECK(manager); - manager->AddContentScripts( - render_frame_host()->GetProcess()->GetID(), - render_frame_host(), params->instance_id, host_id, std::move(result)); + manager->AddContentScripts(source_process_id(), render_frame_host(), + params->instance_id, host_id, std::move(result)); return RespondNow(NoArguments()); } @@ -565,9 +562,8 @@ std::vector<std::string> script_name_list; if (params->script_name_list) script_name_list.swap(*params->script_name_list); - manager->RemoveContentScripts( - render_frame_host()->GetProcess()->GetID(), - params->instance_id, host_id, script_name_list); + manager->RemoveContentScripts(source_process_id(), params->instance_id, + host_id, script_name_list); return RespondNow(NoArguments()); }
diff --git a/extensions/browser/api/runtime/runtime_api.cc b/extensions/browser/api/runtime/runtime_api.cc index 968e2d9..24732a0 100644 --- a/extensions/browser/api/runtime/runtime_api.cc +++ b/extensions/browser/api/runtime/runtime_api.cc
@@ -22,8 +22,6 @@ #include "components/prefs/pref_service.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/child_process_security_policy.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "extensions/browser/api/runtime/runtime_api_delegate.h" #include "extensions/browser/event_router.h" #include "extensions/browser/events/lazy_event_dispatch_util.h" @@ -741,10 +739,9 @@ std::string filesystem_id = isolated_context->RegisterFileSystemForPath( storage::kFileSystemTypeNativeLocal, std::string(), path, &relative_path); - int renderer_id = render_frame_host()->GetProcess()->GetID(); content::ChildProcessSecurityPolicy* policy = content::ChildProcessSecurityPolicy::GetInstance(); - policy->GrantReadFileSystem(renderer_id, filesystem_id); + policy->GrantReadFileSystem(source_process_id(), filesystem_id); std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); dict->SetString("fileSystemId", filesystem_id); dict->SetString("baseName", relative_path);
diff --git a/extensions/common/api/_manifest_features.json b/extensions/common/api/_manifest_features.json index 08a088ad..814e472a 100644 --- a/extensions/common/api/_manifest_features.json +++ b/extensions/common/api/_manifest_features.json
@@ -153,6 +153,11 @@ ] } ], + "host_permissions": { + "channel": "dev", + "extension_types": ["extension"], + "min_manifest_version": 3 + }, "icons": { "channel": "stable", "extension_types": "all"
diff --git a/extensions/common/manifest_constants.cc b/extensions/common/manifest_constants.cc index 4c4bb9f..85455a06 100644 --- a/extensions/common/manifest_constants.cc +++ b/extensions/common/manifest_constants.cc
@@ -69,6 +69,7 @@ const char kGlobal[] = "global"; const char kHideBookmarkButton[] = "hide_bookmark_button"; const char kHomepageURL[] = "homepage_url"; +const char kHostPermissions[] = "host_permissions"; const char kIcons[] = "icons"; const char kId[] = "id"; const char kImeOptionsPage[] = "options_page"; @@ -439,6 +440,9 @@ "Invalid value for overriding homepage url: '[*]'."; const char kInvalidHomepageURL[] = "Invalid value for homepage url: '[*]'."; +const char kInvalidHostPermission[] = + "Invalid value for 'host_permissions[*]'."; +const char kInvalidHostPermissions[] = "Invalid value for 'host_permissions'."; const char kInvalidIconKey[] = "Invalid key in icons: \"*\"."; const char kInvalidIconPath[] = "Invalid value for 'icons[\"*\"]'.";
diff --git a/extensions/common/manifest_constants.h b/extensions/common/manifest_constants.h index 6a4ba12..dbb3e25f 100644 --- a/extensions/common/manifest_constants.h +++ b/extensions/common/manifest_constants.h
@@ -70,6 +70,7 @@ extern const char kGlobal[]; extern const char kHideBookmarkButton[]; extern const char kHomepageURL[]; +extern const char kHostPermissions[]; extern const char kIcons[]; extern const char kId[]; extern const char kImeOptionsPage[]; @@ -345,6 +346,8 @@ extern const char kInvalidGlobList[]; extern const char kInvalidHomepageOverrideURL[]; extern const char kInvalidHomepageURL[]; +extern const char kInvalidHostPermission[]; +extern const char kInvalidHostPermissions[]; extern const char kInvalidIconKey[]; extern const char kInvalidIconPath[]; extern const char kInvalidIcons[];
diff --git a/extensions/common/manifest_handlers/permissions_parser.cc b/extensions/common/manifest_handlers/permissions_parser.cc index 7df8c0c..c7821d9 100644 --- a/extensions/common/manifest_handlers/permissions_parser.cc +++ b/extensions/common/manifest_handlers/permissions_parser.cc
@@ -9,6 +9,7 @@ #include "base/command_line.h" #include "base/memory/ref_counted.h" #include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "content/public/common/url_constants.h" @@ -82,6 +83,35 @@ return true; } +// Parses hosts from the |keys::kHostPermissions| key in the extension's +// manifest into |hosts|. +bool ParseHostsFromJSON(Extension* extension, + std::vector<std::string>* hosts, + base::string16* error) { + if (!extension->manifest()->HasKey(keys::kHostPermissions)) + return true; + + const base::Value* permissions = nullptr; + if (!extension->manifest()->GetList(keys::kHostPermissions, &permissions)) { + *error = base::UTF8ToUTF16(errors::kInvalidHostPermissions); + return false; + } + + // Add all permissions parsed from the manifest to |hosts|. + const base::Value::ListStorage& list_storage = permissions->GetList(); + for (size_t i = 0; i < list_storage.size(); ++i) { + if (list_storage[i].is_string()) { + hosts->push_back(list_storage[i].GetString()); + } else { + *error = ErrorUtils::FormatErrorMessageUTF16( + errors::kInvalidHostPermission, base::NumberToString(i)); + return false; + } + } + + return true; +} + void ParseHostPermissions(Extension* extension, const char* key, const std::vector<std::string>& host_data, @@ -241,8 +271,20 @@ api_permissions->erase(*iter); } - ParseHostPermissions(extension, key, host_data, *api_permissions, - host_permissions); + if (extension->manifest_version() < 3) { + ParseHostPermissions(extension, key, host_data, *api_permissions, + host_permissions); + } else { + // Iterate through unhandled permissions (in |host_data|) and add an install + // warning for each. + for (const auto& permission_str : host_data) { + extension->AddInstallWarning(InstallWarning( + ErrorUtils::FormatErrorMessage( + manifest_errors::kPermissionUnknownOrMalformed, permission_str), + key, permission_str)); + } + } + return true; } @@ -332,6 +374,17 @@ return false; } + if (extension->manifest_version() >= 3) { + std::vector<std::string> manifest_hosts; + if (!ParseHostsFromJSON(extension, &manifest_hosts, error)) + return false; + + // TODO(kelvinjiang): Remove the dependency for |api_permissions| here. + ParseHostPermissions(extension, keys::kHostPermissions, manifest_hosts, + initial_required_permissions_->api_permissions, + &initial_required_permissions_->host_permissions); + } + initial_optional_permissions_.reset(new InitialPermissions); if (!ParseHelper(extension, keys::kOptionalPermissions,
diff --git a/extensions/common/manifest_test.cc b/extensions/common/manifest_test.cc index 2f9555af..397016c 100644 --- a/extensions/common/manifest_test.cc +++ b/extensions/common/manifest_test.cc
@@ -15,6 +15,7 @@ #include "base/values.h" #include "extensions/common/extension_l10n_util.h" #include "extensions/common/extension_paths.h" +#include "testing/gmock/include/gmock/gmock.h" #include "ui/base/l10n/l10n_util.h" namespace extensions { @@ -134,7 +135,7 @@ scoped_refptr<Extension> extension = LoadExtension(manifest, &error, location, flags); EXPECT_TRUE(extension.get()) << manifest.name(); - EXPECT_EQ("", error) << manifest.name(); + EXPECT_EQ(std::string(), error) << manifest.name(); return extension; } @@ -154,7 +155,7 @@ scoped_refptr<Extension> extension = LoadExtension(manifest, &error, location, flags); EXPECT_TRUE(extension.get()) << manifest.name(); - EXPECT_EQ("", error) << manifest.name(); + EXPECT_EQ(std::string(), error) << manifest.name(); EXPECT_EQ(1u, extension->install_warnings().size()); EXPECT_EQ(expected_warning, extension->install_warnings()[0].message); return extension; @@ -169,6 +170,28 @@ ManifestData(manifest_name), expected_warning, location, flags); } +scoped_refptr<Extension> ManifestTest::LoadAndExpectWarnings( + char const* manifest_name, + const std::vector<std::string>& expected_warnings, + extensions::Manifest::Location location, + int flags) { + std::string error; + scoped_refptr<Extension> extension = + LoadExtension(ManifestData(manifest_name), &error, location, flags); + EXPECT_TRUE(extension.get()) << manifest_name; + EXPECT_EQ(std::string(), error) << manifest_name; + + std::vector<std::string> warning_messages; + warning_messages.reserve(extension->install_warnings().size()); + for (const auto& warning : extension->install_warnings()) { + warning_messages.push_back(warning.message); + } + + EXPECT_THAT(warning_messages, + testing::UnorderedElementsAreArray(expected_warnings)); + return extension; +} + void ManifestTest::VerifyExpectedError( Extension* extension, const std::string& name,
diff --git a/extensions/common/manifest_test.h b/extensions/common/manifest_test.h index 8a87932e..c6e3560 100644 --- a/extensions/common/manifest_test.h +++ b/extensions/common/manifest_test.h
@@ -87,16 +87,20 @@ scoped_refptr<extensions::Extension> LoadAndExpectWarning( const ManifestData& manifest, - const std::string& expected_error, - extensions::Manifest::Location location = - extensions::Manifest::INTERNAL, + const std::string& expected_warning, + extensions::Manifest::Location location = extensions::Manifest::INTERNAL, int flags = extensions::Extension::NO_FLAGS); scoped_refptr<extensions::Extension> LoadAndExpectWarning( char const* manifest_name, - const std::string& expected_error, - extensions::Manifest::Location location = - extensions::Manifest::INTERNAL, + const std::string& expected_warning, + extensions::Manifest::Location location = extensions::Manifest::INTERNAL, + int flags = extensions::Extension::NO_FLAGS); + + scoped_refptr<extensions::Extension> LoadAndExpectWarnings( + char const* manifest_name, + const std::vector<std::string>& expected_warnings, + extensions::Manifest::Location location = extensions::Manifest::INTERNAL, int flags = extensions::Extension::NO_FLAGS); void VerifyExpectedError(extensions::Extension* extension,
diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn index 051ac7a3..4e0663d 100644 --- a/extensions/renderer/BUILD.gn +++ b/extensions/renderer/BUILD.gn
@@ -174,8 +174,6 @@ "render_frame_observer_natives.h", "renderer_extension_registry.cc", "renderer_extension_registry.h", - "renderer_messaging_service.cc", - "renderer_messaging_service.h", "resource_bundle_source_map.cc", "resource_bundle_source_map.h", "resources/app_runtime_custom_bindings.js",
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc index 0a4b0c8..34b53284 100644 --- a/extensions/renderer/dispatcher.cc +++ b/extensions/renderer/dispatcher.cc
@@ -73,10 +73,10 @@ #include "extensions/renderer/messaging_util.h" #include "extensions/renderer/module_system.h" #include "extensions/renderer/native_extension_bindings_system.h" +#include "extensions/renderer/native_renderer_messaging_service.h" #include "extensions/renderer/process_info_native_handler.h" #include "extensions/renderer/render_frame_observer_natives.h" #include "extensions/renderer/renderer_extension_registry.h" -#include "extensions/renderer/renderer_messaging_service.h" #include "extensions/renderer/runtime_custom_bindings.h" #include "extensions/renderer/safe_builtins.h" #include "extensions/renderer/script_context.h" @@ -899,7 +899,7 @@ const PortId& target_port_id, const Message& message) { DCHECK_EQ(kMainThreadId, worker_thread_id); - bindings_system_->GetMessagingService()->DeliverMessage( + bindings_system_->messaging_service()->DeliverMessage( script_context_set_.get(), target_port_id, message, NULL); // All render frames. } @@ -913,7 +913,7 @@ DCHECK_EQ(kMainThreadId, worker_thread_id); DCHECK(!target_port_id.is_opener); - bindings_system_->GetMessagingService()->DispatchOnConnect( + bindings_system_->messaging_service()->DispatchOnConnect( script_context_set_.get(), target_port_id, channel_name, source, info, NULL); // All render frames. } @@ -922,7 +922,7 @@ const PortId& port_id, const std::string& error_message) { DCHECK_EQ(kMainThreadId, worker_thread_id); - bindings_system_->GetMessagingService()->DispatchOnDisconnect( + bindings_system_->messaging_service()->DispatchOnDisconnect( script_context_set_.get(), port_id, error_message, NULL); // All render frames. }
diff --git a/extensions/renderer/extension_frame_helper.cc b/extensions/renderer/extension_frame_helper.cc index 4e2b555..4508021 100644 --- a/extensions/renderer/extension_frame_helper.cc +++ b/extensions/renderer/extension_frame_helper.cc
@@ -20,7 +20,7 @@ #include "extensions/renderer/console.h" #include "extensions/renderer/dispatcher.h" #include "extensions/renderer/native_extension_bindings_system.h" -#include "extensions/renderer/renderer_messaging_service.h" +#include "extensions/renderer/native_renderer_messaging_service.h" #include "extensions/renderer/script_context.h" #include "extensions/renderer/script_context_set.h" #include "third_party/blink/public/platform/web_security_origin.h" @@ -398,7 +398,7 @@ const PortId& id) { DCHECK_EQ(kMainThreadId, worker_thread_id); extension_dispatcher_->bindings_system() - ->GetMessagingService() + ->messaging_service() ->ValidateMessagePort( extension_dispatcher_->script_context_set_iterator(), id, render_frame()); @@ -412,7 +412,7 @@ const ExtensionMsg_ExternalConnectionInfo& info) { DCHECK_EQ(kMainThreadId, worker_thread_id); extension_dispatcher_->bindings_system() - ->GetMessagingService() + ->messaging_service() ->DispatchOnConnect(extension_dispatcher_->script_context_set_iterator(), target_port_id, channel_name, source, info, render_frame()); @@ -422,10 +422,9 @@ const PortId& target_id, const Message& message) { DCHECK_EQ(kMainThreadId, worker_thread_id); - extension_dispatcher_->bindings_system() - ->GetMessagingService() - ->DeliverMessage(extension_dispatcher_->script_context_set_iterator(), - target_id, message, render_frame()); + extension_dispatcher_->bindings_system()->messaging_service()->DeliverMessage( + extension_dispatcher_->script_context_set_iterator(), target_id, message, + render_frame()); } void ExtensionFrameHelper::OnExtensionDispatchOnDisconnect( @@ -434,7 +433,7 @@ const std::string& error_message) { DCHECK_EQ(kMainThreadId, worker_thread_id); extension_dispatcher_->bindings_system() - ->GetMessagingService() + ->messaging_service() ->DispatchOnDisconnect( extension_dispatcher_->script_context_set_iterator(), id, error_message, render_frame());
diff --git a/extensions/renderer/native_extension_bindings_system.cc b/extensions/renderer/native_extension_bindings_system.cc index 356db006..13dde54 100644 --- a/extensions/renderer/native_extension_bindings_system.cc +++ b/extensions/renderer/native_extension_bindings_system.cc
@@ -653,10 +653,6 @@ return ipc_message_sender_.get(); } -RendererMessagingService* NativeExtensionBindingsSystem::GetMessagingService() { - return &messaging_service_; -} - void NativeExtensionBindingsSystem::OnExtensionPermissionsUpdated( const ExtensionId& id) { feature_cache_.InvalidateExtension(id);
diff --git a/extensions/renderer/native_extension_bindings_system.h b/extensions/renderer/native_extension_bindings_system.h index 85e4de7..beb55c30 100644 --- a/extensions/renderer/native_extension_bindings_system.h +++ b/extensions/renderer/native_extension_bindings_system.h
@@ -71,9 +71,6 @@ // Returns the associated IPC message sender. IPCMessageSender* GetIPCMessageSender(); - // Returns the associated RendererMessagingService. - RendererMessagingService* GetMessagingService(); - // Called when an extension's permissions are updated. void OnExtensionPermissionsUpdated(const ExtensionId& id);
diff --git a/extensions/renderer/native_renderer_messaging_service.cc b/extensions/renderer/native_renderer_messaging_service.cc index 564a568c..e186dfa 100644 --- a/extensions/renderer/native_renderer_messaging_service.cc +++ b/extensions/renderer/native_renderer_messaging_service.cc
@@ -7,6 +7,8 @@ #include <map> #include <string> +#include "base/bind.h" +#include "base/callback.h" #include "base/supports_user_data.h" #include "content/public/common/child_process_host.h" #include "content/public/renderer/render_frame.h" @@ -22,12 +24,19 @@ #include "extensions/renderer/get_script_context.h" #include "extensions/renderer/ipc_message_sender.h" #include "extensions/renderer/message_target.h" +#include "extensions/renderer/messaging_util.h" #include "extensions/renderer/native_extension_bindings_system.h" #include "extensions/renderer/script_context.h" #include "extensions/renderer/script_context_set.h" +#include "extensions/renderer/script_context_set_iterable.h" #include "gin/data_object_builder.h" #include "gin/handle.h" #include "gin/per_context_data.h" +#include "third_party/blink/public/web/web_document.h" +#include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_scoped_user_gesture.h" +#include "third_party/blink/public/web/web_scoped_window_focus_allowed_indicator.h" +#include "third_party/blink/public/web/web_user_gesture_indicator.h" #include "v8/include/v8.h" namespace extensions { @@ -61,11 +70,88 @@ NativeRendererMessagingService::NativeRendererMessagingService( NativeExtensionBindingsSystem* bindings_system) - : RendererMessagingService(bindings_system), - bindings_system_(bindings_system), + : bindings_system_(bindings_system), one_time_message_handler_(bindings_system) {} NativeRendererMessagingService::~NativeRendererMessagingService() {} +void NativeRendererMessagingService::ValidateMessagePort( + ScriptContextSetIterable* context_set, + const PortId& port_id, + content::RenderFrame* render_frame) { + // TODO(devlin): In practice, |render_frame| should never be null here (unlike + // in other methods, where it legitimately can), but it can be in testing. It + // would be better to fake it somehow, but unfortunately, there's no good way + // to have a RenderFrame in a unittest. :( + int routing_id = + render_frame ? render_frame->GetRoutingID() : MSG_ROUTING_NONE; + + bool has_port = false; + // The base::Unretained() below is safe since ScriptContextSet::ForEach is + // synchronous. + context_set->ForEach( + render_frame, + base::Bind(&NativeRendererMessagingService::ValidateMessagePortInContext, + base::Unretained(this), port_id, &has_port)); + + // A reply is only sent if the port is missing, because the port is assumed to + // exist unless stated otherwise. + if (!has_port) { + bindings_system_->GetIPCMessageSender()->SendCloseMessagePort( + routing_id, port_id, false); + } +} + +void NativeRendererMessagingService::DispatchOnConnect( + ScriptContextSetIterable* context_set, + const PortId& target_port_id, + const std::string& channel_name, + const ExtensionMsg_TabConnectionInfo& source, + const ExtensionMsg_ExternalConnectionInfo& info, + content::RenderFrame* restrict_to_render_frame) { + DCHECK(!target_port_id.is_opener); + int routing_id = restrict_to_render_frame + ? restrict_to_render_frame->GetRoutingID() + : MSG_ROUTING_NONE; + bool port_created = false; + context_set->ForEach( + info.target_id, restrict_to_render_frame, + base::Bind( + &NativeRendererMessagingService::DispatchOnConnectToScriptContext, + base::Unretained(this), target_port_id, channel_name, &source, info, + &port_created)); + // Note: |restrict_to_render_frame| may have been deleted at this point! + + IPCMessageSender* ipc_sender = bindings_system_->GetIPCMessageSender(); + if (port_created) { + ipc_sender->SendOpenMessagePort(routing_id, target_port_id); + } else { + ipc_sender->SendCloseMessagePort(routing_id, target_port_id, false); + } +} + +void NativeRendererMessagingService::DeliverMessage( + ScriptContextSetIterable* context_set, + const PortId& target_port_id, + const Message& message, + content::RenderFrame* restrict_to_render_frame) { + context_set->ForEach( + restrict_to_render_frame, + base::Bind(&NativeRendererMessagingService::DeliverMessageToScriptContext, + base::Unretained(this), message, target_port_id)); +} + +void NativeRendererMessagingService::DispatchOnDisconnect( + ScriptContextSetIterable* context_set, + const PortId& port_id, + const std::string& error_message, + content::RenderFrame* restrict_to_render_frame) { + context_set->ForEach( + restrict_to_render_frame, + base::Bind( + &NativeRendererMessagingService::DispatchOnDisconnectToScriptContext, + base::Unretained(this), port_id, error_message)); +} + gin::Handle<GinPort> NativeRendererMessagingService::Connect( ScriptContext* script_context, const MessageTarget& target, @@ -166,6 +252,98 @@ return ContextHasMessagePort(script_context, port_id); } +void NativeRendererMessagingService::ValidateMessagePortInContext( + const PortId& port_id, + bool* has_port, + ScriptContext* script_context) { + if (*has_port) + return; // Stop checking if the port was found. + + // No need for |=; we know this is false right now from above. + *has_port = ContextHasMessagePort(script_context, port_id); +} + +void NativeRendererMessagingService::DispatchOnConnectToScriptContext( + const PortId& target_port_id, + const std::string& channel_name, + const ExtensionMsg_TabConnectionInfo* source, + const ExtensionMsg_ExternalConnectionInfo& info, + bool* port_created, + ScriptContext* script_context) { + // If the channel was opened by this same context, ignore it. This should only + // happen when messages are sent to an entire process (rather than a single + // frame) as an optimization; otherwise the browser process filters this out. + if (script_context->context_id() == target_port_id.context_id) + return; + + // First, determine the event we'll use to connect. + std::string target_extension_id = script_context->GetExtensionID(); + bool is_external = + (info.source_endpoint.type == MessagingEndpoint::Type::kExtension || + info.source_endpoint.type == MessagingEndpoint::Type::kTab) && + info.source_endpoint.extension_id != target_extension_id; + std::string event_name; + if (info.source_endpoint.type == MessagingEndpoint::Type::kNativeApp) { + event_name = messaging_util::kOnConnectNativeEvent; + } else if (channel_name == messaging_util::kSendRequestChannel) { + event_name = is_external ? messaging_util::kOnRequestExternalEvent + : messaging_util::kOnRequestEvent; + } else if (channel_name == messaging_util::kSendMessageChannel) { + event_name = is_external ? messaging_util::kOnMessageExternalEvent + : messaging_util::kOnMessageEvent; + } else { + event_name = is_external ? messaging_util::kOnConnectExternalEvent + : messaging_util::kOnConnectEvent; + } + + // If there are no listeners for the given event, then we know the port won't + // be used in this context. + if (!bindings_system_->HasEventListenerInContext(event_name, + script_context)) { + return; + } + *port_created = true; + + DispatchOnConnectToListeners(script_context, target_port_id, + target_extension_id, channel_name, source, info, + event_name); +} + +void NativeRendererMessagingService::DeliverMessageToScriptContext( + const Message& message, + const PortId& target_port_id, + ScriptContext* script_context) { + if (!ContextHasMessagePort(script_context, target_port_id)) + return; + + std::unique_ptr<blink::WebScopedUserGesture> web_user_gesture; + std::unique_ptr<blink::WebScopedWindowFocusAllowedIndicator> + allow_window_focus; + if (message.user_gesture) { + web_user_gesture = std::make_unique<blink::WebScopedUserGesture>( + script_context->web_frame()); + + if (script_context->web_frame()) { + blink::WebDocument document = script_context->web_frame()->GetDocument(); + allow_window_focus = + std::make_unique<blink::WebScopedWindowFocusAllowedIndicator>( + &document); + } + } + + DispatchOnMessageToListeners(script_context, message, target_port_id); +} + +void NativeRendererMessagingService::DispatchOnDisconnectToScriptContext( + const PortId& port_id, + const std::string& error_message, + ScriptContext* script_context) { + if (!ContextHasMessagePort(script_context, port_id)) + return; + + DispatchOnDisconnectToListeners(script_context, port_id, error_message); +} + bool NativeRendererMessagingService::ContextHasMessagePort( ScriptContext* script_context, const PortId& port_id) {
diff --git a/extensions/renderer/native_renderer_messaging_service.h b/extensions/renderer/native_renderer_messaging_service.h index 4040265..15baf9c 100644 --- a/extensions/renderer/native_renderer_messaging_service.h +++ b/extensions/renderer/native_renderer_messaging_service.h
@@ -11,14 +11,18 @@ #include "extensions/common/extension_id.h" #include "extensions/renderer/gin_port.h" #include "extensions/renderer/one_time_message_handler.h" -#include "extensions/renderer/renderer_messaging_service.h" #include "gin/handle.h" struct ExtensionMsg_ExternalConnectionInfo; struct ExtensionMsg_TabConnectionInfo; +namespace content { +class RenderFrame; +} + namespace extensions { class NativeExtensionBindingsSystem; +class ScriptContextSetIterable; struct Message; struct MessageTarget; struct PortId; @@ -59,13 +63,42 @@ // TODO(devlin): This is a pretty large comment for a class, and it documents // browser/renderer interaction. I wonder if this would be better in a // messaging.md document? -class NativeRendererMessagingService : public RendererMessagingService, - public GinPort::Delegate { +class NativeRendererMessagingService : public GinPort::Delegate { public: explicit NativeRendererMessagingService( NativeExtensionBindingsSystem* bindings_system); ~NativeRendererMessagingService() override; + // Checks whether the port exists in the given frame. If it does not, a reply + // is sent back to the browser. + void ValidateMessagePort(ScriptContextSetIterable* context_set, + const PortId& port_id, + content::RenderFrame* render_frame); + + // Dispatches the onConnect content script messaging event to some contexts + // in |context_set|. If |restrict_to_render_frame| is specified, only contexts + // in that render frame will receive the message. + void DispatchOnConnect(ScriptContextSetIterable* context_set, + const PortId& target_port_id, + const std::string& channel_name, + const ExtensionMsg_TabConnectionInfo& source, + const ExtensionMsg_ExternalConnectionInfo& info, + content::RenderFrame* restrict_to_render_frame); + + // Delivers a message sent using content script messaging to some of the + // contexts in |bindings_context_set|. If |restrict_to_render_frame| is + // specified, only contexts in that render view will receive the message. + void DeliverMessage(ScriptContextSetIterable* context_set, + const PortId& target_port_id, + const Message& message, + content::RenderFrame* restrict_to_render_frame); + + // Dispatches the onDisconnect event in response to the channel being closed. + void DispatchOnDisconnect(ScriptContextSetIterable* context_set, + const PortId& port_id, + const std::string& error_message, + content::RenderFrame* restrict_to_render_frame); + // Creates and opens a new message port in the specified context. gin::Handle<GinPort> Connect(ScriptContext* script_context, const MessageTarget& target, @@ -97,9 +130,31 @@ bool HasPortForTesting(ScriptContext* script_context, const PortId& port_id); private: - // RendererMessagingService: + // Helpers for the public methods to perform the action in a single + // ScriptContext. + void ValidateMessagePortInContext(const PortId& port_id, + bool* has_port, + ScriptContext* script_context); + void DispatchOnConnectToScriptContext( + const PortId& target_port_id, + const std::string& channel_name, + const ExtensionMsg_TabConnectionInfo* source, + const ExtensionMsg_ExternalConnectionInfo& info, + bool* port_created, + ScriptContext* script_context); + void DeliverMessageToScriptContext(const Message& message, + const PortId& target_port_id, + ScriptContext* script_context); + void DispatchOnDisconnectToScriptContext(const PortId& port_id, + const std::string& error_message, + ScriptContext* script_context); + + // Returns true if the given |script_context| has a port with the given + // |port_id|. bool ContextHasMessagePort(ScriptContext* script_context, - const PortId& port_id) override; + const PortId& port_id); + + // Dispatches the onConnect event to listeners in the given |script_context|. void DispatchOnConnectToListeners( ScriptContext* script_context, const PortId& target_port_id, @@ -107,13 +162,20 @@ const std::string& channel_name, const ExtensionMsg_TabConnectionInfo* source, const ExtensionMsg_ExternalConnectionInfo& info, - const std::string& event_name) override; + const std::string& event_name); + + // Dispatches the onMessage event to listeners in the given |script_context|. + // This will only be called if the context has a port with the given id. void DispatchOnMessageToListeners(ScriptContext* script_context, const Message& message, - const PortId& target_port_id) override; + const PortId& target_port_id); + + // Dispatches the onDisconnect event to listeners in the given + // |script_context|. This will only be called if the context has a port + // with the given id. void DispatchOnDisconnectToListeners(ScriptContext* script_context, const PortId& port_id, - const std::string& error) override; + const std::string& error); // Creates a new port in the given context, with the specified |channel_name| // and |port_id|. Assumes no such port exists.
diff --git a/extensions/renderer/renderer_messaging_service.cc b/extensions/renderer/renderer_messaging_service.cc deleted file mode 100644 index be9c430a..0000000 --- a/extensions/renderer/renderer_messaging_service.cc +++ /dev/null
@@ -1,209 +0,0 @@ -// 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. - -#include "extensions/renderer/renderer_messaging_service.h" - -#include <string> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" -#include "base/callback_helpers.h" -#include "base/unguessable_token.h" -#include "base/values.h" -#include "content/public/renderer/render_frame.h" -#include "content/public/renderer/render_thread.h" -#include "content/public/renderer/v8_value_converter.h" -#include "extensions/common/api/messaging/message.h" -#include "extensions/common/api/messaging/messaging_endpoint.h" -#include "extensions/common/api/messaging/port_id.h" -#include "extensions/common/extension_messages.h" -#include "extensions/renderer/ipc_message_sender.h" -#include "extensions/renderer/messaging_util.h" -#include "extensions/renderer/native_extension_bindings_system.h" -#include "extensions/renderer/script_context.h" -#include "extensions/renderer/script_context_set_iterable.h" -#include "third_party/blink/public/web/web_document.h" -#include "third_party/blink/public/web/web_local_frame.h" -#include "third_party/blink/public/web/web_scoped_user_gesture.h" -#include "third_party/blink/public/web/web_scoped_window_focus_allowed_indicator.h" -#include "third_party/blink/public/web/web_user_gesture_indicator.h" -#include "v8/include/v8.h" - -namespace extensions { - -RendererMessagingService::RendererMessagingService( - NativeExtensionBindingsSystem* bindings_system) - : bindings_system_(bindings_system) {} -RendererMessagingService::~RendererMessagingService() {} - -void RendererMessagingService::ValidateMessagePort( - ScriptContextSetIterable* context_set, - const PortId& port_id, - content::RenderFrame* render_frame) { - // TODO(devlin): In practice, |render_frame| should never be null here (unlike - // in other methods, where it legitimately can), but it can be in testing. It - // would be better to fake it somehow, but unfortunately, there's no good way - // to have a RenderFrame in a unittest. :( - int routing_id = - render_frame ? render_frame->GetRoutingID() : MSG_ROUTING_NONE; - - bool has_port = false; - // The base::Unretained() below is safe since ScriptContextSet::ForEach is - // synchronous. - context_set->ForEach( - render_frame, - base::Bind(&RendererMessagingService::ValidateMessagePortInContext, - base::Unretained(this), port_id, &has_port)); - - // A reply is only sent if the port is missing, because the port is assumed to - // exist unless stated otherwise. - if (!has_port) { - bindings_system_->GetIPCMessageSender()->SendCloseMessagePort( - routing_id, port_id, false); - } -} - -void RendererMessagingService::DispatchOnConnect( - ScriptContextSetIterable* context_set, - const PortId& target_port_id, - const std::string& channel_name, - const ExtensionMsg_TabConnectionInfo& source, - const ExtensionMsg_ExternalConnectionInfo& info, - content::RenderFrame* restrict_to_render_frame) { - DCHECK(!target_port_id.is_opener); - int routing_id = restrict_to_render_frame - ? restrict_to_render_frame->GetRoutingID() - : MSG_ROUTING_NONE; - bool port_created = false; - context_set->ForEach( - info.target_id, restrict_to_render_frame, - base::Bind(&RendererMessagingService::DispatchOnConnectToScriptContext, - base::Unretained(this), target_port_id, channel_name, &source, - info, &port_created)); - // Note: |restrict_to_render_frame| may have been deleted at this point! - - IPCMessageSender* ipc_sender = bindings_system_->GetIPCMessageSender(); - if (port_created) { - ipc_sender->SendOpenMessagePort(routing_id, target_port_id); - } else { - ipc_sender->SendCloseMessagePort(routing_id, target_port_id, false); - } -} - -void RendererMessagingService::DeliverMessage( - ScriptContextSetIterable* context_set, - const PortId& target_port_id, - const Message& message, - content::RenderFrame* restrict_to_render_frame) { - context_set->ForEach( - restrict_to_render_frame, - base::Bind(&RendererMessagingService::DeliverMessageToScriptContext, - base::Unretained(this), message, target_port_id)); -} - -void RendererMessagingService::DispatchOnDisconnect( - ScriptContextSetIterable* context_set, - const PortId& port_id, - const std::string& error_message, - content::RenderFrame* restrict_to_render_frame) { - context_set->ForEach( - restrict_to_render_frame, - base::Bind(&RendererMessagingService::DispatchOnDisconnectToScriptContext, - base::Unretained(this), port_id, error_message)); -} - -void RendererMessagingService::ValidateMessagePortInContext( - const PortId& port_id, - bool* has_port, - ScriptContext* script_context) { - if (*has_port) - return; // Stop checking if the port was found. - - // No need for |=; we know this is false right now from above. - *has_port = ContextHasMessagePort(script_context, port_id); -} - -void RendererMessagingService::DispatchOnConnectToScriptContext( - const PortId& target_port_id, - const std::string& channel_name, - const ExtensionMsg_TabConnectionInfo* source, - const ExtensionMsg_ExternalConnectionInfo& info, - bool* port_created, - ScriptContext* script_context) { - // If the channel was opened by this same context, ignore it. This should only - // happen when messages are sent to an entire process (rather than a single - // frame) as an optimization; otherwise the browser process filters this out. - if (script_context->context_id() == target_port_id.context_id) - return; - - // First, determine the event we'll use to connect. - std::string target_extension_id = script_context->GetExtensionID(); - bool is_external = - (info.source_endpoint.type == MessagingEndpoint::Type::kExtension || - info.source_endpoint.type == MessagingEndpoint::Type::kTab) && - info.source_endpoint.extension_id != target_extension_id; - std::string event_name; - if (info.source_endpoint.type == MessagingEndpoint::Type::kNativeApp) { - event_name = messaging_util::kOnConnectNativeEvent; - } else if (channel_name == messaging_util::kSendRequestChannel) { - event_name = is_external ? messaging_util::kOnRequestExternalEvent - : messaging_util::kOnRequestEvent; - } else if (channel_name == messaging_util::kSendMessageChannel) { - event_name = is_external ? messaging_util::kOnMessageExternalEvent - : messaging_util::kOnMessageEvent; - } else { - event_name = is_external ? messaging_util::kOnConnectExternalEvent - : messaging_util::kOnConnectEvent; - } - - // If there are no listeners for the given event, then we know the port won't - // be used in this context. - if (!bindings_system_->HasEventListenerInContext(event_name, - script_context)) { - return; - } - *port_created = true; - - DispatchOnConnectToListeners(script_context, target_port_id, - target_extension_id, channel_name, source, info, - event_name); -} - -void RendererMessagingService::DeliverMessageToScriptContext( - const Message& message, - const PortId& target_port_id, - ScriptContext* script_context) { - if (!ContextHasMessagePort(script_context, target_port_id)) - return; - - std::unique_ptr<blink::WebScopedUserGesture> web_user_gesture; - std::unique_ptr<blink::WebScopedWindowFocusAllowedIndicator> - allow_window_focus; - if (message.user_gesture) { - web_user_gesture = std::make_unique<blink::WebScopedUserGesture>( - script_context->web_frame()); - - if (script_context->web_frame()) { - blink::WebDocument document = script_context->web_frame()->GetDocument(); - allow_window_focus = - std::make_unique<blink::WebScopedWindowFocusAllowedIndicator>( - &document); - } - } - - DispatchOnMessageToListeners(script_context, message, target_port_id); -} - -void RendererMessagingService::DispatchOnDisconnectToScriptContext( - const PortId& port_id, - const std::string& error_message, - ScriptContext* script_context) { - if (!ContextHasMessagePort(script_context, port_id)) - return; - - DispatchOnDisconnectToListeners(script_context, port_id, error_message); -} - -} // namespace extensions
diff --git a/extensions/renderer/renderer_messaging_service.h b/extensions/renderer/renderer_messaging_service.h deleted file mode 100644 index f725ce4e..0000000 --- a/extensions/renderer/renderer_messaging_service.h +++ /dev/null
@@ -1,122 +0,0 @@ -// 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. - -#ifndef EXTENSIONS_RENDERER_RENDERER_MESSAGING_SERVICE_H_ -#define EXTENSIONS_RENDERER_RENDERER_MESSAGING_SERVICE_H_ - -#include <string> - -#include "base/macros.h" -#include "extensions/common/extension_id.h" - -struct ExtensionMsg_ExternalConnectionInfo; -struct ExtensionMsg_TabConnectionInfo; - -namespace content { -class RenderFrame; -} - -namespace extensions { -class NativeExtensionBindingsSystem; -class ScriptContext; -class ScriptContextSetIterable; -struct Message; -struct PortId; - -// TODO(devlin): There is now only one RendererMessagingService (the -// NativeRendererMessagingService); consolidate the classes. -class RendererMessagingService { - public: - explicit RendererMessagingService( - NativeExtensionBindingsSystem* bindings_system); - virtual ~RendererMessagingService(); - - // Checks whether the port exists in the given frame. If it does not, a reply - // is sent back to the browser. - void ValidateMessagePort(ScriptContextSetIterable* context_set, - const PortId& port_id, - content::RenderFrame* render_frame); - - // Dispatches the onConnect content script messaging event to some contexts - // in |context_set|. If |restrict_to_render_frame| is specified, only contexts - // in that render frame will receive the message. - void DispatchOnConnect(ScriptContextSetIterable* context_set, - const PortId& target_port_id, - const std::string& channel_name, - const ExtensionMsg_TabConnectionInfo& source, - const ExtensionMsg_ExternalConnectionInfo& info, - content::RenderFrame* restrict_to_render_frame); - - // Delivers a message sent using content script messaging to some of the - // contexts in |bindings_context_set|. If |restrict_to_render_frame| is - // specified, only contexts in that render view will receive the message. - void DeliverMessage(ScriptContextSetIterable* context_set, - const PortId& target_port_id, - const Message& message, - content::RenderFrame* restrict_to_render_frame); - - // Dispatches the onDisconnect event in response to the channel being closed. - void DispatchOnDisconnect(ScriptContextSetIterable* context_set, - const PortId& port_id, - const std::string& error_message, - content::RenderFrame* restrict_to_render_frame); - - private: - // Helpers for the public methods to perform the action in a single - // ScriptContext. - void ValidateMessagePortInContext(const PortId& port_id, - bool* has_port, - ScriptContext* script_context); - void DispatchOnConnectToScriptContext( - const PortId& target_port_id, - const std::string& channel_name, - const ExtensionMsg_TabConnectionInfo* source, - const ExtensionMsg_ExternalConnectionInfo& info, - bool* port_created, - ScriptContext* script_context); - void DeliverMessageToScriptContext(const Message& message, - const PortId& target_port_id, - ScriptContext* script_context); - void DispatchOnDisconnectToScriptContext(const PortId& port_id, - const std::string& error_message, - ScriptContext* script_context); - - // Returns true if the given |script_context| has a port with the given - // |port_id|. - virtual bool ContextHasMessagePort(ScriptContext* script_context, - const PortId& port_id) = 0; - - // Dispatches the onConnect event to listeners in the given |script_context|. - virtual void DispatchOnConnectToListeners( - ScriptContext* script_context, - const PortId& target_port_id, - const ExtensionId& target_extension_id, - const std::string& channel_name, - const ExtensionMsg_TabConnectionInfo* source, - const ExtensionMsg_ExternalConnectionInfo& info, - const std::string& event_name) = 0; - - // Dispatches the onMessage event to listeners in the given |script_context|. - // This will only be called if the context has a port with the given id. - virtual void DispatchOnMessageToListeners(ScriptContext* script_context, - const Message& message, - const PortId& target_port_id) = 0; - - // Dispatches the onDisconnect event to listeners in the given - // |script_context|. This will only be called if the context has a port - // with the given id. - virtual void DispatchOnDisconnectToListeners(ScriptContext* script_context, - const PortId& port_id, - const std::string& error) = 0; - - // The associated NativeExtensionBindingsSystem; guaranteed to outlive this - // object. - NativeExtensionBindingsSystem* const bindings_system_; - - DISALLOW_COPY_AND_ASSIGN(RendererMessagingService); -}; - -} // namespace extensions - -#endif // EXTENSIONS_RENDERER_RENDERER_MESSAGING_SERVICE_H_
diff --git a/extensions/renderer/worker_thread_dispatcher.cc b/extensions/renderer/worker_thread_dispatcher.cc index d500685..47b79e0f 100644 --- a/extensions/renderer/worker_thread_dispatcher.cc +++ b/extensions/renderer/worker_thread_dispatcher.cc
@@ -20,7 +20,7 @@ #include "extensions/renderer/dispatcher.h" #include "extensions/renderer/extensions_renderer_client.h" #include "extensions/renderer/native_extension_bindings_system.h" -#include "extensions/renderer/renderer_messaging_service.h" +#include "extensions/renderer/native_renderer_messaging_service.h" #include "extensions/renderer/service_worker_data.h" #include "extensions/renderer/worker_script_context_set.h" @@ -166,7 +166,7 @@ const ExtensionMsg_ExternalConnectionInfo& info) { DCHECK_EQ(worker_thread_id, content::WorkerThread::GetCurrentId()); WorkerThreadDispatcher::GetBindingsSystem() - ->GetMessagingService() + ->messaging_service() ->DispatchOnConnect(Dispatcher::GetWorkerScriptContextSet(), target_port_id, channel_name, source, info, // Render frames do not matter. @@ -177,7 +177,7 @@ const PortId& id) { DCHECK_EQ(content::WorkerThread::GetCurrentId(), worker_thread_id); WorkerThreadDispatcher::GetBindingsSystem() - ->GetMessagingService() + ->messaging_service() ->ValidateMessagePort(Dispatcher::GetWorkerScriptContextSet(), id, // Render frames do not matter. nullptr); @@ -187,7 +187,7 @@ const PortId& target_port_id, const Message& message) { WorkerThreadDispatcher::GetBindingsSystem() - ->GetMessagingService() + ->messaging_service() ->DeliverMessage(Dispatcher::GetWorkerScriptContextSet(), target_port_id, message, // Render frames do not matter. @@ -199,7 +199,7 @@ const PortId& port_id, const std::string& error_message) { WorkerThreadDispatcher::GetBindingsSystem() - ->GetMessagingService() + ->messaging_service() ->DispatchOnDisconnect(Dispatcher::GetWorkerScriptContextSet(), port_id, error_message, // Render frames do not matter.
diff --git a/fuchsia/base/BUILD.gn b/fuchsia/base/BUILD.gn index c29edaf..06e662e9 100644 --- a/fuchsia/base/BUILD.gn +++ b/fuchsia/base/BUILD.gn
@@ -56,7 +56,6 @@ ":base", ":modular", "//base", - "//fuchsia:web_fidl", "//third_party/fuchsia-sdk/sdk:modular", "//third_party/fuchsia-sdk/sdk:web", "//url",
diff --git a/fuchsia/engine/BUILD.gn b/fuchsia/engine/BUILD.gn index 4247d6fb..5496627 100644 --- a/fuchsia/engine/BUILD.gn +++ b/fuchsia/engine/BUILD.gn
@@ -74,7 +74,6 @@ component("web_engine_core") { deps = [ - ":legacy_message_port_bridge", ":mojom", ":web_engine_pak", "//base", @@ -84,7 +83,6 @@ "//content/public/child", "//content/public/common", "//content/public/renderer", - "//fuchsia:web_fidl", "//fuchsia/base", "//fuchsia/base:modular", "//mojo/public/cpp/bindings", @@ -139,16 +137,6 @@ "context_provider_impl.h", "context_provider_main.cc", "context_provider_main.h", - "legacy_context_bridge.cc", - "legacy_context_bridge.h", - "legacy_context_provider_bridge.cc", - "legacy_context_provider_bridge.h", - "legacy_frame_bridge.cc", - "legacy_frame_bridge.h", - "legacy_navigation_controller_bridge.cc", - "legacy_navigation_controller_bridge.h", - "legacy_navigation_event_listener_bridge.cc", - "legacy_navigation_event_listener_bridge.h", "renderer/on_load_script_injector.cc", "renderer/on_load_script_injector.h", "renderer/web_engine_content_renderer_client.cc", @@ -205,7 +193,6 @@ ":web_engine_core", "//content/public/browser", "//content/test:test_support", - "//fuchsia:web_fidl", "//net:test_support", "//testing/gtest", "//third_party/fuchsia-sdk/sdk:web", @@ -216,9 +203,7 @@ test("web_engine_browsertests") { sources = [ "browser/context_impl_browsertest.cc", - "browser/context_impl_legacy_browsertest.cc", "browser/frame_impl_browsertest.cc", - "browser/frame_impl_legacy_browsertest.cc", ] defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] data = [ @@ -241,7 +226,6 @@ test("web_engine_unittests") { sources = [ - "context_provider_impl_legacy_unittest.cc", "context_provider_impl_unittest.cc", "fake_context.cc", "fake_context.h", @@ -250,7 +234,6 @@ ":web_engine_core", "//base/test:run_all_unittests", "//base/test:test_support", - "//fuchsia:web_fidl", "//testing/gmock", "//testing/gtest", "//third_party/fuchsia-sdk/sdk:web",
diff --git a/fuchsia/engine/DEPS b/fuchsia/engine/DEPS index 510cf28..a86f48c 100644 --- a/fuchsia/engine/DEPS +++ b/fuchsia/engine/DEPS
@@ -1,5 +1,4 @@ include_rules = [ - "+chromium/web/cpp", # FIDL generated headers "+content/public/app", "+services/service_manager", "+ui/base",
diff --git a/fuchsia/engine/browser/context_impl.cc b/fuchsia/engine/browser/context_impl.cc index 299798e..83be083f 100644 --- a/fuchsia/engine/browser/context_impl.cc +++ b/fuchsia/engine/browser/context_impl.cc
@@ -11,7 +11,6 @@ #include "base/fuchsia/fuchsia_logging.h" #include "content/public/browser/web_contents.h" #include "fuchsia/engine/browser/frame_impl.h" -#include "fuchsia/engine/legacy_frame_bridge.h" ContextImpl::ContextImpl(content::BrowserContext* browser_context) : browser_context_(browser_context) {} @@ -61,15 +60,3 @@ return nullptr; } - -FrameImpl* ContextImpl::GetFrameImplForTest( - chromium::web::FramePtr* frame_ptr) { - DCHECK(frame_ptr); - - fuchsia::web::FramePtr* fuchsia_frame_ptr = - LegacyFrameBridge::GetFramePtrForTest(frame_ptr); - if (!fuchsia_frame_ptr) - return nullptr; - - return GetFrameImplForTest(fuchsia_frame_ptr); -}
diff --git a/fuchsia/engine/browser/context_impl.h b/fuchsia/engine/browser/context_impl.h index c28f23fe5..1475b60 100644 --- a/fuchsia/engine/browser/context_impl.h +++ b/fuchsia/engine/browser/context_impl.h
@@ -12,7 +12,6 @@ #include "base/containers/unique_ptr_adapters.h" #include "base/macros.h" #include "fuchsia/engine/web_engine_export.h" -#include "fuchsia/fidl/chromium/web/cpp/fidl.h" namespace content { class BrowserContext; @@ -47,7 +46,6 @@ // Gets the underlying FrameImpl service object associated with a connected // |frame_ptr| client. FrameImpl* GetFrameImplForTest(fuchsia::web::FramePtr* frame_ptr); - FrameImpl* GetFrameImplForTest(chromium::web::FramePtr* frame_ptr); private: content::BrowserContext* browser_context_;
diff --git a/fuchsia/engine/browser/context_impl_legacy_browsertest.cc b/fuchsia/engine/browser/context_impl_legacy_browsertest.cc deleted file mode 100644 index f55c63e..0000000 --- a/fuchsia/engine/browser/context_impl_legacy_browsertest.cc +++ /dev/null
@@ -1,175 +0,0 @@ -// Copyright 2018 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 <lib/fidl/cpp/binding.h> - -#include "base/bind.h" -#include "base/macros.h" -#include "base/path_service.h" -#include "base/task/post_task.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/storage_partition.h" -#include "fuchsia/base/test_navigation_listener.h" -#include "fuchsia/engine/common.h" -#include "fuchsia/engine/test/web_engine_browser_test.h" -#include "net/cookies/cookie_store.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_getter.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/url_constants.h" - -using testing::_; -using testing::Field; -using testing::InvokeWithoutArgs; - -// Use a shorter name for NavigationEvent, because it is -// referenced frequently in this file. -using NavigationDetails = chromium::web::NavigationEvent; - -namespace { - -void OnCookiesReceived(net::CookieList* output, - base::OnceClosure on_received_cb, - const net::CookieList& cookies, - const net::CookieStatusList& excluded_cookies) { - *output = cookies; - std::move(on_received_cb).Run(); -} - -} // namespace - -// Defines a suite of tests that exercise browser-level configuration and -// functionality. -class ContextImplLegacyTest : public cr_fuchsia::WebEngineBrowserTest { - public: - ContextImplLegacyTest() = default; - ~ContextImplLegacyTest() override = default; - - protected: - // Creates a Frame with |navigation_listener_| attached. - chromium::web::FramePtr CreateFrame() { - return WebEngineBrowserTest::CreateLegacyFrame(&navigation_listener_); - } - - // Synchronously gets a list of cookies for this BrowserContext. - net::CookieList GetCookies() { - net::CookieStore* cookie_store = - content::BrowserContext::GetDefaultStoragePartition( - context_impl()->browser_context_for_test()) - ->GetURLRequestContext() - ->GetURLRequestContext() - ->cookie_store(); - - base::RunLoop run_loop; - net::CookieList cookies; - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce( - &net::CookieStore::GetAllCookiesAsync, - base::Unretained(cookie_store), - base::BindOnce(&OnCookiesReceived, base::Unretained(&cookies), - run_loop.QuitClosure()))); - run_loop.Run(); - return cookies; - } - - cr_fuchsia::TestNavigationListener navigation_listener_; - - private: - DISALLOW_COPY_AND_ASSIGN(ContextImplLegacyTest); -}; - -// Verifies that the BrowserContext has a working cookie store by setting -// cookies in the content layer and then querying the CookieStore afterward. -IN_PROC_BROWSER_TEST_F(ContextImplLegacyTest, VerifyPersistentCookieStore) { - ASSERT_TRUE(embedded_test_server()->Start()); - GURL cookie_url(embedded_test_server()->GetURL("/set-cookie?foo=bar")); - chromium::web::FramePtr frame = CreateFrame(); - - chromium::web::NavigationControllerPtr nav; - frame->GetNavigationController(nav.NewRequest()); - - nav->LoadUrl(cookie_url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(cookie_url, {}); - - auto cookies = GetCookies(); - bool found = false; - for (auto c : cookies) { - if (c.Name() == "foo" && c.Value() == "bar") { - found = true; - break; - } - } - EXPECT_TRUE(found); - - // Check that the cookie persists beyond the lifetime of the Frame by - // releasing the Frame and re-querying the CookieStore. - frame.Unbind(); - base::RunLoop().RunUntilIdle(); - - found = false; - for (auto c : cookies) { - if (c.Name() == "foo" && c.Value() == "bar") { - found = true; - break; - } - } - EXPECT_TRUE(found); -} - -// Suite for tests which run the BrowserContext in incognito mode (no data -// directory). -class IncognitoContextImplLegacyTest : public ContextImplLegacyTest { - public: - IncognitoContextImplLegacyTest() = default; - ~IncognitoContextImplLegacyTest() override = default; - - void SetUp() override { - base::CommandLine::ForCurrentProcess()->AppendSwitch(kIncognitoSwitch); - ContextImplLegacyTest::SetUp(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(IncognitoContextImplLegacyTest); -}; - -// Verify that the browser can be initialized without a persistent data -// directory. -IN_PROC_BROWSER_TEST_F(IncognitoContextImplLegacyTest, NavigateFrame) { - chromium::web::FramePtr frame = CreateFrame(); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - controller->LoadUrl(url::kAboutBlankURL, chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(GURL(url::kAboutBlankURL), {}); - - frame.Unbind(); -} - -IN_PROC_BROWSER_TEST_F(IncognitoContextImplLegacyTest, - VerifyInMemoryCookieStore) { - ASSERT_TRUE(embedded_test_server()->Start()); - GURL cookie_url(embedded_test_server()->GetURL("/set-cookie?foo=bar")); - chromium::web::FramePtr frame = CreateFrame(); - - chromium::web::NavigationControllerPtr nav; - frame->GetNavigationController(nav.NewRequest()); - - nav->LoadUrl(cookie_url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(cookie_url, {}); - - auto cookies = GetCookies(); - bool found = false; - for (auto c : cookies) { - if (c.Name() == "foo" && c.Value() == "bar") { - found = true; - break; - } - } - EXPECT_TRUE(found); -}
diff --git a/fuchsia/engine/browser/frame_impl_legacy_browsertest.cc b/fuchsia/engine/browser/frame_impl_legacy_browsertest.cc deleted file mode 100644 index 7e32cea..0000000 --- a/fuchsia/engine/browser/frame_impl_legacy_browsertest.cc +++ /dev/null
@@ -1,1229 +0,0 @@ -// Copyright 2018 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 <lib/fidl/cpp/binding.h> -#include <lib/ui/scenic/cpp/view_token_pair.h> - -#include "base/bind.h" -#include "base/fuchsia/fuchsia_logging.h" -#include "base/macros.h" -#include "base/test/bind_test_util.h" -#include "base/test/test_timeouts.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_observer.h" -#include "fuchsia/base/fit_adapter.h" -#include "fuchsia/base/mem_buffer_util.h" -#include "fuchsia/base/result_receiver.h" -#include "fuchsia/base/test_navigation_listener.h" -#include "fuchsia/engine/browser/frame_impl.h" -#include "fuchsia/engine/common.h" -#include "fuchsia/engine/test/web_engine_browser_test.h" -#include "net/test/embedded_test_server/embedded_test_server.h" -#include "net/test/embedded_test_server/http_request.h" -#include "net/url_request/url_request_context.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/url_constants.h" - -using testing::_; -using testing::AllOf; -using testing::Field; -using testing::InvokeWithoutArgs; -using testing::Mock; - -// Use a shorter name for NavigationEvent, because it is -// referenced frequently in this file. -using NavigationDetails = chromium::web::NavigationEvent; -using OnNavigationStateChangedCallback = - fuchsia::web::NavigationEventListener::OnNavigationStateChangedCallback; - -namespace { - -const char kPage1Path[] = "/title1.html"; -const char kPage2Path[] = "/title2.html"; -const char kPage3Path[] = "/websql.html"; -const char kDynamicTitlePath[] = "/dynamic_title.html"; -const char kPage1Title[] = "title 1"; -const char kPage2Title[] = "title 2"; -const char kPage3Title[] = "websql not available"; -const char kDataUrl[] = - "data:text/html;base64,PGI+SGVsbG8sIHdvcmxkLi4uPC9iPg=="; -const char kTestServerRoot[] = FILE_PATH_LITERAL("fuchsia/engine/test/data"); -const int64_t kOnLoadScriptId = 0; - -class MockWebContentsObserver : public content::WebContentsObserver { - public: - MockWebContentsObserver() = default; - ~MockWebContentsObserver() override = default; - - // WebContentsObserver implementation. - using content::WebContentsObserver::Observe; - - MOCK_METHOD2(DidFinishLoad, - void(content::RenderFrameHost* render_frame_host, - const GURL& validated_url)); -}; - -class WebContentsDeletionObserver : public content::WebContentsObserver { - public: - explicit WebContentsDeletionObserver(content::WebContents* web_contents) - : content::WebContentsObserver(web_contents) {} - - MOCK_METHOD1(RenderViewDeleted, - void(content::RenderViewHost* render_view_host)); -}; - -std::vector<uint8_t> StringToUnsignedVector(base::StringPiece str) { - const uint8_t* raw_data = reinterpret_cast<const uint8_t*>(str.data()); - return std::vector<uint8_t>(raw_data, raw_data + str.length()); -} - -std::string StringFromMemBufferOrDie(const fuchsia::mem::Buffer& buffer) { - std::string output; - CHECK(cr_fuchsia::StringFromMemBuffer(buffer, &output)); - return output; -} - -} // namespace - -// Defines a suite of tests that exercise Frame-level functionality, such as -// navigation commands and page events. -class FrameImplLegacyTest : public cr_fuchsia::WebEngineBrowserTest { - public: - FrameImplLegacyTest() - : run_timeout_(TestTimeouts::action_timeout(), - base::MakeExpectedNotRunClosure(FROM_HERE)) { - set_test_server_root(base::FilePath(kTestServerRoot)); - } - - ~FrameImplLegacyTest() = default; - - MOCK_METHOD1(OnServeHttpRequest, - void(const net::test_server::HttpRequest& request)); - - protected: - // Creates a Frame with |navigation_listener_| attached. - chromium::web::FramePtr CreateFrame() { - return WebEngineBrowserTest::CreateLegacyFrame(&navigation_listener_); - } - - cr_fuchsia::TestNavigationListener navigation_listener_; - - private: - const base::RunLoop::ScopedRunTimeoutForTest run_timeout_; - - DISALLOW_COPY_AND_ASSIGN(FrameImplLegacyTest); -}; - -// Verifies that the browser will navigate and generate a navigation observer -// event when LoadUrl() is called. -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, NavigateFrame) { - chromium::web::FramePtr frame = CreateFrame(); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - controller->LoadUrl(url::kAboutBlankURL, chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(GURL(url::kAboutBlankURL), - url::kAboutBlankURL); -} - -// TODO(crbug.com/931831): Remove this test once the transition is complete. -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, DeprecatedNavigateFrame) { - chromium::web::FramePtr frame = CreateFrame(); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - controller->LoadUrl(url::kAboutBlankURL, chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(GURL(url::kAboutBlankURL), {}); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, NavigateDataFrame) { - chromium::web::FramePtr frame = CreateFrame(); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - controller->LoadUrl(kDataUrl, chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(GURL(kDataUrl), kDataUrl); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, FrameDeletedBeforeContext) { - chromium::web::FramePtr frame = CreateFrame(); - - // Process the frame creation message. - base::RunLoop().RunUntilIdle(); - - FrameImpl* frame_impl = context_impl()->GetFrameImplForTest(&frame); - WebContentsDeletionObserver deletion_observer( - frame_impl->web_contents_for_test()); - base::RunLoop run_loop; - EXPECT_CALL(deletion_observer, RenderViewDeleted(_)) - .WillOnce(InvokeWithoutArgs([&run_loop] { run_loop.Quit(); })); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(url::kAboutBlankURL, chromium::web::LoadUrlParams()); - - frame.Unbind(); - run_loop.Run(); - - // Check that |context| remains bound after the frame is closed. - EXPECT_TRUE(context()); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, ContextDeletedBeforeFrame) { - chromium::web::FramePtr frame = CreateFrame(); - EXPECT_TRUE(frame); - - base::RunLoop run_loop; - frame.set_error_handler([&run_loop](zx_status_t status) { - EXPECT_EQ(status, ZX_ERR_PEER_CLOSED); - run_loop.Quit(); - }); - context().Unbind(); - run_loop.Run(); - EXPECT_FALSE(frame); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, ContextDeletedBeforeFrameWithView) { - chromium::web::FramePtr frame = CreateFrame(); - EXPECT_TRUE(frame); - - auto view_tokens = scenic::NewViewTokenPair(); - - frame->CreateView(std::move(view_tokens.first)); - base::RunLoop().RunUntilIdle(); - - base::RunLoop run_loop; - frame.set_error_handler([&run_loop](zx_status_t status) { - EXPECT_EQ(status, ZX_ERR_PEER_CLOSED); - run_loop.Quit(); - }); - context().Unbind(); - run_loop.Run(); - EXPECT_FALSE(frame); -} - -// TODO(https://crbug.com/695592): Remove this test when WebSQL is removed from -// Chrome. -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, EnsureWebSqlDisabled) { - chromium::web::FramePtr frame = CreateFrame(); - EXPECT_TRUE(frame); - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL title3(embedded_test_server()->GetURL(kPage3Path)); - controller->LoadUrl(title3.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(title3, kPage3Title); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, GoBackAndForward) { - chromium::web::FramePtr frame = CreateFrame(); - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL title1(embedded_test_server()->GetURL(kPage1Path)); - GURL title2(embedded_test_server()->GetURL(kPage2Path)); - - controller->LoadUrl(title1.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(title1, kPage1Title); - - controller->LoadUrl(title2.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(title2, kPage2Title); - - controller->GoBack(); - navigation_listener_.RunUntilNavigationEquals(title1, kPage1Title); - - // At the top of the navigation entry list; this should be a no-op. - controller->GoBack(); - - // Process the navigation request message. - base::RunLoop().RunUntilIdle(); - - controller->GoForward(); - navigation_listener_.RunUntilNavigationEquals(title2, kPage2Title); - - // At the end of the navigation entry list; this should be a no-op. - controller->GoForward(); - - // Process the navigation request message. - base::RunLoop().RunUntilIdle(); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, ReloadFrame) { - chromium::web::FramePtr frame = CreateFrame(); - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - embedded_test_server()->RegisterRequestMonitor(base::BindRepeating( - &FrameImplLegacyTest::OnServeHttpRequest, base::Unretained(this))); - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL url(embedded_test_server()->GetURL(kPage1Path)); - - EXPECT_CALL(*this, OnServeHttpRequest(_)).Times(testing::AtLeast(1)); - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(url, kPage1Title); - - MockWebContentsObserver web_contents_observer; - web_contents_observer.Observe( - context_impl()->GetFrameImplForTest(&frame)->web_contents_.get()); - - // Reload with NO_CACHE. - { - base::RunLoop run_loop; - EXPECT_CALL(web_contents_observer, DidFinishLoad(_, url)) - .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); - controller->Reload(chromium::web::ReloadType::NO_CACHE); - run_loop.Run(); - } - // Reload with PARTIAL_CACHE. - { - base::RunLoop run_loop; - EXPECT_CALL(web_contents_observer, DidFinishLoad(_, url)) - .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); - controller->Reload(chromium::web::ReloadType::PARTIAL_CACHE); - run_loop.Run(); - } -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, GetVisibleEntry) { - chromium::web::FramePtr frame = CreateFrame(); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - // Verify that a Frame returns a null NavigationEntry prior to receiving any - // LoadUrl() calls. - { - base::RunLoop run_loop; - controller->GetVisibleEntry( - [&run_loop](std::unique_ptr<chromium::web::NavigationEntry> details) { - EXPECT_EQ(nullptr, details.get()); - run_loop.Quit(); - }); - run_loop.Run(); - } - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL title1(embedded_test_server()->GetURL(kPage1Path)); - GURL title2(embedded_test_server()->GetURL(kPage2Path)); - - // Navigate to a page. - controller->LoadUrl(title1.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(title1, kPage1Title); - - // Verify that GetVisibleEntry() reflects the new Frame navigation state. - { - base::RunLoop run_loop; - controller->GetVisibleEntry( - [&run_loop, - &title1](std::unique_ptr<chromium::web::NavigationEntry> details) { - EXPECT_TRUE(details); - EXPECT_EQ(details->url, title1.spec()); - EXPECT_EQ(details->title, kPage1Title); - run_loop.Quit(); - }); - run_loop.Run(); - } - - // Navigate to another page. - controller->LoadUrl(title2.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(title2, kPage2Title); - - // Verify the navigation with GetVisibleEntry(). - { - base::RunLoop run_loop; - controller->GetVisibleEntry( - [&run_loop, - &title2](std::unique_ptr<chromium::web::NavigationEntry> details) { - EXPECT_TRUE(details); - EXPECT_EQ(details->url, title2.spec()); - EXPECT_EQ(details->title, kPage2Title); - run_loop.Quit(); - }); - run_loop.Run(); - } - - // Navigate back to the first page. - controller->LoadUrl(title1.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(title1, kPage1Title); - - // Verify the navigation with GetVisibleEntry(). - { - base::RunLoop run_loop; - controller->GetVisibleEntry( - [&run_loop, - &title1](std::unique_ptr<chromium::web::NavigationEntry> details) { - EXPECT_TRUE(details); - EXPECT_EQ(details->url, title1.spec()); - EXPECT_EQ(details->title, kPage1Title); - run_loop.Quit(); - }); - run_loop.Run(); - } -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, NoNavigationObserverAttached) { - chromium::web::FramePtr frame = - WebEngineBrowserTest::CreateLegacyFrame(nullptr); - base::RunLoop().RunUntilIdle(); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL title1(embedded_test_server()->GetURL(kPage1Path)); - GURL title2(embedded_test_server()->GetURL(kPage2Path)); - - MockWebContentsObserver observer; - observer.Observe( - context_impl()->GetFrameImplForTest(&frame)->web_contents_.get()); - - { - base::RunLoop run_loop; - EXPECT_CALL(observer, DidFinishLoad(_, title1)) - .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); - controller->LoadUrl(title1.spec(), chromium::web::LoadUrlParams()); - run_loop.Run(); - } - - { - base::RunLoop run_loop; - EXPECT_CALL(observer, DidFinishLoad(_, title2)) - .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); - controller->LoadUrl(title2.spec(), chromium::web::LoadUrlParams()); - run_loop.Run(); - } -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, ExecuteJavaScriptOnLoad) { - constexpr int64_t kBindingsId = 1234; - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL url(embedded_test_server()->GetURL(kDynamicTitlePath)); - chromium::web::FramePtr frame = CreateFrame(); - - frame->AddJavaScriptBindings( - kBindingsId, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), - [](bool success) { EXPECT_TRUE(success); }); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(url, {}); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, ExecuteJavaScriptLegacyOnLoad) { - ASSERT_TRUE(embedded_test_server()->Start()); - GURL url(embedded_test_server()->GetURL(kDynamicTitlePath)); - chromium::web::FramePtr frame = CreateFrame(); - - frame->ExecuteJavaScript( - {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), - chromium::web::ExecuteMode::ON_PAGE_LOAD, - [](bool success) { EXPECT_TRUE(success); }); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(url, "hello"); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, ExecuteJavaScriptUpdatedOnLoad) { - constexpr int64_t kBindingsId = 1234; - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL url(embedded_test_server()->GetURL(kDynamicTitlePath)); - chromium::web::FramePtr frame = CreateFrame(); - - frame->AddJavaScriptBindings( - kBindingsId, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), - [](bool success) { EXPECT_TRUE(success); }); - - // Verify that this script clobbers the previous script, as opposed to being - // injected alongside it. (The latter would result in the title being - // "helloclobber"). - frame->AddJavaScriptBindings( - kBindingsId, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString( - "stashed_title = document.title + 'clobber';"), - [](bool success) { EXPECT_TRUE(success); }); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(url, "clobber"); -} - -// Verifies that bindings are injected in order by producing a cumulative, -// non-commutative result. -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, ExecuteJavaScriptOnLoadOrdered) { - constexpr int64_t kBindingsId1 = 1234; - constexpr int64_t kBindingsId2 = 5678; - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL url(embedded_test_server()->GetURL(kDynamicTitlePath)); - chromium::web::FramePtr frame = CreateFrame(); - - frame->AddJavaScriptBindings( - kBindingsId1, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), - [](bool success) { EXPECT_TRUE(success); }); - frame->AddJavaScriptBindings( - kBindingsId2, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title += ' there';"), - [](bool success) { EXPECT_TRUE(success); }); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(url, "hello there"); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, ExecuteJavaScriptOnLoadRemoved) { - constexpr int64_t kBindingsId1 = 1234; - constexpr int64_t kBindingsId2 = 5678; - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL url(embedded_test_server()->GetURL(kDynamicTitlePath)); - chromium::web::FramePtr frame = CreateFrame(); - - frame->AddJavaScriptBindings( - kBindingsId1, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'foo';"), - [](bool success) { EXPECT_TRUE(success); }); - - // Add a script which clobbers "foo". - frame->AddJavaScriptBindings( - kBindingsId2, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'bar';"), - [](bool success) { EXPECT_TRUE(success); }); - - // Deletes the clobbering script. - frame->RemoveJavaScriptBindings(kBindingsId2, - [](bool removed) { EXPECT_TRUE(removed); }); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(url, "foo"); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, ExecuteJavaScriptRemoveInvalidId) { - ASSERT_TRUE(embedded_test_server()->Start()); - GURL url(embedded_test_server()->GetURL(kPage1Path)); - chromium::web::FramePtr frame = CreateFrame(); - - base::RunLoop remove_loop; - cr_fuchsia::ResultReceiver<bool> remove_result(remove_loop.QuitClosure()); - - frame->RemoveJavaScriptBindings( - kOnLoadScriptId, - cr_fuchsia::CallbackToFitFunction(remove_result.GetReceiveCallback())); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(url, kPage1Title); - - EXPECT_TRUE(*remove_result); -} - -// Test JS injection by using Javascript to trigger document navigation. -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, ExecuteJavaScriptImmediate) { - chromium::web::FramePtr frame = CreateFrame(); - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL title1(embedded_test_server()->GetURL(kPage1Path)); - GURL title2(embedded_test_server()->GetURL(kPage2Path)); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(title1.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(title1, kPage1Title); - - frame->ExecuteJavaScript( - {title1.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("window.location.href = \"" + - title2.spec() + "\";"), - chromium::web::ExecuteMode::IMMEDIATE_ONCE, - [](bool success) { EXPECT_TRUE(success); }); - - navigation_listener_.RunUntilNavigationEquals(title2, kPage2Title); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, - ExecuteJavaScriptOnLoadVmoDestroyed) { - ASSERT_TRUE(embedded_test_server()->Start()); - GURL url(embedded_test_server()->GetURL(kDynamicTitlePath)); - chromium::web::FramePtr frame = CreateFrame(); - - frame->AddJavaScriptBindings( - kOnLoadScriptId, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), - [](bool success) { EXPECT_TRUE(success); }); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(url, "hello"); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, - ExecuteJavascriptOnLoadWrongOrigin) { - ASSERT_TRUE(embedded_test_server()->Start()); - GURL url(embedded_test_server()->GetURL(kDynamicTitlePath)); - chromium::web::FramePtr frame = CreateFrame(); - - frame->AddJavaScriptBindings( - kOnLoadScriptId, {"http://example.com"}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), - [](bool success) { EXPECT_TRUE(success); }); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - // Expect that the original HTML title is used, because we didn't inject a - // script with a replacement title. - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals( - url, "Welcome to Stan the Offline Dino's Homepage"); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, - ExecuteJavaScriptOnLoadWildcardOrigin) { - ASSERT_TRUE(embedded_test_server()->Start()); - GURL url(embedded_test_server()->GetURL(kDynamicTitlePath)); - chromium::web::FramePtr frame = CreateFrame(); - - frame->AddJavaScriptBindings( - kOnLoadScriptId, {"*"}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), - [](bool success) { EXPECT_TRUE(success); }); - - // Test script injection for the origin 127.0.0.1. - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(url, "hello"); - - controller->LoadUrl(url::kAboutBlankURL, chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(GURL(url::kAboutBlankURL), {}); - - // Test script injection using a different origin ("localhost"), which should - // still be picked up by the wildcard. - GURL alt_url = embedded_test_server()->GetURL("localhost", kDynamicTitlePath); - controller->LoadUrl(alt_url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(alt_url, "hello"); -} - -// Test that consecutive scripts are executed in order by computing a cumulative -// result. -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, ExecuteMultipleJavaScriptsOnLoad) { - constexpr int64_t kOnLoadScriptId2 = kOnLoadScriptId + 1; - ASSERT_TRUE(embedded_test_server()->Start()); - GURL url(embedded_test_server()->GetURL(kDynamicTitlePath)); - chromium::web::FramePtr frame = CreateFrame(); - - frame->AddJavaScriptBindings( - kOnLoadScriptId, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), - [](bool success) { EXPECT_TRUE(success); }); - frame->AddJavaScriptBindings( - kOnLoadScriptId2, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title += ' there';"), - [](bool success) { EXPECT_TRUE(success); }); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(url, "hello there"); -} - -// Test that we can inject scripts before and after RenderFrame creation. -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, - ExecuteOnLoadEarlyAndLateRegistrations) { - constexpr int64_t kOnLoadScriptId2 = kOnLoadScriptId + 1; - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL url(embedded_test_server()->GetURL(kDynamicTitlePath)); - chromium::web::FramePtr frame = CreateFrame(); - - frame->AddJavaScriptBindings( - kOnLoadScriptId, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), - [](bool success) { EXPECT_TRUE(success); }); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(url, "hello"); - - frame->AddJavaScriptBindings( - kOnLoadScriptId2, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title += ' there';"), - [](bool success) { EXPECT_TRUE(success); }); - - // Navigate away to clean the slate. - controller->LoadUrl(url::kAboutBlankURL, chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(GURL(url::kAboutBlankURL), {}); - - // Navigate back and see if both scripts are working. - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(url, "hello there"); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, ExecuteJavaScriptBadEncoding) { - chromium::web::FramePtr frame = CreateFrame(); - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL url(embedded_test_server()->GetURL(kPage1Path)); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(url, kPage1Title); - - base::RunLoop run_loop; - - // 0xFE is an illegal UTF-8 byte; it should cause UTF-8 conversion to fail. - frame->ExecuteJavaScript( - {url.host()}, cr_fuchsia::MemBufferFromString("true;\xfe"), - chromium::web::ExecuteMode::IMMEDIATE_ONCE, [&run_loop](bool success) { - EXPECT_FALSE(success); - run_loop.Quit(); - }); - run_loop.Run(); -} - -// Verifies that a Frame will handle navigation observer disconnection events -// gracefully. -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, NavigationObserverDisconnected) { - chromium::web::FramePtr frame = CreateFrame(); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL title1(embedded_test_server()->GetURL(kPage1Path)); - GURL title2(embedded_test_server()->GetURL(kPage2Path)); - - MockWebContentsObserver web_contents_observer; - web_contents_observer.Observe( - context_impl()->GetFrameImplForTest(&frame)->web_contents_.get()); - EXPECT_CALL(web_contents_observer, DidFinishLoad(_, title1)); - - controller->LoadUrl(title1.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(title1, kPage1Title); - - // Disconnect the observer & spin the runloop to propagate the disconnection - // event over IPC. - navigation_listener_bindings().CloseAll(); - base::RunLoop().RunUntilIdle(); - - base::RunLoop run_loop; - EXPECT_CALL(web_contents_observer, DidFinishLoad(_, title2)) - .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); - controller->LoadUrl(title2.spec(), chromium::web::LoadUrlParams()); - run_loop.Run(); -} - -// TODO(crbug.com/947268): Re-enable this once flakiness is addressed. -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, - DISABLED_DelayedNavigationEventAck) { - chromium::web::FramePtr frame = CreateFrame(); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL title1(embedded_test_server()->GetURL(kPage1Path)); - GURL title2(embedded_test_server()->GetURL(kPage2Path)); - - MockWebContentsObserver web_contents_observer; - EXPECT_CALL(web_contents_observer, DidFinishLoad(_, title1)); - - // Expect an navigation event here, but deliberately postpone acknowledgement - // until the end of the test. - base::RunLoop captured_ack_run_loop; - OnNavigationStateChangedCallback captured_ack_cb; - navigation_listener_.SetBeforeAckHook(base::BindRepeating( - [](OnNavigationStateChangedCallback* dest_cb, - const fuchsia::web::NavigationState&, - OnNavigationStateChangedCallback cb) { *dest_cb = std::move(cb); }, - base::Unretained(&captured_ack_cb))); - - controller->LoadUrl(title1.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(title1, kPage1Title); - EXPECT_TRUE(captured_ack_cb); - - // Since we have blocked NavigationEventObserver's flow, we must observe the - // WebContents events directly via a test-only seam. - web_contents_observer.Observe( - context_impl()->GetFrameImplForTest(&frame)->web_contents_.get()); - - // Navigate to a second page. - { - base::RunLoop run_loop; - EXPECT_CALL(web_contents_observer, DidFinishLoad(_, title2)) - .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); - controller->LoadUrl(title2.spec(), chromium::web::LoadUrlParams()); - run_loop.Run(); - Mock::VerifyAndClearExpectations(this); - } - - // Navigate to the first page. - { - base::RunLoop run_loop; - EXPECT_CALL(web_contents_observer, DidFinishLoad(_, title1)) - .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); - controller->LoadUrl(title1.spec(), chromium::web::LoadUrlParams()); - run_loop.Run(); - Mock::VerifyAndClearExpectations(this); - } - - // Since there was no observable change in navigation state since the last - // ack, there should be no more NavigationEvents generated. - captured_ack_cb(); - navigation_listener_.RunUntilNavigationEquals(title1, kPage1Title); -} - -// Observes events specific to the Stop() test case. -struct WebContentsObserverForStop : public content::WebContentsObserver { - using content::WebContentsObserver::Observe; - MOCK_METHOD1(DidStartNavigation, void(content::NavigationHandle*)); - MOCK_METHOD0(NavigationStopped, void()); -}; - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, Stop) { - chromium::web::FramePtr frame = CreateFrame(); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - ASSERT_TRUE(embedded_test_server()->Start()); - - // Use a request handler that will accept the connection and stall - // indefinitely. - GURL hung_url(embedded_test_server()->GetURL("/hung")); - - WebContentsObserverForStop observer; - observer.Observe( - context_impl()->GetFrameImplForTest(&frame)->web_contents_.get()); - - { - base::RunLoop run_loop; - EXPECT_CALL(observer, DidStartNavigation(_)) - .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); - controller->LoadUrl(hung_url.spec(), chromium::web::LoadUrlParams()); - run_loop.Run(); - Mock::VerifyAndClearExpectations(this); - } - - EXPECT_TRUE( - context_impl()->GetFrameImplForTest(&frame)->web_contents_->IsLoading()); - - { - base::RunLoop run_loop; - EXPECT_CALL(observer, NavigationStopped()) - .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); - controller->Stop(); - run_loop.Run(); - Mock::VerifyAndClearExpectations(this); - } - - EXPECT_FALSE( - context_impl()->GetFrameImplForTest(&frame)->web_contents_->IsLoading()); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, PostMessage) { - chromium::web::FramePtr frame = CreateFrame(); - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL post_message_url( - embedded_test_server()->GetURL("/window_post_message.html")); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(post_message_url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(post_message_url, - "postmessage"); - - chromium::web::WebMessage message; - message.data = cr_fuchsia::MemBufferFromString(kPage1Path); - cr_fuchsia::ResultReceiver<bool> post_result; - frame->PostMessage( - std::move(message), post_message_url.GetOrigin().spec(), - cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback())); - - navigation_listener_.RunUntilNavigationEquals( - embedded_test_server()->GetURL(kPage1Path), kPage1Title); - - EXPECT_TRUE(*post_result); -} - -// Send a MessagePort to the content, then perform bidirectional messaging -// through the port. -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, PostMessagePassMessagePort) { - chromium::web::FramePtr frame = CreateFrame(); - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL post_message_url(embedded_test_server()->GetURL("/message_port.html")); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(post_message_url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(post_message_url, - "messageport"); - - chromium::web::MessagePortPtr message_port; - chromium::web::WebMessage msg; - { - msg.outgoing_transfer = - std::make_unique<chromium::web::OutgoingTransferable>(); - msg.outgoing_transfer->set_message_port(message_port.NewRequest()); - msg.data = cr_fuchsia::MemBufferFromString("hi"); - cr_fuchsia::ResultReceiver<bool> post_result; - frame->PostMessage( - std::move(msg), post_message_url.GetOrigin().spec(), - cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback())); - - base::RunLoop run_loop; - cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver( - run_loop.QuitClosure()); - message_port->ReceiveMessage( - cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback())); - run_loop.Run(); - EXPECT_EQ("got_port", StringFromMemBufferOrDie(receiver->data)); - } - - { - msg.data = cr_fuchsia::MemBufferFromString("ping"); - cr_fuchsia::ResultReceiver<bool> post_result; - message_port->PostMessage( - std::move(msg), - cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback())); - base::RunLoop run_loop; - cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver( - run_loop.QuitClosure()); - message_port->ReceiveMessage( - cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback())); - run_loop.Run(); - EXPECT_EQ("ack ping", StringFromMemBufferOrDie(receiver->data)); - EXPECT_TRUE(*post_result); - } -} - -// Send a MessagePort to the content, then perform bidirectional messaging -// over its channel. -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, - PostMessageMessagePortDisconnected) { - chromium::web::FramePtr frame = CreateFrame(); - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL post_message_url(embedded_test_server()->GetURL("/message_port.html")); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(post_message_url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(post_message_url, - "messageport"); - - chromium::web::MessagePortPtr message_port; - chromium::web::WebMessage msg; - { - msg.outgoing_transfer = - std::make_unique<chromium::web::OutgoingTransferable>(); - msg.outgoing_transfer->set_message_port(message_port.NewRequest()); - msg.data = cr_fuchsia::MemBufferFromString("hi"); - cr_fuchsia::ResultReceiver<bool> post_result; - frame->PostMessage( - std::move(msg), post_message_url.GetOrigin().spec(), - cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback())); - - base::RunLoop run_loop; - cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver( - run_loop.QuitClosure()); - message_port->ReceiveMessage( - cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback())); - run_loop.Run(); - EXPECT_EQ("got_port", StringFromMemBufferOrDie(receiver->data)); - EXPECT_TRUE(*post_result); - } - - // Navigating off-page should tear down the Mojo channel, thereby causing the - // MessagePortImpl to self-destruct and tear down its FIDL channel. - { - base::RunLoop run_loop; - message_port.set_error_handler( - [&run_loop](zx_status_t) { run_loop.Quit(); }); - controller->LoadUrl(url::kAboutBlankURL, chromium::web::LoadUrlParams()); - run_loop.Run(); - } -} - -// Send a MessagePort to the content, and through that channel, receive a -// different MessagePort that was created by the content. Verify the second -// channel's liveness by sending a ping to it. -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, PostMessageUseContentProvidedPort) { - chromium::web::FramePtr frame = CreateFrame(); - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL post_message_url(embedded_test_server()->GetURL("/message_port.html")); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(post_message_url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(post_message_url, - "messageport"); - - chromium::web::MessagePortPtr incoming_message_port; - chromium::web::WebMessage msg; - { - chromium::web::MessagePortPtr message_port; - msg.outgoing_transfer = - std::make_unique<chromium::web::OutgoingTransferable>(); - msg.outgoing_transfer->set_message_port(message_port.NewRequest()); - msg.data = cr_fuchsia::MemBufferFromString("hi"); - cr_fuchsia::ResultReceiver<bool> post_result; - frame->PostMessage( - std::move(msg), "*", - cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback())); - - base::RunLoop run_loop; - cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver( - run_loop.QuitClosure()); - message_port->ReceiveMessage( - cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback())); - run_loop.Run(); - EXPECT_EQ("got_port", StringFromMemBufferOrDie(receiver->data)); - incoming_message_port = receiver->incoming_transfer->message_port().Bind(); - EXPECT_TRUE(*post_result); - } - - // Get the content to send three 'ack ping' messages, which will accumulate in - // the MessagePortImpl buffer. - for (int i = 0; i < 3; ++i) { - base::RunLoop run_loop; - cr_fuchsia::ResultReceiver<bool> post_result(run_loop.QuitClosure()); - msg.data = cr_fuchsia::MemBufferFromString("ping"); - incoming_message_port->PostMessage( - std::move(msg), - cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback())); - run_loop.Run(); - EXPECT_TRUE(*post_result); - } - - // Receive another acknowledgement from content on a side channel to ensure - // that all the "ack pings" are ready to be consumed. - { - chromium::web::MessagePortPtr ack_message_port; - chromium::web::WebMessage msg; - msg.outgoing_transfer = - std::make_unique<chromium::web::OutgoingTransferable>(); - msg.outgoing_transfer->set_message_port(ack_message_port.NewRequest()); - msg.data = cr_fuchsia::MemBufferFromString("hi"); - - // Quit the runloop only after we've received a WebMessage AND a PostMessage - // result. - cr_fuchsia::ResultReceiver<bool> post_result; - frame->PostMessage( - std::move(msg), "*", - cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback())); - base::RunLoop run_loop; - cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver( - run_loop.QuitClosure()); - ack_message_port->ReceiveMessage( - cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback())); - run_loop.Run(); - EXPECT_EQ("got_port", StringFromMemBufferOrDie(receiver->data)); - EXPECT_TRUE(*post_result); - } - - // Pull the three 'ack ping's from the buffer. - for (int i = 0; i < 3; ++i) { - base::RunLoop run_loop; - cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver( - run_loop.QuitClosure()); - incoming_message_port->ReceiveMessage( - cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback())); - run_loop.Run(); - EXPECT_EQ("ack ping", StringFromMemBufferOrDie(receiver->data)); - } -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, PostMessageBadOriginDropped) { - chromium::web::FramePtr frame = CreateFrame(); - - ASSERT_TRUE(embedded_test_server()->Start()); - GURL post_message_url(embedded_test_server()->GetURL("/message_port.html")); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - controller->LoadUrl(post_message_url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(post_message_url, - "messageport"); - - chromium::web::MessagePortPtr bad_origin_incoming_message_port; - chromium::web::WebMessage msg; - - // PostMessage() to invalid origins should be ignored. We pass in a - // MessagePort but nothing should happen to it. - chromium::web::MessagePortPtr unused_message_port; - msg.outgoing_transfer = - std::make_unique<chromium::web::OutgoingTransferable>(); - msg.outgoing_transfer->set_message_port(unused_message_port.NewRequest()); - msg.data = cr_fuchsia::MemBufferFromString("bad origin, bad!"); - cr_fuchsia::ResultReceiver<bool> unused_post_result; - frame->PostMessage(std::move(msg), "https://example.com", - cr_fuchsia::CallbackToFitFunction( - unused_post_result.GetReceiveCallback())); - cr_fuchsia::ResultReceiver<chromium::web::WebMessage> unused_message_read; - bad_origin_incoming_message_port->ReceiveMessage( - cr_fuchsia::CallbackToFitFunction( - unused_message_read.GetReceiveCallback())); - - // PostMessage() with a valid origin should succeed. - // Verify it by looking for an ack message on the MessagePort we passed in. - // Since message events are handled in order, observing the result of this - // operation will verify whether the previous PostMessage() was received but - // discarded. - chromium::web::MessagePortPtr incoming_message_port; - chromium::web::MessagePortPtr message_port; - msg.outgoing_transfer = - std::make_unique<chromium::web::OutgoingTransferable>(); - msg.outgoing_transfer->set_message_port(message_port.NewRequest()); - msg.data = cr_fuchsia::MemBufferFromString("good origin"); - cr_fuchsia::ResultReceiver<bool> post_result; - frame->PostMessage( - std::move(msg), "*", - cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback())); - base::RunLoop run_loop; - cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver( - run_loop.QuitClosure()); - message_port->ReceiveMessage( - cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback())); - run_loop.Run(); - EXPECT_EQ("got_port", StringFromMemBufferOrDie(receiver->data)); - incoming_message_port = receiver->incoming_transfer->message_port().Bind(); - EXPECT_TRUE(*post_result); - - // Verify that the first PostMessage() call wasn't handled. - EXPECT_FALSE(unused_message_read.has_value()); -} - -IN_PROC_BROWSER_TEST_F(FrameImplLegacyTest, RecreateView) { - chromium::web::FramePtr frame = CreateFrame(); - - ASSERT_TRUE(embedded_test_server()->Start()); - - // Process the Frame creation request, and verify we can get the FrameImpl. - base::RunLoop().RunUntilIdle(); - FrameImpl* frame_impl = context_impl()->GetFrameImplForTest(&frame); - ASSERT_TRUE(frame_impl); - EXPECT_FALSE(frame_impl->has_view_for_test()); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - // Verify that the Frame can navigate, prior to the View being created. - const GURL page1_url(embedded_test_server()->GetURL(kPage1Path)); - controller->LoadUrl(page1_url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(page1_url, kPage1Title); - - // Request a View from the Frame, and pump the loop to process the request. - zx::eventpair owner_token, frame_token; - ASSERT_EQ(zx::eventpair::create(0, &owner_token, &frame_token), ZX_OK); - frame->CreateView2(std::move(frame_token), nullptr, nullptr); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(frame_impl->has_view_for_test()); - - // Verify that the Frame still works, by navigating to Page #2. - const GURL page2_url(embedded_test_server()->GetURL(kPage2Path)); - controller->LoadUrl(page2_url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(page2_url, kPage2Title); - - // Create new View tokens and request a new view. - zx::eventpair owner_token2, frame_token2; - ASSERT_EQ(zx::eventpair::create(0, &owner_token2, &frame_token2), ZX_OK); - frame->CreateView2(std::move(frame_token), nullptr, nullptr); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(frame_impl->has_view_for_test()); - - // Verify that the Frame still works, by navigating back to Page #1. - controller->LoadUrl(page1_url.spec(), chromium::web::LoadUrlParams()); - navigation_listener_.RunUntilNavigationEquals(page1_url, kPage1Title); -} - -class RequestMonitoringFrameImplLegacyBrowserTest : public FrameImplLegacyTest { - public: - RequestMonitoringFrameImplLegacyBrowserTest() = default; - - protected: - void SetUpOnMainThread() override { - // Accumulate all http requests made to |embedded_test_server| into - // |accumulated_requests_| container. - embedded_test_server()->RegisterRequestMonitor(base::BindRepeating( - &RequestMonitoringFrameImplLegacyBrowserTest::MonitorRequestOnIoThread, - base::Unretained(this), base::SequencedTaskRunnerHandle::Get())); - - ASSERT_TRUE(embedded_test_server()->Start()); - } - - void TearDown() override { - EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); - } - - std::map<GURL, net::test_server::HttpRequest> accumulated_requests_; - - private: - void MonitorRequestOnIoThread( - const scoped_refptr<base::SequencedTaskRunner>& main_thread_task_runner, - const net::test_server::HttpRequest& request) { - main_thread_task_runner->PostTask( - FROM_HERE, base::BindOnce(&RequestMonitoringFrameImplLegacyBrowserTest:: - MonitorRequestOnMainThread, - base::Unretained(this), request)); - } - - void MonitorRequestOnMainThread( - const net::test_server::HttpRequest& request) { - accumulated_requests_[request.GetURL()] = request; - } - - DISALLOW_COPY_AND_ASSIGN(RequestMonitoringFrameImplLegacyBrowserTest); -}; - -IN_PROC_BROWSER_TEST_F(RequestMonitoringFrameImplLegacyBrowserTest, - ExtraHeaders) { - chromium::web::FramePtr frame = CreateFrame(); - - chromium::web::NavigationControllerPtr controller; - frame->GetNavigationController(controller.NewRequest()); - - const GURL page_url(embedded_test_server()->GetURL(kPage1Path)); - chromium::web::LoadUrlParams load_url_params; - load_url_params.set_headers({StringToUnsignedVector("X-ExtraHeaders: 1"), - StringToUnsignedVector("X-2ExtraHeaders: 2")}); - controller->LoadUrl(page_url.spec(), std::move(load_url_params)); - navigation_listener_.RunUntilNavigationEquals(page_url, kPage1Title); - - // At this point, the page should be loaded, the server should have received - // the request and the request should be in the map. - const auto iter = accumulated_requests_.find(page_url); - ASSERT_NE(iter, accumulated_requests_.end()); - EXPECT_THAT(iter->second.headers, - testing::Contains(testing::Key("X-ExtraHeaders"))); - EXPECT_THAT(iter->second.headers, - testing::Contains(testing::Key("X-2ExtraHeaders"))); -}
diff --git a/fuchsia/engine/context_provider_impl.h b/fuchsia/engine/context_provider_impl.h index ebb58f49..e25a982a 100644 --- a/fuchsia/engine/context_provider_impl.h +++ b/fuchsia/engine/context_provider_impl.h
@@ -11,7 +11,6 @@ #include "base/callback.h" #include "base/macros.h" -#include "chromium/web/cpp/fidl.h" #include "fuchsia/engine/web_engine_export.h" namespace base {
diff --git a/fuchsia/engine/context_provider_impl_legacy_unittest.cc b/fuchsia/engine/context_provider_impl_legacy_unittest.cc deleted file mode 100644 index 3e2dde4..0000000 --- a/fuchsia/engine/context_provider_impl_legacy_unittest.cc +++ /dev/null
@@ -1,289 +0,0 @@ -// Copyright 2018 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 "fuchsia/engine/context_provider_impl.h" - -#include <lib/fdio/directory.h> -#include <lib/fidl/cpp/binding.h> -#include <zircon/processargs.h> -#include <zircon/types.h> - -#include <functional> -#include <string> -#include <utility> -#include <vector> - -#include "base/base_paths_fuchsia.h" -#include "base/base_switches.h" -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" -#include "base/command_line.h" -#include "base/files/file.h" -#include "base/files/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "base/fuchsia/default_job.h" -#include "base/fuchsia/file_utils.h" -#include "base/fuchsia/fuchsia_logging.h" -#include "base/fuchsia/service_directory.h" -#include "base/message_loop/message_loop.h" -#include "base/path_service.h" -#include "base/test/multiprocess_test.h" -#include "base/test/test_timeouts.h" -#include "fuchsia/engine/common.h" -#include "fuchsia/engine/fake_context.h" -#include "fuchsia/engine/legacy_context_provider_bridge.h" -#include "fuchsia/fidl/chromium/web/cpp/fidl_test_base.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/multiprocess_func_list.h" - -namespace { - -constexpr char kTestDataFileIn[] = "DataFileIn"; -constexpr char kTestDataFileOut[] = "DataFileOut"; -constexpr char kUrl[] = "chrome://:emorhc"; -constexpr char kTitle[] = "Palindrome"; - -base::Process LaunchFakeContextProcess(const base::CommandLine& command_line, - const base::LaunchOptions& options) { - base::LaunchOptions options_with_tmp = options; - options_with_tmp.paths_to_clone.push_back(base::FilePath("/tmp")); - return base::SpawnMultiProcessTestChild("SpawnContextServer", command_line, - options_with_tmp); -} - -} // namespace - -class ContextProviderImplLegacyTest : public base::MultiProcessTest { - public: - ContextProviderImplLegacyTest() - : context_provider_(std::make_unique<ContextProviderImpl>()) { - fuchsia::web::ContextProviderPtr fuchsia_context_provider; - legacy_binding_ = - std::make_unique<fidl::Binding<fuchsia::web::ContextProvider>>( - context_provider_.get(), fuchsia_context_provider.NewRequest()); - provider_ = std::make_unique<LegacyContextProviderBridge>( - std::move(fuchsia_context_provider)); - - context_provider_->SetLaunchCallbackForTest( - base::BindRepeating(&LaunchFakeContextProcess)); - bindings_.AddBinding(provider_.get(), provider_ptr_.NewRequest()); - } - - ~ContextProviderImplLegacyTest() override { - provider_ptr_.Unbind(); - base::RunLoop().RunUntilIdle(); - } - - // Check if a Context is responsive by creating a Frame from it and then - // listening for an event. - void CheckContextResponsive( - fidl::InterfacePtr<chromium::web::Context>* context) { - // Call a Context method and wait for it to invoke an observer call. - base::RunLoop run_loop; - context->set_error_handler([&run_loop](zx_status_t status) { - ZX_LOG(ERROR, status) << " Context lost."; - ADD_FAILURE(); - run_loop.Quit(); - }); - - chromium::web::FramePtr frame_ptr; - frame_ptr.set_error_handler([&run_loop](zx_status_t status) { - ZX_LOG(ERROR, status) << " Frame lost."; - ADD_FAILURE(); - run_loop.Quit(); - }); - (*context)->CreateFrame(frame_ptr.NewRequest()); - - // Create a Frame and expect to see a navigation event. - CapturingNavigationEventObserver change_observer(run_loop.QuitClosure()); - fidl::Binding<chromium::web::NavigationEventObserver> - change_observer_binding(&change_observer); - frame_ptr->SetNavigationEventObserver(change_observer_binding.NewBinding()); - run_loop.Run(); - - EXPECT_EQ(change_observer.captured_event().url, kUrl); - EXPECT_EQ(change_observer.captured_event().title, kTitle); - } - - chromium::web::CreateContextParams BuildCreateContextParams() { - fidl::InterfaceHandle<fuchsia::io::Directory> directory; - zx_status_t result = - fdio_service_connect(base::fuchsia::kServiceDirectoryPath, - directory.NewRequest().TakeChannel().release()); - ZX_CHECK(result == ZX_OK, result) << "Failed to open /svc"; - - chromium::web::CreateContextParams output; - output.set_service_directory(std::move(directory)); - return output; - } - - // Checks that the Context channel was dropped. - void CheckContextUnresponsive( - fidl::InterfacePtr<chromium::web::Context>* context) { - base::RunLoop run_loop; - context->set_error_handler([&run_loop](zx_status_t status) { - EXPECT_EQ(status, ZX_ERR_PEER_CLOSED); - run_loop.Quit(); - }); - - chromium::web::FramePtr frame; - (*context)->CreateFrame(frame.NewRequest()); - - // The error handler should be called here. - run_loop.Run(); - } - - protected: - base::MessageLoopForIO message_loop_; - std::unique_ptr<LegacyContextProviderBridge> provider_; - std::unique_ptr<fidl::Binding<fuchsia::web::ContextProvider>> legacy_binding_; - chromium::web::ContextProviderPtr provider_ptr_; - fidl::BindingSet<chromium::web::ContextProvider> bindings_; - - private: - struct CapturingNavigationEventObserver - : public chromium::web::NavigationEventObserver { - public: - explicit CapturingNavigationEventObserver(base::OnceClosure on_change_cb) - : on_change_cb_(std::move(on_change_cb)) {} - ~CapturingNavigationEventObserver() override = default; - - void OnNavigationStateChanged( - chromium::web::NavigationEvent change, - OnNavigationStateChangedCallback callback) override { - captured_event_ = std::move(change); - std::move(on_change_cb_).Run(); - } - - chromium::web::NavigationEvent captured_event() { return captured_event_; } - - private: - base::OnceClosure on_change_cb_; - chromium::web::NavigationEvent captured_event_; - }; - - std::unique_ptr<ContextProviderImpl> context_provider_; - - DISALLOW_COPY_AND_ASSIGN(ContextProviderImplLegacyTest); -}; - -TEST_F(ContextProviderImplLegacyTest, LaunchContext) { - // Connect to a new context process. - fidl::InterfacePtr<chromium::web::Context> context; - chromium::web::CreateContextParams create_params = BuildCreateContextParams(); - provider_ptr_->Create(std::move(create_params), context.NewRequest()); - CheckContextResponsive(&context); -} - -TEST_F(ContextProviderImplLegacyTest, MultipleConcurrentClients) { - // Bind a Provider connection, and create a Context from it. - chromium::web::ContextProviderPtr provider_1_ptr; - bindings_.AddBinding(provider_.get(), provider_1_ptr.NewRequest()); - chromium::web::ContextPtr context_1; - provider_1_ptr->Create(BuildCreateContextParams(), context_1.NewRequest()); - - // Do the same on another Provider connection. - chromium::web::ContextProviderPtr provider_2_ptr; - bindings_.AddBinding(provider_.get(), provider_2_ptr.NewRequest()); - chromium::web::ContextPtr context_2; - provider_2_ptr->Create(BuildCreateContextParams(), context_2.NewRequest()); - - CheckContextResponsive(&context_1); - CheckContextResponsive(&context_2); - - // Ensure that the initial ContextProvider connection is still usable, by - // creating and verifying another Context from it. - chromium::web::ContextPtr context_3; - provider_2_ptr->Create(BuildCreateContextParams(), context_3.NewRequest()); - CheckContextResponsive(&context_3); -} - -TEST_F(ContextProviderImplLegacyTest, WithProfileDir) { - base::ScopedTempDir profile_temp_dir; - - // Connect to a new context process. - fidl::InterfacePtr<chromium::web::Context> context; - chromium::web::CreateContextParams create_params = BuildCreateContextParams(); - - // Setup data dir. - EXPECT_TRUE(profile_temp_dir.CreateUniqueTempDir()); - ASSERT_EQ( - base::WriteFile(profile_temp_dir.GetPath().AppendASCII(kTestDataFileIn), - nullptr, 0), - 0); - - // Pass a handle data dir to the context. - create_params.set_data_directory( - base::fuchsia::OpenDirectory(profile_temp_dir.GetPath())); - - provider_ptr_->Create(std::move(create_params), context.NewRequest()); - - CheckContextResponsive(&context); - - // Verify that the context process can write to the data dir. - EXPECT_TRUE(base::PathExists( - profile_temp_dir.GetPath().AppendASCII(kTestDataFileOut))); -} - -TEST_F(ContextProviderImplLegacyTest, FailsDataDirectoryIsFile) { - base::FilePath temp_file_path; - - // Connect to a new context process. - fidl::InterfacePtr<chromium::web::Context> context; - chromium::web::CreateContextParams create_params = BuildCreateContextParams(); - - // Pass in a handle to a file instead of a directory. - CHECK(base::CreateTemporaryFile(&temp_file_path)); - create_params.set_data_directory( - base::fuchsia::OpenDirectory(temp_file_path)); - - provider_ptr_->Create(std::move(create_params), context.NewRequest()); - - CheckContextUnresponsive(&context); -} - -static bool WaitUntilJobIsEmpty(zx::unowned_job job, zx::duration timeout) { - zx_signals_t observed = 0; - zx_status_t status = - job->wait_one(ZX_JOB_NO_JOBS, zx::deadline_after(timeout), &observed); - ZX_CHECK(status == ZX_OK || status == ZX_ERR_TIMED_OUT, status); - return observed & ZX_JOB_NO_JOBS; -} - -// Regression test for https://crbug.com/927403 (Job leak per-Context). -TEST_F(ContextProviderImplLegacyTest, CleansUpContextJobs) { - // Replace the default job with one that is guaranteed to be empty. - zx::job job; - ASSERT_EQ(base::GetDefaultJob()->duplicate(ZX_RIGHT_SAME_RIGHTS, &job), - ZX_OK); - base::ScopedDefaultJobForTest empty_default_job(std::move(job)); - - // Bind to the ContextProvider. - chromium::web::ContextProviderPtr provider; - bindings_.AddBinding(provider_.get(), provider.NewRequest()); - - // Verify that our current default job is still empty. - ASSERT_TRUE(WaitUntilJobIsEmpty(base::GetDefaultJob(), zx::duration())); - - // Create a Context and verify that it is functional. - chromium::web::ContextPtr context; - provider->Create(BuildCreateContextParams(), context.NewRequest()); - CheckContextResponsive(&context); - - // Verify that there is at least one job under our default job. - ASSERT_FALSE(WaitUntilJobIsEmpty(base::GetDefaultJob(), zx::duration())); - - // Detach from the Context and ContextProvider, and spin the loop to allow - // those to be handled. - context.Unbind(); - provider.Unbind(); - base::RunLoop().RunUntilIdle(); - - // Wait until the default job signals that it no longer contains any child - // jobs; this should occur shortly after the Context process terminates. - EXPECT_TRUE(WaitUntilJobIsEmpty( - base::GetDefaultJob(), - zx::duration(TestTimeouts::action_timeout().InNanoseconds()))); -}
diff --git a/fuchsia/engine/context_provider_impl_unittest.cc b/fuchsia/engine/context_provider_impl_unittest.cc index 40fc284..f03815e 100644 --- a/fuchsia/engine/context_provider_impl_unittest.cc +++ b/fuchsia/engine/context_provider_impl_unittest.cc
@@ -34,7 +34,6 @@ #include "base/test/test_timeouts.h" #include "fuchsia/engine/common.h" #include "fuchsia/engine/fake_context.h" -#include "fuchsia/engine/legacy_context_provider_bridge.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/multiprocess_func_list.h"
diff --git a/fuchsia/engine/context_provider_main.cc b/fuchsia/engine/context_provider_main.cc index 6ecda8c..0d25951 100644 --- a/fuchsia/engine/context_provider_main.cc +++ b/fuchsia/engine/context_provider_main.cc
@@ -11,7 +11,6 @@ #include "base/run_loop.h" #include "fuchsia/base/lifecycle_impl.h" #include "fuchsia/engine/context_provider_impl.h" -#include "fuchsia/engine/legacy_context_provider_bridge.h" int ContextProviderMain() { base::MessageLoopForUI message_loop; @@ -25,10 +24,6 @@ fuchsia::web::ContextProviderPtr fuchsia_context_provider; fidl::Binding<fuchsia::web::ContextProvider> fuchsia_binding( &context_provider, fuchsia_context_provider.NewRequest()); - LegacyContextProviderBridge legacy_context_provider( - std::move(fuchsia_context_provider)); - base::fuchsia::ScopedServiceBinding<chromium::web::ContextProvider> - legacy_binding(directory, &legacy_context_provider); base::RunLoop run_loop; cr_fuchsia::LifecycleImpl lifecycle(directory, run_loop.QuitClosure());
diff --git a/fuchsia/engine/legacy_context_bridge.cc b/fuchsia/engine/legacy_context_bridge.cc deleted file mode 100644 index 5e14c5c0..0000000 --- a/fuchsia/engine/legacy_context_bridge.cc +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2019 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 "fuchsia/engine/legacy_context_bridge.h" - -#include "base/fuchsia/fuchsia_logging.h" -#include "fuchsia/engine/legacy_frame_bridge.h" - -LegacyContextBridge::LegacyContextBridge( - fidl::InterfaceRequest<chromium::web::Context> request, - fuchsia::web::ContextPtr handle) - : binding_(this, std::move(request)), context_(std::move(handle)) { - binding_.set_error_handler([this](zx_status_t status) { - ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status) - << " |binding_| disconnected."; - delete this; - }); - context_.set_error_handler([this](zx_status_t status) { - ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status) - << " |context_| disconnected."; - delete this; - }); -} - -LegacyContextBridge::~LegacyContextBridge() = default; - -void LegacyContextBridge::CreateFrame( - fidl::InterfaceRequest<chromium::web::Frame> frame) { - fuchsia::web::FramePtr fuchsia_frame; - context_->CreateFrame(fuchsia_frame.NewRequest()); - new LegacyFrameBridge(std::move(frame), std::move(fuchsia_frame)); -}
diff --git a/fuchsia/engine/legacy_context_bridge.h b/fuchsia/engine/legacy_context_bridge.h deleted file mode 100644 index de4adfd..0000000 --- a/fuchsia/engine/legacy_context_bridge.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2019 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 FUCHSIA_ENGINE_LEGACY_CONTEXT_BRIDGE_H_ -#define FUCHSIA_ENGINE_LEGACY_CONTEXT_BRIDGE_H_ - -#include <fuchsia/web/cpp/fidl.h> -#include <lib/fidl/cpp/binding.h> - -#include "base/macros.h" -#include "fuchsia/engine/web_engine_export.h" -#include "fuchsia/fidl/chromium/web/cpp/fidl.h" - -// Allows chromium::web::Context clients to connect to fuchsia::web::Context -// instances. -// -// LegacyContextBridge instances are self-managed; they destroy themselves when -// the connection with either end is terminated. -class WEB_ENGINE_EXPORT LegacyContextBridge : public chromium::web::Context { - public: - LegacyContextBridge(fidl::InterfaceRequest<chromium::web::Context> request, - fuchsia::web::ContextPtr handle); - - private: - // Non-public to ensure that only this object may destroy itself. - ~LegacyContextBridge() override; - - // chromium::web::Context implementation. - void CreateFrame(fidl::InterfaceRequest<chromium::web::Frame> frame) override; - - fidl::Binding<chromium::web::Context> binding_; - fuchsia::web::ContextPtr context_; - - DISALLOW_COPY_AND_ASSIGN(LegacyContextBridge); -}; - -#endif // FUCHSIA_ENGINE_LEGACY_CONTEXT_BRIDGE_H_
diff --git a/fuchsia/engine/legacy_context_provider_bridge.cc b/fuchsia/engine/legacy_context_provider_bridge.cc deleted file mode 100644 index 1c65449..0000000 --- a/fuchsia/engine/legacy_context_provider_bridge.cc +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2019 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 "fuchsia/engine/legacy_context_provider_bridge.h" - -#include "base/fuchsia/fuchsia_logging.h" -#include "fuchsia/engine/legacy_context_bridge.h" - -LegacyContextProviderBridge::LegacyContextProviderBridge( - fuchsia::web::ContextProviderPtr handle) - : context_provider_(std::move(handle)) {} - -LegacyContextProviderBridge::~LegacyContextProviderBridge() = default; - -void LegacyContextProviderBridge::Create( - chromium::web::CreateContextParams params, - fidl::InterfaceRequest<chromium::web::Context> context_request) { - fuchsia::web::CreateContextParams fuchsia_params; - if (params.has_service_directory()) { - fuchsia_params.set_service_directory( - std::move(*params.mutable_service_directory())); - } - - if (params.has_data_directory()) { - fuchsia_params.set_data_directory( - std::move(*params.mutable_data_directory())); - } - - fuchsia::web::ContextPtr fuchsia_context; - context_provider_->Create(std::move(fuchsia_params), - fuchsia_context.NewRequest()); - new LegacyContextBridge(std::move(context_request), - std::move(fuchsia_context)); -}
diff --git a/fuchsia/engine/legacy_context_provider_bridge.h b/fuchsia/engine/legacy_context_provider_bridge.h deleted file mode 100644 index d99dfd2..0000000 --- a/fuchsia/engine/legacy_context_provider_bridge.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2019 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 FUCHSIA_ENGINE_LEGACY_CONTEXT_PROVIDER_BRIDGE_H_ -#define FUCHSIA_ENGINE_LEGACY_CONTEXT_PROVIDER_BRIDGE_H_ - -#include <fuchsia/web/cpp/fidl.h> -#include <lib/fidl/cpp/binding_set.h> - -#include "base/macros.h" -#include "fuchsia/engine/web_engine_export.h" -#include "fuchsia/fidl/chromium/web/cpp/fidl.h" - -// Allows chromium::web::ContextProvider clients to connect to -// fuchsia::web::ContextProvider instances. -class WEB_ENGINE_EXPORT LegacyContextProviderBridge - : public chromium::web::ContextProvider { - public: - LegacyContextProviderBridge(fuchsia::web::ContextProviderPtr handle); - ~LegacyContextProviderBridge() override; - - private: - // chromium::web::ContextProvider implementation. - void Create( - chromium::web::CreateContextParams params, - fidl::InterfaceRequest<chromium::web::Context> context_request) override; - - fuchsia::web::ContextProviderPtr context_provider_; - - DISALLOW_COPY_AND_ASSIGN(LegacyContextProviderBridge); -}; - -#endif // FUCHSIA_ENGINE_LEGACY_CONTEXT_PROVIDER_BRIDGE_H_
diff --git a/fuchsia/engine/legacy_frame_bridge.cc b/fuchsia/engine/legacy_frame_bridge.cc deleted file mode 100644 index 1255ab16..0000000 --- a/fuchsia/engine/legacy_frame_bridge.cc +++ /dev/null
@@ -1,164 +0,0 @@ -// Copyright 2019 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 "fuchsia/engine/legacy_frame_bridge.h" - -#include "base/fuchsia/fuchsia_logging.h" -#include "fuchsia/engine/legacy_message_port_bridge.h" -#include "fuchsia/engine/legacy_navigation_controller_bridge.h" -#include "fuchsia/engine/legacy_navigation_event_listener_bridge.h" - -namespace { - -// All the active LegacyFrameBridge instances. Used for testing. -std::set<LegacyFrameBridge*> g_legacy_bridges; - -} // namespace - -LegacyFrameBridge::LegacyFrameBridge( - fidl::InterfaceRequest<chromium::web::Frame> request, - fuchsia::web::FramePtr handle) - : binding_(this, std::move(request)), frame_(std::move(handle)) { - binding_.set_error_handler([this](zx_status_t status) { - ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status) - << " |binding_| disconnected."; - delete this; - }); - frame_.set_error_handler([this](zx_status_t status) { - ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status) - << " |frame_| disconnected."; - delete this; - }); - g_legacy_bridges.insert(this); -} - -// static -fuchsia::web::FramePtr* LegacyFrameBridge::GetFramePtrForTest( - chromium::web::FramePtr* frame_ptr) { - // Find the LegacyFrameBridge whose channel is connected to |frame_ptr| by - // inspecting the related_koids of active LegacyFrameBridges. - zx_info_handle_basic_t handle_info; - zx_status_t status = frame_ptr->channel().get_info( - ZX_INFO_HANDLE_BASIC, &handle_info, sizeof(zx_info_handle_basic_t), - nullptr, nullptr); - ZX_CHECK(status == ZX_OK, status) << "zx_object_get_info"; - zx_handle_t client_handle_koid = handle_info.koid; - - for (LegacyFrameBridge* legacy_frame : g_legacy_bridges) { - status = legacy_frame->binding_.channel().get_info( - ZX_INFO_HANDLE_BASIC, &handle_info, sizeof(zx_info_handle_basic_t), - nullptr, nullptr); - ZX_CHECK(status == ZX_OK, status) << "zx_object_get_info"; - - if (client_handle_koid == handle_info.related_koid) - return &legacy_frame->frame_; - } - - return nullptr; -} - -LegacyFrameBridge::~LegacyFrameBridge() { - g_legacy_bridges.erase(this); -} - -void LegacyFrameBridge::CreateView(fuchsia::ui::views::ViewToken view_token) { - frame_->CreateView(std::move(view_token)); -} - -void LegacyFrameBridge::CreateView2( - zx::eventpair view_token_value, - fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> incoming_services, - fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> outgoing_services) { - fuchsia::ui::views::ViewToken view_token; - view_token.value = std::move(view_token_value); - CreateView(std::move(view_token)); -} - -void LegacyFrameBridge::GetNavigationController( - fidl::InterfaceRequest<chromium::web::NavigationController> controller) { - fuchsia::web::NavigationControllerPtr fuchsia_controller; - frame_->GetNavigationController(fuchsia_controller.NewRequest()); - new LegacyNavigationControllerBridge(std::move(controller), - std::move(fuchsia_controller)); -} - -void LegacyFrameBridge::ExecuteJavaScript(std::vector<std::string> origins, - fuchsia::mem::Buffer script, - chromium::web::ExecuteMode mode, - ExecuteJavaScriptCallback callback) { - if (mode == chromium::web::ExecuteMode::ON_PAGE_LOAD) { - AddJavaScriptBindings(next_transitional_bindings_id_++, std::move(origins), - std::move(script), std::move(callback)); - return; - } else if (mode != chromium::web::ExecuteMode::IMMEDIATE_ONCE) { - // Unknown mode, ignored. - callback(false); - return; - } - - frame_->ExecuteJavaScriptNoResult( - std::move(origins), std::move(script), - [callback = std::move(callback)]( - fuchsia::web::Frame_ExecuteJavaScriptNoResult_Result result) { - callback(result.is_response()); - }); -} - -void LegacyFrameBridge::AddJavaScriptBindings( - uint64_t id, - std::vector<std::string> origins, - fuchsia::mem::Buffer script, - AddJavaScriptBindingsCallback callback) { - frame_->AddBeforeLoadJavaScript( - id, std::move(origins), std::move(script), - [callback = std::move(callback)]( - fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { - callback(result.is_response()); - }); -} - -void LegacyFrameBridge::RemoveJavaScriptBindings( - uint64_t id, - RemoveJavaScriptBindingsCallback callback) { - frame_->RemoveBeforeLoadJavaScript(id); - callback(true); -} - -void LegacyFrameBridge::PostMessage( - chromium::web::WebMessage message, - std::string target_origin, - chromium::web::Frame::PostMessageCallback callback) { - base::Optional<fuchsia::web::WebMessage> converted = - cr_fuchsia::LegacyMessagePortBridge::ConvertFromLegacyWebMessage(message); - if (!converted) { - callback(false); - return; - } - frame_->PostMessage(std::move(target_origin), std::move(converted.value()), - [callback = std::move(callback)]( - fuchsia::web::Frame_PostMessage_Result result) { - callback(result.is_response()); - }); -} - -void LegacyFrameBridge::SetNavigationEventObserver( - fidl::InterfaceHandle<chromium::web::NavigationEventObserver> observer) { - if (observer) { - fuchsia::web::NavigationEventListenerPtr listener; - new LegacyNavigationEventListenerBridge(listener.NewRequest(), - observer.Bind()); - frame_->SetNavigationEventListener(std::move(listener)); - } else { - frame_->SetNavigationEventListener(nullptr); - } -} - -void LegacyFrameBridge::SetJavaScriptLogLevel(chromium::web::LogLevel level) { - frame_->SetJavaScriptLogLevel( - static_cast<fuchsia::web::ConsoleLogLevel>(level)); -} - -void LegacyFrameBridge::SetEnableInput(bool enable_input) { - frame_->SetEnableInput(enable_input); -}
diff --git a/fuchsia/engine/legacy_frame_bridge.h b/fuchsia/engine/legacy_frame_bridge.h deleted file mode 100644 index eb134c3..0000000 --- a/fuchsia/engine/legacy_frame_bridge.h +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2019 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 FUCHSIA_ENGINE_LEGACY_FRAME_BRIDGE_H_ -#define FUCHSIA_ENGINE_LEGACY_FRAME_BRIDGE_H_ - -#include <fuchsia/web/cpp/fidl.h> -#include <lib/fidl/cpp/binding.h> -#include <set> - -#include "base/containers/unique_ptr_adapters.h" -#include "base/macros.h" -#include "fuchsia/engine/web_engine_export.h" -#include "fuchsia/fidl/chromium/web/cpp/fidl.h" - -// Allows chromium::web::Frame clients to connect to fuchsia::web::Frame -// instances. -// -// LegacyFrameBridge instances are self-managed; they destroy themselves -// when the connection with either end is terminated. -class WEB_ENGINE_EXPORT LegacyFrameBridge : public chromium::web::Frame { - public: - LegacyFrameBridge(fidl::InterfaceRequest<chromium::web::Frame> request, - fuchsia::web::FramePtr handle); - - static fuchsia::web::FramePtr* GetFramePtrForTest( - chromium::web::FramePtr* frame_ptr); - - private: - // Non-public to ensure that only this object may destroy itself. - ~LegacyFrameBridge() override; - - // chromium::web::Frame implementation. - void CreateView(fuchsia::ui::views::ViewToken view_token) override; - void CreateView2( - zx::eventpair view_token, - fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> incoming_services, - fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> outgoing_services) - override; - void GetNavigationController( - fidl::InterfaceRequest<chromium::web::NavigationController> controller) - override; - void ExecuteJavaScript(std::vector<std::string> origins, - fuchsia::mem::Buffer script, - chromium::web::ExecuteMode mode, - ExecuteJavaScriptCallback callback) override; - void AddJavaScriptBindings(uint64_t id, - std::vector<std::string> origins, - fuchsia::mem::Buffer script, - AddJavaScriptBindingsCallback callback) override; - void RemoveJavaScriptBindings( - uint64_t id, - RemoveJavaScriptBindingsCallback callback) override; - void PostMessage(chromium::web::WebMessage message, - std::string target_origin, - PostMessageCallback callback) override; - void SetNavigationEventObserver( - fidl::InterfaceHandle<chromium::web::NavigationEventObserver> observer) - override; - void SetJavaScriptLogLevel(chromium::web::LogLevel level) override; - void SetEnableInput(bool enable_input) override; - - fidl::Binding<chromium::web::Frame> binding_; - fuchsia::web::FramePtr frame_; - uint64_t next_transitional_bindings_id_ = 0x80000000; - - DISALLOW_COPY_AND_ASSIGN(LegacyFrameBridge); -}; - -#endif // FUCHSIA_ENGINE_LEGACY_FRAME_BRIDGE_H_
diff --git a/fuchsia/engine/legacy_navigation_controller_bridge.cc b/fuchsia/engine/legacy_navigation_controller_bridge.cc deleted file mode 100644 index f0b852587..0000000 --- a/fuchsia/engine/legacy_navigation_controller_bridge.cc +++ /dev/null
@@ -1,121 +0,0 @@ -// Copyright 2019 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 "fuchsia/engine/legacy_navigation_controller_bridge.h" - -#include "base/fuchsia/fuchsia_logging.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "fuchsia/engine/legacy_frame_bridge.h" - -namespace { - -std::unique_ptr<chromium::web::NavigationEntry> ConvertToLegacyNavigationEntry( - const fuchsia::web::NavigationState& entry) { - chromium::web::NavigationEntry converted; - bool is_changed = false; - - if (entry.has_title()) { - converted.title = entry.title(); - is_changed = true; - } - if (entry.has_url()) { - converted.url = entry.url(); - is_changed = true; - } - if (entry.has_page_type()) { - converted.is_error = entry.page_type() == fuchsia::web::PageType::ERROR; - is_changed = true; - } - - return is_changed - ? std::make_unique<chromium::web::NavigationEntry>(converted) - : nullptr; -} - -std::vector<uint8_t> StringToUnsignedVector(base::StringPiece str) { - const uint8_t* raw_data = reinterpret_cast<const uint8_t*>(str.data()); - return std::vector<uint8_t>(raw_data, raw_data + str.length()); -} - -} // namespace - -LegacyNavigationControllerBridge::LegacyNavigationControllerBridge( - fidl::InterfaceRequest<chromium::web::NavigationController> request, - fuchsia::web::NavigationControllerPtr handle) - : binding_(this, std::move(request)), - navigation_controller_(std::move(handle)) { - binding_.set_error_handler([this](zx_status_t status) { - ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status) - << " |binding_| disconnected."; - delete this; - }); - navigation_controller_.set_error_handler([this](zx_status_t status) { - ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status) - << " |navigation_controller_| disconnected."; - delete this; - }); -} - -LegacyNavigationControllerBridge::~LegacyNavigationControllerBridge() = default; - -void LegacyNavigationControllerBridge::LoadUrl( - std::string url, - chromium::web::LoadUrlParams params) { - fuchsia::web::LoadUrlParams converted; - if (params.has_type()) - converted.set_type(static_cast<fuchsia::web::LoadUrlReason>(params.type())); - if (params.has_referrer_url()) - converted.set_referrer_url(std::move(*params.mutable_referrer_url())); - if (params.has_was_user_activated()) - converted.set_was_user_activated(params.was_user_activated()); - if (params.has_headers()) { - std::vector<fuchsia::net::http::Header> headers; - headers.reserve(params.headers().size()); - for (const auto& header : params.headers()) { - base::StringPiece full_header( - reinterpret_cast<const char*>(header.data())); - std::vector<std::string> values = base::SplitString( - full_header, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - if (values.size() != 2) { - // Badly formed header. Ignore. - continue; - } - fuchsia::net::http::Header http_header; - http_header.name = StringToUnsignedVector(values[0]); - http_header.value = StringToUnsignedVector(values[1]); - headers.emplace_back(http_header); - } - converted.set_headers(std::move(headers)); - } - - navigation_controller_->LoadUrl( - std::move(url), std::move(converted), - [](fuchsia::web::NavigationController_LoadUrl_Result) {}); -} - -void LegacyNavigationControllerBridge::GoBack() { - navigation_controller_->GoBack(); -} - -void LegacyNavigationControllerBridge::GoForward() { - navigation_controller_->GoForward(); -} - -void LegacyNavigationControllerBridge::Stop() { - navigation_controller_->Stop(); -} - -void LegacyNavigationControllerBridge::Reload(chromium::web::ReloadType type) { - navigation_controller_->Reload(static_cast<fuchsia::web::ReloadType>(type)); -} - -void LegacyNavigationControllerBridge::GetVisibleEntry( - GetVisibleEntryCallback callback) { - navigation_controller_->GetVisibleEntry( - [callback = std::move(callback)]( - fuchsia::web::NavigationState navigation_entry) { - callback(ConvertToLegacyNavigationEntry(navigation_entry)); - }); -}
diff --git a/fuchsia/engine/legacy_navigation_controller_bridge.h b/fuchsia/engine/legacy_navigation_controller_bridge.h deleted file mode 100644 index f5f3e55..0000000 --- a/fuchsia/engine/legacy_navigation_controller_bridge.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2019 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 FUCHSIA_ENGINE_LEGACY_NAVIGATION_CONTROLLER_BRIDGE_H_ -#define FUCHSIA_ENGINE_LEGACY_NAVIGATION_CONTROLLER_BRIDGE_H_ - -#include <fuchsia/web/cpp/fidl.h> -#include <lib/fidl/cpp/binding.h> -#include <string> - -#include "base/macros.h" -#include "fuchsia/fidl/chromium/web/cpp/fidl.h" - -// Allows chromium::web::gNavigationControllerePort clients to connect to -// fuchsia::web::NavigationController instances. -// -// LegacyNavigationControllerBridge instances are self-managed; they destroy -// themselves when the connection with either end is terminated. -class LegacyNavigationControllerBridge - : public chromium::web::NavigationController { - public: - LegacyNavigationControllerBridge( - fidl::InterfaceRequest<chromium::web::NavigationController> request, - fuchsia::web::NavigationControllerPtr handle); - - private: - // Non-public to ensure that only this object may destroy itself. - ~LegacyNavigationControllerBridge() override; - - // chromium::web::NavigationController implementation. - void LoadUrl(std::string url, chromium::web::LoadUrlParams params) override; - void GoBack() override; - void GoForward() override; - void Stop() override; - void Reload(chromium::web::ReloadType type) override; - void GetVisibleEntry(GetVisibleEntryCallback callback) override; - - fidl::Binding<chromium::web::NavigationController> binding_; - fuchsia::web::NavigationControllerPtr navigation_controller_; - - DISALLOW_COPY_AND_ASSIGN(LegacyNavigationControllerBridge); -}; - -#endif // FUCHSIA_ENGINE_LEGACY_NAVIGATION_CONTROLLER_BRIDGE_H_
diff --git a/fuchsia/engine/legacy_navigation_event_listener_bridge.cc b/fuchsia/engine/legacy_navigation_event_listener_bridge.cc deleted file mode 100644 index fab5357..0000000 --- a/fuchsia/engine/legacy_navigation_event_listener_bridge.cc +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2019 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 "fuchsia/engine/legacy_navigation_event_listener_bridge.h" - -#include "base/fuchsia/fuchsia_logging.h" - -namespace { - -chromium::web::NavigationEvent ConvertToLegacyNavigationEvent( - const fuchsia::web::NavigationState& entry) { - chromium::web::NavigationEvent converted; - - if (entry.has_title()) - converted.title = entry.title(); - if (entry.has_url()) - converted.url = entry.url(); - if (entry.has_page_type()) - converted.is_error = entry.page_type() == fuchsia::web::PageType::ERROR; - - return converted; -} - -} // namespace - -LegacyNavigationEventListenerBridge::LegacyNavigationEventListenerBridge( - fidl::InterfaceRequest<fuchsia::web::NavigationEventListener> request, - chromium::web::NavigationEventObserverPtr handle) - : binding_(this, std::move(request)), observer_(std::move(handle)) { - binding_.set_error_handler([this](zx_status_t status) { - ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status) - << " |binding_| disconnected."; - delete this; - }); - observer_.set_error_handler([this](zx_status_t status) { - ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status) - << " |observer_| disconnected."; - delete this; - }); -} - -LegacyNavigationEventListenerBridge::~LegacyNavigationEventListenerBridge() = - default; - -void LegacyNavigationEventListenerBridge::OnNavigationStateChanged( - fuchsia::web::NavigationState change, - OnNavigationStateChangedCallback callback) { - observer_->OnNavigationStateChanged(ConvertToLegacyNavigationEvent(change), - std::move(callback)); - // [callback = std::move(callback)]() { callback(); }); -}
diff --git a/fuchsia/engine/legacy_navigation_event_listener_bridge.h b/fuchsia/engine/legacy_navigation_event_listener_bridge.h deleted file mode 100644 index b831b070..0000000 --- a/fuchsia/engine/legacy_navigation_event_listener_bridge.h +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2019 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 FUCHSIA_ENGINE_LEGACY_NAVIGATION_EVENT_LISTENER_BRIDGE_H_ -#define FUCHSIA_ENGINE_LEGACY_NAVIGATION_EVENT_LISTENER_BRIDGE_H_ - -#include <fuchsia/web/cpp/fidl.h> -#include <lib/fidl/cpp/binding.h> - -#include "base/macros.h" -#include "fuchsia/fidl/chromium/web/cpp/fidl.h" - -// Allows fuchsia::web::NavigationEventListener clients to connect to -// chromium::web::NavigationEventObserver instances. -// -// LegacyNavigationEventListenerBridge instances are self-managed; they destroy -// themselves when the connection with either end is terminated. -class LegacyNavigationEventListenerBridge - : public fuchsia::web::NavigationEventListener { - public: - LegacyNavigationEventListenerBridge( - fidl::InterfaceRequest<fuchsia::web::NavigationEventListener> request, - chromium::web::NavigationEventObserverPtr handle); - - private: - // Non-public to ensure that only this object may destroy itself. - ~LegacyNavigationEventListenerBridge() override; - - // fuchsia::web::NavigationEventListener implementation. - void OnNavigationStateChanged( - fuchsia::web::NavigationState change, - OnNavigationStateChangedCallback callback) override; - - fidl::Binding<fuchsia::web::NavigationEventListener> binding_; - chromium::web::NavigationEventObserverPtr observer_; - - DISALLOW_COPY_AND_ASSIGN(LegacyNavigationEventListenerBridge); -}; - -#endif // FUCHSIA_ENGINE_LEGACY_NAVIGATION_EVENT_LISTENER_BRIDGE_H_
diff --git a/fuchsia/engine/test/web_engine_browser_test.cc b/fuchsia/engine/test/web_engine_browser_test.cc index c2594589..246945f 100644 --- a/fuchsia/engine/test/web_engine_browser_test.cc +++ b/fuchsia/engine/test/web_engine_browser_test.cc
@@ -10,7 +10,6 @@ #include "fuchsia/engine/browser/web_engine_browser_context.h" #include "fuchsia/engine/browser/web_engine_browser_main_parts.h" #include "fuchsia/engine/browser/web_engine_content_browser_client.h" -#include "fuchsia/engine/legacy_frame_bridge.h" #include "fuchsia/engine/web_engine_main_delegate.h" #include "net/test/embedded_test_server/default_handlers.h" @@ -61,14 +60,6 @@ return frame; } -chromium::web::FramePtr WebEngineBrowserTest::CreateLegacyFrame( - fuchsia::web::NavigationEventListener* listener) { - fuchsia::web::FramePtr fuchsia_frame = CreateFrame(listener); - chromium::web::FramePtr frame; - new LegacyFrameBridge(frame.NewRequest(), std::move(fuchsia_frame)); - return frame; -} - // static void WebEngineBrowserTest::SetContextClientChannel(zx::channel channel) { DCHECK(channel);
diff --git a/fuchsia/engine/test/web_engine_browser_test.h b/fuchsia/engine/test/web_engine_browser_test.h index c3ed835b..6b192da 100644 --- a/fuchsia/engine/test/web_engine_browser_test.h +++ b/fuchsia/engine/test/web_engine_browser_test.h
@@ -13,7 +13,6 @@ #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_base.h" #include "fuchsia/engine/browser/context_impl.h" -#include "fuchsia/fidl/chromium/web/cpp/fidl.h" namespace cr_fuchsia { @@ -32,8 +31,6 @@ // |listener|: If set, specifies the navigation listener for the Frame. fuchsia::web::FramePtr CreateFrame( fuchsia::web::NavigationEventListener* listener); - chromium::web::FramePtr CreateLegacyFrame( - fuchsia::web::NavigationEventListener* listener); // Gets the client object for the Context service. fuchsia::web::ContextPtr& context() { return context_; }
diff --git a/fuchsia/runners/BUILD.gn b/fuchsia/runners/BUILD.gn index b827ee8..82bbe3b 100644 --- a/fuchsia/runners/BUILD.gn +++ b/fuchsia/runners/BUILD.gn
@@ -52,7 +52,6 @@ ] deps = [ "//base", - "//fuchsia:web_fidl", "//fuchsia/base", "//fuchsia/base:modular", "//fuchsia/engine:legacy_message_port_bridge", @@ -62,7 +61,6 @@ public_deps = [ ":common", "//fuchsia:cast_fidl", - "//fuchsia:web_fidl", "//third_party/fuchsia-sdk/sdk:web", ] visibility = [ ":*" ]
diff --git a/fuchsia/runners/cast/cast_runner_integration_test.cc b/fuchsia/runners/cast/cast_runner_integration_test.cc index 3a2fc4cd..e365904d 100644 --- a/fuchsia/runners/cast/cast_runner_integration_test.cc +++ b/fuchsia/runners/cast/cast_runner_integration_test.cc
@@ -19,7 +19,6 @@ #include "fuchsia/base/fit_adapter.h" #include "fuchsia/base/mem_buffer_util.h" #include "fuchsia/base/result_receiver.h" -#include "fuchsia/fidl/chromium/web/cpp/fidl.h" #include "fuchsia/runners/cast/cast_runner.h" #include "fuchsia/runners/cast/fake_application_config_manager.h" #include "fuchsia/runners/common/web_component.h"
diff --git a/gpu/command_buffer/service/external_vk_image_backing.cc b/gpu/command_buffer/service/external_vk_image_backing.cc index 0026293..55eaadb6 100644 --- a/gpu/command_buffer/service/external_vk_image_backing.cc +++ b/gpu/command_buffer/service/external_vk_image_backing.cc
@@ -121,6 +121,9 @@ ->GetVulkanQueue()); vkDestroyImage(device(), image_, nullptr); vkFreeMemory(device(), memory_, nullptr); + + if (texture_) + texture_->RemoveLightweightRef(have_context()); } bool ExternalVkImageBacking::ProduceLegacyMailbox( @@ -153,49 +156,52 @@ gl::GLApi* api = gl::g_current_gl_context; - constexpr GLenum target = GL_TEXTURE_2D; - constexpr GLenum get_target = GL_TEXTURE_BINDING_2D; - GLuint internal_format = viz::TextureStorageFormat(format()); + if (!texture_) { + constexpr GLenum target = GL_TEXTURE_2D; + constexpr GLenum get_target = GL_TEXTURE_BINDING_2D; + GLuint internal_format = viz::TextureStorageFormat(format()); - GLuint memory_object; - api->glCreateMemoryObjectsEXTFn(1, &memory_object); - api->glImportMemoryFdEXTFn(memory_object, memory_size_, - GL_HANDLE_TYPE_OPAQUE_FD_EXT, memory_fd); - GLuint texture_service_id; - api->glGenTexturesFn(1, &texture_service_id); - GLint old_texture_binding = 0; - api->glGetIntegervFn(get_target, &old_texture_binding); - api->glBindTextureFn(target, texture_service_id); - api->glTexParameteriFn(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - api->glTexParameteriFn(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - api->glTexParameteriFn(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - api->glTexParameteriFn(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - api->glTexStorageMem2DEXTFn(GL_TEXTURE_2D, 1, internal_format, size().width(), - size().height(), memory_object, 0); + GLuint memory_object; + api->glCreateMemoryObjectsEXTFn(1, &memory_object); + api->glImportMemoryFdEXTFn(memory_object, memory_size_, + GL_HANDLE_TYPE_OPAQUE_FD_EXT, memory_fd); + GLuint texture_service_id; + api->glGenTexturesFn(1, &texture_service_id); - gles2::Texture* texture = new gles2::Texture(texture_service_id); - texture->SetLightweightRef(); - texture->SetTarget(target, 1); - texture->sampler_state_.min_filter = GL_LINEAR; - texture->sampler_state_.mag_filter = GL_LINEAR; - texture->sampler_state_.wrap_t = GL_CLAMP_TO_EDGE; - texture->sampler_state_.wrap_s = GL_CLAMP_TO_EDGE; - // If the backing is already cleared, no need to clear it again. - gfx::Rect cleared_rect; - if (is_cleared_) - cleared_rect = gfx::Rect(size()); + GLint old_texture_binding = 0; + api->glGetIntegervFn(get_target, &old_texture_binding); + api->glBindTextureFn(target, texture_service_id); + api->glTexParameteriFn(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + api->glTexParameteriFn(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + api->glTexParameteriFn(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + api->glTexParameteriFn(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + api->glTexStorageMem2DEXTFn(GL_TEXTURE_2D, 1, internal_format, + size().width(), size().height(), memory_object, + 0); - GLenum gl_format = viz::GLDataFormat(format()); - GLenum gl_type = viz::GLDataType(format()); - texture->SetLevelInfo(target, 0, internal_format, size().width(), - size().height(), 1, 0, gl_format, gl_type, - cleared_rect); - texture->SetImmutable(true); + texture_ = new gles2::Texture(texture_service_id); + texture_->SetLightweightRef(); + texture_->SetTarget(target, 1); + texture_->sampler_state_.min_filter = GL_LINEAR; + texture_->sampler_state_.mag_filter = GL_LINEAR; + texture_->sampler_state_.wrap_t = GL_CLAMP_TO_EDGE; + texture_->sampler_state_.wrap_s = GL_CLAMP_TO_EDGE; + // If the backing is already cleared, no need to clear it again. + gfx::Rect cleared_rect; + if (is_cleared_) + cleared_rect = gfx::Rect(size()); - api->glBindTextureFn(target, old_texture_binding); + GLenum gl_format = viz::GLDataFormat(format()); + GLenum gl_type = viz::GLDataType(format()); + texture_->SetLevelInfo(target, 0, internal_format, size().width(), + size().height(), 1, 0, gl_format, gl_type, + cleared_rect); + texture_->SetImmutable(true); + api->glBindTextureFn(target, old_texture_binding); + } return std::make_unique<ExternalVkImageGlRepresentation>( - manager, this, tracker, texture, texture_service_id); + manager, this, tracker, texture_, texture_->service_id()); #else // !defined(OS_LINUX) && !defined(OS_FUCHSIA) #error Unsupported OS #endif
diff --git a/gpu/command_buffer/service/external_vk_image_backing.h b/gpu/command_buffer/service/external_vk_image_backing.h index d22432c..173846f 100644 --- a/gpu/command_buffer/service/external_vk_image_backing.h +++ b/gpu/command_buffer/service/external_vk_image_backing.h
@@ -85,6 +85,7 @@ VkFormat vk_format_; bool is_write_in_progress_ = false; uint32_t reads_in_progress_ = 0; + gles2::Texture* texture_ = nullptr; DISALLOW_COPY_AND_ASSIGN(ExternalVkImageBacking); };
diff --git a/gpu/command_buffer/service/external_vk_image_gl_representation.cc b/gpu/command_buffer/service/external_vk_image_gl_representation.cc index d1f741d9..e46de30 100644 --- a/gpu/command_buffer/service/external_vk_image_gl_representation.cc +++ b/gpu/command_buffer/service/external_vk_image_gl_representation.cc
@@ -27,9 +27,7 @@ texture_(texture), texture_service_id_(texture_service_id) {} -ExternalVkImageGlRepresentation::~ExternalVkImageGlRepresentation() { - texture_->RemoveLightweightRef(has_context()); -} +ExternalVkImageGlRepresentation::~ExternalVkImageGlRepresentation() {} gles2::Texture* ExternalVkImageGlRepresentation::GetTexture() { return texture_;
diff --git a/gpu/vulkan/BUILD.gn b/gpu/vulkan/BUILD.gn index fd61fb4..5a440b9d 100644 --- a/gpu/vulkan/BUILD.gn +++ b/gpu/vulkan/BUILD.gn
@@ -93,19 +93,35 @@ } } + jumbo_static_library("test_support") { + testonly = true + sources = [ + "tests/native_window.h", + ] + deps = [ + "//ui/gfx", + "//ui/gfx:native_widget_types", + ] + if (use_x11) { + sources += [ "tests/native_window_x11.cc" ] + deps += [ "//ui/gfx/x" ] + configs += [ "//build/config/linux:x11" ] + } + } + # TODO(cblume): These tests should run on each platform -- crbug.com/858614 if (use_x11) { test("vulkan_tests") { sources = [ "tests/basic_vulkan_test.cc", "tests/basic_vulkan_test.h", - "tests/native_window.h", "tests/vulkan_test.cc", "tests/vulkan_tests_main.cc", "vulkan_fence_helper_unittest.cc", ] deps = [ + ":test_support", "//base:base", "//base/test:test_support", "//components/viz/common:vulkan_context_provider", @@ -116,12 +132,6 @@ "//ui/gfx:native_widget_types", "//ui/gfx/geometry", ] - - if (use_x11) { - sources += [ "tests/native_window_x11.cc" ] - deps += [ "//ui/gfx/x" ] - configs += [ "//build/config/linux:x11" ] - } } } }
diff --git a/gpu/vulkan/fuchsia/vulkan_fuchsia_ext.h b/gpu/vulkan/fuchsia/vulkan_fuchsia_ext.h index cff3d15..b5c7d82d 100644 --- a/gpu/vulkan/fuchsia/vulkan_fuchsia_ext.h +++ b/gpu/vulkan/fuchsia/vulkan_fuchsia_ext.h
@@ -30,6 +30,18 @@ const VkStructureType VK_STRUCTURE_TYPE_TEMP_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA = static_cast<VkStructureType>(1001006001); +const VkStructureType VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA = + static_cast<VkStructureType>(1001004000); +const VkStructureType VK_STRUCTURE_TYPE_FUCHSIA_IMAGE_FORMAT_FUCHSIA = + static_cast<VkStructureType>(1001004001); +const VkStructureType + VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA = + static_cast<VkStructureType>(1001004004); +const VkStructureType + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA = + static_cast<VkStructureType>(1001004005); +const VkStructureType VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA = + static_cast<VkStructureType>(1001004006); const VkExternalMemoryHandleTypeFlagBits VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA = @@ -39,6 +51,9 @@ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA = static_cast<VkExternalSemaphoreHandleTypeFlagBits>(0x00100000); +const VkObjectType VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA = + static_cast<VkObjectType>(1001004002); + #define VK_FUCHSIA_external_memory 1 #define VK_FUCHSIA_EXTERNAL_MEMORY_SPEC_VERSION 1 #define VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME "VK_FUCHSIA_external_memory" @@ -128,6 +143,88 @@ zx_handle_t* pZirconHandle); #endif +#define VK_FUCHSIA_buffer_collection 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferCollectionFUCHSIA) + +#define VK_FUCHSIA_BUFFER_COLLECTION_SPEC_VERSION 1 +#define VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME \ + "VK_FUCHSIA_buffer_collection" + +typedef struct VkBufferCollectionCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + zx_handle_t collectionToken; +} VkBufferCollectionCreateInfoFUCHSIA; + +typedef struct VkFuchsiaImageFormatFUCHSIA { + VkStructureType sType; + const void* pNext; + const void* imageFormat; + uint32_t imageFormatSize; +} VkFuchsiaImageFormatFUCHSIA; + +typedef struct VkImportMemoryBufferCollectionFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkImportMemoryBufferCollectionFUCHSIA; + +typedef struct VkBufferCollectionImageCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkBufferCollectionImageCreateInfoFUCHSIA; + +typedef struct VkBufferCollectionPropertiesFUCHSIA { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; + uint32_t count; +} VkBufferCollectionPropertiesFUCHSIA; + +typedef VkResult(VKAPI_PTR* PFN_vkCreateBufferCollectionFUCHSIA)( + VkDevice device, + const VkBufferCollectionCreateInfoFUCHSIA* pImportInfo, + const VkAllocationCallbacks* pAllocator, + VkBufferCollectionFUCHSIA* pCollection); +typedef VkResult(VKAPI_PTR* PFN_vkSetBufferCollectionConstraintsFUCHSIA)( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkImageCreateInfo* pImageInfo); +typedef void(VKAPI_PTR* PFN_vkDestroyBufferCollectionFUCHSIA)( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkAllocationCallbacks* pAllocator); +typedef VkResult(VKAPI_PTR* PFN_vkGetBufferCollectionPropertiesFUCHSIA)( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + VkBufferCollectionPropertiesFUCHSIA* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferCollectionFUCHSIA( + VkDevice device, + const VkBufferCollectionCreateInfoFUCHSIA* pImportInfo, + const VkAllocationCallbacks* pAllocator, + VkBufferCollectionFUCHSIA* pCollection); + +VKAPI_ATTR VkResult VKAPI_CALL +vkSetBufferCollectionConstraintsFUCHSIA(VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkImageCreateInfo* pImageInfo); + +VKAPI_ATTR void VKAPI_CALL +vkDestroyBufferCollectionFUCHSIA(VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetBufferCollectionPropertiesFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + VkBufferCollectionPropertiesFUCHSIA* pProperties); +#endif + #ifdef __cplusplus } #endif
diff --git a/gpu/vulkan/generate_bindings.py b/gpu/vulkan/generate_bindings.py index 620516c1..278fd0c 100755 --- a/gpu/vulkan/generate_bindings.py +++ b/gpu/vulkan/generate_bindings.py
@@ -95,6 +95,10 @@ VULKAN_DEVICE_FUNCTIONS_FUCHSIA = [ { 'name': 'vkImportSemaphoreZirconHandleFUCHSIA' }, { 'name': 'vkGetSemaphoreZirconHandleFUCHSIA' }, +{ 'name': 'vkCreateBufferCollectionFUCHSIA' }, +{ 'name': 'vkSetBufferCollectionConstraintsFUCHSIA' }, +{ 'name': 'vkGetBufferCollectionPropertiesFUCHSIA' }, +{ 'name': 'vkDestroyBufferCollectionFUCHSIA' }, ] VULKAN_QUEUE_FUNCTIONS = [
diff --git a/gpu/vulkan/vulkan_function_pointers.cc b/gpu/vulkan/vulkan_function_pointers.cc index 807c56d..ba264c7c 100644 --- a/gpu/vulkan/vulkan_function_pointers.cc +++ b/gpu/vulkan/vulkan_function_pointers.cc
@@ -344,6 +344,32 @@ if (!vkGetSemaphoreZirconHandleFUCHSIAFn) return false; + vkCreateBufferCollectionFUCHSIAFn = + reinterpret_cast<PFN_vkCreateBufferCollectionFUCHSIA>( + vkGetDeviceProcAddrFn(vk_device, "vkCreateBufferCollectionFUCHSIA")); + if (!vkCreateBufferCollectionFUCHSIAFn) + return false; + + vkSetBufferCollectionConstraintsFUCHSIAFn = + reinterpret_cast<PFN_vkSetBufferCollectionConstraintsFUCHSIA>( + vkGetDeviceProcAddrFn(vk_device, + "vkSetBufferCollectionConstraintsFUCHSIA")); + if (!vkSetBufferCollectionConstraintsFUCHSIAFn) + return false; + + vkGetBufferCollectionPropertiesFUCHSIAFn = + reinterpret_cast<PFN_vkGetBufferCollectionPropertiesFUCHSIA>( + vkGetDeviceProcAddrFn(vk_device, + "vkGetBufferCollectionPropertiesFUCHSIA")); + if (!vkGetBufferCollectionPropertiesFUCHSIAFn) + return false; + + vkDestroyBufferCollectionFUCHSIAFn = + reinterpret_cast<PFN_vkDestroyBufferCollectionFUCHSIA>( + vkGetDeviceProcAddrFn(vk_device, "vkDestroyBufferCollectionFUCHSIA")); + if (!vkDestroyBufferCollectionFUCHSIAFn) + return false; + #endif // Queue functions
diff --git a/gpu/vulkan/vulkan_function_pointers.h b/gpu/vulkan/vulkan_function_pointers.h index f9d27454..6789848 100644 --- a/gpu/vulkan/vulkan_function_pointers.h +++ b/gpu/vulkan/vulkan_function_pointers.h
@@ -147,6 +147,14 @@ vkImportSemaphoreZirconHandleFUCHSIAFn = nullptr; PFN_vkGetSemaphoreZirconHandleFUCHSIA vkGetSemaphoreZirconHandleFUCHSIAFn = nullptr; + PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIAFn = + nullptr; + PFN_vkSetBufferCollectionConstraintsFUCHSIA + vkSetBufferCollectionConstraintsFUCHSIAFn = nullptr; + PFN_vkGetBufferCollectionPropertiesFUCHSIA + vkGetBufferCollectionPropertiesFUCHSIAFn = nullptr; + PFN_vkDestroyBufferCollectionFUCHSIA vkDestroyBufferCollectionFUCHSIAFn = + nullptr; #endif // Queue functions @@ -294,6 +302,14 @@ gpu::GetVulkanFunctionPointers()->vkImportSemaphoreZirconHandleFUCHSIAFn #define vkGetSemaphoreZirconHandleFUCHSIA \ gpu::GetVulkanFunctionPointers()->vkGetSemaphoreZirconHandleFUCHSIAFn +#define vkCreateBufferCollectionFUCHSIA \ + gpu::GetVulkanFunctionPointers()->vkCreateBufferCollectionFUCHSIAFn +#define vkSetBufferCollectionConstraintsFUCHSIA \ + gpu::GetVulkanFunctionPointers()->vkSetBufferCollectionConstraintsFUCHSIAFn +#define vkGetBufferCollectionPropertiesFUCHSIA \ + gpu::GetVulkanFunctionPointers()->vkGetBufferCollectionPropertiesFUCHSIAFn +#define vkDestroyBufferCollectionFUCHSIA \ + gpu::GetVulkanFunctionPointers()->vkDestroyBufferCollectionFUCHSIAFn #endif // Queue functions
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm index b639cb6..2c4d01d 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
@@ -257,13 +257,19 @@ // Ignore if: // - explicitly requested via IgnoreRemainderOfCurrentScroll(), // - the scroll is a bounce-up animation at the top, - // - the scroll is attempting to scroll content up when it already fits. + // - the scroll is attempting to scroll content up when it already fits, + // - the scroll is attempting to scroll past the bottom of the content when + // the scroll view is being resized (the rebound scroll animation + // interferes with the frame resizing). bool scrolling_content_down = y_content_offset_ - from_offset < 0.0; bool scrolling_past_top = y_content_offset_ <= -top_inset_; bool content_fits = content_height_ <= scroll_view_height_ - top_inset_; + bool scrolling_past_bottom = + y_content_offset_ + scroll_view_height_ + top_inset_ >= content_height_; if (ignoring_current_scroll_ || (scrolling_past_top && !scrolling_content_down) || - (content_fits && !scrolling_content_down)) { + (content_fits && !scrolling_content_down) || + (resizes_scroll_view_ && scrolling_past_bottom)) { return ScrollAction::kIgnore; }
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model_unittest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_model_unittest.mm index 2dd4b7f..70debaa 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_model_unittest.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model_unittest.mm
@@ -263,3 +263,16 @@ 1.0); EXPECT_TRUE(model().enabled()); } + +// Tests that scrolling past the edge of the page content is ignored when the +// scroll view is being resized. +TEST_F(FullscreenModelTest, IgnoreScrollsPastBottomWhileResizing) { + // Instruct the model to resize the scroll view and scroll to the bottom of + // the page. + model().SetResizesScrollView(true); + model().SetYContentOffset(kContentHeight - kScrollViewHeight); + // Try scrolling with a user gesture such that the toolars are hidden, then + // verify that this scroll is ignored. + SimulateFullscreenUserScrollForProgress(&model(), 0.0); + EXPECT_EQ(observer().progress(), 1.0); +}
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index 6b7f3a08..45cb9df 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -346,6 +346,7 @@ "//components/prefs", "//components/search_engines", "//components/strings", + "//components/ukm/ios:features", "//ios/chrome/app:app_internal", "//ios/chrome/app/strings", "//ios/chrome/app/theme",
diff --git a/ios/chrome/browser/ui/settings/password/BUILD.gn b/ios/chrome/browser/ui/settings/password/BUILD.gn index be9017f..68636df 100644 --- a/ios/chrome/browser/ui/settings/password/BUILD.gn +++ b/ios/chrome/browser/ui/settings/password/BUILD.gn
@@ -114,6 +114,7 @@ "//components/password_manager/core/common", "//components/prefs", "//components/strings", + "//components/ukm/ios:features", "//ios/chrome/app/strings", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/passwords",
diff --git a/ios/chrome/browser/ui/settings/privacy_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/privacy_table_view_controller_unittest.mm index 97d3b55..434d62e2 100644 --- a/ios/chrome/browser/ui/settings/privacy_table_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/privacy_table_view_controller_unittest.mm
@@ -106,8 +106,8 @@ NO, l10n_util::GetNSString(IDS_SETTINGS_CAN_MAKE_PAYMENT_TOGGLE_LABEL), 0, 1); if (base::FeatureList::IsEnabled(kUmaCellular)) { - CheckSwitchCellStateAndTextWithId( - YES, IDS_IOS_OPTIONS_SEARCH_URL_SUGGESTIONS, 0, 2); + CheckSwitchCellStateAndTextWithId(NO, IDS_IOS_OPTIONS_SEND_USAGE_DATA, 0, + 2); } else { CheckDetailItemTextWithIds(IDS_IOS_OPTIONS_SEND_USAGE_DATA, IDS_IOS_OPTIONS_DATA_USAGE_NEVER, 0, 2);
diff --git a/ios/chrome/browser/ui/settings/settings_egtest.mm b/ios/chrome/browser/ui/settings/settings_egtest.mm index dcd18be0..2f65735 100644 --- a/ios/chrome/browser/ui/settings/settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/settings_egtest.mm
@@ -17,6 +17,7 @@ #include "components/prefs/pref_member.h" #include "components/prefs/pref_service.h" #include "components/strings/grit/components_strings.h" +#include "components/ukm/ios/features.h" #import "ios/chrome/app/main_controller.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/content_settings/host_content_settings_map_factory.h" @@ -250,6 +251,15 @@ preferences->SetBoolean(browsing_data::prefs::kDeleteFormData, false); } +- (void)setMetricsReportingEnabled:(BOOL)reportingEnabled { + chrome_test_util::SetBooleanLocalStatePref( + metrics::prefs::kMetricsReportingEnabled, reportingEnabled); + // Breakpad uses dispatch_async to update its state. Wait to get to a + // consistent state. + chrome_test_util::WaitForBreakpadQueue(); +} + +// TODO(crbug.com/953862): Remove as part of feature flag cleanup. - (void)setMetricsReportingEnabled:(BOOL)reportingEnabled wifiOnly:(BOOL)wifiOnly { chrome_test_util::SetBooleanLocalStatePref( @@ -355,14 +365,24 @@ // kMetricsReportingEnabled ON and kMetricsReportingWifiOnly OFF // - Services record data and upload data. - // kMetricsReportingEnabled OFF and kMetricsReportingWifiOnly OFF - [self setMetricsReportingEnabled:NO wifiOnly:NO]; + if (base::FeatureList::IsEnabled(kUmaCellular)) { + // kMetricsReportingEnabled OFF + [self setMetricsReportingEnabled:NO]; + } else { + // kMetricsReportingEnabled OFF and kMetricsReportingWifiOnly OFF + [self setMetricsReportingEnabled:NO wifiOnly:NO]; + } // Service should be completely disabled. // I.e. no recording of data, and no uploading of what's been recorded. [self assertMetricsServiceDisabled:serviceType]; - // kMetricsReportingEnabled OFF and kMetricsReportingWifiOnly ON - [self setMetricsReportingEnabled:NO wifiOnly:YES]; + if (base::FeatureList::IsEnabled(kUmaCellular)) { + // kMetricsReportingEnabled OFF + [self setMetricsReportingEnabled:NO]; + } else { + // kMetricsReportingEnabled OFF and kMetricsReportingWifiOnly ON + [self setMetricsReportingEnabled:NO wifiOnly:YES]; + } // If kMetricsReportingEnabled is OFF, any service should remain completely // disabled, i.e. no uploading even if kMetricsReportingWifiOnly is ON. [self assertMetricsServiceDisabled:serviceType]; @@ -375,25 +395,28 @@ // The values of the prefs and the wwan vs wifi state should be honored by // the services, turning on and off according to the rules laid out above. - // kMetricsReportingEnabled ON and kMetricsReportingWifiOnly ON. - [self setMetricsReportingEnabled:YES wifiOnly:YES]; - // Service should be enabled. - [self assertMetricsServiceEnabled:serviceType]; + if (!base::FeatureList::IsEnabled(kUmaCellular)) { + // kMetricsReportingEnabled ON and kMetricsReportingWifiOnly ON. + [self setMetricsReportingEnabled:YES wifiOnly:YES]; + // Service should be enabled. + [self assertMetricsServiceEnabled:serviceType]; - // Set the network to use a cellular network, which should disable uploading - // when the wifi-only flag is set. - chrome_test_util::SetWWANStateTo(YES); - chrome_test_util::WaitForBreakpadQueue(); - [self assertMetricsServiceEnabledButNotUploading:serviceType]; + // Set the network to use a cellular network, which should disable uploading + // when the wifi-only flag is set. + chrome_test_util::SetWWANStateTo(YES); + chrome_test_util::WaitForBreakpadQueue(); + [self assertMetricsServiceEnabledButNotUploading:serviceType]; - // Turn off cellular network usage, which should enable uploading. - chrome_test_util::SetWWANStateTo(NO); - chrome_test_util::WaitForBreakpadQueue(); - [self assertMetricsServiceEnabled:serviceType]; + // Turn off cellular network usage, which should enable uploading. + chrome_test_util::SetWWANStateTo(NO); + chrome_test_util::WaitForBreakpadQueue(); + [self assertMetricsServiceEnabled:serviceType]; - // kMetricsReportingEnabled ON and kMetricsReportingWifiOnly OFF - [self setMetricsReportingEnabled:YES wifiOnly:NO]; - [self assertMetricsServiceEnabled:serviceType]; + // kMetricsReportingEnabled ON and kMetricsReportingWifiOnly OFF + [self setMetricsReportingEnabled:YES wifiOnly:NO]; + [self assertMetricsServiceEnabled:serviceType]; + } + #else // Development build. Do not allow any recording or uploading of data. // Specifically, the kMetricsReportingEnabled preference is completely @@ -402,15 +425,17 @@ // This tests that no matter the state change, pref or network connection, // services remain disabled. - // kMetricsReportingEnabled ON and kMetricsReportingWifiOnly ON - [self setMetricsReportingEnabled:YES wifiOnly:YES]; - // Service should remain disabled. - [self assertMetricsServiceDisabled:serviceType]; + if (!base::FeatureList::IsEnabled(kUmaCellular)) { + // kMetricsReportingEnabled ON and kMetricsReportingWifiOnly ON + [self setMetricsReportingEnabled:YES wifiOnly:YES]; + // Service should remain disabled. + [self assertMetricsServiceDisabled:serviceType]; - // kMetricsReportingEnabled ON and kMetricsReportingWifiOnly OFF - [self setMetricsReportingEnabled:YES wifiOnly:NO]; - // Service should remain disabled. - [self assertMetricsServiceDisabled:serviceType]; + // kMetricsReportingEnabled ON and kMetricsReportingWifiOnly OFF + [self setMetricsReportingEnabled:YES wifiOnly:NO]; + // Service should remain disabled. + [self assertMetricsServiceDisabled:serviceType]; + } #endif }
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn index 39c2b27..672933b7 100644 --- a/ios/chrome/test/earl_grey/BUILD.gn +++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -248,6 +248,8 @@ "accessibility_util.mm", "chrome_actions.h", "chrome_actions.mm", + "chrome_actions_app_interface.h", + "chrome_actions_app_interface.mm", "chrome_earl_grey.h", "chrome_earl_grey.mm", "chrome_earl_grey_ui.h", @@ -337,6 +339,8 @@ ] testonly = true sources = [ + "chrome_actions_app_interface.h", + "chrome_actions_app_interface.mm", "chrome_error_util.h", "chrome_error_util.mm", "chrome_matchers_app_interface.h", @@ -369,6 +373,7 @@ "//ios/testing/earl_grey:eg_app_support+eg2", "//ios/third_party/earl_grey2:app_framework+link", "//ios/web:eg_app_support+eg2", + "//ios/web/public/test:element_selector", "//ui/base", "//ui/base:test_support", ] @@ -383,6 +388,9 @@ testonly = true sources = [ + "chrome_actions.h", + "chrome_actions.mm", + "chrome_actions_app_interface.h", "chrome_error_util.h", "chrome_error_util.mm", "chrome_matchers.h", @@ -394,6 +402,7 @@ "//base", "//ios/testing/earl_grey:eg_test_support+eg2", "//ios/third_party/earl_grey2:test_lib", + "//ios/web/public/test:element_selector", "//url", ] }
diff --git a/ios/chrome/test/earl_grey/chrome_actions.mm b/ios/chrome/test/earl_grey/chrome_actions.mm index 85b38451..467aa299 100644 --- a/ios/chrome/test/earl_grey/chrome_actions.mm +++ b/ios/chrome/test/earl_grey/chrome_actions.mm
@@ -4,98 +4,45 @@ #import "ios/chrome/test/earl_grey/chrome_actions.h" -#import <EarlGrey/EarlGrey.h> - -#include "ios/web/public/test/element_selector.h" #import "base/mac/foundation_util.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.h" -#import "ios/chrome/browser/ui/settings/cells/settings_switch_cell.h" -#import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h" -#import "ios/chrome/test/app/chrome_test_util.h" -#import "ios/web/public/test/earl_grey/web_view_actions.h" +#import "ios/chrome/test/earl_grey/chrome_actions_app_interface.h" +#import "ios/testing/earl_grey/earl_grey_test.h" +#import "ios/web/public/test/element_selector.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif -namespace { -NSString* kChromeActionsErrorDomain = @"ChromeActionsError"; -} // namespace +#if defined(CHROME_EARL_GREY_2) +GREY_STUB_CLASS_IN_APP_MAIN_QUEUE(ChromeActionsAppInterface) +#endif namespace chrome_test_util { id<GREYAction> LongPressElementForContextMenu(ElementSelector* selector, bool triggers_context_menu) { - return WebViewLongPressElementForContextMenu( - chrome_test_util::GetCurrentWebState(), selector, triggers_context_menu); + return [ChromeActionsAppInterface longPressElement:selector + triggerContextMenu:triggers_context_menu]; } id<GREYAction> TurnSettingsSwitchOn(BOOL on) { - id<GREYMatcher> constraints = grey_not(grey_systemAlertViewShown()); - NSString* action_name = - [NSString stringWithFormat:@"Turn settings switch to %@ state", - on ? @"ON" : @"OFF"]; - return [GREYActionBlock - actionWithName:action_name - constraints:constraints - performBlock:^BOOL(id collection_view_cell, - __strong NSError** error_or_nil) { - SettingsSwitchCell* switch_cell = - base::mac::ObjCCast<SettingsSwitchCell>(collection_view_cell); - if (!switch_cell) { - *error_or_nil = [NSError - errorWithDomain:kChromeActionsErrorDomain - code:0 - userInfo:@{ - NSLocalizedDescriptionKey : @"The element isn't of " - @"the expected type " - @"(SettingsSwitchCell)." - }]; - return NO; - } - UISwitch* switch_view = switch_cell.switchView; - if (switch_view.on != on) { - id<GREYAction> long_press_action = [GREYActions - actionForLongPressWithDuration:kGREYLongPressDefaultDuration]; - return [long_press_action perform:switch_view error:error_or_nil]; - } - return YES; - }]; + return [ChromeActionsAppInterface turnSettingsSwitchOn:on]; } id<GREYAction> TurnSyncSwitchOn(BOOL on) { - id<GREYMatcher> constraints = grey_not(grey_systemAlertViewShown()); - NSString* actionName = [NSString - stringWithFormat:@"Turn sync switch to %@ state", on ? @"ON" : @"OFF"]; - return [GREYActionBlock - actionWithName:actionName - constraints:constraints - performBlock:^BOOL(id sync_switch_cell, - __strong NSError** error_or_nil) { - SettingsSwitchCell* switch_cell = - base::mac::ObjCCastStrict<SettingsSwitchCell>(sync_switch_cell); - UISwitch* switch_view = switch_cell.switchView; - if (switch_view.on != on) { - id<GREYAction> long_press_action = [GREYActions - actionForLongPressWithDuration:kGREYLongPressDefaultDuration]; - return [long_press_action perform:switch_view error:error_or_nil]; - } - return YES; - }]; + return [ChromeActionsAppInterface turnSyncSwitchOn:on]; } id<GREYAction> TapWebElement(const std::string& element_id) { - return web::WebViewTapElement( - chrome_test_util::GetCurrentWebState(), - [ElementSelector selectorWithElementID:element_id]); + return [ChromeActionsAppInterface + tapWebElement:[ElementSelector selectorWithElementID:element_id]]; } id<GREYAction> TapWebElementInFrame(const std::string& element_id, const int frame_index) { - return web::WebViewTapElement( - chrome_test_util::GetCurrentWebState(), - [ElementSelector selectorWithElementID:element_id - inFrameWithIndex:frame_index]); + return [ChromeActionsAppInterface + tapWebElement:[ElementSelector selectorWithElementID:element_id + inFrameWithIndex:frame_index]]; } } // namespace chrome_test_util
diff --git a/ios/chrome/test/earl_grey/chrome_actions_app_interface.h b/ios/chrome/test/earl_grey/chrome_actions_app_interface.h new file mode 100644 index 0000000..40058ed --- /dev/null +++ b/ios/chrome/test/earl_grey/chrome_actions_app_interface.h
@@ -0,0 +1,38 @@ +// Copyright 2019 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 IOS_CHROME_TEST_EARL_GREY_CHROME_ACTIONS_APP_INTERFACE_H_ +#define IOS_CHROME_TEST_EARL_GREY_CHROME_ACTIONS_APP_INTERFACE_H_ + +#import <Foundation/Foundation.h> + +@class ElementSelector; +@protocol GREYAction; + +// Helper class to return actions for EG tests. These helpers are compiled +// into the app binary and can be called from either app or test code. +@interface ChromeActionsAppInterface : NSObject + +// Action to longpress on the element selected by |selector| in the Chrome's +// webview. If |triggers_context_menu| is true, this gesture is expected to +// cause the context menu to appear, and is not expected to trigger events +// in the webview. If |triggers_context_menu| is false, the converse is true. +// This action doesn't fail if the context menu isn't displayed; calling code +// should check for that separately with a matcher. ++ (id<GREYAction>)longPressElement:(ElementSelector*)selector + triggerContextMenu:(BOOL)triggerContextMenu; + +// Action to turn the switch of a SettingsSwitchCell to the given |on| state. ++ (id<GREYAction>)turnSettingsSwitchOn:(BOOL)on; + +// Action to turn the switch of a SyncSwitchCell to the given |on| state. ++ (id<GREYAction>)turnSyncSwitchOn:(BOOL)on; + +// Action to tap a web element described by the given |selector| on the current +// web state. ++ (id<GREYAction>)tapWebElement:(ElementSelector*)selector; + +@end + +#endif // IOS_CHROME_TEST_EARL_GREY_CHROME_ACTIONS_APP_INTERFACE_H_
diff --git a/ios/chrome/test/earl_grey/chrome_actions_app_interface.mm b/ios/chrome/test/earl_grey/chrome_actions_app_interface.mm new file mode 100644 index 0000000..76a6b62 --- /dev/null +++ b/ios/chrome/test/earl_grey/chrome_actions_app_interface.mm
@@ -0,0 +1,103 @@ +// Copyright 2019 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 "ios/chrome/test/earl_grey/chrome_actions_app_interface.h" + +#import "base/mac/foundation_util.h" +#import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.h" +#import "ios/chrome/browser/ui/settings/cells/settings_switch_cell.h" +#import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h" +#import "ios/chrome/test/app/chrome_test_util.h" +#import "ios/testing/earl_grey/earl_grey_app.h" +#import "ios/web/public/test/earl_grey/web_view_actions.h" +#import "ios/web/public/test/element_selector.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +NSString* kChromeActionsErrorDomain = @"ChromeActionsError"; +} // namespace + +@implementation ChromeActionsAppInterface : NSObject + ++ (id<GREYAction>)longPressElement:(ElementSelector*)selector + triggerContextMenu:(BOOL)triggerContextMenu { + return WebViewLongPressElementForContextMenu( + chrome_test_util::GetCurrentWebState(), selector, triggerContextMenu); +} + ++ (id<GREYAction>)turnSettingsSwitchOn:(BOOL)on { + id<GREYMatcher> constraints = grey_not(grey_systemAlertViewShown()); + NSString* actionName = + [NSString stringWithFormat:@"Turn settings switch to %@ state", + on ? @"ON" : @"OFF"]; + return [GREYActionBlock + actionWithName:actionName + constraints:constraints + performBlock:^BOOL(id collectionViewCell, + __strong NSError** errorOrNil) { + // EG2 executes actions on a background thread by default. Since this + // action interacts with UI, kick it over to the main thread. + __block BOOL success = NO; + grey_execute_sync_on_main_thread(^{ + SettingsSwitchCell* switchCell = + base::mac::ObjCCast<SettingsSwitchCell>(collectionViewCell); + if (!switchCell) { + NSString* description = @"The element isn't of the expected type " + @"(SettingsSwitchCell)."; + *errorOrNil = [NSError + errorWithDomain:kChromeActionsErrorDomain + code:0 + userInfo:@{NSLocalizedDescriptionKey : description}]; + success = NO; + return; + } + UISwitch* switchView = switchCell.switchView; + if (switchView.on != on) { + id<GREYAction> longPressAction = [GREYActions + actionForLongPressWithDuration:kGREYLongPressDefaultDuration]; + success = [longPressAction perform:switchView error:errorOrNil]; + return; + } + success = YES; + }); + return success; + }]; +} + ++ (id<GREYAction>)turnSyncSwitchOn:(BOOL)on { + id<GREYMatcher> constraints = grey_not(grey_systemAlertViewShown()); + NSString* actionName = [NSString + stringWithFormat:@"Turn sync switch to %@ state", on ? @"ON" : @"OFF"]; + return [GREYActionBlock + actionWithName:actionName + constraints:constraints + performBlock:^BOOL(id syncSwitchCell, __strong NSError** errorOrNil) { + // EG2 executes actions on a background thread by default. Since this + // action interacts with UI, kick it over to the main thread. + __block BOOL success = NO; + grey_execute_sync_on_main_thread(^{ + SettingsSwitchCell* switchCell = + base::mac::ObjCCastStrict<SettingsSwitchCell>(syncSwitchCell); + UISwitch* switchView = switchCell.switchView; + if (switchView.on != on) { + id<GREYAction> longPressAction = [GREYActions + actionForLongPressWithDuration:kGREYLongPressDefaultDuration]; + success = [longPressAction perform:switchView error:errorOrNil]; + return; + } + success = YES; + }); + return success; + }]; +} + ++ (id<GREYAction>)tapWebElement:(ElementSelector*)selector { + return web::WebViewTapElement(chrome_test_util::GetCurrentWebState(), + selector); +} + +@end
diff --git a/ios/chrome/test/earl_grey2/smoke_egtest.mm b/ios/chrome/test/earl_grey2/smoke_egtest.mm index 78027971..2f01ed32 100644 --- a/ios/chrome/test/earl_grey2/smoke_egtest.mm +++ b/ios/chrome/test/earl_grey2/smoke_egtest.mm
@@ -6,6 +6,7 @@ #import <UIKit/UIKit.h> #import <XCTest/XCTest.h> +#import "ios/chrome/test/earl_grey/chrome_actions.h" #import "ios/chrome/test/earl_grey/chrome_matchers.h" #import "ios/chrome/test/earl_grey2/chrome_earl_grey_edo.h" @@ -29,12 +30,6 @@ }); } -// Tests that the tools menu is tappable. -- (void)testTapToolsMenu { - [[EarlGrey selectElementWithMatcher:chrome_test_util::ToolsMenuButton()] - performAction:grey_tap()]; -} - // Tests that a tab can be opened. - (void)testOpenTab { // Open tools menu. @@ -54,4 +49,41 @@ [[GREYHostApplicationDistantObject sharedInstance] GetMainTabCount]; GREYAssertEqual(2, tabCount, @"Expected 2 tabs."); } + +// Tests that helpers from chrome_matchers.h are available for use in tests. +- (void)testTapToolsMenu { + [[EarlGrey selectElementWithMatcher:chrome_test_util::ToolsMenuButton()] + performAction:grey_tap()]; + + // Tap a second time to close the menu. + [[EarlGrey selectElementWithMatcher:chrome_test_util::ToolsMenuButton()] + performAction:grey_tap()]; +} + +// Tests that helpers from chrome_actions.h are available for use in tests. +- (void)testToggleSettingsSwitch { + [[EarlGrey selectElementWithMatcher:chrome_test_util::ToolsMenuButton()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsMenuButton()] + performAction:grey_tap()]; + [[EarlGrey + selectElementWithMatcher:chrome_test_util::SettingsMenuPasswordsButton()] + performAction:grey_tap()]; + + // Toggle the passwords switch off and on. + [[EarlGrey selectElementWithMatcher:grey_accessibilityID( + @"savePasswordsItem_switch")] + performAction:chrome_test_util::TurnSettingsSwitchOn(NO)]; + [[EarlGrey selectElementWithMatcher:grey_accessibilityID( + @"savePasswordsItem_switch")] + performAction:chrome_test_util::TurnSettingsSwitchOn(YES)]; + + // Close the settings menu. + [[EarlGrey + selectElementWithMatcher:chrome_test_util::SettingsMenuBackButton()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsDoneButton()] + performAction:grey_tap()]; +} + @end
diff --git a/ios/testing/earl_grey/BUILD.gn b/ios/testing/earl_grey/BUILD.gn index c5031900..1ff40c9 100644 --- a/ios/testing/earl_grey/BUILD.gn +++ b/ios/testing/earl_grey/BUILD.gn
@@ -18,6 +18,7 @@ "coverage_utils.mm", "disabled_test_macros.h", "earl_grey_app.h", + "earl_grey_app.mm", "earl_grey_test.h", "matchers.h", "matchers.mm", @@ -39,6 +40,7 @@ "coverage_utils.h", "coverage_utils.mm", "earl_grey_app.h", + "earl_grey_app.mm", ] }
diff --git a/ios/testing/earl_grey/earl_grey_app.h b/ios/testing/earl_grey/earl_grey_app.h index b74efd5..4624ddf 100644 --- a/ios/testing/earl_grey/earl_grey_app.h +++ b/ios/testing/earl_grey/earl_grey_app.h
@@ -7,6 +7,8 @@ // Contains includes and typedefs to allow code to compile under both EarlGrey1 // and EarlGrey2 (App Process). +// TODO(crbug.com/917390): Remove this file once all callers have been converted +// to EG2. #if defined(CHROME_EARL_GREY_1) @@ -15,12 +17,18 @@ typedef DescribeToBlock GREYDescribeToBlock; typedef MatchesBlock GREYMatchesBlock; +// Provides a no-op implementation of an EG2 API that doesn't exist in EG1. This +// helper assumes that it is already being called on the main thread and +// synchronously runs the given |block|. +void grey_execute_sync_on_main_thread(void (^block)(void)); + #elif defined(CHROME_EARL_GREY_2) #import <AppFramework/Action/GREYActionsShorthand.h> #import <AppFramework/Core/GREYElementInteraction.h> #import <AppFramework/EarlGreyApp.h> #import <AppFramework/Matcher/GREYMatchersShorthand.h> +#import <AppFramework/Synchronization/GREYSyncAPI.h> #import <CommonLib/Error/GREYErrorConstants.h> #else
diff --git a/ios/testing/earl_grey/earl_grey_app.mm b/ios/testing/earl_grey/earl_grey_app.mm new file mode 100644 index 0000000..5e33940a --- /dev/null +++ b/ios/testing/earl_grey/earl_grey_app.mm
@@ -0,0 +1,15 @@ +// Copyright 2019 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 "ios/testing/earl_grey/earl_grey_app.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#if defined(CHROME_EARL_GREY_1) +void grey_execute_sync_on_main_thread(void (^block)(void)) { + block(); +} +#endif
diff --git a/media/capture/mojom/image_capture.mojom b/media/capture/mojom/image_capture.mojom index c780a1df..720faa9b 100644 --- a/media/capture/mojom/image_capture.mojom +++ b/media/capture/mojom/image_capture.mojom
@@ -64,8 +64,8 @@ // https://w3c.github.io/mediacapture-image/#point2d-section // TODO(mcasas): use gfx::mojom::PointF after https://crbug.com/640049. struct Point2D { - float x; - float y; + double x; + double y; }; // Equivalent to idl PhotoSettings + MediaTrackSettings/MediaTrackConstraintSet.
diff --git a/media/capture/video/android/java/src/org/chromium/media/VideoCapture.java b/media/capture/video/android/java/src/org/chromium/media/VideoCapture.java index 4f346ade..9853d9c 100644 --- a/media/capture/video/android/java/src/org/chromium/media/VideoCapture.java +++ b/media/capture/video/android/java/src/org/chromium/media/VideoCapture.java
@@ -102,7 +102,7 @@ */ @CalledByNative public abstract void setPhotoOptions(double zoom, int focusMode, double focusDistance, - int exposureMode, double width, double height, float[] pointsOfInterest2D, + int exposureMode, double width, double height, double[] pointsOfInterest2D, boolean hasExposureCompensation, double exposureCompensation, double exposureTime, int whiteBalanceMode, double iso, boolean hasRedEyeReduction, boolean redEyeReduction, int fillLightMode, boolean hasTorch, boolean torch, double colorTemperature);
diff --git a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java index 390d21d9..0e72521 100644 --- a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java +++ b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java
@@ -663,7 +663,7 @@ @Override public void setPhotoOptions(double zoom, int focusMode, double focusDistance, int exposureMode, - double width, double height, float[] pointsOfInterest2D, + double width, double height, double[] pointsOfInterest2D, boolean hasExposureCompensation, double exposureCompensation, double exposureTime, int whiteBalanceMode, double iso, boolean hasRedEyeReduction, boolean redEyeReduction, int fillLightMode, boolean hasTorch, boolean torch, double colorTemperature) { @@ -721,8 +721,8 @@ assert pointsOfInterest2D[1] <= 1.0 && pointsOfInterest2D[1] >= 0.0; // Calculate a Rect of 1/8 the canvas, which is fixed to Rect(-1000, -1000, 1000, 1000), // see https://developer.android.com/reference/android/hardware/Camera.Area.html - final int centerX = Math.round(pointsOfInterest2D[0] * 2000) - 1000; - final int centerY = Math.round(pointsOfInterest2D[1] * 2000) - 1000; + final int centerX = (int) (Math.round(pointsOfInterest2D[0] * 2000) - 1000); + final int centerY = (int) (Math.round(pointsOfInterest2D[1] * 2000) - 1000); final int regionWidth = 2000 / 8; final int regionHeight = 2000 / 8; final int weight = 1000;
diff --git a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java index 03819bd0..123493df 100644 --- a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java +++ b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java
@@ -686,7 +686,7 @@ public final int exposureMode; public final double width; public final double height; - public final float[] pointsOfInterest2D; + public final double[] pointsOfInterest2D; public final boolean hasExposureCompensation; public final double exposureCompensation; public final double exposureTime; @@ -700,7 +700,7 @@ public final double colorTemperature; public PhotoOptions(double zoom, int focusMode, double currentFocusDistance, - int exposureMode, double width, double height, float[] pointsOfInterest2D, + int exposureMode, double width, double height, double[] pointsOfInterest2D, boolean hasExposureCompensation, double exposureCompensation, double exposureTime, int whiteBalanceMode, double iso, boolean hasRedEyeReduction, boolean redEyeReduction, int fillLightMode, boolean hasTorch, boolean torch, @@ -790,8 +790,10 @@ // Calculate a Rect of 1/8 the |visibleRect| dimensions, and center it w.r.t. // |canvas|. final Rect visibleRect = (mCropRect.isEmpty()) ? canvas : mCropRect; - int centerX = Math.round(mOptions.pointsOfInterest2D[0] * visibleRect.width()); - int centerY = Math.round(mOptions.pointsOfInterest2D[1] * visibleRect.height()); + int centerX = + (int) Math.round(mOptions.pointsOfInterest2D[0] * visibleRect.width()); + int centerY = + (int) Math.round(mOptions.pointsOfInterest2D[1] * visibleRect.height()); if (visibleRect.equals(mCropRect)) { centerX += (canvas.width() - visibleRect.width()) / 2; centerY += (canvas.height() - visibleRect.height()) / 2; @@ -1541,7 +1543,7 @@ @Override public void setPhotoOptions(double zoom, int focusMode, double currentFocusDistance, - int exposureMode, double width, double height, float[] pointsOfInterest2D, + int exposureMode, double width, double height, double[] pointsOfInterest2D, boolean hasExposureCompensation, double exposureCompensation, double exposureTime, int whiteBalanceMode, double iso, boolean hasRedEyeReduction, boolean redEyeReduction, int fillLightMode, boolean hasTorch, boolean torch, double colorTemperature) {
diff --git a/media/capture/video/android/video_capture_device_android.cc b/media/capture/video/android/video_capture_device_android.cc index 02e4256..777e8229 100644 --- a/media/capture/video/android/video_capture_device_android.cc +++ b/media/capture/video/android/video_capture_device_android.cc
@@ -736,13 +736,13 @@ const double width = settings->has_width ? settings->width : 0.0; const double height = settings->has_height ? settings->height : 0.0; - std::vector<float> points_of_interest_marshalled; + std::vector<double> points_of_interest_marshalled; for (const auto& point : settings->points_of_interest) { points_of_interest_marshalled.push_back(point->x); points_of_interest_marshalled.push_back(point->y); } - ScopedJavaLocalRef<jfloatArray> points_of_interest = - base::android::ToJavaFloatArray(env, points_of_interest_marshalled); + ScopedJavaLocalRef<jdoubleArray> points_of_interest = + base::android::ToJavaDoubleArray(env, points_of_interest_marshalled); const double exposure_compensation = settings->has_exposure_compensation ? settings->exposure_compensation
diff --git a/media/capture/video/chromeos/camera_device_delegate.cc b/media/capture/video/chromeos/camera_device_delegate.cc index 0f17177d..3beb0dfe 100644 --- a/media/capture/video/chromeos/camera_device_delegate.cc +++ b/media/capture/video/chromeos/camera_device_delegate.cc
@@ -820,11 +820,11 @@ // the closest allowed value. // ref: https://www.w3.org/TR/image-capture/#points-of-interest - float x = base::ClampToRange(points_of_interest[0]->x, 0.0f, 1.0f); - float y = base::ClampToRange(points_of_interest[0]->y, 0.0f, 1.0f); + double x = base::ClampToRange(points_of_interest[0]->x, 0.0, 1.0); + double y = base::ClampToRange(points_of_interest[0]->y, 0.0, 1.0); // Handle rotation, still in normalized square space. - std::tie(x, y) = [&]() -> std::pair<float, float> { + std::tie(x, y) = [&]() -> std::pair<double, double> { switch (device_context_->GetCameraFrameOrientation()) { case 0: return {x, y};
diff --git a/net/cert/internal/trust_store_mac.cc b/net/cert/internal/trust_store_mac.cc index 7722bbd..01b505d 100644 --- a/net/cert/internal/trust_store_mac.cc +++ b/net/cert/internal/trust_store_mac.cc
@@ -14,7 +14,6 @@ #include "net/cert/internal/cert_errors.h" #include "net/cert/internal/parse_name.h" #include "net/cert/internal/parsed_certificate.h" -#include "net/cert/internal/verify_signed_data.h" #include "net/cert/test_keychain_search_list_mac.h" #include "net/cert/x509_util.h" #include "net/cert/x509_util_mac.h" @@ -142,21 +141,11 @@ return TrustStatus::UNSPECIFIED; } -bool IsSelfSigned(const scoped_refptr<ParsedCertificate>& cert) { - if (cert->normalized_subject() != cert->normalized_issuer()) - return false; - return VerifySignedData(cert->signature_algorithm(), - cert->tbs_certificate_tlv(), cert->signature_value(), - cert->tbs().spki_tlv); -} - // Returns true if the certificate |cert_handle| is trusted for the policy // |policy_oid|. -TrustStatus IsSecCertificateTrustedForPolicy( - const scoped_refptr<ParsedCertificate>& cert, - SecCertificateRef cert_handle, - const CFStringRef policy_oid) { - const bool is_self_signed = IsSelfSigned(cert); +TrustStatus IsSecCertificateTrustedForPolicy(SecCertificateRef cert_handle, + const CFStringRef policy_oid) { + const bool is_self_signed = x509_util::IsSelfSigned(cert_handle); // Evaluate trust domains in user, admin, system order. Admin settings can // override system ones, and user settings can override both admin and system. for (const auto& trust_domain : @@ -253,7 +242,7 @@ } TrustStatus trust_status = - IsSecCertificateTrustedForPolicy(cert, cert_handle, policy_oid_); + IsSecCertificateTrustedForPolicy(cert_handle, policy_oid_); switch (trust_status) { case TrustStatus::TRUSTED: *trust = CertificateTrust::ForTrustAnchor();
diff --git a/net/cert/x509_util_mac.cc b/net/cert/x509_util_mac.cc index e36e161..5285c4bc 100644 --- a/net/cert/x509_util_mac.cc +++ b/net/cert/x509_util_mac.cc
@@ -121,6 +121,42 @@ return result; } +bool IsSelfSigned(SecCertificateRef cert_handle) { + CSSMCachedCertificate cached_cert; + OSStatus status = cached_cert.Init(cert_handle); + if (status != noErr) + return false; + + CSSMFieldValue subject; + status = cached_cert.GetField(&CSSMOID_X509V1SubjectNameStd, &subject); + if (status != CSSM_OK || !subject.field()) + return false; + + CSSMFieldValue issuer; + status = cached_cert.GetField(&CSSMOID_X509V1IssuerNameStd, &issuer); + if (status != CSSM_OK || !issuer.field()) + return false; + + if (subject.field()->Length != issuer.field()->Length || + memcmp(subject.field()->Data, issuer.field()->Data, + issuer.field()->Length) != 0) { + return false; + } + + CSSM_CL_HANDLE cl_handle = CSSM_INVALID_HANDLE; + status = SecCertificateGetCLHandle(cert_handle, &cl_handle); + if (status) + return false; + CSSM_DATA cert_data; + status = SecCertificateGetData(cert_handle, &cert_data); + if (status) + return false; + + if (CSSM_CL_CertVerify(cl_handle, 0, &cert_data, &cert_data, NULL, 0)) + return false; + return true; +} + SHA256HashValue CalculateFingerprint256(SecCertificateRef cert) { SHA256HashValue sha256; memset(sha256.data, 0, sizeof(sha256.data));
diff --git a/net/cert/x509_util_mac.h b/net/cert/x509_util_mac.h index 8af33ed..77050562 100644 --- a/net/cert/x509_util_mac.h +++ b/net/cert/x509_util_mac.h
@@ -58,6 +58,9 @@ const std::vector<SecCertificateRef>& sec_chain, X509Certificate::UnsafeCreateOptions options); +// Returns true if the certificate is self-signed. +NET_EXPORT bool IsSelfSigned(SecCertificateRef cert_handle); + // Calculates the SHA-256 fingerprint of the certificate. Returns an empty // (all zero) fingerprint on failure. NET_EXPORT SHA256HashValue CalculateFingerprint256(SecCertificateRef cert);
diff --git a/net/disk_cache/disk_cache_fuzzer.cc b/net/disk_cache/disk_cache_fuzzer.cc index 6d707f2..e0d6561 100644 --- a/net/disk_cache/disk_cache_fuzzer.cc +++ b/net/disk_cache/disk_cache_fuzzer.cc
@@ -975,6 +975,9 @@ uint32_t offset, uint32_t len, int rv) { std::move(callback).Run(rv); + if (rv < 0) + return; + int64_t* start_tmp = &start->data; CHECK_LE(offset, *start_tmp); CHECK_LE(*start_tmp, offset + len);
diff --git a/printing/image_win.cc b/printing/image_win.cc index 787c24aa..d473432 100644 --- a/printing/image_win.cc +++ b/printing/image_win.cc
@@ -16,46 +16,10 @@ #include "ui/gfx/gdi_util.h" // EMF support #include "ui/gfx/geometry/rect.h" - -namespace { - -// A simple class which temporarily overrides system settings. -// The bitmap image rendered via the PlayEnhMetaFile() function depends on -// some system settings. -// As a workaround for such dependency, this class saves the system settings -// and changes them. This class also restore the saved settings in its -// destructor. -class DisableFontSmoothing { - public: - DisableFontSmoothing() : enable_again_(false) { - BOOL enabled; - if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &enabled, 0) && - enabled) { - if (SystemParametersInfo(SPI_SETFONTSMOOTHING, FALSE, NULL, 0)) - enable_again_ = true; - } - } - - ~DisableFontSmoothing() { - if (enable_again_) { - BOOL result = SystemParametersInfo(SPI_SETFONTSMOOTHING, TRUE, NULL, 0); - DCHECK(result); - } - } - - private: - bool enable_again_; - - DISALLOW_COPY_AND_ASSIGN(DisableFontSmoothing); -}; - -} // namespace - namespace printing { bool Image::LoadMetafile(const Metafile& metafile) { - gfx::Rect rect(metafile.GetPageBounds(1)); - DisableFontSmoothing disable_in_this_scope; + gfx::Rect rect(metafile.GetPageBounds(1)); // Create a temporary HDC and bitmap to retrieve the rendered data. base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
diff --git a/services/network/public/cpp/is_potentially_trustworthy_unittest.cc b/services/network/public/cpp/is_potentially_trustworthy_unittest.cc index 71818bca..aaa6347 100644 --- a/services/network/public/cpp/is_potentially_trustworthy_unittest.cc +++ b/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
@@ -122,6 +122,12 @@ EXPECT_FALSE(IsPotentiallyTrustworthy("http://128.example.com/a.html")); EXPECT_FALSE( IsPotentiallyTrustworthy("http://foobar.127.example.com/a.html")); + + // When port is not specified, default port is assumed. + EXPECT_TRUE(IsAllowlistedAsSecureOrigin( + url::Origin::Create(GURL("http://example.com:80/a.html")))); + EXPECT_FALSE(IsAllowlistedAsSecureOrigin( + url::Origin::Create(GURL("http://example.com:8080/a.html")))); } TEST_F(SecureOriginAllowlistTest, HostnamePatterns) { @@ -151,6 +157,17 @@ {"test*.foo.com", "http://testblah.foo.com", false}, {"*foo.com", "http://testfoo.com", false}, {"foo*.com", "http://footest.com", false}, + // With Hostname pattern, all ports are allowed. + {"*.foo.com", "http://bar.foo.com:80", true}, + {"*.foo.com", "http://bar.foo.com:1234", true}, + // With Hostname pattern, all schemes are allowed. + {"*.foo.com", "ws://bar.foo.com", true}, + {"*.foo.com", "blob:http://bar.foo.com/guid-goes-here", true}, + // Hostname pattern works on IP addresses, but wildcards must be beyond + // eTLD+1. + {"*.20.30.40", "http://10.20.30.40", true}, + {"*.30.40", "http://10.20.30.40", true}, + {"*.40", "http://10.20.30.40", false}, }; for (const auto& test : kTestCases) { @@ -167,4 +184,20 @@ } } +TEST_F(SecureOriginAllowlistTest, MixOfOriginAndHostnamePatterns) { + base::test::ScopedCommandLine scoped_command_line; + base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine(); + command_line->AppendSwitchASCII( + switches::kUnsafelyTreatInsecureOriginAsSecure, + "http://example.com,*.foo.com,http://10.20.30.40"); + ResetSecureOriginAllowlistForTesting(); + + EXPECT_TRUE(IsAllowlistedAsSecureOrigin( + url::Origin::Create(GURL("http://example.com/a.html")))); + EXPECT_TRUE(IsAllowlistedAsSecureOrigin( + url::Origin::Create(GURL("http://bar.foo.com/b.html")))); + EXPECT_TRUE(IsAllowlistedAsSecureOrigin( + url::Origin::Create(GURL("http://10.20.30.40/c.html")))); +} + } // namespace network
diff --git a/services/service_manager/sandbox/mac/gpu_v2.sb b/services/service_manager/sandbox/mac/gpu_v2.sb index 241a58475..146db3e 100644 --- a/services/service_manager/sandbox/mac/gpu_v2.sb +++ b/services/service_manager/sandbox/mac/gpu_v2.sb
@@ -15,6 +15,7 @@ (global-name "com.apple.coreservices.launchservicesd") (global-name "com.apple.cvmsServ") (global-name "com.apple.gpumemd.source") + (global-name "com.apple.lsd.mapdb") (global-name "com.apple.system.notification_center") (global-name "com.apple.tsm.uiserver") (global-name "com.apple.windowserver.active")
diff --git a/testing/libfuzzer/archive_corpus.py b/testing/libfuzzer/archive_corpus.py index d4e8e51..dddc18ff 100755 --- a/testing/libfuzzer/archive_corpus.py +++ b/testing/libfuzzer/archive_corpus.py
@@ -25,8 +25,6 @@ nargs='+') parser.add_argument('--output', metavar='output_archive_name.zip', required=True) - parser.add_argument('--dry_run', default=False, action='store_true', - help="Don't actually create the output archive.") args = parser.parse_args() corpus_files = [] @@ -41,9 +39,6 @@ full_filename = os.path.join(dirpath, filename) corpus_files.append(full_filename) - if args.dry_run: - return - with zipfile.ZipFile(seed_corpus_path, 'w') as z: # Turn warnings into errors to interrupt the build: crbug.com/653920. with warnings.catch_warnings():
diff --git a/testing/libfuzzer/fuzzer_test.gni b/testing/libfuzzer/fuzzer_test.gni index bd5d7df..4d16b70 100644 --- a/testing/libfuzzer/fuzzer_test.gni +++ b/testing/libfuzzer/fuzzer_test.gni
@@ -74,12 +74,6 @@ } } - # Tell the script not to actually zip the seed corpus if we have been - # instructed not to build it. - if (!archive_seed_corpus) { - args += [ "--dry_run" ] - } - outputs = [ out, ] @@ -87,7 +81,9 @@ deps = [ "//testing/libfuzzer:seed_corpus" ] + seed_corpus_deps } - test_deps += [ ":" + target_name + "_seed_corpus" ] + if (!archive_seed_corpus) { + test_deps += [ ":" + target_name + "_seed_corpus" ] + } } if (defined(invoker.dict) || defined(invoker.libfuzzer_options) ||
diff --git a/testing/merge_scripts/code_coverage/merge_profiles.py b/testing/merge_scripts/code_coverage/merge_profiles.py deleted file mode 120000 index d8ab72c..0000000 --- a/testing/merge_scripts/code_coverage/merge_profiles.py +++ /dev/null
@@ -1 +0,0 @@ -merge_results.py \ No newline at end of file
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index f9c4989d..d241109 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -813,6 +813,27 @@ ] } ], + "AutofillOffNoServerData": [ + { + "platforms": [ + "android", + "android_webview", + "chromeos", + "ios", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AutofillOffNoServerData" + ] + } + ] + } + ], "AutofillPreviewStyleExperiment": [ { "platforms": [
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 930650b1..d76ea97a 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -101,6 +101,7 @@ "service_worker/service_worker_stream_handle.mojom", "site_engagement/site_engagement.mojom", "speech/speech_recognition_error.mojom", + "speech/speech_recognition_error_code.mojom", "speech/speech_recognition_grammar.mojom", "speech/speech_recognition_result.mojom", "speech/speech_recognizer.mojom", @@ -134,7 +135,6 @@ ":android_mojo_bindings", ":authenticator_test_mojo_bindings", ":mojom_mhtml_load_result", - ":speech_recognition_error_code", ":web_client_hints_types_mojo_bindings", ":web_feature_mojo_bindings", "//components/payments/mojom", @@ -226,17 +226,6 @@ scramble_message_ids = false } -# Kept separate from "mojom_platform" because the Java bindings are needed by -# Android's implementation of speech recognition. -mojom_component("speech_recognition_error_code") { - sources = [ - "speech/speech_recognition_error_code.mojom", - ] - - macro_prefix = "SPEECH_RECOGNITION_ERROR_CODE_MOJOM" - output_prefix = "speech_recognition_error_code_mojom" -} - # This target can include mojom interfaces which do use types that are # typemapped to a type in renderer/core. This also means these interfaces are # not available from renderer/platform.
diff --git a/third_party/blink/public/mojom/webauthn/authenticator.mojom b/third_party/blink/public/mojom/webauthn/authenticator.mojom index 8a35cfa..155ff22b 100644 --- a/third_party/blink/public/mojom/webauthn/authenticator.mojom +++ b/third_party/blink/public/mojom/webauthn/authenticator.mojom
@@ -52,6 +52,18 @@ array<uint8> client_data_json; }; +// Content of user verification method extension returned by both +// Authenticator::MakeCredential and Authenticator::GetAssertion. +// See https://w3c.github.io/webauthn/#sctn-uvm-extension +// Registry of the available values, see +// https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-registry-v2.0-id-20180227.html#user-verification-methods +[EnableIf=is_android] +struct UvmEntry { + uint32 user_verification_method; + uint16 key_protection_type; + uint16 matcher_protection_type; +}; + // The public key and attestation returned by Authenticator::MakeCredential. struct MakeCredentialAuthenticatorResponse { CommonCredentialInfo info; @@ -68,6 +80,16 @@ // extension output. If so, |hmac_create_secret| contains the actual value. bool echo_hmac_create_secret; bool hmac_create_secret; + + // Only supported by fido2 devices on android, will eventually supported by + // other platform. + // True if getClientExtensionResults() called on the returned + // PublicKeyCredential instance should contain an 'uvm' extension output. + // If so, |user_verification_methods| contains the actual value. + [EnableIf=is_android] + bool echo_user_verification_methods; + [EnableIf=is_android] + array<UvmEntry>? user_verification_methods; }; struct GetAssertionAuthenticatorResponse { @@ -89,6 +111,16 @@ // If so, |appid_extension| contains the actual value. bool echo_appid_extension; bool appid_extension; + + // Only supported by fido2 devices on android, will eventually supported by + // other platform. + // True if getClientExtensionResults() called on the returned + // PublicKeyCredential instance should contain an 'uvm' extension output. + // If so, |user_verification_methods| contains the actual value. + [EnableIf=is_android] + bool echo_user_verification_methods; + [EnableIf=is_android] + array<UvmEntry>? user_verification_methods; }; // Information about the relying party. These fields take arbitrary input. @@ -193,6 +225,13 @@ // There may be multiple sets if multiple caBLE credentials have been // registered with the relying party. array<CableAuthentication> cable_authentication_data; + + // Only supported by fido2 devices on android, will eventually supported by + // other platform. + // Whether the user verification method extension is requested by + // the RP. See https://w3c.github.io/webauthn/#sctn-uvm-extension + [EnableIf=is_android] + bool user_verification_methods; }; // See https://w3c.github.io/webauthn/#enumdef-attestationconveyancepreference @@ -267,6 +306,13 @@ // The contents of the hmacCreateSecret extension, if any. See // https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html#sctn-hmac-secret-extension bool hmac_create_secret; + + // Only supported by fido2 devices on android, will eventually supported by + // other platform. + // Whether the user verification method extension is requested by + // the RP. See https://w3c.github.io/webauthn/#sctn-uvm-extension + [EnableIf=is_android] + bool user_verification_methods; }; enum PublicKeyCredentialType {
diff --git a/third_party/blink/renderer/core/animation/animation_effect.cc b/third_party/blink/renderer/core/animation/animation_effect.cc index 27597d21..d2b748a 100644 --- a/third_party/blink/renderer/core/animation/animation_effect.cc +++ b/third_party/blink/renderer/core/animation/animation_effect.cc
@@ -194,10 +194,30 @@ ResolvedFillMode(timing_.fill_mode, IsKeyframeEffect()), local_time, current_phase, timing_); - double current_iteration; base::Optional<double> progress; - if (!IterationDuration().is_zero()) { - const double iteration_duration = IterationDuration().InSecondsF(); + const double iteration_duration = IterationDuration().InSecondsF(); + + const double overall_progress = CalculateOverallProgress( + current_phase, active_time, iteration_duration, timing_.iteration_count, + timing_.iteration_start); + const double simple_iteration_progress = CalculateSimpleIterationProgress( + current_phase, overall_progress, timing_.iteration_start, active_time, + active_duration, timing_.iteration_count); + const double current_iteration = CalculateCurrentIteration( + current_phase, active_time, timing_.iteration_count, overall_progress, + simple_iteration_progress); + + const double directed_progress = CalculateDirectedProgress( + simple_iteration_progress, current_iteration, timing_.direction); + progress = CalculateTransformedProgress( + directed_progress, iteration_duration, timing_.timing_function); + if (IsNull(progress.value())) { + progress.reset(); + } + + // Conditionally compute the time to next iteration, which is only + // applicable if the iteration duration is non-zero. + if (iteration_duration) { const double start_offset = MultiplyZeroAlwaysGivesZero( timing_.iteration_start, iteration_duration); DCHECK_GE(start_offset, 0); @@ -206,68 +226,11 @@ const double iteration_time = CalculateIterationTime( iteration_duration, active_duration, offset_active_time, start_offset, current_phase, timing_); - - current_iteration = CalculateCurrentIteration( - current_phase, active_time, iteration_duration, - timing_.iteration_count, timing_.iteration_start); - - const base::Optional<double> transformed_time = CalculateTransformedTime( - current_iteration, iteration_duration, iteration_time, timing_); - - // The infinite iterationDuration case here is a workaround because - // the specified behaviour does not handle infinite durations well. - // There is an open issue against the spec to fix this: - // https://github.com/w3c/web-animations/issues/142 - if (!std::isfinite(iteration_duration)) - progress = fmod(timing_.iteration_start, 1.0); - else if (transformed_time) - progress = transformed_time.value() / iteration_duration; - if (!IsNull(iteration_time)) { time_to_next_iteration = iteration_duration - iteration_time; if (active_duration - active_time < time_to_next_iteration) time_to_next_iteration = std::numeric_limits<double>::infinity(); } - } else { - const double kLocalIterationDuration = 1; - const double local_active_duration = - kLocalIterationDuration * timing_.iteration_count; - DCHECK_GE(local_active_duration, 0); - const double end_time = std::max( - timing_.start_delay + active_duration + timing_.end_delay, 0.0); - const double before_active_boundary_time = - std::max(std::min(timing_.start_delay, end_time), 0.0); - // local_local_time should be greater than or equal to the - // before_active_boundary_time once the local_time goes past the start - // delay. - const double local_local_time = - local_time < timing_.start_delay - ? local_time - : std::max(local_active_duration + timing_.start_delay, - before_active_boundary_time); - - const AnimationEffect::Phase local_current_phase = CalculatePhase( - local_active_duration, local_local_time, direction, timing_); - const double local_active_time = CalculateActiveTime( - local_active_duration, - ResolvedFillMode(timing_.fill_mode, IsKeyframeEffect()), - local_local_time, local_current_phase, timing_); - const double start_offset = - timing_.iteration_start * kLocalIterationDuration; - DCHECK_GE(start_offset, 0); - const double offset_active_time = CalculateOffsetActiveTime( - local_active_duration, local_active_time, start_offset); - const double iteration_time = CalculateIterationTime( - kLocalIterationDuration, local_active_duration, offset_active_time, - start_offset, current_phase, timing_); - - current_iteration = CalculateCurrentIteration(current_phase, active_time, - /*iteration_duration=*/0, - timing_.iteration_count, - timing_.iteration_start); - - progress = CalculateTransformedTime( - current_iteration, kLocalIterationDuration, iteration_time, timing_); } const bool was_canceled = current_phase != calculated_.phase &&
diff --git a/third_party/blink/renderer/core/animation/timing_calculations.h b/third_party/blink/renderer/core/animation/timing_calculations.h index 37f28a20..01c922b 100644 --- a/third_party/blink/renderer/core/animation/timing_calculations.h +++ b/third_party/blink/renderer/core/animation/timing_calculations.h
@@ -211,7 +211,7 @@ double overall_progress, double iteration_start, double active_time, - double iteration_duration, + double active_duration, double iteration_count) { // 1. If the overall progress is unresolved, return unresolved. if (IsNull(overall_progress)) @@ -224,8 +224,6 @@ ? fmod(iteration_start, 1.0) : fmod(overall_progress, 1.0); - const double active_duration = iteration_duration * iteration_count; - // 3. If all of the following conditions are true, // * the simple iteration progress calculated above is zero, and // * the animation effect is in the active phase or the after phase, and @@ -245,11 +243,12 @@ } // https://drafts.csswg.org/web-animations/#calculating-the-current-iteration -static inline double CalculateCurrentIteration(AnimationEffect::Phase phase, - double active_time, - double iteration_duration, - double iteration_count, - double iteration_start) { +static inline double CalculateCurrentIteration( + AnimationEffect::Phase phase, + double active_time, + double iteration_count, + double overall_progress, + double simple_iteration_progress) { // 1. If the active time is unresolved, return unresolved. if (IsNull(active_time)) return NullValue(); @@ -260,15 +259,8 @@ return std::numeric_limits<double>::infinity(); } - const double overall_progress = CalculateOverallProgress( - phase, active_time, iteration_duration, iteration_count, iteration_start); - // 3. If the simple iteration progress is 1.0, return floor(overall progress) // - 1. - const double simple_iteration_progress = CalculateSimpleIterationProgress( - phase, overall_progress, iteration_start, active_time, iteration_duration, - iteration_count); - if (simple_iteration_progress == 1.0) return floor(overall_progress) - 1; @@ -276,57 +268,63 @@ return floor(overall_progress); } -static inline double CalculateDirectedTime(double current_iteration, - double iteration_duration, - double iteration_time, - const Timing& specified) { - DCHECK(IsNull(current_iteration) || current_iteration >= 0); - DCHECK_GT(iteration_duration, 0); +// https://drafts.csswg.org/web-animations/#calculating-the-directed-progress +static inline bool IsCurrentDirectionForwards( + double current_iteration, + Timing::PlaybackDirection direction) { + const bool current_iteration_is_even = + std::isinf(current_iteration) + ? true + : IsWithinEpsilon(fmod(current_iteration, 2), 0); - if (IsNull(iteration_time)) - return NullValue(); + switch (direction) { + case Timing::PlaybackDirection::NORMAL: + return true; - if (IsNull(current_iteration)) - return NullValue(); + case Timing::PlaybackDirection::REVERSE: + return false; - DCHECK_GE(current_iteration, 0); - DCHECK_GE(iteration_time, 0); - DCHECK_LE(iteration_time, iteration_duration); + case Timing::PlaybackDirection::ALTERNATE_NORMAL: + return current_iteration_is_even; - const bool current_iteration_is_odd = fmod(current_iteration, 2) >= 1; - const bool current_direction_is_forwards = - specified.direction == Timing::PlaybackDirection::NORMAL || - (specified.direction == Timing::PlaybackDirection::ALTERNATE_NORMAL && - !current_iteration_is_odd) || - (specified.direction == Timing::PlaybackDirection::ALTERNATE_REVERSE && - current_iteration_is_odd); - - return current_direction_is_forwards ? iteration_time - : iteration_duration - iteration_time; + case Timing::PlaybackDirection::ALTERNATE_REVERSE: + return !current_iteration_is_even; + } } -static inline base::Optional<double> CalculateTransformedTime( +// https://drafts.csswg.org/web-animations/#calculating-the-directed-progress +static inline double CalculateDirectedProgress( + double simple_iteration_progress, double current_iteration, - double iteration_duration, - double iteration_time, - const Timing& specified) { - DCHECK(IsNull(current_iteration) || current_iteration >= 0); - DCHECK_GT(iteration_duration, 0); - DCHECK(IsNull(iteration_time) || - (iteration_time >= 0 && iteration_time <= iteration_duration)); + Timing::PlaybackDirection direction) { + // 1. If the simple progress is unresolved, return unresolved. + if (IsNull(simple_iteration_progress)) + return NullValue(); - double directed_time = CalculateDirectedTime( - current_iteration, iteration_duration, iteration_time, specified); - if (IsNull(directed_time)) - return base::nullopt; - if (!std::isfinite(iteration_duration)) - return directed_time; - double time_fraction = directed_time / iteration_duration; - DCHECK(time_fraction >= 0 && time_fraction <= 1); - return MultiplyZeroAlwaysGivesZero( - iteration_duration, - specified.timing_function->Evaluate( - time_fraction, AccuracyForDuration(iteration_duration))); + // 2. Calculate the current direction. + bool current_direction_is_forwards = + IsCurrentDirectionForwards(current_iteration, direction); + + // 3. If the current direction is forwards then return the simple iteration + // progress. Otherwise return 1 - simple iteration progress. + return current_direction_is_forwards ? simple_iteration_progress + : 1 - simple_iteration_progress; +} + +// https://drafts.csswg.org/web-animations/#calculating-the-transformed-progress +static inline double CalculateTransformedProgress( + double directed_progress, + double iteration_duration, + scoped_refptr<TimingFunction> timing_function) { + if (IsNull(directed_progress)) + return NullValue(); + + // Return the result of evaluating the animation effect’s timing function + // passing directed progress as the input progress value. + // Note that the spec calls for passing in a before flag as well, which should + // be used by the step easing functions (Possibly related to crbug/827560). + return timing_function->Evaluate(directed_progress, + AccuracyForDuration(iteration_duration)); } } // namespace blink
diff --git a/third_party/blink/renderer/core/animation/timing_calculations_test.cc b/third_party/blink/renderer/core/animation/timing_calculations_test.cc index 7832d32..b98ffaf4 100644 --- a/third_party/blink/renderer/core/animation/timing_calculations_test.cc +++ b/third_party/blink/renderer/core/animation/timing_calculations_test.cc
@@ -119,136 +119,185 @@ AnimationEffect::kPhaseActive, timing)); } +TEST(AnimationTimingCalculationsTest, OverallProgress) { + // If the active time is null. + EXPECT_TRUE(IsNull(CalculateOverallProgress(AnimationEffect::kPhaseAfter, + /*active_time=*/NullValue(), + /*iteration_duration=*/1.0, + /*iteration_count=*/1.0, + /*iteration_start=*/1.0))); + + // If iteration duration is zero, calculate progress based on iteration count. + EXPECT_EQ(3, CalculateOverallProgress(AnimationEffect::kPhaseActive, + /*active_time=*/3.0, + /*iteration_duration=*/0.0, + /*iteration_count=*/3.0, + /*iteration_start=*/0.0)); + // ...unless in before phase, in which case progress is zero. + EXPECT_EQ(0, CalculateOverallProgress(AnimationEffect::kPhaseBefore, + /*active_time=*/3.0, + /*iteration_duration=*/0.0, + /*iteration_count=*/3.0, + /*iteration_start=*/0.0)); + + // Otherwise. + EXPECT_EQ(3.0, CalculateOverallProgress(AnimationEffect::kPhaseAfter, + /*active_time=*/2.5, + /*iteration_duration=*/1.0, + /*iteration_count=*/0.0, + /*iteration_start=*/0.5)); +} + +TEST(AnimationTimingCalculationsTest, CalculateSimpleIterationProgress) { + // If the overall progress is null. + EXPECT_TRUE( + IsNull(CalculateSimpleIterationProgress(AnimationEffect::kPhaseAfter, + /*overall_progress=*/NullValue(), + /*iteration_start=*/1.0, + /*active_time=*/NullValue(), + /*active_duration=*/1.0, + /*iteration_count=*/1.0))); + + // If the overall progress is infinite. + const double inf = std::numeric_limits<double>::infinity(); + EXPECT_EQ(0.5, CalculateSimpleIterationProgress(AnimationEffect::kPhaseAfter, + /*overall_progress=*/inf, + /*iteration_start=*/1.5, + /*active_time=*/0.0, + /*active_duration=*/0.0, + /*iteration_count=*/inf)); + + // Precisely on an iteration boundary. + EXPECT_EQ(1.0, CalculateSimpleIterationProgress(AnimationEffect::kPhaseAfter, + /*overall_progress=*/3.0, + /*iteration_start=*/0.0, + /*active_time=*/3.0, + /*active_duration=*/3.0, + /*iteration_count=*/3.0)); + + // Otherwise. + EXPECT_EQ(0.5, CalculateSimpleIterationProgress(AnimationEffect::kPhaseAfter, + /*overall_progress=*/2.5, + /*iteration_start=*/0.0, + /*active_time=*/2.5, + /*active_duration=*/0.0, + /*iteration_count=*/0.0)); +} + TEST(AnimationTimingCalculationsTest, CurrentIteration) { // If the active time is null. - EXPECT_TRUE(IsNull(CalculateCurrentIteration(AnimationEffect::kPhaseAfter, - /*active_time=*/NullValue(), - /*iteration_duration=*/1.0, - /*iteration_count=*/1.0, - /*iteration_start=*/1.0))); - - // If the active time is zero. - EXPECT_EQ(0, CalculateCurrentIteration(AnimationEffect::kPhaseAfter, - /*active_time=*/0.0, - /*iteration_duration=*/1.0, - /*iteration_count=*/0.0, - /*iteration_start=*/0.0)); + EXPECT_TRUE( + IsNull(CalculateCurrentIteration(AnimationEffect::kPhaseAfter, + /*active_time=*/NullValue(), + /*iteration_count=*/1.0, + /*overall_progress=*/NullValue(), + /*simple_iteration_progress=*/0))); // If the iteration count is infinite. const double inf = std::numeric_limits<double>::infinity(); EXPECT_EQ(inf, CalculateCurrentIteration(AnimationEffect::kPhaseAfter, /*active_time=*/1.0, - /*iteration_duration=*/1.0, /*iteration_count=*/inf, - /*iteration_start=*/1.0)); - - // If iteration duration is zero, calculate progress based on iteration count. - EXPECT_EQ(3, CalculateCurrentIteration(AnimationEffect::kPhaseActive, - /*active_time=*/3.0, - /*iteration_duration=*/0.0, - /*iteration_count=*/3.0, - /*iteration_start=*/0.0)); - // ...unless in before phase, in which case progress is zero. - EXPECT_EQ(0, CalculateCurrentIteration(AnimationEffect::kPhaseBefore, - /*active_time=*/3.0, - /*iteration_duration=*/0.0, - /*iteration_count=*/3.0, - /*iteration_start=*/0.0)); + /*overall_progress=*/inf, + /*simple_iteration_progress=*/0.0)); // Hold the endpoint of the final iteration of ending precisely on an // iteration boundary. EXPECT_EQ(2, CalculateCurrentIteration(AnimationEffect::kPhaseAfter, /*active_time=*/3.0, - /*iteration_duration=*/1.0, /*iteration_count=*/3.0, - /*iteration_start=*/0.0)); + /*overall_progress=*/3.0, + /*simple_iteration_progress=*/1.0)); // Otherwise. EXPECT_EQ(2, CalculateCurrentIteration(AnimationEffect::kPhaseAfter, /*active_time=*/2.5, - /*iteration_duration=*/1.0, /*iteration_count=*/0.0, - /*iteration_start=*/0.0)); + /*overall_progress=*/2.5, + /*simple_iteration_progress=*/0.5)); } -TEST(AnimationTimingCalculationsTest, DirectedTime) { - Timing timing; +TEST(AnimationTimingCalculationsTest, IsCurrentDirectionForwards) { + // IsCurrentDirectionForwards(current_iteration, + // direction); - // calculateDirectedTime( - // currentIteration, iterationDuration, iterationTime, timing) + EXPECT_TRUE(IsCurrentDirectionForwards(0, Timing::PlaybackDirection::NORMAL)); + EXPECT_TRUE(IsCurrentDirectionForwards(1, Timing::PlaybackDirection::NORMAL)); + EXPECT_TRUE(IsCurrentDirectionForwards( + 0, Timing::PlaybackDirection::ALTERNATE_NORMAL)); + EXPECT_TRUE(IsCurrentDirectionForwards( + 1, Timing::PlaybackDirection::ALTERNATE_REVERSE)); - // if the iteration time is null - EXPECT_TRUE(IsNull(CalculateDirectedTime(1, 2, NullValue(), timing))); + EXPECT_FALSE( + IsCurrentDirectionForwards(0, Timing::PlaybackDirection::REVERSE)); + EXPECT_FALSE( + IsCurrentDirectionForwards(1, Timing::PlaybackDirection::REVERSE)); + EXPECT_FALSE(IsCurrentDirectionForwards( + 0, Timing::PlaybackDirection::ALTERNATE_REVERSE)); + EXPECT_FALSE(IsCurrentDirectionForwards( + 1, Timing::PlaybackDirection::ALTERNATE_NORMAL)); +} + +TEST(AnimationTimingCalculationsTest, CalculateDirectedProgress) { + // CalculateDirectedProgress(simple_iteration_progress, + // current_iteration, + // direction); + + // if the simple iteration progress is null + EXPECT_TRUE(IsNull(CalculateDirectedProgress( + NullValue(), NullValue(), Timing::PlaybackDirection::NORMAL))); // forwards - EXPECT_EQ(17, CalculateDirectedTime(0, 20, 17, timing)); - EXPECT_EQ(17, CalculateDirectedTime(1, 20, 17, timing)); - timing.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL; - EXPECT_EQ(17, CalculateDirectedTime(0, 20, 17, timing)); - EXPECT_EQ(17, CalculateDirectedTime(2, 20, 17, timing)); - timing.direction = Timing::PlaybackDirection::ALTERNATE_REVERSE; - EXPECT_EQ(17, CalculateDirectedTime(1, 20, 17, timing)); - EXPECT_EQ(17, CalculateDirectedTime(3, 20, 17, timing)); + EXPECT_EQ(0, + CalculateDirectedProgress(0, 8, Timing::PlaybackDirection::NORMAL)); + EXPECT_EQ(1, + CalculateDirectedProgress(1, 8, Timing::PlaybackDirection::NORMAL)); + EXPECT_EQ(0, + CalculateDirectedProgress(0, 9, Timing::PlaybackDirection::NORMAL)); + EXPECT_EQ(1, + CalculateDirectedProgress(1, 9, Timing::PlaybackDirection::NORMAL)); + EXPECT_EQ(0, CalculateDirectedProgress( + 0, 8, Timing::PlaybackDirection::ALTERNATE_NORMAL)); + EXPECT_EQ(1, CalculateDirectedProgress( + 1, 8, Timing::PlaybackDirection::ALTERNATE_NORMAL)); + EXPECT_EQ(0, CalculateDirectedProgress( + 0, 9, Timing::PlaybackDirection::ALTERNATE_REVERSE)); + EXPECT_EQ(1, CalculateDirectedProgress( + 1, 9, Timing::PlaybackDirection::ALTERNATE_REVERSE)); // reverse - timing.direction = Timing::PlaybackDirection::REVERSE; - EXPECT_EQ(3, CalculateDirectedTime(0, 20, 17, timing)); - EXPECT_EQ(3, CalculateDirectedTime(1, 20, 17, timing)); - timing.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL; - EXPECT_EQ(3, CalculateDirectedTime(1, 20, 17, timing)); - EXPECT_EQ(3, CalculateDirectedTime(3, 20, 17, timing)); - timing.direction = Timing::PlaybackDirection::ALTERNATE_REVERSE; - EXPECT_EQ(3, CalculateDirectedTime(0, 20, 17, timing)); - EXPECT_EQ(3, CalculateDirectedTime(2, 20, 17, timing)); + EXPECT_EQ( + 1, CalculateDirectedProgress(0, 8, Timing::PlaybackDirection::REVERSE)); + EXPECT_EQ( + 0, CalculateDirectedProgress(1, 8, Timing::PlaybackDirection::REVERSE)); + EXPECT_EQ( + 1, CalculateDirectedProgress(0, 9, Timing::PlaybackDirection::REVERSE)); + EXPECT_EQ( + 0, CalculateDirectedProgress(1, 9, Timing::PlaybackDirection::REVERSE)); + EXPECT_EQ(1, CalculateDirectedProgress( + 0, 9, Timing::PlaybackDirection::ALTERNATE_NORMAL)); + EXPECT_EQ(0, CalculateDirectedProgress( + 1, 9, Timing::PlaybackDirection::ALTERNATE_NORMAL)); + EXPECT_EQ(1, CalculateDirectedProgress( + 0, 8, Timing::PlaybackDirection::ALTERNATE_REVERSE)); + EXPECT_EQ(0, CalculateDirectedProgress( + 1, 8, Timing::PlaybackDirection::ALTERNATE_REVERSE)); } -TEST(AnimationTimingCalculationsTest, TransformedTime) { - Timing timing; +TEST(AnimationTimingCalculationsTest, TransformedProgress) { + // CalculateTransformedProgress( + // directed_progress, iteration_duraction, timing_function) - // calculateTransformedTime( - // currentIteration, iterationDuration, iterationTime, timing) - - // Iteration time is null - EXPECT_FALSE(CalculateTransformedTime(1, 2, NullValue(), timing).has_value()); - - // PlaybackDirectionForwards - EXPECT_EQ(12, CalculateTransformedTime(0, 20, 12, timing)); - EXPECT_EQ(12, CalculateTransformedTime(1, 20, 12, timing)); - - // PlaybackDirectionForwards with timing function - timing.timing_function = + scoped_refptr<TimingFunction> timing_function = StepsTimingFunction::Create(4, StepsTimingFunction::StepPosition::END); - EXPECT_EQ(10, CalculateTransformedTime(0, 20, 12, timing)); - EXPECT_EQ(10, CalculateTransformedTime(1, 20, 12, timing)); - // PlaybackDirectionReverse - timing.timing_function = Timing::Defaults().timing_function; - timing.direction = Timing::PlaybackDirection::REVERSE; - EXPECT_EQ(8, CalculateTransformedTime(0, 20, 12, timing)); - EXPECT_EQ(8, CalculateTransformedTime(1, 20, 12, timing)); + // directed_progress is null. + EXPECT_TRUE( + IsNull(CalculateTransformedProgress(NullValue(), 1, timing_function))); - // PlaybackDirectionReverse with timing function - timing.timing_function = - StepsTimingFunction::Create(4, StepsTimingFunction::StepPosition::END); - EXPECT_EQ(5, CalculateTransformedTime(0, 20, 12, timing)); - EXPECT_EQ(5, CalculateTransformedTime(1, 20, 12, timing)); - - // Timing function when directed time is null. - EXPECT_FALSE(CalculateTransformedTime(1, 2, NullValue(), timing).has_value()); - - // Timing function when iterationDuration is infinity - timing.direction = Timing::PlaybackDirection::NORMAL; - EXPECT_EQ(0, CalculateTransformedTime( - 0, std::numeric_limits<double>::infinity(), 0, timing)); - EXPECT_EQ(1, CalculateTransformedTime( - 0, std::numeric_limits<double>::infinity(), 1, timing)); - timing.direction = Timing::PlaybackDirection::REVERSE; - EXPECT_EQ(std::numeric_limits<double>::infinity(), - CalculateTransformedTime(0, std::numeric_limits<double>::infinity(), - 0, timing)); - EXPECT_EQ(std::numeric_limits<double>::infinity(), - CalculateTransformedTime(0, std::numeric_limits<double>::infinity(), - 1, timing)); + // Otherwise. + EXPECT_EQ(0, CalculateTransformedProgress(0, 1, timing_function)); + EXPECT_EQ(1, CalculateTransformedProgress(1, 1, timing_function)); } } // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 7ba3094..570fe2c 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1482,7 +1482,9 @@ if (!MainFrameImpl()) return; - if (RuntimeEnabledFeatures::UpdateHoverFromScrollAtBeginFrameEnabled()) { + if (RuntimeEnabledFeatures::UpdateHoverFromScrollAtBeginFrameEnabled() || + RuntimeEnabledFeatures:: + UpdateHoverFromLayoutChangeAtBeginFrameEnabled()) { MainFrameImpl() ->GetFrame() ->GetEventHandler()
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 71c3d053..2c371ed 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -1828,8 +1828,15 @@ FontFaceSetDocument::DidLayout(*frame_->GetDocument()); // Fire a fake a mouse move event to update hover state and mouse cursor, and // send the right mouse out/over events. - frame_->GetEventHandler().MayUpdateHoverWhenContentUnderMouseChanged( - MouseEventManager::UpdateHoverReason::kLayoutOrStyleChanged); + // TODO(lanwei): we should check whether the mouse is inside the frame before + // dirtying the hover state. + if (RuntimeEnabledFeatures:: + UpdateHoverFromLayoutChangeAtBeginFrameEnabled()) { + frame_->LocalFrameRoot().GetEventHandler().MarkHoverStateDirty(); + } else { + frame_->GetEventHandler().MayUpdateHoverWhenContentUnderMouseChanged( + MouseEventManager::UpdateHoverReason::kLayoutOrStyleChanged); + } UpdateGeometriesIfNeeded();
diff --git a/third_party/blink/renderer/core/input/mouse_event_manager.cc b/third_party/blink/renderer/core/input/mouse_event_manager.cc index 4626cf37..61be9f5 100644 --- a/third_party/blink/renderer/core/input/mouse_event_manager.cc +++ b/third_party/blink/renderer/core/input/mouse_event_manager.cc
@@ -415,13 +415,17 @@ } void MouseEventManager::MarkHoverStateDirty() { - DCHECK(RuntimeEnabledFeatures::UpdateHoverFromScrollAtBeginFrameEnabled()); + DCHECK( + RuntimeEnabledFeatures::UpdateHoverFromScrollAtBeginFrameEnabled() || + RuntimeEnabledFeatures::UpdateHoverFromLayoutChangeAtBeginFrameEnabled()); DCHECK(frame_->IsLocalRoot()); hover_state_dirty_ = true; } bool MouseEventManager::HoverStateDirty() { - DCHECK(RuntimeEnabledFeatures::UpdateHoverFromScrollAtBeginFrameEnabled()); + DCHECK( + RuntimeEnabledFeatures::UpdateHoverFromScrollAtBeginFrameEnabled() || + RuntimeEnabledFeatures::UpdateHoverFromLayoutChangeAtBeginFrameEnabled()); DCHECK(frame_->IsLocalRoot()); return hover_state_dirty_; }
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index 27729a43b..bdafc29 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -1113,7 +1113,10 @@ // "contain: strict" element has "position: sticky". This was causing // crashes because PaintLayerScrollableArea::sticky_constraints_map_ was // not updated correctly in some cases (see crbug.com/949887). - !current->GetLayoutObject().IsStickyPositioned()) + !current->GetLayoutObject().IsStickyPositioned() && + // TODO(rego): Disable CompositingInputsRoot optimization for iframes + // (see crbug.com/953159). + !current->GetLayoutObject().IsLayoutIFrame()) break; }
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc index bd8985ca..f822e39 100644 --- a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc +++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
@@ -280,7 +280,7 @@ void WorkletAnimation::play(ExceptionState& exception_state) { DCHECK(IsMainThread()); - if (play_state_ == Animation::kPending) + if (play_state_ == Animation::kPending || play_state_ == Animation::kRunning) return; if (play_state_ == Animation::kPaused) {
diff --git a/third_party/blink/renderer/modules/clipboard/BUILD.gn b/third_party/blink/renderer/modules/clipboard/BUILD.gn index 70bae28..0b60478 100644 --- a/third_party/blink/renderer/modules/clipboard/BUILD.gn +++ b/third_party/blink/renderer/modules/clipboard/BUILD.gn
@@ -8,6 +8,8 @@ sources = [ "clipboard.cc", "clipboard.h", + "clipboard_item.cc", + "clipboard_item.h", "clipboard_promise.cc", "clipboard_promise.h", "clipboard_reader.cc",
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard.cc b/third_party/blink/renderer/modules/clipboard/clipboard.cc index 065bccc..69639363 100644 --- a/third_party/blink/renderer/modules/clipboard/clipboard.cc +++ b/third_party/blink/renderer/modules/clipboard/clipboard.cc
@@ -21,9 +21,8 @@ return ClipboardPromise::CreateForReadText(script_state); } -ScriptPromise Clipboard::write( - ScriptState* script_state, - HeapVector<std::pair<String, Member<Blob>>> data) { +ScriptPromise Clipboard::write(ScriptState* script_state, + const HeapVector<Member<ClipboardItem>>& data) { return ClipboardPromise::CreateForWrite(script_state, std::move(data)); }
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard.h b/third_party/blink/renderer/modules/clipboard/clipboard.h index e18decf8..c74a672 100644 --- a/third_party/blink/renderer/modules/clipboard/clipboard.h +++ b/third_party/blink/renderer/modules/clipboard/clipboard.h
@@ -12,6 +12,7 @@ #include "third_party/blink/renderer/core/dom/events/event_target.h" #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" #include "third_party/blink/renderer/core/fileapi/blob.h" +#include "third_party/blink/renderer/modules/clipboard/clipboard_item.h" namespace blink { @@ -28,8 +29,7 @@ ScriptPromise read(ScriptState*); ScriptPromise readText(ScriptState*); - ScriptPromise write(ScriptState*, - HeapVector<std::pair<String, Member<Blob>>>); + ScriptPromise write(ScriptState*, const HeapVector<Member<ClipboardItem>>&); ScriptPromise writeText(ScriptState*, const String&); // EventTarget
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard.idl b/third_party/blink/renderer/modules/clipboard/clipboard.idl index 4687936..ceefcbf8 100644 --- a/third_party/blink/renderer/modules/clipboard/clipboard.idl +++ b/third_party/blink/renderer/modules/clipboard/clipboard.idl
@@ -11,7 +11,7 @@ [MeasureAs=AsyncClipboardAPIRead, CallWith=ScriptState, RuntimeEnabled=AsyncClipboard - ] Promise<record<DOMString, Blob>> read(); + ] Promise<sequence<ClipboardItem>> read(); [MeasureAs=AsyncClipboardAPIReadText, CallWith=ScriptState @@ -21,7 +21,7 @@ [MeasureAs=AsyncClipboardAPIWrite, CallWith=ScriptState, RuntimeEnabled=AsyncClipboard - ] Promise<void> write(record<DOMString, Blob> data); + ] Promise<void> write(sequence<ClipboardItem> data); [MeasureAs=AsyncClipboardAPIWriteText, CallWith=ScriptState
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_item.cc b/third_party/blink/renderer/modules/clipboard/clipboard_item.cc new file mode 100644 index 0000000..a958544 --- /dev/null +++ b/third_party/blink/renderer/modules/clipboard/clipboard_item.cc
@@ -0,0 +1,61 @@ +// Copyright 2019 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 "third_party/blink/renderer/modules/clipboard/clipboard_item.h" + +#include "third_party/blink/renderer/core/dom/dom_exception.h" +#include "third_party/blink/renderer/platform/bindings/script_state.h" + +namespace blink { + +// static +ClipboardItem* ClipboardItem::Create( + const HeapVector<std::pair<String, Member<Blob>>>& items, + ExceptionState& exception_state) { + // Check that incoming dictionary isn't empty. If it is, it's possible that + // Javascript bindings implicitly converted an Object (like a Blob) into {}, + // an empty dictionary. + if (!items.size()) { + exception_state.ThrowTypeError("Empty dictionary argument"); + return nullptr; + } + return MakeGarbageCollected<ClipboardItem>(items); +} + +ClipboardItem::ClipboardItem( + const HeapVector<std::pair<String, Member<Blob>>>& items) + : items_(items) {} + +Vector<String> ClipboardItem::types() const { + Vector<String> types; + types.ReserveInitialCapacity(items_.size()); + for (const auto& item : items_) { + types.push_back(item.first); + } + return types; +} + +ScriptPromise ClipboardItem::getType(ScriptState* script_state, + const String& type) const { + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); + ScriptPromise promise = resolver->Promise(); + + for (const auto& item : items_) { + if (type == item.first) { + resolver->Resolve(item.second); + return promise; + } + } + + resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError, + "The type was not found")); + return promise; +} + +void ClipboardItem::Trace(blink::Visitor* visitor) { + visitor->Trace(items_); + ScriptWrappable::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_item.h b/third_party/blink/renderer/modules/clipboard/clipboard_item.h new file mode 100644 index 0000000..10e71ed --- /dev/null +++ b/third_party/blink/renderer/modules/clipboard/clipboard_item.h
@@ -0,0 +1,41 @@ +// Copyright 2019 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 THIRD_PARTY_BLINK_RENDERER_MODULES_CLIPBOARD_CLIPBOARD_ITEM_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_CLIPBOARD_CLIPBOARD_ITEM_H_ + +#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" +#include "third_party/blink/renderer/core/fileapi/blob.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" +#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" + +namespace blink { + +class ScriptState; + +class ClipboardItem final : public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); + + public: + static ClipboardItem* Create( + const HeapVector<std::pair<String, Member<Blob>>>& items, + ExceptionState& exception_state); + explicit ClipboardItem( + const HeapVector<std::pair<String, Member<Blob>>>& items); + Vector<String> types() const; + ScriptPromise getType(ScriptState* script_state, const String& type) const; + + const HeapVector<std::pair<String, Member<Blob>>>& GetItems() const { + return items_; + } + + void Trace(blink::Visitor*) override; + + private: + HeapVector<std::pair<String, Member<Blob>>> items_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CLIPBOARD_CLIPBOARD_ITEM_H_
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_item.idl b/third_party/blink/renderer/modules/clipboard/clipboard_item.idl new file mode 100644 index 0000000..63a4e9c --- /dev/null +++ b/third_party/blink/renderer/modules/clipboard/clipboard_item.idl
@@ -0,0 +1,18 @@ +// Copyright 2019 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. + +// https://w3c.github.io/clipboard-apis/#clipboard-interface + +[ + Constructor(record<DOMString, Blob> items), + RaisesException=Constructor, + Exposed=Window, + RuntimeEnabled=AsyncClipboard +] interface ClipboardItem { + readonly attribute FrozenArray<DOMString> types; + + [ + CallWith=ScriptState + ] Promise<Blob> getType(DOMString type); +}; \ No newline at end of file
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc index 8b6a630..f819d5dc 100644 --- a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc +++ b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
@@ -61,16 +61,15 @@ // static ScriptPromise ClipboardPromise::CreateForWrite( ScriptState* script_state, - HeapVector<std::pair<String, Member<Blob>>> clipboard_item) { + const HeapVector<Member<ClipboardItem>>& items) { ClipboardPromise* clipboard_promise = MakeGarbageCollected<ClipboardPromise>(script_state); - HeapVector<std::pair<String, Member<Blob>>>* blob_map = - MakeGarbageCollected<HeapVector<std::pair<String, Member<Blob>>>>( - clipboard_item); + HeapVector<Member<ClipboardItem>>* items_copy = + MakeGarbageCollected<HeapVector<Member<ClipboardItem>>>(items); clipboard_promise->GetTaskRunner()->PostTask( FROM_HERE, WTF::Bind(&ClipboardPromise::HandleWrite, - WrapPersistent(clipboard_promise), WrapPersistent(blob_map))); + WrapPersistent(clipboard_promise), WrapPersistent(items_copy))); return clipboard_promise->script_promise_resolver_->Promise(); } @@ -181,24 +180,24 @@ Vector<String> available_types = SystemClipboard::GetInstance().ReadAvailableTypes(); - HeapVector<std::pair<String, Member<Blob>>> clipboard_item; - clipboard_item.ReserveInitialCapacity(available_types.size()); + HeapVector<std::pair<String, Member<Blob>>> items; + items.ReserveInitialCapacity(available_types.size()); for (String& type_to_read : available_types) { std::unique_ptr<ClipboardReader> reader = ClipboardReader::Create(type_to_read); - if (reader) { - clipboard_item.emplace_back(std::move(type_to_read), - reader->ReadFromSystem()); - } + if (reader) + items.emplace_back(std::move(type_to_read), reader->ReadFromSystem()); } - if (!clipboard_item.size()) { + if (!items.size()) { script_promise_resolver_->Reject(DOMException::Create( DOMExceptionCode::kDataError, "No valid data on clipboard.")); return; } - script_promise_resolver_->Resolve(std::move(clipboard_item)); + HeapVector<Member<ClipboardItem>> clipboard_items = { + MakeGarbageCollected<ClipboardItem>(items)}; + script_promise_resolver_->Resolve(clipboard_items); } void ClipboardPromise::HandleReadText() { @@ -220,10 +219,25 @@ } void ClipboardPromise::HandleWrite( - HeapVector<std::pair<String, Member<Blob>>>* clipboard_item) { + HeapVector<Member<ClipboardItem>>* clipboard_items) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - CHECK(clipboard_item); - clipboard_item_ = std::move(*clipboard_item); + CHECK(clipboard_items); + + if (clipboard_items->size() > 1) { + script_promise_resolver_->Reject(DOMException::Create( + DOMExceptionCode::kNotAllowedError, + "Support for multiple ClipboardItems is not implemented.")); + return; + } + if (!clipboard_items->size()) { + // Do nothing if there are no ClipboardItems. + script_promise_resolver_->Resolve(); + return; + } + + // For now, we only process the first ClipboardItem. + ClipboardItem* clipboard_item = (*clipboard_items)[0]; + clipboard_item_data_ = clipboard_item->GetItems(); CheckWritePermission(WTF::Bind(&ClipboardPromise::HandleWriteWithPermission, WrapPersistent(this))); @@ -237,21 +251,11 @@ return; } - // Check that incoming dictionary isn't empty. If it is, it's possible that - // Javascript bindings implicitly converted an Object (like a Blob) into {}, - // an empty dictionary. - if(!clipboard_item_.size()) { - script_promise_resolver_->Reject( - DOMException::Create(DOMExceptionCode::kNotAllowedError, - "No items in input.")); - return; - } - // Check that all blobs have valid MIME types. // Also, Blobs may have a full MIME type with args // (ex. 'text/plain;charset=utf-8'), whereas the type must not have args // (ex. 'text/plain' only), so ensure that Blob->type is contained in type. - for (const auto& type_and_blob : clipboard_item_) { + for (const auto& type_and_blob : clipboard_item_data_) { String type = type_and_blob.first; String type_with_args = type_and_blob.second->type(); if (!ClipboardWriter::IsValidType(type)) { @@ -277,14 +281,15 @@ void ClipboardPromise::WriteNextRepresentation() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); clipboard_writer_.reset(); // The previous write is done. - if (clipboard_representation_index_ == clipboard_item_.size()) { + if (clipboard_representation_index_ == clipboard_item_data_.size()) { SystemClipboard::GetInstance().CommitWrite(); script_promise_resolver_->Resolve(); return; } - const String& type = clipboard_item_[clipboard_representation_index_].first; + const String& type = + clipboard_item_data_[clipboard_representation_index_].first; const Member<Blob>& blob = - clipboard_item_[clipboard_representation_index_].second; + clipboard_item_data_[clipboard_representation_index_].second; clipboard_representation_index_++; DCHECK(!clipboard_writer_); @@ -317,13 +322,13 @@ script_promise_resolver_->Reject(DOMException::Create( DOMExceptionCode::kDataError, "Failed to read or decode Blob for clipboard item type " + - clipboard_item_[clipboard_representation_index_].first + ".")); + clipboard_item_data_[clipboard_representation_index_].first + ".")); } void ClipboardPromise::Trace(blink::Visitor* visitor) { visitor->Trace(script_state_); visitor->Trace(script_promise_resolver_); - visitor->Trace(clipboard_item_); + visitor->Trace(clipboard_item_data_); ContextLifecycleObserver::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_promise.h b/third_party/blink/renderer/modules/clipboard/clipboard_promise.h index 0e37b458..0393172 100644 --- a/third_party/blink/renderer/modules/clipboard/clipboard_promise.h +++ b/third_party/blink/renderer/modules/clipboard/clipboard_promise.h
@@ -13,6 +13,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" #include "third_party/blink/renderer/core/fileapi/blob.h" +#include "third_party/blink/renderer/modules/clipboard/clipboard_item.h" #include "third_party/blink/renderer/modules/clipboard/clipboard_writer.h" namespace blink { @@ -25,15 +26,14 @@ USING_GARBAGE_COLLECTED_MIXIN(ClipboardPromise); public: - explicit ClipboardPromise(ScriptState*); + ClipboardPromise(ScriptState*); virtual ~ClipboardPromise(); // Creates promise to execute Clipboard API functions off the main thread. static ScriptPromise CreateForRead(ScriptState*); static ScriptPromise CreateForReadText(ScriptState*); - static ScriptPromise CreateForWrite( - ScriptState*, - HeapVector<std::pair<String, Member<Blob>>>); + static ScriptPromise CreateForWrite(ScriptState*, + const HeapVector<Member<ClipboardItem>>&); static ScriptPromise CreateForWriteText(ScriptState*, const String&); // For rejections originating from ClipboardWriter. @@ -58,7 +58,7 @@ // Checks Read/Write permission (interacting with PermissionService). void HandleRead(); void HandleReadText(); - void HandleWrite(HeapVector<std::pair<String, Member<Blob>>>*); + void HandleWrite(HeapVector<Member<ClipboardItem>>*); void HandleWriteText(const String&); // Reads/Writes after permission check. @@ -80,7 +80,7 @@ // Only for use in writeText(). String plain_text_; - HeapVector<std::pair<String, Member<Blob>>> clipboard_item_; + HeapVector<std::pair<String, Member<Blob>>> clipboard_item_data_; // Index of clipboard representation currently being processed. wtf_size_t clipboard_representation_index_;
diff --git a/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_inputs.idl b/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_inputs.idl index da8f02e..801caf8e 100644 --- a/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_inputs.idl +++ b/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_inputs.idl
@@ -11,4 +11,6 @@ sequence<CableAuthenticationData> cableAuthentication; // https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html#sctn-hmac-secret-extension boolean hmacCreateSecret; + // https://w3c.github.io/webauthn/#sctn-uvm-extension + boolean uvm; };
diff --git a/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_outputs.idl b/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_outputs.idl index 582d38e..ca1aa2e3 100644 --- a/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_outputs.idl +++ b/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_outputs.idl
@@ -3,9 +3,13 @@ // found in the LICENSE file. // https://w3c.github.io/webauthn/#dictdef-authenticationextensionsclientoutputs +//typedef sequence<unsigned long> UvmEntry +typedef sequence<sequence<unsigned long>> UvmEntries; dictionary AuthenticationExtensionsClientOutputs { boolean appid; // https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html#sctn-hmac-secret-extension boolean hmacCreateSecret; + // https://w3c.github.io/webauthn/#sctn-uvm-extension + UvmEntries uvm; };
diff --git a/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc b/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc index 9c5afa0..8101bac 100644 --- a/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc +++ b/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include <utility> +#include "build/build_config.h" #include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h" #include "third_party/blink/renderer/modules/credentialmanager/authenticator_selection_criteria.h" #include "third_party/blink/renderer/modules/credentialmanager/cable_authentication_data.h" @@ -448,6 +449,11 @@ if (extensions->hasHmacCreateSecret()) { mojo_options->hmac_create_secret = extensions->hmacCreateSecret(); } +#if defined(OS_ANDROID) + if (extensions->hasUvm()) { + mojo_options->user_verification_methods = extensions->uvm(); + } +#endif } return mojo_options; @@ -531,6 +537,11 @@ } mojo_options->cable_authentication_data = std::move(mojo_data); } +#if defined(OS_ANDROID) + if (extensions->hasUvm()) { + mojo_options->user_verification_methods = extensions->uvm(); + } +#endif } return mojo_options;
diff --git a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc index aab4921..56d1922 100644 --- a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc +++ b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "build/build_config.h" #include "third_party/blink/public/mojom/credentialmanager/credential_manager.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" @@ -319,6 +320,20 @@ buffer.size()); } +#if defined(OS_ANDROID) +Vector<Vector<uint32_t>> UvmEntryToArray( + const Vector<mojom::blink::UvmEntryPtr>& user_verification_methods) { + Vector<Vector<uint32_t>> uvm_array; + for (const auto& uvm : user_verification_methods) { + Vector<uint32_t> uvmEntry = {uvm->user_verification_method, + uvm->key_protection_type, + uvm->matcher_protection_type}; + uvm_array.push_back(uvmEntry); + } + return uvm_array; +} +#endif + void OnMakePublicKeyCredentialComplete( std::unique_ptr<ScopedPromiseResolver> scoped_resolver, AuthenticatorStatus status, @@ -351,6 +366,12 @@ if (credential->echo_hmac_create_secret) { extension_outputs->setHmacCreateSecret(credential->hmac_create_secret); } +#if defined(OS_ANDROID) + if (credential->echo_user_verification_methods) { + extension_outputs->setUvm( + UvmEntryToArray(std::move(*credential->user_verification_methods))); + } +#endif resolver->Resolve(MakeGarbageCollected<PublicKeyCredential>( credential->info->id, raw_id, authenticator_response, extension_outputs)); @@ -398,6 +419,12 @@ if (credential->echo_appid_extension) { extension_outputs->setAppid(credential->appid_extension); } +#if defined(OS_ANDROID) + if (credential->echo_user_verification_methods) { + extension_outputs->setUvm( + UvmEntryToArray(std::move(*credential->user_verification_methods))); + } +#endif resolver->Resolve(MakeGarbageCollected<PublicKeyCredential>( credential->info->id, raw_id, authenticator_response, extension_outputs));
diff --git a/third_party/blink/renderer/modules/imagecapture/point_2d.idl b/third_party/blink/renderer/modules/imagecapture/point_2d.idl index b77caf6..6efbbd02 100644 --- a/third_party/blink/renderer/modules/imagecapture/point_2d.idl +++ b/third_party/blink/renderer/modules/imagecapture/point_2d.idl
@@ -5,6 +5,6 @@ // https://w3c.github.io/mediacapture-image/#point2d-section dictionary Point2D { - float x = 0.0; - float y = 0.0; + double x = 0.0; + double y = 0.0; };
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_forward.svg b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_forward.svg index a286740d..09a9805 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_forward.svg +++ b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_forward.svg
@@ -1,4 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 48 48" fill="#FFFFFF"> - <path d="M8 36l17-12L8 12v24zm18-24v24l17-12-17-12z"/> - <path d="M0 0h48v48H0z" fill="none"/> -</svg> +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M15 9.86L18.03 12 15 14.14V9.86m-9 0L9.03 12 6 14.14V9.86M13 6v12l8.5-6L13 6zM4 6v12l8.5-6L4 6z"/><path fill="none" d="M0 0h24v24H0zm0 0h24v24H0zm0 0h24v24H0z"/></svg>
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_rewind.svg b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_rewind.svg index d012f4cb..384fdc4 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_rewind.svg +++ b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_rewind.svg
@@ -1,4 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 48 48" fill="#FFFFFF"> - <path d="M22 36V12L5 24l17 12zm1-12l17 12V12L23 24z"/> - <path d="M0 0h48v48H0z" fill="none"/> -</svg> +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M18 9.86v4.28L14.97 12 18 9.86m-9 0v4.28L5.97 12 9 9.86M20 6l-8.5 6 8.5 6V6zm-9 0l-8.5 6 8.5 6V6z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_mid_background.svg b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_mid_background.svg new file mode 100644 index 0000000..77cf41f --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_mid_background.svg
@@ -0,0 +1,4 @@ +<svg width="104" height="104" viewBox="0 0 104 104" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path opacity="0.85" fill-rule="evenodd" clip-rule="evenodd" d="M32 0C14.3269 0 0 14.3269 0 32V72C0 89.6731 14.3269 104 32 104H72C89.6731 104 104 89.6731 104 72V32C104 14.3269 89.6731 0 72 0H32ZM46 30C37.1634 30 30 37.1634 30 46V58C30 66.8366 37.1634 74 46 74H58C66.8366 74 74 66.8366 74 58V46C74 37.1634 66.8366 30 58 30H46Z" fill="#202124"/> +<rect opacity="0.85" x="32" y="32" width="40" height="40" rx="14" fill="#202124"/> +</svg>
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_pause.svg b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_pause.svg index 5ac5ff20..bd17d16 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_pause.svg +++ b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_pause.svg
@@ -1,4 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="#FFFFFF"> - <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/> - <path d="M0 0h24v24H0z" fill="none"/> -</svg> +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M19 19h-6V5h6v14zm-4-2h2V7h-2v10zm-4 2H5V5h6v14zm-4-2h2V7H7v10z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_play_arrow.svg b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_play_arrow.svg index 80296d81..10c1d08 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_play_arrow.svg +++ b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_play_arrow.svg
@@ -1,4 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="#FFFFFF"> - <path d="M8 5v14l11-7z"/> - <path d="M0 0h24v24H0z" fill="none"/> -</svg> +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M10 8.64L15.27 12 10 15.36V8.64M8 5v14l11-7L8 5z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_down.svg b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_down.svg index 156d652..67af7988 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_down.svg +++ b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_down.svg
@@ -1,4 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 48 48" fill="#FFFFFF"> - <path d="M37 24c0-3.53-2.04-6.58-5-8.05v16.11c2.96-1.48 5-4.53 5-8.06zm-27-6v12h8l10 10V8L18 18h-8z"/> - <path d="M0 0h48v48H0z" fill="none"/> -</svg> +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M16 7.97v8.05c1.48-.73 2.5-2.25 2.5-4.02 0-1.77-1.02-3.29-2.5-4.03zM5 9v6h4l5 5V4L9 9H5zm7-.17v6.34L9.83 13H7v-2h2.83L12 8.83z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_up.svg b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_up.svg index 4187bafa..9c82fbc 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_up.svg +++ b/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_up.svg
@@ -1,4 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 48 48" fill="#FFFFFF"> - <path d="M6 18v12h8l10 10V8L14 18H6zm27 6c0-3.53-2.04-6.58-5-8.05v16.11c2.96-1.48 5-4.53 5-8.06zM28 6.46v4.13c5.78 1.72 10 7.07 10 13.41s-4.22 11.69-10 13.41v4.13c8.01-1.82 14-8.97 14-17.54S36.01 8.28 28 6.46z"/> - <path d="M0 0h48v48H0z" fill="none"/> -</svg> +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M3 9v6h4l5 5V4L7 9H3zm7-.17v6.34L7.83 13H5v-2h2.83L10 8.83zM16.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77 0-4.28-2.99-7.86-7-8.77z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/resources/mediaControlsTouchless.css b/third_party/blink/renderer/modules/media_controls/touchless/resources/mediaControlsTouchless.css index 271fb96..3a4ddb0 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/resources/mediaControlsTouchless.css +++ b/third_party/blink/renderer/modules/media_controls/touchless/resources/mediaControlsTouchless.css
@@ -26,7 +26,10 @@ video::-internal-media-controls-touchless-overlay { width: 104px; height: 104px; - background-color: rgba(32, 33, 36, .9); + background-image: -webkit-image-set(url(ic_mid_background.svg) 1x); + background-size: 104px; + background-position: center; + background-repeat: no-repeat; position: absolute; z-index: 1; margin: auto; @@ -34,7 +37,6 @@ left: 0; bottom: 0; right: 0; - border-radius: 24px; } video::-internal-media-controls-touchless-volume-up-button { @@ -51,7 +53,7 @@ video::-internal-media-controls-touchless-seek-backward-button { width: 30px; height: 30px; - margin-top: 7px /* (play button height + (2*play button border) - height) / 2 */; + margin-top: 7px /* (play button height - height) / 2 */; float: left; background-image: -webkit-image-set(url(ic_fast_rewind.svg) 1x); background-size: 20px; @@ -61,13 +63,11 @@ video::-internal-media-controls-touchless-play-button { - width: 40px; - height: 40px; - border: 2px solid white; + width: 44px; + height: 44px; background-position: center; background-size: 24px; background-repeat: no-repeat; - border-radius: 16px; float: left; } @@ -82,7 +82,7 @@ video::-internal-media-controls-touchless-seek-forward-button { width: 30px; height: 30px; - margin-top: 7px /* (play button height + (2*play button border) - height) / 2 */; + margin-top: 7px /* (play button height - height) / 2 */; float: left; background-image: -webkit-image-set(url(ic_fast_forward.svg) 1x); background-size: 20px; @@ -103,6 +103,7 @@ } video::-internal-media-controls-touchless-bottom-container { + position: absolute; display: flex; flex-direction: column; justify-content: flex-end;
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni index a943f08..0c35474 100644 --- a/third_party/blink/renderer/modules/modules_idl_files.gni +++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -96,6 +96,7 @@ "canvas/imagebitmap/image_bitmap_rendering_context.idl", "canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.idl", "clipboard/clipboard.idl", + "clipboard/clipboard_item.idl", "contacts_picker/contacts_manager.idl", "cookie_store/cookie_change_event.idl", "cookie_store/cookie_store.idl", @@ -819,7 +820,6 @@ "xr/xr_reference_space_event_init.idl", "xr/xr_reference_space_options.idl", "xr/xr_render_state_init.idl", - "xr/xr_session_creation_options.idl", "xr/xr_session_event_init.idl", "xr/xr_webgl_layer_init.idl", ],
diff --git a/third_party/blink/renderer/modules/xr/xr.cc b/third_party/blink/renderer/modules/xr/xr.cc index f8ecd32..52dbc23 100644 --- a/third_party/blink/renderer/modules/xr/xr.cc +++ b/third_party/blink/renderer/modules/xr/xr.cc
@@ -216,7 +216,7 @@ } ScriptPromise XR::requestSession(ScriptState* script_state, - const XRSessionCreationOptions* options) { + const String& mode) { LocalFrame* frame = GetFrame(); if (!frame || !frame->GetDocument()) { // Reject if the frame is inaccessible. @@ -226,9 +226,9 @@ } Document* doc = frame->GetDocument(); - XRSession::SessionMode mode = stringToSessionMode(options->mode()); - bool is_immersive = mode == XRSession::kModeImmersiveVR || - mode == XRSession::kModeImmersiveAR; + XRSession::SessionMode session_mode = stringToSessionMode(mode); + bool is_immersive = session_mode == XRSession::kModeImmersiveVR || + session_mode == XRSession::kModeImmersiveAR; if (is_immersive && !did_log_request_immersive_session_) { ukm::builders::XR_WebXR(GetSourceId()) @@ -249,7 +249,7 @@ // If we no longer have a valid service connection reject the request, unless // it was for an inline mode. In which case, we'll end up creating the // session in OnRequestSessionReturned. - if (!service_ && mode != XRSession::kModeInline) { + if (!service_ && session_mode != XRSession::kModeInline) { return ScriptPromise::RejectWithDOMException( script_state, DOMException::Create(DOMExceptionCode::kNotFoundError, kNoDevicesMessage)); @@ -264,14 +264,14 @@ // All immersive and AR sessions require a user gesture. bool has_user_activation = LocalFrame::HasTransientUserActivation(frame); - if ((is_immersive || mode == XRSession::kModeInlineAR) && + if ((is_immersive || session_mode == XRSession::kModeInlineAR) && !has_user_activation) { return ScriptPromise::RejectWithDOMException( script_state, DOMException::Create(DOMExceptionCode::kSecurityError, kRequestRequiresUserActivation)); } - if (mode == XRSession::kModeInlineAR) { + if (session_mode == XRSession::kModeInlineAR) { doc->AddConsoleMessage(ConsoleMessage::Create( mojom::ConsoleMessageSource::kOther, mojom::ConsoleMessageLevel::kWarning, @@ -282,7 +282,7 @@ ScriptPromise promise = resolver->Promise(); PendingSessionQuery* query = - MakeGarbageCollected<PendingSessionQuery>(resolver, mode); + MakeGarbageCollected<PendingSessionQuery>(resolver, session_mode); query->has_user_activation = has_user_activation; if (!device_) {
diff --git a/third_party/blink/renderer/modules/xr/xr.h b/third_party/blink/renderer/modules/xr/xr.h index 80cb19d..9c04d8f 100644 --- a/third_party/blink/renderer/modules/xr/xr.h +++ b/third_party/blink/renderer/modules/xr/xr.h
@@ -13,7 +13,6 @@ #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" #include "third_party/blink/renderer/core/page/focus_changed_observer.h" #include "third_party/blink/renderer/modules/xr/xr_session.h" -#include "third_party/blink/renderer/modules/xr/xr_session_creation_options.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/forward.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -40,7 +39,7 @@ DEFINE_ATTRIBUTE_EVENT_LISTENER(devicechange, kDevicechange) ScriptPromise supportsSessionMode(ScriptState*, const String&); - ScriptPromise requestSession(ScriptState*, const XRSessionCreationOptions*); + ScriptPromise requestSession(ScriptState*, const String&); XRFrameProvider* frameProvider();
diff --git a/third_party/blink/renderer/modules/xr/xr.idl b/third_party/blink/renderer/modules/xr/xr.idl index 3301a0e8..a49f200 100644 --- a/third_party/blink/renderer/modules/xr/xr.idl +++ b/third_party/blink/renderer/modules/xr/xr.idl
@@ -10,5 +10,5 @@ ] interface XR : EventTarget { attribute EventHandler ondevicechange; [CallWith=ScriptState, MeasureAs=XRSupportsSession] Promise<void> supportsSessionMode(XRSessionMode mode); - [CallWith=ScriptState, MeasureAs=XRRequestSession] Promise<XRSession> requestSession([PermissiveDictionaryConversion] optional XRSessionCreationOptions options); + [CallWith=ScriptState, MeasureAs=XRRequestSession] Promise<XRSession> requestSession(XRSessionMode mode); };
diff --git a/third_party/blink/renderer/modules/xr/xr_session_creation_options.idl b/third_party/blink/renderer/modules/xr/xr_session_creation_options.idl deleted file mode 100644 index fccbf19..0000000 --- a/third_party/blink/renderer/modules/xr/xr_session_creation_options.idl +++ /dev/null
@@ -1,8 +0,0 @@ -// 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. - -// https://immersive-web.github.io/webxr/#xrsessioncreationoptions-interface -dictionary XRSessionCreationOptions { - XRSessionMode mode = "inline"; -};
diff --git a/third_party/blink/renderer/platform/fonts/font.cc b/third_party/blink/renderer/platform/fonts/font.cc index 20430be5..ff783ac8 100644 --- a/third_party/blink/renderer/platform/fonts/font.cc +++ b/third_party/blink/renderer/platform/fonts/font.cc
@@ -164,15 +164,6 @@ const NGTextFragmentPaintInfo& text_info, const FloatPoint& point, float device_scale_factor, - const cc::PaintFlags& flags) const { - DrawText(canvas, text_info, point, device_scale_factor, - cc::NodeHolder::EmptyNodeHolder(), flags); -} - -void Font::DrawText(cc::PaintCanvas* canvas, - const NGTextFragmentPaintInfo& text_info, - const FloatPoint& point, - float device_scale_factor, const cc::NodeHolder& node_holder, const cc::PaintFlags& flags) const { // Don't draw anything while we are using custom fonts that are in the process
diff --git a/third_party/blink/renderer/platform/fonts/font.h b/third_party/blink/renderer/platform/fonts/font.h index df8659e..218fb5cd0 100644 --- a/third_party/blink/renderer/platform/fonts/font.h +++ b/third_party/blink/renderer/platform/fonts/font.h
@@ -100,11 +100,6 @@ const NGTextFragmentPaintInfo&, const FloatPoint&, float device_scale_factor, - const cc::PaintFlags&) const; - void DrawText(cc::PaintCanvas*, - const NGTextFragmentPaintInfo&, - const FloatPoint&, - float device_scale_factor, const cc::NodeHolder&, const cc::PaintFlags&) const; bool DrawBidiText(cc::PaintCanvas*,
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.cc b/third_party/blink/renderer/platform/graphics/graphics_context.cc index 73b15d19..cc5a1df 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -762,33 +762,16 @@ } } -template <typename TextPaintInfo> -void GraphicsContext::DrawTextInternal(const Font& font, - const TextPaintInfo& text_info, - const FloatPoint& point, - const PaintFlags& flags, - const cc::NodeHolder& node_holder) { - if (ContextDisabled()) - return; - - font.DrawText(canvas_, text_info, point, device_scale_factor_, node_holder, - DarkModeFlags(this, flags)); -} - void GraphicsContext::DrawText(const Font& font, const TextRunPaintInfo& text_info, const FloatPoint& point, const PaintFlags& flags, const cc::NodeHolder& node_holder) { - DrawTextInternal(font, text_info, point, flags, node_holder); -} + if (ContextDisabled()) + return; -void GraphicsContext::DrawText(const Font& font, - const NGTextFragmentPaintInfo& text_info, - const FloatPoint& point, - const PaintFlags& flags, - const cc::NodeHolder& node_holder) { - DrawTextInternal(font, text_info, point, flags, node_holder); + font.DrawText(canvas_, text_info, point, device_scale_factor_, node_holder, + DarkModeFlags(this, flags)); } template <typename DrawTextFunc>
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.h b/third_party/blink/renderer/platform/graphics/graphics_context.h index bc9f657..d1ad6e56 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.h +++ b/third_party/blink/renderer/platform/graphics/graphics_context.h
@@ -267,16 +267,13 @@ const FloatPoint&, const cc::NodeHolder&); + // TODO(layout-dev): This method is only used by SVGInlineTextBoxPainter, see + // if we can change that to use the four parameter version above. void DrawText(const Font&, const TextRunPaintInfo&, const FloatPoint&, const PaintFlags&, const cc::NodeHolder&); - void DrawText(const Font&, - const NGTextFragmentPaintInfo&, - const FloatPoint&, - const PaintFlags&, - const cc::NodeHolder&); void DrawEmphasisMarks(const Font&, const TextRunPaintInfo&, @@ -412,13 +409,6 @@ void DrawTextInternal(const Font&, const TextPaintInfo&, const FloatPoint&, - const PaintFlags&, - const cc::NodeHolder&); - - template <typename TextPaintInfo> - void DrawTextInternal(const Font&, - const TextPaintInfo&, - const FloatPoint&, const cc::NodeHolder&); template <typename TextPaintInfo>
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG index d82d77396..03715c1 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -236,7 +236,6 @@ crbug.com/591099 external/wpt/css/cssom-view/elementsFromPoint-inline-vrl-ltr.html [ Pass ] crbug.com/591099 external/wpt/css/cssom-view/elementsFromPoint-inline-vrl-rtl.html [ Pass ] crbug.com/953479 external/wpt/css/cssom-view/offsetTopLeftEmptyInline.html [ Failure ] -crbug.com/953572 external/wpt/css/cssom-view/offsetTopLeftInlineMultiLine.html [ Failure ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-horiz-002.xhtml [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-011.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ib-split/emptyspan-1.html [ Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index e9b15146..1e6d342 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3076,6 +3076,9 @@ crbug.com/952266 virtual/omt-worker-fetch/external/wpt/workers/modules/dedicated-worker-options-credentials.html [ Timeout ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/client-navigate.https.html [ Timeout ] +crbug.com/626703 external/wpt/service-workers/service-worker/client-navigate.https.html [ Timeout ] +crbug.com/626703 virtual/outofblink-cors/external/wpt/service-workers/service-worker/client-navigate.https.html [ Timeout ] crbug.com/626703 external/wpt/css/css-text/overflow-wrap/overflow-wrap-cluster-002.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/overflow-wrap/overflow-wrap-cluster-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/overflow-wrap/overflow-wrap-normal-keep-all-001.html [ Failure ] @@ -3260,11 +3263,9 @@ crbug.com/626703 [ Mac10.10 ] external/wpt/content-security-policy/frame-ancestors/frame-ancestors-self-block.html [ Timeout ] crbug.com/626703 [ Mac10.10 ] external/wpt/fetch/api/cors/cors-redirect.any.html [ Timeout ] crbug.com/626703 [ Mac10.10 ] external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-self-block.html [ Timeout ] -crbug.com/626703 [ Mac10.10 ] virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-redirect-credentials.any.worker.html [ Timeout ] crbug.com/626703 [ Mac10.10 ] virtual/not-site-per-process/external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-same-origin-domain.sub.html [ Timeout ] crbug.com/626703 [ Mac10.10 ] external/wpt/html/dom/self-origin.sub.html [ Timeout ] crbug.com/626703 [ Mac10.10 ] external/wpt/fetch/api/cors/cors-redirect-preflight.any.html [ Timeout ] -crbug.com/626703 [ Mac10.10 ] virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-cookies-redirect.any.worker.html [ Timeout ] crbug.com/626703 [ Mac10.10 ] external/wpt/content-security-policy/frame-ancestors/frame-ancestors-url-block.html [ Timeout ] crbug.com/626703 [ Retina Mac ] external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-width-height.html [ Crash Timeout ] crbug.com/626703 external/wpt/css/css-values/ic-unit-010.html [ Failure ] @@ -5865,8 +5866,8 @@ crbug.com/921151 [ Linux ] http/tests/security/mixedContent/insecure-iframe-with-hsts.https.html [ Failure Pass ] crbug.com/921151 [ Linux ] virtual/outofblink-cors/http/tests/security/mixedContent/insecure-iframe-with-hsts.https.html [ Failure Pass ] -# Writable Files tests depend on mojo interfaces that are only exposed behind a flag. -crbug.com/922735 fast/filesystem/writable-files/ [ Skip ] +# Native Filesystem tests depend on mojo interfaces that are only exposed behind a flag. +crbug.com/853326 external/wpt/native-file-system/ [ Skip ] # These fail (some time out, some are flaky, etc.) when landing valid changes to Mojo bindings # dispatch timing. Many of them seem to fail for different reasons, but pretty consistently in most
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 0a5754b..af43d3ae 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -1051,5 +1051,10 @@ "prefix": "insecure-device-sensor-events", "base": "http/tests/security/powerfulFeatureRestrictions/", "args": ["--disable-features=RestrictDeviceSensorEventsToSecureContexts"] + }, + { + "prefix": "native-file-system", + "base": "external/wpt/native-file-system", + "args": ["--enable-features=NativeFilesystemAPI"] } ]
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/README.md b/third_party/blink/web_tests/clipboard/async-clipboard/README.md index 619b08a4..9d1a0fd8 100644 --- a/third_party/blink/web_tests/clipboard/async-clipboard/README.md +++ b/third_party/blink/web_tests/clipboard/async-clipboard/README.md
@@ -1,4 +1,4 @@ -spec: https://w3c.github.io/clipboard-apis/ +spec: https://w3c.github.io/clipboard-apis/#async-clipboard-api This directory contains async clipboard tests automated through use of Chrome-specific test helper `permissions-helper.js`. Related tests not requiring
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/async-navigator-clipboard-basics.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/async-navigator-clipboard-basics.https.html index dabf1d6..d8628e2 100644 --- a/third_party/blink/web_tests/clipboard/async-clipboard/async-navigator-clipboard-basics.https.html +++ b/third_party/blink/web_tests/clipboard/async-clipboard/async-navigator-clipboard-basics.https.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>Async Clipboard input type validation tests</title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../http/tests/resources/permissions-helper.js"></script> @@ -21,33 +22,44 @@ promise_test(async () => { await getPermissions(); const blob = new Blob(['hello'], {type: 'text/plain'}); - await navigator.clipboard.write({'text/plain': blob}); -}, 'navigator.clipboard.write({string : text/plain Blob}) succeeds'); + const item = new ClipboardItem({'text/plain': blob}); + + await navigator.clipboard.write([item]); +}, 'navigator.clipboard.write([text/plain ClipboardItem]) succeeds'); promise_test(async t => { await getPermissions(); - await promise_rejects(t, new TypeError(), - navigator.clipboard.write()); -}, 'navigator.clipboard.write() fails (expect {string : Blob})'); + const blob1 = new Blob(['hello'], {type: 'text/plain'}); + const blob2 = new Blob(['world'], {type: 'text/plain'}); + + const item1 = new ClipboardItem({'text/plain': blob1}); + const item2 = new ClipboardItem({'text/plain': blob2}); + + await promise_rejects(t, "NotAllowedError", + navigator.clipboard.write([item1, item2])); +}, 'navigator.clipboard.write([>1 ClipboardItems]) fails (not implemented)'); promise_test(async t => { await getPermissions(); - await promise_rejects(t, new TypeError(), - navigator.clipboard.write(null)); -}, 'navigator.clipboard.write(null) fails (expect {string : Blob})'); + await promise_rejects(t, new TypeError(), navigator.clipboard.write()); +}, 'navigator.clipboard.write() fails (expect [ClipboardItem])'); + +promise_test(async t => { + await getPermissions(); + await promise_rejects(t, new TypeError(), navigator.clipboard.write(null)); +}, 'navigator.clipboard.write(null) fails (expect [ClipboardItem])'); promise_test(async t => { await getPermissions(); await promise_rejects(t, new TypeError(), navigator.clipboard.write('Bad string')); -}, 'navigator.clipboard.write(DOMString) fails (expect {string : Blob})'); +}, 'navigator.clipboard.write(DOMString) fails (expect [ClipboardItem])'); promise_test(async t => { await getPermissions(); const blob = new Blob(['hello'], {type: 'text/plain'}); - await promise_rejects(t, 'NotAllowedError', - navigator.clipboard.write(blob)); -}, 'navigator.clipboard.write(Blob) fails (expect {string : Blob})'); + await promise_rejects(t, new TypeError(), navigator.clipboard.write(blob)); +}, 'navigator.clipboard.write(Blob) fails (expect [ClipboardItem])'); promise_test(async () => { await getPermissions(); @@ -64,6 +76,7 @@ await getPermissions(); const result = await navigator.clipboard.read(); assert_true(result instanceof Object); + assert_true(result[0] instanceof ClipboardItem); }, 'navigator.clipboard.read() succeeds'); promise_test(async () => {
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-blobtext.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-blobtext.https.html index f93359f..10d640f7 100644 --- a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-blobtext.https.html +++ b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-blobtext.https.html
@@ -1,8 +1,10 @@ <!DOCTYPE html> <meta charset="utf-8"> <title> - Async Clipboard write ([text/plain Blob]) -> read ([text/plain Blob]) tests + Async Clipboard write ([text/plain ClipboardItem]) -> + read ([text/plain ClipboardItem]) tests </title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../http/tests/resources/permissions-helper.js"></script> @@ -13,11 +15,15 @@ await PermissionsHelper.setPermission('clipboard-write', 'granted'); const blobInput = new Blob([textInput], {type: 'text/plain'}); + const clipboardItemInput = new ClipboardItem({'text/plain': blobInput}); - await navigator.clipboard.write({'text/plain': blobInput}); - const blobsOutput = await navigator.clipboard.read(); - assert_equals(Object.keys(blobsOutput).length, 1); - const blobOutput = blobsOutput['text/plain']; + await navigator.clipboard.write([clipboardItemInput]); + const clipboardItems = await navigator.clipboard.read(); + assert_equals(clipboardItems.length, 1); + const clipboardItemOutput = clipboardItems[0]; + assert_true(clipboardItemOutput instanceof ClipboardItem); + assert_equals(clipboardItemOutput.types.length, 1); + const blobOutput = await clipboardItemOutput.getType('text/plain'); assert_equals(blobOutput.type, 'text/plain'); const textOutput = await (new Response(blobOutput)).text(); @@ -25,6 +31,6 @@ }, 'Verify write and read clipboard given text: ' + textInput); } -readWriteTest('Clipboard write ([text/plain Blob]) -> read ([text/plain Blob]) test'); +readWriteTest('Clipboard write ([text/plain ClipboardItem]) -> read ([text/plain ClipboardItem]) test'); readWriteTest('non-Latin1 text encoding test データ'); </script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-text.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-text.https.html index dcc5645..0f88633 100644 --- a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-text.https.html +++ b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-text.https.html
@@ -1,6 +1,9 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>Async Clipboard write ([text/plain Blob]) -> readText tests</title> +<title> + Async Clipboard write ([text/plain ClipboardItem]) -> readText tests +</title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../http/tests/resources/permissions-helper.js"></script> @@ -11,14 +14,15 @@ await PermissionsHelper.setPermission('clipboard-write', 'granted'); const blobInput = new Blob([textInput], {type: 'text/plain'}); + const clipboardItem = new ClipboardItem({'text/plain': blobInput}); - await navigator.clipboard.write({'text/plain': blobInput}); + await navigator.clipboard.write([clipboardItem]); const textOutput = await navigator.clipboard.readText(); assert_equals(textOutput, textInput); }, 'Verify write and read clipboard given text: ' + textInput); } -readWriteTest('Clipboard write ([text/plain Blob]) -> read text test'); +readWriteTest('Clipboard write ([text/plain ClipboardItem]) -> read text test'); readWriteTest('non-Latin1 text encoding test データ'); </script>
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-text-read-blobtext.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-text-read-blobtext.https.html index ad41560..177ff34 100644 --- a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-text-read-blobtext.https.html +++ b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-text-read-blobtext.https.html
@@ -1,6 +1,9 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>Async Clipboard writeText -> read ([text/plain Blob]) tests</title> +<title> + Async Clipboard writeText -> read ([text/plain ClipboardItem]) tests +</title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../http/tests/resources/permissions-helper.js"></script> @@ -11,9 +14,12 @@ await PermissionsHelper.setPermission('clipboard-write', 'granted'); await navigator.clipboard.writeText(textInput); - const blobsOutput = await navigator.clipboard.read(); - assert_equals(Object.keys(blobsOutput).length, 1); - const blobOutput = blobsOutput['text/plain']; + const clipboardItems = await navigator.clipboard.read(); + assert_equals(clipboardItems.length, 1); + const clipboardItem = clipboardItems[0]; + assert_true(clipboardItem instanceof ClipboardItem); + assert_equals(clipboardItem.types.length, 1); + const blobOutput = await clipboardItem.getType('text/plain'); assert_equals(blobOutput.type, 'text/plain'); const textOutput = await (new Response(blobOutput)).text(); @@ -21,6 +27,6 @@ }, 'Verify write and read clipboard given text: ' + textInput); } -readWriteTest('Clipboard write text -> read ([text/plain Blob]) test'); +readWriteTest('Clipboard write text -> read ([text/plain ClipboardItem]) test'); readWriteTest('non-Latin1 text encoding test データ'); </script>
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-text-read-text.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-text-read-text.https.html index f20545f5..80800b9 100644 --- a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-text-read-text.https.html +++ b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-text-read-text.https.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>Async Clipboard writeText -> readText tests</title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../http/tests/resources/permissions-helper.js"></script>
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/readtext-denied.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/readtext-denied.https.html index 47fb031..1f5a9bc 100644 --- a/third_party/blink/web_tests/clipboard/async-clipboard/readtext-denied.https.html +++ b/third_party/blink/web_tests/clipboard/async-clipboard/readtext-denied.https.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>navigator.clipboard.readText() fails when permission denied</title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../http/tests/resources/permissions-helper.js"></script>
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/readtext-granted.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/readtext-granted.https.html index d38dc44b..ab90b95f 100644 --- a/third_party/blink/web_tests/clipboard/async-clipboard/readtext-granted.https.html +++ b/third_party/blink/web_tests/clipboard/async-clipboard/readtext-granted.https.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>navigator.clipboard.readText() succeeds when permission granted</title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../http/tests/resources/permissions-helper.js"></script>
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/writetext-denied.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/writetext-denied.https.html index 808df44..6077273 100644 --- a/third_party/blink/web_tests/clipboard/async-clipboard/writetext-denied.https.html +++ b/third_party/blink/web_tests/clipboard/async-clipboard/writetext-denied.https.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>navigator.clipboard.writeText() fails when permission denied</title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../http/tests/resources/permissions-helper.js"></script>
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/writetext-granted.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/writetext-granted.https.html index a96a273..9409030 100644 --- a/third_party/blink/web_tests/clipboard/async-clipboard/writetext-granted.https.html +++ b/third_party/blink/web_tests/clipboard/async-clipboard/writetext-granted.https.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>navigator.clipboard.writeText() succeeds when permission granted</title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../http/tests/resources/permissions-helper.js"></script>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json index 5c230ed..bae4e58 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -163672,6 +163672,16 @@ {} ] ], + "fetch/api/basic/mode-same-origin.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/basic/referrer.any.worker-expected.txt": [ + [ + {} + ] + ], "fetch/api/basic/request-upload.any-expected.txt": [ [ {} @@ -163682,6 +163692,21 @@ {} ] ], + "fetch/api/cors/cors-basic.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/cors/cors-cookies-redirect.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/cors/cors-cookies.any.worker-expected.txt": [ + [ + {} + ] + ], "fetch/api/cors/cors-filtering-expected.txt": [ [ {} @@ -163712,6 +163737,26 @@ {} ] ], + "fetch/api/cors/cors-no-preflight.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/cors/cors-origin.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/cors/cors-preflight-cache.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/cors/cors-preflight-not-cors-safelisted.any.worker-expected.txt": [ + [ + {} + ] + ], "fetch/api/cors/cors-preflight-redirect.any-expected.txt": [ [ {} @@ -163722,6 +163767,41 @@ {} ] ], + "fetch/api/cors/cors-preflight-referrer.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/cors/cors-preflight-star.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/cors/cors-preflight-status.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/cors/cors-preflight.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/cors/cors-redirect-credentials.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/cors/cors-redirect-preflight.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/cors/cors-redirect.any.worker-expected.txt": [ + [ + {} + ] + ], "fetch/api/cors/resources/corspreflight.js": [ [ {} @@ -163842,6 +163922,11 @@ {} ] ], + "fetch/api/redirect/redirect-back-to-original-origin.any.worker-expected.txt": [ + [ + {} + ] + ], "fetch/api/redirect/redirect-empty-location-expected.txt": [ [ {} @@ -163882,6 +163967,26 @@ {} ] ], + "fetch/api/redirect/redirect-mode.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/redirect/redirect-origin.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/redirect/redirect-referrer.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/api/redirect/redirect-to-dataurl.any.worker-expected.txt": [ + [ + {} + ] + ], "fetch/api/request/destination/resources/dummy": [ [ {} @@ -164427,6 +164532,31 @@ {} ] ], + "fetch/cross-origin-resource-policy/fetch.any.sharedworker-expected.txt": [ + [ + {} + ] + ], + "fetch/cross-origin-resource-policy/fetch.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/cross-origin-resource-policy/fetch.https.any.serviceworker-expected.txt": [ + [ + {} + ] + ], + "fetch/cross-origin-resource-policy/fetch.https.any.sharedworker-expected.txt": [ + [ + {} + ] + ], + "fetch/cross-origin-resource-policy/fetch.https.any.worker-expected.txt": [ + [ + {} + ] + ], "fetch/cross-origin-resource-policy/resources/green.png": [ [ {} @@ -164462,6 +164592,16 @@ {} ] ], + "fetch/cross-origin-resource-policy/scheme-restriction.any.worker-expected.txt": [ + [ + {} + ] + ], + "fetch/cross-origin-resource-policy/syntax.any.worker-expected.txt": [ + [ + {} + ] + ], "fetch/data-urls/README.md": [ [ {} @@ -164582,6 +164722,11 @@ {} ] ], + "fetch/origin/no-cors.any.worker-expected.txt": [ + [ + {} + ] + ], "fetch/origin/resources/redirect-and-stash.py": [ [ {} @@ -187967,6 +188112,16 @@ {} ] ], + "service-workers/service-worker/fetch-request-css-cross-origin.https-expected.txt": [ + [ + {} + ] + ], + "service-workers/service-worker/fetch-request-html-imports.https-expected.txt": [ + [ + {} + ] + ], "service-workers/service-worker/fetch-request-xhr-sync.https-expected.txt": [ [ {} @@ -188032,6 +188187,11 @@ {} ] ], + "service-workers/service-worker/multipart-image.https-expected.txt": [ + [ + {} + ] + ], "service-workers/service-worker/navigate-window.https-expected.txt": [ [ {} @@ -188122,6 +188282,11 @@ {} ] ], + "service-workers/service-worker/opaque-response-preloaded.https-expected.txt": [ + [ + {} + ] + ], "service-workers/service-worker/ready.https-expected.txt": [ [ {} @@ -188132,6 +188297,11 @@ {} ] ], + "service-workers/service-worker/resource-timing-cross-origin.https-expected.txt": [ + [ + {} + ] + ], "service-workers/service-worker/resources/404.py": [ [ {} @@ -189657,11 +189827,31 @@ {} ] ], + "service-workers/service-worker/respond-with-body-accessed-response.https-expected.txt": [ + [ + {} + ] + ], "service-workers/service-worker/sandboxed-iframe-navigator-serviceworker.https-expected.txt": [ [ {} ] ], + "service-workers/service-worker/service-worker-csp-connect.https-expected.txt": [ + [ + {} + ] + ], + "service-workers/service-worker/service-worker-csp-default.https-expected.txt": [ + [ + {} + ] + ], + "service-workers/service-worker/service-worker-csp-script.https-expected.txt": [ + [ + {} + ] + ], "service-workers/service-worker/unregister-then-register-new-script.https-expected.txt": [ [ {} @@ -198932,11 +199122,6 @@ {} ] ], - "web-animations/timing-model/animation-effects/simple-iteration-progress-expected.txt": [ - [ - {} - ] - ], "web-animations/timing-model/animations/canceling-an-animation-expected.txt": [ [ {} @@ -221852,6 +222037,12 @@ {} ] ], + "clipboard-apis/clipboard-item.https.html": [ + [ + "clipboard-apis/clipboard-item.https.html", + {} + ] + ], "compat/css-style-declaration-alias-enumeration.html": [ [ "compat/css-style-declaration-alias-enumeration.html", @@ -299205,6 +299396,18 @@ {} ] ], + "resource-timing/crossorigin-sandwich-TAO.sub.html": [ + [ + "resource-timing/crossorigin-sandwich-TAO.sub.html", + {} + ] + ], + "resource-timing/crossorigin-sandwich-no-TAO.sub.html": [ + [ + "resource-timing/crossorigin-sandwich-no-TAO.sub.html", + {} + ] + ], "resource-timing/document-domain-no-impact-loader.sub.html": [ [ "resource-timing/document-domain-no-impact-loader.sub.html", @@ -342448,7 +342651,7 @@ "support" ], "clipboard-apis/async-interfaces.https-expected.txt": [ - "6719ecbeee21795978d31cb29f0d0a7605067cd2", + "269b04e054ebfbc2420b077f8db47788c119a4b1", "support" ], "clipboard-apis/async-interfaces.https.html": [ @@ -342456,27 +342659,27 @@ "testharness" ], "clipboard-apis/async-navigator-clipboard-basics.https.html": [ - "b71b43efe064c3fba60c6922c09da7e835398903", + "9bff6ab08582ce6389eb1a3a9d866c9c3d8de3bc", "testharness" ], "clipboard-apis/async-write-blobs-read-blobs-manual.https.html": [ - "57cf542ca77bc648d4a839e21775957f287ec60f", + "a7d1fde24fb54b4bc84436aad7755493106de4b9", "manual" ], "clipboard-apis/async-write-blobtext-read-blobtext-manual.https.html": [ - "fded721f9bfa1a9efd9e42b05b4ddcc40a3b8e48", + "aaf0b589c81ca6bf3f7e965cfc65fe6a9df7e5c0", "manual" ], "clipboard-apis/async-write-blobtext-read-text-manual.https.html": [ - "98ff7c27b667182432d744edcdbdfc5ca36dabb0", + "72fe597fb74defc294f87eba85aab66f3472d20e", "manual" ], "clipboard-apis/async-write-image-read-image-manual.https.html": [ - "6c326cf8ddeaa8777ef6b41d6bc9e4c32282a5c3", + "2cc6eb70542b92238441a6581552abe525751e15", "manual" ], "clipboard-apis/async-write-text-read-blobtext-manual.https.html": [ - "ab85a6fc649e6a6c7a86127adb1a41845324f3ff", + "d62c119a8f5246e3169bc785dbe24c9a0137f393", "manual" ], "clipboard-apis/async-write-text-read-text-manual.https.html": [ @@ -342487,6 +342690,10 @@ "fa40d8c20038c5a9c2cc09fe7dcfb1568de58be2", "testharness" ], + "clipboard-apis/clipboard-item.https.html": [ + "aa55f9985c05cf8b8c8003d979ca00da1b306474", + "testharness" + ], "clipboard-apis/copy-event-manual.html": [ "6f687af196fa198cda7d83f468945f9f69330568", "manual" @@ -342604,7 +342811,7 @@ "support" ], "common/get-host-info.sub.js": [ - "743bec18ec26279dc2e83dba664873e4babbf6c3", + "595a539f1953db41ff828abfc383c030ba58baac", "support" ], "common/get-host-info.sub.js.headers": [ @@ -432256,7 +432463,7 @@ "testharness" ], "feature-policy/feature-policy-for-sandbox/resources/helper.js": [ - "09a8aa7846cd724e203bb12ce9a014662d01ea0d", + "9de8416535613fc1d46396953750cc9ab6a7990b", "support" ], "feature-policy/feature-policy-for-sandbox/resources/opened_window.html": [ @@ -432892,15 +433099,15 @@ "testharness" ], "fetch/api/abort/general.any.serviceworker-expected.txt": [ - "99afa96328e06ddad8d3aa03f3c2ec9da9c1918f", + "2640a04f18e1f1d4da0921ef2e42069eb4b62d35", "support" ], "fetch/api/abort/general.any.sharedworker-expected.txt": [ - "99afa96328e06ddad8d3aa03f3c2ec9da9c1918f", + "c1e9262408133c9638bb9574c98b9d3339d8d8a2", "support" ], "fetch/api/abort/general.any.worker-expected.txt": [ - "99afa96328e06ddad8d3aa03f3c2ec9da9c1918f", + "c1e9262408133c9638bb9574c98b9d3339d8d8a2", "support" ], "fetch/api/abort/keepalive.html": [ @@ -432959,10 +433166,18 @@ "5bd156f43233587fc10ae0c727cef7157fd9c772", "testharness" ], + "fetch/api/basic/mode-same-origin.any.worker-expected.txt": [ + "84090d992236379cf195ccddee7bd28677f36428", + "support" + ], "fetch/api/basic/referrer.any.js": [ "85745e692a2fe0e5834b3fa432eb508ad76308bb", "testharness" ], + "fetch/api/basic/referrer.any.worker-expected.txt": [ + "da20300d68fbbb126bb24bf625d5d9b6389f936a", + "support" + ], "fetch/api/basic/request-forbidden-headers.any.js": [ "fedabed5418bea81e9ff19c3c325d542b99faf31", "testharness" @@ -433035,14 +433250,26 @@ "0b3d7aac584ecd6c84916acecd94fca3534aea9f", "testharness" ], + "fetch/api/cors/cors-basic.any.worker-expected.txt": [ + "7b470e16d26ce4d63ad22a7fff6365c2b3de1eb5", + "support" + ], "fetch/api/cors/cors-cookies-redirect.any.js": [ "f5217b42460a57c191300bddce21b6cde6a697d0", "testharness" ], + "fetch/api/cors/cors-cookies-redirect.any.worker-expected.txt": [ + "2dbda7952fc4f16ab1f5fd98429a291a0368150d", + "support" + ], "fetch/api/cors/cors-cookies.any.js": [ "8c666e4782f4c8d5dfb407ccc265e34b633883c3", "testharness" ], + "fetch/api/cors/cors-cookies.any.worker-expected.txt": [ + "ec99c702c28da7a7b8e59334fc2797a048be03d6", + "support" + ], "fetch/api/cors/cors-expose-star.sub.any.js": [ "340e99ab5f99d74d6475bac0b7c692968be7b03d", "testharness" @@ -433083,18 +433310,34 @@ "7a0269aae4ec3dd19026e7c9d0db6ae1232ab597", "testharness" ], + "fetch/api/cors/cors-no-preflight.any.worker-expected.txt": [ + "234a75501ab682cf4f096e70cf6d2a3d4168d861", + "support" + ], "fetch/api/cors/cors-origin.any.js": [ "0903147e400deedde62e639ba6f8afc249aabcde", "testharness" ], + "fetch/api/cors/cors-origin.any.worker-expected.txt": [ + "35224610f1a4e4d6943a52283548d8ef2a47e88c", + "support" + ], "fetch/api/cors/cors-preflight-cache.any.js": [ "ce6a169d8146750b183c9210d1b2041fac879248", "testharness" ], + "fetch/api/cors/cors-preflight-cache.any.worker-expected.txt": [ + "ad66d802123731ed11dfa6c4a98726093c43a6d5", + "support" + ], "fetch/api/cors/cors-preflight-not-cors-safelisted.any.js": [ "b2747ccd5bc09e4174aa4c59244e386c80527b51", "testharness" ], + "fetch/api/cors/cors-preflight-not-cors-safelisted.any.worker-expected.txt": [ + "658fceaf554731bf8c39538166b2a33a9c38dc9e", + "support" + ], "fetch/api/cors/cors-preflight-redirect.any-expected.txt": [ "265fbe0cf7b7ec4b4d274d9387b4add7515571a9", "support" @@ -433104,37 +433347,65 @@ "testharness" ], "fetch/api/cors/cors-preflight-redirect.any.worker-expected.txt": [ - "265fbe0cf7b7ec4b4d274d9387b4add7515571a9", + "b39cf76af7dc21b4cecff4996412c1d7b2e6ec3a", "support" ], "fetch/api/cors/cors-preflight-referrer.any.js": [ "6d69b328644a8aa2155b25a153b094fec2bf18de", "testharness" ], + "fetch/api/cors/cors-preflight-referrer.any.worker-expected.txt": [ + "5abdf7470196ba6b4604d3931c07355222a4f805", + "support" + ], "fetch/api/cors/cors-preflight-star.any.js": [ "44255d806e8cbb1cb429bcd1dffb4b99a4c094a2", "testharness" ], + "fetch/api/cors/cors-preflight-star.any.worker-expected.txt": [ + "edda8e76fc334ee5a22b1dbd119cee95f0b6c28f", + "support" + ], "fetch/api/cors/cors-preflight-status.any.js": [ "037526e618ce9b46d08aad0f59cb18e53b1adf12", "testharness" ], + "fetch/api/cors/cors-preflight-status.any.worker-expected.txt": [ + "dd36bae0de8ec9de5e2673c193513c21cf8d8d1f", + "support" + ], "fetch/api/cors/cors-preflight.any.js": [ "7455b9774031c8ead6ebaf65165ee920eb9f4218", "testharness" ], + "fetch/api/cors/cors-preflight.any.worker-expected.txt": [ + "9e6a2937475b6c1c30445f14c6d9b8ba1385f8e5", + "support" + ], "fetch/api/cors/cors-redirect-credentials.any.js": [ "0fa85cc2470ea5c42d8c2654fc83887239669678", "testharness" ], + "fetch/api/cors/cors-redirect-credentials.any.worker-expected.txt": [ + "536c42b6841c29ae70f39b24e292450890a04284", + "support" + ], "fetch/api/cors/cors-redirect-preflight.any.js": [ "e9c53bd10fb4a9b9914fedf31388dbad8e3bb5bb", "testharness" ], + "fetch/api/cors/cors-redirect-preflight.any.worker-expected.txt": [ + "75b51ff852ab88ec4a6c0ecd2b05fb58ed685b3c", + "support" + ], "fetch/api/cors/cors-redirect.any.js": [ "cdf4097d5669241373dc7a03ad52c1cb974b5258", "testharness" ], + "fetch/api/cors/cors-redirect.any.worker-expected.txt": [ + "e54b878168a9febe2e7d7a6b7a398aa3e7f03d7e", + "support" + ], "fetch/api/cors/resources/corspreflight.js": [ "f85d90d9edd6a345564e2b8144123472fde58e4d", "support" @@ -433351,6 +433622,10 @@ "32d413cb2f16db6753bd71cfa0395ff8bd7efea9", "testharness" ], + "fetch/api/redirect/redirect-back-to-original-origin.any.worker-expected.txt": [ + "8491507ab7cdf13e2a17d58eaf8a095bfb32acc1", + "support" + ], "fetch/api/redirect/redirect-count.any.js": [ "0c45d8d87ce44e0ebdde4d10d974681384d47c09", "testharness" @@ -433407,14 +433682,26 @@ "7d34fa61a96bf6e92b39451e073044ef194a7cbf", "testharness" ], + "fetch/api/redirect/redirect-mode.any.worker-expected.txt": [ + "f89be69a8da9c696e3f3ad5166ec53ba97c02530", + "support" + ], "fetch/api/redirect/redirect-origin.any.js": [ "3edb1bd03e891672e0939dfb0b797950d8a9aacb", "testharness" ], + "fetch/api/redirect/redirect-origin.any.worker-expected.txt": [ + "1dc9374784b8fed2ff1f910dc6a6c1a45e1e345f", + "support" + ], "fetch/api/redirect/redirect-referrer.any.js": [ "99fda42e69b29ff8bd12b7d987dbe00306059c5c", "testharness" ], + "fetch/api/redirect/redirect-referrer.any.worker-expected.txt": [ + "4cb4237c27723eb9dc62b01360000a86b6bfbee7", + "support" + ], "fetch/api/redirect/redirect-schemes.html": [ "cffec19d56a32f4b19eac363bbf48e66d9bcda1e", "testharness" @@ -433423,6 +433710,10 @@ "68ff2c5bcf2d85e6930196b8b1a3a2005ea54094", "testharness" ], + "fetch/api/redirect/redirect-to-dataurl.any.worker-expected.txt": [ + "68c0035631afdf29332d22cbe20f90f96e8ce6cc", + "support" + ], "fetch/api/request/destination/fetch-destination-iframe.https.html": [ "cb1e9d87cd537fce1a21f2d839d105739b1df2d2", "testharness" @@ -434151,10 +434442,30 @@ "cf3d19ded38abf6b7a5015509a9b3035b501098e", "testharness" ], + "fetch/cross-origin-resource-policy/fetch.any.sharedworker-expected.txt": [ + "4430cfb7a415cdd3f29e9cb8f14fd69c1cf80fd7", + "support" + ], + "fetch/cross-origin-resource-policy/fetch.any.worker-expected.txt": [ + "4430cfb7a415cdd3f29e9cb8f14fd69c1cf80fd7", + "support" + ], "fetch/cross-origin-resource-policy/fetch.https.any.js": [ "98b9ba4785312c1ea2da3825b2f812cb28a4a97c", "testharness" ], + "fetch/cross-origin-resource-policy/fetch.https.any.serviceworker-expected.txt": [ + "4b60d04e559f2d59f92d885d247204d0ad5a8cd6", + "support" + ], + "fetch/cross-origin-resource-policy/fetch.https.any.sharedworker-expected.txt": [ + "4430cfb7a415cdd3f29e9cb8f14fd69c1cf80fd7", + "support" + ], + "fetch/cross-origin-resource-policy/fetch.https.any.worker-expected.txt": [ + "4430cfb7a415cdd3f29e9cb8f14fd69c1cf80fd7", + "support" + ], "fetch/cross-origin-resource-policy/iframe-loads.html": [ "63902c302b7ce6cb5a3f0fb126be2a56a830f42b", "testharness" @@ -434195,6 +434506,10 @@ "192572e28421b364edb79e6590fcc3ea5d10a578", "testharness" ], + "fetch/cross-origin-resource-policy/scheme-restriction.any.worker-expected.txt": [ + "5f4a522a4b99795678a6c4e2defdedde8fed5bc8", + "support" + ], "fetch/cross-origin-resource-policy/scheme-restriction.https.window.js": [ "4c7457187419e059b016d5f2602b516d3382be7b", "testharness" @@ -434207,6 +434522,10 @@ "dc874977a63e51978af6a4a6769d81750beec200", "testharness" ], + "fetch/cross-origin-resource-policy/syntax.any.worker-expected.txt": [ + "f4da5128b741d4b4b31fdab7efbc9e9cb5a15500", + "support" + ], "fetch/data-urls/README.md": [ "1ce5b18b53825079305fa325e53127ba4c9c7bdf", "support" @@ -434383,6 +434702,10 @@ "c9d1d3b3af3750ec43549a3d96a0912e2cf6b399", "testharness" ], + "fetch/origin/no-cors.any.worker-expected.txt": [ + "af1b0b734fc7e3ca2a0b93f073bc5b193afa3e9b", + "support" + ], "fetch/origin/resources/redirect-and-stash.py": [ "1b1b46ba177ad3af56ef83e90b0974dd81cd3eae", "support" @@ -456860,7 +457183,7 @@ "support" ], "interfaces/wake-lock.idl": [ - "4c11b695f49986e7e9852348f21fe9bd5e68d185", + "c0d4bc9c239aae45d48924ef79c6fe354bbe7204", "support" ], "interfaces/wasm-js-api.idl": [ @@ -457684,7 +458007,7 @@ "support" ], "mathml/presentation-markup/operators/mo-paint-lspace-rspace.html": [ - "66df88264d191d91234364aebaa33c849e0217b5", + "879962c4776181b6bb505d1e0072b5f5e58b667e", "reftest" ], "mathml/presentation-markup/radicals/root-parameters-1.html": [ @@ -480487,6 +480810,14 @@ "eaf21b483ccd6ec63bcb8dc87c9e19a4305bf43d", "testharness" ], + "resource-timing/crossorigin-sandwich-TAO.sub.html": [ + "c3085950bd68ac72e1079a04d52ac3e1e1c603fb", + "testharness" + ], + "resource-timing/crossorigin-sandwich-no-TAO.sub.html": [ + "c7e7e5948dc5cbb5fb331112ab2dc562d5e430ad", + "testharness" + ], "resource-timing/document-domain-no-impact-loader.sub.html": [ "8a1c433a5c3a7b79d92b797ee1057c624d4a9866", "testharness" @@ -480828,7 +481159,7 @@ "support" ], "resource-timing/resources/multi_redirect.py": [ - "d1802a1e02d9aacad091e814cc2955d244d2f977", + "39121ddbb45824240655eafd0ef6554334bcffd8", "support" ], "resource-timing/resources/navigate_back.html": [ @@ -482612,7 +482943,7 @@ "testharness" ], "service-workers/cache-storage/serviceworker/cache-match.https-expected.txt": [ - "3f30ee17d732d3526b7af3db038eebcc39d8c07c", + "cc293b89610419cd1bed38441ca9fd9fb8527904", "support" ], "service-workers/cache-storage/serviceworker/cache-match.https.html": [ @@ -482744,7 +483075,7 @@ "testharness" ], "service-workers/cache-storage/worker/cache-match.https-expected.txt": [ - "7326e233734b782029455fa300496f7047a70c45", + "81fddb17977a5178745d18b01c53715e5c77a360", "support" ], "service-workers/cache-storage/worker/cache-match.https.html": [ @@ -483080,7 +483411,7 @@ "testharness" ], "service-workers/service-worker/fetch-canvas-tainting-video-with-range-request.https-expected.txt": [ - "eb2733136fe9f8fbdb385fff6da47c50a73f9148", + "6e71b26dfc1037c179fbb078b1de18ee5b648417", "support" ], "service-workers/service-worker/fetch-canvas-tainting-video-with-range-request.https.html": [ @@ -483227,6 +483558,10 @@ "a08e0c74881364f7fd29d3e6ac332a7e1d94bf7a", "testharness" ], + "service-workers/service-worker/fetch-request-css-cross-origin.https-expected.txt": [ + "a4d342ad6a304887b6a47c5a52658f62ee31e86c", + "support" + ], "service-workers/service-worker/fetch-request-css-cross-origin.https.html": [ "2cdfdea996f7c55a56c4bbcd6fe94dace192a497", "testharness" @@ -483239,6 +483574,10 @@ "634b8d6d8159f292d2d755a6f2621a89e4143226", "testharness" ], + "service-workers/service-worker/fetch-request-html-imports.https-expected.txt": [ + "3bc7820ecca3db7d26bc35861bc410e124fa3803", + "support" + ], "service-workers/service-worker/fetch-request-html-imports.https.html": [ "7a39fa85284addeb8b8d1144efda74bdfa0134fe", "testharness" @@ -483411,6 +483750,10 @@ "b9dfe3634353382e85dd0f7be4ea5b69c8083e08", "testharness" ], + "service-workers/service-worker/multipart-image.https-expected.txt": [ + "e1bae60da37755239dfe7a60eb0bba641742b50c", + "support" + ], "service-workers/service-worker/multipart-image.https.html": [ "9bdadff21fbbac84e6150724a3a9bfdb035be38f", "testharness" @@ -483555,6 +483898,10 @@ "fe7f6e901206e07b611496a191a8023516aa4b84", "testharness" ], + "service-workers/service-worker/opaque-response-preloaded.https-expected.txt": [ + "1a146d3e48c21847087f3523b1a22fe9bcd6de7a", + "support" + ], "service-workers/service-worker/opaque-response-preloaded.https.html": [ "417aa4ebec8380ec778bbe42f3ee8fb45649292f", "testharness" @@ -483679,6 +484026,10 @@ "a39ceadd9f3feec1b8b73643aecf7530dcc61311", "testharness" ], + "service-workers/service-worker/resource-timing-cross-origin.https-expected.txt": [ + "99c6abc6fc1edbc0bf830b54fbe5c8258ea392e9", + "support" + ], "service-workers/service-worker/resource-timing-cross-origin.https.html": [ "827688df011ea9be216a7414b161dbb730f1b975", "testharness" @@ -484907,6 +485258,10 @@ "2cd7f2f8f86a23d464b30feab0939931134810cc", "support" ], + "service-workers/service-worker/respond-with-body-accessed-response.https-expected.txt": [ + "3ea07374ab1823ca671661a24c9b404f9b96f996", + "support" + ], "service-workers/service-worker/respond-with-body-accessed-response.https.html": [ "f6713d89216ec0a8e5cfc6f4cbb326f0bd6e672e", "testharness" @@ -484923,14 +485278,26 @@ "a58525f422203b087a2c88ef24cfadfa567fade2", "testharness" ], + "service-workers/service-worker/service-worker-csp-connect.https-expected.txt": [ + "b1def0b562d87dcb3f95bcc415e3a262cb7c19ba", + "support" + ], "service-workers/service-worker/service-worker-csp-connect.https.html": [ "226f4a40e4e9ab40bbeeac4e874208af3106d2da", "testharness" ], + "service-workers/service-worker/service-worker-csp-default.https-expected.txt": [ + "4982a4d03b630b3b228ef9ab4e2c4872ba3e0c95", + "support" + ], "service-workers/service-worker/service-worker-csp-default.https.html": [ "1d4e7624d861bc1ce1fde706409cfad160978c41", "testharness" ], + "service-workers/service-worker/service-worker-csp-script.https-expected.txt": [ + "871359eaa9f01b54a1ef730626722c655e137d56", + "support" + ], "service-workers/service-worker/service-worker-csp-script.https.html": [ "14c2eb72bdc49c4e13fa2d9da4a47be785b072f2", "testharness" @@ -493556,7 +493923,7 @@ "support" ], "tools/wptrunner/requirements.txt": [ - "887068b34d28bdf875e42f440cedac478b9f411a", + "4b568b746168fdf5e06e4a5e592194f5e87f49d4", "support" ], "tools/wptrunner/requirements_chrome.txt": [ @@ -495440,7 +495807,7 @@ "support" ], "wake-lock/idlharness.https.any-expected.txt": [ - "3930e1230bde2cf7199b566c5963cbcb12f35bec", + "0f847f0ba3997d884cbdd8cb06fda6b3bbd1e47d", "support" ], "wake-lock/idlharness.https.any.js": [ @@ -495448,7 +495815,7 @@ "testharness" ], "wake-lock/idlharness.https.any.worker-expected.txt": [ - "a17dfea9f40571d8a150f1bf9dd2fa492691d469", + "0d9d4a9e4c28a28e406dfb29ad2b3731b739ed18", "support" ], "wake-lock/wakelock-applicability-manual.https-expected.txt": [ @@ -496315,10 +496682,6 @@ "b62726c7e64b2733f7eb8c4e731e6bc8ad8df5bc", "testharness" ], - "web-animations/timing-model/animation-effects/simple-iteration-progress-expected.txt": [ - "9fd64511241fd3da5929f495d851a0a0436105d6", - "support" - ], "web-animations/timing-model/animation-effects/simple-iteration-progress.html": [ "3c42f79a7101e44195938137414d05cf6ff503ef", "testharness" @@ -500012,7 +500375,7 @@ "testharness" ], "webrtc/idlharness.https.window-expected.txt": [ - "9904644e9b32bf0b7d7efe550435315959e57608", + "5e62ee6f092bcf9302253f2d17bf173d313bc705", "support" ], "webrtc/idlharness.https.window.js": [
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/animator-animate.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/animator-animate.https.html deleted file mode 100644 index 2ac25498..0000000 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/animator-animate.https.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!DOCTYPE html> -<title>Basic use of Worklet Animation</title> -<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/"> - -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/web-animations/testcommon.js"></script> -<script src="common.js"></script> - -<div id="target"></div> - -<script> - promise_test(async t => { - await registerConstantLocalTimeAnimator(500); - const effect = new KeyframeEffect(target, [{ opacity: 0 }], { duration: 1000 }); - const animation = new WorkletAnimation('constant_time', effect); - animation.play(); - - // wait until local times are synced back to the main thread. - await waitForAnimationFrameWithCondition(_ => { - return getComputedStyle(target).opacity != '1'; - }); - assert_equals(getComputedStyle(target).opacity, "0.5"); - }, "Simple worklet animation should output values at specified local time"); -</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-play.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-play.https.html new file mode 100644 index 0000000..038cd74a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-play.https.html
@@ -0,0 +1,45 @@ +<!DOCTYPE html> +<title>Basic use of Worklet Animation</title> +<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/web-animations/testcommon.js"></script> +<script src="common.js"></script> + +<div id="target"></div> + +<script> + promise_test(async t => { + await registerConstantLocalTimeAnimator(500); + const effect = new KeyframeEffect(target, [{ opacity: 0 }], { duration: 1000 }); + const animation = new WorkletAnimation('constant_time', effect); + animation.play(); + + // wait until local times are synced back to the main thread. + await waitForAnimationFrameWithCondition(_ => { + return getComputedStyle(target).opacity != '1'; + }); + assert_equals(getComputedStyle(target).opacity, "0.5"); + + animation.cancel(); + }, "A running worklet animation should output values at specified local time."); + + promise_test(async t => { + await registerConstantLocalTimeAnimator(500); + const effect = new KeyframeEffect(target, [{ opacity: 0 }], { duration: 1000 }); + const animation = new WorkletAnimation('constant_time', effect); + animation.play(); + + await waitForAnimationFrameWithCondition(_=> { + return animation.playState == "running" + }); + + const prevCurrentTime = animation.currentTime; + animation.play(); + assert_equals(animation.playState, "running"); + assert_equals(animation.currentTime, prevCurrentTime) + + animation.cancel(); + }, "Playing a running animation should be a no-op."); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-interfaces.https-expected.txt b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-interfaces.https-expected.txt index 6719ecb..269b04e 100644 --- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-interfaces.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-interfaces.https-expected.txt
@@ -31,17 +31,17 @@ PASS Clipboard interface: calling write(ClipboardItems) on navigator.clipboard with too few arguments must throw TypeError PASS Clipboard interface: navigator.clipboard must inherit property "writeText(DOMString)" with the proper type PASS Clipboard interface: calling writeText(DOMString) on navigator.clipboard with too few arguments must throw TypeError -FAIL ClipboardItem interface: existence and properties of interface object assert_own_property: self does not have own property "ClipboardItem" expected property "ClipboardItem" missing -FAIL ClipboardItem interface object length assert_own_property: self does not have own property "ClipboardItem" expected property "ClipboardItem" missing -FAIL ClipboardItem interface object name assert_own_property: self does not have own property "ClipboardItem" expected property "ClipboardItem" missing -FAIL ClipboardItem interface: existence and properties of interface prototype object assert_own_property: self does not have own property "ClipboardItem" expected property "ClipboardItem" missing -FAIL ClipboardItem interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "ClipboardItem" expected property "ClipboardItem" missing -FAIL ClipboardItem interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "ClipboardItem" expected property "ClipboardItem" missing -FAIL ClipboardItem interface: operation createDelayed([object Object],[object Object], ClipboardItemOptions) assert_own_property: self does not have own property "ClipboardItem" expected property "ClipboardItem" missing -FAIL ClipboardItem interface: attribute presentationStyle assert_own_property: self does not have own property "ClipboardItem" expected property "ClipboardItem" missing -FAIL ClipboardItem interface: attribute lastModified assert_own_property: self does not have own property "ClipboardItem" expected property "ClipboardItem" missing -FAIL ClipboardItem interface: attribute delayed assert_own_property: self does not have own property "ClipboardItem" expected property "ClipboardItem" missing -FAIL ClipboardItem interface: attribute types assert_own_property: self does not have own property "ClipboardItem" expected property "ClipboardItem" missing -FAIL ClipboardItem interface: operation getType(DOMString) assert_own_property: self does not have own property "ClipboardItem" expected property "ClipboardItem" missing +PASS ClipboardItem interface: existence and properties of interface object +PASS ClipboardItem interface object length +PASS ClipboardItem interface object name +PASS ClipboardItem interface: existence and properties of interface prototype object +PASS ClipboardItem interface: existence and properties of interface prototype object's "constructor" property +PASS ClipboardItem interface: existence and properties of interface prototype object's @@unscopables property +FAIL ClipboardItem interface: operation createDelayed([object Object],[object Object], ClipboardItemOptions) assert_own_property: interface object missing static operation expected property "createDelayed" missing +FAIL ClipboardItem interface: attribute presentationStyle assert_true: The prototype object must have a property "presentationStyle" expected true got false +FAIL ClipboardItem interface: attribute lastModified assert_true: The prototype object must have a property "lastModified" expected true got false +FAIL ClipboardItem interface: attribute delayed assert_true: The prototype object must have a property "delayed" expected true got false +PASS ClipboardItem interface: attribute types +PASS ClipboardItem interface: operation getType(DOMString) Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-interfaces.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-interfaces.https.html index e0d0977..e19c958 100644 --- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-interfaces.https.html +++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-interfaces.https.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset=utf-8> <title>Clipboard IDL test</title> -<link rel='help' href='https://w3c.github.io/clipboard-apis/'> +<link rel='help' href='https://w3c.github.io/clipboard-apis/#async-clipboard-api'> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/resources/WebIDLParser.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html index b71b43e..706093a 100644 --- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html +++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>Async Clipboard input type validation tests</title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script> @@ -13,29 +14,28 @@ promise_test(async () => { const blob = new Blob(['hello'], {type: 'text/plain'}); - await navigator.clipboard.write({'text/plain': blob}); -}, 'navigator.clipboard.write({string : text/plain Blob}) succeeds'); + const item = new ClipboardItem({'text/plain': blob}); + + await navigator.clipboard.write([item]); +}, 'navigator.clipboard.write([text/plain ClipboardItem]) succeeds'); promise_test(async t => { - await promise_rejects(t, new TypeError(), - navigator.clipboard.write()); -}, 'navigator.clipboard.write() fails (expect {string : Blob})'); + await promise_rejects(t, new TypeError(), navigator.clipboard.write()); +}, 'navigator.clipboard.write() fails (expect [ClipboardItem])'); promise_test(async t => { - await promise_rejects(t, new TypeError(), - navigator.clipboard.write(null)); -}, 'navigator.clipboard.write(null) fails (expect {string : Blob})'); + await promise_rejects(t, new TypeError(), navigator.clipboard.write(null)); +}, 'navigator.clipboard.write(null) fails (expect [ClipboardItem])'); promise_test(async t => { await promise_rejects(t, new TypeError(), navigator.clipboard.write('Bad string')); -}, 'navigator.clipboard.write(DOMString) fails (expect {string : Blob})'); +}, 'navigator.clipboard.write(DOMString) fails (expect [ClipboardItem])'); promise_test(async t => { const blob = new Blob(['hello'], {type: 'text/plain'}); - await promise_rejects(t, 'NotAllowedError', - navigator.clipboard.write(blob)); -}, 'navigator.clipboard.write(Blob) fails (expect {string : Blob})'); + await promise_rejects(t, new TypeError(), navigator.clipboard.write(blob)); +}, 'navigator.clipboard.write(Blob) fails (expect [ClipboardItem])'); promise_test(async () => { await navigator.clipboard.writeText('New clipboard text'); @@ -50,13 +50,15 @@ const fetched = await fetch( 'http://localhost:8001/clipboard-apis/resources/greenbox.png'); const image = await fetched.blob(); + const item = new ClipboardItem({'image/png': image}); - await navigator.clipboard.write({'image/png' : image}); + await navigator.clipboard.write([item]); }, 'navigator.clipboard.write({string : image/png Blob}) succeeds'); promise_test(async () => { const result = await navigator.clipboard.read(); assert_true(result instanceof Object); + assert_true(result[0] instanceof ClipboardItem); }, 'navigator.clipboard.read() succeeds'); promise_test(async () => {
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobs-read-blobs-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobs-read-blobs-manual.https.html index 57cf542..b5f0f3d 100644 --- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobs-read-blobs-manual.https.html +++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobs-read-blobs-manual.https.html
@@ -3,6 +3,7 @@ <title> Async Clipboard write blobs -> read blobs tests </title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -19,14 +20,22 @@ assert_equals(blobText.type, 'text/plain'); assert_equals(blobImage.type, 'image/png'); - await navigator.clipboard.write( + const clipboardItemInput = new ClipboardItem( {'text/plain' : blobText, 'image/png' : blobImage}); - const output = await navigator.clipboard.read(); - assert_equals(Object.keys(output).length, 2); - assert_equals(output['text/plain'].type, 'text/plain'); - assert_equals(output['image/png'].type, 'image/png'); -}, 'Verify write and read clipboard (multiple blobs)'); + await navigator.clipboard.write([clipboardItemInput]); + const clipboardItems = await navigator.clipboard.read(); + + assert_equals(clipboardItems.length, 1); + const clipboardItem = clipboardItems[0]; + assert_true(clipboardItem instanceof ClipboardItem); + + assert_equals(clipboardItem.types.length, 2); + const blobTextOutput = await clipboardItem.getType('text/plain'); + const blobImageOutput = await clipboardItem.getType('image/png'); + assert_equals(blobTextOutput.type, 'text/plain'); + assert_equals(blobImageOutput.type, 'image/png'); +}, 'Verify write and read clipboard (multiple types)'); </script> <p> Note: This is a manual test because it writes/reads to the shared system
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-blobtext-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-blobtext-manual.https.html index fded721..b374333c 100644 --- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-blobtext-manual.https.html +++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-blobtext-manual.https.html
@@ -1,19 +1,25 @@ <!DOCTYPE html> <meta charset="utf-8"> <title> - Async Clipboard write ([text/plain Blob]) -> read ([text/plain Blob]) tests + Async Clipboard write ([text/plain ClipboardItem]) -> + read ([text/plain ClipboardItem]) tests </title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script> async function readWriteTest(textInput) { promise_test(async t => { const blobInput = new Blob([textInput], {type: 'text/plain'}); + const clipboardItemInput = new ClipboardItem({'text/plain': blobInput}); - await navigator.clipboard.write({'text/plain': blobInput}); - const blobsOutput = await navigator.clipboard.read(); - assert_equals(Object.keys(blobsOutput).length, 1); - const blobOutput = blobsOutput['text/plain']; + await navigator.clipboard.write([clipboardItemInput]); + const clipboardItems = await navigator.clipboard.read(); + assert_equals(clipboardItems.length, 1); + const clipboardItemOutput = clipboardItems[0]; + assert_true(clipboardItemOutput instanceof ClipboardItem); + assert_equals(clipboardItemOutput.types.length, 1); + const blobOutput = await clipboardItemOutput.getType('text/plain'); assert_equals(blobOutput.type, 'text/plain'); const textOutput = await (new Response(blobOutput)).text(); @@ -21,7 +27,7 @@ }, 'Verify write and read clipboard given text: ' + textInput); } -readWriteTest('Clipboard write ([text/plain Blob]) -> read ([text/plain Blob]) test'); +readWriteTest('Clipboard write ([text/plain ClipboardItem]) -> read ([text/plain ClipboardItem]) test'); readWriteTest('non-Latin1 text encoding test データ'); </script> <p>
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-text-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-text-manual.https.html index 98ff7c27..2d78b2f 100644 --- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-text-manual.https.html +++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-text-manual.https.html
@@ -1,21 +1,25 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>Async Clipboard write ([text/plain Blob]) -> readText tests</title> +<title> + Async Clipboard write ([text/plain ClipboardItem]) -> readText tests +</title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script> async function readWriteTest(textInput) { promise_test(async t => { const blobInput = new Blob([textInput], {type: 'text/plain'}); + const clipboardItem = new ClipboardItem({'text/plain': blobInput}); - await navigator.clipboard.write({'text/plain': blobInput}); + await navigator.clipboard.write([clipboardItem]); const textOutput = await navigator.clipboard.readText(); assert_equals(textOutput, textInput); }, 'Verify write and read clipboard given text: ' + textInput); } -readWriteTest('Clipboard write ([text/plain Blob]) -> read text test'); +readWriteTest('Clipboard write ([text/plain ClipboardItem) -> read text test'); readWriteTest('non-Latin1 text encoding test データ'); </script> <p>
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-image-read-image-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-image-read-image-manual.https.html index 6c326cf..351e74b 100644 --- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-image-read-image-manual.https.html +++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-image-read-image-manual.https.html
@@ -1,8 +1,10 @@ <!DOCTYPE html> <meta charset="utf-8"> <title> - Async Clipboard write [image/png Blob] -> read [image/png Blob] tests + Async Clipboard write [image/png ClipboardItem] -> + read [image/png ClipboardItem] tests </title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -40,10 +42,15 @@ const blobInput = await loadBlob('resources/greenbox.png'); assert_equals(blobInput.type, 'image/png'); - await navigator.clipboard.write({'image/png' : blobInput}); - const blobsOutput = await navigator.clipboard.read(); - assert_equals(Object.keys(blobsOutput).length, 1); - const blobOutput = blobsOutput['image/png']; + const clipboardItemInput = new ClipboardItem({'image/png' : blobInput}); + await navigator.clipboard.write([clipboardItemInput]); + const clipboardItems = await navigator.clipboard.read(); + + assert_equals(clipboardItems.length, 1); + const clipboardItem = clipboardItems[0]; + assert_true(clipboardItem instanceof ClipboardItem); + assert_equals(clipboardItem.types.length, 1); + const blobOutput = await clipboardItem.getType('image/png'); assert_equals(blobOutput.type, 'image/png'); document.getElementById('image-on-clipboard').src = @@ -53,7 +60,7 @@ const comparableOutput = await getBitmapString(blobOutput); assert_equals(comparableOutput, comparableInput); -}, 'Verify write and read clipboard ([image/png Blob])'); +}, 'Verify write and read clipboard [image/png Blob]'); </script> <p> Note: This is a manual test because it writes/reads to the shared system
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-blobtext-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-blobtext-manual.https.html index ab85a6f..4f9fe25 100644 --- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-blobtext-manual.https.html +++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-blobtext-manual.https.html
@@ -1,15 +1,21 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>Async Clipboard writeText -> read ([text/plain Blob]) tests</title> +<title> + Async Clipboard writeText -> read ([text/plain ClipboardItem]) tests +</title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script> async function readWriteTest(textInput) { promise_test(async t => { await navigator.clipboard.writeText(textInput); - const blobsOutput = await navigator.clipboard.read(); - assert_equals(Object.keys(blobsOutput).length, 1); - const blobOutput = blobsOutput['text/plain']; + const clipboardItems = await navigator.clipboard.read(); + assert_equals(clipboardItems.length, 1); + const clipboardItem = clipboardItems[0]; + assert_true(clipboardItem instanceof ClipboardItem); + assert_equals(clipboardItem.types.length, 1); + const blobOutput = await clipboardItem.getType('text/plain'); assert_equals(blobOutput.type, 'text/plain'); const textOutput = await (new Response(blobOutput)).text(); @@ -17,7 +23,7 @@ }, 'Verify write and read clipboard given text: ' + textInput); } -readWriteTest('Clipboard write text -> read ([text/plain Blob]) test'); +readWriteTest('Clipboard write text -> read ([text/plain ClipboardItem]) test'); readWriteTest('non-Latin1 text encoding test データ'); </script> <p>
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html index 25c7edb..48e5adb5 100644 --- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html +++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>Async Clipboard writeText -> readText tests</title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script>
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/clipboard-item.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/clipboard-item.https.html new file mode 100644 index 0000000..9218ee29 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/clipboard-item.https.html
@@ -0,0 +1,78 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>ClipboardItem tests</title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + +const blob = new Blob(['hello'], {type: 'text/plain'}); +const blob2 = new Blob(['this should work'], {type: 'not a/real type'}); + +test(() => { + new ClipboardItem({'text/plain': blob}); + new ClipboardItem({'text/plain': blob, 'not a/real type': blob2}); +}, "ClipboardItem({string, Blob}) succeeds with different types"); + +test(() => { + new ClipboardItem({'text/plain': blob}, {}); +}, "ClipboardItem() succeeds with empty options"); + +test(() => { + assert_throws(new TypeError(), () => {new ClipboardItem({});}); +}, "ClipboardItem({}) fails with empty dictionary input"); + +test(() => { + assert_throws(new TypeError(), () => {new ClipboardItem(blob);}); +}, "ClipboardItem(Blob) fails"); + +test(() => { + assert_throws(new TypeError(), () => {new ClipboardItem(null);}); +}, "ClipboardItem() fails with null input"); + +test(() => { + assert_throws(new TypeError(), () => {new ClipboardItem();}); +}, "ClipboardItem() fails with no input"); + +test(() => { + const item = new ClipboardItem({'text/plain': blob}); + const types = item.types; + assert_equals(types.length, 1); + assert_equals(types[0], 'text/plain'); + const item2 = + new ClipboardItem({'text/plain': blob, 'not a/real type': blob2}); + const types2 = item2.types; + assert_equals(types2.length, 2); + assert_equals(types2[0], 'text/plain'); + assert_equals(types2[1], 'not a/real type'); +}, "types() returns correct values"); + +promise_test(async () => { + const item = + new ClipboardItem({'text/plain': blob, 'not a/real type': blob2}); + + const blobOutput = await item.getType('text/plain'); + assert_true(blobOutput.type.includes('text/plain')); + const text = await (new Response(blobOutput)).text(); + + assert_equals('hello', text); +}, "getType(DOMString valid type) succeeds with correct output"); + +promise_test(async () => { + const item = + new ClipboardItem({'text/plain': blob, 'not a/real type': blob2}); + + const blobOutput = await item.getType('not a/real type'); + assert_true(blobOutput.type.includes('not a/real type')); + const text = await (new Response(blobOutput)).text(); + + assert_equals('this should work', text); +}, "getType(DOMString invalid type) succeeds with correct output"); + +promise_test(async t => { + const item = + new ClipboardItem({'text/plain': blob, 'not a/real type': blob2}); + promise_rejects(t, "NotFoundError", item.getType('type not in item')); + promise_rejects(t, "NotFoundError", item.getType('text/plain:subtype')); +}, "getType(DOMString type) rejects correctly when querying for missing type"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/common/get-host-info.sub.js b/third_party/blink/web_tests/external/wpt/common/get-host-info.sub.js index 743bec18..595a539 100644 --- a/third_party/blink/web_tests/external/wpt/common/get-host-info.sub.js +++ b/third_party/blink/web_tests/external/wpt/common/get-host-info.sub.js
@@ -3,9 +3,12 @@ var HTTP_PORT = '{{ports[http][0]}}'; var HTTP_PORT2 = '{{ports[http][1]}}'; var HTTPS_PORT = '{{ports[https][0]}}'; + var PROTOCOL = window.location.protocol; + var IS_HTTPS = (PROTOCOL == "https:"); var HTTP_PORT_ELIDED = HTTP_PORT == "80" ? "" : (":" + HTTP_PORT); var HTTP_PORT2_ELIDED = HTTP_PORT2 == "80" ? "" : (":" + HTTP_PORT2); var HTTPS_PORT_ELIDED = HTTPS_PORT == "443" ? "" : (":" + HTTPS_PORT); + var PORT_ELIDED = IS_HTTPS ? HTTPS_PORT_ELIDED : HTTP_PORT_ELIDED; var ORIGINAL_HOST = '{{host}}'; var REMOTE_HOST = (ORIGINAL_HOST === 'localhost') ? '127.0.0.1' : ('www1.' + ORIGINAL_HOST); var OTHER_HOST = '{{domains[www2]}}'; @@ -18,10 +21,12 @@ ORIGINAL_HOST: ORIGINAL_HOST, REMOTE_HOST: REMOTE_HOST, + ORIGIN: PROTOCOL + "//" + ORIGINAL_HOST + PORT_ELIDED, HTTP_ORIGIN: 'http://' + ORIGINAL_HOST + HTTP_PORT_ELIDED, HTTPS_ORIGIN: 'https://' + ORIGINAL_HOST + HTTPS_PORT_ELIDED, HTTPS_ORIGIN_WITH_CREDS: 'https://foo:bar@' + ORIGINAL_HOST + HTTPS_PORT_ELIDED, HTTP_ORIGIN_WITH_DIFFERENT_PORT: 'http://' + ORIGINAL_HOST + HTTP_PORT2_ELIDED, + REMOTE_ORIGIN: PROTOCOL + "//" + REMOTE_HOST + PORT_ELIDED, HTTP_REMOTE_ORIGIN: 'http://' + REMOTE_HOST + HTTP_PORT_ELIDED, HTTP_NOTSAMESITE_ORIGIN: 'http://' + NOTSAMESITE_HOST + HTTP_PORT_ELIDED, HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT: 'http://' + REMOTE_HOST + HTTP_PORT2_ELIDED,
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom-view/offsetTopLeftInlineMultiLine.html b/third_party/blink/web_tests/external/wpt/css/cssom-view/offsetTopLeftInlineMultiLine.html deleted file mode 100644 index b93095c..0000000 --- a/third_party/blink/web_tests/external/wpt/css/cssom-view/offsetTopLeftInlineMultiLine.html +++ /dev/null
@@ -1,55 +0,0 @@ -<!DOCTYPE html> -<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org"> -<link rel="author" title="Xianzhu Wang" href="wangxianzhu@chromium.org"> -<link rel="help" href="https://drafts.csswg.org/cssom-view-1/#extensions-to-the-htmlelement-interface"> -<link rel="match" href="../reference/nothing.html"> -<style> - .container { - float: left; - width: 8em; - height: 7em; - padding: 1em; - color: red; - } - .correctionFluid { - position: absolute; - background: white; - - /* Add some fluff to cover text ink-overflow. */ - outline:2px solid white; - } -</style> -<p>There should be nothing below.</p> - <div class="container" style="writing-mode:horizontal-tb;"> - <br><span class="child">FAIL<br>FAIL<br>FAIL</span> - </div> - <div class="container" style="writing-mode:vertical-lr;"> - <br><span class="child">FAIL<br>FAIL<br>FAIL</span> - </div> - <div class="container" style="writing-mode:vertical-rl;"> - <br><span class="child">FAIL<br>FAIL<br>FAIL</span> - </div> - <div class="container" style="writing-mode:horizontal-tb; direction:rtl;"> - <br><span class="child">FAIL<br>FAIL<br>FAIL</span> - </div> - <div class="container" style="writing-mode:vertical-lr; direction:rtl;"> - <br><span class="child">FAIL<br>FAIL<br>FAIL</span> - </div> - <div class="container" style="writing-mode:vertical-rl; direction:rtl;"> - <br><span class="child">FAIL<br>FAIL<br>FAIL</span> - </div> -<script> - // Create a white absolutely positioned box for each span.child - // element and cover it. - - let elements = document.querySelectorAll("span.child"); - elements.forEach((element)=> { - let correctionFluid = document.createElement("div"); - correctionFluid.className = "correctionFluid"; - correctionFluid.style.left = element.offsetLeft + "px"; - correctionFluid.style.top = element.offsetTop + "px"; - correctionFluid.style.width = element.offsetWidth + "px"; - correctionFluid.style.height = element.offsetHeight + "px"; - document.body.appendChild(correctionFluid); - }); -</script>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt index 99afa96..2640a04 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt +++ b/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.serviceworker-expected.txt
@@ -1,51 +1,4 @@ This is a testharness.js-based test. -PASS Aborting rejects with AbortError -PASS Aborting rejects with AbortError - no-cors -PASS TypeError from request constructor takes priority - RequestInit's window is not null -PASS TypeError from request constructor takes priority - Input URL is not valid -PASS TypeError from request constructor takes priority - Input URL has credentials -PASS TypeError from request constructor takes priority - RequestInit's mode is navigate -PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid -PASS TypeError from request constructor takes priority - RequestInit's method is invalid -PASS TypeError from request constructor takes priority - RequestInit's method is forbidden -PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple -PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin -PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors -PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors -PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value -PASS TypeError from request constructor takes priority - Bad mode init parameter value -PASS TypeError from request constructor takes priority - Bad credentials init parameter value -PASS TypeError from request constructor takes priority - Bad cache init parameter value -PASS TypeError from request constructor takes priority - Bad redirect init parameter value -PASS Request objects have a signal property -PASS Signal on request object -PASS Signal on request object created from request object -PASS Signal on request object created from request object, with signal on second request -PASS Signal on request object created from request object, with signal on second request overriding another -PASS Signal retained after unrelated properties are overridden by fetch -PASS Signal removed by setting to null -PASS Already aborted signal rejects immediately -PASS Request is still 'used' if signal is aborted before fetching -PASS response.arrayBuffer() rejects if already aborted -PASS response.blob() rejects if already aborted -PASS response.formData() rejects if already aborted -PASS response.json() rejects if already aborted -PASS response.text() rejects if already aborted -PASS Already aborted signal does not make request -PASS Already aborted signal can be used for many fetches -PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting -PASS Underlying connection is closed when aborting after receiving response -PASS Underlying connection is closed when aborting after receiving response - no-cors -PASS Fetch aborted & connection closed when aborted after calling response.arrayBuffer() -PASS Fetch aborted & connection closed when aborted after calling response.blob() -PASS Fetch aborted & connection closed when aborted after calling response.formData() -PASS Fetch aborted & connection closed when aborted after calling response.json() -PASS Fetch aborted & connection closed when aborted after calling response.text() -PASS Stream errors once aborted. Underlying connection closed. -PASS Stream errors once aborted, after reading. Underlying connection closed. -PASS Stream will not error if body is empty. It's closed with an empty queue before it errors. -FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false -PASS Signal state is cloned -PASS Clone aborts with original controller +FAIL general Failed to register a ServiceWorker: ServiceWorker script evaluation failed Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt index 99afa96..c1e92624 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt +++ b/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.sharedworker-expected.txt
@@ -1,51 +1,4 @@ This is a testharness.js-based test. -PASS Aborting rejects with AbortError -PASS Aborting rejects with AbortError - no-cors -PASS TypeError from request constructor takes priority - RequestInit's window is not null -PASS TypeError from request constructor takes priority - Input URL is not valid -PASS TypeError from request constructor takes priority - Input URL has credentials -PASS TypeError from request constructor takes priority - RequestInit's mode is navigate -PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid -PASS TypeError from request constructor takes priority - RequestInit's method is invalid -PASS TypeError from request constructor takes priority - RequestInit's method is forbidden -PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple -PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin -PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors -PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors -PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value -PASS TypeError from request constructor takes priority - Bad mode init parameter value -PASS TypeError from request constructor takes priority - Bad credentials init parameter value -PASS TypeError from request constructor takes priority - Bad cache init parameter value -PASS TypeError from request constructor takes priority - Bad redirect init parameter value -PASS Request objects have a signal property -PASS Signal on request object -PASS Signal on request object created from request object -PASS Signal on request object created from request object, with signal on second request -PASS Signal on request object created from request object, with signal on second request overriding another -PASS Signal retained after unrelated properties are overridden by fetch -PASS Signal removed by setting to null -PASS Already aborted signal rejects immediately -PASS Request is still 'used' if signal is aborted before fetching -PASS response.arrayBuffer() rejects if already aborted -PASS response.blob() rejects if already aborted -PASS response.formData() rejects if already aborted -PASS response.json() rejects if already aborted -PASS response.text() rejects if already aborted -PASS Already aborted signal does not make request -PASS Already aborted signal can be used for many fetches -PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting -PASS Underlying connection is closed when aborting after receiving response -PASS Underlying connection is closed when aborting after receiving response - no-cors -PASS Fetch aborted & connection closed when aborted after calling response.arrayBuffer() -PASS Fetch aborted & connection closed when aborted after calling response.blob() -PASS Fetch aborted & connection closed when aborted after calling response.formData() -PASS Fetch aborted & connection closed when aborted after calling response.json() -PASS Fetch aborted & connection closed when aborted after calling response.text() -PASS Stream errors once aborted. Underlying connection closed. -PASS Stream errors once aborted, after reading. Underlying connection closed. -PASS Stream will not error if body is empty. It's closed with an empty queue before it errors. -FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false -PASS Signal state is cloned -PASS Clone aborts with original controller +FAIL general Uncaught ReferenceError: window is not defined Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.worker-expected.txt index 99afa96..c1e92624 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.worker-expected.txt +++ b/third_party/blink/web_tests/external/wpt/fetch/api/abort/general.any.worker-expected.txt
@@ -1,51 +1,4 @@ This is a testharness.js-based test. -PASS Aborting rejects with AbortError -PASS Aborting rejects with AbortError - no-cors -PASS TypeError from request constructor takes priority - RequestInit's window is not null -PASS TypeError from request constructor takes priority - Input URL is not valid -PASS TypeError from request constructor takes priority - Input URL has credentials -PASS TypeError from request constructor takes priority - RequestInit's mode is navigate -PASS TypeError from request constructor takes priority - RequestInit's referrer is invalid -PASS TypeError from request constructor takes priority - RequestInit's method is invalid -PASS TypeError from request constructor takes priority - RequestInit's method is forbidden -PASS TypeError from request constructor takes priority - RequestInit's mode is no-cors and method is not simple -PASS TypeError from request constructor takes priority - RequestInit's cache mode is only-if-cached and mode is not same-origin -PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode cors -PASS TypeError from request constructor takes priority - Request with cache mode: only-if-cached and fetch mode no-cors -PASS TypeError from request constructor takes priority - Bad referrerPolicy init parameter value -PASS TypeError from request constructor takes priority - Bad mode init parameter value -PASS TypeError from request constructor takes priority - Bad credentials init parameter value -PASS TypeError from request constructor takes priority - Bad cache init parameter value -PASS TypeError from request constructor takes priority - Bad redirect init parameter value -PASS Request objects have a signal property -PASS Signal on request object -PASS Signal on request object created from request object -PASS Signal on request object created from request object, with signal on second request -PASS Signal on request object created from request object, with signal on second request overriding another -PASS Signal retained after unrelated properties are overridden by fetch -PASS Signal removed by setting to null -PASS Already aborted signal rejects immediately -PASS Request is still 'used' if signal is aborted before fetching -PASS response.arrayBuffer() rejects if already aborted -PASS response.blob() rejects if already aborted -PASS response.formData() rejects if already aborted -PASS response.json() rejects if already aborted -PASS response.text() rejects if already aborted -PASS Already aborted signal does not make request -PASS Already aborted signal can be used for many fetches -PASS Signal can be used to abort other fetches, even if another fetch succeeded before aborting -PASS Underlying connection is closed when aborting after receiving response -PASS Underlying connection is closed when aborting after receiving response - no-cors -PASS Fetch aborted & connection closed when aborted after calling response.arrayBuffer() -PASS Fetch aborted & connection closed when aborted after calling response.blob() -PASS Fetch aborted & connection closed when aborted after calling response.formData() -PASS Fetch aborted & connection closed when aborted after calling response.json() -PASS Fetch aborted & connection closed when aborted after calling response.text() -PASS Stream errors once aborted. Underlying connection closed. -PASS Stream errors once aborted, after reading. Underlying connection closed. -PASS Stream will not error if body is empty. It's closed with an empty queue before it errors. -FAIL Readable stream synchronously cancels with AbortError if aborted before reading assert_true: Cancel called sync expected true got false -PASS Signal state is cloned -PASS Clone aborts with original controller +FAIL general Uncaught ReferenceError: window is not defined Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/basic/mode-same-origin.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/basic/mode-same-origin.any.worker-expected.txt new file mode 100644 index 0000000..84090d9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/basic/mode-same-origin.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL mode-same-origin Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/basic/referrer.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/basic/referrer.any.worker-expected.txt new file mode 100644 index 0000000..da20300 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/basic/referrer.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL referrer Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-basic.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-basic.any.worker-expected.txt new file mode 100644 index 0000000..7b470e16 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-basic.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-basic Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-cookies-redirect.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-cookies-redirect.any.worker-expected.txt new file mode 100644 index 0000000..2dbda795 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-cookies-redirect.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-cookies-redirect Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-cookies.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-cookies.any.worker-expected.txt new file mode 100644 index 0000000..ec99c702 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-cookies.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-cookies Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-no-preflight.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-no-preflight.any.worker-expected.txt new file mode 100644 index 0000000..234a755 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-no-preflight.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-no-preflight Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-origin.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-origin.any.worker-expected.txt new file mode 100644 index 0000000..35224610 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-origin.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-origin Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-cache.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-cache.any.worker-expected.txt new file mode 100644 index 0000000..ad66d802 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-cache.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-preflight-cache Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-not-cors-safelisted.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-not-cors-safelisted.any.worker-expected.txt new file mode 100644 index 0000000..658fcea --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-not-cors-safelisted.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-preflight-not-cors-safelisted Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-redirect.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-redirect.any.worker-expected.txt index 265fbe0c..b39cf76 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-redirect.any.worker-expected.txt +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-redirect.any.worker-expected.txt
@@ -1,13 +1,4 @@ This is a testharness.js-based test. -FAIL Redirection 301 on preflight failed promise_test: test body must return a 'thenable' object (received undefined) -FAIL Redirection 301 after preflight failed promise_test: test body must return a 'thenable' object (received undefined) -FAIL Redirection 302 on preflight failed promise_test: test body must return a 'thenable' object (received undefined) -FAIL Redirection 302 after preflight failed promise_test: test body must return a 'thenable' object (received undefined) -FAIL Redirection 303 on preflight failed promise_test: test body must return a 'thenable' object (received undefined) -FAIL Redirection 303 after preflight failed promise_test: test body must return a 'thenable' object (received undefined) -FAIL Redirection 307 on preflight failed promise_test: test body must return a 'thenable' object (received undefined) -FAIL Redirection 307 after preflight failed promise_test: test body must return a 'thenable' object (received undefined) -FAIL Redirection 308 on preflight failed promise_test: test body must return a 'thenable' object (received undefined) -FAIL Redirection 308 after preflight failed promise_test: test body must return a 'thenable' object (received undefined) +FAIL cors-preflight-redirect Uncaught ReferenceError: window is not defined Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-referrer.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-referrer.any.worker-expected.txt new file mode 100644 index 0000000..5abdf747 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-referrer.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-preflight-referrer Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any.worker-expected.txt new file mode 100644 index 0000000..edda8e76f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-preflight-star Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-status.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-status.any.worker-expected.txt new file mode 100644 index 0000000..dd36bae0d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-status.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-preflight-status Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight.any.worker-expected.txt new file mode 100644 index 0000000..9e6a293 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-preflight Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-redirect-credentials.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-redirect-credentials.any.worker-expected.txt new file mode 100644 index 0000000..536c42b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-redirect-credentials.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-redirect-credentials Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-redirect-preflight.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-redirect-preflight.any.worker-expected.txt new file mode 100644 index 0000000..75b51ff --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-redirect-preflight.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-redirect-preflight Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-redirect.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-redirect.any.worker-expected.txt new file mode 100644 index 0000000..e54b878 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-redirect.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL cors-redirect Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-back-to-original-origin.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-back-to-original-origin.any.worker-expected.txt new file mode 100644 index 0000000..8491507 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-back-to-original-origin.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL redirect-back-to-original-origin Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.worker-expected.txt new file mode 100644 index 0000000..f89be69a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.worker-expected.txt
@@ -0,0 +1,34 @@ +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Error in remote http://web-platform.test:8001/common/get-host-info.sub.js: Uncaught ReferenceError: window is not defined +PASS same-origin redirect 301 in error redirect and cors mode +PASS same-origin redirect 301 in error redirect and no-cors mode +PASS same-origin redirect 301 in manual redirect and cors mode +PASS same-origin redirect 301 in manual redirect and no-cors mode +PASS same-origin redirect 301 in follow redirect and cors mode +PASS same-origin redirect 301 in follow redirect and no-cors mode +PASS same-origin redirect 302 in error redirect and cors mode +PASS same-origin redirect 302 in error redirect and no-cors mode +PASS same-origin redirect 302 in manual redirect and cors mode +PASS same-origin redirect 302 in manual redirect and no-cors mode +PASS same-origin redirect 302 in follow redirect and cors mode +PASS same-origin redirect 302 in follow redirect and no-cors mode +PASS same-origin redirect 303 in error redirect and cors mode +PASS same-origin redirect 303 in error redirect and no-cors mode +PASS same-origin redirect 303 in manual redirect and cors mode +PASS same-origin redirect 303 in manual redirect and no-cors mode +PASS same-origin redirect 303 in follow redirect and cors mode +PASS same-origin redirect 303 in follow redirect and no-cors mode +PASS same-origin redirect 307 in error redirect and cors mode +PASS same-origin redirect 307 in error redirect and no-cors mode +PASS same-origin redirect 307 in manual redirect and cors mode +PASS same-origin redirect 307 in manual redirect and no-cors mode +PASS same-origin redirect 307 in follow redirect and cors mode +PASS same-origin redirect 307 in follow redirect and no-cors mode +PASS same-origin redirect 308 in error redirect and cors mode +PASS same-origin redirect 308 in error redirect and no-cors mode +PASS same-origin redirect 308 in manual redirect and cors mode +PASS same-origin redirect 308 in manual redirect and no-cors mode +PASS same-origin redirect 308 in follow redirect and cors mode +PASS same-origin redirect 308 in follow redirect and no-cors mode +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-origin.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-origin.any.worker-expected.txt new file mode 100644 index 0000000..1dc9374 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-origin.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL redirect-origin Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-referrer.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-referrer.any.worker-expected.txt new file mode 100644 index 0000000..4cb4237 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-referrer.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL redirect-referrer Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-to-dataurl.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-to-dataurl.any.worker-expected.txt new file mode 100644 index 0000000..68c00356 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-to-dataurl.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL redirect-to-dataurl Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.any.sharedworker-expected.txt new file mode 100644 index 0000000..4430cfb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.any.sharedworker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL fetch Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.any.worker-expected.txt new file mode 100644 index 0000000..4430cfb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL fetch Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.https.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.https.any.serviceworker-expected.txt new file mode 100644 index 0000000..4b60d04e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.https.any.serviceworker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL fetch Failed to register a ServiceWorker: ServiceWorker script evaluation failed +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.https.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.https.any.sharedworker-expected.txt new file mode 100644 index 0000000..4430cfb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.https.any.sharedworker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL fetch Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.https.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.https.any.worker-expected.txt new file mode 100644 index 0000000..4430cfb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/fetch.https.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL fetch Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/scheme-restriction.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/scheme-restriction.any.worker-expected.txt new file mode 100644 index 0000000..5f4a522a4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/scheme-restriction.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Cross-Origin-Resource-Policy: same-site blocks retrieving HTTPS from HTTP window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/syntax.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/syntax.any.worker-expected.txt new file mode 100644 index 0000000..f4da512 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/cross-origin-resource-policy/syntax.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL syntax Uncaught ReferenceError: window is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/origin/no-cors.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/origin/no-cors.any.worker-expected.txt new file mode 100644 index 0000000..af1b0b7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/origin/no-cors.any.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Origin header and 308 redirect promise_test: Unhandled rejection with value: object "ReferenceError: window is not defined" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl b/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl index 4c11b69..c0d4bc9 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl
@@ -11,16 +11,13 @@ [Constructor(WakeLockType type), SecureContext, Exposed=(DedicatedWorker,Window)] interface WakeLock : EventTarget { + [Exposed=Window] static Promise<PermissionState> requestPermission(WakeLockType type); readonly attribute WakeLockType type; readonly attribute boolean active; attribute EventHandler onactivechange; - Promise<void> request(optional WakeLockRequestOptions options); + Promise<void> request(); + void abort(); static sequence<WakeLock> query(optional WakeLockQueryFilter filter); - [Exposed=Window] static Promise<PermissionState> requestPermission(WakeLockType type); -}; - -dictionary WakeLockRequestOptions { - AbortSignal? signal; }; dictionary WakeLockQueryFilter {
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-paint-lspace-rspace.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-paint-lspace-rspace.html index 66df8826..879962c4 100644 --- a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-paint-lspace-rspace.html +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-paint-lspace-rspace.html
@@ -13,7 +13,7 @@ <p>The test passes if the arrow has a leading space of 100px, which is as wide as the black block to the left, and a trailing space of 200px, which is as wide as the black block to the right.</p> - <mth> + <math> <mspace width="100px" height="10px" depth="10px" style="background: black"></mspace> <mo lspace="100px" rspace="200px">→</mo> <mspace width="200px" height="10px" depth="10px" style="background: black"></mspace>
diff --git a/third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemBaseHandle-copyTo.html b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-copyTo.tentative.window.js similarity index 90% rename from third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemBaseHandle-copyTo.html rename to third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-copyTo.tentative.window.js index 63d5b9c9..2019024 100644 --- a/third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemBaseHandle-copyTo.html +++ b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-copyTo.tentative.window.js
@@ -1,9 +1,4 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<script src="../../../resources/testharness.js"></script> -<script src="../../../resources/testharnessreport.js"></script> -<script src="resources/test-helpers.js"></script> -<script> +// META: script=resources/test-helpers.js promise_test(async t => cleanupSandboxedFileSystem(), 'Cleanup to setup test environment'); @@ -33,7 +28,6 @@ t.add_cleanup(() => target_dir.removeRecursively()); const new_handle = await old_handle.copyTo(target_dir); - t.add_cleanup(() => new_handle.remove()); // Verify new file. assert_true(new_handle.isFile); @@ -76,4 +70,3 @@ }, 'copyTo() when target file already exists should overwrite target'); // TODO(mek): Tests to copy directories. -</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemBaseHandle-moveTo.html b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-moveTo.tentative.window.js similarity index 90% rename from third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemBaseHandle-moveTo.html rename to third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-moveTo.tentative.window.js index d52fadc..3badce1 100644 --- a/third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemBaseHandle-moveTo.html +++ b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-moveTo.tentative.window.js
@@ -1,9 +1,4 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<script src="../../../resources/testharness.js"></script> -<script src="../../../resources/testharnessreport.js"></script> -<script src="resources/test-helpers.js"></script> -<script> +// META: script=resources/test-helpers.js promise_test(async t => cleanupSandboxedFileSystem(), 'Cleanup to setup test environment'); @@ -33,7 +28,6 @@ t.add_cleanup(() => target_dir.removeRecursively()); const new_handle = await old_handle.moveTo(target_dir); - t.add_cleanup(() => new_handle.remove()); // Verify new file. assert_true(new_handle.isFile); @@ -75,5 +69,4 @@ assert_array_equals(await getSortedDirectoryEntries(dir), ['target']); }, 'moveTo() when target file already exists should overwrite target'); -// TODO(mek): Tests to move directories. -</script> \ No newline at end of file +// TODO(mek): Tests to move directories. \ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemBaseHandle-remove.html b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-remove.tentative.window.js similarity index 88% rename from third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemBaseHandle-remove.html rename to third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-remove.tentative.window.js index 0c34daa..33ac960 100644 --- a/third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemBaseHandle-remove.html +++ b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-remove.tentative.window.js
@@ -1,9 +1,4 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<script src="../../../resources/testharness.js"></script> -<script src="../../../resources/testharnessreport.js"></script> -<script src="resources/test-helpers.js"></script> -<script> +// META: script=resources/test-helpers.js promise_test(async t => cleanupSandboxedFileSystem(), 'Cleanup to setup test environment'); @@ -43,5 +38,4 @@ await promise_rejects(t, 'InvalidModificationError', dir.remove()); assert_array_equals(await getSortedDirectoryEntries(root), ['dir-to-remove/']); assert_array_equals(await getSortedDirectoryEntries(dir), ['file-in-dir']); -}, 'remove() on a non-empty directory should fail'); -</script> \ No newline at end of file +}, 'remove() on a non-empty directory should fail'); \ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemDirectoryHandle-getDirectory.html b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getDirectory.tentative.window.js similarity index 90% rename from third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemDirectoryHandle-getDirectory.html rename to third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getDirectory.tentative.window.js index 2af9c31..105879db 100644 --- a/third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemDirectoryHandle-getDirectory.html +++ b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getDirectory.tentative.window.js
@@ -1,9 +1,4 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<script src="../../../resources/testharness.js"></script> -<script src="../../../resources/testharnessreport.js"></script> -<script src="resources/test-helpers.js"></script> -<script> +// META: script=resources/test-helpers.js promise_test(async t => cleanupSandboxedFileSystem(), 'Cleanup to setup test environment'); @@ -43,7 +38,6 @@ const existing_handle = await root.getDirectory('dir-with-contents', { create: true }); t.add_cleanup(() => existing_handle.removeRecursively()); const file_handle = await existing_handle.getFile('test-file', { create: true }); - t.add_cleanup(() => file_handle.remove()); const handle = await root.getDirectory('dir-with-contents', { create: true }); @@ -61,4 +55,3 @@ await promise_rejects(t, 'TypeMismatchError', root.getDirectory('file-name', { create: false })); await promise_rejects(t, 'TypeMismatchError', root.getDirectory('file-name', { create: true })); }, 'getDirectory() when a file already exists with the same name'); -</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemDirectoryHandle-getFile.html b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getFile.tentative.window.js similarity index 91% rename from third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemDirectoryHandle-getFile.html rename to third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getFile.tentative.window.js index 70f8b92..0d9bacd 100644 --- a/third_party/blink/web_tests/fast/filesystem/writable-files/FileSystemDirectoryHandle-getFile.html +++ b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getFile.tentative.window.js
@@ -1,9 +1,4 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<script src="../../../resources/testharness.js"></script> -<script src="../../../resources/testharnessreport.js"></script> -<script src="resources/test-helpers.js"></script> -<script> +// META: script=resources/test-helpers.js promise_test(async t => cleanupSandboxedFileSystem(), 'Cleanup to setup test environment'); @@ -64,5 +59,4 @@ t.add_cleanup(() => dir_handle.removeRecursively()); await promise_rejects(t, 'TypeMismatchError', dir.getFile('dir-name', { create: true })); -}, 'getFile(create=true) when a directory already exists with the same name'); -</script> \ No newline at end of file +}, 'getFile(create=true) when a directory already exists with the same name'); \ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/filesystem/writable-files/file-writer.html b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemWriter.tentative.window.js similarity index 92% rename from third_party/blink/web_tests/fast/filesystem/writable-files/file-writer.html rename to third_party/blink/web_tests/external/wpt/native-file-system/FileSystemWriter.tentative.window.js index 3121a4c..cc844423 100644 --- a/third_party/blink/web_tests/fast/filesystem/writable-files/file-writer.html +++ b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemWriter.tentative.window.js
@@ -1,9 +1,4 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<script src="../../../resources/testharness.js"></script> -<script src="../../../resources/testharnessreport.js"></script> -<script src="resources/test-helpers.js"></script> -<script> +// META: script=resources/test-helpers.js promise_test(async t => cleanupSandboxedFileSystem(), 'Cleanup to setup test environment'); @@ -99,4 +94,3 @@ assert_equals(await getFileContents(handle), 'streams!!!'); assert_equals(await getFileSize(handle), 10); }, 'Using a WritableStream writer to write'); -</script>
diff --git a/third_party/blink/web_tests/external/wpt/native-file-system/README.md b/third_party/blink/web_tests/external/wpt/native-file-system/README.md new file mode 100644 index 0000000..6905a68 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/native-file-system/README.md
@@ -0,0 +1,2 @@ +This directory contains (tentative) tests for the +[Native File System](https://wicg.github.io/native-file-system/) specification.
diff --git a/third_party/blink/web_tests/fast/filesystem/writable-files/resources/test-helpers.js b/third_party/blink/web_tests/external/wpt/native-file-system/resources/test-helpers.js similarity index 77% rename from third_party/blink/web_tests/fast/filesystem/writable-files/resources/test-helpers.js rename to third_party/blink/web_tests/external/wpt/native-file-system/resources/test-helpers.js index a41b448..dc5f376 100644 --- a/third_party/blink/web_tests/fast/filesystem/writable-files/resources/test-helpers.js +++ b/third_party/blink/web_tests/external/wpt/native-file-system/resources/test-helpers.js
@@ -61,17 +61,7 @@ } function garbageCollect() { - if (self.gc) { - // Use --expose_gc for V8 (and Node.js) - // Exposed in SpiderMonkey shell as well - self.gc(); - } else if (self.GCController) { - // Present in some WebKit development environments - GCController.collect(); - } else { - /* eslint-disable no-console */ - console.warn('Tests are running without the ability to do manual garbage collection. They will still work, but ' + - 'coverage will be suboptimal.'); - /* eslint-enable no-console */ - } + // TODO(https://github.com/web-platform-tests/wpt/issues/7899): Change to + // some sort of cross-browser GC trigger. + if (self.gc) self.gc(); }; \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/crossorigin-sandwich-TAO.sub.html b/third_party/blink/web_tests/external/wpt/resource-timing/crossorigin-sandwich-TAO.sub.html new file mode 100644 index 0000000..c308595 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/crossorigin-sandwich-TAO.sub.html
@@ -0,0 +1,46 @@ +<!DOCTYPE HTML> +<html> +<head> +<meta charset="utf-8" /> +<title>This test validates resource timing information for a same-origin=>cross-origin=>same-origin redirect chain with Timing-Allow-Origin.</title> +<link rel="help" href="http://www.w3.org/TR/resource-timing/#performanceresourcetiming"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="resources/webperftestharness.js"></script> +<script src="resources/webperftestharnessextension.js"></script> + +<script> + setup({explicit_done: true}); + test_namespace('getEntriesByName'); + const pageOrigin = get_host_info()['ORIGIN']; + const crossOrigin = get_host_info()['REMOTE_ORIGIN']; + + function onload_test() + { + const entries = performance.getEntriesByName(document.getElementById('frameContext').src, 'resource'); + test_equals(entries.length, 1, 'There should be one entry.'); + const entry = entries[0]; + + test_greater_than(entry.redirectStart, 0, 'redirectStart > 0 in cross-origin redirect with Timing-Allow-Origin.'); + test_greater_than(entry.redirectEnd, 0, 'redirectEnd > 0 in cross-origin redirect with Timing-Allow-Origin.'); + test_greater_than(entry.fetchStart, 0, 'fetchStart > 0 in cross-origin redirect.'); + test_greater_than(entry.fetchStart, entry.startTime, 'startTime < fetchStart in cross-origin redirect with Timing-Allow-Origin.'); + done(); + } +</script> + +</head> +<body> +<iframe id="frameContext" src="" style="width: 250px; height: 250px;"></iframe> +<script> + let destUrl = pageOrigin + '/resource-timing/resources/multi_redirect.py?'; + destUrl += 'page_origin=' + pageOrigin; + destUrl += '&timing_allow=1'; + destUrl += '&cross_origin=' + crossOrigin; + const frameContext = document.getElementById('frameContext'); + frameContext.onload = onload_test; + frameContext.src = destUrl; +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/crossorigin-sandwich-no-TAO.sub.html b/third_party/blink/web_tests/external/wpt/resource-timing/crossorigin-sandwich-no-TAO.sub.html new file mode 100644 index 0000000..c7e7e59 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/crossorigin-sandwich-no-TAO.sub.html
@@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<head> +<meta charset="utf-8" /> +<title>This test validates resource timing information for a same-origin=>cross-origin=>same-origin redirect chain without Timing-Allow-Origin.</title> +<link rel="help" href="http://www.w3.org/TR/resource-timing/#performanceresourcetiming"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="resources/webperftestharness.js"></script> +<script src="resources/webperftestharnessextension.js"></script> + +<script> + setup({explicit_done: true}); + test_namespace('getEntriesByName'); + const pageOrigin = get_host_info()['ORIGIN']; + const crossOrigin = get_host_info()['REMOTE_ORIGIN']; + + function onload_test() + { + const entries = performance.getEntriesByName(document.getElementById('frameContext').src, 'resource'); + test_equals(entries.length, 1, 'There should be one entry.'); + const entry = entries[0]; + + test_equals(entry.redirectStart, 0, 'redirectStart == 0 in cross-origin redirect with no Timing-Allow-Origin.'); + test_equals(entry.redirectEnd, 0, 'redirectEnd == 0 in cross-origin redirect with no Timing-Allow-Origin.'); + test_greater_than(entry.fetchStart, 0, 'fetchStart > 0 in cross-origin redirect.'); + test_equals(entry.fetchStart, entry.startTime, 'startTime == fetchStart in cross-origin redirect with no Timing-Allow-Origin.'); + done(); + } +</script> + +</head> +<body> +<iframe id="frameContext" src="" style="width: 250px; height: 250px;"></iframe> +<script> + let destUrl = pageOrigin + '/resource-timing/resources/multi_redirect.py?'; + destUrl += 'page_origin=' + pageOrigin; + destUrl += '&cross_origin=' + crossOrigin; + const frameContext = document.getElementById('frameContext'); + frameContext.onload = onload_test; + frameContext.src = destUrl; +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/multi_redirect.py b/third_party/blink/web_tests/external/wpt/resource-timing/resources/multi_redirect.py index d1802a1..39121dd 100644 --- a/third_party/blink/web_tests/external/wpt/resource-timing/resources/multi_redirect.py +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/multi_redirect.py
@@ -13,27 +13,31 @@ except ValueError: pass + origin = request.url_parts.scheme + "://" + request.url_parts.hostname + ":" + str(request.url_parts.port) page_origin = request.GET.first("page_origin") cross_origin = request.GET.first("cross_origin") timing_allow = "0" if "timing_allow" in request.GET: timing_allow = request.GET.first("timing_allow") - redirect_url = "/resource-timing/resources/multi_redirect.py?" - redirect_url += "page_origin=" + page_origin - redirect_url += "&cross_origin=" + cross_origin - redirect_url += "&timing_allow=" + timing_allow - redirect_url += "&step=" + redirect_url_path = "/resource-timing/resources/multi_redirect.py?" + redirect_url_path += "page_origin=" + page_origin + redirect_url_path += "&cross_origin=" + cross_origin + redirect_url_path += "&timing_allow=" + timing_allow + redirect_url_path += "&step=" if step == 1: - redirect_url = cross_origin + redirect_url + "2" - if timing_allow != "0": + # On the first request, redirect to a cross origin URL + redirect_url = cross_origin + redirect_url_path + "2" + if timing_allow != "0" and origin != page_origin: response.headers.set("timing-allow-origin", page_origin) elif step == 2: - redirect_url = page_origin + redirect_url + "3" + # On the second request, redirect to a same origin URL + redirect_url = page_origin + redirect_url_path + "3" if timing_allow != "0": response.headers.set("timing-allow-origin", page_origin) else: + # On the third request, redirect to a static response redirect_url = page_origin + "/resource-timing/resources/blank_page_green.htm" response.status = 302
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/image_capture.mojom.js b/third_party/blink/web_tests/external/wpt/resources/chromium/image_capture.mojom.js index bf8dd16c..50428ffc 100644 --- a/third_party/blink/web_tests/external/wpt/resources/chromium/image_capture.mojom.js +++ b/third_party/blink/web_tests/external/wpt/resources/chromium/image_capture.mojom.js
@@ -434,7 +434,7 @@ return err; var kVersionSizes = [ - {version: 0, numBytes: 16} + {version: 0, numBytes: 24} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) @@ -445,15 +445,15 @@ return validator.validationError.NONE; }; - Point2D.encodedSize = codec.kStructHeaderSize + 8; + Point2D.encodedSize = codec.kStructHeaderSize + 16; Point2D.decode = function(decoder) { var packed; var val = new Point2D(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); - val.x = decoder.decodeStruct(codec.Float); - val.y = decoder.decodeStruct(codec.Float); + val.x = decoder.decodeStruct(codec.Double); + val.y = decoder.decodeStruct(codec.Double); return val; }; @@ -461,8 +461,8 @@ var packed; encoder.writeUint32(Point2D.encodedSize); encoder.writeUint32(0); - encoder.encodeStruct(codec.Float, val.x); - encoder.encodeStruct(codec.Float, val.y); + encoder.encodeStruct(codec.Double, val.x); + encoder.encodeStruct(codec.Double, val.y); }; function PhotoSettings(values) { this.initDefaults_();
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt index 3f30ee1..cc293b8 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt
@@ -21,7 +21,7 @@ PASS Cache.match with a non-2xx Response PASS Cache.match with a network error Response PASS Cache produces large Responses that can be cloned and read correctly. -PASS cors-exposed header should be stored correctly. +FAIL cors-exposed header should be stored correctly. promise_test: Unhandled rejection with value: object "ReferenceError: window is not defined" PASS MIME type should be set from content-header correctly. FAIL MIME type should be frozen at response construction. assert_equals: original and cached overwritten response mime types should match expected "text/html" but got "text/plain" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/worker/cache-match.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/worker/cache-match.https-expected.txt index 7326e23..81fddb1 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/worker/cache-match.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/worker/cache-match.https-expected.txt
@@ -20,7 +20,7 @@ PASS Cache.match with a non-2xx Response PASS Cache.match with a network error Response PASS Cache produces large Responses that can be cloned and read correctly. -PASS cors-exposed header should be stored correctly. +FAIL cors-exposed header should be stored correctly. promise_test: Unhandled rejection with value: object "ReferenceError: window is not defined" PASS MIME type should be set from content-header correctly. FAIL MIME type should be frozen at response construction. assert_equals: original and cached overwritten response mime types should match expected "text/html" but got "text/plain" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-with-range-request.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-with-range-request.https-expected.txt index eb273313..6e71b26 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-with-range-request.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-with-range-request.https-expected.txt
@@ -1,6 +1,6 @@ This is a testharness.js-based test. PASS range responses from single origin (same-origin) -FAIL range responses from multiple origins (cross-origin first) assert_equals: expected "TAINTED" but got "LOAD_ERROR" -PASS range responses from single origin with both opaque and non-opaque responses +FAIL range responses from multiple origins (cross-origin first) assert_equals: expected "TAINTED" but got "NOT_TAINTED" +FAIL range responses from single origin with both opaque and non-opaque responses assert_equals: expected "TAINTED" but got "NOT_TAINTED" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-request-css-cross-origin.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-request-css-cross-origin.https-expected.txt new file mode 100644 index 0000000..a4d342ad --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-request-css-cross-origin.https-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +FAIL setup global state assert_unreached: unregister and register should not fail: Failed to register a ServiceWorker: ServiceWorker script evaluation failed Reached unreachable code +FAIL MIME checking of CSS resources fetched via service worker when Content-Type is not set. assert_equals: The color must be overridden by cross origin CSS. expected "rgb(0, 0, 255)" but got "rgb(255, 0, 0)" +FAIL Same-origin policy for access to CSS resources fetched via service worker assert_throws: function "() => { + f.contentDocument.styleSheets[0].cssRules[0].cssText; + }" threw object "TypeError: Cannot read property 'cssText' of undefined" that is not a DOMException SecurityError: property "code" is equal to undefined, expected 18 +FAIL cleanup global state promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'unregister' of undefined" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-request-html-imports.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-request-html-imports.https-expected.txt new file mode 100644 index 0000000..3bc7820 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-request-html-imports.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Verify the FetchEvent for HTMLImports assert_unreached: unregister and register should not fail: Failed to register a ServiceWorker: ServiceWorker script evaluation failed Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/multipart-image.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/multipart-image.https-expected.txt new file mode 100644 index 0000000..e1bae60 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/multipart-image.https-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +FAIL initialize global state assert_unreached: unregister and register should not fail: Failed to register a ServiceWorker: ServiceWorker script evaluation failed Reached unreachable code +FAIL same-origin multipart image via SW should be readable Cannot read property 'contentWindow' of undefined +FAIL cross-origin multipart image via SW with approved CORS should be readable Cannot read property 'contentWindow' of undefined +FAIL cross-origin multipart image with no-cors via SW should not be readable Cannot read property 'contentWindow' of undefined +FAIL cross-origin multipart image via SW with rejected CORS should fail to load Cannot read property 'contentWindow' of undefined +FAIL restore global state Cannot read property 'unregister' of undefined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/opaque-response-preloaded.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/opaque-response-preloaded.https-expected.txt new file mode 100644 index 0000000..1a146d3e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/opaque-response-preloaded.https-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +FAIL Opaque responses should not be reused for XHRs, loading case assert_unreached: unregister and register should not fail: Failed to register a ServiceWorker: ServiceWorker script evaluation failed Reached unreachable code +FAIL Opaque responses should not be reused for XHRs, done case assert_unreached: unregister and register should not fail: Failed to register a ServiceWorker: ServiceWorker script evaluation failed Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resource-timing-cross-origin.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resource-timing-cross-origin.https-expected.txt new file mode 100644 index 0000000..99c6abc --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resource-timing-cross-origin.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Test that timing allow check fails when service worker changes origin from same to cross origin. assert_unreached: unexpected rejection: assert_equals: expected 1 but got 0 Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/respond-with-body-accessed-response.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/respond-with-body-accessed-response.https-expected.txt new file mode 100644 index 0000000..3ea07374 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/respond-with-body-accessed-response.https-expected.txt
@@ -0,0 +1,23 @@ +This is a testharness.js-based test. +PASS initialize global state +PASS test: type=basic +FAIL test: type=opaque promise_test: Unhandled rejection with value: "Failed to load url:TestRequest?type=opaque" +PASS test: type=default +PASS test: type=basic&clone=1 +FAIL test: type=opaque&clone=1 promise_test: Unhandled rejection with value: "Failed to load url:TestRequest?type=opaque&clone=1" +PASS test: type=default&clone=1 +PASS test: type=basic&clone=2 +FAIL test: type=opaque&clone=2 promise_test: Unhandled rejection with value: "Failed to load url:TestRequest?type=opaque&clone=2" +PASS test: type=default&clone=2 +PASS test: type=basic&passThroughCache=true +FAIL test: type=opaque&passThroughCache=true promise_test: Unhandled rejection with value: "Failed to load url:TestRequest?type=opaque&passThroughCache=true" +PASS test: type=default&passThroughCache=true +PASS test: type=basic&clone=1&passThroughCache=true +FAIL test: type=opaque&clone=1&passThroughCache=true promise_test: Unhandled rejection with value: "Failed to load url:TestRequest?type=opaque&clone=1&passThroughCache=true" +PASS test: type=default&clone=1&passThroughCache=true +PASS test: type=basic&clone=2&passThroughCache=true +FAIL test: type=opaque&clone=2&passThroughCache=true promise_test: Unhandled rejection with value: "Failed to load url:TestRequest?type=opaque&clone=2&passThroughCache=true" +PASS test: type=default&clone=2&passThroughCache=true +PASS restore global state +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/service-worker-csp-connect.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/service-worker-csp-connect.https-expected.txt new file mode 100644 index 0000000..b1def0b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/service-worker-csp-connect.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL CSP test for connect-src in ServiceWorkerGlobalScope assert_unreached: unregister and register should not fail: Failed to register a ServiceWorker: ServiceWorker script evaluation failed Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/service-worker-csp-default.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/service-worker-csp-default.https-expected.txt new file mode 100644 index 0000000..4982a4d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/service-worker-csp-default.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL CSP test for default-src in ServiceWorkerGlobalScope assert_unreached: unregister and register should not fail: Failed to register a ServiceWorker: ServiceWorker script evaluation failed Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/service-worker-csp-script.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/service-worker-csp-script.https-expected.txt new file mode 100644 index 0000000..871359eaa9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/service-worker-csp-script.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL CSP test for script-src in ServiceWorkerGlobalScope assert_unreached: unregister and register should not fail: Failed to register a ServiceWorker: ServiceWorker script evaluation failed Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt index 887068b..4b568b74 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt
@@ -3,6 +3,6 @@ mozlog==4.0 mozdebug==0.1.1 pillow==6.0.0 -urllib3[secure]==1.24.1 +urllib3[secure]==1.24.2 requests==2.21.0 six>=1.8
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt index 3930e12..0f847f0 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt +++ b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt
@@ -6,22 +6,23 @@ PASS WakeLock interface: existence and properties of interface prototype object PASS WakeLock interface: existence and properties of interface prototype object's "constructor" property PASS WakeLock interface: existence and properties of interface prototype object's @@unscopables property +FAIL WakeLock interface: operation requestPermission(WakeLockType) assert_own_property: interface object missing static operation expected property "requestPermission" missing PASS WakeLock interface: attribute type PASS WakeLock interface: attribute active PASS WakeLock interface: attribute onactivechange -FAIL WakeLock interface: operation request(WakeLockRequestOptions) assert_own_property: interface prototype object missing non-static operation expected property "request" missing +FAIL WakeLock interface: operation request() assert_own_property: interface prototype object missing non-static operation expected property "request" missing +FAIL WakeLock interface: operation abort() assert_own_property: interface prototype object missing non-static operation expected property "abort" missing FAIL WakeLock interface: operation query(WakeLockQueryFilter) assert_own_property: interface object missing static operation expected property "query" missing -FAIL WakeLock interface: operation requestPermission(WakeLockType) assert_own_property: interface object missing static operation expected property "requestPermission" missing FAIL WakeLock must be primary interface of new WakeLock("screen") assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" FAIL Stringification of new WakeLock("screen") assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" +FAIL WakeLock interface: new WakeLock("screen") must inherit property "requestPermission(WakeLockType)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" +FAIL WakeLock interface: calling requestPermission(WakeLockType) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" FAIL WakeLock interface: new WakeLock("screen") must inherit property "type" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" FAIL WakeLock interface: new WakeLock("screen") must inherit property "active" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" FAIL WakeLock interface: new WakeLock("screen") must inherit property "onactivechange" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" -FAIL WakeLock interface: new WakeLock("screen") must inherit property "request(WakeLockRequestOptions)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" -FAIL WakeLock interface: calling request(WakeLockRequestOptions) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" +FAIL WakeLock interface: new WakeLock("screen") must inherit property "request()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" +FAIL WakeLock interface: new WakeLock("screen") must inherit property "abort()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" FAIL WakeLock interface: new WakeLock("screen") must inherit property "query(WakeLockQueryFilter)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" FAIL WakeLock interface: calling query(WakeLockQueryFilter) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" -FAIL WakeLock interface: new WakeLock("screen") must inherit property "requestPermission(WakeLockType)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" -FAIL WakeLock interface: calling requestPermission(WakeLockType) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt index a17dfea9..0d9d4a9e 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt +++ b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt
@@ -6,21 +6,22 @@ FAIL WakeLock interface: existence and properties of interface prototype object assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing FAIL WakeLock interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing FAIL WakeLock interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing +FAIL WakeLock interface: member requestPermission Cannot use 'in' operator to search for 'requestPermission' in undefined FAIL WakeLock interface: attribute type assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing FAIL WakeLock interface: attribute active assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing FAIL WakeLock interface: attribute onactivechange assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing -FAIL WakeLock interface: operation request(WakeLockRequestOptions) assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing +FAIL WakeLock interface: operation request() assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing +FAIL WakeLock interface: operation abort() assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing FAIL WakeLock interface: operation query(WakeLockQueryFilter) assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing -FAIL WakeLock interface: member requestPermission Cannot use 'in' operator to search for 'requestPermission' in undefined FAIL WakeLock must be primary interface of new WakeLock("screen") assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" FAIL Stringification of new WakeLock("screen") assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" +FAIL WakeLock interface: new WakeLock("screen") must not have property "requestPermission" assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" FAIL WakeLock interface: new WakeLock("screen") must inherit property "type" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" FAIL WakeLock interface: new WakeLock("screen") must inherit property "active" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" FAIL WakeLock interface: new WakeLock("screen") must inherit property "onactivechange" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" -FAIL WakeLock interface: new WakeLock("screen") must inherit property "request(WakeLockRequestOptions)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" -FAIL WakeLock interface: calling request(WakeLockRequestOptions) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" +FAIL WakeLock interface: new WakeLock("screen") must inherit property "request()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" +FAIL WakeLock interface: new WakeLock("screen") must inherit property "abort()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" FAIL WakeLock interface: new WakeLock("screen") must inherit property "query(WakeLockQueryFilter)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" FAIL WakeLock interface: calling query(WakeLockQueryFilter) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" -FAIL WakeLock interface: new WakeLock("screen") must not have property "requestPermission" assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animation-effects/simple-iteration-progress-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animation-effects/simple-iteration-progress-expected.txt deleted file mode 100644 index 9fd64511..0000000 --- a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animation-effects/simple-iteration-progress-expected.txt +++ /dev/null
@@ -1,52 +0,0 @@ -This is a testharness.js-based test. -PASS Test zero iterations: iterations:0 iterationStart:0 duration:0 delay:1 fill:both -PASS Test zero iterations: iterations:0 iterationStart:0 duration:100 delay:1 fill:both -PASS Test zero iterations: iterations:0 iterationStart:0 duration:Infinity delay:1 fill:both -PASS Test zero iterations: iterations:0 iterationStart:2.5 duration:0 delay:1 fill:both -PASS Test zero iterations: iterations:0 iterationStart:2.5 duration:100 delay:1 fill:both -PASS Test zero iterations: iterations:0 iterationStart:2.5 duration:Infinity delay:1 fill:both -PASS Test zero iterations: iterations:0 iterationStart:3 duration:0 delay:1 fill:both -PASS Test zero iterations: iterations:0 iterationStart:3 duration:100 delay:1 fill:both -PASS Test zero iterations: iterations:0 iterationStart:3 duration:Infinity delay:1 fill:both -PASS Test integer iterations: iterations:3 iterationStart:0 duration:0 delay:1 fill:both -PASS Test integer iterations: iterations:3 iterationStart:0 duration:100 delay:1 fill:both -PASS Test integer iterations: iterations:3 iterationStart:0 duration:Infinity delay:1 fill:both -PASS Test integer iterations: iterations:3 iterationStart:2.5 duration:0 delay:1 fill:both -PASS Test integer iterations: iterations:3 iterationStart:2.5 duration:100 delay:1 fill:both -PASS Test integer iterations: iterations:3 iterationStart:2.5 duration:Infinity delay:1 fill:both -PASS Test integer iterations: iterations:3 iterationStart:3 duration:0 delay:1 fill:both -PASS Test integer iterations: iterations:3 iterationStart:3 duration:100 delay:1 fill:both -PASS Test integer iterations: iterations:3 iterationStart:3 duration:Infinity delay:1 fill:both -PASS Test fractional iterations: iterations:3.5 iterationStart:0 duration:0 delay:1 fill:both -PASS Test fractional iterations: iterations:3.5 iterationStart:0 duration:100 delay:1 fill:both -PASS Test fractional iterations: iterations:3.5 iterationStart:0 duration:Infinity delay:1 fill:both -PASS Test fractional iterations: iterations:3.5 iterationStart:2.5 duration:0 delay:1 fill:both -FAIL Test fractional iterations: iterations:3.5 iterationStart:2.5 duration:100 delay:1 fill:both assert_approx_equals: Value of progress in the after phase expected 1 +/- 0.001 but got 5.551115123125783e-16 -PASS Test fractional iterations: iterations:3.5 iterationStart:2.5 duration:Infinity delay:1 fill:both -PASS Test fractional iterations: iterations:3.5 iterationStart:3 duration:0 delay:1 fill:both -PASS Test fractional iterations: iterations:3.5 iterationStart:3 duration:100 delay:1 fill:both -PASS Test fractional iterations: iterations:3.5 iterationStart:3 duration:Infinity delay:1 fill:both -PASS Test infinity iterations: iterations:Infinity iterationStart:0 duration:0 delay:1 fill:both -PASS Test infinity iterations: iterations:Infinity iterationStart:0 duration:100 delay:1 fill:both -PASS Test infinity iterations: iterations:Infinity iterationStart:0 duration:Infinity delay:1 fill:both -FAIL Test infinity iterations: iterations:Infinity iterationStart:2.5 duration:0 delay:1 fill:both assert_approx_equals: Value of progress in the after phase expected 0.5 +/- 0.001 but got 1 -PASS Test infinity iterations: iterations:Infinity iterationStart:2.5 duration:100 delay:1 fill:both -PASS Test infinity iterations: iterations:Infinity iterationStart:2.5 duration:Infinity delay:1 fill:both -PASS Test infinity iterations: iterations:Infinity iterationStart:3 duration:0 delay:1 fill:both -PASS Test infinity iterations: iterations:Infinity iterationStart:3 duration:100 delay:1 fill:both -PASS Test infinity iterations: iterations:Infinity iterationStart:3 duration:Infinity delay:1 fill:both -PASS Test end delay: duration:100 delay:1 fill:both endDelay:50 -PASS Test end delay: duration:100 delay:1 fill:both endDelay:-50 -PASS Test end delay: duration:100 delay:1 fill:both endDelay:-100 -PASS Test end delay: duration:100 delay:1 fill:both endDelay:-200 -PASS Test end delay: iterationStart:0.5 duration:100 delay:1 fill:both endDelay:50 -FAIL Test end delay: iterationStart:0.5 duration:100 delay:1 fill:both endDelay:-50 assert_approx_equals: Value of progress in the after phase expected 0 +/- 0.001 but got 1 -PASS Test end delay: iterationStart:0.5 duration:100 delay:1 fill:both endDelay:-100 -FAIL Test end delay: iterations:2 duration:100 delay:1 fill:both endDelay:-100 assert_approx_equals: Value of progress in the after phase expected 0 +/- 0.001 but got 1 -PASS Test end delay: iterations:1 iterationStart:2 duration:100 delay:1 fill:both endDelay:-50 -FAIL Test end delay: iterations:1 iterationStart:2 duration:100 delay:1 fill:both endDelay:-100 assert_approx_equals: Value of progress in the after phase expected 0 +/- 0.001 but got 1 -PASS Test negative playback rate: duration:1 delay:1 fill:both playbackRate:-1 -FAIL Test negative playback rate: duration:0 delay:1 fill:both playbackRate:-1 assert_approx_equals: Value of progress in the before phase expected 0 +/- 0.001 but got 0.9999999999999999 -PASS Test negative playback rate: duration:0 iterations:0 delay:1 fill:both playbackRate:-1 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt index 2455866..969bdab 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 219 tests; 211 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 219 tests; 213 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS Partial interface Navigator: original interface defined PASS Partial dictionary WebGLContextAttributes: original dictionary defined @@ -11,14 +11,14 @@ PASS XR interface: existence and properties of interface prototype object's "constructor" property PASS XR interface: existence and properties of interface prototype object's @@unscopables property PASS XR interface: operation supportsSessionMode(XRSessionMode) -FAIL XR interface: operation requestSession(XRSessionMode) assert_equals: property has wrong .length expected 1 but got 0 +PASS XR interface: operation requestSession(XRSessionMode) PASS XR interface: attribute ondevicechange PASS XR must be primary interface of navigator.xr PASS Stringification of navigator.xr PASS XR interface: navigator.xr must inherit property "supportsSessionMode(XRSessionMode)" with the proper type PASS XR interface: calling supportsSessionMode(XRSessionMode) on navigator.xr with too few arguments must throw TypeError PASS XR interface: navigator.xr must inherit property "requestSession(XRSessionMode)" with the proper type -FAIL XR interface: calling requestSession(XRSessionMode) on navigator.xr with too few arguments must throw TypeError assert_unreached: Should have rejected: Called with 0 arguments Reached unreachable code +PASS XR interface: calling requestSession(XRSessionMode) on navigator.xr with too few arguments must throw TypeError PASS XR interface: navigator.xr must inherit property "ondevicechange" with the proper type PASS XRSession interface: existence and properties of interface object PASS XRSession interface object length
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html index c5956e7f..50a9d344 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html
@@ -9,6 +9,6 @@ "Tests requestSession resolves when supported", (session) => { assert_not_equals(session, null); - }, { supportsImmersive:true }, { mode: 'immersive-vr' }); + }, { supportsImmersive:true }, 'immersive-vr'); </script> </body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_no_gesture.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_no_gesture.https.html index c1b32867..eb5a4fd 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_no_gesture.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_no_gesture.https.html
@@ -9,7 +9,7 @@ (t) => { return XRTest.simulateDeviceConnection({ supportsImmersive:true }) .then( (controller) => promise_rejects( - t, 'SecurityError', navigator.xr.requestSession({ mode: 'immersive-vr' }))); + t, 'SecurityError', navigator.xr.requestSession('immersive-vr'))); }); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_unsupported.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_unsupported.https.html index 60e9e6c..2592f3a 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_unsupported.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_unsupported.https.html
@@ -13,7 +13,7 @@ resolve(promise_rejects( t, "NotSupportedError", - navigator.xr.requestSession({ mode: 'immersive-vr' }) + navigator.xr.requestSession('immersive-vr') )) }); }));
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_no_mode.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_no_mode.https.html new file mode 100644 index 0000000..c4ac3f6b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_no_mode.https.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <script> + xr_promise_test( + "Requesting a session with no mode rejects", + (t) => { + return XRTest.simulateDeviceConnection({ supportsImmersive:false }) + .then( (controller) => new Promise((resolve) => { + XRTest.simulateUserActivation( () => { + resolve(promise_rejects( + t, + new TypeError(), + navigator.xr.requestSession() + )) + }); + })); + }); + </script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html index 241b5de..40e6f49 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html
@@ -8,9 +8,7 @@ "Requesting non-immersive session outside of a user gesture succeeds", (t) => { return XRTest.simulateDeviceConnection({ supportsImmersive:false }) - .then( (controller) => navigator.xr.requestSession({ - mode: 'inline' - })) + .then( (controller) => navigator.xr.requestSession('inline')) .then( (session) => { assert_not_equals(session, null); }); }); </script>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getPose.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getPose.https.html index 2c75275..a8015e3 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getPose.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getPose.https.html
@@ -12,8 +12,6 @@ let nonImmersiveTestName = "XRFrame.getPose works for non-immersive sessions"; let fakeDeviceInitParams = { supportsImmersive:true }; -let immersiveSessionOptions = { mode: 'immersive-vr' }; -let nonImmersiveSessionOptions = { outputContext: getOutputContext() }; let testFunction = function(session, fakeDeviceController, t) { // Need to have a valid pose or input events don't process. @@ -88,8 +86,8 @@ }; xr_session_promise_test(immersiveTestName, testFunction, - fakeDeviceInitParams, immersiveSessionOptions); + fakeDeviceInitParams, 'immersive-vr'); xr_session_promise_test(nonImmersiveTestName, testFunction, - fakeDeviceInitParams, nonImmersiveSessionOptions); + fakeDeviceInitParams, 'inline'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_lifetime.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_lifetime.https.html index 30cf5f9..b924c89 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_lifetime.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_lifetime.https.html
@@ -13,9 +13,6 @@ let fakeDeviceInitParams = { supportsImmersive:true }; - let immersiveSessionOptions = { mode: 'immersive-vr' }; - let nonImmersiveSessionOptions = { outputContext: getOutputContext() }; - let testFunction = (testSession, testController, t) => new Promise((resolve) => { let staleFrame = null; let currentReferenceSpace = null; @@ -48,9 +45,9 @@ }); xr_session_promise_test(immersiveTestName, testFunction, - fakeDeviceInitParams, immersiveSessionOptions); + fakeDeviceInitParams, 'immersive-vr'); xr_session_promise_test(nonImmersiveTestName, testFunction, - fakeDeviceInitParams, nonImmersiveSessionOptions); + fakeDeviceInitParams, 'inline'); </script> </body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_constructor.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_constructor.https.html index abaf8bf9..1566697 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_constructor.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_constructor.https.html
@@ -9,7 +9,6 @@ let testName = "XRRigidTransform constructor works"; let fakeDeviceInitParams = { supportsImmersive: true }; -let requestSessionOptions = { mode: 'immersive-vr' }; let testFunction = (session, fakeDeviceController, t) => new Promise((resolve, reject) => { @@ -108,6 +107,6 @@ }); xr_session_promise_test(testName, testFunction, fakeDeviceInitParams, - requestSessionOptions); + 'immersive-vr'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_inverse.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_inverse.https.html index e795a99..da34fec 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_inverse.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_inverse.https.html
@@ -9,7 +9,6 @@ let testName = "XRRigidTransform inverse works"; let fakeDeviceInitParams = { supportsImmersive: true }; -let requestSessionOptions = { mode: 'immersive-vr' }; let testFunction = (session, fakeDeviceController, t) => new Promise((resolve, reject) => { @@ -103,6 +102,6 @@ }); xr_session_promise_test(testName, testFunction, fakeDeviceInitParams, - requestSessionOptions); + 'immersive-vr'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html index cc7b880..d45349a 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html
@@ -13,9 +13,6 @@ let fakeDeviceInitParams = { supportsImmersive:true }; - let immersiveSessionOptions = { mode: 'immersive-vr' }; - let nonImmersiveSessionOptions = { mode: 'inline' }; - let testFunction = (session) => new Promise((resolve, reject) => { // Schedule and immediately cancel animation frame @@ -49,9 +46,9 @@ }); xr_session_promise_test(immersiveTestName, testFunction, - fakeDeviceInitParams, immersiveSessionOptions); + fakeDeviceInitParams, 'immersive-vr'); xr_session_promise_test(nonImmersiveTestName, testFunction, - fakeDeviceInitParams, nonImmersiveSessionOptions); + fakeDeviceInitParams, 'inline'); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html index e6a9c06..b93f4e2 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html
@@ -12,9 +12,6 @@ let fakeDeviceInitParams = { supportsImmersive:true }; - let immersiveSessionOptions = { mode: 'immersive-vr' }; - let nonImmersiveSessionOptions = { mode: 'inline' }; - let testFunction = (testSession) => new Promise((resolve) => { let counter = 0; @@ -37,9 +34,9 @@ }); xr_session_promise_test( - immersiveTestName, testFunction, fakeDeviceInitParams, immersiveSessionOptions); + immersiveTestName, testFunction, fakeDeviceInitParams, 'immersive-vr'); xr_session_promise_test( - nonImmersiveTestName, testFunction, fakeDeviceInitParams, nonImmersiveSessionOptions); + nonImmersiveTestName, testFunction, fakeDeviceInitParams, 'inline'); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_end.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_end.https.html index 6365c7d..26b6b47 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_end.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_end.https.html
@@ -11,9 +11,6 @@ let watcherDone = new Event("watcherdone"); const fakeDeviceInitParams = { supportsImmersive:true }; - const immersiveSessionOptions = { mode: 'immersive-vr' }; - const nonImmersiveSessionOptions = { mode: 'inline' }; - let testFunction = function(session, testDeviceController, t) { let eventWatcher = new EventWatcher(t, session, ["end", "watcherdone"]); let eventPromise = eventWatcher.wait_for(["end", "watcherdone"]); @@ -31,8 +28,8 @@ }; xr_session_promise_test(immersivetestName, testFunction, - fakeDeviceInitParams, immersiveSessionOptions); + fakeDeviceInitParams, 'immersive-vr'); xr_session_promise_test(nonimmersiveTestName, testFunction, - fakeDeviceInitParams, nonImmersiveSessionOptions); + fakeDeviceInitParams, 'inline'); </script> </body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_identity_referenceSpace.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_identity_referenceSpace.https.html index fb18edf..07abc397 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_identity_referenceSpace.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_identity_referenceSpace.https.html
@@ -14,9 +14,6 @@ let fakeDeviceInitParams = { supportsImmersive: true }; - let immersiveSessionOptions = { mode: 'immersive-vr' }; - let inlineSessionOptions = { mode: 'inline' }; - const identityMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; // Valid matrices for when we don't care about specific values @@ -80,9 +77,9 @@ }; xr_session_promise_test(inlineTestName, testFunction, - fakeDeviceInitParams, inlineSessionOptions); + fakeDeviceInitParams, 'inline'); xr_session_promise_test(immersiveTestName, testFunction, - fakeDeviceInitParams, immersiveSessionOptions); + fakeDeviceInitParams, 'immersive-vr'); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_mode.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_mode.https.html index 4b54d948..a1d0660 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_mode.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_mode.https.html
@@ -11,7 +11,7 @@ return XRTest.simulateDeviceConnection({ supportsImmersive:true }) .then( (controller) => new Promise((resolve) => { XRTest.simulateUserActivation( () => { - resolve(navigator.xr.requestSession({ mode: 'immersive-vr' }).then( (session) => { + resolve(navigator.xr.requestSession('immersive-vr').then( (session) => { assert_equals(session.mode, 'immersive-vr'); })); });
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_prevent_multiple_exclusive.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_prevent_multiple_exclusive.https.html index c2e7f3b..e61bd39 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_prevent_multiple_exclusive.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_prevent_multiple_exclusive.https.html
@@ -12,7 +12,7 @@ return XRTest.simulateDeviceConnection({ supportsImmersive:true }) .then( (controller) => new Promise((resolve) => { XRTest.simulateUserActivation( () => { - resolve(navigator.xr.requestSession({ mode: 'immersive-vr' }) + resolve(navigator.xr.requestSession('immersive-vr') .then( (session) => new Promise((resolve) => { XRTest.simulateUserActivation( () => { // Requesting a second immersive session when another immersive @@ -22,13 +22,13 @@ resolve(promise_rejects( t, "InvalidStateError", - navigator.xr.requestSession({ mode: 'immersive-vr' }) + navigator.xr.requestSession('immersive-vr') ).then( () => { // End the immersive session and try again. Now the immersive // session creation should succeed. return session.end().then( () => new Promise((resolve) => { XRTest.simulateUserActivation( () => { - resolve(navigator.xr.requestSession({ mode: 'immersive-vr' })); + resolve(navigator.xr.requestSession('immersive-vr')); }); })); }));
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html index 92f7d1f7..2ed468b 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html
@@ -13,9 +13,6 @@ let fakeDeviceInitParams = { supportsImmersive:true }; - let immersiveSessionOptions = { mode: 'immersive-vr' }; - let nonImmersiveSessionOptions = { mode: 'inline' }; - let testFunction = (testSession) => new Promise((resolve) => { function onFrame(time, xrFrame) { assert_true(xrFrame instanceof XRFrame); @@ -27,9 +24,9 @@ }); xr_session_promise_test(immersiveTestName, testFunction, - fakeDeviceInitParams, immersiveSessionOptions); + fakeDeviceInitParams, 'immersive-vr'); xr_session_promise_test(nonImmersiveTestName, testFunction, - fakeDeviceInitParams, nonImmersiveSessionOptions); + fakeDeviceInitParams, 'inline'); </script> </body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html index 2278666..44e903e 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html
@@ -28,7 +28,6 @@ }; const fakeDeviceInitOptions = { supportsImmersive:true }; - const sessionOptions = { mode: 'immersive-vr' }; let testSession; @@ -77,6 +76,6 @@ } xr_session_promise_test( - testName, testFunction, fakeDeviceInitOptions, sessionOptions); + testName, testFunction, fakeDeviceInitOptions, 'immersive-vr'); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html index 8c8e26a..5606fa1a 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html
@@ -14,9 +14,6 @@ let fakeDeviceInitParams = { supportsImmersive: true }; - let immersiveSessionOptions = { mode: 'immersive-vr' }; - let nonImmersiveSessionOptions = { mode: 'inline' }; - // Valid matrices for when we don't care about specific values const validPoseMatrix = [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1]; const validProjectionMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 3, 2, -1, -1, 0, 0, -0.2, 0]; @@ -71,9 +68,9 @@ }; xr_session_promise_test(nonImmersiveTestName, testFunction, - fakeDeviceInitParams, nonImmersiveSessionOptions); + fakeDeviceInitParams, 'inline'); xr_session_promise_test(immersiveTestName, testFunction, - fakeDeviceInitParams, immersiveSessionOptions); + fakeDeviceInitParams, 'immersive-vr'); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html index ed31f37..0027d5d 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html
@@ -13,9 +13,6 @@ let fakeDeviceInitParams = { supportsImmersive: true }; - let immersiveSessionOptions = { mode: 'immersive-vr' }; - let nonImmersiveSessionOptions = { mode: 'inline' }; - let testFunction = function(session, fakeDeviceController, t) { return promise_rejects(t, new TypeError(), session.requestReferenceSpace({ type: "foo" })) .then(() => promise_rejects(t, "NotSupportedError", session.requestReferenceSpace({ type: "stationary" }))) @@ -75,9 +72,9 @@ }; xr_session_promise_test( - immersiveTestName, testFunction, fakeDeviceInitParams, immersiveSessionOptions); + immersiveTestName, testFunction, fakeDeviceInitParams, 'immersive-vr'); xr_session_promise_test( - nonImmersiveTestName, testFunction, fakeDeviceInitParams, nonImmersiveSessionOptions); + nonImmersiveTestName, testFunction, fakeDeviceInitParams, 'inline'); </script> </body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_transfer_outputContext.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_transfer_outputContext.https.html index 658cb32..759d97ba 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_transfer_outputContext.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_transfer_outputContext.https.html
@@ -11,8 +11,8 @@ return XRTest.simulateDeviceConnection({ supportsImmersive:false }) .then( (controller) => { return Promise.all([ - navigator.xr.requestSession({ mode: 'inline'}), - navigator.xr.requestSession({ mode: 'inline'}) + navigator.xr.requestSession('inline'), + navigator.xr.requestSession('inline') ]).then((sessions) => { t.step(() => { assert_not_equals(sessions[0], null);
diff --git a/third_party/blink/web_tests/fast/css/containment/compositing-inputs-root-iframe-crash-expected.txt b/third_party/blink/web_tests/fast/css/containment/compositing-inputs-root-iframe-crash-expected.txt new file mode 100644 index 0000000..5f1872e --- /dev/null +++ b/third_party/blink/web_tests/fast/css/containment/compositing-inputs-root-iframe-crash-expected.txt
@@ -0,0 +1 @@ +The test passes if it doesn't crash in debug.
diff --git a/third_party/blink/web_tests/fast/css/containment/compositing-inputs-root-iframe-crash.html b/third_party/blink/web_tests/fast/css/containment/compositing-inputs-root-iframe-crash.html new file mode 100644 index 0000000..c15a559 --- /dev/null +++ b/third_party/blink/web_tests/fast/css/containment/compositing-inputs-root-iframe-crash.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<script> + if (window.testRunner) + testRunner.dumpAsText(); +</script> +<p>The test passes if it doesn't crash in debug.</p> +<iframe style="contain: strict;" src="http://xx/"> +</iframe>
diff --git a/third_party/blink/web_tests/fast/events/no-mouse-cursor-update-after-layout-change.html b/third_party/blink/web_tests/fast/events/update-mouse-cursor-after-layout-change.html similarity index 72% rename from third_party/blink/web_tests/fast/events/no-mouse-cursor-update-after-layout-change.html rename to third_party/blink/web_tests/fast/events/update-mouse-cursor-after-layout-change.html index 659d828..b836263 100644 --- a/third_party/blink/web_tests/fast/events/no-mouse-cursor-update-after-layout-change.html +++ b/third_party/blink/web_tests/fast/events/update-mouse-cursor-after-layout-change.html
@@ -29,14 +29,11 @@ <div id="target"></div> </div> <script> -var addedOverlay = false; - function addOverlay() { var testContainer = document.getElementById('test-container'); var overlay = document.createElement('div'); overlay.id='overlay'; testContainer.appendChild(overlay); - addedOverlay = true; } window.onload = async () => { @@ -49,10 +46,9 @@ var target = document.getElementById('target'); var rect = target.getBoundingClientRect(); await mouseMoveTo(rect.left + 3, rect.top + 3); - await waitFor( () => { return internals.getCurrentCursorInfo() == 'type=IBeam hotSpot=0,0';}, 'wait for move to target'); + assert_equals(internals.getCurrentCursorInfo(), 'type=IBeam hotSpot=0,0', 'wait for move to target'); await mouseClickOn(rect.left + 3, rect.top + 3); - await waitFor(() => { return addedOverlay; }); - await conditionHolds( () => { return internals.getCurrentCursorInfo() == 'type=IBeam hotSpot=0,0';}, 'wait for no mouse cursor change'); - }, 'Tests that there is no mouse cursor update when the element underneath the mouse cursor is changed.'); + assert_equals(internals.getCurrentCursorInfo(), 'type=Wait hotSpot=0,0', 'wait for mouse cursor change'); + }, 'Tests that there is mouse cursor update when the element underneath the mouse cursor is changed.'); } </script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/events/no_hover_update_after_layout_change.html b/third_party/blink/web_tests/fast/events/update_hover_after_layout_change.html similarity index 63% rename from third_party/blink/web_tests/fast/events/no_hover_update_after_layout_change.html rename to third_party/blink/web_tests/fast/events/update_hover_after_layout_change.html index e2eece8f..e60016b 100644 --- a/third_party/blink/web_tests/fast/events/no_hover_update_after_layout_change.html +++ b/third_party/blink/web_tests/fast/events/update_hover_after_layout_change.html
@@ -23,23 +23,15 @@ var eventList = []; var x = 100; var y = 100; -var addedBlue = false; function addBlue() { - document.body.innerHTML += '<div id="blue"></div>'; - var blue = document.getElementById("blue"); + var blue = document.createElement('div'); + blue.id = "blue"; var events = ['mouseover', 'mousemove', 'mouseout', 'mouseenter', 'mouseleave']; events.forEach(function (event) { blue.addEventListener(event, addMouseEvents); }); - addedBlue = true; -} - -function checkMouseOverEvent() { - var result = eventList.join(); - assert_true(result == ''); - assert_equals(getComputedStyle(document.getElementById("blue")).backgroundColor, "rgb(0, 0, 255)"); - assert_true(internals.runtimeFlags.updateHoverFromLayoutChangeAtBeginFrameEnabled) + document.body.appendChild(blue); } function addMouseEvents(event) { @@ -49,8 +41,9 @@ promise_test (async () => { document.addEventListener('click', addBlue); await mouseClickOn(x, y); - await waitFor(() => { return addedBlue; }); - await conditionHolds(() => { return addedBlue; }); - checkMouseOverEvent(); -}, 'Tests that the mouseover event is not fired and the element has no hover effect when the element underneath the mouse cursor is changed.'); + var result = eventList.join(); + assert_true(result == 'mouseover,mouseenter'); + assert_true(document.getElementById("blue").matches(':hover')); + assert_true(internals.runtimeFlags.updateHoverFromLayoutChangeAtBeginFrameEnabled); +}, 'Tests that the mouseover event is fired and the element has hover effect when the element underneath the mouse cursor is changed.'); </script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/events/update_hover_after_layout_change_at_begin_frame.html b/third_party/blink/web_tests/fast/events/update_hover_after_layout_change_at_begin_frame.html new file mode 100644 index 0000000..7abc3496 --- /dev/null +++ b/third_party/blink/web_tests/fast/events/update_hover_after_layout_change_at_begin_frame.html
@@ -0,0 +1,44 @@ +<!DOCTYPE html> +<script src='../../resources/gesture-util.js'></script> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> + +<style> +#blue { + background-color: rgb(0, 0, 255); + position: absolute; + left: 75px; + top: 75px; + height: 100px; + width: 100px; +} +#blue:hover { + background-color: rgb(255, 255, 0); +} +</style> +<div id="blue"></div> +<script> +var x = 100; +var y = 100; +var blue = document.getElementById('blue'); + +window.onload = async () => { + if (window.internals) { + internals.runtimeFlags.updateHoverFromLayoutChangeAtBeginFrameEnabled = true; + } + + promise_test(async () => { + await mouseMoveTo(x, y); + await raf(); + assert_true(blue.matches(':hover'), "Hover on the element blue"); + // Move the element blue away from the mouse cursor. + blue.style.top = y + 500 + 'px'; + // Force a layout change. + assert_equals(blue.offsetTop, 600, "Check that the blue element is moved by 600px"); + assert_true(blue.matches(':hover'), "The hover state is not yet updated"); + await raf(); + assert_false(blue.matches(':hover'), "The hover state is updated after the begin frame"); + }, 'The hover state is updated at the begin frame after the layout changes.'); + +} +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/clipboard/README.md b/third_party/blink/web_tests/http/tests/clipboard/README.md index 4e170d3..baa33c23 100644 --- a/third_party/blink/web_tests/http/tests/clipboard/README.md +++ b/third_party/blink/web_tests/http/tests/clipboard/README.md
@@ -1,4 +1,4 @@ -spec: https://w3c.github.io/clipboard-apis/ +spec: https://w3c.github.io/clipboard-apis/#async-clipboard-api This directory contains async clipboard tests automated through use of Chrome-specific test helper `permissions-helper.js`, and requiring an http
diff --git a/third_party/blink/web_tests/http/tests/clipboard/async-write-blobs-read-blobs.html b/third_party/blink/web_tests/http/tests/clipboard/async-write-blobs-read-blobs.html index 589ab2c..30ccb79 100644 --- a/third_party/blink/web_tests/http/tests/clipboard/async-write-blobs-read-blobs.html +++ b/third_party/blink/web_tests/http/tests/clipboard/async-write-blobs-read-blobs.html
@@ -3,6 +3,7 @@ <title> Async Clipboard write blobs -> read blobs tests </title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../resources/permissions-helper.js"></script> @@ -23,12 +24,20 @@ assert_equals(blobText.type, 'text/plain'); assert_equals(blobImage.type, 'image/png'); - await navigator.clipboard.write( - {'text/plain' : blobText, 'image/png' : blobImage}); - const output = await navigator.clipboard.read(); + const clipboardItemInput = new ClipboardItem( + {'text/plain' : blobText, 'image/png' : blobImage}); - assert_equals(Object.keys(output).length, 2); - assert_equals(output['text/plain'].type, 'text/plain'); - assert_equals(output['image/png'].type, 'image/png'); -}, 'Verify write and read clipboard (multiple blobs)'); + await navigator.clipboard.write([clipboardItemInput]); + const clipboardItems = await navigator.clipboard.read(); + + assert_equals(clipboardItems.length, 1); + const clipboardItem = clipboardItems[0]; + assert_true(clipboardItem instanceof ClipboardItem); + + assert_equals(clipboardItem.types.length, 2); + const blobTextOutput = await clipboardItem.getType('text/plain'); + const blobImageOutput = await clipboardItem.getType('image/png'); + assert_equals(blobTextOutput.type, 'text/plain'); + assert_equals(blobImageOutput.type, 'image/png'); +}, 'Verify write and read clipboard (multiple types)'); </script>
diff --git a/third_party/blink/web_tests/http/tests/clipboard/async-write-image-read-image.html b/third_party/blink/web_tests/http/tests/clipboard/async-write-image-read-image.html index ec617163..3cf6d9b 100644 --- a/third_party/blink/web_tests/http/tests/clipboard/async-write-image-read-image.html +++ b/third_party/blink/web_tests/http/tests/clipboard/async-write-image-read-image.html
@@ -1,8 +1,10 @@ <!DOCTYPE html> <meta charset="utf-8"> <title> - Async Clipboard write image/png Blob -> read image/png Blob tests + Async Clipboard write [image/png ClipboardItem] -> + read [image/png ClipboardItem] tests </title> +<link rel="help" href="https://w3c.github.io/clipboard-apis/#async-clipboard-api"> <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../resources/permissions-helper.js"></script> @@ -44,10 +46,15 @@ const blobInput = await loadBlob('resources/greenbox.png'); assert_equals(blobInput.type, 'image/png'); - await navigator.clipboard.write({'image/png' : blobInput}); - const blobsOutput = await navigator.clipboard.read(); - assert_equals(Object.keys(blobsOutput).length, 1); - const blobOutput = blobsOutput['image/png']; + const clipboardItemInput = new ClipboardItem({'image/png' : blobInput}); + await navigator.clipboard.write([clipboardItemInput]); + const clipboardItems = await navigator.clipboard.read(); + + assert_equals(clipboardItems.length, 1); + const clipboardItem = clipboardItems[0]; + assert_true(clipboardItem instanceof ClipboardItem); + assert_equals(clipboardItem.types.length, 1); + const blobOutput = await clipboardItem.getType('image/png'); assert_equals(blobOutput.type, 'image/png'); document.getElementById('image-on-clipboard').src = @@ -57,5 +64,5 @@ const comparableOutput = await getBitmapString(blobOutput); assert_equals(comparableOutput, comparableInput); -}, 'Verify write and read clipboard (image/png Blob)'); +}, 'Verify write and read clipboard [image/png ClipboardItem]'); </script>
diff --git a/third_party/blink/web_tests/resources/gesture-util.js b/third_party/blink/web_tests/resources/gesture-util.js index eafe130..36863d0 100644 --- a/third_party/blink/web_tests/resources/gesture-util.js +++ b/third_party/blink/web_tests/resources/gesture-util.js
@@ -373,3 +373,12 @@ y: rect.y + rect.height / 2 }; } + +// Requests an animation frame. +function raf() { + return new Promise((resolve) => { + requestAnimationFrame(() => { + resolve(); + }); + }); +}
diff --git a/third_party/blink/web_tests/virtual/native-file-system/external/wpt/native-file-system/README.txt b/third_party/blink/web_tests/virtual/native-file-system/external/wpt/native-file-system/README.txt new file mode 100644 index 0000000..27be796 --- /dev/null +++ b/third_party/blink/web_tests/virtual/native-file-system/external/wpt/native-file-system/README.txt
@@ -0,0 +1,2 @@ +# This suite runs the tests with +# --enable-features=NativeFilesystemAPI
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/service-worker-csp-default.https-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/service-worker-csp-default.https-expected.txt deleted file mode 100644 index 7409f704..0000000 --- a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/service-worker-csp-default.https-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -This is a testharness.js-based test. -PASS CSP test for default-src in ServiceWorkerGlobalScope -PASS importScripts test for default-src -FAIL eval test for default-src assert_throws: eval() should throw EvalError. function "function() { eval('1 + 1'); }" did not throw -PASS Fetch test for default-src -PASS Redirected fetch test for default-src -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/service-worker-csp-script.https-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/service-worker-csp-script.https-expected.txt deleted file mode 100644 index a4f95319..0000000 --- a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/service-worker-csp-script.https-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -This is a testharness.js-based test. -PASS CSP test for script-src in ServiceWorkerGlobalScope -PASS importScripts test for script-src -FAIL eval test for script-src assert_throws: eval() should throw EvalError. function "function() { eval('1 + 1'); }" did not throw -PASS Fetch test for script-src -PASS Redirected fetch test for script-src -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index bff890f..92602f3 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -1071,6 +1071,11 @@ attribute @@toStringTag getter clipboardData method constructor +interface ClipboardItem + attribute @@toStringTag + getter types + method constructor + method getType interface CloseEvent : Event attribute @@toStringTag getter code
diff --git a/third_party/blink/web_tests/xr/ar_hittest.html b/third_party/blink/web_tests/xr/ar_hittest.html index 430adc1..d99409cf5 100644 --- a/third_party/blink/web_tests/xr/ar_hittest.html +++ b/third_party/blink/web_tests/xr/ar_hittest.html
@@ -16,7 +16,7 @@ let fakeDeviceInitParams = { supportsImmersive: false, supportsEnvironmentIntegration: true }; -let requestSessionOptions = [ {mode: 'legacy-inline-ar' } ]; +let requestSessionOptions = [ 'legacy-inline-ar' ]; let expectedHitMatrix = [1, 0, 0, 1, 0, 1, 0, 2,
diff --git a/third_party/blink/web_tests/xr/events_session_resetpose.html b/third_party/blink/web_tests/xr/events_session_resetpose.html index ab37bf3..0fdc5e9 100644 --- a/third_party/blink/web_tests/xr/events_session_resetpose.html +++ b/third_party/blink/web_tests/xr/events_session_resetpose.html
@@ -18,8 +18,8 @@ let fakeDeviceInitParams = { supportsImmersive:true }; let requestSessionOptions = [ - { mode: 'inline' }, - { mode: 'immersive-vr' }, + 'inline', + 'immersive-vr', ]; let testFunction = function(session, t, fakeDeviceController) {
diff --git a/third_party/blink/web_tests/xr/events_session_select.html b/third_party/blink/web_tests/xr/events_session_select.html index 9bc49eb..ac10f41d 100644 --- a/third_party/blink/web_tests/xr/events_session_select.html +++ b/third_party/blink/web_tests/xr/events_session_select.html
@@ -17,7 +17,7 @@ let fakeDeviceInitParams = { supportsImmersive:true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = function(session, t, fakeDeviceController) { let eventWatcher = new EventWatcher(
diff --git a/third_party/blink/web_tests/xr/events_session_select_subframe.html b/third_party/blink/web_tests/xr/events_session_select_subframe.html index 7f89fe7..6933037 100644 --- a/third_party/blink/web_tests/xr/events_session_select_subframe.html +++ b/third_party/blink/web_tests/xr/events_session_select_subframe.html
@@ -18,7 +18,7 @@ let fakeDeviceInitParams = { supportsImmersive:true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = function(session, t, fakeDeviceController) { let eventWatcher = new EventWatcher(
diff --git a/third_party/blink/web_tests/xr/exclusive_requestFrame_nolayer.html b/third_party/blink/web_tests/xr/exclusive_requestFrame_nolayer.html index 7e8222bd..0bfd705 100644 --- a/third_party/blink/web_tests/xr/exclusive_requestFrame_nolayer.html +++ b/third_party/blink/web_tests/xr/exclusive_requestFrame_nolayer.html
@@ -14,8 +14,8 @@ let fakeDeviceInitParams = { supportsImmersive:true }; let requestSessionOptions = [ - { mode: 'immersive-vr' }, - { mode: 'inline' } + 'immersive-vr', + 'inline' ]; let testFunction = (session) => new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/xr/getInputPose_hand.html b/third_party/blink/web_tests/xr/getInputPose_hand.html index e5e9cd69..c08b0a4 100644 --- a/third_party/blink/web_tests/xr/getInputPose_hand.html +++ b/third_party/blink/web_tests/xr/getInputPose_hand.html
@@ -16,7 +16,7 @@ let fakeDeviceInitParams = { supportsImmersive: true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = (session, t, fakeDeviceController) => new Promise((resolve) => {
diff --git a/third_party/blink/web_tests/xr/getInputPose_handedness.html b/third_party/blink/web_tests/xr/getInputPose_handedness.html index 08ebc6a..78646c7 100644 --- a/third_party/blink/web_tests/xr/getInputPose_handedness.html +++ b/third_party/blink/web_tests/xr/getInputPose_handedness.html
@@ -15,7 +15,7 @@ let fakeDeviceInitParams = { supportsImmersive: true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = (session, t, fakeDeviceController) => new Promise((resolve) => {
diff --git a/third_party/blink/web_tests/xr/getInputPose_ray.html b/third_party/blink/web_tests/xr/getInputPose_ray.html index ce0cdee..408a79b 100644 --- a/third_party/blink/web_tests/xr/getInputPose_ray.html +++ b/third_party/blink/web_tests/xr/getInputPose_ray.html
@@ -15,7 +15,7 @@ let fakeDeviceInitParams = { supportsImmersive: true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = (session, t, fakeDeviceController) => new Promise((resolve) => {
diff --git a/third_party/blink/web_tests/xr/navigator_xr_blocks_getVRDisplays.html b/third_party/blink/web_tests/xr/navigator_xr_blocks_getVRDisplays.html index 520333f..ba76f212 100644 --- a/third_party/blink/web_tests/xr/navigator_xr_blocks_getVRDisplays.html +++ b/third_party/blink/web_tests/xr/navigator_xr_blocks_getVRDisplays.html
@@ -3,7 +3,7 @@ <script src="../resources/testharnessreport.js"></script> <script> -promise_test((t) => navigator.xr.requestSession({ mode: 'immersive-vr' }).catch(() => { +promise_test((t) => navigator.xr.requestSession('immersive-vr').catch(() => { return promise_rejects(t, "InvalidStateError", navigator.getVRDisplays()); }), "Test that calls to navigator.getVRDisplays are blocked once navigator.xr has been accessed.");
diff --git a/third_party/blink/web_tests/xr/navigator_xr_detached.html b/third_party/blink/web_tests/xr/navigator_xr_detached.html index e90a33d..27e3a04 100644 --- a/third_party/blink/web_tests/xr/navigator_xr_detached.html +++ b/third_party/blink/web_tests/xr/navigator_xr_detached.html
@@ -13,7 +13,7 @@ var nav_xr = window.frames[0].navigator.xr; document.getElementById("subframe").remove(); return promise_rejects(t, "InvalidStateError", nav_xr.supportsSessionMode('inline')) - .then(() => promise_rejects(t, "InvalidStateError", nav_xr.requestSession({ mode: 'inline' }))); + .then(() => promise_rejects(t, "InvalidStateError", nav_xr.requestSession('inline'))); }, "Check that navigator.xr.supportsSessionMode and navigator.xr.requestSession reject on a detached navigator."); </script>
diff --git a/third_party/blink/web_tests/xr/xrBoundedReferenceSpace_updates.html b/third_party/blink/web_tests/xr/xrBoundedReferenceSpace_updates.html index a1e15ba6..a100f7a 100644 --- a/third_party/blink/web_tests/xr/xrBoundedReferenceSpace_updates.html +++ b/third_party/blink/web_tests/xr/xrBoundedReferenceSpace_updates.html
@@ -16,7 +16,7 @@ let fakeDeviceInitParams = { supportsImmersive:true }; let requestSessionOptions = [ - { mode: 'immersive-vr' }, + 'immersive-vr', ]; let testFunction = function(session, t, fakeDeviceController) {
diff --git a/third_party/blink/web_tests/xr/xrFrame_getPose.html b/third_party/blink/web_tests/xr/xrFrame_getPose.html index d161133a..a43ca661 100644 --- a/third_party/blink/web_tests/xr/xrFrame_getPose.html +++ b/third_party/blink/web_tests/xr/xrFrame_getPose.html
@@ -17,7 +17,7 @@ let fakeDeviceInitParams = { supportsImmersive:true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = function(session, t, fakeDeviceController) { // Session must have a baseLayer or frame requests will be ignored.
diff --git a/third_party/blink/web_tests/xr/xrInputSource_add_remove.html b/third_party/blink/web_tests/xr/xrInputSource_add_remove.html index 90b6dfb0..6925668d 100644 --- a/third_party/blink/web_tests/xr/xrInputSource_add_remove.html +++ b/third_party/blink/web_tests/xr/xrInputSource_add_remove.html
@@ -16,7 +16,7 @@ let fakeDeviceInitParams = { supportsImmersive:true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = (session, t, fakeDeviceController) => new Promise((resolve) => { // Session must have a baseLayer or frame requests will be ignored.
diff --git a/third_party/blink/web_tests/xr/xrReferenceSpace_originOffset.html b/third_party/blink/web_tests/xr/xrReferenceSpace_originOffset.html index 0ed917c..c6e971f 100644 --- a/third_party/blink/web_tests/xr/xrReferenceSpace_originOffset.html +++ b/third_party/blink/web_tests/xr/xrReferenceSpace_originOffset.html
@@ -17,7 +17,7 @@ let fakeDeviceInitParams = { supportsImmersive: true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = (session, t, fakeDeviceController) => new Promise((resolve) => {
diff --git a/third_party/blink/web_tests/xr/xrSession_environmentBlendMode.html b/third_party/blink/web_tests/xr/xrSession_environmentBlendMode.html index 848e579..92e8688 100644 --- a/third_party/blink/web_tests/xr/xrSession_environmentBlendMode.html +++ b/third_party/blink/web_tests/xr/xrSession_environmentBlendMode.html
@@ -14,8 +14,8 @@ let fakeDeviceInitParams = { supportsImmersive:true }; let requestSessionOptions = [ - { mode: 'inline' }, - { mode: 'immersive-vr' }, + 'inline', + 'immersive-vr', ]; let testFunction = function(session, t) {
diff --git a/third_party/blink/web_tests/xr/xrSession_environmentProviderDisconnect.html b/third_party/blink/web_tests/xr/xrSession_environmentProviderDisconnect.html index 86a9a6f..bd72888 100644 --- a/third_party/blink/web_tests/xr/xrSession_environmentProviderDisconnect.html +++ b/third_party/blink/web_tests/xr/xrSession_environmentProviderDisconnect.html
@@ -16,7 +16,7 @@ let fakeDeviceInitParams = { supportsImmersive: false, supportsEnvironmentIntegration: true }; -let requestSessionOptions = [ {mode: 'legacy-inline-ar' } ]; +let requestSessionOptions = ['legacy-inline-ar']; let refSpace = undefined; let ray = new XRRay({x : 0.0, y : 0.0, z : 0.0}, {x : 1.0, y : 0.0, z: 0.0});
diff --git a/third_party/blink/web_tests/xr/xrSession_requestAnimationFrame_timestamp.html b/third_party/blink/web_tests/xr/xrSession_requestAnimationFrame_timestamp.html index df79d023..3360dc0 100644 --- a/third_party/blink/web_tests/xr/xrSession_requestAnimationFrame_timestamp.html +++ b/third_party/blink/web_tests/xr/xrSession_requestAnimationFrame_timestamp.html
@@ -17,8 +17,8 @@ let fakeDeviceInitParams = { supportsImmersive:true }; let requestSessionOptions = [ - { mode: 'inline' }, - { mode: 'immersive-vr' }, + 'inline', + 'immersive-vr', ]; let testFunction = function(session, t, fakeDeviceController) {
diff --git a/third_party/blink/web_tests/xr/xrStationaryReferenceSpace_floorlevel_updates.html b/third_party/blink/web_tests/xr/xrStationaryReferenceSpace_floorlevel_updates.html index 4fc1fba6a..db99d6ab 100644 --- a/third_party/blink/web_tests/xr/xrStationaryReferenceSpace_floorlevel_updates.html +++ b/third_party/blink/web_tests/xr/xrStationaryReferenceSpace_floorlevel_updates.html
@@ -16,8 +16,8 @@ let fakeDeviceInitParams = { supportsImmersive:true }; let requestSessionOptions = [ - { mode: 'inline' }, - { mode: 'immersive-vr' }, + 'inline', + 'immersive-vr', ]; let testFunction = function(session, t, fakeDeviceController) {
diff --git a/third_party/blink/web_tests/xr/xrView_match.html b/third_party/blink/web_tests/xr/xrView_match.html index d9bbac38..0dbe6f5 100644 --- a/third_party/blink/web_tests/xr/xrView_match.html +++ b/third_party/blink/web_tests/xr/xrView_match.html
@@ -14,7 +14,7 @@ let fakeDeviceInitParams = { supportsImmersive:true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = function(session, t, fakeDeviceController) { // Session must have a baseLayer or frame requests will be ignored.
diff --git a/third_party/blink/web_tests/xr/xrView_oneframeupdate.html b/third_party/blink/web_tests/xr/xrView_oneframeupdate.html index 3d57826..030f209 100644 --- a/third_party/blink/web_tests/xr/xrView_oneframeupdate.html +++ b/third_party/blink/web_tests/xr/xrView_oneframeupdate.html
@@ -15,7 +15,7 @@ let fakeDeviceInitParams = { supportsImmersive:true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = function(session, t, fakeDeviceController) { // Session must have a baseLayer or frame requests will be ignored.
diff --git a/third_party/blink/web_tests/xr/xrViewport_valid.html b/third_party/blink/web_tests/xr/xrViewport_valid.html index 00a1f5d..3e29245 100644 --- a/third_party/blink/web_tests/xr/xrViewport_valid.html +++ b/third_party/blink/web_tests/xr/xrViewport_valid.html
@@ -13,7 +13,7 @@ let fakeDeviceInitParams = { supportsImmersive:true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = function(session, t, fakeDeviceController) { // Session must have a baseLayer or frame requests will be ignored.
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_constructor.html b/third_party/blink/web_tests/xr/xrWebGLLayer_constructor.html index bd60801..2e5d9d16c 100644 --- a/third_party/blink/web_tests/xr/xrWebGLLayer_constructor.html +++ b/third_party/blink/web_tests/xr/xrWebGLLayer_constructor.html
@@ -13,7 +13,7 @@ let fakeDeviceInitParams = { supportsImmersive: true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = (session, t, fakeDeviceController) => new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_dirty_framebuffer.html b/third_party/blink/web_tests/xr/xrWebGLLayer_dirty_framebuffer.html index 5cac048..68be54c4 100644 --- a/third_party/blink/web_tests/xr/xrWebGLLayer_dirty_framebuffer.html +++ b/third_party/blink/web_tests/xr/xrWebGLLayer_dirty_framebuffer.html
@@ -15,7 +15,7 @@ let fakeDeviceInitParams = { supportsImmersive: true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = (session, t, fakeDeviceController) => new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_draw.html b/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_draw.html index c2e35a65..d2154637 100644 --- a/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_draw.html +++ b/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_draw.html
@@ -14,7 +14,7 @@ let fakeDeviceInitParams = { supportsImmersive: true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; // Very simple program setup with no error checking. function setupProgram(gl, vertexSrc, fragmentSrc) {
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_scale.html b/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_scale.html index dbb47b4..e4d3dc28 100644 --- a/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_scale.html +++ b/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_scale.html
@@ -14,7 +14,7 @@ let fakeDeviceInitParams = { supportsImmersive: true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = (session, t, fakeDeviceController) => new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_incompatible_device.html b/third_party/blink/web_tests/xr/xrWebGLLayer_incompatible_device.html index 94c632f..39c8a0f 100644 --- a/third_party/blink/web_tests/xr/xrWebGLLayer_incompatible_device.html +++ b/third_party/blink/web_tests/xr/xrWebGLLayer_incompatible_device.html
@@ -15,7 +15,7 @@ return XRTest.simulateDeviceConnection({ supportsImmersive:true }) .then( (controller) => new Promise((resolve) => { runWithUserGesture( () => { - resolve(navigator.xr.requestSession({ mode: 'immersive-vr' }) + resolve(navigator.xr.requestSession('immersive-vr') .then( (session) => new Promise((resolve) => { try { let webglLayer = new XRWebGLLayer(session, gl);
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_non_exclusive_adjust_size.html b/third_party/blink/web_tests/xr/xrWebGLLayer_non_exclusive_adjust_size.html index 1d49947..bca0ca6f 100644 --- a/third_party/blink/web_tests/xr/xrWebGLLayer_non_exclusive_adjust_size.html +++ b/third_party/blink/web_tests/xr/xrWebGLLayer_non_exclusive_adjust_size.html
@@ -22,7 +22,7 @@ let fakeDeviceInitParams = { supportsImmersive: true }; -let requestSessionOptions = [{ }]; +let requestSessionOptions = ['inline']; let testFunction = (session, t) => new Promise((resolve, reject) => { console.log("Test start");
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_opaque_framebuffer.html b/third_party/blink/web_tests/xr/xrWebGLLayer_opaque_framebuffer.html index 7c361cc5..7be74af 100644 --- a/third_party/blink/web_tests/xr/xrWebGLLayer_opaque_framebuffer.html +++ b/third_party/blink/web_tests/xr/xrWebGLLayer_opaque_framebuffer.html
@@ -13,8 +13,8 @@ let fakeDeviceInitParams = { supportsImmersive: true }; let requestSessionOptions = [ - { mode: 'immersive-vr' }, - { mode: 'inline' } + 'immersive-vr', + 'inline' ]; let testFunction =
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_viewport_scale.html b/third_party/blink/web_tests/xr/xrWebGLLayer_viewport_scale.html index bb5de50a..33541fa4 100644 --- a/third_party/blink/web_tests/xr/xrWebGLLayer_viewport_scale.html +++ b/third_party/blink/web_tests/xr/xrWebGLLayer_viewport_scale.html
@@ -15,7 +15,7 @@ let fakeDeviceInitParams = { supportsImmersive: true }; -let requestSessionOptions = [{ mode: 'immersive-vr' }]; +let requestSessionOptions = ['immersive-vr']; let testFunction = function(session, t, fakeDeviceController) { // Session must have a baseLayer or else frame requests will be ignored.
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js index 1716b22..aafce1c 100644 --- a/third_party/closure_compiler/externs/automation.js +++ b/third_party/closure_compiler/externs/automation.js
@@ -942,42 +942,42 @@ chrome.automation.AutomationNode.prototype.focusAffinity; /** - * The node at the start of the selection, if any. + * The selection start node of the tree selection, if any. * @type {(!chrome.automation.AutomationNode|undefined)} * @see https://developer.chrome.com/extensions/automation#type-selectionStartObject */ chrome.automation.AutomationNode.prototype.selectionStartObject; /** - * The offset at the start of the selection, if any. + * The selection start offset of the tree selection, if any. * @type {(number|undefined)} * @see https://developer.chrome.com/extensions/automation#type-selectionStartOffset */ chrome.automation.AutomationNode.prototype.selectionStartOffset; /** - * The affinity at the start of the selection, if any. + * The affinity of the tree selection start, if any. * @type {(string|undefined)} * @see https://developer.chrome.com/extensions/automation#type-selectionStartAffinity */ chrome.automation.AutomationNode.prototype.selectionStartAffinity; /** - * The node at the end of the selection, if any. + * The selection end node of the tree selection, if any. * @type {(!chrome.automation.AutomationNode|undefined)} * @see https://developer.chrome.com/extensions/automation#type-selectionEndObject */ chrome.automation.AutomationNode.prototype.selectionEndObject; /** - * The offset at the end of the selection, if any. + * The selection end offset of the tree selection, if any. * @type {(number|undefined)} * @see https://developer.chrome.com/extensions/automation#type-selectionEndOffset */ chrome.automation.AutomationNode.prototype.selectionEndOffset; /** - * The affinity at the end of the selection, if any. + * The affinity of the tree selection end, if any. * @type {(string|undefined)} * @see https://developer.chrome.com/extensions/automation#type-selectionEndAffinity */ @@ -1341,18 +1341,6 @@ chrome.automation.AutomationNode.prototype.lineThrough; /** - * The font family of this node. - * @type {string|undefined} - */ -chrome.automation.AutomationNode.prototype.fontFamily; - -/** - * The font size of this node. - * @type {number|undefined} - */ -chrome.automation.AutomationNode.prototype.fontSize; - -/** * Indicates whether this node is selected, unselected, or neither. * @type {(boolean|undefined)} * @see https://developer.chrome.com/extensions/automation#type-selected @@ -1360,6 +1348,20 @@ chrome.automation.AutomationNode.prototype.selected; /** + * Indicates the font size of this node. + * @type {(number|undefined)} + * @see https://developer.chrome.com/extensions/automation#type-fontSize + */ +chrome.automation.AutomationNode.prototype.fontSize; + +/** + * Indicates the font family. + * @type {string} + * @see https://developer.chrome.com/extensions/automation#type-fontFamily + */ +chrome.automation.AutomationNode.prototype.fontFamily; + +/** * Walking the tree. * @type {!Array<!chrome.automation.AutomationNode>} * @see https://developer.chrome.com/extensions/automation#type-children
diff --git a/third_party/closure_compiler/externs/settings_private.js b/third_party/closure_compiler/externs/settings_private.js index fb13fc7..f625474 100644 --- a/third_party/closure_compiler/externs/settings_private.js +++ b/third_party/closure_compiler/externs/settings_private.js
@@ -1,4 +1,4 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2019 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. @@ -37,6 +37,7 @@ OWNER: 'OWNER', PRIMARY_USER: 'PRIMARY_USER', EXTENSION: 'EXTENSION', + PARENT: 'PARENT', }; /**
diff --git a/third_party/inspector_protocol/README.chromium b/third_party/inspector_protocol/README.chromium index 831ec945..4faba6d 100644 --- a/third_party/inspector_protocol/README.chromium +++ b/third_party/inspector_protocol/README.chromium
@@ -2,7 +2,7 @@ Short Name: inspector_protocol URL: https://chromium.googlesource.com/deps/inspector_protocol/ Version: 0 -Revision: 0f1e67db47db6e547ca67324dc1d2ca850a80d49 +Revision: 34bdcd1fb46ec80fb22908ee03fdb7cacf2575ac License: BSD License File: LICENSE Security Critical: no
diff --git a/third_party/inspector_protocol/encoding/encoding.cc b/third_party/inspector_protocol/encoding/encoding.cc index 352687d..211deff 100644 --- a/third_party/inspector_protocol/encoding/encoding.cc +++ b/third_party/inspector_protocol/encoding/encoding.cc
@@ -383,45 +383,45 @@ // ============================================================================= template <typename C> -void EncodeStartTmpl(C* out, std::size_t& byte_size_pos) { - assert(byte_size_pos == 0); +void EncodeStartTmpl(C* out, std::size_t* byte_size_pos) { + assert(*byte_size_pos == 0); out->push_back(kInitialByteForEnvelope); out->push_back(kInitialByteFor32BitLengthByteString); - byte_size_pos = out->size(); + *byte_size_pos = out->size(); out->resize(out->size() + sizeof(uint32_t)); } void EnvelopeEncoder::EncodeStart(std::vector<uint8_t>* out) { - EncodeStartTmpl<std::vector<uint8_t>>(out, byte_size_pos_); + EncodeStartTmpl<std::vector<uint8_t>>(out, &byte_size_pos_); } void EnvelopeEncoder::EncodeStart(std::string* out) { - EncodeStartTmpl<std::string>(out, byte_size_pos_); + EncodeStartTmpl<std::string>(out, &byte_size_pos_); } template <typename C> -bool EncodeStopTmpl(C* out, std::size_t& byte_size_pos) { - assert(byte_size_pos != 0); +bool EncodeStopTmpl(C* out, std::size_t* byte_size_pos) { + assert(*byte_size_pos != 0); // The byte size is the size of the payload, that is, all the // bytes that were written past the byte size position itself. - uint64_t byte_size = out->size() - (byte_size_pos + sizeof(uint32_t)); + uint64_t byte_size = out->size() - (*byte_size_pos + sizeof(uint32_t)); // We store exactly 4 bytes, so at most INT32MAX, with most significant // byte first. if (byte_size > std::numeric_limits<uint32_t>::max()) return false; for (int shift_bytes = sizeof(uint32_t) - 1; shift_bytes >= 0; --shift_bytes) { - (*out)[byte_size_pos++] = 0xff & (byte_size >> (shift_bytes * 8)); + (*out)[(*byte_size_pos)++] = 0xff & (byte_size >> (shift_bytes * 8)); } return true; } bool EnvelopeEncoder::EncodeStop(std::vector<uint8_t>* out) { - return EncodeStopTmpl(out, byte_size_pos_); + return EncodeStopTmpl(out, &byte_size_pos_); } bool EnvelopeEncoder::EncodeStop(std::string* out) { - return EncodeStopTmpl(out, byte_size_pos_); + return EncodeStopTmpl(out, &byte_size_pos_); } // ============================================================================= @@ -437,57 +437,94 @@ } void HandleMapBegin() override { + if (!status_->ok()) + return; envelopes_.emplace_back(); envelopes_.back().EncodeStart(out_); out_->push_back(kInitialByteIndefiniteLengthMap); } void HandleMapEnd() override { + if (!status_->ok()) + return; out_->push_back(kStopByte); assert(!envelopes_.empty()); - envelopes_.back().EncodeStop(out_); + if (!envelopes_.back().EncodeStop(out_)) { + HandleError( + Status(Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED, out_->size())); + return; + } envelopes_.pop_back(); } void HandleArrayBegin() override { + if (!status_->ok()) + return; envelopes_.emplace_back(); envelopes_.back().EncodeStart(out_); out_->push_back(kInitialByteIndefiniteLengthArray); } void HandleArrayEnd() override { + if (!status_->ok()) + return; out_->push_back(kStopByte); assert(!envelopes_.empty()); - envelopes_.back().EncodeStop(out_); + if (!envelopes_.back().EncodeStop(out_)) { + HandleError( + Status(Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED, out_->size())); + return; + } envelopes_.pop_back(); } void HandleString8(span<uint8_t> chars) override { + if (!status_->ok()) + return; EncodeString8(chars, out_); } void HandleString16(span<uint16_t> chars) override { + if (!status_->ok()) + return; EncodeFromUTF16(chars, out_); } - void HandleBinary(span<uint8_t> bytes) override { EncodeBinary(bytes, out_); } + void HandleBinary(span<uint8_t> bytes) override { + if (!status_->ok()) + return; + EncodeBinary(bytes, out_); + } - void HandleDouble(double value) override { EncodeDouble(value, out_); } + void HandleDouble(double value) override { + if (!status_->ok()) + return; + EncodeDouble(value, out_); + } - void HandleInt32(int32_t value) override { EncodeInt32(value, out_); } + void HandleInt32(int32_t value) override { + if (!status_->ok()) + return; + EncodeInt32(value, out_); + } void HandleBool(bool value) override { + if (!status_->ok()) + return; // See RFC 7049 Section 2.3, Table 2. out_->push_back(value ? kEncodedTrue : kEncodedFalse); } void HandleNull() override { + if (!status_->ok()) + return; // See RFC 7049 Section 2.3, Table 2. out_->push_back(kEncodedNull); } void HandleError(Status error) override { - assert(!error.ok()); + if (!status_->ok()) + return; *status_ = error; out_->clear(); }
diff --git a/third_party/inspector_protocol/encoding/encoding.h b/third_party/inspector_protocol/encoding/encoding.h index a5137a8..ac39910 100644 --- a/third_party/inspector_protocol/encoding/encoding.h +++ b/third_party/inspector_protocol/encoding/encoding.h
@@ -7,6 +7,7 @@ #include <cstddef> #include <cstdint> +#include <cstring> #include <memory> #include <string> #include <vector> @@ -58,6 +59,16 @@ return span<T>(v.data(), v.size()); } +template <size_t N> +span<uint8_t> SpanFrom(const char (&str)[N]) { + return span<uint8_t>(reinterpret_cast<const uint8_t*>(str), N - 1); +} + +inline span<uint8_t> SpanFrom(const char* str) { + return str ? span<uint8_t>(reinterpret_cast<const uint8_t*>(str), strlen(str)) + : span<uint8_t>(); +} + inline span<uint8_t> SpanFrom(const std::string& v) { return span<uint8_t>(reinterpret_cast<const uint8_t*>(v.data()), v.size()); }
diff --git a/third_party/inspector_protocol/encoding/encoding_test.cc b/third_party/inspector_protocol/encoding/encoding_test.cc index 5c302d53..e48d359 100644 --- a/third_party/inspector_protocol/encoding/encoding_test.cc +++ b/third_party/inspector_protocol/encoding/encoding_test.cc
@@ -125,6 +125,22 @@ EXPECT_EQ(34, two_items[1]); } +TEST(SpanFromTest, FromConstCharAndLiteral) { + // Testing this is useful because strlen(nullptr) is undefined. + EXPECT_EQ(nullptr, SpanFrom(nullptr).data()); + EXPECT_EQ(0, SpanFrom(nullptr).size()); + + const char* kEmpty = ""; + EXPECT_EQ(kEmpty, reinterpret_cast<const char*>(SpanFrom(kEmpty).data())); + EXPECT_EQ(0, SpanFrom(kEmpty).size()); + + const char* kFoo = "foo"; + EXPECT_EQ(kFoo, reinterpret_cast<const char*>(SpanFrom(kFoo).data())); + EXPECT_EQ(3, SpanFrom(kFoo).size()); + + EXPECT_EQ(3, SpanFrom("foo").size()); +} + namespace cbor { // ============================================================================= @@ -525,7 +541,7 @@ std::vector<uint8_t> decoded; CBORTokenizer tokenizer(SpanFrom(encoded)); EXPECT_EQ(CBORTokenTag::BINARY, tokenizer.TokenTag()); - EXPECT_EQ(0, int(tokenizer.Status().error)); + EXPECT_EQ(0, static_cast<int>(tokenizer.Status().error)); decoded = std::vector<uint8_t>(tokenizer.GetBinary().begin(), tokenizer.GetBinary().end()); EXPECT_THAT(decoded, ElementsAreArray(binary)); @@ -1356,11 +1372,11 @@ bool StrToD(const char* str, double* result) const override { return false; } // A map with pre-registered responses for DToSTr. - std::map<double, std::string> dtostr_responses; + std::map<double, std::string> dtostr_responses_; std::unique_ptr<char[]> DToStr(double value) const override { - auto it = dtostr_responses.find(value); - CHECK(it != dtostr_responses.end()); + auto it = dtostr_responses_.find(value); + CHECK(it != dtostr_responses_.end()); const std::string& str = it->second; std::unique_ptr<char[]> response(new char[str.size() + 1]); memcpy(response.get(), str.c_str(), str.size() + 1); @@ -1372,8 +1388,8 @@ // This "broken" platform responds without the leading 0 before the // decimal dot, so it'd be invalid JSON. MockPlatform platform; - platform.dtostr_responses[.1] = ".1"; - platform.dtostr_responses[-.7] = "-.7"; + platform.dtostr_responses_[.1] = ".1"; + platform.dtostr_responses_[-.7] = "-.7"; std::string out; Status status;
diff --git a/third_party/inspector_protocol/lib/encoding_cpp.template b/third_party/inspector_protocol/lib/encoding_cpp.template index a5376142..9aa164a3 100644 --- a/third_party/inspector_protocol/lib/encoding_cpp.template +++ b/third_party/inspector_protocol/lib/encoding_cpp.template
@@ -390,45 +390,45 @@ // ============================================================================= template <typename C> -void EncodeStartTmpl(C* out, std::size_t& byte_size_pos) { - assert(byte_size_pos == 0); +void EncodeStartTmpl(C* out, std::size_t* byte_size_pos) { + assert(*byte_size_pos == 0); out->push_back(kInitialByteForEnvelope); out->push_back(kInitialByteFor32BitLengthByteString); - byte_size_pos = out->size(); + *byte_size_pos = out->size(); out->resize(out->size() + sizeof(uint32_t)); } void EnvelopeEncoder::EncodeStart(std::vector<uint8_t>* out) { - EncodeStartTmpl<std::vector<uint8_t>>(out, byte_size_pos_); + EncodeStartTmpl<std::vector<uint8_t>>(out, &byte_size_pos_); } void EnvelopeEncoder::EncodeStart(std::string* out) { - EncodeStartTmpl<std::string>(out, byte_size_pos_); + EncodeStartTmpl<std::string>(out, &byte_size_pos_); } template <typename C> -bool EncodeStopTmpl(C* out, std::size_t& byte_size_pos) { - assert(byte_size_pos != 0); +bool EncodeStopTmpl(C* out, std::size_t* byte_size_pos) { + assert(*byte_size_pos != 0); // The byte size is the size of the payload, that is, all the // bytes that were written past the byte size position itself. - uint64_t byte_size = out->size() - (byte_size_pos + sizeof(uint32_t)); + uint64_t byte_size = out->size() - (*byte_size_pos + sizeof(uint32_t)); // We store exactly 4 bytes, so at most INT32MAX, with most significant // byte first. if (byte_size > std::numeric_limits<uint32_t>::max()) return false; for (int shift_bytes = sizeof(uint32_t) - 1; shift_bytes >= 0; --shift_bytes) { - (*out)[byte_size_pos++] = 0xff & (byte_size >> (shift_bytes * 8)); + (*out)[(*byte_size_pos)++] = 0xff & (byte_size >> (shift_bytes * 8)); } return true; } bool EnvelopeEncoder::EncodeStop(std::vector<uint8_t>* out) { - return EncodeStopTmpl(out, byte_size_pos_); + return EncodeStopTmpl(out, &byte_size_pos_); } bool EnvelopeEncoder::EncodeStop(std::string* out) { - return EncodeStopTmpl(out, byte_size_pos_); + return EncodeStopTmpl(out, &byte_size_pos_); } // ============================================================================= @@ -444,57 +444,94 @@ } void HandleMapBegin() override { + if (!status_->ok()) + return; envelopes_.emplace_back(); envelopes_.back().EncodeStart(out_); out_->push_back(kInitialByteIndefiniteLengthMap); } void HandleMapEnd() override { + if (!status_->ok()) + return; out_->push_back(kStopByte); assert(!envelopes_.empty()); - envelopes_.back().EncodeStop(out_); + if (!envelopes_.back().EncodeStop(out_)) { + HandleError( + Status(Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED, out_->size())); + return; + } envelopes_.pop_back(); } void HandleArrayBegin() override { + if (!status_->ok()) + return; envelopes_.emplace_back(); envelopes_.back().EncodeStart(out_); out_->push_back(kInitialByteIndefiniteLengthArray); } void HandleArrayEnd() override { + if (!status_->ok()) + return; out_->push_back(kStopByte); assert(!envelopes_.empty()); - envelopes_.back().EncodeStop(out_); + if (!envelopes_.back().EncodeStop(out_)) { + HandleError( + Status(Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED, out_->size())); + return; + } envelopes_.pop_back(); } void HandleString8(span<uint8_t> chars) override { + if (!status_->ok()) + return; EncodeString8(chars, out_); } void HandleString16(span<uint16_t> chars) override { + if (!status_->ok()) + return; EncodeFromUTF16(chars, out_); } - void HandleBinary(span<uint8_t> bytes) override { EncodeBinary(bytes, out_); } + void HandleBinary(span<uint8_t> bytes) override { + if (!status_->ok()) + return; + EncodeBinary(bytes, out_); + } - void HandleDouble(double value) override { EncodeDouble(value, out_); } + void HandleDouble(double value) override { + if (!status_->ok()) + return; + EncodeDouble(value, out_); + } - void HandleInt32(int32_t value) override { EncodeInt32(value, out_); } + void HandleInt32(int32_t value) override { + if (!status_->ok()) + return; + EncodeInt32(value, out_); + } void HandleBool(bool value) override { + if (!status_->ok()) + return; // See RFC 7049 Section 2.3, Table 2. out_->push_back(value ? kEncodedTrue : kEncodedFalse); } void HandleNull() override { + if (!status_->ok()) + return; // See RFC 7049 Section 2.3, Table 2. out_->push_back(kEncodedNull); } void HandleError(Status error) override { - assert(!error.ok()); + if (!status_->ok()) + return; *status_ = error; out_->clear(); }
diff --git a/third_party/inspector_protocol/lib/encoding_h.template b/third_party/inspector_protocol/lib/encoding_h.template index 8f62c9e..74cf20c0 100644 --- a/third_party/inspector_protocol/lib/encoding_h.template +++ b/third_party/inspector_protocol/lib/encoding_h.template
@@ -10,6 +10,7 @@ #include <cstddef> #include <cstdint> +#include <cstring> #include <memory> #include <string> #include <vector> @@ -66,6 +67,16 @@ return span<T>(v.data(), v.size()); } +template <size_t N> +span<uint8_t> SpanFrom(const char (&str)[N]) { + return span<uint8_t>(reinterpret_cast<const uint8_t*>(str), N - 1); +} + +inline span<uint8_t> SpanFrom(const char* str) { + return str ? span<uint8_t>(reinterpret_cast<const uint8_t*>(str), strlen(str)) + : span<uint8_t>(); +} + inline span<uint8_t> SpanFrom(const std::string& v) { return span<uint8_t>(reinterpret_cast<const uint8_t*>(v.data()), v.size()); }
diff --git a/third_party/webxr_test_pages/webxr-samples/360-photos.html b/third_party/webxr_test_pages/webxr-samples/360-photos.html index 2650ca9..621b3a9 100644 --- a/third_party/webxr_test_pages/webxr-samples/360-photos.html +++ b/third_party/webxr_test_pages/webxr-samples/360-photos.html
@@ -88,7 +88,7 @@ document.querySelector('header').appendChild(xrButton.domElement); if (navigator.xr) { - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } else { initFallback(); } @@ -114,7 +114,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html b/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html index 6ac11d4..b64d3e9 100644 --- a/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html +++ b/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html
@@ -88,7 +88,7 @@ document.querySelector('header').appendChild(xrButton.domElement); if (navigator.xr) { - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } else { // If navigator.xr isn't present in the browser then we need to use // the fallback rendering path. @@ -140,7 +140,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/framebuffer-scaling.html b/third_party/webxr_test_pages/webxr-samples/framebuffer-scaling.html index 1a6a68d..1203704b 100644 --- a/third_party/webxr_test_pages/webxr-samples/framebuffer-scaling.html +++ b/third_party/webxr_test_pages/webxr-samples/framebuffer-scaling.html
@@ -113,7 +113,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then(onSessionStarted); + navigator.xr.requestSession('immersive-vr').then(onSessionStarted); } function onSessionStarted(session) {
diff --git a/third_party/webxr_test_pages/webxr-samples/input-selection.html b/third_party/webxr_test_pages/webxr-samples/input-selection.html index 41f931c..f5ea025 100644 --- a/third_party/webxr_test_pages/webxr-samples/input-selection.html +++ b/third_party/webxr_test_pages/webxr-samples/input-selection.html
@@ -104,7 +104,7 @@ document.querySelector('header').appendChild(xrButton.domElement); if (navigator.xr) { - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } else { initFallback(); } @@ -176,7 +176,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/input-tracking.html b/third_party/webxr_test_pages/webxr-samples/input-tracking.html index 60ccc0a..04047e14 100644 --- a/third_party/webxr_test_pages/webxr-samples/input-tracking.html +++ b/third_party/webxr_test_pages/webxr-samples/input-tracking.html
@@ -88,7 +88,7 @@ document.querySelector('header').appendChild(xrButton.domElement); if (navigator.xr) { - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } else { initFallback(); } @@ -118,7 +118,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/magic-window.html b/third_party/webxr_test_pages/webxr-samples/magic-window.html index e1e992cb8..7fde66a 100644 --- a/third_party/webxr_test_pages/webxr-samples/magic-window.html +++ b/third_party/webxr_test_pages/webxr-samples/magic-window.html
@@ -96,12 +96,12 @@ if (navigator.xr) { // Pick an arbitrary device for the magic window content and start // up a non-immersive session if possible. - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/mirroring.html b/third_party/webxr_test_pages/webxr-samples/mirroring.html index 5a701a46..1aa95455 100644 --- a/third_party/webxr_test_pages/webxr-samples/mirroring.html +++ b/third_party/webxr_test_pages/webxr-samples/mirroring.html
@@ -89,9 +89,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ - mode: 'immersive-vr' - }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { // In order to mirror an exclusive session, we must provide // an XRPresentationContext, which indicates the canvas that will // contain results of the session's rendering.
diff --git a/third_party/webxr_test_pages/webxr-samples/positional-audio.html b/third_party/webxr_test_pages/webxr-samples/positional-audio.html index 35a3cab..77188f0 100644 --- a/third_party/webxr_test_pages/webxr-samples/positional-audio.html +++ b/third_party/webxr_test_pages/webxr-samples/positional-audio.html
@@ -303,7 +303,7 @@ scene.addNode(playButton); }); - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } else { initFallback(); } @@ -330,7 +330,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/proposals/phone-ar-hit-test.html b/third_party/webxr_test_pages/webxr-samples/proposals/phone-ar-hit-test.html index 63f233e..4d5dd47 100644 --- a/third_party/webxr_test_pages/webxr-samples/proposals/phone-ar-hit-test.html +++ b/third_party/webxr_test_pages/webxr-samples/proposals/phone-ar-hit-test.html
@@ -127,11 +127,11 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-ar' }).then((session) => { + navigator.xr.requestSession('immersive-ar').then((session) => { xrButton.setSession(session); onSessionStarted(session); }).catch(() => { - navigator.xr.requestSession({ mode: 'legacy-inline-ar' }) + navigator.xr.requestSession('legacy-inline-ar') .then((session) => { xrButton.setSession(session); onSessionStarted(session);
diff --git a/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html b/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html index 5434d8c..9f6e3cc3 100644 --- a/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html +++ b/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html
@@ -84,7 +84,7 @@ document.querySelector('header').appendChild(xrButton.domElement); if (navigator.xr) { - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } else { initFallback(); } @@ -117,7 +117,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/room-scale.html b/third_party/webxr_test_pages/webxr-samples/room-scale.html index 8b535325..9223484 100644 --- a/third_party/webxr_test_pages/webxr-samples/room-scale.html +++ b/third_party/webxr_test_pages/webxr-samples/room-scale.html
@@ -89,7 +89,7 @@ document.querySelector('header').appendChild(xrButton.domElement); if (navigator.xr) { - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } else { initFallback(); } @@ -103,7 +103,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/spectator-mode.html b/third_party/webxr_test_pages/webxr-samples/spectator-mode.html index ce71463..375e7660 100644 --- a/third_party/webxr_test_pages/webxr-samples/spectator-mode.html +++ b/third_party/webxr_test_pages/webxr-samples/spectator-mode.html
@@ -101,7 +101,7 @@ if (navigator.xr) { outputCanvas = document.createElement('canvas'); - navigator.xr.requestSession() + navigator.xr.requestSession('inline') .then((session) => { document.body.appendChild(outputCanvas); session.updateRenderState({ @@ -140,7 +140,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session);
diff --git a/third_party/webxr_test_pages/webxr-samples/stereo-video.html b/third_party/webxr_test_pages/webxr-samples/stereo-video.html index 26a965e..7d10be9 100644 --- a/third_party/webxr_test_pages/webxr-samples/stereo-video.html +++ b/third_party/webxr_test_pages/webxr-samples/stereo-video.html
@@ -139,7 +139,7 @@ document.querySelector('header').appendChild(xrButton.domElement); if (navigator.xr) { - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } else { initFallback(); } @@ -165,7 +165,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/cube-sea.html b/third_party/webxr_test_pages/webxr-samples/tests/cube-sea.html index 6d8c4a7..93bc3b1 100644 --- a/third_party/webxr_test_pages/webxr-samples/tests/cube-sea.html +++ b/third_party/webxr_test_pages/webxr-samples/tests/cube-sea.html
@@ -276,7 +276,7 @@ if (navigator.xr) { // Set up "magic window" mode. if (appSettings.magicWindow) { - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } } else { initFallback(); @@ -306,7 +306,7 @@ } function onRequestSession() { - let xrOptions = { mode: appSettings.arMode ? 'immersive-ar' : 'immersive-vr' }; + let xrOptions = appSettings.arMode ? 'immersive-ar' : 'immersive-vr'; navigator.xr.requestSession(xrOptions).then((session) => { xrButton.setSession(session); onSessionStarted(session);
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/offscreen-canvas.html b/third_party/webxr_test_pages/webxr-samples/tests/offscreen-canvas.html index 2e2bf5a0..968d7ad 100644 --- a/third_party/webxr_test_pages/webxr-samples/tests/offscreen-canvas.html +++ b/third_party/webxr_test_pages/webxr-samples/tests/offscreen-canvas.html
@@ -86,7 +86,7 @@ document.querySelector('header').appendChild(xrButton.domElement); if (navigator.xr) { - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } } @@ -105,7 +105,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/permission-request.html b/third_party/webxr_test_pages/webxr-samples/tests/permission-request.html index ff3ce490..a7629ed9 100644 --- a/third_party/webxr_test_pages/webxr-samples/tests/permission-request.html +++ b/third_party/webxr_test_pages/webxr-samples/tests/permission-request.html
@@ -96,7 +96,7 @@ document.querySelector('header').appendChild(xrButton.domElement); if (navigator.xr) { - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } else { initFallback(); } @@ -194,7 +194,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/pointer-painter.html b/third_party/webxr_test_pages/webxr-samples/tests/pointer-painter.html index 6d00676..5ea081a 100644 --- a/third_party/webxr_test_pages/webxr-samples/tests/pointer-painter.html +++ b/third_party/webxr_test_pages/webxr-samples/tests/pointer-painter.html
@@ -85,7 +85,7 @@ document.querySelector('header').appendChild(xrButton.domElement); if (navigator.xr) { - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } else { initFallback(); } @@ -112,7 +112,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/sponza.html b/third_party/webxr_test_pages/webxr-samples/tests/sponza.html index e16cb363..ccbac7c 100644 --- a/third_party/webxr_test_pages/webxr-samples/tests/sponza.html +++ b/third_party/webxr_test_pages/webxr-samples/tests/sponza.html
@@ -95,7 +95,7 @@ document.querySelector('header').appendChild(xrButton.domElement); if (navigator.xr) { - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } else { initFallback(); } @@ -125,7 +125,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/viewport-scaling.html b/third_party/webxr_test_pages/webxr-samples/viewport-scaling.html index 8486e9af..3208f70 100644 --- a/third_party/webxr_test_pages/webxr-samples/viewport-scaling.html +++ b/third_party/webxr_test_pages/webxr-samples/viewport-scaling.html
@@ -112,7 +112,7 @@ document.querySelector('header').appendChild(xrButton.domElement); if (navigator.xr) { - navigator.xr.requestSession().then(onSessionStarted); + navigator.xr.requestSession('inline').then(onSessionStarted); } else { initFallback(); } @@ -141,7 +141,7 @@ } function onRequestSession() { - navigator.xr.requestSession({ mode: 'immersive-vr' }).then((session) => { + navigator.xr.requestSession('immersive-vr').then((session) => { xrButton.setSession(session); onSessionStarted(session); });
diff --git a/third_party/webxr_test_pages/webxr-samples/xr-barebones.html b/third_party/webxr_test_pages/webxr-samples/xr-barebones.html index 8c292a7..438d2f98 100644 --- a/third_party/webxr_test_pages/webxr-samples/xr-barebones.html +++ b/third_party/webxr_test_pages/webxr-samples/xr-barebones.html
@@ -97,7 +97,7 @@ // session already we'll request one, and if we do we'll end it. function onButtonClicked() { if (!xrSession) { - navigator.xr.requestSession({mode: 'immersive-vr'}).then(onSessionStarted); + navigator.xr.requestSession('immersive-vr').then(onSessionStarted); } else { xrSession.end(); }
diff --git a/third_party/webxr_test_pages/webxr-samples/xr-presentation.html b/third_party/webxr_test_pages/webxr-samples/xr-presentation.html index 2dcfa774..7a2303a 100644 --- a/third_party/webxr_test_pages/webxr-samples/xr-presentation.html +++ b/third_party/webxr_test_pages/webxr-samples/xr-presentation.html
@@ -94,7 +94,7 @@ // Called when the user selects a device to present to. In response we // will request an exclusive session from that device. function onRequestSession() { - navigator.xr.requestSession({mode: 'immersive-vr'}).then(onSessionStarted); + navigator.xr.requestSession('immersive-vr').then(onSessionStarted); } // Called when we've successfully acquired a XRSession. In response we
diff --git a/tools/clang/traffic_annotation_extractor/traffic_annotation_extractor.cpp b/tools/clang/traffic_annotation_extractor/traffic_annotation_extractor.cpp index a685f15..b1e64db 100644 --- a/tools/clang/traffic_annotation_extractor/traffic_annotation_extractor.cpp +++ b/tools/clang/traffic_annotation_extractor/traffic_annotation_extractor.cpp
@@ -32,6 +32,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Lex/Lexer.h" +#include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Refactoring.h" #include "clang/Tooling/Tooling.h" @@ -398,6 +399,7 @@ clang::tooling::CommonOptionsParser options(argc, argv, ToolCategory); clang::tooling::ClangTool tool(options.getCompilations(), options.getSourcePathList()); + tool.appendArgumentsAdjuster(clang::tooling::getStripPluginsAdjuster()); Collector collector; llvm::InitializeNativeTarget();
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 8d0f3c4..63b39c8e 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -185,7 +185,7 @@ 'ASan Debug (32-bit x86 with V8-ARM)': 'asan_v8_heap_debug_bot_hybrid', 'ASan Release (32-bit x86 with V8-ARM)': 'asan_fuzzer_v8_heap_release_bot_hybrid', 'ASan Release Media (32-bit x86 with V8-ARM)': 'asan_fuzzer_v8_heap_chromeos_codecs_release_bot_hybrid', - 'Afl Upload Linux ASan': 'afl_asan_release_bot', + 'Afl Upload Linux ASan': 'afl_asan_shared_release_bot', 'ChromiumOS ASAN Release': 'chromeos_asan_lsan_fuzzer_v8_heap_release_bot', 'Libfuzzer Upload Chrome OS ASan': 'libfuzzer_chromeos_asan_release_bot', 'Libfuzzer Upload Linux32 ASan': 'libfuzzer_asan_release_bot_x86', @@ -213,7 +213,7 @@ }, 'chromium.fyi': { - 'Afl Upload Linux ASan': 'afl_asan_release_bot', + 'Afl Upload Linux ASan': 'afl_asan_shared_release_bot', 'Android Builder (dbg) Goma Canary': 'android_debug_static_bot_vrdata', 'Android Builder (dbg) Goma Latest Client': 'android_debug_static_bot_vrdata', @@ -880,8 +880,9 @@ # is not necessarily so (i.e., we might have mac, win, and linux # bots all using the 'release_bot' config). 'configs': { - 'afl_asan_release_bot': [ - 'afl', 'asan', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + 'afl_asan_shared_release_bot': [ + 'afl', 'asan', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', + 'optimize_for_fuzzing', 'shared_release_bot', 'disable_seed_corpus', ], 'android_binary_size': [ @@ -1421,20 +1422,16 @@ 'debug_bot', 'x86', 'minimal_symbols', 'no_com_init_hooks', 'chrome_with_codecs' ], - 'libfuzzer_asan_debug_bot': [ - 'libfuzzer', 'asan', 'debug_bot', 'shared', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', - ], - 'libfuzzer_asan_debug_bot_v8_arm64': [ - 'libfuzzer', 'asan', 'debug_bot', 'shared', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'v8_simulate_arm64', + 'libfuzzer', 'asan', 'debug_bot', 'shared', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'v8_simulate_arm64', 'disable_seed_corpus', ], 'libfuzzer_asan_debug_bot_x86': [ - 'libfuzzer', 'asan', 'debug_bot', 'shared', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'x86', 'x86_host', + 'libfuzzer', 'asan', 'debug_bot', 'shared', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'x86', 'x86_host', 'disable_seed_corpus', ], 'libfuzzer_asan_debug_bot_x86_v8_arm': [ - 'libfuzzer', 'asan', 'debug_bot', 'shared', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'x86_host', 'v8_simulate_arm', + 'libfuzzer', 'asan', 'debug_bot', 'shared', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'x86_host', 'v8_simulate_arm', 'disable_seed_corpus', ], 'debug_trybot': [ @@ -1620,11 +1617,11 @@ ], 'libfuzzer_asan_debug_bot': [ - 'libfuzzer', 'asan', 'debug_bot', 'shared', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + 'libfuzzer', 'asan', 'debug_bot', 'shared', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'disable_seed_corpus', ], 'libfuzzer_chromeos_asan_release_bot': [ - 'libfuzzer', 'asan', 'shared_release_bot', 'chromeos_with_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + 'libfuzzer', 'asan', 'shared_release_bot', 'chromeos_with_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'disable_seed_corpus', ], 'libfuzzer_asan_release_bot': [ @@ -1632,15 +1629,15 @@ ], 'libfuzzer_asan_release_bot_v8_arm64': [ - 'libfuzzer', 'asan', 'shared_release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'v8_simulate_arm64', + 'libfuzzer', 'asan', 'shared_release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'v8_simulate_arm64', 'disable_seed_corpus', ], 'libfuzzer_asan_release_bot_x86': [ - 'libfuzzer', 'asan', 'shared_release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'x86', 'x86_host', + 'libfuzzer', 'asan', 'shared_release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'x86', 'x86_host', 'disable_seed_corpus', ], 'libfuzzer_asan_release_bot_x86_v8_arm': [ - 'libfuzzer', 'asan', 'shared_release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'x86_host', 'v8_simulate_arm', + 'libfuzzer', 'asan', 'shared_release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'x86_host', 'v8_simulate_arm', 'disable_seed_corpus', ], 'libfuzzer_asan_release_trybot': [ @@ -1652,11 +1649,11 @@ ], 'libfuzzer_msan_release_bot': [ - 'libfuzzer', 'msan', 'shared_release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + 'libfuzzer', 'msan', 'shared_release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'disable_seed_corpus', ], 'libfuzzer_ubsan_release_bot': [ - 'libfuzzer', 'ubsan_security', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + 'libfuzzer', 'ubsan_security', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', 'disable_seed_corpus', ], 'libfuzzer_mac_asan_shared_release_bot': [ @@ -2101,6 +2098,10 @@ 'gn_args': 'enable_nacl=false', }, + 'disable_seed_corpus': { + 'gn_args': 'archive_seed_corpus=false', + }, + 'enable_blink_animation_use_time_delta': { 'gn_args': 'blink_animation_use_time_delta=true', },
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 11ee207..679a1bb 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -24892,6 +24892,7 @@ <int value="10" label="GAMEPAD_SOURCE_TEST"/> <int value="11" label="GAMEPAD_SOURCE_WIN_XINPUT"/> <int value="12" label="GAMEPAD_SOURCE_WIN_RAW"/> + <int value="13" label="GAMEPAD_SOURCE_WIN_MR"/> </enum> <enum name="GamepadVendorProduct">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 9bd494f2..484df08 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -174,6 +174,16 @@ <summary>Records how users invoke Dictation.</summary> </histogram> +<histogram name="Accessibility.CrosDockedMagnifier" enum="BooleanEnabled" + expires_after="2020-04-15"> + <owner>dmazzoni@chromium.org</owner> + <owner>katie@chromium.org</owner> + <summary> + Whether the Chrome OS Docked Magnifier feature is on (checked once 45 secs + after startup). + </summary> +</histogram> + <histogram name="Accessibility.CrosFocusHighlight" enum="BooleanEnabled"> <owner>dmazzoni@chromium.org</owner> <summary> @@ -4588,7 +4598,8 @@ <histogram name="Apps.StateTransition.AnimationSmoothness" units="%"> <!-- Name completed by histogram_suffixes name="TabletOrClamshellMode" and - name="EnterOrExitOverview" --> + name="EnterOrExitOverview" and + name="AppListTargetState" --> <owner>newcomer@chromium.org</owner> <summary> @@ -142361,6 +142372,17 @@ <affected-histogram name="Apps.AppsInFolders"/> </histogram_suffixes> +<histogram_suffixes name="AppListTargetState" separator="."> + <suffix name="Close.ClamshellMode" label="Closing the app list"/> + <suffix name="FullscreenAllApps.ClamshellMode" + label="Fullscreen and showing all apps"/> + <suffix name="FullscreenSearch.ClamshellMode" + label="Fullscreen with search results"/> + <suffix name="Half.ClamshellMode" label="Half-visible state of the app list"/> + <suffix name="Peeking.ClamshellMode" label="Peek state of the app list"/> + <affected-histogram name="Apps.StateTransition.AnimationSmoothness"/> +</histogram_suffixes> + <histogram_suffixes name="AppUIComponent" separator="."> <suffix name="AppGrid" label="App - Fullscreen Launcher"/> <suffix name="Desktop" label="Desktop"/> @@ -146351,6 +146373,8 @@ </histogram_suffixes> <histogram_suffixes name="ImageFetcherClients" separator="."> + <suffix name="AnswerSuggestions" + label="Showing cache patterns only for AnswerSuggestions."/> <suffix name="AssistantDetails" label="Showing cache patterns only for AssistantDetails."/> <suffix name="ContextualSuggestions"
diff --git a/tools/traffic_annotation/bin/README.md b/tools/traffic_annotation/bin/README.md index 95563af0..0a43e82 100644 --- a/tools/traffic_annotation/bin/README.md +++ b/tools/traffic_annotation/bin/README.md
@@ -75,4 +75,4 @@ README should be committed along with the updated .sha1 checksums. CLANG_REVISION = '357692' -LASTCHANGE=4e7b710eaec0d246a3a16cc3d5594c169a34f0be-refs/heads/master@{#648669} +LASTCHANGE=344017b45ac7c4c94742ec577fe3babc0dfd271a-refs/heads/master@{#651701}
diff --git a/tools/traffic_annotation/bin/linux64/traffic_annotation_extractor.sha1 b/tools/traffic_annotation/bin/linux64/traffic_annotation_extractor.sha1 index e0f5492..c8636dc3 100644 --- a/tools/traffic_annotation/bin/linux64/traffic_annotation_extractor.sha1 +++ b/tools/traffic_annotation/bin/linux64/traffic_annotation_extractor.sha1
@@ -1 +1 @@ -cb73626ecd59e93627a0b151923012e22e459a47 \ No newline at end of file +ac5d58a08edc6f8dc8fc1ed343d56437bba1eaa8 \ No newline at end of file
diff --git a/tools/traffic_annotation/bin/win32/traffic_annotation_extractor.exe.sha1 b/tools/traffic_annotation/bin/win32/traffic_annotation_extractor.exe.sha1 index 0fa5960e..be0688af 100644 --- a/tools/traffic_annotation/bin/win32/traffic_annotation_extractor.exe.sha1 +++ b/tools/traffic_annotation/bin/win32/traffic_annotation_extractor.exe.sha1
@@ -1 +1 @@ -1951d61859d76edc0dc3a1c0f4e778aea5bff9b2 \ No newline at end of file +5314ef2a54f60f179e6cf5e4dd65d0f3bbc51bdf \ No newline at end of file
diff --git a/ui/accessibility/ax_node.cc b/ui/accessibility/ax_node.cc index 74f6a6a..1b089925 100644 --- a/ui/accessibility/ax_node.cc +++ b/ui/accessibility/ax_node.cc
@@ -601,6 +601,10 @@ return 0; } + // If tree is being updated, return 0. + if (tree()->GetTreeUpdateInProgressState()) + return 0; + // See AXTree::GetPosInSet return tree_->GetPosInSet(*this, ordered_set); } @@ -620,6 +624,10 @@ if (!ordered_set) return 0; + // If tree is being updated, return 0. + if (tree()->GetTreeUpdateInProgressState()) + return 0; + // See AXTree::GetSetSize return tree_->GetSetSize(*this, ordered_set); }
diff --git a/ui/accessibility/ax_node.h b/ui/accessibility/ax_node.h index 2ce901e..5fc97ce 100644 --- a/ui/accessibility/ax_node.h +++ b/ui/accessibility/ax_node.h
@@ -39,6 +39,7 @@ const AXNode* ordered_set) = 0; virtual int32_t GetSetSize(const AXNode& node, const AXNode* ordered_set) = 0; + virtual bool GetTreeUpdateInProgressState() const = 0; }; // The constructor requires a parent, id, and index in parent, but
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc index 7f0266a..36e661e 100644 --- a/ui/accessibility/ax_tree.cc +++ b/ui/accessibility/ax_tree.cc
@@ -8,6 +8,7 @@ #include <set> +#include "base/auto_reset.h" #include "base/command_line.h" #include "base/logging.h" #include "base/strings/stringprintf.h" @@ -370,6 +371,11 @@ } bool AXTree::Unserialize(const AXTreeUpdate& update) { + // Set update state to true. + // tree_update_in_progress_ gets set back to false whenever this function + // exits. + base::AutoReset<bool> update_state_resetter(&tree_update_in_progress_, true); + AXTreeUpdateState update_state; int32_t old_root_id = root_ ? root_->id() : 0; @@ -491,6 +497,10 @@ } changes.push_back(AXTreeObserver::Change(node, change)); } + + // Tree is no longer updating. + SetTreeUpdateInProgressState(false); + for (AXTreeObserver& observer : observers_) { observer.OnAtomicUpdateFinished(this, root_->id() != old_root_id, changes); } @@ -1137,4 +1147,12 @@ return ordered_set_info_map_[node.id()].set_size; } +bool AXTree::GetTreeUpdateInProgressState() const { + return tree_update_in_progress_; +} + +void AXTree::SetTreeUpdateInProgressState(bool set_tree_update_value) { + tree_update_in_progress_ = set_tree_update_value; +} + } // namespace ui
diff --git a/ui/accessibility/ax_tree.h b/ui/accessibility/ax_tree.h index 5cc2035..a151d76 100644 --- a/ui/accessibility/ax_tree.h +++ b/ui/accessibility/ax_tree.h
@@ -147,6 +147,9 @@ // set_size values, minimizing the size of the cache. int32_t GetSetSize(const AXNode& node, const AXNode* ordered_set) override; + bool GetTreeUpdateInProgressState() const override; + void SetTreeUpdateInProgressState(bool set_tree_update_value); + // Language detection statistics std::unique_ptr<AXLanguageInfoStats> language_info_stats; @@ -267,6 +270,9 @@ // AXTree owns pointers so copying is non-trivial. DISALLOW_COPY_AND_ASSIGN(AXTree); + + // Indicates if the tree is updating. + bool tree_update_in_progress_ = false; }; } // namespace ui
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc index 80b03cd..3a14156 100644 --- a/ui/accessibility/ax_tree_unittest.cc +++ b/ui/accessibility/ax_tree_unittest.cc
@@ -91,6 +91,8 @@ void OnNodeChanged(AXTree* tree, AXNode* node) override { changed_ids_.push_back(node->id()); + if (call_posinset_and_setsize) + AssertPosinsetAndSetsizeZero(node); } void OnAtomicUpdateFinished(AXTree* tree, @@ -212,6 +214,12 @@ return attribute_change_log_; } + bool call_posinset_and_setsize = false; + void AssertPosinsetAndSetsizeZero(AXNode* node) { + ASSERT_EQ(0, node->GetPosInSet()); + ASSERT_EQ(0, node->GetSetSize()); + } + private: AXTree* tree_; bool tree_data_changed_; @@ -2344,4 +2352,35 @@ EXPECT_EQ(ordered_set->GetSetSize(), 3); } +// Tests that GetPosInSet and GetSetSize work while a tree is being +// unserialized. +TEST(AXTreeTest, TestSetSizePosInSetSubtreeDeleted) { + AXTreeUpdate initial_state; + initial_state.root_id = 1; + initial_state.nodes.resize(3); + initial_state.nodes[0].id = 1; + initial_state.nodes[0].role = ax::mojom::Role::kTree; + initial_state.nodes[0].child_ids = {2, 3}; + initial_state.nodes[1].id = 2; + initial_state.nodes[1].role = ax::mojom::Role::kTreeItem; + initial_state.nodes[2].id = 3; + initial_state.nodes[2].role = ax::mojom::Role::kTreeItem; + AXTree tree(initial_state); + + // This should work normally. + AXNode* item = tree.GetFromId(3); + EXPECT_EQ(item->GetPosInSet(), 2); + EXPECT_EQ(item->GetSetSize(), 2); + + // Use test observer to assert posinset and setsize are 0. + TestAXTreeObserver test_observer(&tree); + test_observer.call_posinset_and_setsize = true; + // Remove item from tree. + AXTreeUpdate tree_update = initial_state; + tree_update.nodes.resize(1); + tree_update.nodes[0].child_ids = {2}; + + ASSERT_TRUE(tree.Unserialize(tree_update)); +} + } // namespace ui
diff --git a/ui/gl/features.gni b/ui/gl/features.gni index a90d220..456990c 100644 --- a/ui/gl/features.gni +++ b/ui/gl/features.gni
@@ -14,5 +14,5 @@ # Should Dawn support be compiled to back the WebGPU implementation. # Also controls linking Dawn depedencies in such as SPIRV-Tools and # SPIRV-Cross - use_dawn = is_mac + use_dawn = false }
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane.cc b/ui/views/controls/tabbed_pane/tabbed_pane.cc index 93e9c7ba..29f4fd59 100644 --- a/ui/views/controls/tabbed_pane/tabbed_pane.cc +++ b/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -434,6 +434,8 @@ layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_START); layout->SetDefaultFlex(0); SetLayoutManager(std::move(layout)); + + GetViewAccessibility().OverrideRole(ax::mojom::Role::kIgnored); } TabStrip::~TabStrip() = default;
diff --git a/ui/webui/resources/cr_elements/icons.html b/ui/webui/resources/cr_elements/icons.html index 8eb27b5..b42ef7c 100644 --- a/ui/webui/resources/cr_elements/icons.html +++ b/ui/webui/resources/cr_elements/icons.html
@@ -18,6 +18,7 @@ Keep these in sorted order by id="". See also http://goo.gl/Y1OdAq --> <g id="domain"><path d="M2,3 L2,17 L11.8267655,17 L13.7904799,17 L18,17 L18,7 L12,7 L12,3 L2,3 Z M8,13 L10,13 L10,15 L8,15 L8,13 Z M4,13 L6,13 L6,15 L4,15 L4,13 Z M8,9 L10,9 L10,11 L8,11 L8,9 Z M4,9 L6,9 L6,11 L4,11 L4,9 Z M12,9 L16,9 L16,15 L12,15 L12,9 Z M12,11 L14,11 L14,13 L12,13 L12,11 Z M8,5 L10,5 L10,7 L8,7 L8,5 Z M4,5 L6,5 L6,7 L4,7 L4,5 Z"></path></g> + <g id="kite"><path d="M 10.32 2 L 4.63 8 l 4.92 7.5 l -0.4 0.6 c -0.04 0.07 -0.09 0.12 -0.14 0.18 c -0.24 0.25 -0.56 0.39 -0.9 0.39 c -0.34 0 -0.65 -0.13 -0.9 -0.39 a 1.35 1.35 0 0 1 -0.37 -0.94 a 2.72 2.72 0 0 0 -0.74 -1.88 a 2.44 2.44 0 0 0 -1.78 -0.78 H 4 v 1.38 h 0.33 c 0.34 0 0.65 0.14 0.9 0.39 c 0.24 0.26 0.37 0.59 0.37 0.95 c 0 0.71 0.26 1.38 0.74 1.88 c 0.48 0.5 1.11 0.78 1.78 0.78 c 0.67 0 1.31 -0.28 1.78 -0.78 c 0.11 -0.11 0.2 -0.23 0.28 -0.35 l 1.27 -1.94 L 16 8 L 10.32 2 z"></path></g> </svg> </iron-iconset-svg> <iron-iconset-svg name="cr" size="24">
diff --git a/ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js b/ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js index d050d08..73d320e 100644 --- a/ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js +++ b/ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js
@@ -20,6 +20,7 @@ * controlledSettingShared: (string|undefined), * controlledSettingWithOwner: string, * controlledSettingNoOwner: string, + * controlledSettingParent: string, * }} */ // eslint-disable-next-line no-var @@ -34,6 +35,7 @@ PRIMARY_USER: 'primary_user', RECOMMENDED: 'recommended', USER_POLICY: 'userPolicy', + PARENT: 'parent', }; /** @polymerBehavior */ @@ -100,6 +102,8 @@ case CrPolicyIndicatorType.DEVICE_POLICY: case CrPolicyIndicatorType.RECOMMENDED: return 'cr20:domain'; + case CrPolicyIndicatorType.PARENT: + return 'cr20:kite'; default: assertNotReached(); } @@ -135,6 +139,8 @@ return opt_matches ? CrPolicyStrings.controlledSettingRecommendedMatches : CrPolicyStrings.controlledSettingRecommendedDiffers; + case CrPolicyIndicatorType.PARENT: + return CrPolicyStrings.controlledSettingParent; } return ''; },
diff --git a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js index d9dfa22d..08745d4 100644 --- a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js +++ b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
@@ -61,6 +61,8 @@ return CrPolicyIndicatorType.USER_POLICY; case chrome.settingsPrivate.ControlledBy.DEVICE_POLICY: return CrPolicyIndicatorType.DEVICE_POLICY; + case chrome.settingsPrivate.ControlledBy.PARENT: + return CrPolicyIndicatorType.PARENT; } } return CrPolicyIndicatorType.NONE;