diff --git a/AUTHORS b/AUTHORS index 05de8dc9..f773b6d 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -58,6 +58,7 @@ Andra Paraschiv <andra.paraschiv@intel.com> Andrei Parvu <andrei.prv@gmail.com> Andrei Parvu <parvu@adobe.com> +Andrew Boyarshin <andrew.boyarshin@gmail.com> Andrew Brampton <me@bramp.net> Andrew Hung <andrhung@amazon.com> Andrew MacPherson <andrew.macpherson@soundtrap.com>
diff --git a/DEPS b/DEPS index 3207e8b3..db2158c 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '6ecc911070add386dc9ffeb8b131d21035672fb6', + 'skia_revision': '1b0126b01511fe23d6e8f7b5be402d4d81921245', # 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': '326a8fdf23e2ba9faf35a5e200ffb50f847a06d9', + 'v8_revision': '175a595935ba451d675245238d3c2f9ba7075cbc', # 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. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '77e3fc5cebfb19aed09f920536200e017cff9a0b', + 'pdfium_revision': '2bf942d8c21b653efdfdcae681769cffbfaa0663', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'e9dc4c57fb003d9b289f6bf8bac98f820e1fe8b4', + 'catapult_revision': '57e600c76c9f2f6ab3a5b82d3cc21ca738a62a7e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -366,7 +366,7 @@ Var('chromium_git') + '/external/github.com/swisspol/GCDWebServer.git' + '@' + '43555c66627f6ed44817855a0f6d465f559d30e0', 'src/ios/third_party/material_components_ios/src': - Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '6d5844642b004594ba1607916032616f85c7c045', + Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'b452b1e7fb85cc9aeef2df2b6a44cbe0e8594560', 'src/ios/third_party/material_font_disk_loader_ios/src': Var('chromium_git') + '/external/github.com/material-foundation/material-font-disk-loader-ios.git' + '@' + '8e30188777b016182658fbaa0a4a020a48183224', @@ -1229,7 +1229,7 @@ 'action': [ 'python', 'src/build/fuchsia/update_sdk.py', - 'f79f55be4e69ebd90ea84f79d7322525853256c3', + '9c7191fae2233b5688d34f9d66717ee5c16ee2c7', ], }, ],
diff --git a/android_webview/browser/net/aw_cookie_store_wrapper_unittest.cc b/android_webview/browser/net/aw_cookie_store_wrapper_unittest.cc index 171bfb7..d856d24 100644 --- a/android_webview/browser/net/aw_cookie_store_wrapper_unittest.cc +++ b/android_webview/browser/net/aw_cookie_store_wrapper_unittest.cc
@@ -34,6 +34,7 @@ static const bool preserves_trailing_dots = true; static const bool filters_schemes = true; static const bool has_path_prefix_bug = false; + static const bool forbids_setting_empty_name = false; static const int creation_time_granularity_in_ms = 0; };
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java index 56d09a9..50edaf6 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java +++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java
@@ -100,6 +100,8 @@ mCommittedNavigation = true; + if (!isInMainFrame) return; + AwContentsClient client = mAwContentsClient.get(); if (hasCommitted && client != null) { boolean isReload = pageTransition != null @@ -107,8 +109,6 @@ client.getCallbackHelper().postDoUpdateVisitedHistory(url, isReload); } - if (!isInMainFrame) return; - // Only invoke the onPageCommitVisible callback when navigating to a different document, // but not when navigating to a different fragment within the same document. if (!isSameDocument) {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientVisitedHistoryTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientVisitedHistoryTest.java index 04b8906..0434d53 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientVisitedHistoryTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientVisitedHistoryTest.java
@@ -67,8 +67,9 @@ AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); AwContents awContents = testView.getAwContents(); + // Load a page with an iframe to make sure the callback only happens for the main frame URL. final String path = "/testUpdateVisitedHistoryCallback.html"; - final String html = "testUpdateVisitedHistoryCallback"; + final String html = "<iframe src=\"about:blank\"></iframe>"; TestWebServer webServer = TestWebServer.start(); try { @@ -80,13 +81,14 @@ doUpdateVisitedHistoryHelper.waitForCallback(callCount); assertEquals(pageUrl, doUpdateVisitedHistoryHelper.getUrl()); assertEquals(false, doUpdateVisitedHistoryHelper.getIsReload()); + assertEquals(callCount + 1, doUpdateVisitedHistoryHelper.getCallCount()); // Reload - callCount = doUpdateVisitedHistoryHelper.getCallCount(); loadUrlAsync(awContents, pageUrl); - doUpdateVisitedHistoryHelper.waitForCallback(callCount); + doUpdateVisitedHistoryHelper.waitForCallback(callCount + 1); assertEquals(pageUrl, doUpdateVisitedHistoryHelper.getUrl()); assertEquals(true, doUpdateVisitedHistoryHelper.getIsReload()); + assertEquals(callCount + 2, doUpdateVisitedHistoryHelper.getCallCount()); } finally { webServer.shutdown(); }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java index 0db88d6..0718fa1a 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java
@@ -160,6 +160,20 @@ assertEquals(false, doUpdateVisitedHistoryHelper.getIsReload()); callCount = doUpdateVisitedHistoryHelper.getCallCount(); + mWebContentsObserver.didFinishNavigation(nullUrl, isInMainFrame, isErrorPage, hasCommitted, + !isSameDocument, fragmentNavigation, PageTransition.TYPED, errorCode, + errorDescription, httpStatusCode); + mWebContentsObserver.didFinishNavigation(EXAMPLE_URL, !isInMainFrame, isErrorPage, + hasCommitted, !isSameDocument, fragmentNavigation, PageTransition.TYPED, errorCode, + errorDescription, httpStatusCode); + doUpdateVisitedHistoryHelper.waitForCallback(callCount); + assertEquals("doUpdateVisitedHistory should only be called for the main frame.", + callCount + 1, doUpdateVisitedHistoryHelper.getCallCount()); + assertEquals("doUpdateVisitedHistory should only be called for the main frame.", nullUrl, + doUpdateVisitedHistoryHelper.getUrl()); + assertEquals(false, doUpdateVisitedHistoryHelper.getIsReload()); + + callCount = doUpdateVisitedHistoryHelper.getCallCount(); mWebContentsObserver.didFinishNavigation(EXAMPLE_URL, isInMainFrame, isErrorPage, hasCommitted, isSameDocument, !fragmentNavigation, PageTransition.RELOAD, errorCode, errorDescription, httpStatusCode);
diff --git a/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt b/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt index f29be24..dcee1c8 100644 --- a/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt +++ b/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt
@@ -5166,8 +5166,7 @@ getter animationName getter elapsedTime method constructor -interface WebKitCSSMatrix : DOMMatrixReadOnly - attribute @@toStringTag +interface WebKitCSSMatrix getter a getter b getter c @@ -5191,18 +5190,16 @@ getter m43 getter m44 method constructor - method invertSelf - method multiplySelf - method preMultiplySelf - method rotateAxisAngleSelf - method rotateFromVectorSelf - method rotateSelf - method scale3dSelf - method scaleSelf + method inverse + method multiply + method rotate + method rotateAxisAngle + method scale method setMatrixValue - method skewXSelf - method skewYSelf - method translateSelf + method skewX + method skewY + method toString + method translate setter a setter b setter c
diff --git a/ash/ash_switches.cc b/ash/ash_switches.cc index 3db6f13..30fc6c4 100644 --- a/ash/ash_switches.cc +++ b/ash/ash_switches.cc
@@ -30,9 +30,6 @@ // Enable keyboard shortcuts used by developers only. const char kAshDeveloperShortcuts[] = "ash-dev-shortcuts"; -// Disable the Night Light feature. -const char kAshDisableNightLight[] = "ash-disable-night-light"; - // Disable the Touch Exploration Mode. Touch Exploration Mode will no longer be // turned on automatically when spoken feedback is enabled when this flag is // set. @@ -43,6 +40,9 @@ const char kAshEnableMagnifierKeyScroller[] = "ash-enable-magnifier-key-scroller"; +// Enables the NightLight feature. +const char kAshEnableNightLight[] = "ash-enable-night-light"; + // Enables the palette on every display, instead of only the internal one. const char kAshEnablePaletteOnAllDisplays[] = "ash-enable-palette-on-all-displays";
diff --git a/ash/ash_switches.h b/ash/ash_switches.h index e3e7337..5aecb7b5 100644 --- a/ash/ash_switches.h +++ b/ash/ash_switches.h
@@ -20,10 +20,10 @@ ASH_EXPORT extern const char kAshCopyHostBackgroundAtBoot[]; ASH_EXPORT extern const char kAshDebugShortcuts[]; ASH_EXPORT extern const char kAshDeveloperShortcuts[]; -ASH_EXPORT extern const char kAshDisableNightLight[]; ASH_EXPORT extern const char kAshDisableSmoothScreenRotation[]; ASH_EXPORT extern const char kAshDisableTouchExplorationMode[]; ASH_EXPORT extern const char kAshEnableMagnifierKeyScroller[]; +ASH_EXPORT extern const char kAshEnableNightLight[]; ASH_EXPORT extern const char kAshEnablePaletteOnAllDisplays[]; ASH_EXPORT extern const char kAshEnableScaleSettingsTray[]; ASH_EXPORT extern const char kAshEnableTouchView[];
diff --git a/ash/mojo_interface_factory.cc b/ash/mojo_interface_factory.cc index 10aec6ab..b11a3f8 100644 --- a/ash/mojo_interface_factory.cc +++ b/ash/mojo_interface_factory.cc
@@ -27,7 +27,6 @@ #include "base/bind.h" #include "base/single_thread_task_runner.h" #include "services/service_manager/public/cpp/bind_source_info.h" -#include "services/service_manager/public/cpp/binder_registry.h" #include "ui/app_list/presenter/app_list.h" namespace ash {
diff --git a/ash/mojo_interface_factory.h b/ash/mojo_interface_factory.h index ea3b95e3..49edce2 100644 --- a/ash/mojo_interface_factory.h +++ b/ash/mojo_interface_factory.h
@@ -8,15 +8,12 @@ #include "ash/ash_export.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "services/service_manager/public/cpp/binder_registry.h" namespace base { class SingleThreadTaskRunner; } -namespace service_manager { -class BinderRegistry; -} - namespace ash { namespace mojo_interface_factory {
diff --git a/ash/system/night_light/night_light_controller.cc b/ash/system/night_light/night_light_controller.cc index e84b5ce..e5f68eaa 100644 --- a/ash/system/night_light/night_light_controller.cc +++ b/ash/system/night_light/night_light_controller.cc
@@ -110,8 +110,8 @@ // static bool NightLightController::IsFeatureEnabled() { - return !base::CommandLine::ForCurrentProcess()->HasSwitch( - ash::switches::kAshDisableNightLight); + return base::CommandLine::ForCurrentProcess()->HasSwitch( + ash::switches::kAshEnableNightLight); } // static
diff --git a/ash/system/night_light/night_light_controller_unittest.cc b/ash/system/night_light/night_light_controller_unittest.cc index c3427a1f..3745641 100644 --- a/ash/system/night_light/night_light_controller_unittest.cc +++ b/ash/system/night_light/night_light_controller_unittest.cc
@@ -7,6 +7,7 @@ #include <cmath> #include <limits> +#include "ash/ash_switches.h" #include "ash/public/cpp/ash_pref_names.h" #include "ash/public/cpp/config.h" #include "ash/public/cpp/session_types.h" @@ -17,6 +18,7 @@ #include "ash/test/test_shell_delegate.h" #include "base/bind.h" #include "base/callback_forward.h" +#include "base/command_line.h" #include "base/macros.h" #include "components/prefs/testing_pref_service.h" #include "ui/compositor/layer.h" @@ -125,6 +127,10 @@ // ash::test::AshTestBase: void SetUp() override { + // Explicitly enable the NightLight feature for the tests. + base::CommandLine::ForCurrentProcess()->AppendSwitch( + ash::switches::kAshEnableNightLight); + test::AshTestBase::SetUp(); CreateTestUserSessions(); Shell::RegisterPrefs(user1_pref_service_.registry());
diff --git a/ash/system/night_light/tray_night_light_unittest.cc b/ash/system/night_light/tray_night_light_unittest.cc index 3a8ca56..1491771c 100644 --- a/ash/system/night_light/tray_night_light_unittest.cc +++ b/ash/system/night_light/tray_night_light_unittest.cc
@@ -4,6 +4,7 @@ #include "ash/system/night_light/tray_night_light.h" +#include "ash/ash_switches.h" #include "ash/public/cpp/config.h" #include "ash/shell.h" #include "ash/system/night_light/night_light_controller.h" @@ -11,6 +12,7 @@ #include "ash/test/ash_test_base.h" #include "ash/test/ash_test_helper.h" #include "ash/test/test_shell_delegate.h" +#include "base/command_line.h" #include "base/macros.h" #include "components/prefs/testing_pref_service.h" @@ -27,6 +29,10 @@ // ash::test::AshTestBase: void SetUp() override { + // Explicitly enable the NightLight feature for the tests. + base::CommandLine::ForCurrentProcess()->AppendSwitch( + ash::switches::kAshEnableNightLight); + test::AshTestBase::SetUp(); GetSessionControllerClient()->Reset(); GetSessionControllerClient()->AddUserSession(kFakeUserEmail);
diff --git a/ash/system/tiles/tray_tiles_unittest.cc b/ash/system/tiles/tray_tiles_unittest.cc index 50a4920..6599f48 100644 --- a/ash/system/tiles/tray_tiles_unittest.cc +++ b/ash/system/tiles/tray_tiles_unittest.cc
@@ -4,12 +4,14 @@ #include "ash/system/tiles/tray_tiles.h" +#include "ash/ash_switches.h" #include "ash/system/night_light/night_light_controller.h" #include "ash/system/night_light/night_light_toggle_button.h" #include "ash/system/tiles/tiles_default_view.h" #include "ash/system/tray/system_menu_button.h" #include "ash/test/ash_test_base.h" #include "ash/test/test_session_controller_client.h" +#include "base/command_line.h" #include "components/user_manager/user_type.h" #include "ui/views/view.h" @@ -24,6 +26,10 @@ ~TrayTilesTest() override {} void SetUp() override { + // Explicitly enable the NightLight feature for the tests. + base::CommandLine::ForCurrentProcess()->AppendSwitch( + ash::switches::kAshEnableNightLight); + test::NoSessionAshTestBase::SetUp(); tray_tiles_.reset(new TrayTiles(GetPrimarySystemTray())); }
diff --git a/base/cpu.cc b/base/cpu.cc index 848208f7..136501c 100644 --- a/base/cpu.cc +++ b/base/cpu.cc
@@ -19,7 +19,7 @@ #endif #if defined(ARCH_CPU_X86_FAMILY) -#if defined(_MSC_VER) +#if defined(COMPILER_MSVC) #include <intrin.h> #include <immintrin.h> // For _xgetbv() #endif @@ -54,7 +54,7 @@ namespace { #if defined(ARCH_CPU_X86_FAMILY) -#ifndef _MSC_VER +#if !defined(COMPILER_MSVC) #if defined(__pic__) && defined(__i386__) @@ -89,7 +89,7 @@ return (static_cast<uint64_t>(edx) << 32) | eax; } -#endif // !_MSC_VER +#endif // !defined(COMPILER_MSVC) #endif // ARCH_CPU_X86_FAMILY #if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
diff --git a/base/cpu.h b/base/cpu.h index 0e24df6..2c6caeaf 100644 --- a/base/cpu.h +++ b/base/cpu.h
@@ -12,9 +12,8 @@ namespace base { // Query information about the processor. -class BASE_EXPORT CPU { +class BASE_EXPORT CPU final { public: - // Constructor CPU(); enum IntelMicroArchitecture {
diff --git a/base/process/memory_unittest.cc b/base/process/memory_unittest.cc index ca6a112..03704c4 100644 --- a/base/process/memory_unittest.cc +++ b/base/process/memory_unittest.cc
@@ -38,7 +38,7 @@ #if defined(OS_WIN) -#if defined(_MSC_VER) +#if defined(COMPILER_MSVC) // ssize_t needed for OutOfMemoryTest. #if defined(_WIN64) typedef __int64 ssize_t;
diff --git a/base/strings/safe_sprintf.h b/base/strings/safe_sprintf.h index 65524a50..d6886db 100644 --- a/base/strings/safe_sprintf.h +++ b/base/strings/safe_sprintf.h
@@ -21,7 +21,7 @@ namespace base { namespace strings { -#if defined(_MSC_VER) +#if defined(COMPILER_MSVC) // Define ssize_t inside of our namespace. #if defined(_WIN64) typedef __int64 ssize_t;
diff --git a/build/check_gn_headers.py b/build/check_gn_headers.py index 1db587a7..f6ae8f5 100755 --- a/build/check_gn_headers.py +++ b/build/check_gn_headers.py
@@ -148,9 +148,12 @@ def IsBuildClean(out_dir): cmd = [os.path.join(DEPOT_TOOLS_DIR, 'ninja'), '-C', out_dir, '-n'] - out = subprocess.check_output(cmd) - return 'no work to do.' in out - + try: + out = subprocess.check_output(cmd) + return 'no work to do.' in out + except Exception as e: + print e + return False def ParseWhiteList(whitelist): out = set()
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py index 0e191073..bb48708b 100755 --- a/build/vs_toolchain.py +++ b/build/vs_toolchain.py
@@ -23,7 +23,7 @@ # Use MSVS2015 as the default toolchain. -CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2015' +CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2017' def SetEnvironmentAndGetRuntimeDllDirs():
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index bfb71501..c17e76d 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -87,7 +87,6 @@ property_tree_sequence_number_(-1), should_flatten_transform_from_property_tree_(false), draws_content_(false), - use_local_transform_for_backface_visibility_(false), should_check_backface_visibility_(false), force_render_surface_for_testing_(false), subtree_property_changed_(false), @@ -1029,13 +1028,6 @@ SetNeedsPushProperties(); } -void Layer::SetUseLocalTransformForBackfaceVisibility(bool use_local) { - if (use_local_transform_for_backface_visibility_ == use_local) - return; - use_local_transform_for_backface_visibility_ = use_local; - SetNeedsPushProperties(); -} - void Layer::SetShouldCheckBackfaceVisibility( bool should_check_backface_visibility) { if (should_check_backface_visibility_ == should_check_backface_visibility) @@ -1144,6 +1136,7 @@ // The ElementId should be set first because other setters depend on it such // as LayerImpl::SetScrollClipLayer. layer->SetElementId(inputs_.element_id); + layer->SetHasTransformNode(has_transform_node_); layer->SetBackgroundColor(inputs_.background_color); layer->SetSafeOpaqueBackgroundColor(safe_opaque_background_color_); layer->SetBounds(inputs_.bounds); @@ -1176,8 +1169,6 @@ layer->set_should_flatten_transform_from_property_tree( should_flatten_transform_from_property_tree_); layer->SetUseParentBackfaceVisibility(inputs_.use_parent_backface_visibility); - layer->SetUseLocalTransformForBackfaceVisibility( - use_local_transform_for_backface_visibility_); layer->SetShouldCheckBackfaceVisibility(should_check_backface_visibility_); layer->SetScrollClipLayer(inputs_.scroll_clip_layer_id);
diff --git a/cc/layers/layer.h b/cc/layers/layer.h index 1c21419..e77765e 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h
@@ -281,11 +281,6 @@ return inputs_.use_parent_backface_visibility; } - void SetUseLocalTransformForBackfaceVisibility(bool use_local); - bool use_local_transform_for_backface_visibility() const { - return use_local_transform_for_backface_visibility_; - } - void SetShouldCheckBackfaceVisibility(bool should_check_backface_visibility); bool should_check_backface_visibility() const { return should_check_backface_visibility_; @@ -629,7 +624,6 @@ gfx::Vector2dF offset_to_transform_parent_; bool should_flatten_transform_from_property_tree_ : 1; bool draws_content_ : 1; - bool use_local_transform_for_backface_visibility_ : 1; bool should_check_backface_visibility_ : 1; bool force_render_surface_for_testing_ : 1; bool subtree_property_changed_ : 1;
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index d46326c..ede6881a 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc
@@ -62,7 +62,6 @@ masks_to_bounds_(false), contents_opaque_(false), use_parent_backface_visibility_(false), - use_local_transform_for_backface_visibility_(false), should_check_backface_visibility_(false), draws_content_(false), contributes_to_drawn_render_surface_(false), @@ -80,7 +79,8 @@ needs_push_properties_(false), scrollbars_hidden_(false), needs_show_scrollbars_(false), - raster_even_if_not_drawn_(false) { + raster_even_if_not_drawn_(false), + has_transform_node_(false) { DCHECK_GT(layer_id_, 0); DCHECK(layer_tree_impl_); @@ -312,6 +312,7 @@ // as LayerImpl::SetScrollClipLayer. layer->SetElementId(element_id_); + layer->has_transform_node_ = has_transform_node_; layer->offset_to_transform_parent_ = offset_to_transform_parent_; layer->main_thread_scrolling_reasons_ = main_thread_scrolling_reasons_; layer->should_flatten_transform_from_property_tree_ = @@ -320,8 +321,6 @@ layer->contents_opaque_ = contents_opaque_; layer->may_contain_video_ = may_contain_video_; layer->use_parent_backface_visibility_ = use_parent_backface_visibility_; - layer->use_local_transform_for_backface_visibility_ = - use_local_transform_for_backface_visibility_; layer->should_check_backface_visibility_ = should_check_backface_visibility_; layer->draws_content_ = draws_content_; layer->non_fast_scrollable_region_ = non_fast_scrollable_region_; @@ -674,11 +673,6 @@ return GetMutatorHost()->HasFilterAnimationThatInflatesBounds(element_id()); } -bool LayerImpl::HasTransformAnimationThatInflatesBounds() const { - return GetMutatorHost()->HasTransformAnimationThatInflatesBounds( - element_id()); -} - bool LayerImpl::HasAnimationThatInflatesBounds() const { return GetMutatorHost()->HasAnimationThatInflatesBounds(element_id()); }
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index 245c777..9c2e758 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h
@@ -87,6 +87,9 @@ gfx::ScrollOffset ScrollOffsetForAnimation() const; bool IsActive() const; + void SetHasTransformNode(bool val) { has_transform_node_ = val; } + bool has_transform_node() { return has_transform_node_; } + void set_property_tree_sequence_number(int sequence_number) {} void SetTransformTreeIndex(int index); @@ -202,13 +205,6 @@ return use_parent_backface_visibility_; } - void SetUseLocalTransformForBackfaceVisibility(bool use_local) { - use_local_transform_for_backface_visibility_ = use_local; - } - bool use_local_transform_for_backface_visibility() const { - return use_local_transform_for_backface_visibility_; - } - void SetShouldCheckBackfaceVisibility(bool should_check_backface_visibility) { should_check_backface_visibility_ = should_check_backface_visibility; } @@ -331,7 +327,6 @@ bool HasPotentiallyRunningTransformAnimation() const; bool HasFilterAnimationThatInflatesBounds() const; - bool HasTransformAnimationThatInflatesBounds() const; bool HasAnimationThatInflatesBounds() const; bool FilterAnimationBoundsForBox(const gfx::BoxF& box, @@ -496,7 +491,6 @@ bool masks_to_bounds_ : 1; bool contents_opaque_ : 1; bool use_parent_backface_visibility_ : 1; - bool use_local_transform_for_backface_visibility_ : 1; bool should_check_backface_visibility_ : 1; bool draws_content_ : 1; bool contributes_to_drawn_render_surface_ : 1; @@ -565,6 +559,8 @@ // are still rasterized. bool raster_even_if_not_drawn_ : 1; + bool has_transform_node_ : 1; + DISALLOW_COPY_AND_ASSIGN(LayerImpl); };
diff --git a/cc/layers/layer_utils.cc b/cc/layers/layer_utils.cc index 6dbaecd..715fd06f 100644 --- a/cc/layers/layer_utils.cc +++ b/cc/layers/layer_utils.cc
@@ -14,10 +14,6 @@ namespace { -bool HasTransformAnimationThatInflatesBounds(const LayerImpl& layer) { - return layer.HasTransformAnimationThatInflatesBounds(); -} - inline bool HasAncestorTransformAnimation(const TransformNode* transform_node) { return transform_node->to_screen_is_potentially_animated; } @@ -86,19 +82,19 @@ for (; transform_tree.parent(transform_node); transform_node = transform_tree.parent(transform_node)) { - LayerImpl* layer = - layer_in.layer_tree_impl()->LayerById(transform_node->owning_layer_id); - // Filter animation bounds are unimplemented, see function // HasAncestorFilterAnimation() for reference. - if (HasTransformAnimationThatInflatesBounds(*layer)) { + if (transform_node->element_id != ElementId() && + layer_in.GetMutatorHost()->HasTransformAnimationThatInflatesBounds( + transform_node->element_id)) { coalesced_transform.ConcatTransform(transform_node->pre_local); coalesced_transform.TransformBox(&box); coalesced_transform.MakeIdentity(); gfx::BoxF inflated; - if (!layer->TransformAnimationBoundsForBox(box, &inflated)) + if (!layer_in.GetMutatorHost()->TransformAnimationBoundsForBox( + transform_node->element_id, box, &inflated)) return false; box = inflated;
diff --git a/cc/trees/clip_node.cc b/cc/trees/clip_node.cc index a0da843..76272e39 100644 --- a/cc/trees/clip_node.cc +++ b/cc/trees/clip_node.cc
@@ -14,7 +14,6 @@ ClipNode::ClipNode() : id(ClipTree::kInvalidNodeId), parent_id(ClipTree::kInvalidNodeId), - owning_layer_id(Layer::INVALID_ID), clip_type(ClipType::APPLIES_LOCAL_CLIP), transform_id(TransformTree::kInvalidNodeId) { } @@ -22,7 +21,6 @@ ClipNode::ClipNode(const ClipNode& other) : id(other.id), parent_id(other.parent_id), - owning_layer_id(other.owning_layer_id), clip_type(other.clip_type), clip(other.clip), transform_id(other.transform_id) { @@ -38,7 +36,6 @@ ClipNode& ClipNode::operator=(const ClipNode& other) { id = other.id; parent_id = other.parent_id; - owning_layer_id = other.owning_layer_id; clip_type = other.clip_type; clip = other.clip; transform_id = other.transform_id; @@ -65,7 +62,6 @@ (!clip_expander && other.clip_expander)) return false; return id == other.id && parent_id == other.parent_id && - owning_layer_id == other.owning_layer_id && clip_type == other.clip_type && clip == other.clip && transform_id == other.transform_id; } @@ -73,7 +69,6 @@ void ClipNode::AsValueInto(base::trace_event::TracedValue* value) const { value->SetInteger("id", id); value->SetInteger("parent_id", parent_id); - value->SetInteger("owning_layer_id", owning_layer_id); value->SetInteger("clip_type", static_cast<int>(clip_type)); MathUtil::AddToTracedValue("clip", clip, value); value->SetInteger("transform_id", transform_id);
diff --git a/cc/trees/clip_node.h b/cc/trees/clip_node.h index dcad9cb..506b493 100644 --- a/cc/trees/clip_node.h +++ b/cc/trees/clip_node.h
@@ -32,8 +32,6 @@ int id; // The node index of the parent node in the clip tree node vector. int parent_id; - // The layer id of the layer that owns this node. - int owning_layer_id; enum class ClipType { // The node contributes a new clip (that is, |clip| needs to be applied).
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc index c9c729d..7578582 100644 --- a/cc/trees/draw_property_utils.cc +++ b/cc/trees/draw_property_utils.cc
@@ -355,11 +355,9 @@ template <typename LayerType> static int TransformTreeIndexForBackfaceVisibility(LayerType* layer, const TransformTree& tree) { - if (!layer->use_parent_backface_visibility()) + if (!layer->use_parent_backface_visibility() || !layer->has_transform_node()) return layer->transform_tree_index(); - const TransformNode* node = tree.Node(layer->transform_tree_index()); - return layer->id() == node->owning_layer_id ? tree.parent(node)->id - : node->id; + return tree.Node(layer->transform_tree_index())->parent_id; } static bool IsTargetSpaceTransformBackFaceVisible( @@ -386,12 +384,8 @@ static bool IsLayerBackFaceVisible(LayerType* layer, int transform_tree_index, const PropertyTrees* property_trees) { - const TransformNode* node = - property_trees->transform_tree.Node(transform_tree_index); - return layer->use_local_transform_for_backface_visibility() - ? node->local.IsBackFaceVisible() - : IsTargetSpaceTransformBackFaceVisible( - layer, transform_tree_index, property_trees); + return IsTargetSpaceTransformBackFaceVisible(layer, transform_tree_index, + property_trees); } static inline bool TransformToScreenIsKnown(Layer* layer,
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index 89e907e2..f5b9502 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -5606,16 +5606,10 @@ EXPECT_EQ(1u, render_surface_list_impl()->size()); EXPECT_TRUE(grand_child->contributes_to_drawn_render_surface()); - // As all layers have identity transform, we shouldn't check for backface - // visibility. + // A ll layers with invisible backfgaces should be checked. EXPECT_FALSE(root->should_check_backface_visibility()); - EXPECT_FALSE(child->should_check_backface_visibility()); - EXPECT_FALSE(grand_child->should_check_backface_visibility()); - // As there are no 3d rendering contexts, all layers should use their local - // transform for backface visibility. - EXPECT_TRUE(root->use_local_transform_for_backface_visibility()); - EXPECT_TRUE(child->use_local_transform_for_backface_visibility()); - EXPECT_TRUE(grand_child->use_local_transform_for_backface_visibility()); + EXPECT_TRUE(child->should_check_backface_visibility()); + EXPECT_TRUE(grand_child->should_check_backface_visibility()); gfx::Transform rotation_transform; rotation_transform.RotateAboutXAxis(180.0); @@ -5635,13 +5629,6 @@ EXPECT_FALSE(root->should_check_backface_visibility()); EXPECT_TRUE(child->should_check_backface_visibility()); EXPECT_TRUE(grand_child->should_check_backface_visibility()); - // child uses its local transform for backface visibility as it is the root of - // a 3d rendering context. grand_child is in a 3d rendering context and is not - // the root, but it derives its backface visibility from its parent which uses - // its local transform. - EXPECT_TRUE(root->use_local_transform_for_backface_visibility()); - EXPECT_TRUE(child->use_local_transform_for_backface_visibility()); - EXPECT_TRUE(grand_child->use_local_transform_for_backface_visibility()); grand_child->SetUseParentBackfaceVisibility(false); grand_child->test_properties()->double_sided = false; @@ -5657,11 +5644,6 @@ EXPECT_FALSE(root->should_check_backface_visibility()); EXPECT_TRUE(child->should_check_backface_visibility()); EXPECT_TRUE(grand_child->should_check_backface_visibility()); - // grand_child is in an existing 3d rendering context, so it should not use - // local transform for backface visibility. - EXPECT_TRUE(root->use_local_transform_for_backface_visibility()); - EXPECT_TRUE(child->use_local_transform_for_backface_visibility()); - EXPECT_FALSE(grand_child->use_local_transform_for_backface_visibility()); } TEST_F(LayerTreeHostCommonTest, TransformAnimationUpdatesBackfaceVisibility) { @@ -9207,12 +9189,6 @@ page_scale_layer, inner_viewport_scroll_layer, outer_viewport_scroll_layer); - TransformTree& transform_tree = - root->layer_tree_impl()->property_trees()->transform_tree; - TransformNode* transform_node = - transform_tree.Node(significant_transform->transform_tree_index()); - EXPECT_EQ(transform_node->owning_layer_id, significant_transform->id()); - EXPECT_TRUE(GetRenderSurface(root)); EXPECT_EQ(GetRenderSurface(significant_transform), GetRenderSurface(root)); EXPECT_TRUE(GetRenderSurface(layer_clips_subtree));
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 1d8c66c..8f83f803 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -207,17 +207,12 @@ for (auto& pair : element_id_to_scrollbar_layer_ids_) { ElementId scrolling_element_id = pair.first; - // TODO(pdr): Remove this LayerImpl access and just use scroll nodes. This - // is blocked on scroll offset's dependency on LayerImpl. - LayerImpl* scrolling_layer = LayerByElementId(scrolling_element_id); - if (!scrolling_layer) - continue; - gfx::ScrollOffset current_offset = scrolling_layer->CurrentScrollOffset(); - auto& scroll_tree = property_trees()->scroll_tree; auto* scroll_node = scroll_tree.FindNodeFromElementId(scrolling_element_id); if (!scroll_node) continue; + gfx::ScrollOffset current_offset = + scroll_tree.current_scroll_offset(scrolling_element_id); gfx::SizeF scrolling_size(scroll_node->bounds); gfx::SizeF bounds_size( scroll_tree.scroll_clip_layer_bounds(scroll_node->id)); @@ -246,14 +241,13 @@ bounds_size.Scale(1 / current_page_scale_factor()); } - bool y_offset_did_change = false; for (auto* scrollbar : ScrollbarsFor(scrolling_element_id)) { if (scrollbar->orientation() == HORIZONTAL) { scrollbar->SetCurrentPos(current_offset.x()); scrollbar->SetClipLayerLength(bounds_size.width()); scrollbar->SetScrollLayerLength(scrolling_size.width()); } else { - y_offset_did_change = scrollbar->SetCurrentPos(current_offset.y()); + scrollbar->SetCurrentPos(current_offset.y()); scrollbar->SetClipLayerLength(bounds_size.height()); scrollbar->SetScrollLayerLength(scrolling_size.height()); } @@ -262,10 +256,6 @@ InnerViewportContainerLayer()->ViewportBoundsDelta().y()); } } - - if (y_offset_did_change && is_viewport_scrollbar) - TRACE_COUNTER_ID1("cc", "scroll_offset_y", scrolling_layer->id(), - current_offset.y()); } scrollbar_geometries_need_update_ = false;
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index 32ffa3ec..6f2fcdd 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc
@@ -1949,15 +1949,16 @@ .combined_starting_animation_scale = max_local_scale * ancestor_starting_animation_scale; } else { - // TODO(sunxd): make LayerTreeImpl::MaximumTargetScale take layer id as - // parameter. - LayerImpl* layer_impl = layer_tree_impl->LayerById(node->owning_layer_id); - layer_impl->GetMutatorHost()->MaximumTargetScale( - layer_impl->element_id(), layer_impl->GetElementTypeForAnimation(), + ElementListType list_type = layer_tree_impl->IsActiveTree() + ? ElementListType::ACTIVE + : ElementListType::PENDING; + + layer_tree_impl->mutator_host()->MaximumTargetScale( + node->element_id, list_type, &cached_data_.animation_scales[transform_node_id] .local_maximum_animation_target_scale); - layer_impl->GetMutatorHost()->AnimationStartScale( - layer_impl->element_id(), layer_impl->GetElementTypeForAnimation(), + layer_tree_impl->mutator_host()->AnimationStartScale( + node->element_id, list_type, &cached_data_.animation_scales[transform_node_id] .local_starting_animation_scale); gfx::Vector2dF local_scales =
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc index 490a055..2f287ca 100644 --- a/cc/trees/property_tree_builder.cc +++ b/cc/trees/property_tree_builder.cc
@@ -274,7 +274,6 @@ node.clip = gfx::RectF(gfx::PointF() + layer->offset_to_transform_parent(), gfx::SizeF(layer->bounds())); node.transform_id = transform_parent->transform_tree_index(); - node.owning_layer_id = layer->id(); if (layer_clips_subtree) { node.clip_type = ClipNode::ClipType::APPLIES_LOCAL_CLIP; } else { @@ -435,6 +434,7 @@ if (layer->element_id()) { data_for_children->property_trees ->element_id_to_transform_node_index[layer->element_id()] = node->id; + node->element_id = layer->element_id(); } node->scrolls = is_scrollable; @@ -575,8 +575,6 @@ // Flattening (if needed) will be handled by |node|. layer->set_should_flatten_transform_from_property_tree(false); - node->owning_layer_id = layer->id(); - return true; } @@ -998,8 +996,8 @@ return layer->test_properties()->user_scrollable_vertical; } -void SetHasTransformNode(LayerImpl* layer, bool val) {} -void SetHasTransformNode(Layer* layer, bool val) { +template <typename LayerType> +void SetHasTransformNode(LayerType* layer, bool val) { layer->SetHasTransformNode(val); } @@ -1098,37 +1096,19 @@ template <typename LayerType> void SetBackfaceVisibilityTransform(LayerType* layer, bool created_transform_node) { - const bool is_at_boundary_of_3d_rendering_context = - IsAtBoundaryOf3dRenderingContext(layer); if (layer->use_parent_backface_visibility()) { - DCHECK(!is_at_boundary_of_3d_rendering_context); DCHECK(Parent(layer)); DCHECK(!Parent(layer)->use_parent_backface_visibility()); - layer->SetUseLocalTransformForBackfaceVisibility( - Parent(layer)->use_local_transform_for_backface_visibility()); layer->SetShouldCheckBackfaceVisibility( Parent(layer)->should_check_backface_visibility()); } else { - // The current W3C spec on CSS transforms says that backface visibility - // should be determined differently depending on whether the layer is in a - // "3d rendering context" or not. For Chromium code, we can determine - // whether we are in a 3d rendering context by checking if the parent - // preserves 3d. - const bool use_local_transform = - !Is3dSorted(layer) || - (Is3dSorted(layer) && is_at_boundary_of_3d_rendering_context); - layer->SetUseLocalTransformForBackfaceVisibility(use_local_transform); - // A double-sided layer's backface can been shown when its visible. - if (DoubleSided(layer)) - layer->SetShouldCheckBackfaceVisibility(false); - // The backface of a layer that uses local transform for backface visibility - // is not visible when it does not create a transform node as its local - // transform is identity or 2d translation and is not animating. - else if (use_local_transform && !created_transform_node) - layer->SetShouldCheckBackfaceVisibility(false); - else - layer->SetShouldCheckBackfaceVisibility(true); + // In addition, we need to check if (1) there might be a local 3D transform + // on the layer that might turn it to the backface, or (2) it is not drawn + // into a flattened space. + layer->SetShouldCheckBackfaceVisibility( + !DoubleSided(layer) && + (created_transform_node || !ShouldFlattenTransform(Parent(layer)))); } }
diff --git a/cc/trees/transform_node.cc b/cc/trees/transform_node.cc index 6f89261d..044975f 100644 --- a/cc/trees/transform_node.cc +++ b/cc/trees/transform_node.cc
@@ -14,7 +14,6 @@ TransformNode::TransformNode() : id(TransformTree::kInvalidNodeId), parent_id(TransformTree::kInvalidNodeId), - owning_layer_id(Layer::INVALID_ID), sticky_position_constraint_id(-1), source_node_id(TransformTree::kInvalidNodeId), sorting_context_id(0), @@ -43,9 +42,9 @@ bool TransformNode::operator==(const TransformNode& other) const { return id == other.id && parent_id == other.parent_id && - owning_layer_id == other.owning_layer_id && - pre_local == other.pre_local && local == other.local && - post_local == other.post_local && to_parent == other.to_parent && + element_id == other.element_id && pre_local == other.pre_local && + local == other.local && post_local == other.post_local && + to_parent == other.to_parent && source_node_id == other.source_node_id && sorting_context_id == other.sorting_context_id && needs_local_transform_update == other.needs_local_transform_update && @@ -104,7 +103,7 @@ void TransformNode::AsValueInto(base::trace_event::TracedValue* value) const { value->SetInteger("id", id); value->SetInteger("parent_id", parent_id); - value->SetInteger("owning_layer_id", owning_layer_id); + value->SetInteger("element_id", element_id.id_); MathUtil::AddToTracedValue("pre_local", pre_local, value); MathUtil::AddToTracedValue("local", local, value); MathUtil::AddToTracedValue("post_local", post_local, value);
diff --git a/cc/trees/transform_node.h b/cc/trees/transform_node.h index 2abfb1c..9318675 100644 --- a/cc/trees/transform_node.h +++ b/cc/trees/transform_node.h
@@ -26,8 +26,8 @@ int id; // The node index of the parent node in the transform tree node vector. int parent_id; - // The layer id of the layer that owns this node. - int owning_layer_id; + + ElementId element_id; // The local transform information is combined to form to_parent (ignoring // snapping) as follows:
diff --git a/chrome/VERSION b/chrome/VERSION index 59a6461..78ffc81c 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=61 MINOR=0 -BUILD=3133 +BUILD=3135 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/JavascriptAppModalDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/JavascriptAppModalDialog.java index 97a68d33..1836678 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/JavascriptAppModalDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/JavascriptAppModalDialog.java
@@ -142,6 +142,19 @@ layout.findViewById(R.id.js_modal_dialog_scroll_view).setVisibility(View.GONE); } else { ((TextView) layout.findViewById(R.id.js_modal_dialog_message)).setText(mMessage); + + layout.findViewById(R.id.js_modal_dialog_scroll_view) + .addOnLayoutChangeListener(new View.OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + boolean isScrollable = + v.getMeasuredHeight() - v.getPaddingTop() - v.getPaddingBottom() + < ((ViewGroup) v).getChildAt(0).getMeasuredHeight(); + + v.setFocusable(isScrollable); + } + }); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index 01dbb160..05c0aa6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -65,6 +65,7 @@ import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabDelegateFactory; +import org.chromium.chrome.browser.tabmodel.AsyncTabParams; import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager; import org.chromium.chrome.browser.tabmodel.ChromeTabCreator; import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver; @@ -98,7 +99,8 @@ private static final int WEBCONTENTS_STATE_NO_WEBCONTENTS = 0; private static final int WEBCONTENTS_STATE_PRERENDERED_WEBCONTENTS = 1; private static final int WEBCONTENTS_STATE_SPARE_WEBCONTENTS = 2; - private static final int WEBCONTENTS_STATE_MAX = 3; + private static final int WEBCONTENTS_STATE_TRANSFERRED_WEBCONTENTS = 3; + private static final int WEBCONTENTS_STATE_MAX = 4; private static CustomTabContentHandler sActiveContentHandler; @@ -574,28 +576,15 @@ private Tab createMainTab() { CustomTabsConnection connection = CustomTabsConnection.getInstance(getApplication()); - String url = getUrlToLoad(); - String referrerUrl = connection.getReferrer(mSession, getIntent()); - Tab tab = new Tab(Tab.INVALID_TAB_ID, Tab.INVALID_TAB_ID, false, this, getWindowAndroid(), + WebContents webContents = takeWebContents(connection); + + int assignedTabId = IntentUtils.safeGetIntExtra( + getIntent(), IntentHandler.EXTRA_TAB_ID, Tab.INVALID_TAB_ID); + int parentTabId = IntentUtils.safeGetIntExtra( + getIntent(), IntentHandler.EXTRA_PARENT_TAB_ID, Tab.INVALID_TAB_ID); + Tab tab = new Tab(assignedTabId, parentTabId, false, this, getWindowAndroid(), TabLaunchType.FROM_EXTERNAL_APP, null, null); tab.setAppAssociatedWith(connection.getClientPackageNameForSession(mSession)); - - int webContentsStateOnLaunch = WEBCONTENTS_STATE_NO_WEBCONTENTS; - WebContents webContents = connection.takePrerenderedUrl(mSession, url, referrerUrl); - mUsingPrerender = webContents != null; - if (mUsingPrerender) webContentsStateOnLaunch = WEBCONTENTS_STATE_PRERENDERED_WEBCONTENTS; - if (!mUsingPrerender) { - webContents = WarmupManager.getInstance().takeSpareWebContents(false, false); - if (webContents != null) webContentsStateOnLaunch = WEBCONTENTS_STATE_SPARE_WEBCONTENTS; - } - RecordHistogram.recordEnumeratedHistogram("CustomTabs.WebContentsStateOnLaunch", - webContentsStateOnLaunch, WEBCONTENTS_STATE_MAX); - if (webContents == null) { - webContents = WebContentsFactory.createWebContentsWithWarmRenderer(false, false); - } - if (!mUsingPrerender) { - connection.resetPostMessageHandlerForSession(mSession, webContents); - } tab.initialize( webContents, getTabContentManager(), new CustomTabDelegateFactory( @@ -612,6 +601,52 @@ return tab; } + private WebContents takeWebContents(CustomTabsConnection connection) { + mUsingPrerender = true; + int webContentsStateOnLaunch = WEBCONTENTS_STATE_PRERENDERED_WEBCONTENTS; + WebContents webContents = takePrerenderedWebContents(connection); + + if (webContents == null) { + mUsingPrerender = false; + webContents = takeAsyncWebContents(); + if (webContents != null) { + webContentsStateOnLaunch = WEBCONTENTS_STATE_TRANSFERRED_WEBCONTENTS; + } else { + webContents = WarmupManager.getInstance().takeSpareWebContents(false, false); + if (webContents != null) { + webContentsStateOnLaunch = WEBCONTENTS_STATE_SPARE_WEBCONTENTS; + } else { + webContents = + WebContentsFactory.createWebContentsWithWarmRenderer(false, false); + webContentsStateOnLaunch = WEBCONTENTS_STATE_NO_WEBCONTENTS; + } + } + } + + RecordHistogram.recordEnumeratedHistogram("CustomTabs.WebContentsStateOnLaunch", + webContentsStateOnLaunch, WEBCONTENTS_STATE_MAX); + + if (!mUsingPrerender) { + connection.resetPostMessageHandlerForSession(mSession, webContents); + } + + return webContents; + } + + private WebContents takePrerenderedWebContents(CustomTabsConnection connection) { + String url = getUrlToLoad(); + String referrerUrl = connection.getReferrer(mSession, getIntent()); + return connection.takePrerenderedUrl(mSession, url, referrerUrl); + } + + private WebContents takeAsyncWebContents() { + int assignedTabId = IntentUtils.safeGetIntExtra( + getIntent(), IntentHandler.EXTRA_TAB_ID, Tab.INVALID_TAB_ID); + AsyncTabParams asyncParams = AsyncTabParamsManager.remove(assignedTabId); + if (asyncParams == null) return null; + return asyncParams.getWebContents(); + } + private void initializeMainTab(Tab tab) { tab.getTabRedirectHandler().updateIntent(getIntent()); tab.getView().requestFocus();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java index 83ecd149..299aaa5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
@@ -301,7 +301,9 @@ if (mShouldRemovePreviousNavigation) { mShouldRemovePreviousNavigation = false; NavigationController controller = webContents.getNavigationController(); - controller.removeEntryAtIndex(mLastDistillerPageIndex); + if (controller.getEntryAtIndex(mLastDistillerPageIndex) != null) { + controller.removeEntryAtIndex(mLastDistillerPageIndex); + } } // Make sure the tab was not destroyed. @@ -376,7 +378,7 @@ return; } - ReaderModeInfoBar.showReaderModeInfoBar(mTabModelSelector.getCurrentTab(), this); + ReaderModeInfoBar.showReaderModeInfoBar(mTabModelSelector.getCurrentTab()); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/ReaderModeInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/ReaderModeInfoBar.java index 8d7749e..38ce0d86 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/ReaderModeInfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/ReaderModeInfoBar.java
@@ -22,9 +22,6 @@ * {@link OverlayPanel} implementation when Chrome Home is enabled. */ public class ReaderModeInfoBar extends InfoBar { - /** A handle to the {@link ReaderModeManager} to trigger page navigations. */ - private static ReaderModeManager sManager; - /** * Default constructor. */ @@ -51,7 +48,7 @@ prompt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - sManager.navigateToReaderMode(); + if (getReaderModeManager() != null) getReaderModeManager().navigateToReaderMode(); } }); @@ -61,20 +58,31 @@ @Override public void onCloseButtonClicked() { super.onCloseButtonClicked(); - sManager.onClosed(StateChangeReason.CLOSE_BUTTON); + if (getReaderModeManager() != null) { + getReaderModeManager().onClosed(StateChangeReason.CLOSE_BUTTON); + } } /** * Create and show the Reader Mode {@link InfoBar}. * @param tab The tab that the {@link InfoBar} should be shown in. - * @param manager The {@link ReaderModeManager} for this instance of Chrome. */ - public static void showReaderModeInfoBar(Tab tab, ReaderModeManager manager) { - sManager = manager; + public static void showReaderModeInfoBar(Tab tab) { nativeCreate(tab); } /** + * @return The {@link ReaderModeManager} for this infobar. + */ + private ReaderModeManager getReaderModeManager() { + if (getNativeInfoBarPtr() == 0) return null; + Tab tab = nativeGetTab(getNativeInfoBarPtr()); + + if (tab == null || tab.getActivity() == null) return null; + return tab.getActivity().getReaderModeManager(); + } + + /** * @return An instance of the {@link ReaderModeInfoBar}. */ @CalledByNative @@ -83,4 +91,5 @@ } private static native void nativeCreate(Tab tab); + private native Tab nativeGetTab(long nativeReaderModeInfoBar); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java index 6ec9d02..4642fac 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java
@@ -8,18 +8,14 @@ import android.graphics.Rect; import android.os.StrictMode; import android.text.Editable; -import android.text.Selection; -import android.text.Spanned; import android.text.TextUtils; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; -import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; -import android.view.inputmethod.InputConnectionWrapper; import android.widget.EditText; import org.chromium.base.Log; @@ -29,40 +25,38 @@ /** * An {@link EditText} that shows autocomplete text at the end. */ -public class AutocompleteEditText extends VerticallyFixedEditText { +public class AutocompleteEditText + extends VerticallyFixedEditText implements AutocompleteEditTextModelBase.Delegate { private static final String TAG = "cr_AutocompleteEdit"; private static final boolean DEBUG = false; - private final AutocompleteSpan mAutocompleteSpan; private final AccessibilityManager mAccessibilityManager; + // This contains most of the logic. Lazily initialized in ensureModel() because View constructor + // may call its methods, so always call ensureModel() before accessing it. + private AutocompleteEditTextModelBase mModel; + /** * Whether default TextView scrolling should be disabled because autocomplete has been added. * This allows the user entered text to be shown instead of the end of the autocomplete. */ private boolean mDisableTextScrollingFromAutocomplete; - private int mBatchEditNestCount; - private int mBeforeBatchEditAutocompleteIndex = -1; - private String mBeforeBatchEditFullText; - private boolean mSelectionChangedInBatchMode; - private boolean mTextDeletedInBatchMode; - - // Set to true when the text is modified programmatically. Initially set to true until the old - // state has been loaded. - private boolean mIgnoreTextChangeFromAutocomplete = true; - private boolean mLastEditWasDelete; - private boolean mIgnoreImeForTest; public AutocompleteEditText(Context context, AttributeSet attrs) { super(context, attrs); - mAutocompleteSpan = new AutocompleteSpan(); mAccessibilityManager = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE); } + private void ensureModel() { + // Lazy initialization here to ensure that model methods get called even in View's + // constructor. + if (mModel == null) mModel = new AutocompleteEditTextModel(this); + } + /** * Sets whether text changes should trigger autocomplete. * @@ -70,51 +64,29 @@ * triggered. */ public void setIgnoreTextChangesForAutocomplete(boolean ignoreAutocomplete) { - if (DEBUG) Log.i(TAG, "setIgnoreTextChangesForAutocomplete: " + ignoreAutocomplete); - mIgnoreTextChangeFromAutocomplete = ignoreAutocomplete; - } - - /** @return Text that includes autocomplete. */ - public String getTextWithAutocomplete() { - return getEditableText() != null ? getEditableText().toString() : ""; - } - - /** - * @return Whether the current cursor position is at the end of the user typed text (i.e. - * at the beginning of the inline autocomplete text if present otherwise the very - * end of the current text). - */ - private boolean isCursorAtEndOfTypedText() { - final int selectionStart = getSelectionStart(); - final int selectionEnd = getSelectionEnd(); - - int expectedSelectionStart = getText().getSpanStart(mAutocompleteSpan); - int expectedSelectionEnd = getText().length(); - if (expectedSelectionStart < 0) { - expectedSelectionStart = expectedSelectionEnd; - } - - return selectionStart == expectedSelectionStart && selectionEnd == expectedSelectionEnd; + ensureModel(); + mModel.setIgnoreTextChangeFromAutocomplete(ignoreAutocomplete); } /** * @return The user text without the autocomplete text. */ public String getTextWithoutAutocomplete() { - int autoCompleteIndex = getText().getSpanStart(mAutocompleteSpan); - if (autoCompleteIndex < 0) { - return getTextWithAutocomplete(); - } else { - return getTextWithAutocomplete().substring(0, autoCompleteIndex); - } + ensureModel(); + return mModel.getTextWithoutAutocomplete(); + } + + /** @return Text that includes autocomplete. */ + public String getTextWithAutocomplete() { + ensureModel(); + return mModel.getTextWithAutocomplete(); } /** @return Whether any autocomplete information is specified on the current text. */ @VisibleForTesting public boolean hasAutocomplete() { - return getText().getSpanStart(mAutocompleteSpan) >= 0 - || mAutocompleteSpan.mAutocompleteText != null - || mAutocompleteSpan.mUserText != null; + ensureModel(); + return mModel.hasAutocomplete(); } /** @@ -124,100 +96,21 @@ * @return Whether we want to be showing inline autocomplete results. */ public boolean shouldAutocomplete() { - if (mLastEditWasDelete) return false; - Editable text = getText(); - - return isCursorAtEndOfTypedText() && mBatchEditNestCount == 0 - && BaseInputConnection.getComposingSpanEnd(text) - == BaseInputConnection.getComposingSpanStart(text); - } - - private void onPostEndBatchEdit() { - if (mSelectionChangedInBatchMode) { - validateSelection(getSelectionStart(), getSelectionEnd()); - mSelectionChangedInBatchMode = false; - } - - String newText = getText().toString(); - if (!TextUtils.equals(mBeforeBatchEditFullText, newText) - || getText().getSpanStart(mAutocompleteSpan) != mBeforeBatchEditAutocompleteIndex) { - // If the text being typed is a single character that matches the next character in the - // previously visible autocomplete text, we reapply the autocomplete text to prevent - // a visual flickering when the autocomplete text is cleared and then quickly reapplied - // when the next round of suggestions is received. - if (shouldAutocomplete() && mBeforeBatchEditAutocompleteIndex != -1 - && mBeforeBatchEditFullText != null - && mBeforeBatchEditFullText.startsWith(newText) && !mTextDeletedInBatchMode - && newText.length() - mBeforeBatchEditAutocompleteIndex == 1) { - setAutocompleteText(newText, mBeforeBatchEditFullText.substring(newText.length())); - } - notifyAutocompleteTextStateChanged(mTextDeletedInBatchMode, true); - } - - mTextDeletedInBatchMode = false; - mBeforeBatchEditAutocompleteIndex = -1; - mBeforeBatchEditFullText = null; + ensureModel(); + return mModel.shouldAutocomplete(); } @Override protected void onSelectionChanged(int selStart, int selEnd) { - if (DEBUG) Log.i(TAG, "onSelectionChanged -- selStart: %d, selEnd: %d", selStart, selEnd); - if (mBatchEditNestCount == 0) { - int beforeTextLength = getText().length(); - if (validateSelection(selStart, selEnd)) { - boolean textDeleted = getText().length() < beforeTextLength; - notifyAutocompleteTextStateChanged(textDeleted, false); - } - } else { - mSelectionChangedInBatchMode = true; - } + ensureModel(); + mModel.onSelectionChanged(selStart, selEnd); super.onSelectionChanged(selStart, selEnd); } - /** - * Validates the selection and clears the autocomplete span if needed. The autocomplete text - * will be deleted if the selection occurs entirely before the autocomplete region. - * - * @param selStart The start of the selection. - * @param selEnd The end of the selection. - * @return Whether the autocomplete span was removed as a result of this validation. - */ - private boolean validateSelection(int selStart, int selEnd) { - int spanStart = getText().getSpanStart(mAutocompleteSpan); - int spanEnd = getText().getSpanEnd(mAutocompleteSpan); - - if (DEBUG) { - Log.i(TAG, "validateSelection -- selStart: %d, selEnd: %d, spanStart: %d, spanEnd: %d", - selStart, selEnd, spanStart, spanEnd); - } - - if (spanStart >= 0 && (spanStart != selStart || spanEnd != selEnd)) { - CharSequence previousAutocompleteText = mAutocompleteSpan.mAutocompleteText; - - // On selection changes, the autocomplete text has been accepted by the user or needs - // to be deleted below. - mAutocompleteSpan.clearSpan(); - - // The autocomplete text will be deleted any time the selection occurs entirely before - // the start of the autocomplete text. This is required because certain keyboards will - // insert characters temporarily when starting a key entry gesture (whether it be - // swyping a word or long pressing to get a special character). When this temporary - // character appears, Chrome may decide to append some autocomplete, but the keyboard - // will then remove this temporary character only while leaving the autocomplete text - // alone. See crbug/273763 for more details. - if (selEnd <= spanStart - && TextUtils.equals(previousAutocompleteText, - getText().subSequence(spanStart, getText().length()))) { - getText().delete(spanStart, getText().length()); - } - return true; - } - return false; - } - @Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { - if (!focused) mAutocompleteSpan.clearSpan(); + ensureModel(); + mModel.onFocusChanged(focused); super.onFocusChanged(focused, direction, previouslyFocusedRect); } @@ -241,6 +134,12 @@ return retVal; } + /** Call this when text is pasted. */ + public void onPaste() { + ensureModel(); + mModel.onPaste(); + } + /** * Autocompletes the text and selects the text that was not entered by the user. Using append() * instead of setText() to preserve the soft-keyboard layout. @@ -248,50 +147,10 @@ * @param inlineAutocompleteText The suggested autocompletion for the user's text. */ public void setAutocompleteText(CharSequence userText, CharSequence inlineAutocompleteText) { - if (DEBUG) { - Log.i(TAG, "setAutocompleteText -- userText: %s, inlineAutocompleteText: %s", userText, - inlineAutocompleteText); - } boolean emptyAutocomplete = TextUtils.isEmpty(inlineAutocompleteText); - if (!emptyAutocomplete) mDisableTextScrollingFromAutocomplete = true; - - int autocompleteIndex = userText.length(); - - String previousText = getTextWithAutocomplete(); - CharSequence newText = TextUtils.concat(userText, inlineAutocompleteText); - - setIgnoreTextChangesForAutocomplete(true); - - if (!TextUtils.equals(previousText, newText)) { - // The previous text may also have included autocomplete text, so we only - // append the new autocomplete text that has changed. - if (TextUtils.indexOf(newText, previousText) == 0) { - append(newText.subSequence(previousText.length(), newText.length())); - } else { - replaceAllTextFromAutocomplete(newText.toString()); - } - } - - if (getSelectionStart() != autocompleteIndex || getSelectionEnd() != getText().length()) { - setSelection(autocompleteIndex, getText().length()); - - if (inlineAutocompleteText.length() != 0) { - // Sending a TYPE_VIEW_TEXT_SELECTION_CHANGED accessibility event causes the - // previous TYPE_VIEW_TEXT_CHANGED event to be swallowed. As a result the user - // hears the autocomplete text but *not* the text they typed. Instead we send a - // TYPE_ANNOUNCEMENT event, which doesn't swallow the text-changed event. - announceForAccessibility(inlineAutocompleteText); - } - } - - if (emptyAutocomplete) { - mAutocompleteSpan.clearSpan(); - } else { - mAutocompleteSpan.setSpan(userText, inlineAutocompleteText); - } - - setIgnoreTextChangesForAutocomplete(false); + ensureModel(); + mModel.setAutocompleteText(userText, inlineAutocompleteText); } /** @@ -299,31 +158,20 @@ * currently displayed. */ public int getAutocompleteLength() { - int autoCompleteIndex = getText().getSpanStart(mAutocompleteSpan); - if (autoCompleteIndex < 0) return 0; - return getText().length() - autoCompleteIndex; + ensureModel(); + return mModel.getAutocompleteText().length(); } @Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { - if (DEBUG) { - Log.i(TAG, "onTextChanged -- text: %s, start: %d, lengthBefore: %d, lengthAfter: %d", - text, start, lengthBefore, lengthAfter); - } - super.onTextChanged(text, start, lengthBefore, lengthAfter); - boolean textDeleted = lengthAfter == 0; - if (mBatchEditNestCount == 0) { - notifyAutocompleteTextStateChanged(textDeleted, true); - } else { - mTextDeletedInBatchMode = textDeleted; - } + ensureModel(); + mModel.onTextChanged(text, start, lengthBefore, lengthAfter); } @Override public void setText(CharSequence text, BufferType type) { if (DEBUG) Log.i(TAG, "setText -- text: %s", text); - mDisableTextScrollingFromAutocomplete = false; // Avoid setting the same text as it will mess up the scroll/cursor position. @@ -339,39 +187,17 @@ StrictMode.setThreadPolicy(oldPolicy); } } - - // Verify the autocomplete is still valid after the text change. - // Note: mAutocompleteSpan may be still null here if setText() is called in View - // constructor. - if (mAutocompleteSpan != null && mAutocompleteSpan.mUserText != null - && mAutocompleteSpan.mAutocompleteText != null) { - if (getText().getSpanStart(mAutocompleteSpan) < 0) { - mAutocompleteSpan.clearSpan(); - } else { - clearAutocompleteSpanIfInvalid(); - } - } - } - - private void clearAutocompleteSpanIfInvalid() { - Editable editableText = getEditableText(); - CharSequence previousUserText = mAutocompleteSpan.mUserText; - CharSequence previousAutocompleteText = mAutocompleteSpan.mAutocompleteText; - if (editableText.length() - != (previousUserText.length() + previousAutocompleteText.length())) { - mAutocompleteSpan.clearSpan(); - } else if (TextUtils.indexOf(getText(), previousUserText) != 0 - || TextUtils.indexOf(getText(), previousAutocompleteText, previousUserText.length()) - != 0) { - mAutocompleteSpan.clearSpan(); - } + ensureModel(); + mModel.onSetText(text); } @Override public void sendAccessibilityEventUnchecked(AccessibilityEvent event) { - if (mIgnoreTextChangeFromAutocomplete) { + ensureModel(); + if (mModel.shouldIgnoreTextChangeFromAutocomplete()) { if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED || event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) { + if (DEBUG) Log.i(TAG, "Ignoring accessibility event from autocomplete."); return; } } @@ -391,8 +217,9 @@ } @VisibleForTesting - public InputConnectionWrapper getInputConnection() { - return mInputConnection; + public InputConnection getInputConnection() { + ensureModel(); + return mModel.getInputConnection(); } @VisibleForTesting @@ -400,145 +227,17 @@ mIgnoreImeForTest = ignore; } - private InputConnectionWrapper mInputConnection = new InputConnectionWrapper(null, true) { - private final char[] mTempSelectionChar = new char[1]; - - @Override - public boolean beginBatchEdit() { - ++mBatchEditNestCount; - if (mBatchEditNestCount == 1) { - if (DEBUG) Log.i(TAG, "beginBatchEdit"); - mBeforeBatchEditAutocompleteIndex = getText().getSpanStart(mAutocompleteSpan); - mBeforeBatchEditFullText = getText().toString(); - - boolean retVal = super.beginBatchEdit(); - mTextDeletedInBatchMode = false; - return retVal; - } - return super.beginBatchEdit(); - } - - @Override - public boolean endBatchEdit() { - mBatchEditNestCount = Math.max(mBatchEditNestCount - 1, 0); - if (mBatchEditNestCount == 0) { - if (DEBUG) Log.i(TAG, "endBatchEdit"); - boolean retVal = super.endBatchEdit(); - onPostEndBatchEdit(); - return retVal; - } - return super.endBatchEdit(); - } - - @Override - public boolean commitText(CharSequence text, int newCursorPosition) { - if (DEBUG) Log.i(TAG, "commitText: [%s]", text); - Editable currentText = getText(); - if (currentText == null) return super.commitText(text, newCursorPosition); - - int selectionStart = Selection.getSelectionStart(currentText); - int selectionEnd = Selection.getSelectionEnd(currentText); - int autocompleteIndex = currentText.getSpanStart(mAutocompleteSpan); - // If the text being committed is a single character that matches the next character - // in the selection (assumed to be the autocomplete text), we only move the text - // selection instead clearing the autocomplete text causing flickering as the - // autocomplete text will appear once the next suggestions are received. - // - // To be confident that the selection is an autocomplete, we ensure the selection - // is at least one character and the end of the selection is the end of the - // currently entered text. - if (newCursorPosition == 1 && selectionStart > 0 && selectionStart != selectionEnd - && selectionEnd >= currentText.length() && autocompleteIndex == selectionStart - && text.length() == 1) { - currentText.getChars(selectionStart, selectionStart + 1, mTempSelectionChar, 0); - if (mTempSelectionChar[0] == text.charAt(0)) { - // Since the text isn't changing, TalkBack won't read out the typed characters. - // To work around this, explicitly send an accessibility event. crbug.com/416595 - if (mAccessibilityManager != null && mAccessibilityManager.isEnabled()) { - AccessibilityEvent event = AccessibilityEvent.obtain( - AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); - event.setFromIndex(selectionStart); - event.setRemovedCount(0); - event.setAddedCount(1); - event.setBeforeText(currentText.toString().substring(0, selectionStart)); - sendAccessibilityEventUnchecked(event); - } - - setAutocompleteText(currentText.subSequence(0, selectionStart + 1), - currentText.subSequence(selectionStart + 1, selectionEnd)); - if (mBatchEditNestCount == 0) { - notifyAutocompleteTextStateChanged(false, false); - } - return true; - } - } - - boolean retVal = super.commitText(text, newCursorPosition); - - // Ensure the autocomplete span is removed if it is no longer valid after committing the - // text. - if (getText().getSpanStart(mAutocompleteSpan) >= 0) clearAutocompleteSpanIfInvalid(); - - return retVal; - } - - @Override - public boolean setComposingText(CharSequence text, int newCursorPosition) { - if (DEBUG) Log.i(TAG, "setComposingText: [%s]", text); - Editable currentText = getText(); - int autoCompleteSpanStart = currentText.getSpanStart(mAutocompleteSpan); - if (autoCompleteSpanStart >= 0) { - int composingEnd = BaseInputConnection.getComposingSpanEnd(currentText); - - // On certain device/keyboard combinations, the composing regions are specified - // with a noticeable delay after the initial character is typed, and in certain - // circumstances it does not check that the current state of the text matches the - // expectations of it's composing region. - // For example, you can be typing: - // chrome://f - // Chrome will autocomplete to: - // chrome://f[lags] - // And after the autocomplete has been set, the keyboard will set the composing - // region to the last character and it assumes it is 'f' as it was the last - // character the keyboard sent. If we commit this composition, the text will - // look like: - // chrome://flag[f] - // And if we use the autocomplete clearing logic below, it will look like: - // chrome://f[f] - // To work around this, we see if the composition matches all the characters prior - // to the autocomplete and just readjust the composing region to be that subset. - // - // See crbug.com/366732 - if (composingEnd == currentText.length() && autoCompleteSpanStart >= text.length() - && TextUtils.equals( - currentText.subSequence(autoCompleteSpanStart - text.length(), - autoCompleteSpanStart), - text)) { - setComposingRegion( - autoCompleteSpanStart - text.length(), autoCompleteSpanStart); - } - - // Once composing text is being modified, the autocomplete text has been accepted - // or has to be deleted. - mAutocompleteSpan.clearSpan(); - Selection.setSelection(currentText, autoCompleteSpanStart); - currentText.delete(autoCompleteSpanStart, currentText.length()); - } - return super.setComposingText(text, newCursorPosition); - } - }; - @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - if (DEBUG) Log.i(TAG, "onCreateInputConnection"); return createInputConnection(super.onCreateInputConnection(outAttrs)); } @VisibleForTesting public InputConnection createInputConnection(InputConnection target) { - mInputConnection.setTarget(target); + ensureModel(); + InputConnection retVal = mModel.onCreateInputConnection(target); if (mIgnoreImeForTest) return null; - return mInputConnection; + return retVal; } @Override @@ -547,58 +246,38 @@ return super.dispatchKeyEvent(event); } - private void notifyAutocompleteTextStateChanged(boolean textDeleted, boolean updateDisplay) { - if (DEBUG) { - Log.i(TAG, "notifyAutocompleteTextStateChanged: DEL[%b] DIS[%b] IGN[%b]", textDeleted, - updateDisplay, mIgnoreTextChangeFromAutocomplete); - } - if (mIgnoreTextChangeFromAutocomplete) return; - if (!hasFocus()) return; - mLastEditWasDelete = textDeleted; - onAutocompleteTextStateChanged(textDeleted, updateDisplay); + /** + * @return Whether the current UrlBar input has been pasted from the clipboard. + */ + public boolean isPastedText() { + ensureModel(); + return mModel.isPastedText(); } - /** - * This is called when autocomplete replaces the whole text. - * - * @param text The text. - */ - protected void replaceAllTextFromAutocomplete(String text) { - setText(text); + @Override + public void replaceAllTextFromAutocomplete(String text) { + assert false; // make sure that this method is properly overridden. } - /** - * This is called when autocomplete text state changes. - * @param textDeleted True if text is just deleted. - * @param updateDisplay True if string is changed. - */ - public void onAutocompleteTextStateChanged(boolean textDeleted, boolean updateDisplay) {} + @Override + public void onAutocompleteTextStateChanged(boolean textDeleted, boolean updateDisplay) { + assert false; // make sure that this method is properly overridden. + } - /** - * Simple span used for tracking the current autocomplete state. - */ - private class AutocompleteSpan { - private CharSequence mUserText; - private CharSequence mAutocompleteText; - - /** - * Adds the span to the current text. - * @param userText The user entered text. - * @param autocompleteText The autocomplete text being appended. - */ - public void setSpan(CharSequence userText, CharSequence autocompleteText) { - Editable text = getText(); - text.removeSpan(this); - mAutocompleteText = autocompleteText; - mUserText = userText; - text.setSpan(this, userText.length(), text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - - /** Removes this span from the current text and clears the internal state. */ - public void clearSpan() { - getText().removeSpan(this); - mAutocompleteText = null; - mUserText = null; + @Override + public void onNoChangeTypingAccessibilityEvent(int selectionStart) { + if (DEBUG) Log.i(TAG, "onNoChangeTypingAccessibilityEvent: " + selectionStart); + // Since the text isn't changing, TalkBack won't read out the typed characters. + // To work around this, explicitly send an accessibility event. crbug.com/416595 + Editable currentText = getText(); + if (mAccessibilityManager != null && mAccessibilityManager.isEnabled()) { + AccessibilityEvent event = + AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); + event.setFromIndex(selectionStart); + event.setRemovedCount(0); + event.setAddedCount(1); + event.setBeforeText(currentText.toString().substring(0, selectionStart)); + sendAccessibilityEventUnchecked(event); } } -} \ No newline at end of file +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModel.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModel.java new file mode 100644 index 0000000..2bbcc5f --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModel.java
@@ -0,0 +1,471 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.omnibox; + +import android.text.Editable; +import android.text.Selection; +import android.text.Spanned; +import android.text.TextUtils; +import android.view.inputmethod.BaseInputConnection; +import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputConnectionWrapper; + +import org.chromium.base.Log; + +/** + * An autocomplete model that appends autocomplete text at the end of query/URL text and selects it. + */ +public class AutocompleteEditTextModel implements AutocompleteEditTextModelBase { + private static final String TAG = "cr_AutocompleteEdit"; + + private static final boolean DEBUG = false; + + private final Delegate mDelegate; + private final AutocompleteSpan mAutocompleteSpan; + + private int mBatchEditNestCount; + private int mBeforeBatchEditAutocompleteIndex = -1; + private String mBeforeBatchEditFullText; + private boolean mSelectionChangedInBatchMode; + private boolean mTextDeletedInBatchMode; + // Set to true when the text is modified programmatically. Initially set to true until the old + // state has been loaded. + private boolean mIgnoreTextChangeFromAutocomplete = true; + + private boolean mLastEditWasDelete; + private boolean mIsPastedText; + + public AutocompleteEditTextModel(AutocompleteEditTextModel.Delegate delegate) { + mDelegate = delegate; + mAutocompleteSpan = new AutocompleteSpan(); + } + + @Override + public void setIgnoreTextChangeFromAutocomplete(boolean ignore) { + if (DEBUG) Log.i(TAG, "setIgnoreTextChangesForAutocomplete: " + ignore); + mIgnoreTextChangeFromAutocomplete = ignore; + } + + @Override + public String getTextWithAutocomplete() { + return mDelegate.getText().toString(); + } + + /** + * @return Whether the current cursor position is at the end of the user typed text (i.e. + * at the beginning of the inline autocomplete text if present otherwise the very + * end of the current text). + */ + private boolean isCursorAtEndOfTypedText() { + final int selectionStart = mDelegate.getSelectionStart(); + final int selectionEnd = mDelegate.getSelectionEnd(); + + int expectedSelectionStart = mDelegate.getText().getSpanStart(mAutocompleteSpan); + int expectedSelectionEnd = mDelegate.getText().length(); + if (expectedSelectionStart < 0) { + expectedSelectionStart = expectedSelectionEnd; + } + + return selectionStart == expectedSelectionStart && selectionEnd == expectedSelectionEnd; + } + + @Override + public String getTextWithoutAutocomplete() { + int autoCompleteIndex = mDelegate.getText().getSpanStart(mAutocompleteSpan); + if (autoCompleteIndex < 0) { + return getTextWithAutocomplete(); + } else { + return getTextWithAutocomplete().substring(0, autoCompleteIndex); + } + } + + @Override + public boolean hasAutocomplete() { + return mDelegate.getText().getSpanStart(mAutocompleteSpan) >= 0 + || mAutocompleteSpan.mAutocompleteText != null + || mAutocompleteSpan.mUserText != null; + } + + @Override + public boolean shouldAutocomplete() { + if (mLastEditWasDelete) return false; + Editable text = mDelegate.getText(); + return isCursorAtEndOfTypedText() && !isPastedText() && mBatchEditNestCount == 0 + && BaseInputConnection.getComposingSpanEnd(text) + == BaseInputConnection.getComposingSpanStart(text); + } + + private void onPostEndBatchEdit() { + if (mSelectionChangedInBatchMode) { + validateSelection(mDelegate.getSelectionStart(), mDelegate.getSelectionEnd()); + mSelectionChangedInBatchMode = false; + } + + String newText = mDelegate.getText().toString(); + if (!TextUtils.equals(mBeforeBatchEditFullText, newText) + || mDelegate.getText().getSpanStart(mAutocompleteSpan) + != mBeforeBatchEditAutocompleteIndex) { + // If the text being typed is a single character that matches the next character in the + // previously visible autocomplete text, we reapply the autocomplete text to prevent + // a visual flickering when the autocomplete text is cleared and then quickly reapplied + // when the next round of suggestions is received. + if (shouldAutocomplete() && mBeforeBatchEditAutocompleteIndex != -1 + && mBeforeBatchEditFullText != null + && mBeforeBatchEditFullText.startsWith(newText) && !mTextDeletedInBatchMode + && newText.length() - mBeforeBatchEditAutocompleteIndex == 1) { + setAutocompleteText(newText, mBeforeBatchEditFullText.substring(newText.length())); + } + notifyAutocompleteTextStateChanged(mTextDeletedInBatchMode, true); + } + + mTextDeletedInBatchMode = false; + mBeforeBatchEditAutocompleteIndex = -1; + mBeforeBatchEditFullText = null; + } + + @Override + public void onSelectionChanged(int selStart, int selEnd) { + if (DEBUG) Log.i(TAG, "onSelectionChanged -- selStart: %d, selEnd: %d", selStart, selEnd); + if (mBatchEditNestCount == 0) { + int beforeTextLength = mDelegate.getText().length(); + if (validateSelection(selStart, selEnd)) { + boolean textDeleted = mDelegate.getText().length() < beforeTextLength; + notifyAutocompleteTextStateChanged(textDeleted, false); + } + } else { + mSelectionChangedInBatchMode = true; + } + } + + /** + * Validates the selection and clears the autocomplete span if needed. The autocomplete text + * will be deleted if the selection occurs entirely before the autocomplete region. + * + * @param selStart The start of the selection. + * @param selEnd The end of the selection. + * @return Whether the autocomplete span was removed as a result of this validation. + */ + private boolean validateSelection(int selStart, int selEnd) { + Editable text = mDelegate.getText(); + int spanStart = text.getSpanStart(mAutocompleteSpan); + int spanEnd = text.getSpanEnd(mAutocompleteSpan); + + if (DEBUG) { + Log.i(TAG, "validateSelection -- selStart: %d, selEnd: %d, spanStart: %d, spanEnd: %d", + selStart, selEnd, spanStart, spanEnd); + } + + if (spanStart >= 0 && (spanStart != selStart || spanEnd != selEnd)) { + CharSequence previousAutocompleteText = mAutocompleteSpan.mAutocompleteText; + + // On selection changes, the autocomplete text has been accepted by the user or needs + // to be deleted below. + mAutocompleteSpan.clearSpan(); + + // The autocomplete text will be deleted any time the selection occurs entirely before + // the start of the autocomplete text. This is required because certain keyboards will + // insert characters temporarily when starting a key entry gesture (whether it be + // swyping a word or long pressing to get a special character). When this temporary + // character appears, Chrome may decide to append some autocomplete, but the keyboard + // will then remove this temporary character only while leaving the autocomplete text + // alone. See crbug/273763 for more details. + if (selEnd <= spanStart + && TextUtils.equals(previousAutocompleteText, + text.subSequence(spanStart, text.length()))) { + text.delete(spanStart, text.length()); + } + return true; + } + return false; + } + + @Override + public void onFocusChanged(boolean focused) { + if (!focused) mAutocompleteSpan.clearSpan(); + } + + @Override + public void setAutocompleteText(CharSequence userText, CharSequence inlineAutocompleteText) { + if (DEBUG) { + Log.i(TAG, "setAutocompleteText -- userText: %s, inlineAutocompleteText: %s", userText, + inlineAutocompleteText); + } + + int autocompleteIndex = userText.length(); + String previousText = getTextWithAutocomplete(); + CharSequence newText = TextUtils.concat(userText, inlineAutocompleteText); + + setIgnoreTextChangeFromAutocomplete(true); + + if (!TextUtils.equals(previousText, newText)) { + // The previous text may also have included autocomplete text, so we only + // append the new autocomplete text that has changed. + if (TextUtils.indexOf(newText, previousText) == 0) { + mDelegate.append(newText.subSequence(previousText.length(), newText.length())); + } else { + mDelegate.replaceAllTextFromAutocomplete(newText.toString()); + } + } + + if (mDelegate.getSelectionStart() != autocompleteIndex + || mDelegate.getSelectionEnd() != mDelegate.getText().length()) { + mDelegate.setSelection(autocompleteIndex, mDelegate.getText().length()); + + if (inlineAutocompleteText.length() != 0) { + // Sending a TYPE_VIEW_TEXT_SELECTION_CHANGED accessibility event causes the + // previous TYPE_VIEW_TEXT_CHANGED event to be swallowed. As a result the user + // hears the autocomplete text but *not* the text they typed. Instead we send a + // TYPE_ANNOUNCEMENT event, which doesn't swallow the text-changed event. + mDelegate.announceForAccessibility(inlineAutocompleteText); + } + } + + boolean emptyAutocomplete = TextUtils.isEmpty(inlineAutocompleteText); + if (emptyAutocomplete) { + mAutocompleteSpan.clearSpan(); + } else { + mAutocompleteSpan.setSpan(userText, inlineAutocompleteText); + } + + setIgnoreTextChangeFromAutocomplete(false); + if (DEBUG) Log.i(TAG, "setAutocompleteText finished"); + } + + @Override + public String getAutocompleteText() { + if (!hasAutocomplete()) return ""; + return mAutocompleteSpan.mAutocompleteText.toString(); + } + + @Override + public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { + if (DEBUG) { + Log.i(TAG, "onTextChanged: [%s], start: %d, bef: %d, aft: %d", text, start, + lengthBefore, lengthAfter); + } + boolean textDeleted = lengthAfter == 0; + if (mBatchEditNestCount == 0) { + notifyAutocompleteTextStateChanged(textDeleted, true); + } else { + mTextDeletedInBatchMode = textDeleted; + } + mIsPastedText = false; + } + + @Override + public void onSetText(CharSequence text) { + if (DEBUG) Log.i(TAG, "onSetText: [%s]", text); + // Verify the autocomplete is still valid after the text change. + if (mAutocompleteSpan.mUserText != null && mAutocompleteSpan.mAutocompleteText != null) { + if (mDelegate.getText().getSpanStart(mAutocompleteSpan) < 0) { + mAutocompleteSpan.clearSpan(); + } else { + clearAutocompleteSpanIfInvalid(); + } + } + } + + private void clearAutocompleteSpanIfInvalid() { + Editable editableText = mDelegate.getEditableText(); + CharSequence previousUserText = mAutocompleteSpan.mUserText; + CharSequence previousAutocompleteText = mAutocompleteSpan.mAutocompleteText; + if (editableText.length() + != (previousUserText.length() + previousAutocompleteText.length())) { + mAutocompleteSpan.clearSpan(); + } else if (TextUtils.indexOf(mDelegate.getText(), previousUserText) != 0 + || TextUtils.indexOf( + mDelegate.getText(), previousAutocompleteText, previousUserText.length()) + != 0) { + mAutocompleteSpan.clearSpan(); + } + } + + @Override + public InputConnection getInputConnection() { + return mInputConnection; + } + + private final InputConnectionWrapper mInputConnection = new InputConnectionWrapper(null, true) { + private final char[] mTempSelectionChar = new char[1]; + + @Override + public boolean beginBatchEdit() { + ++mBatchEditNestCount; + if (mBatchEditNestCount == 1) { + if (DEBUG) Log.i(TAG, "beginBatchEdit"); + mBeforeBatchEditAutocompleteIndex = + mDelegate.getText().getSpanStart(mAutocompleteSpan); + mBeforeBatchEditFullText = mDelegate.getText().toString(); + boolean retVal = super.beginBatchEdit(); + mTextDeletedInBatchMode = false; + return retVal; + } + return super.beginBatchEdit(); + } + + @Override + public boolean endBatchEdit() { + mBatchEditNestCount = Math.max(mBatchEditNestCount - 1, 0); + if (mBatchEditNestCount == 0) { + if (DEBUG) Log.i(TAG, "endBatchEdit"); + boolean retVal = super.endBatchEdit(); + onPostEndBatchEdit(); + return retVal; + } + return super.endBatchEdit(); + } + + @Override + public boolean commitText(CharSequence text, int newCursorPosition) { + if (DEBUG) Log.i(TAG, "commitText: [%s]", text); + Editable currentText = mDelegate.getText(); + if (currentText == null) return super.commitText(text, newCursorPosition); + + int selectionStart = Selection.getSelectionStart(currentText); + int selectionEnd = Selection.getSelectionEnd(currentText); + int autocompleteIndex = currentText.getSpanStart(mAutocompleteSpan); + // If the text being committed is a single character that matches the next character + // in the selection (assumed to be the autocomplete text), we only move the text + // selection instead clearing the autocomplete text causing flickering as the + // autocomplete text will appear once the next suggestions are received. + // + // To be confident that the selection is an autocomplete, we ensure the selection + // is at least one character and the end of the selection is the end of the + // currently entered text. + if (newCursorPosition == 1 && selectionStart > 0 && selectionStart != selectionEnd + && selectionEnd >= currentText.length() && autocompleteIndex == selectionStart + && text.length() == 1) { + currentText.getChars(selectionStart, selectionStart + 1, mTempSelectionChar, 0); + if (mTempSelectionChar[0] == text.charAt(0)) { + mDelegate.onNoChangeTypingAccessibilityEvent(selectionStart); + + setAutocompleteText(currentText.subSequence(0, selectionStart + 1), + currentText.subSequence(selectionStart + 1, selectionEnd)); + if (mBatchEditNestCount == 0) { + notifyAutocompleteTextStateChanged(false, false); + } + return true; + } + } + + boolean retVal = super.commitText(text, newCursorPosition); + + // Ensure the autocomplete span is removed if it is no longer valid after committing + // the text. + if (currentText.getSpanStart(mAutocompleteSpan) >= 0) { + clearAutocompleteSpanIfInvalid(); + } + + return retVal; + } + + @Override + public boolean setComposingText(CharSequence text, int newCursorPosition) { + if (DEBUG) Log.i(TAG, "setComposingText: [%s]", text); + Editable currentText = mDelegate.getText(); + int autoCompleteSpanStart = currentText.getSpanStart(mAutocompleteSpan); + if (autoCompleteSpanStart >= 0) { + int composingEnd = BaseInputConnection.getComposingSpanEnd(currentText); + + // On certain device/keyboard combinations, the composing regions are specified + // with a noticeable delay after the initial character is typed, and in certain + // circumstances it does not check that the current state of the text matches + // the expectations of it's composing region. For example, you can be typing: + // chrome://f + // Chrome will autocomplete to: + // chrome://f[lags] + // And after the autocomplete has been set, the keyboard will set the composing + // region to the last character and it assumes it is 'f' as it was the last + // character the keyboard sent. If we commit this composition, the text will + // look like: + // chrome://flag[f] + // And if we use the autocomplete clearing logic below, it will look like: + // chrome://f[f] + // To work around this, we see if the composition matches all the characters + // prior to the autocomplete and just readjust the composing region to be that + // subset. + // + // See crbug.com/366732 + if (composingEnd == currentText.length() + && autoCompleteSpanStart >= text.length()) { + CharSequence trailingText = currentText.subSequence( + autoCompleteSpanStart - text.length(), autoCompleteSpanStart); + if (TextUtils.equals(trailingText, text)) { + setComposingRegion( + autoCompleteSpanStart - text.length(), autoCompleteSpanStart); + } + } + + // Once composing text is being modified, the autocomplete text has been + // accepted or has to be deleted. + mAutocompleteSpan.clearSpan(); + Selection.setSelection(currentText, autoCompleteSpanStart); + currentText.delete(autoCompleteSpanStart, currentText.length()); + } + return super.setComposingText(text, newCursorPosition); + } + }; + + @Override + public InputConnection onCreateInputConnection(InputConnection superInputConnection) { + if (DEBUG) Log.i(TAG, "onCreateInputConnection"); + mInputConnection.setTarget(superInputConnection); + return mInputConnection; + } + + private void notifyAutocompleteTextStateChanged(boolean textDeleted, boolean updateDisplay) { + if (DEBUG) { + Log.i(TAG, "notifyAutocompleteTextStateChanged: DEL[%b] DIS[%b] IGN[%b]", textDeleted, + updateDisplay, mIgnoreTextChangeFromAutocomplete); + } + if (mIgnoreTextChangeFromAutocomplete) return; + mLastEditWasDelete = textDeleted; + mDelegate.onAutocompleteTextStateChanged(textDeleted, updateDisplay); + } + + @Override + public boolean shouldIgnoreTextChangeFromAutocomplete() { + return mIgnoreTextChangeFromAutocomplete; + } + + @Override + public void onPaste() { + if (DEBUG) Log.i(TAG, "onPaste"); + mIsPastedText = true; + } + + @Override + public boolean isPastedText() { + return mIsPastedText; + } + + /** + * Simple span used for tracking the current autocomplete state. + */ + private class AutocompleteSpan { + private CharSequence mUserText; + private CharSequence mAutocompleteText; + + /** + * Adds the span to the current text. + * @param userText The user entered text. + * @param autocompleteText The autocomplete text being appended. + */ + public void setSpan(CharSequence userText, CharSequence autocompleteText) { + Editable text = mDelegate.getText(); + text.removeSpan(this); + mAutocompleteText = autocompleteText; + mUserText = userText; + text.setSpan(this, userText.length(), text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + + /** Removes this span from the current text and clears the internal state. */ + public void clearSpan() { + mDelegate.getText().removeSpan(this); + mAutocompleteText = null; + mUserText = null; + } + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModelBase.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModelBase.java new file mode 100644 index 0000000..acc4024e --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModelBase.java
@@ -0,0 +1,148 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.omnibox; + +import android.text.Editable; +import android.view.inputmethod.InputConnection; +import android.widget.EditText; +import android.widget.TextView; + +import org.chromium.base.VisibleForTesting; + +/** + * An abstraction of the text model to show, keep track of, and update autocomplete. + */ +public interface AutocompleteEditTextModelBase { + /** + * An embedder should implement this. + */ + public interface Delegate { + /** @see TextView#getText() */ + Editable getText(); + /** @see TextView#getEditableText() */ + Editable getEditableText(); + /** @see TextView#append(CharSequence) */ + void append(CharSequence subSequence); + /** @see TextView#getSelectionStart() */ + int getSelectionStart(); + /** @see TextView#getSelectionEnd() */ + int getSelectionEnd(); + /** @see EditText#setSelection(int, int) */ + void setSelection(int autocompleteIndex, int length); + /** @see TextView#announceForAccessibility(CharSequence) */ + void announceForAccessibility(CharSequence inlineAutocompleteText); + + /** + * This is called when autocomplete replaces the whole text. + * @param text The text. + */ + void replaceAllTextFromAutocomplete(String text); + + /** + * This is called when there is a typing accessibility event that actually causes no change. + * @param selectionStart The selection start. + */ + void onNoChangeTypingAccessibilityEvent(int selectionStart); + + /** + * This is called when autocomplete text state changes. + * @param textDeleted True if text is just deleted. + * @param updateDisplay True if string is changed. + */ + void onAutocompleteTextStateChanged(boolean textDeleted, boolean updateDisplay); + } + + /** + * Called when creating an input connection. + * @param inputConnection An {@link InputConnection} created by EditText. + * @return A wrapper @{link InputConnection} created by the model. + */ + InputConnection onCreateInputConnection(InputConnection inputConnection); + + /** + * Called when TextView#setText(CharSequence, BufferType) is called. + * @param text The new text. + */ + void onSetText(CharSequence text); + + /** + * Called when TextView#onSelectionChanged(int, int) is called. + * @param selStart The selection start. + * @param selEnd The selection end. + */ + void onSelectionChanged(int selStart, int selEnd); + + /** + * Called when View#onFocusChanged(boolean, int, Rect) is called. + * @param focused True if the View has focus; false otherwise. + */ + void onFocusChanged(boolean focused); + + /** + * Called when TextView#onTextChanged(CharSequence, int, int, int) is called. + * @param text The text the TextView is displaying. + * @param start The offset of the start of the range of the text that was modified. + * @param beforeLength The length of the former text that has been replaced. + * @param afterLength The length of the replacement modified text. + */ + void onTextChanged(CharSequence text, int start, int beforeLength, int afterLength); + + /** Called when text gets pasted. */ + void onPaste(); + + /** + * @return Whether or not the user just pasted text. + */ + boolean isPastedText(); + + /** + * @return The whole text including both user text and autocomplete text. + */ + String getTextWithAutocomplete(); + + /** + * @return The user text without the autocomplete text. + */ + String getTextWithoutAutocomplete(); + + /** + * Returns the length of the autocomplete text currently displayed, zero if none is + * currently displayed. + */ + String getAutocompleteText(); + + /** + * Sets whether text changes should trigger autocomplete. + * @param ignore Whether text changes should be ignored and no auto complete. + */ + void setIgnoreTextChangeFromAutocomplete(boolean ignore); + + /** @return Whether we should ignore text change from autocomplete. */ + boolean shouldIgnoreTextChangeFromAutocomplete(); + + /** + * Autocompletes the text and selects the text that was not entered by the user. Using append() + * instead of setText() to preserve the soft-keyboard layout. + * @param userText user The text entered by the user. + * @param inlineAutocompleteText The suggested autocompletion for the user's text. + */ + void setAutocompleteText(CharSequence userText, CharSequence inlineAutocompleteText); + + /** + * Whether we want to be showing inline autocomplete results. We don't want to show them as the + * user deletes input. Also if there is a composition (e.g. while using the Japanese IME), + * we must not autocomplete or we'll destroy the composition. + * @return Whether we want to be showing inline autocomplete results. + */ + boolean shouldAutocomplete(); + + /** @return Whether any autocomplete information is specified on the current text. */ + @VisibleForTesting + boolean hasAutocomplete(); + + /** @return The current {@link InputConnection} object. */ + @VisibleForTesting + InputConnection getInputConnection(); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java index 7d8be3d3..04daa63 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
@@ -114,8 +114,6 @@ private long mFirstFocusTimeMs; - private boolean mIsPastedText; - // Used as a hint to indicate the text may contain an ellipsize span. This will be true if an // ellispize span was applied the last time the text changed. A true value here does not // guarantee that the text does contain the span currently as newly set text may have cleared @@ -287,12 +285,6 @@ return super.onKeyPreIme(keyCode, event); } - @Override - public boolean shouldAutocomplete() { - if (isPastedText()) return false; - return super.shouldAutocomplete(); - } - /** * See {@link AutocompleteEditText#setIgnoreTextChangesForAutocomplete(boolean)}. * <p> @@ -538,7 +530,7 @@ Selection.setSelection(getText(), max); getText().replace(min, max, pasteString); - mIsPastedText = true; + onPaste(); return true; } } @@ -665,12 +657,6 @@ } @Override - protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { - super.onTextChanged(text, start, lengthBefore, lengthAfter); - mIsPastedText = false; - } - - @Override public void setText(CharSequence text, BufferType type) { if (DEBUG) Log.i(TAG, "setText -- text: %s", text); super.setText(text, type); @@ -780,13 +766,6 @@ OmniboxUrlEmphasizer.deEmphasizeUrl(getText()); } - /** - * @return Whether the current UrlBar input has been pasted from the clipboard. - */ - public boolean isPastedText() { - return mIsPastedText; - } - @Override public CharSequence getAccessibilityClassName() { // When UrlBar is used as a read-only TextView, force Talkback to pronounce it like @@ -799,12 +778,17 @@ } @Override - protected void replaceAllTextFromAutocomplete(String text) { + public void replaceAllTextFromAutocomplete(String text) { + if (DEBUG) Log.i(TAG, "replaceAllTextFromAutocomplete: " + text); setUrl(text, null); } @Override public void onAutocompleteTextStateChanged(boolean textDeleted, boolean updateDisplay) { + if (DEBUG) { + Log.i(TAG, "onAutocompleteTextStateChanged: DEL[%b], DIS[%b]", textDeleted, + updateDisplay); + } if (mUrlBarDelegate == null) return; if (updateDisplay) limitDisplayableLength();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java index fa894a6..3735ad3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java
@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.preferences.password.SavePasswordsPreferences; import org.chromium.chrome.browser.search_engines.TemplateUrlService; import org.chromium.chrome.browser.search_engines.TemplateUrlService.LoadListener; +import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; import org.chromium.chrome.browser.signin.SigninManager; import org.chromium.chrome.browser.signin.SigninManager.SignInStateObserver; import org.chromium.chrome.browser.sync.ProfileSyncService; @@ -161,10 +162,14 @@ private void updateSummary() { ChromeBasePreference searchEnginePref = (ChromeBasePreference) findPreference(PREF_SEARCH_ENGINE); + searchEnginePref.setManagedPreferenceDelegate(mManagedPreferenceDelegate); searchEnginePref.setEnabled(true); - searchEnginePref.setSummary(TemplateUrlService.getInstance() - .getDefaultSearchEngineTemplateUrl() - .getShortName()); + + String defaultSearchEngineName = null; + TemplateUrl dseTemplateUrl = + TemplateUrlService.getInstance().getDefaultSearchEngineTemplateUrl(); + if (dseTemplateUrl != null) defaultSearchEngineName = dseTemplateUrl.getShortName(); + searchEnginePref.setSummary(defaultSearchEngineName); } private void setOnOffSummary(Preference pref, boolean isOn) { @@ -215,6 +220,9 @@ if (PREF_DATA_REDUCTION.equals(preference.getKey())) { return DataReductionProxySettings.getInstance().isDataReductionProxyManaged(); } + if (PREF_SEARCH_ENGINE.equals(preference.getKey())) { + return TemplateUrlService.getInstance().isDefaultSearchManaged(); + } return false; } @@ -234,6 +242,9 @@ return settings.isDataReductionProxyManaged() && !settings.isDataReductionProxyEnabled(); } + if (PREF_SEARCH_ENGINE.equals(preference.getKey())) { + return TemplateUrlService.getInstance().isDefaultSearchManaged(); + } return super.isPreferenceClickDisabledByPolicy(preference); } };
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java index 0678a0f8..a3e338a7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
@@ -18,6 +18,8 @@ import java.util.List; import java.util.Locale; +import javax.annotation.Nullable; + /** * Android wrapper of the TemplateUrlService which provides access from the Java * layer. @@ -250,9 +252,10 @@ } /** - * @return {@link TemplateUrlService.TemplateUrl} for the default search engine. + * @return {@link TemplateUrlService.TemplateUrl} for the default search engine. This can + * be null if DSEs are disabled entirely by administrators. */ - public TemplateUrl getDefaultSearchEngineTemplateUrl() { + public @Nullable TemplateUrl getDefaultSearchEngineTemplateUrl() { if (!isLoaded()) return null; int defaultSearchEngineIndex = getDefaultSearchEngineIndex(); @@ -271,8 +274,12 @@ mNativeTemplateUrlServiceAndroid, selectedKeyword); } - public boolean isSearchProviderManaged() { - return nativeIsSearchProviderManaged(mNativeTemplateUrlServiceAndroid); + /** + * @return Whether the default search engine is managed and controlled by policy. If true, the + * DSE can not be modified by the user. + */ + public boolean isDefaultSearchManaged() { + return nativeIsDefaultSearchManaged(mNativeTemplateUrlServiceAndroid); } /** @@ -431,7 +438,7 @@ private native void nativeSetUserSelectedDefaultSearchProvider( long nativeTemplateUrlServiceAndroid, String selectedKeyword); private native int nativeGetDefaultSearchProviderIndex(long nativeTemplateUrlServiceAndroid); - private native boolean nativeIsSearchProviderManaged(long nativeTemplateUrlServiceAndroid); + private native boolean nativeIsDefaultSearchManaged(long nativeTemplateUrlServiceAndroid); private native boolean nativeIsSearchResultsPageFromDefaultSearchProvider( long nativeTemplateUrlServiceAndroid, String url); private native boolean nativeIsSearchByImageAvailable(long nativeTemplateUrlServiceAndroid);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java index 427aba5..2e410a19 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java
@@ -32,6 +32,7 @@ import org.chromium.chrome.browser.omnibox.LocationBarLayout; import org.chromium.chrome.browser.search_engines.TemplateUrlService; import org.chromium.chrome.browser.search_engines.TemplateUrlService.LoadListener; +import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrlServiceObserver; import org.chromium.chrome.browser.util.IntentUtils; @@ -303,12 +304,17 @@ if (!service.isLoaded()) return; // Update the URL that we show for zero-suggest. - String searchEngineUrl = service.getSearchEngineUrlFromTemplateUrl( - service.getDefaultSearchEngineTemplateUrl().getKeyword()); - sDefaultSearchEngineUrl = - LocationBarLayout.splitPathFromUrlDisplayText(searchEngineUrl).first; + TemplateUrl dseTemplateUrl = service.getDefaultSearchEngineTemplateUrl(); + String engineName = null; + if (dseTemplateUrl != null) { + String searchEngineUrl = + service.getSearchEngineUrlFromTemplateUrl(dseTemplateUrl.getKeyword()); + sDefaultSearchEngineUrl = + LocationBarLayout.splitPathFromUrlDisplayText(searchEngineUrl).first; + engineName = dseTemplateUrl.getShortName(); + } - updateCachedEngineName(service.getDefaultSearchEngineTemplateUrl().getShortName()); + updateCachedEngineName(engineName); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java index 26e30c3..a64514d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.tab; +import org.chromium.base.ThreadUtils; import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; @@ -24,6 +25,10 @@ * Class that controls navigations and allows to intercept them. It is used on Android to 'convert' * certain navigations to Intents to 3rd party applications and to "pause" navigations when data use * tracking has ended. + * Note the Intent is often created together with a new empty tab which then shoud be closed + * immediately. This task of closing tab should be done in an asynchrnous fashion by posting + * the task onto UI thread again to avoid accessing the WebContents and the associated objects + * afterwards since they will have been destroyed as well. see https://crbug.com/732260. */ public class InterceptNavigationDelegateImpl implements InterceptNavigationDelegate { private final Tab mTab; @@ -243,7 +248,14 @@ // crbug.com/487938. mTab.getActivity().moveTaskToBack(false); } - mTab.getTabModelSelector().closeTab(mTab); + // Defer closing a tab (and the associated WebContents) till the navigation + // request and the throttle finishes the job with it. + ThreadUtils.postOnUiThread(new Runnable() { + @Override + public void run() { + mTab.getTabModelSelector().closeTab(mTab); + } + }); } else if (mTab.getTabRedirectHandler().isOnNavigation()) { int lastCommittedEntryIndexBeforeNavigation = mTab.getTabRedirectHandler() .getLastCommittedEntryIndexBeforeStartingNavigation();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java index c011fcd..6d995d7c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java
@@ -140,6 +140,13 @@ intent.setComponent(componentName); } + addAsyncTabExtras(asyncParams, parentId, isChromeUI, assignedTabId, intent); + + return intent; + } + + protected final void addAsyncTabExtras(AsyncTabCreationParams asyncParams, int parentId, + boolean isChromeUI, int assignedTabId, Intent intent) { Map<String, String> extraHeaders = asyncParams.getLoadUrlParams().getExtraHeaders(); if (extraHeaders != null && !extraHeaders.isEmpty()) { Bundle bundle = new Bundle(); @@ -171,7 +178,6 @@ } intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - return intent; } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java index 3067695..3d20118 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
@@ -267,6 +267,19 @@ } finally { StrictMode.setThreadPolicy(oldPolicy); } + + // If the browser has been initialized by this point, check the experiment as well to + // avoid the restart logic in cacheChromeHomeEnabled. + if (ChromeFeatureList.isInitialized()) { + boolean chromeHomeExperimentEnabled = + ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_HOME); + + if (chromeHomeExperimentEnabled != sChromeHomeEnabled) { + sChromeHomeEnabled = chromeHomeExperimentEnabled; + ChromePreferenceManager.getInstance().setChromeHomeEnabled( + chromeHomeExperimentEnabled); + } + } } return sChromeHomeEnabled;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java index 470a58d..1632c42 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
@@ -13,6 +13,7 @@ import org.chromium.base.ActivityState; import org.chromium.base.ApplicationStatus; +import org.chromium.base.Callback; import org.chromium.base.CommandLine; import org.chromium.base.ContextUtils; import org.chromium.base.Log; @@ -64,19 +65,20 @@ */ private static class PendingUpdate { public WebApkInfo mUpdateInfo; - public String mPrimaryIconUrl; - public String mBadgeIconUrl; - public boolean mIsManifestStale; + byte[] mSerializedProto; - public PendingUpdate(WebApkInfo info, String primaryIconUrl, String badgeIconUrl, - boolean isManifestStale) { + public PendingUpdate(WebApkInfo info, byte[] serializedProto) { mUpdateInfo = info; - mPrimaryIconUrl = primaryIconUrl; - mBadgeIconUrl = badgeIconUrl; - mIsManifestStale = isManifestStale; + mSerializedProto = serializedProto; } } + /** Called with update result. */ + private static interface WebApkUpdateCallback { + @CalledByNative("WebApkUpdateCallback") + public void onResultFromNative(@WebApkInstallResult int result, boolean relaxUpdates); + } + public WebApkUpdateManager(WebApkActivity activity, WebappDataStorage storage) { mActivity = activity; mStorage = storage; @@ -103,8 +105,7 @@ */ public boolean requestPendingUpdate() { if (mPendingUpdate != null) { - updateAsync(mPendingUpdate.mUpdateInfo, mPendingUpdate.mPrimaryIconUrl, - mPendingUpdate.mBadgeIconUrl, mPendingUpdate.mIsManifestStale); + updateAsync(mPendingUpdate.mUpdateInfo, mPendingUpdate.mSerializedProto); return true; } return false; @@ -156,25 +157,26 @@ if (!needsUpgrade) { if (!mStorage.didPreviousUpdateSucceed()) { - recordUpdate(mStorage, WebApkInstallResult.SUCCESS, false /* relaxUpdates */); + recordUpdate(WebApkInstallResult.SUCCESS, false /* relaxUpdates */); } return; } // Set WebAPK update as having failed in case that Chrome is killed prior to // {@link onBuiltWebApk} being called. - recordUpdate(mStorage, WebApkInstallResult.FAILURE, false /* relaxUpdates*/); + recordUpdate(WebApkInstallResult.FAILURE, false /* relaxUpdates*/); if (fetchedInfo != null) { - scheduleUpdate(fetchedInfo, primaryIconUrl, badgeIconUrl, false /* isManifestStale */); + buildProtoAndScheduleUpdate( + fetchedInfo, primaryIconUrl, badgeIconUrl, false /* isManifestStale */); return; } // Tell the server that the our version of the Web Manifest might be stale and to ignore // our Web Manifest data if the server's Web Manifest data is newer. This scenario can // occur if the Web Manifest is temporarily unreachable. - scheduleUpdate(mInfo, "" /* primaryIconUrl */, "" /* badgeIconUrl */, - true /* isManifestStale */); + buildProtoAndScheduleUpdate( + mInfo, "" /* primaryIconUrl */, "" /* badgeIconUrl */, true /* isManifestStale */); } /** @@ -184,16 +186,43 @@ return new WebApkUpdateDataFetcher(); } + /** Builds proto to send to the WebAPK server. */ + protected void buildProtoAndScheduleUpdate(final WebApkInfo info, String primaryIconUrl, + String badgeIconUrl, boolean isManifestStale) { + int versionCode = readVersionCodeFromAndroidManifest(info.webApkPackageName()); + int size = info.iconUrlToMurmur2HashMap().size(); + String[] iconUrls = new String[size]; + String[] iconHashes = new String[size]; + int i = 0; + for (Map.Entry<String, String> entry : info.iconUrlToMurmur2HashMap().entrySet()) { + iconUrls[i] = entry.getKey(); + String iconHash = entry.getValue(); + iconHashes[i] = (iconHash != null) ? iconHash : ""; + i++; + } + + Callback<byte[]> callback = new Callback<byte[]>() { + @Override + public void onResult(byte[] result) { + scheduleUpdate(info, result); + } + }; + nativeBuildUpdateWebApkProto(info.manifestStartUrl(), info.scopeUri().toString(), + info.name(), info.shortName(), primaryIconUrl, info.icon(), badgeIconUrl, + info.badgeIcon(), iconUrls, iconHashes, info.displayMode(), info.orientation(), + info.themeColor(), info.backgroundColor(), info.manifestUrl(), + info.webApkPackageName(), versionCode, isManifestStale, callback); + } + /** * Sends update request to WebAPK Server if the WebAPK is running in the background; caches the * fetched WebApkInfo otherwise. */ - protected void scheduleUpdate(WebApkInfo info, String primaryIconUrl, String badgeIconUrl, - boolean isManifestStale) { + protected void scheduleUpdate(WebApkInfo info, byte[] serializedProto) { int numberOfUpdateRequests = mStorage.getUpdateRequests(); boolean forceUpdateNow = numberOfUpdateRequests >= MAX_UPDATE_ATTEMPTS; if (!isInForeground() || forceUpdateNow) { - updateAsync(info, primaryIconUrl, badgeIconUrl, isManifestStale); + updateAsync(info, serializedProto); WebApkUma.recordUpdateRequestSent(WebApkUma.UPDATE_REQUEST_SENT_FIRST_TRY); return; } @@ -202,7 +231,7 @@ // The {@link numberOfUpdateRequests} can never exceed 2 here (otherwise we'll have taken // the branch above and have returned before reaching this statement). WebApkUma.recordUpdateRequestQueued(numberOfUpdateRequests); - mPendingUpdate = new PendingUpdate(info, primaryIconUrl, badgeIconUrl, isManifestStale); + mPendingUpdate = new PendingUpdate(info, serializedProto); } /** Returns whether the associated WebApkActivity is running in foreground. */ @@ -214,9 +243,8 @@ /** * Sends update request to the WebAPK Server and cleanup. */ - private void updateAsync(WebApkInfo info, String primaryIconUrl, String badgeIconUrl, - boolean isManifestStale) { - updateAsyncImpl(info, primaryIconUrl, badgeIconUrl, isManifestStale); + private void updateAsync(WebApkInfo info, byte[] serializedProto) { + updateAsyncImpl(info, serializedProto); mStorage.resetUpdateRequests(); mPendingUpdate = null; } @@ -224,28 +252,21 @@ /** * Sends update request to the WebAPK Server. */ - protected void updateAsyncImpl(WebApkInfo info, String primaryIconUrl, String badgeIconUrl, - boolean isManifestStale) { - if (info == null) { + protected void updateAsyncImpl(WebApkInfo info, byte[] serializedProto) { + if (info == null || serializedProto == null) { return; } - int versionCode = readVersionCodeFromAndroidManifest(info.webApkPackageName()); - int size = info.iconUrlToMurmur2HashMap().size(); - String[] iconUrls = new String[size]; - String[] iconHashes = new String[size]; - int i = 0; - for (Map.Entry<String, String> entry : info.iconUrlToMurmur2HashMap().entrySet()) { - iconUrls[i] = entry.getKey(); - String iconHash = entry.getValue(); - iconHashes[i] = iconHash != null ? iconHash : ""; - i++; - } - nativeUpdateAsync(info.id(), info.manifestStartUrl(), info.scopeUri().toString(), - info.name(), info.shortName(), primaryIconUrl, info.icon(), badgeIconUrl, - info.badgeIcon(), iconUrls, iconHashes, info.displayMode(), info.orientation(), - info.themeColor(), info.backgroundColor(), info.manifestUrl(), - info.webApkPackageName(), versionCode, isManifestStale); + WebApkUpdateCallback callback = new WebApkUpdateCallback() { + @Override + public void onResultFromNative(@WebApkInstallResult int result, boolean relaxUpdates) { + recordUpdate(result, relaxUpdates); + mStorage.updateLastRequestedShellApkVersion( + WebApkVersion.CURRENT_SHELL_APK_VERSION); + } + }; + nativeUpdateWebApk(info.webApkPackageName(), info.manifestStartUrl(), info.shortName(), + serializedProto, callback); } /** @@ -313,13 +334,12 @@ * Updates {@link WebappDataStorage} with the time of the latest WebAPK update and whether the * WebAPK update succeeded. */ - private static void recordUpdate( - WebappDataStorage storage, @WebApkInstallResult int result, boolean relaxUpdates) { + private void recordUpdate(@WebApkInstallResult int result, boolean relaxUpdates) { // Update the request time and result together. It prevents getting a correct request time // but a result from the previous request. - storage.updateTimeOfLastWebApkUpdateRequestCompletion(); - storage.updateDidLastWebApkUpdateRequestSucceed(result == WebApkInstallResult.SUCCESS); - storage.setRelaxedUpdates(relaxUpdates); + mStorage.updateTimeOfLastWebApkUpdateRequestCompletion(); + mStorage.updateDidLastWebApkUpdateRequestSucceed(result == WebApkInstallResult.SUCCESS); + mStorage.setRelaxedUpdates(relaxUpdates); } /** @@ -379,23 +399,12 @@ return UrlUtilities.urlsMatchIgnoringFragments(url1, url2); } - /** - * Called after either a request to update the WebAPK has been sent or the update process - * fails. - */ - @CalledByNative - private static void onBuiltWebApk( - String id, @WebApkInstallResult int result, boolean relaxUpdates) { - WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorage(id); - if (storage == null) return; - - recordUpdate(storage, result, relaxUpdates); - storage.updateLastRequestedShellApkVersion(WebApkVersion.CURRENT_SHELL_APK_VERSION); - } - - private static native void nativeUpdateAsync(String id, String startUrl, String scope, + private static native void nativeBuildUpdateWebApkProto(String startUrl, String scope, String name, String shortName, String primaryIconUrl, Bitmap primaryIcon, String badgeIconUrl, Bitmap badgeIcon, String[] iconUrls, String[] iconHashes, int displayMode, int orientation, long themeColor, long backgroundColor, - String manifestUrl, String webApkPackage, int webApkVersion, boolean isManifestStale); + String manifestUrl, String webApkPackage, int webApkVersion, boolean isManifestStale, + Callback<byte[]> callback); + private static native void nativeUpdateWebApk(String webApkPackage, String startUrl, + String shortName, byte[] serializedProto, WebApkUpdateCallback callback); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index 5ca8630..a98fb2e4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -39,6 +39,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabDelegateFactory; import org.chromium.chrome.browser.tab.TabObserver; +import org.chromium.chrome.browser.tabmodel.document.TabDelegate; import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.chrome.browser.util.UrlUtilities; import org.chromium.content.browser.ScreenOrientationProvider; @@ -714,6 +715,11 @@ return new WebappDelegateFactory(this); } + @Override + protected TabDelegate createTabDelegate(boolean incognito) { + return new WebappTabDelegate(this, incognito); + } + // We're temporarily disable CS on webapp since there are some issues. (http://crbug.com/471950) // TODO(changwan): re-enable it once the issues are resolved. @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappTabDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappTabDelegate.java new file mode 100644 index 0000000..e3e1e9e9 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappTabDelegate.java
@@ -0,0 +1,42 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +package org.chromium.chrome.browser.webapps; + +import android.net.Uri; +import android.support.customtabs.CustomTabsIntent; + +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabIdManager; +import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager; +import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; +import org.chromium.chrome.browser.tabmodel.document.AsyncTabCreationParams; +import org.chromium.chrome.browser.tabmodel.document.TabDelegate; + +/** + * Asynchronously creates Tabs for navigation originating from an installed PWA. + * + * This is the same as the parent class with exception of opening a Custom Tab for + * {@code _blank} links and {@code window.open(url)} calls instead of creating a new tab in Chrome. + */ +public class WebappTabDelegate extends TabDelegate { + private final WebappActivity mActivity; + + public WebappTabDelegate(WebappActivity activity, boolean incognito) { + super(incognito); + this.mActivity = activity; + } + + @Override + public void createNewTab(AsyncTabCreationParams asyncParams, TabLaunchType type, int parentId) { + int assignedTabId = TabIdManager.getInstance().generateValidId(Tab.INVALID_TAB_ID); + AsyncTabParamsManager.add(assignedTabId, asyncParams); + + CustomTabsIntent customTabIntent = + new CustomTabsIntent.Builder().setShowTitle(true).build(); + + customTabIntent.intent.setPackage(mActivity.getPackageName()); + addAsyncTabExtras(asyncParams, parentId, true, assignedTabId, customTabIntent.intent); + customTabIntent.launchUrl(mActivity, Uri.parse(asyncParams.getLoadUrlParams().getUrl())); + } +}
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index a61c550..9f958ec 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -713,6 +713,8 @@ "java/src/org/chromium/chrome/browser/omnibox/AnswersImage.java", "java/src/org/chromium/chrome/browser/omnibox/AutocompleteController.java", "java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java", + "java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModel.java", + "java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModelBase.java", "java/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelper.java", "java/src/org/chromium/chrome/browser/omnibox/LocationBar.java", "java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java", @@ -1210,6 +1212,7 @@ "java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java", "java/src/org/chromium/chrome/browser/webapps/WebappManagedActivity.java", "java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java", + "java/src/org/chromium/chrome/browser/webapps/WebappTabDelegate.java", "java/src/org/chromium/chrome/browser/webapps/WebappUrlBar.java", "java/src/org/chromium/chrome/browser/webshare/ShareServiceImpl.java", "java/src/org/chromium/chrome/browser/webshare/ShareServiceImplementationFactory.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ModalDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ModalDialogTest.java index db3903b..12bcd77 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ModalDialogTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ModalDialogTest.java
@@ -186,6 +186,48 @@ Assert.assertEquals("Invalid return value.", '"' + promptText + '"', resultString); } + /** + * Verifies that message content in a dialog is only focusable if the message itself is long + * enough to require scrolling. + */ + @Test + @MediumTest + @Feature({"Browser", "Main"}) + public void testAlertModalDialogMessageFocus() + throws InterruptedException, TimeoutException, ExecutionException { + assertScrollViewFocusabilityInAlertDialog("alert('Short message!');", false); + + assertScrollViewFocusabilityInAlertDialog( + "alert(new Array(200).join('Long message!'));", true); + } + + private void assertScrollViewFocusabilityInAlertDialog( + final String jsAlertScript, final boolean expectedFocusability) + throws InterruptedException, TimeoutException, ExecutionException { + final OnEvaluateJavaScriptResultHelper scriptEvent = + executeJavaScriptAndWaitForDialog(jsAlertScript); + + final JavascriptAppModalDialog jsDialog = getCurrentDialog(); + Assert.assertNotNull("No dialog showing.", jsDialog); + + final String errorMessage = + "Scroll view focusability was incorrect. Expected: " + expectedFocusability; + + CriteriaHelper.pollUiThread(new Criteria(errorMessage) { + @Override + public boolean isSatisfied() { + return jsDialog.getDialogForTest() + .findViewById(R.id.js_modal_dialog_scroll_view) + .isFocusable() + == expectedFocusability; + } + }); + + clickOk(jsDialog); + Assert.assertTrue("JavaScript execution should continue after closing prompt.", + scriptEvent.waitUntilHasValue()); + } + private static class TapGestureStateListener extends GestureStateListener { private CallbackHelper mCallbackHelper = new CallbackHelper();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java index ba24728..e33d26f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
@@ -93,7 +93,7 @@ } @Override - protected void scheduleUpdate(WebApkInfo fetchedInfo, String primaryIconUrl, + protected void buildProtoAndScheduleUpdate(final WebApkInfo info, String primaryIconUrl, String badgeIconUrl, boolean isManifestStale) { mNeedsUpdate = true; }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java index a105310..5845ad5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
@@ -21,7 +21,6 @@ import org.chromium.base.ApplicationStatus; import org.chromium.base.ContextUtils; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; @@ -36,13 +35,9 @@ import org.chromium.chrome.browser.tab.TabIdManager; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.MultiActivityTestRule; -import org.chromium.chrome.test.util.ActivityUtils; import org.chromium.chrome.test.util.ApplicationTestUtils; -import org.chromium.chrome.test.util.browser.TabLoadObserver; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; -import org.chromium.content.browser.test.util.JavaScriptUtils; -import org.chromium.content.browser.test.util.TouchCommon; import org.chromium.content_public.common.ScreenOrientationValues; import org.chromium.net.test.EmbeddedTestServer; @@ -273,77 +268,6 @@ } /** - * Tests that WebappActivities handle window.open() properly in tabbed mode. - */ - @Test - @MediumTest - @Feature({"Webapps"}) - public void testWebappHandlesWindowOpenInTabbedMode() throws Exception { - triggerWindowOpenAndWaitForLoad(ChromeTabbedActivity.class, getOnClickLinkUrl(), true); - } - - /** - * Tests that WebappActivities handle suppressed window.open() properly in tabbed mode. - */ - @Test - @MediumTest - @Feature({"Webapps"}) - public void testWebappHandlesSuppressedWindowOpenInTabbedMode() throws Exception { - triggerWindowOpenAndWaitForLoad( - ChromeTabbedActivity.class, getHrefNoReferrerLinkUrl(), false); - } - - private <T extends ChromeActivity> void triggerWindowOpenAndWaitForLoad( - Class<T> classToWaitFor, String linkHtml, boolean checkContents) throws Exception { - final WebappActivity firstActivity = - startWebappActivity(WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON); - final int firstWebappId = firstActivity.getActivityTab().getId(); - - // Load up the test page. - new TabLoadObserver(firstActivity.getActivityTab()).fullyLoadUrl(linkHtml); - - // Do a plain click to make the link open in the main browser via a window.open(). - // If the window is opened successfully, javascript on the first page triggers and changes - // its URL as a signal for this test. - Runnable fgTrigger = new Runnable() { - @Override - public void run() { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - View view = firstActivity.findViewById(android.R.id.content).getRootView(); - TouchCommon.singleClickView(view); - } - }); - } - }; - ChromeActivity secondActivity = ActivityUtils.waitForActivity( - InstrumentationRegistry.getInstrumentation(), classToWaitFor, fgTrigger); - mTestRule.waitForFullLoad(secondActivity, "The Google"); - if (checkContents) { - Assert.assertEquals("New WebContents was not created", "SUCCESS", - firstActivity.getActivityTab().getTitle()); - } - Assert.assertNotSame("Wrong Activity in foreground", firstActivity, - ApplicationStatus.getLastTrackedFocusedActivity()); - - // Close the child window to kick the user back to the WebappActivity. - JavaScriptUtils.executeJavaScript( - secondActivity.getActivityTab().getWebContents(), "window.close()"); - CriteriaHelper.pollUiThread(new Criteria() { - @Override - public boolean isSatisfied() { - Activity lastActivity = ApplicationStatus.getLastTrackedFocusedActivity(); - if (!isWebappActivityReady(lastActivity)) return false; - - WebappActivity webappActivity = (WebappActivity) lastActivity; - return webappActivity.getActivityTab().getId() == firstWebappId; - } - }); - ApplicationTestUtils.waitUntilChromeInForeground(); - } - - /** * Starts a WebappActivity for the given data and waits for it to be initialized. We can't use * ActivityUtils.waitForActivity() because of the way WebappActivity is instanced on pre-L * devices. @@ -372,49 +296,4 @@ return true; } - - /** Defines one gigantic link spanning the whole page that creates a new - * window with chrome/test/data/android/google.html. Disallowing a referrer from being - * sent triggers another codepath. - */ - private String getHrefNoReferrerLinkUrl() { - return UrlUtils.encodeHtmlDataUri("<html>" - + " <head>" - + " <title>href no referrer link page</title>" - + " <meta name='viewport'" - + " content='width=device-width initial-scale=0.5, maximum-scale=0.5'>" - + " <style>" - + " body {margin: 0em;} div {width: 100%; height: 100%; background: #011684;}" - + " </style>" - + " </head>" - + " <body>" - + " <a href='" + mTestServer.getURL("/chrome/test/data/android/google.html") - + "' target='_blank' rel='noreferrer'><div></div></a>" - + " </body>"); - } - - /** Returns a URL where clicking the body triggers a window.open() call to open - * chrome/test/data/android/google.html. */ - private String getOnClickLinkUrl() { - return UrlUtils.encodeHtmlDataUri("<html>" - + " <head>" - + " <title>window.open page</title>" - + " <meta name='viewport'" - + " content='width=device-width initial-scale=0.5, maximum-scale=0.5'>" - + " <style>" - + " body {margin: 0em;} div {width: 100%; height: 100%; background: #011684;}" - + " </style>" - + " <script>" - + " function openNewWindow() {" - + " var site = window.open('" - + mTestServer.getURL("/chrome/test/data/android/google.html") + "');" - + " document.title = site ? 'SUCCESS' : 'FAILURE';" - + " }" - + " </script>" - + " </head>" - + " <body id='body'>" - + " <div onclick='openNewWindow()'></div>" - + " </body>" - + "</html>"); - } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java index 25c476d3..6d234b8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java
@@ -4,8 +4,12 @@ package org.chromium.chrome.browser.webapps; +import android.app.ActivityManager; +import android.app.ActivityManager.AppTask; +import android.content.Context; import android.content.Intent; import android.graphics.Color; +import android.os.Build; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; @@ -17,7 +21,6 @@ import org.junit.runner.RunWith; import org.chromium.base.ApiCompatibilityUtils; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; @@ -28,7 +31,7 @@ import org.chromium.chrome.browser.firstrun.FirstRunStatus; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.browser.contextmenu.ContextMenuUtils; -import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.content.browser.test.util.DOMUtils; import org.chromium.net.test.EmbeddedTestServer; import org.chromium.ui.base.PageTransition; @@ -64,18 +67,12 @@ @Test @SmallTest @Feature({"Webapps"}) - public void testOffOriginNavigationUsingLinkAndNoWebappThemeColor() throws Exception { + public void testRegularLinkOffOriginInCctNoWebappThemeColor() throws Exception { runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent()); - - // Not using #loadUrl, as it expects the URL to load in the activity under test, - // which is not happening here. - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mActivityTestRule.getActivity().getActivityTab().loadUrl( - new LoadUrlParams(OFF_ORIGIN_URL, PageTransition.LINK)); - } - }); + assertNumberOfTasksInRecents("We should start with one Android task", 1); + addAnchor("testId", OFF_ORIGIN_URL, "_self"); + DOMUtils.clickNode( + mActivityTestRule.getActivity().getActivityTab().getContentViewCore(), "testId"); CustomTabActivity customTab = assertCustomTabActivityLaunchedForOffOriginUrl(); @@ -84,14 +81,17 @@ ApiCompatibilityUtils.getColor( customTab.getResources(), R.color.default_primary_color), customTab.getToolbarManager().getPrimaryColor()); + assertNumberOfTasksInRecents( + "Link with target=\"_self\" should stay in the same Android task.", 1); } @Test @SmallTest @Feature({"Webapps"}) - public void testOffOriginNavigationUsingJavaScriptAndWebappThemeColor() throws Exception { + public void testWindowTopLocationOffOriginInCctAndWebappThemeColor() throws Exception { runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent().putExtra( ShortcutHelper.EXTRA_THEME_COLOR, (long) Color.CYAN)); + assertNumberOfTasksInRecents("We should start with one Android task", 1); mActivityTestRule.runJavaScriptCodeInCurrentTab( String.format("window.top.location = '%s'", OFF_ORIGIN_URL)); @@ -100,16 +100,58 @@ Assert.assertEquals("CCT Toolbar should use the theme color of a webapp", Color.CYAN, customTab.getToolbarManager().getPrimaryColor()); + assertNumberOfTasksInRecents( + "Executing window.top.location = url; should stay in the same Android task.", 1); } - private CustomTabActivity assertCustomTabActivityLaunchedForOffOriginUrl() { - CustomTabActivity customTab = activityListener.waitFor(CustomTabActivity.class); + @Test + @SmallTest + @Feature({"Webapps"}) + public void testNewTabLinkOpensInCct() throws Exception { + runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent().putExtra( + ShortcutHelper.EXTRA_THEME_COLOR, (long) Color.CYAN)); + assertNumberOfTasksInRecents("We should start with one Android task", 1); + addAnchor("testId", OFF_ORIGIN_URL, "_blank"); + DOMUtils.clickNode( + mActivityTestRule.getActivity().getActivityTab().getContentViewCore(), "testId"); + CustomTabActivity customTab = assertCustomTabActivityLaunchedForOffOriginUrl(); + Assert.assertEquals( + "CCT Toolbar should use default primary color even if webapp has theme color", + ApiCompatibilityUtils.getColor( + customTab.getResources(), R.color.default_primary_color), + customTab.getToolbarManager().getPrimaryColor()); + assertNumberOfTasksInRecents( + "Link with target=\"_blank\" should open in a new Android task.", 2); + } - mActivityTestRule.waitUntilIdle(customTab); - // Dropping the TLD as Google can redirect to a local site, so this could fail outside US. - Assert.assertTrue(customTab.getActivityTab().getUrl().startsWith("https://www.google.")); + @Test + @SmallTest + @Feature({"Webapps"}) + public void testWindowOpenInCct() throws Exception { + runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent()); + assertNumberOfTasksInRecents("We should start with one Android task", 1); + // Executing window.open() through a click on a link, + // as it needs user gesture to avoid Chrome blocking it as a popup. + mActivityTestRule.runJavaScriptCodeInCurrentTab( + String.format("var aTag = document.createElement('testId');" + + "aTag.id = 'testId';" + + "aTag.innerHTML = 'Click Me!';" + + "aTag.onclick = function() {" + + " window.open('%s');" + + " return false;" + + "};" + + "document.body.appendChild(aTag);", + OFF_ORIGIN_URL)); + DOMUtils.clickNode( + mActivityTestRule.getActivity().getActivityTab().getContentViewCore(), "testId"); - return customTab; + CustomTabActivity customTab = assertCustomTabActivityLaunchedForOffOriginUrl(); + Assert.assertEquals("CCT Toolbar should use default primary color", + ApiCompatibilityUtils.getColor( + customTab.getResources(), R.color.default_primary_color), + customTab.getToolbarManager().getPrimaryColor()); + assertNumberOfTasksInRecents( + "Executing window.open(url) should open a new Android task.", 2); } @Test @@ -138,11 +180,7 @@ FirstRunStatus.setFirstRunFlowComplete(true); runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent()); - mActivityTestRule.runJavaScriptCodeInCurrentTab("var aTag = document.createElement('a');" - + "aTag.id = 'myTestAnchorId';" - + "aTag.setAttribute('href','https://www.google.com/');" - + "aTag.innerHTML = 'Click Me!';" - + "document.body.appendChild(aTag);"); + addAnchor("myTestAnchorId", OFF_ORIGIN_URL, "_self"); ContextMenuUtils.selectContextMenuItem(InstrumentationRegistry.getInstrumentation(), null /* activity to check for focus after click */, @@ -163,4 +201,45 @@ mActivityTestRule.waitUntilSplashscreenHides(); mActivityTestRule.waitUntilIdle(); } + + private CustomTabActivity assertCustomTabActivityLaunchedForOffOriginUrl() { + CustomTabActivity customTab = activityListener.waitFor(CustomTabActivity.class); + + mActivityTestRule.waitUntilIdle(customTab); + // Dropping the TLD as Google can redirect to a local site, so this could fail outside US. + Assert.assertTrue(customTab.getActivityTab().getUrl().contains("https://www.google.")); + + return customTab; + } + + private void addAnchor(String id, String url, String target) throws Exception { + mActivityTestRule.runJavaScriptCodeInCurrentTab( + String.format("var aTag = document.createElement('a');" + + "aTag.id = '%s';" + + "aTag.setAttribute('href','%s');" + + "aTag.setAttribute('target','%s');" + + "aTag.innerHTML = 'Click Me!';" + + "document.body.appendChild(aTag);", + id, url, target)); + } + + private void assertNumberOfTasksInRecents(String message, int expectedNumberOfTasks) { + // We only have API to check this since Lollipop. + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return; + + ActivityManager activityManager = + (ActivityManager) mActivityTestRule.getActivity().getSystemService( + Context.ACTIVITY_SERVICE); + + int count = 0; + for (AppTask task : activityManager.getAppTasks()) { + if ((task.getTaskInfo().baseIntent.getFlags() + & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) + == 0) { + count++; + } + } + + Assert.assertEquals(message, expectedNumberOfTasks, count); + } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java index d15846f..27284cc 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java
@@ -107,8 +107,10 @@ mAutocomplete.setIgnoreTextChangesForAutocomplete(false); // User types "h". assertTrue(mInputConnection.commitText("h", 1)); + mInOrder.verify(mEmbedder).onAutocompleteTextStateChanged(false, true); // User types "hello". assertTrue(mInputConnection.commitText("ello", 1)); + mInOrder.verify(mEmbedder).onAutocompleteTextStateChanged(false, true); mInOrder.verifyNoMoreInteractions(); // The controller kicks in. mAutocomplete.setAutocompleteText("hello", " world");
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java index 3dbb28f..b3717f5 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
@@ -144,15 +144,14 @@ } @Override - protected void scheduleUpdate(WebApkInfo info, String primaryIconUrl, String badgeIconUrl, - boolean isManifestStale) { + protected void buildProtoAndScheduleUpdate(WebApkInfo info, String primaryIconUrl, + String badgeIconUrl, boolean isManifestStale) { mUpdateName = info.name(); - super.scheduleUpdate(info, primaryIconUrl, badgeIconUrl, isManifestStale); + scheduleUpdate(info, new byte[0]); } @Override - protected void updateAsyncImpl(WebApkInfo info, String primaryIconUrl, String badgeIconUrl, - boolean isManifestStale) { + protected void updateAsyncImpl(WebApkInfo info, byte[] serializedProto) { mUpdateRequested = true; }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index b1747d4..f094008 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1162,6 +1162,8 @@ "resource_delegate_mac.mm", "resources_util.cc", "resources_util.h", + "safe_browsing/browser_url_loader_throttle.cc", + "safe_browsing/browser_url_loader_throttle.h", "safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc", "safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h", "safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win.cc", @@ -1182,6 +1184,8 @@ "safe_browsing/mojo_safe_browsing_impl.h", "safe_browsing/safe_browsing_tab_observer.cc", "safe_browsing/safe_browsing_tab_observer.h", + "safe_browsing/safe_browsing_url_checker_impl.cc", + "safe_browsing/safe_browsing_url_checker_impl.h", "safe_search_api/safe_search_url_checker.cc", "safe_search_api/safe_search_url_checker.h", "search/iframe_source.cc", @@ -2208,12 +2212,15 @@ "android/offline_pages/request_coordinator_factory.h", "offline_pages/background_loader_offliner.cc", "offline_pages/background_loader_offliner.h", + "offline_pages/offliner_user_data.cc", + "offline_pages/offliner_user_data.h", "offline_pages/prefetch/offline_metrics_collector_impl.cc", "offline_pages/prefetch/offline_metrics_collector_impl.h", "offline_pages/prefetch/prefetch_instance_id_proxy.cc", "offline_pages/prefetch/prefetch_instance_id_proxy.h", "offline_pages/prefetch/prefetch_service_factory.cc", "offline_pages/prefetch/prefetch_service_factory.h", + "offline_pages/resource_loading_observer.h", ] if (is_android) { sources += [
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index b376a1c..d302cd55 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -389,13 +389,6 @@ switches::kForceGpuRasterization, ""}, }; -const FeatureEntry::Choice kColorCorrectRenderingChoices[] = { - {flags_ui::kGenericExperimentChoiceDefault, "", ""}, - {flags_ui::kGenericExperimentChoiceEnabled, - switches::kEnableColorCorrectRendering, ""}, - {flags_ui::kGenericExperimentChoiceDisabled, "", ""}, -}; - const FeatureEntry::Choice kEnableWebGL2Choices[] = { {flags_ui::kGenericExperimentChoiceDefault, "", ""}, {flags_ui::kGenericExperimentChoiceEnabled, switches::kEnableES3APIs, ""}, @@ -1397,9 +1390,9 @@ proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery)}, #endif // OS_CHROMEOS #if defined(USE_ASH) - {"ash-disable-night-light", flag_descriptions::kDisableNightLightName, - flag_descriptions::kDisableNightLightDescription, kOsAll, - SINGLE_DISABLE_VALUE_TYPE(ash::switches::kAshDisableNightLight)}, + {"ash-enable-night-light", flag_descriptions::kEnableNightLightName, + flag_descriptions::kEnableNightLightDescription, kOsAll, + SINGLE_VALUE_TYPE(ash::switches::kAshEnableNightLight)}, {"show-touch-hud", flag_descriptions::kShowTouchHudName, flag_descriptions::kShowTouchHudDescription, kOsAll, SINGLE_VALUE_TYPE(ash::switches::kAshTouchHud)}, @@ -2944,7 +2937,7 @@ {"enable-color-correct-rendering", flag_descriptions::kColorCorrectRenderingName, flag_descriptions::kColorCorrectRenderingDescription, kOsAll, - MULTI_VALUE_TYPE(kColorCorrectRenderingChoices)}, + FEATURE_VALUE_TYPE(features::kColorCorrectRendering)}, #if defined(OS_CHROMEOS) {"quick-unlock-pin-signin", flag_descriptions::kQuickUnlockPinSignin,
diff --git a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.cc b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.cc index c46efc1..c81115e2 100644 --- a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.cc +++ b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.cc
@@ -12,6 +12,7 @@ #include "base/location.h" #include "base/logging.h" #include "base/strings/string16.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/ssl/security_state_tab_helper.h" #include "components/security_state/core/security_state.h" @@ -27,10 +28,10 @@ void DeleteFileOnFileThread(const base::FilePath& file_path, const base::Closure& callback) { - content::BrowserThread::PostTaskAndReply( - content::BrowserThread::FILE, FROM_HERE, - base::Bind(base::IgnoreResult(&base::DeleteFile), file_path, - false /* recursive */), + base::PostTaskWithTraitsAndReply( + FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, + base::BindOnce(base::IgnoreResult(&base::DeleteFile), file_path, + false /* recursive */), callback); } } // namespace
diff --git a/chrome/browser/android/usb/web_usb_chooser_service_android.cc b/chrome/browser/android/usb/web_usb_chooser_service_android.cc index d4618a0..88148a82 100644 --- a/chrome/browser/android/usb/web_usb_chooser_service_android.cc +++ b/chrome/browser/android/usb/web_usb_chooser_service_android.cc
@@ -20,10 +20,10 @@ WebUsbChooserServiceAndroid::~WebUsbChooserServiceAndroid() {} void WebUsbChooserServiceAndroid::GetPermission( - const std::vector<device::UsbDeviceFilter>& device_filters, + std::vector<device::mojom::UsbDeviceFilterPtr> device_filters, const GetPermissionCallback& callback) { usb_chooser_dialog_android_.push_back( - base::MakeUnique<UsbChooserDialogAndroid>(device_filters, + base::MakeUnique<UsbChooserDialogAndroid>(std::move(device_filters), render_frame_host_, callback)); }
diff --git a/chrome/browser/android/usb/web_usb_chooser_service_android.h b/chrome/browser/android/usb/web_usb_chooser_service_android.h index db2df4d9..d6919ba 100644 --- a/chrome/browser/android/usb/web_usb_chooser_service_android.h +++ b/chrome/browser/android/usb/web_usb_chooser_service_android.h
@@ -30,8 +30,9 @@ ~WebUsbChooserServiceAndroid() override; // device::usb::ChooserService: - void GetPermission(const std::vector<device::UsbDeviceFilter>& device_filters, - const GetPermissionCallback& callback) override; + void GetPermission( + std::vector<device::mojom::UsbDeviceFilterPtr> device_filters, + const GetPermissionCallback& callback) override; void Bind(mojo::InterfaceRequest<device::mojom::UsbChooserService> request);
diff --git a/chrome/browser/android/webapk/webapk_install_service.cc b/chrome/browser/android/webapk/webapk_install_service.cc index 2c027b2..22dcbbeae 100644 --- a/chrome/browser/android/webapk/webapk_install_service.cc +++ b/chrome/browser/android/webapk/webapk_install_service.cc
@@ -42,24 +42,14 @@ } void WebApkInstallService::UpdateAsync( - const ShortcutInfo& shortcut_info, - const SkBitmap& primary_icon, - const SkBitmap& badge_icon, const std::string& webapk_package, - int webapk_version, - const std::map<std::string, std::string>& icon_url_to_murmur2_hash, - bool is_manifest_stale, + const GURL& start_url, + const base::string16& short_name, + std::unique_ptr<std::vector<uint8_t>> serialized_proto, const FinishCallback& finish_callback) { - DCHECK(!IsInstallInProgress(shortcut_info.manifest_url)); - - installs_.insert(shortcut_info.manifest_url); - - WebApkInstaller::UpdateAsync( - browser_context_, shortcut_info, primary_icon, badge_icon, webapk_package, - webapk_version, icon_url_to_murmur2_hash, is_manifest_stale, - base::Bind(&WebApkInstallService::OnFinishedInstall, - weak_ptr_factory_.GetWeakPtr(), shortcut_info.manifest_url, - finish_callback)); + WebApkInstaller::UpdateAsync(browser_context_, webapk_package, start_url, + short_name, std::move(serialized_proto), + finish_callback); } void WebApkInstallService::OnFinishedInstall(
diff --git a/chrome/browser/android/webapk/webapk_install_service.h b/chrome/browser/android/webapk/webapk_install_service.h index 476e9c7..6134f08b 100644 --- a/chrome/browser/android/webapk/webapk_install_service.h +++ b/chrome/browser/android/webapk/webapk_install_service.h
@@ -6,12 +6,15 @@ #define CHROME_BROWSER_ANDROID_WEBAPK_WEBAPK_INSTALL_SERVICE_H_ #include <map> +#include <memory> #include <set> #include <string> +#include <vector> #include "base/callback.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/strings/string16.h" #include "components/keyed_service/core/keyed_service.h" #include "url/gurl.h" @@ -63,17 +66,13 @@ const FinishCallback& finish_callback); // Talks to the Chrome WebAPK server to update a WebAPK on the server and to - // the Google Play server to install the downloaded WebAPK. Calls |callback| - // after the request to install the WebAPK is sent to Google Play. - void UpdateAsync( - const ShortcutInfo& shortcut_info, - const SkBitmap& primary_icon, - const SkBitmap& badge_icon, - const std::string& webapk_package, - int webapk_version, - const std::map<std::string, std::string>& icon_url_to_murmur2_hash, - bool is_manifest_stale, - const FinishCallback& finish_callback); + // the Google Play server to install the downloaded WebAPK. Calls + // |finish_callback| once the update completed or failed. + void UpdateAsync(const std::string& webapk_package, + const GURL& start_url, + const base::string16& short_name, + std::unique_ptr<std::vector<uint8_t>> serialized_proto, + const FinishCallback& finish_callback); private: // Called once the install/update completed or failed.
diff --git a/chrome/browser/android/webapk/webapk_installer.cc b/chrome/browser/android/webapk/webapk_installer.cc index 31966bd..663093d 100644 --- a/chrome/browser/android/webapk/webapk_installer.cc +++ b/chrome/browser/android/webapk/webapk_installer.cc
@@ -4,12 +4,15 @@ #include "chrome/browser/android/webapk/webapk_installer.h" +#include <utility> + #include "base/android/build_info.h" #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/android/path_utils.h" #include "base/bind.h" #include "base/command_line.h" +#include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -108,7 +111,7 @@ // Populates webapk::WebApk and returns it. // Must be called on a worker thread because it encodes an SkBitmap. -std::unique_ptr<webapk::WebApk> BuildProtoInBackground( +std::unique_ptr<std::vector<uint8_t>> BuildProtoInBackground( const ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, const SkBitmap& badge_icon, @@ -171,7 +174,12 @@ image->set_hash(entry.second); } - return webapk; + size_t serialized_size = webapk->ByteSize(); + std::unique_ptr<std::vector<uint8_t>> serialized_proto = + base::MakeUnique<std::vector<uint8_t>>(); + serialized_proto->resize(serialized_size); + webapk->SerializeToArray(serialized_proto->data(), serialized_size); + return serialized_proto; } // Returns task runner for running background tasks. @@ -196,48 +204,44 @@ const SkBitmap& badge_icon, const FinishCallback& finish_callback) { // The installer will delete itself when it is done. - WebApkInstaller* installer = - new WebApkInstaller(context, shortcut_info, primary_icon, badge_icon); - installer->InstallAsync(finish_callback); + WebApkInstaller* installer = new WebApkInstaller(context); + installer->InstallAsync(shortcut_info, primary_icon, badge_icon, + finish_callback); } // static void WebApkInstaller::UpdateAsync( content::BrowserContext* context, - const ShortcutInfo& shortcut_info, - const SkBitmap& primary_icon, - const SkBitmap& badge_icon, const std::string& webapk_package, - int webapk_version, - const std::map<std::string, std::string>& icon_url_to_murmur2_hash, - bool is_manifest_stale, + const GURL& start_url, + const base::string16& short_name, + std::unique_ptr<std::vector<uint8_t>> serialized_proto, const FinishCallback& finish_callback) { // The installer will delete itself when it is done. - WebApkInstaller* installer = new WebApkInstaller( - context, shortcut_info, primary_icon, badge_icon); - installer->UpdateAsync(webapk_package, webapk_version, - icon_url_to_murmur2_hash, is_manifest_stale, - finish_callback); + WebApkInstaller* installer = new WebApkInstaller(context); + installer->UpdateAsync(webapk_package, start_url, short_name, + std::move(serialized_proto), finish_callback); } -// staic -void WebApkInstaller::InstallAsyncForTesting( - WebApkInstaller* installer, - const FinishCallback& finish_callback) { - installer->InstallAsync(finish_callback); +// static +void WebApkInstaller::InstallAsyncForTesting(WebApkInstaller* installer, + const ShortcutInfo& shortcut_info, + const SkBitmap& primary_icon, + const SkBitmap& badge_icon, + const FinishCallback& callback) { + installer->InstallAsync(shortcut_info, primary_icon, badge_icon, callback); } // static void WebApkInstaller::UpdateAsyncForTesting( WebApkInstaller* installer, const std::string& webapk_package, - int webapk_version, - const std::map<std::string, std::string>& icon_url_to_murmur2_hash, - bool is_manifest_stale, + const GURL& start_url, + const base::string16& short_name, + std::unique_ptr<std::vector<uint8_t>> serialized_proto, const FinishCallback& finish_callback) { - installer->UpdateAsync(webapk_package, webapk_version, - icon_url_to_murmur2_hash, is_manifest_stale, - finish_callback); + installer->UpdateAsync(webapk_package, start_url, short_name, + std::move(serialized_proto), finish_callback); } void WebApkInstaller::SetTimeoutMs(int timeout_ms) { @@ -260,7 +264,8 @@ const std::string& version, const std::map<std::string, std::string>& icon_url_to_murmur2_hash, bool is_manifest_stale, - const base::Callback<void(std::unique_ptr<webapk::WebApk>)>& callback) { + const base::Callback<void(std::unique_ptr<std::vector<uint8_t>>)>& + callback) { base::PostTaskAndReplyWithResult( GetBackgroundTaskRunner().get(), FROM_HERE, base::Bind(&BuildProtoInBackground, shortcut_info, primary_icon, @@ -283,17 +288,17 @@ base::android::ScopedJavaLocalRef<jstring> java_webapk_package = base::android::ConvertUTF8ToJavaString(env, webapk_package_); base::android::ScopedJavaLocalRef<jstring> java_title = - base::android::ConvertUTF16ToJavaString(env, shortcut_info_.user_title); + base::android::ConvertUTF16ToJavaString(env, short_name_); base::android::ScopedJavaLocalRef<jstring> java_token = base::android::ConvertUTF8ToJavaString(env, token); base::android::ScopedJavaLocalRef<jstring> java_url = - base::android::ConvertUTF8ToJavaString(env, shortcut_info_.url.spec()); + base::android::ConvertUTF8ToJavaString(env, start_url_.spec()); if (task_type_ == WebApkInstaller::INSTALL) { webapk::TrackRequestTokenDuration(install_duration_timer_->Elapsed()); - Java_WebApkInstaller_installWebApkAsync(env, java_ref_, java_webapk_package, - version, java_title, java_token, - java_url, shortcut_info_.source); + Java_WebApkInstaller_installWebApkAsync( + env, java_ref_, java_webapk_package, version, java_title, java_token, + java_url, install_shortcut_info_->source); } else { Java_WebApkInstaller_updateAsync(env, java_ref_, java_webapk_package, version, java_title, java_token, java_url); @@ -317,15 +322,9 @@ delete this; } -WebApkInstaller::WebApkInstaller(content::BrowserContext* browser_context, - const ShortcutInfo& shortcut_info, - const SkBitmap& primary_icon, - const SkBitmap& badge_icon) +WebApkInstaller::WebApkInstaller(content::BrowserContext* browser_context) : request_context_getter_( Profile::FromBrowserContext(browser_context)->GetRequestContext()), - shortcut_info_(shortcut_info), - primary_icon_(primary_icon), - badge_icon_(badge_icon), server_url_(GetServerUrl()), webapk_server_timeout_ms_(kWebApkDownloadUrlTimeoutMs), relax_updates_(false), @@ -340,9 +339,17 @@ Java_WebApkInstaller_create(env, reinterpret_cast<intptr_t>(this))); } -void WebApkInstaller::InstallAsync(const FinishCallback& finish_callback) { +void WebApkInstaller::InstallAsync(const ShortcutInfo& shortcut_info, + const SkBitmap& primary_icon, + const SkBitmap& badge_icon, + const FinishCallback& finish_callback) { install_duration_timer_.reset(new base::ElapsedTimer()); + install_shortcut_info_.reset(new ShortcutInfo(shortcut_info)); + install_primary_icon_ = primary_icon; + install_badge_icon_ = badge_icon; + start_url_ = shortcut_info.url; + short_name_ = shortcut_info.short_name; finish_callback_ = finish_callback; task_type_ = INSTALL; @@ -355,26 +362,29 @@ // We redownload the icon in order to take the Murmur2 hash. The redownload // should be fast because the icon should be in the HTTP cache. WebApkIconHasher::DownloadAndComputeMurmur2Hash( - request_context_getter_, shortcut_info_.best_primary_icon_url, + request_context_getter_, install_shortcut_info_->best_primary_icon_url, base::Bind(&WebApkInstaller::OnGotPrimaryIconMurmur2Hash, weak_ptr_factory_.GetWeakPtr())); } void WebApkInstaller::UpdateAsync( const std::string& webapk_package, - int webapk_version, - const std::map<std::string, std::string>& icon_url_to_murmur2_hash, - bool is_manifest_stale, + const GURL& start_url, + const base::string16& short_name, + std::unique_ptr<std::vector<uint8_t>> serialized_proto, const FinishCallback& finish_callback) { webapk_package_ = webapk_package; + start_url_ = start_url; + short_name_ = short_name; finish_callback_ = finish_callback; task_type_ = UPDATE; - BuildProto(shortcut_info_, primary_icon_, badge_icon_, webapk_package_, - std::to_string(webapk_version), icon_url_to_murmur2_hash, - is_manifest_stale, - base::Bind(&WebApkInstaller::SendRequest, - weak_ptr_factory_.GetWeakPtr())); + if (!serialized_proto || serialized_proto->empty()) { + OnResult(WebApkInstallResult::FAILURE); + return; + } + + SendRequest(std::move(serialized_proto)); } void WebApkInstaller::OnURLFetchComplete(const net::URLFetcher* source) { @@ -426,11 +436,11 @@ return; } - if (!shortcut_info_.best_badge_icon_url.is_empty() && - shortcut_info_.best_badge_icon_url != - shortcut_info_.best_primary_icon_url) { + if (!install_shortcut_info_->best_badge_icon_url.is_empty() && + install_shortcut_info_->best_badge_icon_url != + install_shortcut_info_->best_primary_icon_url) { WebApkIconHasher::DownloadAndComputeMurmur2Hash( - request_context_getter_, shortcut_info_.best_badge_icon_url, + request_context_getter_, install_shortcut_info_->best_badge_icon_url, base::Bind(&WebApkInstaller::OnGotBadgeIconMurmur2Hash, weak_ptr_factory_.GetWeakPtr(), true, primary_icon_hash)); } else { @@ -450,35 +460,36 @@ // Maps icon URLs to Murmur2 hashes. std::map<std::string, std::string> icon_url_to_murmur2_hash; - for (const std::string& icon_url : shortcut_info_.icon_urls) { - if (icon_url == shortcut_info_.best_primary_icon_url.spec()) + for (const std::string& icon_url : install_shortcut_info_->icon_urls) { + if (icon_url == install_shortcut_info_->best_primary_icon_url.spec()) icon_url_to_murmur2_hash[icon_url] = primary_icon_hash; - else if (icon_url == shortcut_info_.best_badge_icon_url.spec()) + else if (icon_url == install_shortcut_info_->best_badge_icon_url.spec()) icon_url_to_murmur2_hash[icon_url] = badge_icon_hash; else icon_url_to_murmur2_hash[icon_url] = ""; } - BuildProto(shortcut_info_, primary_icon_, badge_icon_, "" /* package_name */, - "" /* version */, icon_url_to_murmur2_hash, - false /* is_manifest_stale */, + BuildProto(*install_shortcut_info_, install_primary_icon_, + install_badge_icon_, "" /* package_name */, "" /* version */, + icon_url_to_murmur2_hash, false /* is_manifest_stale */, base::Bind(&WebApkInstaller::SendRequest, weak_ptr_factory_.GetWeakPtr())); } void WebApkInstaller::SendRequest( - std::unique_ptr<webapk::WebApk> request_proto) { + std::unique_ptr<std::vector<uint8_t>> serialized_proto) { timer_.Start( FROM_HERE, base::TimeDelta::FromMilliseconds(webapk_server_timeout_ms_), base::Bind(&WebApkInstaller::OnResult, weak_ptr_factory_.GetWeakPtr(), WebApkInstallResult::FAILURE)); + std::string serialized_proto_string(serialized_proto->begin(), + serialized_proto->end()); + url_fetcher_ = net::URLFetcher::Create(server_url_, net::URLFetcher::POST, this); url_fetcher_->SetRequestContext(request_context_getter_); - std::string serialized_request; - request_proto->SerializeToString(&serialized_request); - url_fetcher_->SetUploadData(kProtoMimeType, serialized_request); + url_fetcher_->SetUploadData(kProtoMimeType, serialized_proto_string); url_fetcher_->SetLoadFlags( net::LOAD_DISABLE_CACHE | net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_AUTH_DATA);
diff --git a/chrome/browser/android/webapk/webapk_installer.h b/chrome/browser/android/webapk/webapk_installer.h index 807b24b4..2c21121a 100644 --- a/chrome/browser/android/webapk/webapk_installer.h +++ b/chrome/browser/android/webapk/webapk_installer.h
@@ -8,11 +8,13 @@ #include <jni.h> #include <map> #include <memory> +#include <vector> #include "base/android/scoped_java_ref.h" #include "base/callback.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/strings/string16.h" #include "base/timer/timer.h" #include "chrome/browser/android/shortcut_info.h" #include "chrome/browser/android/webapk/webapk_install_service.h" @@ -28,11 +30,7 @@ class BrowserContext; } -namespace webapk { -class WebApk; -} - -// Talks to Chrome WebAPK server to download metadata about a WebApk and issue +// Talks to Chrome WebAPK server to download metadata about a WebAPK and issue // a request for it to be installed. The native WebApkInstaller owns the Java // WebApkInstaller counterpart. class WebApkInstaller : public net::URLFetcherDelegate { @@ -55,18 +53,18 @@ // APK to be installed. Calls |callback| once the install completed or failed. static void UpdateAsync( content::BrowserContext* context, - const ShortcutInfo& shortcut_info, - const SkBitmap& primary_icon, - const SkBitmap& badge_icon, const std::string& webapk_package, - int webapk_version, - const std::map<std::string, std::string>& icon_url_to_murmur2_hash, - bool is_manifest_stale, + const GURL& start_url, + const base::string16& short_name, + std::unique_ptr<std::vector<uint8_t>> serialized_proto, const FinishCallback& callback); // Calls the private function |InstallAsync| for testing. // Should be used only for testing. static void InstallAsyncForTesting(WebApkInstaller* installer, + const ShortcutInfo& shortcut_info, + const SkBitmap& primary_icon, + const SkBitmap& badge_icon, const FinishCallback& finish_callback); // Calls the private function |UpdateAsync| for testing. @@ -74,9 +72,9 @@ static void UpdateAsyncForTesting( WebApkInstaller* installer, const std::string& webapk_package, - int webapk_version, - const std::map<std::string, std::string>& icon_url_to_murmur2_hash, - bool is_manifest_stale, + const GURL& start_url, + const base::string16& short_name, + std::unique_ptr<std::vector<uint8_t>> serialized_proto, const FinishCallback& callback); // Sets the timeout for the server requests. @@ -97,16 +95,14 @@ const std::string& version, const std::map<std::string, std::string>& icon_url_to_murmur2_hash, bool is_manifest_stale, - const base::Callback<void(std::unique_ptr<webapk::WebApk>)>& callback); + const base::Callback<void(std::unique_ptr<std::vector<uint8_t>>)>& + callback); // Registers JNI hooks. static bool Register(JNIEnv* env); protected: - WebApkInstaller(content::BrowserContext* browser_context, - const ShortcutInfo& shortcut_info, - const SkBitmap& primary_icon, - const SkBitmap& badge_icon); + explicit WebApkInstaller(content::BrowserContext* browser_context); // Called when the package name of the WebAPK is available and the install // or update request should be issued. @@ -130,17 +126,19 @@ // Talks to the Chrome WebAPK server to generate a WebAPK on the server and to // Google Play to install the downloaded WebAPK. Calls |callback| once the // install completed or failed. - void InstallAsync(const FinishCallback& finish_callback); + void InstallAsync(const ShortcutInfo& shortcut_info, + const SkBitmap& primary_icon, + const SkBitmap& badge_icon, + const FinishCallback& finish_callback); // Talks to the Chrome WebAPK server to update a WebAPK on the server and to - // the Google Play server to install the downloaded WebAPK. Calls |callback| - // after the request to install the WebAPK is sent to the Google Play server. - void UpdateAsync( - const std::string& webapk_package, - int webapk_version, - const std::map<std::string, std::string>& icon_url_to_murmur2_hash, - bool is_manifest_stale, - const FinishCallback& callback); + // the Google Play server to install the downloaded WebAPK. Calls + // |finish_callback| once the update completed or failed. + void UpdateAsync(const std::string& webapk_package, + const GURL& start_url, + const base::string16& short_name, + const std::unique_ptr<std::vector<uint8_t>> serialized_proto, + const FinishCallback& callback); // net::URLFetcherDelegate: void OnURLFetchComplete(const net::URLFetcher* source) override; @@ -156,9 +154,9 @@ const std::string& badge_icon_hash); // Sends a request to WebAPK server to create/update WebAPK. During a - // successful request the WebAPK server responds with the URL of the generated - // WebAPK. - void SendRequest(std::unique_ptr<webapk::WebApk> request_proto); + // successful request the WebAPK server responds with a token to send to + // Google Play. + void SendRequest(std::unique_ptr<std::vector<uint8_t>> serialized_proto); net::URLRequestContextGetter* request_context_getter_; @@ -175,14 +173,13 @@ // Callback to call once WebApkInstaller succeeds or fails. FinishCallback finish_callback_; - // Web Manifest info. - const ShortcutInfo shortcut_info_; + // Data for installs. + std::unique_ptr<ShortcutInfo> install_shortcut_info_; + SkBitmap install_primary_icon_; + SkBitmap install_badge_icon_; - // WebAPK primary icon. - const SkBitmap primary_icon_; - - // WebAPK badge icon. - const SkBitmap badge_icon_; + GURL start_url_; + base::string16 short_name_; // WebAPK server URL. GURL server_url_;
diff --git a/chrome/browser/android/webapk/webapk_installer_unittest.cc b/chrome/browser/android/webapk/webapk_installer_unittest.cc index 6b209d35..341c5ec 100644 --- a/chrome/browser/android/webapk/webapk_installer_unittest.cc +++ b/chrome/browser/android/webapk/webapk_installer_unittest.cc
@@ -13,6 +13,7 @@ #include "base/callback_forward.h" #include "base/command_line.h" #include "base/files/file_path.h" +#include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" @@ -63,14 +64,8 @@ // WebApkInstaller::InstallOrUpdateWebApkFromGooglePlay() are stubbed out. class TestWebApkInstaller : public WebApkInstaller { public: - TestWebApkInstaller(content::BrowserContext* browser_context, - const ShortcutInfo& shortcut_info, - const SkBitmap& primary_icon, - const SkBitmap& badge_icon) - : WebApkInstaller(browser_context, - shortcut_info, - primary_icon, - badge_icon) {} + explicit TestWebApkInstaller(content::BrowserContext* browser_context) + : WebApkInstaller(browser_context) {} void InstallOrUpdateWebApk(const std::string& package_name, int version, @@ -102,45 +97,48 @@ ~WebApkInstallerRunner() {} void RunInstallWebApk() { + base::RunLoop run_loop; + on_completed_callback_ = run_loop.QuitClosure(); + + ShortcutInfo info((GURL())); + info.best_primary_icon_url = best_primary_icon_url_; + info.best_badge_icon_url = best_badge_icon_url_; WebApkInstaller::InstallAsyncForTesting( - CreateWebApkInstaller(), base::Bind(&WebApkInstallerRunner::OnCompleted, - base::Unretained(this))); - Run(); + CreateWebApkInstaller(), info, SkBitmap(), SkBitmap(), + base::Bind(&WebApkInstallerRunner::OnCompleted, + base::Unretained(this))); + + run_loop.Run(); } - void RunUpdateWebApk() { - const int kWebApkVersion = 1; + void RunUpdateWebApk(const std::string& serialized_proto) { + base::RunLoop run_loop; + on_completed_callback_ = run_loop.QuitClosure(); std::map<std::string, std::string> icon_url_to_murmur2_hash{ {best_primary_icon_url_.spec(), "0"}, {best_badge_icon_url_.spec(), "0"}}; + std::unique_ptr<std::vector<uint8_t>> serialized_proto_vector = + base::MakeUnique<std::vector<uint8_t>>(serialized_proto.begin(), + serialized_proto.end()); WebApkInstaller::UpdateAsyncForTesting( - CreateWebApkInstaller(), kDownloadedWebApkPackageName, kWebApkVersion, - icon_url_to_murmur2_hash, false /* is_manifest_stale */, + CreateWebApkInstaller(), kDownloadedWebApkPackageName, + GURL() /* start_url */, base::string16() /* short_name */, + std::move(serialized_proto_vector), base::Bind(&WebApkInstallerRunner::OnCompleted, base::Unretained(this))); - Run(); + + run_loop.Run(); } WebApkInstaller* CreateWebApkInstaller() { - ShortcutInfo info(GURL::EmptyGURL()); - info.best_primary_icon_url = best_primary_icon_url_; - info.best_badge_icon_url = best_badge_icon_url_; - // WebApkInstaller owns itself. - WebApkInstaller* installer = - new TestWebApkInstaller(browser_context_, info, SkBitmap(), SkBitmap()); + WebApkInstaller* installer = new TestWebApkInstaller(browser_context_); installer->SetTimeoutMs(100); return installer; } - void Run() { - base::RunLoop run_loop; - on_completed_callback_ = run_loop.QuitClosure(); - run_loop.Run(); - } - WebApkInstallResult result() { return result_; } private: @@ -216,8 +214,11 @@ private: // Called when the |webapk_request_| is populated. - void OnBuiltWebApkProto(std::unique_ptr<webapk::WebApk> webapk) { - webapk_request_ = std::move(webapk); + void OnBuiltWebApkProto( + std::unique_ptr<std::vector<uint8_t>> serialized_proto) { + webapk_request_ = base::MakeUnique<webapk::WebApk>(); + webapk_request_->ParseFromArray(serialized_proto->data(), + serialized_proto->size()); on_completed_callback_.Run(); } @@ -386,7 +387,7 @@ // Test update succeeding. TEST_F(WebApkInstallerTest, UpdateSuccess) { std::unique_ptr<WebApkInstallerRunner> runner = CreateWebApkInstallerRunner(); - runner->RunUpdateWebApk(); + runner->RunUpdateWebApk("non-empty"); EXPECT_EQ(WebApkInstallResult::SUCCESS, runner->result()); } @@ -401,10 +402,17 @@ SetWebApkResponseBuilder(base::Bind(&BuildValidWebApkResponse, "")); std::unique_ptr<WebApkInstallerRunner> runner = CreateWebApkInstallerRunner(); - runner->RunUpdateWebApk(); + runner->RunUpdateWebApk("non-empty"); EXPECT_EQ(WebApkInstallResult::SUCCESS, runner->result()); } +// Test that an update fails if an empty proto is passed to UpdateAsync(). +TEST_F(WebApkInstallerTest, UpdateFailsEmptyProto) { + std::unique_ptr<WebApkInstallerRunner> runner = CreateWebApkInstallerRunner(); + runner->RunUpdateWebApk(""); + EXPECT_EQ(WebApkInstallResult::FAILURE, runner->result()); +} + // When there is no Web Manifest available for a site, an empty // |best_primary_icon_url| and an empty |best_badge_icon_url| is used to build a // WebApk update request. Tests the request can be built properly.
diff --git a/chrome/browser/android/webapk/webapk_update_manager.cc b/chrome/browser/android/webapk/webapk_update_manager.cc index 177d915..6728b2a 100644 --- a/chrome/browser/android/webapk/webapk_update_manager.cc +++ b/chrome/browser/android/webapk/webapk_update_manager.cc
@@ -5,13 +5,20 @@ #include "chrome/browser/android/webapk/webapk_update_manager.h" #include <jni.h> +#include <memory> +#include <vector> +#include "base/android/callback_android.h" #include "base/android/jni_array.h" #include "base/android/jni_string.h" +#include "base/android/scoped_java_ref.h" #include "base/bind.h" +#include "base/memory/ptr_util.h" +#include "base/strings/string16.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/android/shortcut_info.h" #include "chrome/browser/android/webapk/webapk_install_service.h" +#include "chrome/browser/android/webapk/webapk_installer.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "content/public/browser/browser_thread.h" @@ -20,31 +27,39 @@ #include "ui/gfx/android/java_bitmap.h" #include "url/gurl.h" +using base::android::JavaRef; using base::android::JavaParamRef; +using base::android::ScopedJavaGlobalRef; + +namespace { + +// Called with the serialized proto to send to the WebAPK server. +void OnBuiltProto(const JavaRef<jobject>& java_callback, + std::unique_ptr<std::vector<uint8_t>> proto) { + base::android::RunCallbackAndroid(java_callback, *proto); +} + +// Called after the update either succeeds or fails. +void OnUpdated(const JavaRef<jobject>& java_callback, + WebApkInstallResult result, + bool relax_updates, + const std::string& webapk_package) { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_WebApkUpdateCallback_onResultFromNative( + env, java_callback, static_cast<int>(result), relax_updates); +} + +} // anonymous namespace // static bool WebApkUpdateManager::Register(JNIEnv* env) { return RegisterNativesImpl(env); } -// static -void WebApkUpdateManager::OnBuiltWebApk(const std::string& id, - WebApkInstallResult result, - bool relax_updates, - const std::string& webapk_package) { - JNIEnv* env = base::android::AttachCurrentThread(); - - base::android::ScopedJavaLocalRef<jstring> java_id = - base::android::ConvertUTF8ToJavaString(env, id); - Java_WebApkUpdateManager_onBuiltWebApk( - env, java_id.obj(), static_cast<int>(result), relax_updates); -} - // static JNI method. -static void UpdateAsync( +static void BuildUpdateWebApkProto( JNIEnv* env, const JavaParamRef<jclass>& clazz, - const JavaParamRef<jstring>& java_id, const JavaParamRef<jstring>& java_start_url, const JavaParamRef<jstring>& java_scope, const JavaParamRef<jstring>& java_name, @@ -62,16 +77,10 @@ const JavaParamRef<jstring>& java_web_manifest_url, const JavaParamRef<jstring>& java_webapk_package, jint java_webapk_version, - jboolean java_is_manifest_stale) { + jboolean java_is_manifest_stale, + const JavaParamRef<jobject>& java_callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - Profile* profile = ProfileManager::GetLastUsedProfile(); - if (profile == nullptr) { - NOTREACHED() << "Profile not found."; - return; - } - - std::string id(ConvertJavaStringToUTF8(env, java_id)); ShortcutInfo info(GURL(ConvertJavaStringToUTF8(env, java_start_url))); info.scope = GURL(ConvertJavaStringToUTF8(env, java_scope)); info.name = ConvertJavaStringToUTF16(env, java_name); @@ -112,17 +121,43 @@ std::string webapk_package; ConvertJavaStringToUTF8(env, java_webapk_package, &webapk_package); - WebApkInstallService* install_service = WebApkInstallService::Get(profile); - if (install_service->IsInstallInProgress(info.manifest_url)) { + WebApkInstaller::BuildProto( + info, primary_icon, badge_icon, webapk_package, + std::to_string(java_webapk_version), icon_url_to_murmur2_hash, + java_is_manifest_stale, + base::Bind(&OnBuiltProto, ScopedJavaGlobalRef<jobject>(java_callback))); +} + +// static JNI method. +static void UpdateWebApk(JNIEnv* env, + const JavaParamRef<jclass>& clazz, + const JavaParamRef<jstring>& java_webapk_package, + const JavaParamRef<jstring>& java_start_url, + const JavaParamRef<jstring>& java_short_name, + const JavaParamRef<jbyteArray>& java_serialized_proto, + const JavaParamRef<jobject>& java_callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + ScopedJavaGlobalRef<jobject> callback_ref(java_callback); + + Profile* profile = ProfileManager::GetLastUsedProfile(); + if (profile == nullptr) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind(&WebApkUpdateManager::OnBuiltWebApk, id, - WebApkInstallResult::FAILURE, false /* relax_updates */, - "" /* webapk_package */)); + base::Bind(&OnUpdated, callback_ref, WebApkInstallResult::FAILURE, + false /* relax_updates */, "" /* webapk_package */)); return; } - install_service->UpdateAsync( - info, primary_icon, badge_icon, webapk_package, java_webapk_version, - icon_url_to_murmur2_hash, java_is_manifest_stale, - base::Bind(&WebApkUpdateManager::OnBuiltWebApk, id)); + + std::string webapk_package = + ConvertJavaStringToUTF8(env, java_webapk_package); + GURL start_url = GURL(ConvertJavaStringToUTF8(env, java_start_url)); + base::string16 short_name = ConvertJavaStringToUTF16(env, java_short_name); + std::unique_ptr<std::vector<uint8_t>> serialized_proto = + base::MakeUnique<std::vector<uint8_t>>(); + JavaByteArrayToByteVector(env, java_serialized_proto, serialized_proto.get()); + + WebApkInstallService::Get(profile)->UpdateAsync( + webapk_package, start_url, short_name, std::move(serialized_proto), + base::Bind(&OnUpdated, callback_ref)); }
diff --git a/chrome/browser/android/webapk/webapk_update_manager.h b/chrome/browser/android/webapk/webapk_update_manager.h index db196233..6040726 100644 --- a/chrome/browser/android/webapk/webapk_update_manager.h +++ b/chrome/browser/android/webapk/webapk_update_manager.h
@@ -18,15 +18,6 @@ // Registers JNI hooks. static bool Register(JNIEnv* env); - // Called after either a request to update the WebAPK has been sent, or the - // update process fails. |success| indicates whether the request was issued - // to the server. A "true" value of |success| does not guarantee that the - // WebAPK will be successfully updated. - static void OnBuiltWebApk(const std::string& id, - WebApkInstallResult result, - bool relax_updates, - const std::string& webapk_package); - private: DISALLOW_IMPLICIT_CONSTRUCTORS(WebApkUpdateManager); };
diff --git a/chrome/browser/apps/app_url_redirector.cc b/chrome/browser/apps/app_url_redirector.cc index 46321f2e..e5ec867 100644 --- a/chrome/browser/apps/app_url_redirector.cc +++ b/chrome/browser/apps/app_url_redirector.cc
@@ -113,8 +113,7 @@ new navigation_interception::InterceptNavigationThrottle( handle, base::Bind(&LaunchAppWithUrl, - scoped_refptr<const Extension>(*iter), handler->id), - true)); + scoped_refptr<const Extension>(*iter), handler->id))); } }
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index b6c80d45..e6061e9 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -3935,7 +3935,13 @@ WebViewScrollGuestContentTest, testing::Values(false)); -IN_PROC_BROWSER_TEST_P(WebViewScrollGuestContentTest, ScrollGuestContent) { +#if defined(OS_WIN) +#define MAYBE_ScrollGuestContent DISABLED_ScrollGuestContent +#else +#define MAYBE_ScrollGuestContent ScrollGuestContent +#endif +IN_PROC_BROWSER_TEST_P(WebViewScrollGuestContentTest, + MAYBE_ScrollGuestContent) { LoadAppWithGuest("web_view/scrollable_embedder_and_guest"); content::WebContents* embedder_contents = GetEmbedderWebContents();
diff --git a/chrome/browser/chooser_controller/chooser_controller.h b/chrome/browser/chooser_controller/chooser_controller.h index 33658c6..4de65c10 100644 --- a/chrome/browser/chooser_controller/chooser_controller.h +++ b/chrome/browser/chooser_controller/chooser_controller.h
@@ -130,6 +130,9 @@ void set_view(View* view) { view_ = view; } View* view() const { return view_; } + protected: + void set_title_for_testing(const base::string16& title) { title_ = title; } + private: base::string16 title_; View* view_ = nullptr;
diff --git a/chrome/browser/chooser_controller/mock_chooser_controller.cc b/chrome/browser/chooser_controller/mock_chooser_controller.cc index 9763d8c..92fc1e1 100644 --- a/chrome/browser/chooser_controller/mock_chooser_controller.cc +++ b/chrome/browser/chooser_controller/mock_chooser_controller.cc
@@ -14,7 +14,9 @@ MockChooserController::MockChooserController() : ChooserController(nullptr, IDS_USB_DEVICE_CHOOSER_PROMPT_ORIGIN, - IDS_USB_DEVICE_CHOOSER_PROMPT_EXTENSION_NAME) {} + IDS_USB_DEVICE_CHOOSER_PROMPT_EXTENSION_NAME) { + set_title_for_testing(base::ASCIIToUTF16("Mock Chooser Dialog")); +} MockChooserController::~MockChooserController() {}
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 0a963d1..ab1628f6 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -72,6 +72,7 @@ #include "chrome/browser/renderer_host/chrome_navigation_ui_data.h" #include "chrome/browser/renderer_host/chrome_render_message_filter.h" #include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h" +#include "chrome/browser/safe_browsing/browser_url_loader_throttle.h" #include "chrome/browser/safe_browsing/certificate_reporting_service.h" #include "chrome/browser/safe_browsing/certificate_reporting_service_factory.h" #include "chrome/browser/safe_browsing/mojo_safe_browsing_impl.h" @@ -186,6 +187,7 @@ #include "content/public/common/sandbox_type.h" #include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" +#include "content/public/common/url_loader_throttle.h" #include "content/public/common/url_utils.h" #include "content/public/common/web_preferences.h" #include "device/bluetooth/adapter_factory.h" @@ -2452,6 +2454,9 @@ void ChromeContentBrowserClient::ResourceDispatcherHostCreated() { DCHECK_CURRENTLY_ON(BrowserThread::UI); + + safe_browsing_service_ = g_browser_process->safe_browsing_service(); + for (size_t i = 0; i < extra_parts_.size(); ++i) extra_parts_[i]->ResourceDispatcherHostCreated(); @@ -2938,11 +2943,10 @@ if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableNetworkService)) { registry->AddInterface( - base::Bind( - &safe_browsing::MojoSafeBrowsingImpl::Create, - g_browser_process->safe_browsing_service()->database_manager(), - g_browser_process->safe_browsing_service()->ui_manager(), - render_process_host->GetID()), + base::Bind(&safe_browsing::MojoSafeBrowsingImpl::Create, + safe_browsing_service_->database_manager(), + safe_browsing_service_->ui_manager(), + render_process_host->GetID()), BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)); } @@ -3433,6 +3437,20 @@ return logging::GetLogFileName(); } +std::vector<std::unique_ptr<content::URLLoaderThrottle>> +ChromeContentBrowserClient::CreateURLLoaderThrottles( + const base::Callback<content::WebContents*()>& wc_getter) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableNetworkService)); + + std::vector<std::unique_ptr<content::URLLoaderThrottle>> result; + result.push_back(base::MakeUnique<safe_browsing::BrowserURLLoaderThrottle>( + safe_browsing_service_->database_manager(), + safe_browsing_service_->ui_manager(), wc_getter)); + return result; +} + // static void ChromeContentBrowserClient::SetDefaultQuotaSettingsForTesting( const storage::QuotaSettings* settings) {
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 7fc27d390..9456a061 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -15,6 +15,7 @@ #include "base/callback.h" #include "base/macros.h" +#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "build/build_config.h" #include "content/public/browser/content_browser_client.h" @@ -40,6 +41,10 @@ class QuotaPermissionContext; } +namespace safe_browsing { +class SafeBrowsingService; +} + namespace user_prefs { class PrefRegistrySyncable; } @@ -317,6 +322,9 @@ std::unique_ptr<base::TaskScheduler::InitParams> GetTaskSchedulerInitParams() override; base::FilePath GetLoggingFileName() override; + std::vector<std::unique_ptr<content::URLLoaderThrottle>> + CreateURLLoaderThrottles( + const base::Callback<content::WebContents*()>& wc_getter) override; private: friend class DisableWebRtcEncryptionFlagTest; @@ -372,6 +380,8 @@ service_manager::BinderRegistry gpu_binder_registry_; + scoped_refptr<safe_browsing::SafeBrowsingService> safe_browsing_service_; + base::WeakPtrFactory<ChromeContentBrowserClient> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ChromeContentBrowserClient);
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 32b52ad..2d8618d2 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1247,11 +1247,10 @@ "power/renderer_freezer.h", "preferences.cc", "preferences.h", - "printer_detector/cups_printer_detector.cc", - "printer_detector/legacy_printer_detector.cc", - "printer_detector/printer_detector.h", - "printer_detector/printer_detector_factory.cc", - "printer_detector/printer_detector_factory.h", + "printer_detector/usb_printer_detector.cc", + "printer_detector/usb_printer_detector.h", + "printer_detector/usb_printer_detector_factory.cc", + "printer_detector/usb_printer_detector_factory.h", "printing/cups_print_job.cc", "printing/cups_print_job.h", "printing/cups_print_job_manager.cc", @@ -1768,7 +1767,6 @@ "power/power_prefs_unittest.cc", "power/renderer_freezer_unittest.cc", "preferences_unittest.cc", - "printer_detector/printer_detector_unittest.cc", "printing/printers_manager_unittest.cc", "printing/specifics_translation_unittest.cc", "profiles/profile_list_chromeos_unittest.cc",
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 42fd5682..136cc7c 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -990,8 +990,8 @@ // fetch of the initial CrosSettings DeviceRebootOnShutdown policy. shutdown_policy_forwarder_ = base::MakeUnique<ShutdownPolicyForwarder>(); - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - ash::switches::kAshDisableNightLight)) { + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + ash::switches::kAshEnableNightLight)) { night_light_client_ = base::MakeUnique<NightLightClient>( g_browser_process->system_request_context()); night_light_client_->Start();
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index c0254c90..6877c0f9 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -103,7 +103,6 @@ ::switches::kDisableTouchDragDrop, ::switches::kDisableZeroCopy, ::switches::kEnableBlinkFeatures, - ::switches::kEnableColorCorrectRendering, ::switches::kDisableDisplayList2dCanvas, ::switches::kEnableDisplayList2dCanvas, ::switches::kForceDisplayList2dCanvas,
diff --git a/chrome/browser/chromeos/printer_detector/legacy_printer_detector.cc b/chrome/browser/chromeos/printer_detector/legacy_printer_detector.cc deleted file mode 100644 index e40dc51..0000000 --- a/chrome/browser/chromeos/printer_detector/legacy_printer_detector.cc +++ /dev/null
@@ -1,333 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdint.h> - -#include <memory> -#include <utility> -#include <vector> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/macros.h" -#include "base/metrics/histogram_macros.h" -#include "base/scoped_observer.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/printer_detector/printer_detector.h" -#include "chrome/browser/chromeos/printing/usb_printer_util.h" -#include "chrome/browser/chromeos/profiles/profile_helper.h" -#include "chrome/browser/notifications/notification.h" -#include "chrome/browser/notifications/notification_delegate.h" -#include "chrome/browser/notifications/notification_ui_manager.h" -#include "chrome/browser/ui/browser_navigator.h" -#include "chrome/common/extensions/api/webstore_widget_private.h" -#include "chrome/common/extensions/extension_constants.h" -#include "chrome/grit/generated_resources.h" -#include "chrome/grit/theme_resources.h" -#include "components/user_manager/user.h" -#include "components/user_manager/user_manager.h" -#include "device/base/device_client.h" -#include "device/usb/usb_device.h" -#include "device/usb/usb_device_filter.h" -#include "device/usb/usb_ids.h" -#include "device/usb/usb_service.h" -#include "extensions/browser/event_router.h" -#include "extensions/browser/extension_registry.h" -#include "extensions/browser/extension_system.h" -#include "extensions/common/api/printer_provider/usb_printer_manifest_data.h" -#include "extensions/common/extension.h" -#include "extensions/common/extension_set.h" -#include "extensions/common/one_shot_event.h" -#include "extensions/common/permissions/api_permission.h" -#include "extensions/common/permissions/permissions_data.h" -#include "extensions/common/permissions/usb_device_permission.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" - -namespace webstore_widget_private_api = - extensions::api::webstore_widget_private; - -namespace chromeos { -namespace { - -const char kPrinterProviderFoundNotificationID[] = - "chrome://settings/printer/printer_app_found"; - -const char kNoPrinterProviderNotificationID[] = - "chrome://settings/printer/no_printer_app"; - -enum PrinterServiceEvent { - PRINTER_ADDED, - DEPRECATED_PAGE_DISPLAYED, - NOTIFICATION_SHOWN_PRINTER_SUPPORTED, - NOTIFICATION_SHOWN_PRINTER_NOT_SUPPORTED, - WEBSTORE_WIDGET_APP_LAUNCHED, - PRINTER_SERVICE_EVENT_MAX, -}; - -base::string16 GetNotificationTitle(uint16_t vendor_id, uint16_t product_id) { - const char* vendor_name = device::UsbIds::GetVendorName(vendor_id); - if (vendor_name) { - return l10n_util::GetStringFUTF16(IDS_PRINTER_DETECTED_NOTIFICATION_TITLE, - base::UTF8ToUTF16(vendor_name)); - } else { - return l10n_util::GetStringUTF16( - IDS_PRINTER_DETECTED_NOTIFICATION_TITLE_UNKNOWN_VENDOR); - } -} - -std::string GetNotificationTag(const std::string& vendor_id, - const std::string& product_id) { - return vendor_id + ":" + product_id; -} - -// Checks if there is an enabled extension with printerProvider permission and -// usbDevices persmission for the USB (vendor_id, product_id) pair. -bool HasAppThatSupportsPrinter(Profile* profile, - const scoped_refptr<device::UsbDevice>& device) { - const extensions::ExtensionSet& enabled_extensions = - extensions::ExtensionRegistry::Get(profile)->enabled_extensions(); - for (const auto& extension : enabled_extensions) { - if (!extension->permissions_data() || - !extension->permissions_data()->HasAPIPermission( - extensions::APIPermission::kPrinterProvider) || - !extension->permissions_data()->HasAPIPermission( - extensions::APIPermission::kUsb)) { - continue; - } - - const extensions::UsbPrinterManifestData* manifest_data = - extensions::UsbPrinterManifestData::Get(extension.get()); - if (manifest_data && manifest_data->SupportsDevice(device)) { - return true; - } - - std::unique_ptr<extensions::UsbDevicePermission::CheckParam> param = - extensions::UsbDevicePermission::CheckParam::ForUsbDevice( - extension.get(), device.get()); - if (extension->permissions_data()->CheckAPIPermissionWithParam( - extensions::APIPermission::kUsbDevice, param.get())) { - return true; - } - } - return false; -} - -// Delegate for notification shown when a printer provider app for the plugged -// in printer is found. -class PrinterProviderExistsNotificationDelegate : public NotificationDelegate { - public: - PrinterProviderExistsNotificationDelegate(const std::string& vendor_id, - const std::string& product_id) - : vendor_id_(vendor_id), product_id_(product_id) {} - - std::string id() const override { - return "system.printer.printer_provider_exists/" + - GetNotificationTag(vendor_id_, product_id_); - } - - private: - ~PrinterProviderExistsNotificationDelegate() override = default; - - const std::string vendor_id_; - const std::string product_id_; - - DISALLOW_COPY_AND_ASSIGN(PrinterProviderExistsNotificationDelegate); -}; - -// Delegate for notification shown when there are no printer provider apps that -// support the plugged in printer found. -// The notification is clickable, and clicking it is supposed to launch -// Chrome Web Store widget listing apps that can support the plugged in printer. -// (not implemented yet). -class SearchPrinterAppNotificationDelegate : public NotificationDelegate { - public: - SearchPrinterAppNotificationDelegate(content::BrowserContext* browser_context, - uint16_t vendor_id, - const std::string& vendor_id_str, - uint16_t product_id, - const std::string& product_id_str) - : browser_context_(browser_context), - vendor_id_(vendor_id), - vendor_id_str_(vendor_id_str), - product_id_(product_id), - product_id_str_(product_id_str) {} - - std::string id() const override { - return "system.printer.no_printer_provider_found/" + - GetNotificationTag(vendor_id_str_, product_id_str_); - } - - bool HasClickedListener() override { return true; } - - void Click() override { - UMA_HISTOGRAM_ENUMERATION("PrinterService.PrinterServiceEvent", - WEBSTORE_WIDGET_APP_LAUNCHED, - PRINTER_SERVICE_EVENT_MAX); - webstore_widget_private_api::Options options; - options.type = webstore_widget_private_api::TYPE_PRINTER_PROVIDER; - options.usb_id.reset(new webstore_widget_private_api::UsbId()); - options.usb_id->vendor_id = vendor_id_; - options.usb_id->product_id = product_id_; - - extensions::EventRouter* event_router = - extensions::EventRouter::Get(browser_context_); - std::unique_ptr<extensions::Event> event(new extensions::Event( - extensions::events::WEBSTORE_WIDGET_PRIVATE_ON_SHOW_WIDGET, - webstore_widget_private_api::OnShowWidget::kEventName, - webstore_widget_private_api::OnShowWidget::Create(options))); - event_router->DispatchEventToExtension(extension_misc::kWebstoreWidgetAppId, - std::move(event)); - } - - private: - ~SearchPrinterAppNotificationDelegate() override = default; - - content::BrowserContext* browser_context_; - uint16_t vendor_id_; - std::string vendor_id_str_; - uint16_t product_id_; - std::string product_id_str_; - - DISALLOW_COPY_AND_ASSIGN(SearchPrinterAppNotificationDelegate); -}; - -// The PrinterDetector that initiates extension-based USB printer setup: -// -// * if there is a printer provider extension for a detected USB printer -// installed, it shows a notification informing the user the printer is ready to -// be used. -// -// * otherwise, it shows a notification offering the user an option to install a -// printer provider extension for the printer from the Chrome Web Store. -// -// TODO(justincarlson) - Remove this implementation when CUPS support is enabled -// by default. -class LegacyPrinterDetectorImpl : public PrinterDetector, - public device::UsbService::Observer { - public: - explicit LegacyPrinterDetectorImpl(Profile* profile) - : profile_(profile), - notification_ui_manager_(nullptr), - observer_(this), - weak_ptr_factory_(this) { - extensions::ExtensionSystem::Get(profile)->ready().Post( - FROM_HERE, base::Bind(&LegacyPrinterDetectorImpl::Initialize, - weak_ptr_factory_.GetWeakPtr())); - } - ~LegacyPrinterDetectorImpl() override = default; - - private: - // UsbService::observer override: - void OnDeviceAdded(scoped_refptr<device::UsbDevice> device) override { - const user_manager::User* user = - ProfileHelper::Get()->GetUserByProfile(profile_); - if (!user || !user->HasGaiaAccount() || !user_manager::UserManager::Get() || - user != user_manager::UserManager::Get()->GetActiveUser()) { - return; - } - - if (!UsbDeviceIsPrinter(*device)) { - return; - } - - if (notification_ui_manager_ == nullptr) { - notification_ui_manager_ = g_browser_process->notification_ui_manager(); - } - - UMA_HISTOGRAM_ENUMERATION("PrinterService.PrinterServiceEvent", - PRINTER_ADDED, PRINTER_SERVICE_EVENT_MAX); - ShowPrinterPluggedNotification(device); - } - - // Initializes the printer detector. - void Initialize() { - device::UsbService* usb_service = - device::DeviceClient::Get()->GetUsbService(); - if (!usb_service) - return; - observer_.Add(usb_service); - } - - void SetNotificationUIManagerForTesting( - NotificationUIManager* manager) override { - notification_ui_manager_ = manager; - } - - // Shows a notification for a plugged in printer. - // If there is a printerProvider app that handles the printer's USB - // (vendor_id, product_id) pair, the notification informs the user that the - // printer is ready to be used, otherwise it offers the user to search the - // Chrome Web Store for an app that can handle the printer. - void ShowPrinterPluggedNotification( - const scoped_refptr<device::UsbDevice>& device) { - ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); - std::unique_ptr<Notification> notification; - - const std::string kVendorIdStr = base::IntToString(device->vendor_id()); - const std::string kProductIdStr = base::IntToString(device->product_id()); - - if (HasAppThatSupportsPrinter(profile_, device)) { - UMA_HISTOGRAM_ENUMERATION("PrinterService.PrinterServiceEvent", - NOTIFICATION_SHOWN_PRINTER_SUPPORTED, - PRINTER_SERVICE_EVENT_MAX); - notification.reset(new Notification( - message_center::NOTIFICATION_TYPE_SIMPLE, - GetNotificationTitle(device->vendor_id(), device->product_id()), - l10n_util::GetStringUTF16( - IDS_PRINTER_DETECTED_NOTIFICATION_PRINT_APP_FOUND_BODY), - bundle.GetImageNamed(IDR_PRINTER_NOTIFICATION), - message_center::NotifierId( - message_center::NotifierId::SYSTEM_COMPONENT, - kPrinterProviderFoundNotificationID), - base::string16(), GURL(kPrinterProviderFoundNotificationID), - GetNotificationTag(kVendorIdStr, kProductIdStr), - message_center::RichNotificationData(), - new PrinterProviderExistsNotificationDelegate(kVendorIdStr, - kProductIdStr))); - } else { - UMA_HISTOGRAM_ENUMERATION("PrinterService.PrinterServiceEvent", - NOTIFICATION_SHOWN_PRINTER_NOT_SUPPORTED, - PRINTER_SERVICE_EVENT_MAX); - message_center::RichNotificationData options; - options.clickable = true; - notification.reset(new Notification( - message_center::NOTIFICATION_TYPE_SIMPLE, - GetNotificationTitle(device->vendor_id(), device->product_id()), - l10n_util::GetStringUTF16( - IDS_PRINTER_DETECTED_NOTIFICATION_NO_PRINT_APP_BODY), - bundle.GetImageNamed(IDR_PRINTER_NOTIFICATION), - message_center::NotifierId( - message_center::NotifierId::SYSTEM_COMPONENT, - kNoPrinterProviderNotificationID), - base::string16(), GURL(kNoPrinterProviderNotificationID), - GetNotificationTag(kVendorIdStr, kProductIdStr), options, - new SearchPrinterAppNotificationDelegate( - profile_, device->vendor_id(), kVendorIdStr, device->product_id(), - kProductIdStr))); - } - - notification->SetSystemPriority(); - notification_ui_manager_->Add(*notification, profile_); - } - - std::unique_ptr<Notification> notification_; - - Profile* profile_; - NotificationUIManager* notification_ui_manager_; - ScopedObserver<device::UsbService, device::UsbService::Observer> observer_; - base::WeakPtrFactory<LegacyPrinterDetectorImpl> weak_ptr_factory_; -}; - -} // namespace - -// static -std::unique_ptr<PrinterDetector> PrinterDetector::CreateLegacy( - Profile* profile) { - return base::MakeUnique<LegacyPrinterDetectorImpl>(profile); -} - -} // namespace chromeos
diff --git a/chrome/browser/chromeos/printer_detector/printer_detector.h b/chrome/browser/chromeos/printer_detector/printer_detector.h deleted file mode 100644 index 1789377..0000000 --- a/chrome/browser/chromeos/printer_detector/printer_detector.h +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_CHROMEOS_PRINTER_DETECTOR_PRINTER_DETECTOR_H_ -#define CHROME_BROWSER_CHROMEOS_PRINTER_DETECTOR_PRINTER_DETECTOR_H_ - -#include <memory> -#include <string> -#include <vector> - -#include "base/macros.h" -#include "chromeos/printing/printer_configuration.h" -#include "components/keyed_service/core/keyed_service.h" - -class NotificationUIManager; -class Profile; - -namespace chromeos { - -// Observes device::UsbService for addition of USB printers (devices with -// interface class 7). What it does with this depends on whether or not -// CUPS printing support is enabled. -// -// If CUPS is disabled, the Legacy implementation should be used. The legacy -// implementation shows a notification depending on whether there are printer -// provider apps that declared support for the USB device installed. If such -// app exists, the notification notifies the user the printer is ready. -// Otherwise the notification offers user to search Chrome Web Store for apps -// that support the printer. Clicking the notification launches webstore_widget -// app for the printer. The notification is shown only for active user's -// profile. -// -// If CUPS is enabled, the Cups implementation should be used. This -// implementation to guides the user through setting up a new USB printer in the -// CUPS backend. -class PrinterDetector : public KeyedService { - public: - class Observer { - public: - virtual ~Observer() = default; - - // The set of available printers has changed. - virtual void OnAvailableUsbPrintersChanged( - const std::vector<Printer>& printers) = 0; - }; - - // Factory function for the Legacy implementation. - static std::unique_ptr<PrinterDetector> CreateLegacy(Profile* profile); - - // Factory function for the CUPS implementation. - static std::unique_ptr<PrinterDetector> CreateCups(Profile* profile); - ~PrinterDetector() override {} - - // Observer management. Note these are only implemented for the cups backend. - // TODO(justincarlson) - Change these all to pure virtual functions when the - // legacy backend is retired. - - virtual void AddObserver(Observer* observer) {} - virtual void RemoveObserver(Observer* observer) {} - - // Get the current set of detected printers. - virtual std::vector<Printer> GetPrinters(); - - protected: - PrinterDetector() = default; - - private: - friend class PrinterDetectorAppSearchEnabledTest; - - virtual void SetNotificationUIManagerForTesting( - NotificationUIManager* manager) = 0; - - DISALLOW_COPY_AND_ASSIGN(PrinterDetector); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_PRINTER_DETECTOR_PRINTER_DETECTOR_H_
diff --git a/chrome/browser/chromeos/printer_detector/printer_detector_factory.cc b/chrome/browser/chromeos/printer_detector/printer_detector_factory.cc deleted file mode 100644 index 4e5dc707..0000000 --- a/chrome/browser/chromeos/printer_detector/printer_detector_factory.cc +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chromeos/printer_detector/printer_detector_factory.h" - -#include "base/command_line.h" -#include "chrome/browser/chromeos/printer_detector/printer_detector.h" -#include "chrome/browser/chromeos/printing/printers_manager_factory.h" -#include "chrome/browser/profiles/incognito_helpers.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/common/chrome_switches.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" -#include "extensions/browser/extensions_browser_client.h" - -namespace chromeos { - -namespace { - -static base::LazyInstance<PrinterDetectorFactory>::DestructorAtExit g_factory = - LAZY_INSTANCE_INITIALIZER; - -} // namespace - -// static -PrinterDetectorFactory* PrinterDetectorFactory::GetInstance() { - return g_factory.Pointer(); -} - -PrinterDetector* PrinterDetectorFactory::Get(content::BrowserContext* context) { - return static_cast<PrinterDetector*>( - GetServiceForBrowserContext(context, false)); -} - -PrinterDetectorFactory::PrinterDetectorFactory() - : BrowserContextKeyedServiceFactory( - "PrinterDetectorFactory", - BrowserContextDependencyManager::GetInstance()) { - DependsOn( - extensions::ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); - DependsOn(PrintersManagerFactory::GetInstance()); -} - -PrinterDetectorFactory::~PrinterDetectorFactory() { -} - -content::BrowserContext* PrinterDetectorFactory::GetBrowserContextToUse( - content::BrowserContext* context) const { - return chrome::GetBrowserContextRedirectedInIncognito(context); -} - -KeyedService* PrinterDetectorFactory::BuildServiceInstanceFor( - content::BrowserContext* context) const { - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - ::switches::kDisableNativeCups)) { - return PrinterDetector::CreateLegacy(Profile::FromBrowserContext(context)) - .release(); - } - - return PrinterDetector::CreateCups(Profile::FromBrowserContext(context)) - .release(); -} - -bool PrinterDetectorFactory::ServiceIsCreatedWithBrowserContext() const { - return true; -} - -bool PrinterDetectorFactory::ServiceIsNULLWhileTesting() const { - return true; -} - -} // namespace chromeos
diff --git a/chrome/browser/chromeos/printer_detector/printer_detector_factory.h b/chrome/browser/chromeos/printer_detector/printer_detector_factory.h deleted file mode 100644 index 39e69d2..0000000 --- a/chrome/browser/chromeos/printer_detector/printer_detector_factory.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_CHROMEOS_PRINTER_DETECTOR_PRINTER_DETECTOR_FACTORY_H_ -#define CHROME_BROWSER_CHROMEOS_PRINTER_DETECTOR_PRINTER_DETECTOR_FACTORY_H_ - -#include "base/lazy_instance.h" -#include "base/macros.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -#include "extensions/browser/extension_system_provider.h" - -namespace content { -class BrowserContext; -} - -namespace chromeos { - -class PrinterDetector; - -class PrinterDetectorFactory : public BrowserContextKeyedServiceFactory { - public: - static PrinterDetectorFactory* GetInstance(); - - PrinterDetector* Get(content::BrowserContext* context); - - protected: - // BrowserContextKeyedServiceFactory: - content::BrowserContext* GetBrowserContextToUse( - content::BrowserContext* context) const override; - - private: - friend struct base::LazyInstanceTraitsBase<PrinterDetectorFactory>; - PrinterDetectorFactory(); - ~PrinterDetectorFactory() override; - - // BrowserContextKeyedServiceFactory: - KeyedService* BuildServiceInstanceFor( - content::BrowserContext* browser_context) const override; - bool ServiceIsCreatedWithBrowserContext() const override; - bool ServiceIsNULLWhileTesting() const override; - - DISALLOW_COPY_AND_ASSIGN(PrinterDetectorFactory); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_PRINTER_DETECTOR_PRINTER_DETECTOR_FACTORY_H_
diff --git a/chrome/browser/chromeos/printer_detector/printer_detector_unittest.cc b/chrome/browser/chromeos/printer_detector/printer_detector_unittest.cc deleted file mode 100644 index 2c7f55c..0000000 --- a/chrome/browser/chromeos/printer_detector/printer_detector_unittest.cc +++ /dev/null
@@ -1,345 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chromeos/printer_detector/printer_detector.h" - -#include <stdint.h> - -#include <memory> -#include <utility> - -#include "base/macros.h" -#include "base/run_loop.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" -#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" -#include "chrome/browser/chromeos/printer_detector/printer_detector_factory.h" -#include "chrome/browser/chromeos/profiles/profile_helper.h" -#include "chrome/browser/extensions/test_extension_system.h" -#include "chrome/browser/notifications/notification.h" -#include "chrome/browser/notifications/notification_test_util.h" -#include "chrome/browser/notifications/notification_ui_manager.h" -#include "chrome/test/base/testing_profile.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "device/base/mock_device_client.h" -#include "device/usb/mock_usb_device.h" -#include "device/usb/mock_usb_service.h" -#include "device/usb/usb_descriptors.h" -#include "device/usb/usb_service.h" -#include "extensions/browser/extension_registry.h" -#include "extensions/common/extension_builder.h" -#include "extensions/common/value_builder.h" -#include "testing/gtest/include/gtest/gtest.h" - -using extensions::DictionaryBuilder; -using extensions::ListBuilder; - -namespace chromeos { - -namespace { - -const uint8_t kPrinterInterfaceClass = 7; - -const char kTestUserId[] = "test_user"; - -const char kPrinterAppExistsDelegateIDTemplate[] = - "system.printer.printer_provider_exists/%s:%s"; - -const char kPrinterAppNotFoundDelegateIDTemplate[] = - "system.printer.no_printer_provider_found/%s:%s"; - -std::unique_ptr<KeyedService> CreatePrinterDetector( - content::BrowserContext* context) { - return PrinterDetector::CreateLegacy(Profile::FromBrowserContext(context)); -} - -} // namespace - -// TODO(tbarzic): Rename this test. -class PrinterDetectorAppSearchEnabledTest : public testing::Test { - public: - PrinterDetectorAppSearchEnabledTest() - : user_manager_(new chromeos::FakeChromeUserManager()), - user_manager_enabler_(user_manager_) {} - - ~PrinterDetectorAppSearchEnabledTest() override = default; - - void SetUp() override { - device_client_.GetUsbService(); - // Make sure the profile is created after adding the switch and setting up - // device client. - profile_.reset(new TestingProfile()); - chromeos::PrinterDetectorFactory::GetInstance()->SetTestingFactoryAndUse( - profile_.get(), &CreatePrinterDetector); - AddTestUser(); - SetExtensionSystemReady(profile_.get()); - } - - protected: - void SetExtensionSystemReady(TestingProfile* profile) { - extensions::TestExtensionSystem* test_extension_system = - static_cast<extensions::TestExtensionSystem*>( - extensions::ExtensionSystem::Get(profile)); - test_extension_system->SetReady(); - base::RunLoop().RunUntilIdle(); - } - - void AddTestUser() { - const user_manager::User* user = - user_manager_->AddUser(AccountId::FromUserEmail(kTestUserId)); - profile_->set_profile_name(kTestUserId); - chromeos::ProfileHelper::Get()->SetUserToProfileMappingForTesting( - user, profile_.get()); - chromeos::PrinterDetectorFactory::GetInstance() - ->Get(profile_.get()) - ->SetNotificationUIManagerForTesting(¬ification_ui_manager_); - } - - void InvokeUsbAdded(uint16_t vendor_id, - uint16_t product_id, - uint8_t interface_class) { - device::UsbConfigDescriptor config(1, false, false, 0); - config.interfaces.emplace_back(1, 0, interface_class, 0, 0); - device_client_.usb_service()->AddDevice( - new device::MockUsbDevice(vendor_id, product_id, config)); - } - - // Creates a test extension with the provided permissions. - scoped_refptr<extensions::Extension> CreateTestExtension( - std::unique_ptr<base::ListValue> permissions_builder, - std::unique_ptr<base::DictionaryValue> usb_printers_builder) { - return extensions::ExtensionBuilder() - .SetID("fake_extension_id") - .SetManifest( - DictionaryBuilder() - .Set("name", "Printer provider extension") - .Set("manifest_version", 2) - .Set("version", "1.0") - // Needed to enable usb API. - .Set("app", - DictionaryBuilder() - .Set("background", - DictionaryBuilder() - .Set("scripts", - ListBuilder().Append("bg.js").Build()) - .Build()) - .Build()) - .Set("permissions", std::move(permissions_builder)) - .Set("usb_printers", std::move(usb_printers_builder)) - .Build()) - .Build(); - } - - content::TestBrowserThreadBundle thread_bundle_; - StubNotificationUIManager notification_ui_manager_; - chromeos::FakeChromeUserManager* user_manager_; - chromeos::ScopedUserManagerEnabler user_manager_enabler_; - device::MockDeviceClient device_client_; - std::unique_ptr<TestingProfile> profile_; - - private: - DISALLOW_COPY_AND_ASSIGN(PrinterDetectorAppSearchEnabledTest); -}; - -TEST_F(PrinterDetectorAppSearchEnabledTest, ShowFindAppNotification) { - InvokeUsbAdded(123, 456, kPrinterInterfaceClass); - - ASSERT_EQ(1u, notification_ui_manager_.GetNotificationCount()); - const Notification& notification = - notification_ui_manager_.GetNotificationAt(0); - EXPECT_EQ("123:456", notification.tag()); - EXPECT_EQ( - base::StringPrintf(kPrinterAppNotFoundDelegateIDTemplate, "123", "456"), - notification.delegate_id()); -} - -TEST_F(PrinterDetectorAppSearchEnabledTest, ShowAppFoundNotification) { - scoped_refptr<extensions::Extension> extension = CreateTestExtension( - ListBuilder() - .Append("usb") - .Append("printerProvider") - .Append(DictionaryBuilder() - .Set("usbDevices", ListBuilder() - .Append(DictionaryBuilder() - .Set("vendorId", 123) - .Set("productId", 456) - .Build()) - .Build()) - .Build()) - .Build(), - DictionaryBuilder().Set("filters", ListBuilder().Build()).Build()); - ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_.get()) - ->AddEnabled(extension)); - - InvokeUsbAdded(123, 456, kPrinterInterfaceClass); - - ASSERT_EQ(1u, notification_ui_manager_.GetNotificationCount()); - const Notification& notification = - notification_ui_manager_.GetNotificationAt(0); - EXPECT_EQ("123:456", notification.tag()); - EXPECT_EQ( - base::StringPrintf(kPrinterAppExistsDelegateIDTemplate, "123", "456"), - notification.delegate_id()); -} - -TEST_F(PrinterDetectorAppSearchEnabledTest, - UsbHandlerExists_NotPrinterProvider) { - scoped_refptr<extensions::Extension> extension = CreateTestExtension( - ListBuilder() - .Append("usb") - .Append(DictionaryBuilder() - .Set("usbDevices", ListBuilder() - .Append(DictionaryBuilder() - .Set("vendorId", 123) - .Set("productId", 756) - .Build()) - .Build()) - .Build()) - .Build(), - DictionaryBuilder().Set("filters", ListBuilder().Build()).Build()); - ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_.get()) - ->AddEnabled(extension)); - - InvokeUsbAdded(123, 756, kPrinterInterfaceClass); - - ASSERT_EQ(1u, notification_ui_manager_.GetNotificationCount()); - const Notification& notification = - notification_ui_manager_.GetNotificationAt(0); - EXPECT_EQ("123:756", notification.tag()); - EXPECT_EQ( - base::StringPrintf(kPrinterAppNotFoundDelegateIDTemplate, "123", "756"), - notification.delegate_id()); -} - -TEST_F(PrinterDetectorAppSearchEnabledTest, - PrinterProvider_DifferentUsbProductId) { - scoped_refptr<extensions::Extension> extension = CreateTestExtension( - ListBuilder() - .Append("usb") - .Append("printerProvider") - .Append(DictionaryBuilder() - .Set("usbDevices", ListBuilder() - .Append(DictionaryBuilder() - .Set("vendorId", 123) - .Set("productId", 001) - .Build()) - .Build()) - .Build()) - .Build(), - DictionaryBuilder().Set("filters", ListBuilder().Build()).Build()); - ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_.get()) - ->AddEnabled(extension)); - - InvokeUsbAdded(123, 456, kPrinterInterfaceClass); - - ASSERT_EQ(1u, notification_ui_manager_.GetNotificationCount()); - const Notification& notification = - notification_ui_manager_.GetNotificationAt(0); - EXPECT_EQ("123:456", notification.tag()); - EXPECT_EQ( - base::StringPrintf(kPrinterAppNotFoundDelegateIDTemplate, "123", "456"), - notification.delegate_id()); -} - -TEST_F(PrinterDetectorAppSearchEnabledTest, - PrinterProvider_UsbPrinters_NotFound) { - scoped_refptr<extensions::Extension> extension = CreateTestExtension( - ListBuilder().Append("usb").Append("printerProvider").Build(), - DictionaryBuilder() - .Set("filters", ListBuilder() - .Append(DictionaryBuilder() - .Set("vendorId", 123) - .Set("productId", 001) - .Build()) - .Build()) - .Build()); - ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_.get()) - ->AddEnabled(extension)); - - InvokeUsbAdded(123, 456, kPrinterInterfaceClass); - - ASSERT_EQ(1u, notification_ui_manager_.GetNotificationCount()); - const Notification& notification = - notification_ui_manager_.GetNotificationAt(0); - EXPECT_EQ("123:456", notification.tag()); - EXPECT_EQ( - base::StringPrintf(kPrinterAppNotFoundDelegateIDTemplate, "123", "456"), - notification.delegate_id()); -} - -TEST_F(PrinterDetectorAppSearchEnabledTest, - PrinterProvider_UsbPrinters_WithProductId) { - scoped_refptr<extensions::Extension> extension = CreateTestExtension( - ListBuilder().Append("usb").Append("printerProvider").Build(), - DictionaryBuilder() - .Set("filters", ListBuilder() - .Append(DictionaryBuilder() - .Set("vendorId", 123) - .Set("productId", 456) - .Build()) - .Build()) - .Build()); - ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_.get()) - ->AddEnabled(extension)); - - InvokeUsbAdded(123, 456, kPrinterInterfaceClass); - - ASSERT_EQ(1u, notification_ui_manager_.GetNotificationCount()); - const Notification& notification = - notification_ui_manager_.GetNotificationAt(0); - EXPECT_EQ("123:456", notification.tag()); - EXPECT_EQ( - base::StringPrintf(kPrinterAppExistsDelegateIDTemplate, "123", "456"), - notification.delegate_id()); -} - -TEST_F(PrinterDetectorAppSearchEnabledTest, - PrinterProvider_UsbPrinters_WithInterfaceClass) { - scoped_refptr<extensions::Extension> extension = CreateTestExtension( - ListBuilder().Append("usb").Append("printerProvider").Build(), - DictionaryBuilder() - .Set("filters", - ListBuilder() - .Append(DictionaryBuilder() - .Set("vendorId", 123) - .Set("interfaceClass", kPrinterInterfaceClass) - .Build()) - .Build()) - .Build()); - ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_.get()) - ->AddEnabled(extension)); - - InvokeUsbAdded(123, 456, kPrinterInterfaceClass); - - ASSERT_EQ(1u, notification_ui_manager_.GetNotificationCount()); - const Notification& notification = - notification_ui_manager_.GetNotificationAt(0); - EXPECT_EQ("123:456", notification.tag()); - EXPECT_EQ( - base::StringPrintf(kPrinterAppExistsDelegateIDTemplate, "123", "456"), - notification.delegate_id()); -} - -TEST_F(PrinterDetectorAppSearchEnabledTest, IgnoreNonPrinters) { - scoped_refptr<extensions::Extension> extension = CreateTestExtension( - ListBuilder().Append("usb").Append("printerProvider").Build(), - DictionaryBuilder() - .Set("filters", - ListBuilder() - .Append(DictionaryBuilder() - .Set("vendorId", 123) - .Set("interfaceClass", kPrinterInterfaceClass) - .Build()) - .Build()) - .Build()); - ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_.get()) - ->AddEnabled(extension)); - - InvokeUsbAdded(123, 456, 1); - - ASSERT_EQ(0u, notification_ui_manager_.GetNotificationCount()); -} - -} // namespace chromeos
diff --git a/chrome/browser/chromeos/printer_detector/cups_printer_detector.cc b/chrome/browser/chromeos/printer_detector/usb_printer_detector.cc similarity index 87% rename from chrome/browser/chromeos/printer_detector/cups_printer_detector.cc rename to chrome/browser/chromeos/printer_detector/usb_printer_detector.cc index 00168bb..88e06a3a 100644 --- a/chrome/browser/chromeos/printer_detector/cups_printer_detector.cc +++ b/chrome/browser/chromeos/printer_detector/usb_printer_detector.cc
@@ -4,7 +4,9 @@ #include <stdint.h> +#include <map> #include <memory> +#include <set> #include <utility> #include <vector> @@ -18,7 +20,7 @@ #include "base/synchronization/lock.h" #include "base/threading/sequenced_task_runner_handle.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/printer_detector/printer_detector.h" +#include "chrome/browser/chromeos/printer_detector/usb_printer_detector.h" #include "chrome/browser/chromeos/printing/ppd_provider_factory.h" #include "chrome/browser/chromeos/printing/printer_configurer.h" #include "chrome/browser/chromeos/printing/printers_manager_factory.h" @@ -30,7 +32,6 @@ #include "content/public/browser/browser_thread.h" #include "device/base/device_client.h" #include "device/usb/usb_device.h" -#include "device/usb/usb_device_filter.h" #include "device/usb/usb_service.h" namespace chromeos { @@ -71,32 +72,32 @@ // The PrinterDetector that drives the flow for setting up a USB printer to use // CUPS backend. -class CupsPrinterDetectorImpl : public PrinterDetector, - public device::UsbService::Observer { +class UsbPrinterDetectorImpl : public UsbPrinterDetector, + public device::UsbService::Observer { public: - explicit CupsPrinterDetectorImpl(Profile* profile) + explicit UsbPrinterDetectorImpl(Profile* profile) : profile_(profile), usb_observer_(this), observer_list_( - new base::ObserverListThreadSafe<PrinterDetector::Observer>), + new base::ObserverListThreadSafe<UsbPrinterDetector::Observer>), weak_ptr_factory_(this) { device::UsbService* usb_service = device::DeviceClient::Get()->GetUsbService(); if (usb_service) { usb_observer_.Add(usb_service); - usb_service->GetDevices(base::Bind(&CupsPrinterDetectorImpl::OnGetDevices, + usb_service->GetDevices(base::Bind(&UsbPrinterDetectorImpl::OnGetDevices, weak_ptr_factory_.GetWeakPtr())); } } - ~CupsPrinterDetectorImpl() override = default; + ~UsbPrinterDetectorImpl() override = default; // PrinterDetector interface function. - void AddObserver(PrinterDetector::Observer* observer) override { + void AddObserver(UsbPrinterDetector::Observer* observer) override { observer_list_->AddObserver(observer); } // PrinterDetector interface function. - void RemoveObserver(PrinterDetector::Observer* observer) override { + void RemoveObserver(UsbPrinterDetector::Observer* observer) override { observer_list_->RemoveObserver(observer); } @@ -146,7 +147,8 @@ // We already have pp_lock_, so need to call the pre-locked version of // GetPrinters to prevent deadlock. observer_list_->Notify( - FROM_HERE, &PrinterDetector::Observer::OnAvailableUsbPrintersChanged, + FROM_HERE, + &UsbPrinterDetector::Observer::OnAvailableUsbPrintersChanged, GetPrintersLocked()); } else { // If the device has been removed but it's not in present_printers_, it @@ -203,7 +205,7 @@ printing::CreateProvider(profile_); ppd_provider->ResolveUsbIds( device->vendor_id(), device->product_id(), - base::Bind(&CupsPrinterDetectorImpl::ResolveUsbIdsDone, + base::Bind(&UsbPrinterDetectorImpl::ResolveUsbIdsDone, weak_ptr_factory_.GetWeakPtr(), ppd_provider, base::Passed(std::move(data)))); } @@ -214,7 +216,7 @@ SetUpPrinterData* data_ptr = data.get(); data_ptr->configurer->SetUpPrinter( *(data_ptr->printer), - base::Bind(&CupsPrinterDetectorImpl::SetUpPrinterDone, + base::Bind(&UsbPrinterDetectorImpl::SetUpPrinterDone, weak_ptr_factory_.GetWeakPtr(), base::Passed(std::move(data)))); } @@ -273,16 +275,12 @@ base::AutoLock auto_lock(pp_lock_); present_printers_.emplace(data->device->guid(), std::move(data->printer)); observer_list_->Notify( - FROM_HERE, &PrinterDetector::Observer::OnAvailableUsbPrintersChanged, + FROM_HERE, + &UsbPrinterDetector::Observer::OnAvailableUsbPrintersChanged, GetPrintersLocked()); } } - void SetNotificationUIManagerForTesting( - NotificationUIManager* manager) override { - LOG(FATAL) << "Not implemented for CUPS"; - } - // Map from USB GUID to Printer that we have detected as being currently // plugged in and have finished processing. Note present_printers_ may be // accessed from multiple threads, so is protected by pp_lock_. @@ -297,22 +295,17 @@ Profile* profile_; ScopedObserver<device::UsbService, device::UsbService::Observer> usb_observer_; - scoped_refptr<base::ObserverListThreadSafe<PrinterDetector::Observer>> + scoped_refptr<base::ObserverListThreadSafe<UsbPrinterDetector::Observer>> observer_list_; - base::WeakPtrFactory<CupsPrinterDetectorImpl> weak_ptr_factory_; + base::WeakPtrFactory<UsbPrinterDetectorImpl> weak_ptr_factory_; }; } // namespace -// Nop base class implementation of GetPrinters(). Because this is non-empty we -// have to define it out-of-line. -std::vector<Printer> PrinterDetector::GetPrinters() { - return std::vector<Printer>(); -} - // static -std::unique_ptr<PrinterDetector> PrinterDetector::CreateCups(Profile* profile) { - return base::MakeUnique<CupsPrinterDetectorImpl>(profile); +std::unique_ptr<UsbPrinterDetector> UsbPrinterDetector::Create( + Profile* profile) { + return base::MakeUnique<UsbPrinterDetectorImpl>(profile); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/printer_detector/usb_printer_detector.h b/chrome/browser/chromeos/printer_detector/usb_printer_detector.h new file mode 100644 index 0000000..b7e7ad5 --- /dev/null +++ b/chrome/browser/chromeos/printer_detector/usb_printer_detector.h
@@ -0,0 +1,53 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_PRINTER_DETECTOR_USB_PRINTER_DETECTOR_H_ +#define CHROME_BROWSER_CHROMEOS_PRINTER_DETECTOR_USB_PRINTER_DETECTOR_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "chromeos/printing/printer_configuration.h" +#include "components/keyed_service/core/keyed_service.h" + +class Profile; + +namespace chromeos { + +// Observes device::UsbService for addition of USB printers (devices with +// interface class 7). When a device is detected, it is forwarded to the +// printing subsystem for either autoconfiguration or user guidance. +class UsbPrinterDetector : public KeyedService { + public: + class Observer { + public: + virtual ~Observer() = default; + + // The set of available printers has changed. + virtual void OnAvailableUsbPrintersChanged( + const std::vector<Printer>& printers) = 0; + }; + + // Factory function for the CUPS implementation. + static std::unique_ptr<UsbPrinterDetector> Create(Profile* profile); + ~UsbPrinterDetector() override = default; + + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Get the current set of detected printers. + virtual std::vector<Printer> GetPrinters() = 0; + + protected: + UsbPrinterDetector() = default; + + private: + DISALLOW_COPY_AND_ASSIGN(UsbPrinterDetector); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_PRINTER_DETECTOR_USB_PRINTER_DETECTOR_H_
diff --git a/chrome/browser/chromeos/printer_detector/usb_printer_detector_factory.cc b/chrome/browser/chromeos/printer_detector/usb_printer_detector_factory.cc new file mode 100644 index 0000000..66047b65 --- /dev/null +++ b/chrome/browser/chromeos/printer_detector/usb_printer_detector_factory.cc
@@ -0,0 +1,66 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/printer_detector/usb_printer_detector_factory.h" + +#include "base/command_line.h" +#include "chrome/browser/chromeos/printer_detector/usb_printer_detector.h" +#include "chrome/browser/chromeos/printing/printers_manager_factory.h" +#include "chrome/browser/profiles/incognito_helpers.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/chrome_switches.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "extensions/browser/extensions_browser_client.h" + +namespace chromeos { + +namespace { + +base::LazyInstance<UsbPrinterDetectorFactory>::DestructorAtExit g_factory = + LAZY_INSTANCE_INITIALIZER; + +} // namespace + +// static +UsbPrinterDetectorFactory* UsbPrinterDetectorFactory::GetInstance() { + return g_factory.Pointer(); +} + +UsbPrinterDetector* UsbPrinterDetectorFactory::Get( + content::BrowserContext* context) { + return static_cast<UsbPrinterDetector*>( + GetServiceForBrowserContext(context, false)); +} + +UsbPrinterDetectorFactory::UsbPrinterDetectorFactory() + : BrowserContextKeyedServiceFactory( + "UsbPrinterDetectorFactory", + BrowserContextDependencyManager::GetInstance()) { + DependsOn( + extensions::ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); + DependsOn(PrintersManagerFactory::GetInstance()); +} + +UsbPrinterDetectorFactory::~UsbPrinterDetectorFactory() {} + +content::BrowserContext* UsbPrinterDetectorFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + return chrome::GetBrowserContextRedirectedInIncognito(context); +} + +KeyedService* UsbPrinterDetectorFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return UsbPrinterDetector::Create(Profile::FromBrowserContext(context)) + .release(); +} + +bool UsbPrinterDetectorFactory::ServiceIsCreatedWithBrowserContext() const { + return true; +} + +bool UsbPrinterDetectorFactory::ServiceIsNULLWhileTesting() const { + return true; +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/printer_detector/usb_printer_detector_factory.h b/chrome/browser/chromeos/printer_detector/usb_printer_detector_factory.h new file mode 100644 index 0000000..68f1e6a --- /dev/null +++ b/chrome/browser/chromeos/printer_detector/usb_printer_detector_factory.h
@@ -0,0 +1,48 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_PRINTER_DETECTOR_USB_PRINTER_DETECTOR_FACTORY_H_ +#define CHROME_BROWSER_CHROMEOS_PRINTER_DETECTOR_USB_PRINTER_DETECTOR_FACTORY_H_ + +#include "base/lazy_instance.h" +#include "base/macros.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include "extensions/browser/extension_system_provider.h" + +namespace content { +class BrowserContext; +} + +namespace chromeos { + +class UsbPrinterDetector; + +class UsbPrinterDetectorFactory : public BrowserContextKeyedServiceFactory { + public: + static UsbPrinterDetectorFactory* GetInstance(); + + UsbPrinterDetector* Get(content::BrowserContext* context); + + protected: + // BrowserContextKeyedServiceFactory: + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; + + private: + friend struct base::LazyInstanceTraitsBase<UsbPrinterDetectorFactory>; + UsbPrinterDetectorFactory(); + ~UsbPrinterDetectorFactory() override; + + // BrowserContextKeyedServiceFactory: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* browser_context) const override; + bool ServiceIsCreatedWithBrowserContext() const override; + bool ServiceIsNULLWhileTesting() const override; + + DISALLOW_COPY_AND_ASSIGN(UsbPrinterDetectorFactory); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_PRINTER_DETECTOR_USB_PRINTER_DETECTOR_FACTORY_H_
diff --git a/chrome/browser/chromeos/printing/printer_discoverer.cc b/chrome/browser/chromeos/printing/printer_discoverer.cc index 6781249..cfa53df 100644 --- a/chrome/browser/chromeos/printing/printer_discoverer.cc +++ b/chrome/browser/chromeos/printing/printer_discoverer.cc
@@ -10,8 +10,8 @@ #include "base/observer_list.h" #include "base/scoped_observer.h" #include "base/threading/sequenced_task_runner_handle.h" -#include "chrome/browser/chromeos/printer_detector/printer_detector.h" -#include "chrome/browser/chromeos/printer_detector/printer_detector_factory.h" +#include "chrome/browser/chromeos/printer_detector/usb_printer_detector.h" +#include "chrome/browser/chromeos/printer_detector/usb_printer_detector_factory.h" #include "chrome/browser/chromeos/printing/printers_manager.h" #include "chrome/browser/chromeos/printing/printers_manager_factory.h" #include "chrome/browser/profiles/profile.h" @@ -22,15 +22,15 @@ // Implementation of PrinterDiscoverer interface. class PrinterDiscovererImpl : public PrinterDiscoverer, - public PrinterDetector::Observer { + public UsbPrinterDetector::Observer { public: explicit PrinterDiscovererImpl(Profile* profile) : detector_observer_(this), profile_(profile), weak_ptr_factory_(this) { - PrinterDetector* detector = - PrinterDetectorFactory::GetInstance()->Get(profile); - DCHECK(detector); - detector_observer_.Add(detector); - usb_printers_ = detector->GetPrinters(); + UsbPrinterDetector* usb_detector = + UsbPrinterDetectorFactory::GetInstance()->Get(profile); + DCHECK(usb_detector); + detector_observer_.Add(usb_detector); + usb_printers_ = usb_detector->GetPrinters(); } ~PrinterDiscovererImpl() override = default; @@ -103,7 +103,8 @@ std::vector<Printer> usb_printers_; base::ObserverList<PrinterDiscoverer::Observer> observer_list_; - ScopedObserver<PrinterDetector, PrinterDetector::Observer> detector_observer_; + ScopedObserver<UsbPrinterDetector, UsbPrinterDetector::Observer> + detector_observer_; Profile* profile_; base::WeakPtrFactory<PrinterDiscovererImpl> weak_ptr_factory_; };
diff --git a/chrome/browser/chromeos/printing/usb_printer_util.cc b/chrome/browser/chromeos/printing/usb_printer_util.cc index 2221fcc..28ae5c1 100644 --- a/chrome/browser/chromeos/printing/usb_printer_util.cc +++ b/chrome/browser/chromeos/printing/usb_printer_util.cc
@@ -16,8 +16,9 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "chromeos/printing/printer_configuration.h" +#include "device/usb/public/cpp/filter_utils.h" +#include "device/usb/public/interfaces/device_manager.mojom.h" #include "device/usb/usb_device.h" -#include "device/usb/usb_device_filter.h" #include "ui/base/l10n/l10n_util.h" namespace chromeos { @@ -112,9 +113,10 @@ } // namespace bool UsbDeviceIsPrinter(const device::UsbDevice& usb_device) { - device::UsbDeviceFilter printer_filter; - printer_filter.interface_class = kPrinterInterfaceClass; - return printer_filter.Matches(usb_device); + auto printer_filter = device::mojom::UsbDeviceFilter::New(); + printer_filter->has_class_code = true; + printer_filter->class_code = kPrinterInterfaceClass; + return UsbDeviceFilterMatches(*printer_filter, usb_device); } std::string UsbPrinterDeviceDetailsAsString(const device::UsbDevice& device) {
diff --git a/chrome/browser/devtools/devtools_file_helper.cc b/chrome/browser/devtools/devtools_file_helper.cc index 463cedea..7fd7f1cc 100644 --- a/chrome/browser/devtools/devtools_file_helper.cc +++ b/chrome/browser/devtools/devtools_file_helper.cc
@@ -15,6 +15,8 @@ #include "base/md5.h" #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/task_scheduler/post_task.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/value_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/devtools/devtools_file_watcher.h" @@ -120,14 +122,14 @@ }; void WriteToFile(const base::FilePath& path, const std::string& content) { - DCHECK_CURRENTLY_ON(BrowserThread::FILE); + base::ThreadRestrictions::AssertIOAllowed(); DCHECK(!path.empty()); base::WriteFile(path, content.c_str(), content.length()); } void AppendToFile(const base::FilePath& path, const std::string& content) { - DCHECK_CURRENTLY_ON(BrowserThread::FILE); + base::ThreadRestrictions::AssertIOAllowed(); DCHECK(!path.empty()); base::AppendToFile(path, content.c_str(), content.size()); @@ -210,14 +212,13 @@ : web_contents_(web_contents), profile_(profile), delegate_(delegate), + file_task_runner_( + base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()})), weak_factory_(this) { pref_change_registrar_.Init(profile_->GetPrefs()); } -DevToolsFileHelper::~DevToolsFileHelper() { - BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, - file_watcher_.release()); -} +DevToolsFileHelper::~DevToolsFileHelper() = default; void DevToolsFileHelper::Save(const std::string& url, const std::string& content, @@ -275,8 +276,8 @@ if (it == saved_files_.end()) return; callback.Run(); - BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, - BindOnce(&AppendToFile, it->second, content)); + file_task_runner_->PostTask(FROM_HERE, + BindOnce(&AppendToFile, it->second, content)); } void DevToolsFileHelper::SaveAsFileSelected(const std::string& url, @@ -292,8 +293,7 @@ files_map->SetWithoutPathExpansion(base::MD5String(url), base::CreateFilePathValue(path)); callback.Run(); - BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, - BindOnce(&WriteToFile, path, content)); + file_task_runner_->PostTask(FROM_HERE, BindOnce(&WriteToFile, path, content)); } void DevToolsFileHelper::AddFileSystem( @@ -308,23 +308,25 @@ select_file_dialog->Show(ui::SelectFileDialog::SELECT_FOLDER, base::FilePath()); } else { - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, + file_task_runner_->PostTask( + FROM_HERE, BindOnce(&DevToolsFileHelper::CheckProjectFileExistsAndAddFileSystem, weak_factory_.GetWeakPtr(), show_info_bar_callback, base::FilePath::FromUTF8Unsafe(file_system_path))); } } +// static void DevToolsFileHelper::CheckProjectFileExistsAndAddFileSystem( - const ShowInfoBarCallback& show_info_bar_callback, - const base::FilePath& path) { - DCHECK_CURRENTLY_ON(BrowserThread::FILE); + base::WeakPtr<DevToolsFileHelper> self, + ShowInfoBarCallback show_info_bar_callback, + base::FilePath path) { + base::ThreadRestrictions::AssertIOAllowed(); if (base::PathExists(path.Append(FILE_PATH_LITERAL(".devtools")))) { BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - BindOnce(&DevToolsFileHelper::InnerAddFileSystem, - weak_factory_.GetWeakPtr(), show_info_bar_callback, path)); + BindOnce(&DevToolsFileHelper::InnerAddFileSystem, std::move(self), + std::move(show_info_bar_callback), path)); } } @@ -387,8 +389,10 @@ file_system_paths_ = GetAddedFileSystemPaths(profile_); std::vector<FileSystem> file_systems; if (!file_watcher_) { - file_watcher_.reset(new DevToolsFileWatcher(base::Bind( - &DevToolsFileHelper::FilePathsChanged, weak_factory_.GetWeakPtr()))); + file_watcher_.reset(new DevToolsFileWatcher( + base::Bind(&DevToolsFileHelper::FilePathsChanged, + weak_factory_.GetWeakPtr()), + base::SequencedTaskRunnerHandle::Get())); pref_change_registrar_.Add( prefs::kDevToolsFileSystemPaths, base::Bind(&DevToolsFileHelper::FileSystemPathsSettingChanged, @@ -401,10 +405,7 @@ file_system_id, file_system_path); file_systems.push_back(filesystem); - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - BindOnce(&DevToolsFileWatcher::AddWatch, - base::Unretained(file_watcher_.get()), path)); + file_watcher_->AddWatch(std::move(path)); } return file_systems; } @@ -440,10 +441,7 @@ file_system_id, file_system_path); delegate_->FileSystemAdded(filesystem); - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - BindOnce(&DevToolsFileWatcher::AddWatch, - base::Unretained(file_watcher_.get()), path)); + file_watcher_->AddWatch(std::move(path)); } else { remaining.erase(file_system_path); } @@ -453,10 +451,7 @@ for (auto file_system_path : remaining) { delegate_->FileSystemRemoved(file_system_path); base::FilePath path = base::FilePath::FromUTF8Unsafe(file_system_path); - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - BindOnce(&DevToolsFileWatcher::RemoveWatch, - base::Unretained(file_watcher_.get()), path)); + file_watcher_->RemoveWatch(std::move(path)); } }
diff --git a/chrome/browser/devtools/devtools_file_helper.h b/chrome/browser/devtools/devtools_file_helper.h index e613d02..cb37572 100644 --- a/chrome/browser/devtools/devtools_file_helper.h +++ b/chrome/browser/devtools/devtools_file_helper.h
@@ -16,13 +16,14 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" +#include "chrome/browser/devtools/devtools_file_watcher.h" #include "components/prefs/pref_change_registrar.h" -class DevToolsFileWatcher; class Profile; namespace base { class FilePath; +class SequencedTaskRunner; } namespace content { @@ -128,9 +129,6 @@ void InnerAddFileSystem( const ShowInfoBarCallback& show_info_bar_callback, const base::FilePath& path); - void CheckProjectFileExistsAndAddFileSystem( - const ShowInfoBarCallback& show_info_bar_callback, - const base::FilePath& path); void AddUserConfirmedFileSystem( const base::FilePath& path, bool allowed); @@ -139,6 +137,12 @@ const std::vector<std::string>& added_paths, const std::vector<std::string>& removed_paths); + // This should only be called on the file sequence. + static void CheckProjectFileExistsAndAddFileSystem( + base::WeakPtr<DevToolsFileHelper> self, + ShowInfoBarCallback show_info_bar_callback, + base::FilePath path); + content::WebContents* web_contents_; Profile* profile_; DevToolsFileHelper::Delegate* delegate_; @@ -146,7 +150,9 @@ PathsMap saved_files_; PrefChangeRegistrar pref_change_registrar_; std::set<std::string> file_system_paths_; - std::unique_ptr<DevToolsFileWatcher> file_watcher_; + std::unique_ptr<DevToolsFileWatcher, DevToolsFileWatcher::Deleter> + file_watcher_; + scoped_refptr<base::SequencedTaskRunner> file_task_runner_; base::WeakPtrFactory<DevToolsFileHelper> weak_factory_; DISALLOW_COPY_AND_ASSIGN(DevToolsFileHelper); };
diff --git a/chrome/browser/devtools/devtools_file_watcher.cc b/chrome/browser/devtools/devtools_file_watcher.cc index e97ef21..1f0f1bd 100644 --- a/chrome/browser/devtools/devtools_file_watcher.cc +++ b/chrome/browser/devtools/devtools_file_watcher.cc
@@ -15,6 +15,9 @@ #include "base/files/file_path_watcher.h" #include "base/files/file_util.h" #include "base/memory/ref_counted.h" +#include "base/sequenced_task_runner.h" +#include "base/task_scheduler/lazy_task_runner.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "content/public/browser/browser_thread.h" using content::BrowserThread; @@ -51,6 +54,7 @@ std::set<base::FilePath> pending_paths_; base::Time last_event_time_; base::TimeDelta last_dispatch_cost_; + SEQUENCE_CHECKER(sequence_checker_); }; DevToolsFileWatcher::SharedFileWatcher::SharedFileWatcher() @@ -60,22 +64,26 @@ } DevToolsFileWatcher::SharedFileWatcher::~SharedFileWatcher() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DevToolsFileWatcher::s_shared_watcher_ = nullptr; } void DevToolsFileWatcher::SharedFileWatcher::AddListener( DevToolsFileWatcher* watcher) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); listeners_.push_back(watcher); } void DevToolsFileWatcher::SharedFileWatcher::RemoveListener( DevToolsFileWatcher* watcher) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto it = std::find(listeners_.begin(), listeners_.end(), watcher); listeners_.erase(it); } void DevToolsFileWatcher::SharedFileWatcher::AddWatch( const base::FilePath& path) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (watchers_.find(path) != watchers_.end()) return; if (!base::FilePathWatcher::RecursiveWatchAvailable()) @@ -104,13 +112,14 @@ void DevToolsFileWatcher::SharedFileWatcher::RemoveWatch( const base::FilePath& path) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); watchers_.erase(path); } void DevToolsFileWatcher::SharedFileWatcher::DirectoryChanged( const base::FilePath& path, bool error) { - DCHECK_CURRENTLY_ON(BrowserThread::FILE); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); pending_paths_.insert(path); if (pending_paths_.size() > 1) return; // PostDelayedTask is already pending. @@ -122,8 +131,8 @@ base::TimeDelta::FromMilliseconds(kFirstThrottleTimeout) : last_dispatch_cost_ * 2; - BrowserThread::PostDelayedTask( - BrowserThread::FILE, FROM_HERE, + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, base::BindOnce( &DevToolsFileWatcher::SharedFileWatcher::DispatchNotifications, this), shedule_for); @@ -131,6 +140,7 @@ } void DevToolsFileWatcher::SharedFileWatcher::DispatchNotifications() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!pending_paths_.size()) return; base::Time start = base::Time::Now(); @@ -160,30 +170,49 @@ pending_paths_.clear(); for (auto* watcher : listeners_) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::BindOnce(watcher->callback_, changed_paths, - added_paths, removed_paths)); + watcher->client_task_runner_->PostTask( + FROM_HERE, base::BindOnce(watcher->callback_, changed_paths, + added_paths, removed_paths)); } last_dispatch_cost_ = base::Time::Now() - start; } +// DevToolsFileWatcher --------------------------------------------------------- + +namespace { +base::SequencedTaskRunner* impl_task_runner() { + constexpr base::TaskTraits kImplTaskTraits = {base::MayBlock(), + base::TaskPriority::BACKGROUND}; + static base::LazySequencedTaskRunner s_file_task_runner = + LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(kImplTaskTraits); + + return s_file_task_runner.Get().get(); +} +} // namespace + // static DevToolsFileWatcher::SharedFileWatcher* DevToolsFileWatcher::s_shared_watcher_ = nullptr; -// DevToolsFileWatcher --------------------------------------------------------- +// static +void DevToolsFileWatcher::Deleter::operator()(const DevToolsFileWatcher* ptr) { + impl_task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&DevToolsFileWatcher::Destroy, base::Unretained(ptr))); +} -DevToolsFileWatcher::DevToolsFileWatcher(const WatchCallback& callback) - : callback_(callback) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - base::BindOnce(&DevToolsFileWatcher::InitSharedWatcher, - base::Unretained(this))); +DevToolsFileWatcher::DevToolsFileWatcher( + WatchCallback callback, + scoped_refptr<base::SequencedTaskRunner> callback_task_runner) + : callback_(std::move(callback)), + client_task_runner_(std::move(callback_task_runner)) { + impl_task_runner()->PostTask( + FROM_HERE, base::BindOnce(&DevToolsFileWatcher::InitSharedWatcher, + base::Unretained(this))); } DevToolsFileWatcher::~DevToolsFileWatcher() { - DCHECK_CURRENTLY_ON(BrowserThread::FILE); + DCHECK(impl_task_runner()->RunsTasksInCurrentSequence()); shared_watcher_->RemoveListener(this); } @@ -194,12 +223,16 @@ shared_watcher_->AddListener(this); } -void DevToolsFileWatcher::AddWatch(const base::FilePath& path) { - DCHECK_CURRENTLY_ON(BrowserThread::FILE); - shared_watcher_->AddWatch(path); +void DevToolsFileWatcher::AddWatch(base::FilePath path) { + impl_task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&SharedFileWatcher::AddWatch, + base::Unretained(shared_watcher_.get()), std::move(path))); } -void DevToolsFileWatcher::RemoveWatch(const base::FilePath& path) { - DCHECK_CURRENTLY_ON(BrowserThread::FILE); - shared_watcher_->RemoveWatch(path); +void DevToolsFileWatcher::RemoveWatch(base::FilePath path) { + impl_task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&SharedFileWatcher::RemoveWatch, + base::Unretained(shared_watcher_.get()), std::move(path))); }
diff --git a/chrome/browser/devtools/devtools_file_watcher.h b/chrome/browser/devtools/devtools_file_watcher.h index eb597fccf..a0f6bd6d 100644 --- a/chrome/browser/devtools/devtools_file_watcher.h +++ b/chrome/browser/devtools/devtools_file_watcher.h
@@ -12,28 +12,38 @@ namespace base { class FilePath; +class SequencedTaskRunner; } class DevToolsFileWatcher { public: + struct Deleter { + void operator()(const DevToolsFileWatcher* ptr); + }; + using WatchCallback = base::Callback<void(const std::vector<std::string>&, const std::vector<std::string>&, const std::vector<std::string>&)>; - explicit DevToolsFileWatcher(const WatchCallback& callback); - ~DevToolsFileWatcher(); + DevToolsFileWatcher( + WatchCallback callback, + scoped_refptr<base::SequencedTaskRunner> callback_task_runner); - void AddWatch(const base::FilePath& path); - void RemoveWatch(const base::FilePath& path); + void AddWatch(base::FilePath path); + void RemoveWatch(base::FilePath path); private: + ~DevToolsFileWatcher(); // Use Deleter to destroy objects of this type. class SharedFileWatcher; static SharedFileWatcher* s_shared_watcher_; + void Destroy() const { delete this; } void InitSharedWatcher(); void FileChanged(const base::FilePath&, int); scoped_refptr<SharedFileWatcher> shared_watcher_; WatchCallback callback_; + scoped_refptr<base::SequencedTaskRunner> client_task_runner_; + DISALLOW_COPY_AND_ASSIGN(DevToolsFileWatcher); };
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 12c367a..c9876e02 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1055,6 +1055,11 @@ "flag. The trace may include personally identifiable information (PII) " "such as the titles and URLs of websites you visit."; +const char kEnableNightLightName[] = "Enable Night Light"; +const char kEnableNightLightDescription[] = + "Enable the Night Light feature to control the color temperature of the " + "screen."; + const char kEnablePictureInPictureName[] = "Enable picture in picture."; const char kEnablePictureInPictureDescription[] = @@ -1076,11 +1081,6 @@ "With this flag on, desktop share picker window will not let the user " "choose whether to share audio."; -const char kDisableNightLightName[] = "Disable Night Light"; -const char kDisableNightLightDescription[] = - "Disable the Night Light feature which controls the color temperature of " - "the screen."; - const char kDisableTabForDesktopShareName[] = "Disable Desktop Share with tab source";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 5bf504af..06fac16 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -139,9 +139,6 @@ extern const char kDisableAudioForDesktopShareName[]; extern const char kDisableAudioForDesktopShareDescription[]; -extern const char kDisableNightLightName[]; -extern const char kDisableNightLightDescription[]; - extern const char kDisableTabForDesktopShareName[]; extern const char kDisableTabForDesktopShareDescription[]; @@ -239,6 +236,9 @@ extern const char kEnableNavigationTracingName[]; extern const char kEnableNavigationTracingDescription[]; +extern const char kEnableNightLightName[]; +extern const char kEnableNightLightDescription[]; + extern const char kEnablePictureInPictureName[]; extern const char kEnablePictureInPictureDescription[];
diff --git a/chrome/browser/offline_pages/background_loader_offliner.cc b/chrome/browser/offline_pages/background_loader_offliner.cc index fa299ab..c5203bb 100644 --- a/chrome/browser/offline_pages/background_loader_offliner.cc +++ b/chrome/browser/offline_pages/background_loader_offliner.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h" #include "chrome/browser/android/offline_pages/offliner_helper.h" #include "chrome/browser/loader/chrome_navigation_data.h" +#include "chrome/browser/offline_pages/offliner_user_data.h" #include "chrome/browser/profiles/profile.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h" #include "components/offline_pages/core/background/offliner_policy.h" @@ -38,28 +39,6 @@ "Content-Transfer-Encoding: binary"; const char kXHeaderForSignals[] = "X-Chrome-Loading-Metrics-Data: 1"; -class OfflinerData : public content::WebContentsUserData<OfflinerData> { - public: - static void AddToWebContents(content::WebContents* webcontents, - BackgroundLoaderOffliner* offliner) { - DCHECK(offliner); - webcontents->SetUserData(UserDataKey(), std::unique_ptr<OfflinerData>( - new OfflinerData(offliner))); - } - - explicit OfflinerData(BackgroundLoaderOffliner* offliner) { - offliner_ = offliner; - } - BackgroundLoaderOffliner* offliner() { return offliner_; } - - private: - // The offliner that the WebContents is attached to. The offliner owns the - // Delegate which owns the WebContents that this data is attached to. - // Therefore, its lifetime should exceed that of the WebContents, so this - // should always be non-null. - BackgroundLoaderOffliner* offliner_; -}; - std::string AddHistogramSuffix(const ClientId& client_id, const char* histogram_name) { if (client_id.name_space.empty()) { @@ -138,9 +117,11 @@ // static BackgroundLoaderOffliner* BackgroundLoaderOffliner::FromWebContents( content::WebContents* contents) { - OfflinerData* data = OfflinerData::FromWebContents(contents); - if (data) - return data->offliner(); + Offliner* offliner = OfflinerUserData::OfflinerFromWebContents(contents); + // Today we only have one kind of offliner that uses OfflinerUserData. If we + // add other types, revisit this cast. + if (offliner) + return static_cast<BackgroundLoaderOffliner*>(offliner); return nullptr; } @@ -364,6 +345,12 @@ std::unique_ptr<SnapshotController> controller) { snapshot_controller_ = std::move(controller); } +void BackgroundLoaderOffliner::ObserveResourceLoading( + ResourceLoadingObserver::ResourceDataType type, + bool started) { + // TODO(petewil) Not implemented yet. + return; +} void BackgroundLoaderOffliner::OnNetworkBytesChanged(int64_t bytes) { if (pending_request_ && save_state_ != SAVING) { @@ -521,7 +508,7 @@ void BackgroundLoaderOffliner::AttachObservers() { content::WebContents* contents = loader_->web_contents(); content::WebContentsObserver::Observe(contents); - OfflinerData::AddToWebContents(contents, this); + OfflinerUserData::AddToWebContents(contents, this); } void BackgroundLoaderOffliner::AddLoadingSignal(const char* signal_name) { @@ -536,5 +523,3 @@ } } // namespace offline_pages - -DEFINE_WEB_CONTENTS_USER_DATA_KEY(offline_pages::OfflinerData);
diff --git a/chrome/browser/offline_pages/background_loader_offliner.h b/chrome/browser/offline_pages/background_loader_offliner.h index bace442..560e830 100644 --- a/chrome/browser/offline_pages/background_loader_offliner.h +++ b/chrome/browser/offline_pages/background_loader_offliner.h
@@ -9,6 +9,7 @@ #include "base/memory/weak_ptr.h" #include "base/values.h" +#include "chrome/browser/offline_pages/resource_loading_observer.h" #include "components/offline_pages/content/background_loader/background_loader_contents.h" #include "components/offline_pages/core/background/load_termination_listener.h" #include "components/offline_pages/core/background/offliner.h" @@ -30,7 +31,8 @@ // OfflinePageModel to save it. Only one request may be active at a time. class BackgroundLoaderOffliner : public Offliner, public content::WebContentsObserver, - public SnapshotController::Client { + public SnapshotController::Client, + public ResourceLoadingObserver { public: BackgroundLoaderOffliner( content::BrowserContext* browser_context, @@ -63,7 +65,11 @@ void SetSnapshotControllerForTest( std::unique_ptr<SnapshotController> controller); - void OnNetworkBytesChanged(int64_t bytes); + + // ResourceLoadingObserver implemenation + void ObserveResourceLoading(ResourceLoadingObserver::ResourceDataType type, + bool started) override; + void OnNetworkBytesChanged(int64_t bytes) override; protected: // Called to reset the loader.
diff --git a/chrome/browser/offline_pages/offliner_user_data.cc b/chrome/browser/offline_pages/offliner_user_data.cc new file mode 100644 index 0000000..0dc7273a --- /dev/null +++ b/chrome/browser/offline_pages/offliner_user_data.cc
@@ -0,0 +1,41 @@ +// 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 "chrome/browser/offline_pages/offliner_user_data.h" + +class ResourceTrackerObserver; + +namespace offline_pages { + +void OfflinerUserData::AddToWebContents(content::WebContents* webcontents, + BackgroundLoaderOffliner* offliner) { + DCHECK(offliner); + webcontents->SetUserData(UserDataKey(), std::unique_ptr<OfflinerUserData>( + new OfflinerUserData(offliner))); +} + +// static - gets the data pointer as a BackgroundLoaderOffliner +BackgroundLoaderOffliner* OfflinerUserData::OfflinerFromWebContents( + content::WebContents* webcontents) { + OfflinerUserData* data = OfflinerUserData::FromWebContents(webcontents); + if (data) + return data->offliner(); + + return nullptr; +} + +// static - gets the data pointer as a ResourceLoadingObserver +ResourceLoadingObserver* +OfflinerUserData::ResourceLoadingObserverFromWebContents( + content::WebContents* webcontents) { + OfflinerUserData* data = OfflinerUserData::FromWebContents(webcontents); + if (data) + return data->offliner(); + + return nullptr; +} + +} // namespace offline_pages + +DEFINE_WEB_CONTENTS_USER_DATA_KEY(offline_pages::OfflinerUserData);
diff --git a/chrome/browser/offline_pages/offliner_user_data.h b/chrome/browser/offline_pages/offliner_user_data.h new file mode 100644 index 0000000..9ed7c6a --- /dev/null +++ b/chrome/browser/offline_pages/offliner_user_data.h
@@ -0,0 +1,41 @@ +// 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 CHROME_BROWSER_OFFLINE_PAGES_OFFLINER_USER_DATA_H_ +#define CHROME_BROWSER_OFFLINE_PAGES_OFFLINER_USER_DATA_H_ + +#include "chrome/browser/offline_pages/background_loader_offliner.h" +#include "chrome/browser/offline_pages/resource_loading_observer.h" +#include "components/offline_pages/features/features.h" +#include "content/public/browser/web_contents_user_data.h" + +namespace offline_pages { + +class OfflinerUserData : public content::WebContentsUserData<OfflinerUserData> { + public: + static void AddToWebContents(content::WebContents* webcontents, + BackgroundLoaderOffliner* offliner); + + static BackgroundLoaderOffliner* OfflinerFromWebContents( + content::WebContents* webcontents); + + static ResourceLoadingObserver* ResourceLoadingObserverFromWebContents( + content::WebContents* webcontents); + + explicit OfflinerUserData(BackgroundLoaderOffliner* offliner) { + offliner_ = offliner; + } + BackgroundLoaderOffliner* offliner() { return offliner_; } + + private: + // The offliner that the WebContents is attached to. The offliner owns the + // Delegate which owns the WebContents that this data is attached to. + // Therefore, its lifetime should exceed that of the WebContents, so this + // should always be non-null. + BackgroundLoaderOffliner* offliner_; +}; + +} // namespace offline_pages + +#endif // CHROME_BROWSER_OFFLINE_PAGES_OFFLINER_USER_DATA_H_
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc index 92eed1c4..eeb6acd7 100644 --- a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc +++ b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
@@ -14,7 +14,6 @@ #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h" #include "components/offline_pages/core/prefetch/prefetch_gcm_app_handler.h" -#include "components/offline_pages/core/prefetch/prefetch_in_memory_store.h" #include "components/offline_pages/core/prefetch/prefetch_service_impl.h" #include "components/offline_pages/core/prefetch/suggested_articles_observer.h" #include "content/public/browser/browser_context.h" @@ -47,12 +46,11 @@ base::MakeUnique<OfflineMetricsCollectorImpl>(); auto suggested_articles_observer = base::MakeUnique<SuggestedArticlesObserver>(prefetch_dispatcher.get()); - auto in_memory_store = base::MakeUnique<PrefetchInMemoryStore>(); - return new PrefetchServiceImpl( - std::move(offline_metrics_collector), std::move(prefetch_dispatcher), - std::move(prefetch_gcm_app_handler), std::move(in_memory_store), - std::move(suggested_articles_observer)); + return new PrefetchServiceImpl(std::move(offline_metrics_collector), + std::move(prefetch_dispatcher), + std::move(prefetch_gcm_app_handler), + std::move(suggested_articles_observer)); } } // namespace offline_pages
diff --git a/chrome/browser/offline_pages/resource_loading_observer.h b/chrome/browser/offline_pages/resource_loading_observer.h new file mode 100644 index 0000000..6a6e90d --- /dev/null +++ b/chrome/browser/offline_pages/resource_loading_observer.h
@@ -0,0 +1,32 @@ +// 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 CHROME_BROWSER_OFFLINE_PAGES_RESOURCE_LOADING_OBSERVER_H_ +#define CHROME_BROWSER_OFFLINE_PAGES_RESOURCE_LOADING_OBSERVER_H_ + +#include <stdint.h> + +namespace offline_pages { + +// This interface is used by clients who want to be notified when a resource is +// requested or completes loading, and to report the size of the resource. +class ResourceLoadingObserver { + public: + enum ResourceDataType { + IMAGE, + TEXT_CSS, + OTHER, + RESOURCE_DATA_TYPE_COUNT, + }; + + // Report when a resource starts or completes loading. + virtual void ObserveResourceLoading(ResourceDataType type, bool started) = 0; + + // Report how many bytes were received for a resource. + virtual void OnNetworkBytesChanged(int64_t received_bytes) = 0; +}; + +} // namespace offline_pages + +#endif // CHROME_BROWSER_OFFLINE_PAGES_RESOURCE_LOADING_OBSERVER_H_
diff --git a/chrome/browser/plugins/flash_download_interception.cc b/chrome/browser/plugins/flash_download_interception.cc index b4f6678..f9a7b44 100644 --- a/chrome/browser/plugins/flash_download_interception.cc +++ b/chrome/browser/plugins/flash_download_interception.cc
@@ -159,5 +159,5 @@ } return base::MakeUnique<navigation_interception::InterceptNavigationThrottle>( - handle, base::Bind(&InterceptNavigation, source_url), true); + handle, base::Bind(&InterceptNavigation, source_url)); }
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc index bf641e6..6d143fa 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -119,7 +119,7 @@ #endif #if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/printer_detector/printer_detector_factory.h" +#include "chrome/browser/chromeos/printer_detector/usb_printer_detector_factory.h" #include "chrome/browser/chromeos/printing/cups_print_job_manager_factory.h" #include "chrome/browser/chromeos/printing/printers_manager_factory.h" #include "chrome/browser/chromeos/tether/tether_service_factory.h" @@ -230,7 +230,7 @@ EnhancedBookmarkKeyServiceFactory::GetInstance(); #endif #if defined(OS_CHROMEOS) - chromeos::PrinterDetectorFactory::GetInstance(); + chromeos::UsbPrinterDetectorFactory::GetInstance(); chromeos::CupsPrintJobManagerFactory::GetInstance(); chromeos::PrintersManagerFactory::GetInstance(); TetherServiceFactory::GetInstance();
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/injected/externs.js b/chrome/browser/resources/chromeos/chromevox/chromevox/injected/externs.js index 5d6280b..bf3e55c 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/injected/externs.js +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/injected/externs.js
@@ -162,12 +162,3 @@ * @typedef {Object} */ function mediaWiki() {} - - -/** - * @param {?function(this:S, T, number, !Array<T>): ?} callback - * @param {S=} opt_thisobj - * @this {{length: number}|Array<T>} - * @template T,S - */ -NodeList.prototype.forEach = function(callback, opt_thisobj) {};
diff --git a/chrome/browser/resources/extensions/extensions.css b/chrome/browser/resources/extensions/extensions.css index 011d0f7..57468d4 100644 --- a/chrome/browser/resources/extensions/extensions.css +++ b/chrome/browser/resources/extensions/extensions.css
@@ -98,6 +98,16 @@ line-height: 150%; } +#page-header { + -webkit-padding-start: 23px; + left: 0; +} + +[dir='rtl'] #page-header { + left: auto; + right: 0; +} + #page-header > .page-banner > .page-banner-gradient { -webkit-margin-end: 0; }
diff --git a/chrome/browser/safe_browsing/browser_url_loader_throttle.cc b/chrome/browser/safe_browsing/browser_url_loader_throttle.cc new file mode 100644 index 0000000..cc4ec69 --- /dev/null +++ b/chrome/browser/safe_browsing/browser_url_loader_throttle.cc
@@ -0,0 +1,87 @@ +// 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 "chrome/browser/safe_browsing/browser_url_loader_throttle.h" + +#include "base/logging.h" +#include "chrome/browser/safe_browsing/safe_browsing_url_checker_impl.h" +#include "chrome/browser/safe_browsing/ui_manager.h" +#include "components/safe_browsing_db/database_manager.h" +#include "net/url_request/redirect_info.h" + +namespace safe_browsing { + +BrowserURLLoaderThrottle::BrowserURLLoaderThrottle( + scoped_refptr<SafeBrowsingDatabaseManager> database_manager, + scoped_refptr<SafeBrowsingUIManager> ui_manager, + const base::Callback<content::WebContents*()>& web_contents_getter) + : database_manager_(database_manager), + ui_manager_(ui_manager), + web_contents_getter_(web_contents_getter) {} + +BrowserURLLoaderThrottle::~BrowserURLLoaderThrottle() = default; + +void BrowserURLLoaderThrottle::WillStartRequest( + const GURL& url, + int load_flags, + content::ResourceType resource_type, + bool* defer) { + DCHECK_EQ(0u, pending_checks_); + DCHECK(!blocked_); + DCHECK(!url_checker_); + + pending_checks_++; + url_checker_ = base::MakeUnique<SafeBrowsingUrlCheckerImpl>( + load_flags, resource_type, std::move(database_manager_), + std::move(ui_manager_), web_contents_getter_); + url_checker_->CheckUrl(url, + base::Bind(&BrowserURLLoaderThrottle::OnCheckUrlResult, + base::Unretained(this))); +} + +void BrowserURLLoaderThrottle::WillRedirectRequest( + const net::RedirectInfo& redirect_info, + bool* defer) { + // If |blocked_| is true, the resource load has been canceled and there + // shouldn't be such a notification. + DCHECK(!blocked_); + + pending_checks_++; + url_checker_->CheckUrl( + redirect_info.new_url, + base::BindOnce(&BrowserURLLoaderThrottle::OnCheckUrlResult, + base::Unretained(this))); +} + +void BrowserURLLoaderThrottle::WillProcessResponse(bool* defer) { + // If |blocked_| is true, the resource load has been canceled and there + // shouldn't be such a notification. + DCHECK(!blocked_); + + if (pending_checks_ > 0) + *defer = true; +} + +void BrowserURLLoaderThrottle::OnCheckUrlResult(bool safe) { + if (blocked_) + return; + + DCHECK_LT(0u, pending_checks_); + pending_checks_--; + + if (safe) { + if (pending_checks_ == 0) { + // The resource load is not necessarily deferred, in that case Resume() is + // a no-op. + delegate_->Resume(); + } + } else { + url_checker_.reset(); + blocked_ = true; + pending_checks_ = 0; + delegate_->CancelWithError(net::ERR_ABORTED); + } +} + +} // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/browser_url_loader_throttle.h b/chrome/browser/safe_browsing/browser_url_loader_throttle.h new file mode 100644 index 0000000..1eca9d49 --- /dev/null +++ b/chrome/browser/safe_browsing/browser_url_loader_throttle.h
@@ -0,0 +1,68 @@ +// 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 CHROME_BROWSER_SAFE_BROWSING_BROWSER_URL_LOADER_THROTTLE_H_ +#define CHROME_BROWSER_SAFE_BROWSING_BROWSER_URL_LOADER_THROTTLE_H_ + +#include <memory> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "content/public/common/url_loader_throttle.h" + +namespace content { +class WebContents; +} + +namespace safe_browsing { + +class SafeBrowsingDatabaseManager; +class SafeBrowsingUIManager; +class SafeBrowsingUrlCheckerImpl; + +// BrowserURLLoaderThrottle is used in the browser process to query +// SafeBrowsing to determine whether a URL and also its redirect URLs are safe +// to load. It defers response processing until all URL checks are completed; +// cancels the load if any URLs turn out to be bad. +// Used when --enable-network-service is in effect. +class BrowserURLLoaderThrottle : public content::URLLoaderThrottle { + public: + // |web_contents_getter| is used for displaying SafeBrowsing UI when + // necessary. + BrowserURLLoaderThrottle( + scoped_refptr<SafeBrowsingDatabaseManager> database_manager, + scoped_refptr<SafeBrowsingUIManager> ui_manager, + const base::Callback<content::WebContents*()>& web_contents_getter); + ~BrowserURLLoaderThrottle() override; + + // content::URLLoaderThrottle implementation. + void WillStartRequest(const GURL& url, + int load_flags, + content::ResourceType resource_type, + bool* defer) override; + void WillRedirectRequest(const net::RedirectInfo& redirect_info, + bool* defer) override; + void WillProcessResponse(bool* defer) override; + + private: + void OnCheckUrlResult(bool safe); + + // The following two members stay valid until |url_checker_| is created. + scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; + scoped_refptr<SafeBrowsingUIManager> ui_manager_; + + base::Callback<content::WebContents*()> web_contents_getter_; + + std::unique_ptr<SafeBrowsingUrlCheckerImpl> url_checker_; + + size_t pending_checks_ = 0; + bool blocked_ = false; + + DISALLOW_COPY_AND_ASSIGN(BrowserURLLoaderThrottle); +}; + +} // namespace safe_browsing + +#endif // CHROME_BROWSER_SAFE_BROWSING_BROWSER_URL_LOADER_THROTTLE_H_
diff --git a/chrome/browser/safe_browsing/mojo_safe_browsing_impl.cc b/chrome/browser/safe_browsing/mojo_safe_browsing_impl.cc index 8aed827..67e38a72 100644 --- a/chrome/browser/safe_browsing/mojo_safe_browsing_impl.cc +++ b/chrome/browser/safe_browsing/mojo_safe_browsing_impl.cc
@@ -7,10 +7,7 @@ #include <vector> #include "base/memory/ptr_util.h" -#include "base/memory/weak_ptr.h" -#include "base/timer/timer.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/prerender/prerender_contents.h" +#include "chrome/browser/safe_browsing/safe_browsing_url_checker_impl.h" #include "chrome/browser/safe_browsing/ui_manager.h" #include "components/safe_browsing_db/database_manager.h" #include "content/public/browser/browser_thread.h" @@ -23,12 +20,6 @@ namespace safe_browsing { namespace { -// TODO(yzshen): Share such value with safe_browsing::BaseResourceThrottle. -// Maximum time in milliseconds to wait for the SafeBrowsing service reputation -// check. After this amount of time the outstanding check will be aborted, and -// the resource will be treated as if it were safe. -const int kCheckUrlTimeoutMs = 5000; - content::WebContents* GetWebContentsFromID(int render_process_id, int render_frame_id) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -40,222 +31,23 @@ return content::WebContents::FromRenderFrameHost(render_frame_host); } -// TODO(yzshen): Handle the case where SafeBrowsing is not enabled, or -// !database_manager()->IsSupported(). -// TODO(yzshen): Make sure it also works on Andorid. -// TODO(yzshen): Do all the logging like what BaseResourceThrottle does. -class SafeBrowsingUrlCheckerImpl : public mojom::SafeBrowsingUrlChecker, - public SafeBrowsingDatabaseManager::Client { +// This class wraps a base::OnceCallback<void(bool)> and runs it on destruction, +// if it hasn't been run yet. +class BooleanCallbackWrapper { public: - SafeBrowsingUrlCheckerImpl( - int load_flags, - content::ResourceType resource_type, - scoped_refptr<SafeBrowsingDatabaseManager> database_manager, - scoped_refptr<SafeBrowsingUIManager> ui_manager, - int render_process_id, - int render_frame_id) - : load_flags_(load_flags), - resource_type_(resource_type), - render_process_id_(render_process_id), - render_frame_id_(render_frame_id), - database_manager_(std::move(database_manager)), - ui_manager_(std::move(ui_manager)), - weak_factory_(this) { - DCHECK_NE(resource_type, content::RESOURCE_TYPE_MAIN_FRAME); - DCHECK_NE(resource_type, content::RESOURCE_TYPE_SUB_FRAME); + using BooleanCallback = base::OnceCallback<void(bool)>; + + explicit BooleanCallbackWrapper(BooleanCallback callback) + : callback_(std::move(callback)) {} + ~BooleanCallbackWrapper() { + if (callback_) + Run(false); } - ~SafeBrowsingUrlCheckerImpl() override { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (state_ == STATE_CHECKING_URL) - database_manager_->CancelCheck(this); - - for (size_t i = next_index_; i < callbacks_.size(); ++i) - std::move(callbacks_[i]).Run(false); - } - - // mojom::SafeBrowsingUrlChecker implementation. - void CheckUrl(const GURL& url, CheckUrlCallback callback) override { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - DVLOG(1) << "SafeBrowsingUrlCheckerImpl checks URL: " << url; - urls_.push_back(url); - callbacks_.push_back(std::move(callback)); - - ProcessUrls(); - } + void Run(bool value) { std::move(callback_).Run(value); } private: - // SafeBrowsingDatabaseManager::Client implementation: - void OnCheckBrowseUrlResult(const GURL& url, - SBThreatType threat_type, - const ThreatMetadata& metadata) override { - DCHECK_EQ(STATE_CHECKING_URL, state_); - DCHECK_LT(next_index_, urls_.size()); - DCHECK_EQ(urls_[next_index_], url); - - timer_.Stop(); - if (threat_type == SB_THREAT_TYPE_SAFE) { - state_ = STATE_NONE; - std::move(callbacks_[next_index_]).Run(true); - next_index_++; - ProcessUrls(); - return; - } - - if (load_flags_ & net::LOAD_PREFETCH) { - BlockAndProcessUrls(); - return; - } - - security_interstitials::UnsafeResource resource; - resource.url = url; - resource.original_url = urls_[0]; - if (urls_.size() > 1) - resource.redirect_urls = - std::vector<GURL>(urls_.begin() + 1, urls_.end()); - resource.is_subresource = true; - resource.is_subframe = false; - resource.threat_type = threat_type; - resource.threat_metadata = metadata; - resource.callback = - base::Bind(&SafeBrowsingUrlCheckerImpl::OnBlockingPageComplete, - weak_factory_.GetWeakPtr()); - resource.callback_thread = content::BrowserThread::GetTaskRunnerForThread( - content::BrowserThread::IO); - resource.web_contents_getter = - base::Bind(&GetWebContentsFromID, render_process_id_, render_frame_id_); - resource.threat_source = database_manager_->GetThreatSource(); - - state_ = STATE_DISPLAYING_BLOCKING_PAGE; - - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&SafeBrowsingUrlCheckerImpl::StartDisplayingBlockingPage, - weak_factory_.GetWeakPtr(), ui_manager_, resource)); - } - - static void StartDisplayingBlockingPage( - const base::WeakPtr<SafeBrowsingUrlCheckerImpl>& checker, - scoped_refptr<BaseUIManager> ui_manager, - const security_interstitials::UnsafeResource& resource) { - content::WebContents* web_contents = resource.web_contents_getter.Run(); - if (web_contents) { - prerender::PrerenderContents* prerender_contents = - prerender::PrerenderContents::FromWebContents(web_contents); - if (prerender_contents) { - prerender_contents->Destroy(prerender::FINAL_STATUS_SAFE_BROWSING); - } else { - ui_manager->DisplayBlockingPage(resource); - return; - } - } - - // Tab is gone or it's being prerendered. - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::BindOnce(&SafeBrowsingUrlCheckerImpl::BlockAndProcessUrls, - checker)); - } - - void OnCheckUrlTimeout() { - database_manager_->CancelCheck(this); - - OnCheckBrowseUrlResult(urls_[next_index_], - safe_browsing::SB_THREAT_TYPE_SAFE, - ThreatMetadata()); - } - - void ProcessUrls() { - DCHECK_NE(STATE_BLOCKED, state_); - - if (state_ == STATE_CHECKING_URL || - state_ == STATE_DISPLAYING_BLOCKING_PAGE) { - return; - } - - while (next_index_ < urls_.size()) { - DCHECK_EQ(STATE_NONE, state_); - // TODO(yzshen): Consider moving CanCheckResourceType() to the renderer - // side. That would save some IPCs. It requires a method on the - // SafeBrowsing mojo interface to query all supported resource types. - if (!database_manager_->CanCheckResourceType(resource_type_) || - database_manager_->CheckBrowseUrl(urls_[next_index_], this)) { - std::move(callbacks_[next_index_]).Run(true); - next_index_++; - continue; - } - - state_ = STATE_CHECKING_URL; - // Start a timer to abort the check if it takes too long. - timer_.Start(FROM_HERE, - base::TimeDelta::FromMilliseconds(kCheckUrlTimeoutMs), this, - &SafeBrowsingUrlCheckerImpl::OnCheckUrlTimeout); - - break; - } - } - - void BlockAndProcessUrls() { - DVLOG(1) << "SafeBrowsingUrlCheckerImpl blocks URL: " << urls_[next_index_]; - state_ = STATE_BLOCKED; - - // If user decided to not proceed through a warning, mark all the remaining - // redirects as "bad". - for (; next_index_ < callbacks_.size(); ++next_index_) - std::move(callbacks_[next_index_]).Run(false); - } - - void OnBlockingPageComplete(bool proceed) { - DCHECK_EQ(STATE_DISPLAYING_BLOCKING_PAGE, state_); - - if (proceed) { - state_ = STATE_NONE; - std::move(callbacks_[next_index_]).Run(true); - next_index_++; - ProcessUrls(); - } else { - BlockAndProcessUrls(); - } - } - - enum State { - // Haven't started checking or checking is complete. - STATE_NONE, - // We have one outstanding URL-check. - STATE_CHECKING_URL, - // We're displaying a blocking page. - STATE_DISPLAYING_BLOCKING_PAGE, - // The blocking page has returned *not* to proceed. - STATE_BLOCKED - }; - - const int load_flags_; - const content::ResourceType resource_type_; - const int render_process_id_; - const int render_frame_id_; - scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; - scoped_refptr<BaseUIManager> ui_manager_; - - // The redirect chain for this resource, including the original URL and - // subsequent redirect URLs. - std::vector<GURL> urls_; - // Callbacks corresponding to |urls_| to report check results. |urls_| and - // |callbacks_| are always of the same size. - std::vector<CheckUrlCallback> callbacks_; - // |urls_| before |next_index_| have been checked. If |next_index_| is smaller - // than the size of |urls_|, the URL at |next_index_| is being processed. - size_t next_index_ = 0; - - State state_ = STATE_NONE; - - // Timer to abort the SafeBrowsing check if it takes too long. - base::OneShotTimer timer_; - - base::WeakPtrFactory<SafeBrowsingUrlCheckerImpl> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(SafeBrowsingUrlCheckerImpl); + BooleanCallback callback_; }; } // namespace @@ -296,8 +88,14 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); auto checker_impl = base::MakeUnique<SafeBrowsingUrlCheckerImpl>( static_cast<int>(load_flags), resource_type, database_manager_, - ui_manager_, render_process_id_, static_cast<int>(render_frame_id)); - checker_impl->CheckUrl(url, std::move(callback)); + ui_manager_, + base::Bind(&GetWebContentsFromID, render_process_id_, + static_cast<int>(render_frame_id))); + + checker_impl->CheckUrl( + url, base::BindOnce( + &BooleanCallbackWrapper::Run, + base::Owned(new BooleanCallbackWrapper(std::move(callback))))); mojo::MakeStrongBinding(std::move(checker_impl), std::move(request)); }
diff --git a/chrome/browser/safe_browsing/safe_browsing_url_checker_impl.cc b/chrome/browser/safe_browsing/safe_browsing_url_checker_impl.cc new file mode 100644 index 0000000..405d493 --- /dev/null +++ b/chrome/browser/safe_browsing/safe_browsing_url_checker_impl.cc
@@ -0,0 +1,188 @@ +// 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 "chrome/browser/safe_browsing/safe_browsing_url_checker_impl.h" + +#include "chrome/browser/prerender/prerender_contents.h" +#include "chrome/browser/safe_browsing/ui_manager.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_contents.h" +#include "net/base/load_flags.h" + +namespace safe_browsing { +namespace { + +// TODO(yzshen): Share such value with safe_browsing::BaseResourceThrottle. +// Maximum time in milliseconds to wait for the SafeBrowsing service reputation +// check. After this amount of time the outstanding check will be aborted, and +// the resource will be treated as if it were safe. +const int kCheckUrlTimeoutMs = 5000; + +} // namespace + +SafeBrowsingUrlCheckerImpl::SafeBrowsingUrlCheckerImpl( + int load_flags, + content::ResourceType resource_type, + scoped_refptr<SafeBrowsingDatabaseManager> database_manager, + scoped_refptr<SafeBrowsingUIManager> ui_manager, + const base::Callback<content::WebContents*()>& web_contents_getter) + : load_flags_(load_flags), + resource_type_(resource_type), + web_contents_getter_(web_contents_getter), + database_manager_(std::move(database_manager)), + ui_manager_(std::move(ui_manager)), + weak_factory_(this) {} + +SafeBrowsingUrlCheckerImpl::~SafeBrowsingUrlCheckerImpl() { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + if (state_ == STATE_CHECKING_URL) + database_manager_->CancelCheck(this); +} + +void SafeBrowsingUrlCheckerImpl::CheckUrl(const GURL& url, + CheckUrlCallback callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + DVLOG(1) << "SafeBrowsingUrlCheckerImpl checks URL: " << url; + urls_.push_back(url); + callbacks_.push_back(std::move(callback)); + + ProcessUrls(); +} + +void SafeBrowsingUrlCheckerImpl::OnCheckBrowseUrlResult( + const GURL& url, + SBThreatType threat_type, + const ThreatMetadata& metadata) { + DCHECK_EQ(STATE_CHECKING_URL, state_); + DCHECK_LT(next_index_, urls_.size()); + DCHECK_EQ(urls_[next_index_], url); + + timer_.Stop(); + if (threat_type == SB_THREAT_TYPE_SAFE) { + state_ = STATE_NONE; + std::move(callbacks_[next_index_]).Run(true); + next_index_++; + ProcessUrls(); + return; + } + + if (load_flags_ & net::LOAD_PREFETCH) { + // TODO(yzshen): Destroy prerender contents if necessary. + + BlockAndProcessUrls(); + return; + } + + security_interstitials::UnsafeResource resource; + resource.url = url; + resource.original_url = urls_[0]; + if (urls_.size() > 1) + resource.redirect_urls = std::vector<GURL>(urls_.begin() + 1, urls_.end()); + resource.is_subresource = resource_type_ != content::RESOURCE_TYPE_MAIN_FRAME; + resource.is_subframe = resource_type_ == content::RESOURCE_TYPE_SUB_FRAME; + resource.threat_type = threat_type; + resource.threat_metadata = metadata; + resource.callback = + base::Bind(&SafeBrowsingUrlCheckerImpl::OnBlockingPageComplete, + weak_factory_.GetWeakPtr()); + resource.callback_thread = content::BrowserThread::GetTaskRunnerForThread( + content::BrowserThread::IO); + resource.web_contents_getter = web_contents_getter_; + resource.threat_source = database_manager_->GetThreatSource(); + + state_ = STATE_DISPLAYING_BLOCKING_PAGE; + + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&SafeBrowsingUrlCheckerImpl::StartDisplayingBlockingPage, + weak_factory_.GetWeakPtr(), ui_manager_, resource)); +} + +// static +void SafeBrowsingUrlCheckerImpl::StartDisplayingBlockingPage( + const base::WeakPtr<SafeBrowsingUrlCheckerImpl>& checker, + scoped_refptr<BaseUIManager> ui_manager, + const security_interstitials::UnsafeResource& resource) { + content::WebContents* web_contents = resource.web_contents_getter.Run(); + if (web_contents) { + prerender::PrerenderContents* prerender_contents = + prerender::PrerenderContents::FromWebContents(web_contents); + if (prerender_contents) { + prerender_contents->Destroy(prerender::FINAL_STATUS_SAFE_BROWSING); + } else { + ui_manager->DisplayBlockingPage(resource); + return; + } + } + + // Tab is gone or it's being prerendered. + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&SafeBrowsingUrlCheckerImpl::BlockAndProcessUrls, + checker)); +} + +void SafeBrowsingUrlCheckerImpl::OnCheckUrlTimeout() { + database_manager_->CancelCheck(this); + + OnCheckBrowseUrlResult(urls_[next_index_], safe_browsing::SB_THREAT_TYPE_SAFE, + ThreatMetadata()); +} + +void SafeBrowsingUrlCheckerImpl::ProcessUrls() { + DCHECK_NE(STATE_BLOCKED, state_); + + if (state_ == STATE_CHECKING_URL || + state_ == STATE_DISPLAYING_BLOCKING_PAGE) { + return; + } + + while (next_index_ < urls_.size()) { + DCHECK_EQ(STATE_NONE, state_); + // TODO(yzshen): Consider moving CanCheckResourceType() to the renderer + // side. That would save some IPCs. It requires a method on the + // SafeBrowsing mojo interface to query all supported resource types. + if (!database_manager_->CanCheckResourceType(resource_type_) || + database_manager_->CheckBrowseUrl(urls_[next_index_], this)) { + std::move(callbacks_[next_index_]).Run(true); + next_index_++; + continue; + } + + state_ = STATE_CHECKING_URL; + // Start a timer to abort the check if it takes too long. + timer_.Start(FROM_HERE, + base::TimeDelta::FromMilliseconds(kCheckUrlTimeoutMs), this, + &SafeBrowsingUrlCheckerImpl::OnCheckUrlTimeout); + + break; + } +} + +void SafeBrowsingUrlCheckerImpl::BlockAndProcessUrls() { + DVLOG(1) << "SafeBrowsingUrlCheckerImpl blocks URL: " << urls_[next_index_]; + state_ = STATE_BLOCKED; + + // If user decided to not proceed through a warning, mark all the remaining + // redirects as "bad". + for (; next_index_ < callbacks_.size(); ++next_index_) + std::move(callbacks_[next_index_]).Run(false); +} + +void SafeBrowsingUrlCheckerImpl::OnBlockingPageComplete(bool proceed) { + DCHECK_EQ(STATE_DISPLAYING_BLOCKING_PAGE, state_); + + if (proceed) { + state_ = STATE_NONE; + std::move(callbacks_[next_index_]).Run(true); + next_index_++; + ProcessUrls(); + } else { + BlockAndProcessUrls(); + } +} + +} // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/safe_browsing_url_checker_impl.h b/chrome/browser/safe_browsing/safe_browsing_url_checker_impl.h new file mode 100644 index 0000000..4815e99 --- /dev/null +++ b/chrome/browser/safe_browsing/safe_browsing_url_checker_impl.h
@@ -0,0 +1,116 @@ +// 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 CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_URL_CHECKER_IMPL_H_ +#define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_URL_CHECKER_IMPL_H_ + +#include <vector> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/timer/timer.h" +#include "components/safe_browsing/common/safe_browsing.mojom.h" +#include "components/safe_browsing_db/database_manager.h" +#include "content/public/common/resource_type.h" +#include "url/gurl.h" + +namespace content { +class WebContents; +} + +namespace security_interstitials { +struct UnsafeResource; +} + +namespace safe_browsing { + +class SafeBrowsingUIManager; +class BaseUIManager; + +// A SafeBrowsingUrlCheckerImpl instance is used to perform SafeBrowsing check +// for a URL and its redirect URLs. It implements Mojo interface so that it can +// be used to handle queries from renderers. But it is also used to handle +// queries from the browser. In that case, the public methods are called +// directly instead of through Mojo. +// Used when --enable-network-service is in effect. +// +// TODO(yzshen): Handle the case where SafeBrowsing is not enabled, or +// !database_manager()->IsSupported(). +// TODO(yzshen): Make sure it also works on Andorid. +// TODO(yzshen): Do all the logging like what BaseResourceThrottle does. +class SafeBrowsingUrlCheckerImpl : public mojom::SafeBrowsingUrlChecker, + public SafeBrowsingDatabaseManager::Client { + public: + SafeBrowsingUrlCheckerImpl( + int load_flags, + content::ResourceType resource_type, + scoped_refptr<SafeBrowsingDatabaseManager> database_manager, + scoped_refptr<SafeBrowsingUIManager> ui_manager, + const base::Callback<content::WebContents*()>& web_contents_getter); + + ~SafeBrowsingUrlCheckerImpl() override; + + // mojom::SafeBrowsingUrlChecker implementation. + void CheckUrl(const GURL& url, CheckUrlCallback callback) override; + + private: + // SafeBrowsingDatabaseManager::Client implementation: + void OnCheckBrowseUrlResult(const GURL& url, + SBThreatType threat_type, + const ThreatMetadata& metadata) override; + + static void StartDisplayingBlockingPage( + const base::WeakPtr<SafeBrowsingUrlCheckerImpl>& checker, + scoped_refptr<BaseUIManager> ui_manager, + const security_interstitials::UnsafeResource& resource); + + void OnCheckUrlTimeout(); + + void ProcessUrls(); + + void BlockAndProcessUrls(); + + void OnBlockingPageComplete(bool proceed); + + enum State { + // Haven't started checking or checking is complete. + STATE_NONE, + // We have one outstanding URL-check. + STATE_CHECKING_URL, + // We're displaying a blocking page. + STATE_DISPLAYING_BLOCKING_PAGE, + // The blocking page has returned *not* to proceed. + STATE_BLOCKED + }; + + const int load_flags_; + const content::ResourceType resource_type_; + base::Callback<content::WebContents*()> web_contents_getter_; + scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; + scoped_refptr<BaseUIManager> ui_manager_; + + // The redirect chain for this resource, including the original URL and + // subsequent redirect URLs. + std::vector<GURL> urls_; + // Callbacks corresponding to |urls_| to report check results. |urls_| and + // |callbacks_| are always of the same size. + std::vector<CheckUrlCallback> callbacks_; + // |urls_| before |next_index_| have been checked. If |next_index_| is smaller + // than the size of |urls_|, the URL at |next_index_| is being processed. + size_t next_index_ = 0; + + State state_ = STATE_NONE; + + // Timer to abort the SafeBrowsing check if it takes too long. + base::OneShotTimer timer_; + + base::WeakPtrFactory<SafeBrowsingUrlCheckerImpl> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(SafeBrowsingUrlCheckerImpl); +}; + +} // namespace safe_browsing + +#endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_URL_CHECKER_IMPL_H_
diff --git a/chrome/browser/search_engines/template_url_service_android.cc b/chrome/browser/search_engines/template_url_service_android.cc index f7dc785..8e8f5e1 100644 --- a/chrome/browser/search_engines/template_url_service_android.cc +++ b/chrome/browser/search_engines/template_url_service_android.cc
@@ -91,7 +91,7 @@ return template_urls_.size(); } -jboolean TemplateUrlServiceAndroid::IsSearchProviderManaged( +jboolean TemplateUrlServiceAndroid::IsDefaultSearchManaged( JNIEnv* env, const JavaParamRef<jobject>& obj) { return template_url_service_->is_default_search_managed();
diff --git a/chrome/browser/search_engines/template_url_service_android.h b/chrome/browser/search_engines/template_url_service_android.h index 764708a..af6c8b05 100644 --- a/chrome/browser/search_engines/template_url_service_android.h +++ b/chrome/browser/search_engines/template_url_service_android.h
@@ -43,7 +43,7 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, jint index) const; - jboolean IsSearchProviderManaged( + jboolean IsDefaultSearchManaged( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); jboolean IsSearchByImageAvailable(
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc index c1a90a65..a22b65a 100644 --- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc +++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
@@ -76,6 +76,8 @@ } void SubresourceFilterContentSettingsManager::WhitelistSite(const GURL& url) { + DCHECK(base::FeatureList::IsEnabled( + subresource_filter::kSafeBrowsingSubresourceFilterExperimentalUI)); base::AutoReset<bool> resetter(&ignore_settings_changes_, true); settings_map_->SetContentSettingDefaultScope( url, GURL(), ContentSettingsType::CONTENT_SETTINGS_TYPE_ADS, @@ -123,6 +125,9 @@ void SubresourceFilterContentSettingsManager::SetSiteMetadata( const GURL& url, std::unique_ptr<base::DictionaryValue> dict) { + if (!base::FeatureList::IsEnabled( + subresource_filter::kSafeBrowsingSubresourceFilterExperimentalUI)) + return; settings_map_->SetWebsiteSettingDefaultScope( url, GURL(), ContentSettingsType::CONTENT_SETTINGS_TYPE_ADS_DATA, std::string(), std::move(dict));
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc index 7df821c8..f4f6b68 100644 --- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc +++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc
@@ -24,12 +24,15 @@ #include "components/content_settings/core/common/content_settings.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/test/history_service_test_util.h" +#include "components/subresource_filter/core/browser/subresource_filter_features.h" +#include "components/subresource_filter/core/browser/subresource_filter_features_test_support.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" namespace { +using subresource_filter::testing::ScopedSubresourceFilterFeatureToggle; const char kActionsHistogram[] = "SubresourceFilter.Actions"; class SubresourceFilterContentSettingsManagerTest : public testing::Test { @@ -37,6 +40,9 @@ SubresourceFilterContentSettingsManagerTest() {} void SetUp() override { + scoped_feature_toggle().ResetSubresourceFilterState( + base::FeatureList::OVERRIDE_ENABLE_FEATURE, + "SubresourceFilterExperimentalUI" /* additional_features */); settings_manager_ = SubresourceFilterProfileContextFactory::GetForProfile(&testing_profile_) ->settings_manager(); @@ -56,6 +62,10 @@ return settings_manager_; } + ScopedSubresourceFilterFeatureToggle& scoped_feature_toggle() { + return scoped_feature_toggle_; + } + TestingProfile* profile() { return &testing_profile_; } ContentSetting GetContentSettingMatchingUrlWithEmptyPath(const GURL& url) { @@ -78,6 +88,7 @@ base::ScopedTempDir scoped_dir_; content::TestBrowserThreadBundle thread_bundle_; + ScopedSubresourceFilterFeatureToggle scoped_feature_toggle_; base::HistogramTester histogram_tester_; TestingProfile testing_profile_; @@ -188,8 +199,7 @@ // Showing the UI should trigger a forced content setting update, but no // metrics should be recorded. - histogram_tester().ExpectBucketCount(kActionsHistogram, - kActionContentSettingsBlocked, 0); + histogram_tester().ExpectTotalCount(kActionsHistogram, 0); // Fast forward the clock. test_clock()->Advance( @@ -226,9 +236,6 @@ kActionContentSettingsAllowedFromUI, 0); histogram_tester().ExpectBucketCount( kActionsHistogram, kActionContentSettingsAllowedWhileUISuppressed, 1); - - // Smart UI should be reset. - EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(url)); } TEST_F(SubresourceFilterContentSettingsManagerTest, @@ -276,6 +283,23 @@ kActionContentSettingsBlockedGlobal, 1); } +TEST_F(SubresourceFilterContentSettingsManagerTest, + NoExperimentalUI_NoWebsiteSetting) { + GURL url("https://example.test/"); + + // Do no explicitly allow the experimental UI. + scoped_feature_toggle().ResetSubresourceFilterState( + base::FeatureList::OVERRIDE_ENABLE_FEATURE); + settings_manager()->OnDidShowUI(url); + EXPECT_FALSE(settings_manager()->GetSiteMetadata(url)); + + scoped_feature_toggle().ResetSubresourceFilterState( + base::FeatureList::OVERRIDE_ENABLE_FEATURE, + "SubresourceFilterExperimentalUI" /* additional_features */); + settings_manager()->OnDidShowUI(url); + EXPECT_TRUE(settings_manager()->GetSiteMetadata(url)); +} + TEST_F(SubresourceFilterContentSettingsManagerHistoryTest, HistoryUrlDeleted_ClearsWebsiteSetting) { if (!settings_manager()->should_use_smart_ui())
diff --git a/chrome/browser/subresource_filter/subresource_filter_unittest.cc b/chrome/browser/subresource_filter/subresource_filter_unittest.cc index a98db80..4886201 100644 --- a/chrome/browser/subresource_filter/subresource_filter_unittest.cc +++ b/chrome/browser/subresource_filter/subresource_filter_unittest.cc
@@ -63,7 +63,7 @@ // Ensure correct features. scoped_feature_toggle_.ResetSubresourceFilterState( base::FeatureList::OVERRIDE_ENABLE_FEATURE, - "SafeBrowsingV4OnlyEnabled" /* additional_features */); + "SafeBrowsingV4OnlyEnabled,SubresourceFilterExperimentalUI"); scoped_configuration_.ResetConfiguration(subresource_filter::Configuration( subresource_filter::ActivationLevel::ENABLED, subresource_filter::ActivationScope::ACTIVATION_LIST,
diff --git a/chrome/browser/themes/theme_properties.cc b/chrome/browser/themes/theme_properties.cc index d2fb1b92..b2ee2422 100644 --- a/chrome/browser/themes/theme_properties.cc +++ b/chrome/browser/themes/theme_properties.cc
@@ -90,9 +90,8 @@ // Defaults for properties which are not stored in the browser theme pack. constexpr SkColor kDefaultColorControlBackground = SK_ColorWHITE; -const SkColor kDefaultDetachedBookmarkBarSeparator = - SkColorSetRGB(0xB6, 0xB4, 0xB6); -const SkColor kDefaultDetachedBookmarkBarSeparatorIncognito = +const SkColor kDefaultToolbarBottomSeparator = SkColorSetRGB(0xB6, 0xB4, 0xB6); +const SkColor kDefaultToolbarBottomSeparatorIncognito = SkColorSetRGB(0x28, 0x28, 0x28); const SkColor kDefaultToolbarTopSeparator = SkColorSetA(SK_ColorBLACK, 0x40); @@ -262,13 +261,17 @@ case COLOR_BOOKMARK_BAR_INSTRUCTIONS_TEXT: return incognito ? kDefaultColorBookmarkInstructionsTextIncognito : kDefaultColorBookmarkInstructionsText; - case COLOR_TOOLBAR_BOTTOM_SEPARATOR: case COLOR_DETACHED_BOOKMARK_BAR_SEPARATOR: - return incognito ? kDefaultDetachedBookmarkBarSeparatorIncognito - : kDefaultDetachedBookmarkBarSeparator; + // We shouldn't reach this case because the color is calculated from + // others. + NOTREACHED(); + return gfx::kPlaceholderColor; case COLOR_DETACHED_BOOKMARK_BAR_BACKGROUND: return incognito ? kDefaultDetachedBookmarkBarBackgroundIncognito : kDefaultDetachedBookmarkBarBackground; + case COLOR_TOOLBAR_BOTTOM_SEPARATOR: + return incognito ? kDefaultToolbarBottomSeparatorIncognito + : kDefaultToolbarBottomSeparator; case COLOR_TOOLBAR_TOP_SEPARATOR: case COLOR_TOOLBAR_TOP_SEPARATOR_INACTIVE: return kDefaultToolbarTopSeparator;
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc index ed768b4..f5c851be 100644 --- a/chrome/browser/themes/theme_service.cc +++ b/chrome/browser/themes/theme_service.cc
@@ -472,16 +472,18 @@ if (UsingDefaultTheme()) break; return GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT, incognito); + case ThemeProperties::COLOR_TOOLBAR_BOTTOM_SEPARATOR: + if (UsingDefaultTheme()) + break; + return GetColor(ThemeProperties::COLOR_LOCATION_BAR_BORDER, incognito); case ThemeProperties::COLOR_DETACHED_BOOKMARK_BAR_BACKGROUND: if (UsingDefaultTheme()) break; return GetColor(ThemeProperties::COLOR_TOOLBAR, incognito); case ThemeProperties::COLOR_DETACHED_BOOKMARK_BAR_SEPARATOR: - if (UsingDefaultTheme()) - break; - // Use 50% of bookmark text color as separator color. + // Use a faint version of the text color as the separator color. return SkColorSetA( - GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT, incognito), 128); + GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT, incognito), 0x20); case ThemeProperties::COLOR_NTP_TEXT_LIGHT: return IncreaseLightness(GetColor(kNtpText, incognito), 0.40); case ThemeProperties::COLOR_TAB_THROBBER_SPINNING:
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index d8b19e3..c617085 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2356,6 +2356,7 @@ deps += [ "//chrome/browser:jni_headers", "//components/web_contents_delegate_android", + "//device/usb/public/cpp", ] deps -= [ "//ui/events" ] } else {
diff --git a/chrome/browser/ui/android/infobars/reader_mode_infobar.cc b/chrome/browser/ui/android/infobars/reader_mode_infobar.cc index e424ebd6..bcb2144 100644 --- a/chrome/browser/ui/android/infobars/reader_mode_infobar.cc +++ b/chrome/browser/ui/android/infobars/reader_mode_infobar.cc
@@ -46,6 +46,14 @@ return Java_ReaderModeInfoBar_create(env); } +base::android::ScopedJavaLocalRef<jobject> ReaderModeInfoBar::GetTab( + JNIEnv* env, + const JavaParamRef<jobject>& obj) { + content::WebContents* web_contents = + InfoBarService::WebContentsFromInfoBar(this); + return TabAndroid::FromWebContents(web_contents)->GetJavaObject(); +} + void ReaderModeInfoBar::ProcessButton(int action) {} void Create(JNIEnv* env,
diff --git a/chrome/browser/ui/android/infobars/reader_mode_infobar.h b/chrome/browser/ui/android/infobars/reader_mode_infobar.h index 22059e2..430c7f9 100644 --- a/chrome/browser/ui/android/infobars/reader_mode_infobar.h +++ b/chrome/browser/ui/android/infobars/reader_mode_infobar.h
@@ -19,6 +19,10 @@ std::unique_ptr<ReaderModeInfoBarDelegate> delegate); ~ReaderModeInfoBar() override; + base::android::ScopedJavaLocalRef<jobject> GetTab( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj); + protected: infobars::InfoBarDelegate* GetDelegate();
diff --git a/chrome/browser/ui/android/usb_chooser_dialog_android.cc b/chrome/browser/ui/android/usb_chooser_dialog_android.cc index 39d3a6e..c1c50ccd 100644 --- a/chrome/browser/ui/android/usb_chooser_dialog_android.cc +++ b/chrome/browser/ui/android/usb_chooser_dialog_android.cc
@@ -7,6 +7,7 @@ #include <stddef.h> #include <algorithm> +#include <utility> #include "base/android/jni_android.h" #include "base/android/jni_string.h" @@ -26,8 +27,8 @@ #include "content/public/browser/web_contents.h" #include "device/base/device_client.h" #include "device/usb/mojo/type_converters.h" +#include "device/usb/public/cpp/filter_utils.h" #include "device/usb/usb_device.h" -#include "device/usb/usb_device_filter.h" #include "device/usb/webusb_descriptors.h" #include "device/vr/features/features.h" #include "jni/UsbChooserDialog_jni.h" @@ -39,7 +40,6 @@ #endif // BUILDFLAG(ENABLE_VR) using device::UsbDevice; -using device::UsbDeviceFilter; namespace { @@ -56,13 +56,13 @@ } // namespace UsbChooserDialogAndroid::UsbChooserDialogAndroid( - const std::vector<UsbDeviceFilter>& filters, + std::vector<device::mojom::UsbDeviceFilterPtr> filters, content::RenderFrameHost* render_frame_host, const device::mojom::UsbChooserService::GetPermissionCallback& callback) : render_frame_host_(render_frame_host), callback_(callback), usb_service_observer_(this), - filters_(filters), + filters_(std::move(filters)), weak_factory_(this) { content::WebContents* web_contents = content::WebContents::FromRenderFrameHost(render_frame_host_); @@ -240,7 +240,7 @@ bool UsbChooserDialogAndroid::DisplayDevice( scoped_refptr<UsbDevice> device) const { - if (!UsbDeviceFilter::MatchesAny(*device, filters_)) + if (!UsbDeviceFilterMatchesAny(filters_, *device)) return false; if (UsbBlocklist::Get().IsExcluded(device))
diff --git a/chrome/browser/ui/android/usb_chooser_dialog_android.h b/chrome/browser/ui/android/usb_chooser_dialog_android.h index 318d835..09cbcdb1 100644 --- a/chrome/browser/ui/android/usb_chooser_dialog_android.h +++ b/chrome/browser/ui/android/usb_chooser_dialog_android.h
@@ -23,7 +23,6 @@ namespace device { class UsbDevice; -struct UsbDeviceFilter; } // Represents a way to ask the user to select a USB device from a list of @@ -31,7 +30,7 @@ class UsbChooserDialogAndroid : public device::UsbService::Observer { public: UsbChooserDialogAndroid( - const std::vector<device::UsbDeviceFilter>& filters, + std::vector<device::mojom::UsbDeviceFilterPtr> filters, content::RenderFrameHost* render_frame_host, const device::mojom::UsbChooserService::GetPermissionCallback& callback); ~UsbChooserDialogAndroid() override; @@ -74,7 +73,7 @@ device::mojom::UsbChooserService::GetPermissionCallback callback_; ScopedObserver<device::UsbService, device::UsbService::Observer> usb_service_observer_; - std::vector<device::UsbDeviceFilter> filters_; + std::vector<device::mojom::UsbDeviceFilterPtr> filters_; std::vector<scoped_refptr<device::UsbDevice>> devices_;
diff --git a/chrome/browser/ui/libgtkui/gtk_ui.cc b/chrome/browser/ui/libgtkui/gtk_ui.cc index d8ce7ba..53dae5c 100644 --- a/chrome/browser/ui/libgtkui/gtk_ui.cc +++ b/chrome/browser/ui/libgtkui/gtk_ui.cc
@@ -896,8 +896,6 @@ colors_[ThemeProperties::COLOR_TOOLBAR_BOTTOM_SEPARATOR] = tab_border; // Separates entries in the downloads bar. colors_[ThemeProperties::COLOR_TOOLBAR_VERTICAL_SEPARATOR] = tab_border; - // Separates the bookmark bar from the web content. - colors_[ThemeProperties::COLOR_DETACHED_BOOKMARK_BAR_SEPARATOR] = tab_border; // These colors represent the border drawn around tabs and between // the tabstrip and toolbar.
diff --git a/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc b/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc index e9d7fe43..18af0d7 100644 --- a/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc +++ b/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
@@ -214,7 +214,7 @@ views::View* GetContentsView() override { return this; } views::NonClientFrameView* CreateNonClientFrameView( views::Widget* widget) override { - return views::DialogDelegate::CreateDialogFrameView(widget, gfx::Insets()); + return views::DialogDelegate::CreateDialogFrameView(widget); } bool ShouldShowCloseButton() const override { // No close button if the dialog doesn't want a title bar.
diff --git a/chrome/browser/ui/views/extensions/chooser_dialog_view.cc b/chrome/browser/ui/views/extensions/chooser_dialog_view.cc index 93dcf5b..839322c6 100644 --- a/chrome/browser/ui/views/extensions/chooser_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/chooser_dialog_view.cc
@@ -18,6 +18,7 @@ #include "content/public/browser/browser_thread.h" #include "ui/gfx/geometry/insets.h" #include "ui/views/background.h" +#include "ui/views/border.h" #include "ui/views/controls/link.h" #include "ui/views/controls/styled_label.h" #include "ui/views/layout/fill_layout.h" @@ -43,6 +44,9 @@ DCHECK(chooser_controller); device_chooser_content_view_ = new DeviceChooserContentView(this, std::move(chooser_controller)); + device_chooser_content_view_->SetBorder( + views::CreateEmptyBorder(ChromeLayoutProvider::Get()->GetInsetsMetric( + views::INSETS_DIALOG_CONTENTS))); chrome::RecordDialogCreation(chrome::DialogIdentifier::CHOOSER); } @@ -70,27 +74,13 @@ } views::View* ChooserDialogView::CreateFootnoteView() { - return device_chooser_content_view_->footnote_link(); -} - -views::ClientView* ChooserDialogView::CreateClientView(views::Widget* widget) { - views::DialogClientView* client = - new views::DialogClientView(widget, GetContentsView()); - ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); - client->SetButtonRowInsets(gfx::Insets( - provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL), - 0, 0, 0)); - return client; -} - -views::NonClientFrameView* ChooserDialogView::CreateNonClientFrameView( - views::Widget* widget) { - // ChooserDialogView always has a parent, so ShouldUseCustomFrame() should - // always be true. - DCHECK(ShouldUseCustomFrame()); - return views::DialogDelegate::CreateDialogFrameView( - widget, ChromeLayoutProvider::Get()->GetInsetsMetric( - views::INSETS_BUBBLE_CONTENTS)); + views::View* footnote_link = device_chooser_content_view_->footnote_link(); + if (footnote_link) { + footnote_link->SetBorder( + views::CreateEmptyBorder(ChromeLayoutProvider::Get()->GetInsetsMetric( + views::INSETS_DIALOG_CONTENTS))); + } + return footnote_link; } bool ChooserDialogView::Accept() {
diff --git a/chrome/browser/ui/views/extensions/chooser_dialog_view.h b/chrome/browser/ui/views/extensions/chooser_dialog_view.h index 231dd9f..dcb4f6e 100644 --- a/chrome/browser/ui/views/extensions/chooser_dialog_view.h +++ b/chrome/browser/ui/views/extensions/chooser_dialog_view.h
@@ -32,9 +32,6 @@ base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; bool IsDialogButtonEnabled(ui::DialogButton button) const override; views::View* CreateFootnoteView() override; - views::ClientView* CreateClientView(views::Widget* widget) override; - views::NonClientFrameView* CreateNonClientFrameView( - views::Widget* widget) override; bool Accept() override; bool Cancel() override; bool Close() override;
diff --git a/chrome/browser/ui/views/extensions/chooser_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/chooser_dialog_view_browsertest.cc new file mode 100644 index 0000000..34b2d90 --- /dev/null +++ b/chrome/browser/ui/views/extensions/chooser_dialog_view_browsertest.cc
@@ -0,0 +1,63 @@ +// 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 "chrome/browser/ui/views/extensions/chooser_dialog_view.h" + +#include <string> + +#include "base/command_line.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/chooser_controller/mock_chooser_controller.h" +#include "chrome/browser/platform_util.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/test/test_browser_dialog.h" +#include "components/constrained_window/constrained_window_views.h" +#include "components/web_modal/web_contents_modal_dialog_manager.h" + +// Invokes the device chooser dialog with mock content. See +// test_browser_dialog.h. +class ChooserDialogViewBrowserTest : public DialogBrowserTest { + public: + ChooserDialogViewBrowserTest() : controller_(new MockChooserController()) {} + + // DialogBrowserTest: + void ShowDialog(const std::string& name) override { + auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); + web_modal::WebContentsModalDialogManager* manager = + web_modal::WebContentsModalDialogManager::FromWebContents(web_contents); + if (manager) { + constrained_window::ShowWebModalDialogViews( + new ChooserDialogView(std::move(controller_)), web_contents); + } + } + + MockChooserController& controller() { return *controller_; } + + private: + std::unique_ptr<MockChooserController> controller_; + + DISALLOW_COPY_AND_ASSIGN(ChooserDialogViewBrowserTest); +}; + +IN_PROC_BROWSER_TEST_F(ChooserDialogViewBrowserTest, InvokeDialog_noDevices) { + RunDialog(); +} + +IN_PROC_BROWSER_TEST_F(ChooserDialogViewBrowserTest, InvokeDialog_withDevices) { + controller().OptionAdded(base::ASCIIToUTF16("Device 1"), + MockChooserController::kNoSignalStrengthLevelImage, + MockChooserController::NONE); + controller().OptionAdded(base::ASCIIToUTF16("Device 2"), + MockChooserController::kSignalStrengthLevel2Bar, + MockChooserController::PAIRED); + controller().OptionAdded(base::ASCIIToUTF16("Device 3"), + MockChooserController::kSignalStrengthLevel4Bar, + MockChooserController::CONNECTED); + controller().OptionAdded( + base::ASCIIToUTF16("Device 4"), + MockChooserController::kSignalStrengthLevel1Bar, + MockChooserController::PAIRED | MockChooserController::CONNECTED); + RunDialog(); +}
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 290e386..acf909d 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -207,18 +207,10 @@ fill_rect, tp->GetColor(ThemeProperties::COLOR_DETACHED_BOOKMARK_BAR_BACKGROUND)); - // Draw the separators above and below bookmark bar; - // if animating, these are fading in/out. - SkColor separator_color = - tp->GetColor(ThemeProperties::COLOR_DETACHED_BOOKMARK_BAR_SEPARATOR); - - // For the bottom separator, increase the luminance. Either double it or halve - // the distance to 1.0, whichever is less of a difference. - color_utils::HSL hsl; - color_utils::SkColorToHSL(separator_color, &hsl); - hsl.l = std::min((hsl.l + 1) / 2, hsl.l * 2); + // Draw the separator below the detached bookmark bar. BrowserView::Paint1pxHorizontalLine( - canvas, color_utils::HSLToSkColor(hsl, SK_AlphaOPAQUE), + canvas, + tp->GetColor(ThemeProperties::COLOR_DETACHED_BOOKMARK_BAR_SEPARATOR), view->GetLocalBounds(), true); }
diff --git a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc index 9ccfde4..c080507b 100644 --- a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc +++ b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc
@@ -21,9 +21,9 @@ #include "components/autofill/core/browser/country_combobox_model.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/personal_data_manager.h" -#include "components/autofill/core/browser/region_combobox_model.h" #include "components/autofill/core/browser/validation.h" #include "components/autofill/core/common/autofill_constants.h" +#include "components/autofill/core/common/autofill_l10n_util.h" #include "components/payments/content/payment_request_state.h" #include "components/payments/core/payment_request_data_util.h" #include "components/payments/core/payments_profile_comparator.h" @@ -84,6 +84,25 @@ *profile_to_edit_, state()->GetApplicationLocale()); } + if (type == autofill::ADDRESS_HOME_STATE) { + // For the state, check if the inital value matches either a region code or + // a region name. + base::string16 initial_region = profile_to_edit_->GetInfo( + autofill::AutofillType(type), state()->GetApplicationLocale()); + autofill::l10n::CaseInsensitiveCompare compare; + + for (const auto& region : region_model_->GetRegions()) { + base::string16 region_name = base::UTF8ToUTF16(region.second); + if (compare.StringsEqual(initial_region, + base::UTF8ToUTF16(region.first)) || + compare.StringsEqual(initial_region, region_name)) { + return region_name; + } + } + + return initial_region; + } + return profile_to_edit_->GetInfo(autofill::AutofillType(type), state()->GetApplicationLocale()); } @@ -142,6 +161,7 @@ case autofill::ADDRESS_HOME_STATE: { std::unique_ptr<autofill::RegionComboboxModel> model = base::MakeUnique<autofill::RegionComboboxModel>(); + region_model_ = model.get(); if (chosen_country_index_ < countries_.size()) { model->LoadRegionData(countries_[chosen_country_index_].first, state()->GetRegionDataLoader(),
diff --git a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.h b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.h index ab863a74..250e956 100644 --- a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.h +++ b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.h
@@ -14,6 +14,7 @@ #include "base/strings/string16.h" #include "chrome/browser/ui/views/payments/editor_view_controller.h" #include "chrome/browser/ui/views/payments/validating_textfield.h" +#include "components/autofill/core/browser/region_combobox_model.h" namespace autofill { class AutofillProfile; @@ -126,6 +127,9 @@ // Identifies whether we tried and failed to load region data. bool failed_to_load_region_data_; + // Owned by the state combobox, which is owned by this object's base class. + autofill::RegionComboboxModel* region_model_; + // Updates |countries_| with the content of |model| if it's not null, // otherwise use a local model. void UpdateCountries(autofill::CountryComboboxModel* model);
diff --git a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc index 35ea784..c5db770 100644 --- a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc +++ b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc
@@ -967,4 +967,66 @@ EXPECT_TRUE(save_button->enabled()); } +// Tests that the state dropdown is set to the right value if the value from the +// profile is a region code. +IN_PROC_BROWSER_TEST_F(PaymentRequestShippingAddressEditorTest, + DefaultRegion_RegionCode) { + // Add address without a country but a valid state for the default country. + autofill::AutofillProfile profile = autofill::test::GetFullProfile(); + profile.SetInfo(autofill::AutofillType(autofill::ADDRESS_HOME_COUNTRY), + base::ASCIIToUTF16(""), kLocale); + profile.SetInfo(autofill::AutofillType(autofill::ADDRESS_HOME_STATE), + base::ASCIIToUTF16("ca"), kLocale); + AddAutofillProfile(profile); + + InvokePaymentRequestUI(); + SetRegionDataLoader(&test_region_data_loader_); + + test_region_data_loader_.set_synchronous_callback(true); + std::vector<std::pair<std::string, std::string>> regions; + regions.push_back(std::make_pair("AL", "Alabama")); + regions.push_back(std::make_pair("CA", "California")); + test_region_data_loader_.SetRegionData(regions); + OpenShippingAddressSectionScreen(); + + ResetEventObserver(DialogEvent::SHIPPING_ADDRESS_EDITOR_OPENED); + ClickOnChildInListViewAndWait(/*child_index=*/0, /*num_children=*/1, + DialogViewID::SHIPPING_ADDRESS_SHEET_LIST_VIEW); + + // Expect that the state was selected. + EXPECT_EQ(base::ASCIIToUTF16("California"), + GetComboboxValue(autofill::ADDRESS_HOME_STATE)); +} + +// Tests that the state dropdown is set to the right value if the value from the +// profile is a region name. +IN_PROC_BROWSER_TEST_F(PaymentRequestShippingAddressEditorTest, + DefaultRegion_RegionName) { + // Add address without a country but a valid state for the default country. + autofill::AutofillProfile profile = autofill::test::GetFullProfile(); + profile.SetInfo(autofill::AutofillType(autofill::ADDRESS_HOME_COUNTRY), + base::ASCIIToUTF16(""), kLocale); + profile.SetInfo(autofill::AutofillType(autofill::ADDRESS_HOME_STATE), + base::ASCIIToUTF16("california"), kLocale); + AddAutofillProfile(profile); + + InvokePaymentRequestUI(); + SetRegionDataLoader(&test_region_data_loader_); + + test_region_data_loader_.set_synchronous_callback(true); + std::vector<std::pair<std::string, std::string>> regions; + regions.push_back(std::make_pair("AL", "Alabama")); + regions.push_back(std::make_pair("CA", "California")); + test_region_data_loader_.SetRegionData(regions); + OpenShippingAddressSectionScreen(); + + ResetEventObserver(DialogEvent::SHIPPING_ADDRESS_EDITOR_OPENED); + ClickOnChildInListViewAndWait(/*child_index=*/0, /*num_children=*/1, + DialogViewID::SHIPPING_ADDRESS_SHEET_LIST_VIEW); + + // Expect that the state was selected. + EXPECT_EQ(base::ASCIIToUTF16("California"), + GetComboboxValue(autofill::ADDRESS_HOME_STATE)); +} + } // namespace payments
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc index 2d32a54..af7cbcc 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc
@@ -335,7 +335,7 @@ const extensions::DevicePermissions* device_permissions = permissions_manager->GetForExtension(extension->id()); for (const auto& device : devices) { - if (manifest_data->SupportsDevice(device)) { + if (manifest_data->SupportsDevice(*device)) { std::unique_ptr<extensions::UsbDevicePermission::CheckParam> param = extensions::UsbDevicePermission::CheckParam::ForUsbDevice( extension.get(), device.get());
diff --git a/chrome/browser/usb/usb_browsertest.cc b/chrome/browser/usb/usb_browsertest.cc index 011ac35..5f555e9 100644 --- a/chrome/browser/usb/usb_browsertest.cc +++ b/chrome/browser/usb/usb_browsertest.cc
@@ -4,6 +4,7 @@ #include <memory> #include <string> +#include <utility> #include "base/command_line.h" #include "base/memory/ref_counted.h" @@ -74,10 +75,11 @@ ~FakeChooserService() override {} // device::mojom::UsbChooserService: - void GetPermission(const std::vector<device::UsbDeviceFilter>& device_filters, - const GetPermissionCallback& callback) override { + void GetPermission( + std::vector<device::mojom::UsbDeviceFilterPtr> device_filters, + const GetPermissionCallback& callback) override { auto chooser_controller = base::MakeUnique<UsbChooserController>( - render_frame_host_, device_filters, callback); + render_frame_host_, std::move(device_filters), callback); new FakeChooserView(std::move(chooser_controller)); }
diff --git a/chrome/browser/usb/usb_chooser_controller.cc b/chrome/browser/usb/usb_chooser_controller.cc index 9433805..662d292 100644 --- a/chrome/browser/usb/usb_chooser_controller.cc +++ b/chrome/browser/usb/usb_chooser_controller.cc
@@ -26,8 +26,8 @@ #include "content/public/browser/web_contents.h" #include "device/base/device_client.h" #include "device/usb/mojo/type_converters.h" +#include "device/usb/public/cpp/filter_utils.h" #include "device/usb/usb_device.h" -#include "device/usb/usb_device_filter.h" #include "device/usb/usb_ids.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" @@ -35,7 +35,6 @@ using content::RenderFrameHost; using content::WebContents; using device::UsbDevice; -using device::UsbDeviceFilter; namespace { @@ -74,12 +73,12 @@ UsbChooserController::UsbChooserController( RenderFrameHost* render_frame_host, - const std::vector<UsbDeviceFilter>& device_filters, + std::vector<device::mojom::UsbDeviceFilterPtr> device_filters, const device::mojom::UsbChooserService::GetPermissionCallback& callback) : ChooserController(render_frame_host, IDS_USB_DEVICE_CHOOSER_PROMPT_ORIGIN, IDS_USB_DEVICE_CHOOSER_PROMPT_EXTENSION_NAME), - filters_(device_filters), + filters_(std::move(device_filters)), callback_(callback), usb_service_observer_(this), weak_factory_(this) { @@ -223,7 +222,7 @@ bool UsbChooserController::DisplayDevice( scoped_refptr<UsbDevice> device) const { - if (!UsbDeviceFilter::MatchesAny(*device, filters_)) + if (!UsbDeviceFilterMatchesAny(filters_, *device)) return false; if (UsbBlocklist::Get().IsExcluded(device))
diff --git a/chrome/browser/usb/usb_chooser_controller.h b/chrome/browser/usb/usb_chooser_controller.h index 02611fd..22bc030 100644 --- a/chrome/browser/usb/usb_chooser_controller.h +++ b/chrome/browser/usb/usb_chooser_controller.h
@@ -24,7 +24,6 @@ namespace device { class UsbDevice; -struct UsbDeviceFilter; } class UsbChooserContext; @@ -36,7 +35,7 @@ public: UsbChooserController( content::RenderFrameHost* render_frame_host, - const std::vector<device::UsbDeviceFilter>& device_filters, + std::vector<device::mojom::UsbDeviceFilterPtr> device_filters, const device::mojom::UsbChooserService::GetPermissionCallback& callback); ~UsbChooserController() override; @@ -62,7 +61,7 @@ const std::vector<scoped_refptr<device::UsbDevice>>& devices); bool DisplayDevice(scoped_refptr<device::UsbDevice> device) const; - std::vector<device::UsbDeviceFilter> filters_; + std::vector<device::mojom::UsbDeviceFilterPtr> filters_; device::mojom::UsbChooserService::GetPermissionCallback callback_; GURL requesting_origin_; GURL embedding_origin_;
diff --git a/chrome/browser/usb/usb_chooser_controller_unittest.cc b/chrome/browser/usb/usb_chooser_controller_unittest.cc index 8e63cd5..484c5d9 100644 --- a/chrome/browser/usb/usb_chooser_controller_unittest.cc +++ b/chrome/browser/usb/usb_chooser_controller_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include <memory> +#include <utility> #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -47,13 +48,13 @@ void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); - std::vector<device::UsbDeviceFilter> device_filters; + std::vector<device::mojom::UsbDeviceFilterPtr> device_filters; device::mojom::UsbChooserService::GetPermissionCallback callback; content::WebContentsTester* web_contents_tester = content::WebContentsTester::For(web_contents()); web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); - usb_chooser_controller_.reset( - new UsbChooserController(main_rfh(), device_filters, callback)); + usb_chooser_controller_.reset(new UsbChooserController( + main_rfh(), std::move(device_filters), callback)); mock_usb_chooser_view_.reset(new MockUsbChooserView()); usb_chooser_controller_->set_view(mock_usb_chooser_view_.get()); }
diff --git a/chrome/browser/usb/web_usb_chooser_service.cc b/chrome/browser/usb/web_usb_chooser_service.cc index 2dfacec..00a5fc4 100644 --- a/chrome/browser/usb/web_usb_chooser_service.cc +++ b/chrome/browser/usb/web_usb_chooser_service.cc
@@ -29,13 +29,14 @@ } void WebUsbChooserService::GetPermission( - const std::vector<device::UsbDeviceFilter>& device_filters, + std::vector<device::mojom::UsbDeviceFilterPtr> device_filters, const GetPermissionCallback& callback) { content::WebContents* web_contents = content::WebContents::FromRenderFrameHost(render_frame_host_); Browser* browser = chrome::FindBrowserWithWebContents(web_contents); std::unique_ptr<UsbChooserController> usb_chooser_controller( - new UsbChooserController(render_frame_host_, device_filters, callback)); + new UsbChooserController(render_frame_host_, std::move(device_filters), + callback)); std::unique_ptr<ChooserBubbleDelegate> chooser_bubble_delegate( new ChooserBubbleDelegate(render_frame_host_, std::move(usb_chooser_controller)));
diff --git a/chrome/browser/usb/web_usb_chooser_service.h b/chrome/browser/usb/web_usb_chooser_service.h index 9dd7e88c..99dae9b 100644 --- a/chrome/browser/usb/web_usb_chooser_service.h +++ b/chrome/browser/usb/web_usb_chooser_service.h
@@ -27,8 +27,9 @@ ~WebUsbChooserService() override; // device::usb::ChooserService: - void GetPermission(const std::vector<device::UsbDeviceFilter>& device_filters, - const GetPermissionCallback& callback) override; + void GetPermission( + std::vector<device::mojom::UsbDeviceFilterPtr> device_filters, + const GetPermissionCallback& callback) override; void Bind(device::mojom::UsbChooserServiceRequest request);
diff --git a/chrome/installer/linux/debian/expected_deps_x64_jessie b/chrome/installer/linux/debian/expected_deps_x64_jessie index e88b1fd..3f08359e 100644 --- a/chrome/installer/linux/debian/expected_deps_x64_jessie +++ b/chrome/installer/linux/debian/expected_deps_x64_jessie
@@ -4,14 +4,14 @@ libc6 (>= 2.15) libcairo2 (>= 1.6.0) libcups2 (>= 1.4.0) -libdbus-1-3 (>= 1.1.4) +libdbus-1-3 (>= 1.2.14) libexpat1 (>= 2.0.1) libfontconfig1 (>= 2.11) libgcc1 (>= 1:4.1.1) libgconf-2-4 (>= 3.2.5) libgdk-pixbuf2.0-0 (>= 2.22.0) libglib2.0-0 (>= 2.28.0) -libgtk-3-0 (>= 3.3.16) +libgtk-3-0 (>= 3.9.10) libnspr4 (>= 2:4.9-2~) libnss3 (>= 2:3.13.4-2~) libpango-1.0-0 (>= 1.14.0)
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn index 87494b8d..7923c36 100644 --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn
@@ -84,8 +84,8 @@ "prerender/prerender_helper.h", "prerender/prerenderer_client.cc", "prerender/prerenderer_client.h", - "safe_browsing/safe_browsing_url_loader_throttle.cc", - "safe_browsing/safe_browsing_url_loader_throttle.h", + "safe_browsing/renderer_url_loader_throttle.cc", + "safe_browsing/renderer_url_loader_throttle.h", "sandbox_status_extension_android.cc", "sandbox_status_extension_android.h", "searchbox/search_bouncer.cc",
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index fedd53c..d55fd27 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -57,7 +57,7 @@ #include "chrome/renderer/prerender/prerender_helper.h" #include "chrome/renderer/prerender/prerenderer_client.h" #include "chrome/renderer/safe_browsing/phishing_classifier_delegate.h" -#include "chrome/renderer/safe_browsing/safe_browsing_url_loader_throttle.h" +#include "chrome/renderer/safe_browsing/renderer_url_loader_throttle.h" #include "chrome/renderer/searchbox/search_bouncer.h" #include "chrome/renderer/searchbox/searchbox.h" #include "chrome/renderer/searchbox/searchbox_extension.h" @@ -1213,7 +1213,7 @@ } RenderFrame* render_frame = content::RenderFrame::FromWebFrame(frame); throttles->push_back( - base::MakeUnique<safe_browsing::SafeBrowsingURLLoaderThrottle>( + base::MakeUnique<safe_browsing::RendererURLLoaderThrottle>( safe_browsing_.get(), render_frame->GetRoutingID())); }
diff --git a/chrome/renderer/resources/extensions/input.ime_custom_bindings.js b/chrome/renderer/resources/extensions/input.ime_custom_bindings.js index 512c4e8..f3daa9c 100644 --- a/chrome/renderer/resources/extensions/input.ime_custom_bindings.js +++ b/chrome/renderer/resources/extensions/input.ime_custom_bindings.js
@@ -5,41 +5,48 @@ // Custom binding for the input ime API. Only injected into the // v8 contexts for extensions which have permission for the API. -var binding = require('binding').Binding.create('input.ime'); - -var Event = require('event_bindings').Event; - +var binding = apiBridge || require('binding').Binding.create('input.ime'); var appWindowNatives = requireNative('app_window_natives'); +var registerArgumentMassager = bindingUtil ? + $Function.bind(bindingUtil.registerEventArgumentMassager, bindingUtil) : + require('event_bindings').registerArgumentMassager; + +// TODO(crbug.com/733825): These bindings have some issues. + +var inputIme; +registerArgumentMassager('input.ime.onKeyEvent', + function(args, dispatch) { + var keyData = args[1]; + var result = false; + try { + // dispatch() is weird - it returns an object {results: array<results>} iff + // there is at least one result value that !== undefined. Since onKeyEvent + // has a maximum of one listener, we know that any result we find is the one + // we're interested in. + var dispatchResult = dispatch(args); + if (dispatchResult && dispatchResult.results) + result = dispatchResult.results[0]; + } catch (e) { + console.error('Error in event handler for onKeyEvent: ' + e.stack); + } + if (!inputIme.onKeyEvent.async) + inputIme.keyEventHandled(keyData.requestId, result); +}); binding.registerCustomHook(function(api) { - var input_ime = api.compiledApi; + inputIme = api.compiledApi; - input_ime.onKeyEvent.dispatchToListener = function(callback, args) { - var engineID = args[0]; - var keyData = args[1]; - - var result = false; - try { - result = $Function.call(Event.prototype.dispatchToListener, - this, callback, args); - } catch (e) { - console.error('Error in event handler for onKeyEvent: ' + e.stack); - } - if (!input_ime.onKeyEvent.async) { - input_ime.keyEventHandled(keyData.requestId, result); - } - }; - - input_ime.onKeyEvent.addListener = function(cb, opt_extraInfo) { - input_ime.onKeyEvent.async = false; + var originalAddListener = inputIme.onKeyEvent.addListener; + inputIme.onKeyEvent.addListener = function(cb, opt_extraInfo) { + inputIme.onKeyEvent.async = false; if (opt_extraInfo instanceof Array) { for (var i = 0; i < opt_extraInfo.length; ++i) { - if (opt_extraInfo[i] == "async") { - input_ime.onKeyEvent.async = true; + if (opt_extraInfo[i] == 'async') { + inputIme.onKeyEvent.async = true; } } } - $Function.call(Event.prototype.addListener, this, cb); + $Function.call(originalAddListener, this, cb); }; api.apiFunctions.setCustomCallback('createWindow', @@ -57,4 +64,5 @@ }); }); -exports.$set('binding', binding.generate()); +if (!apiBridge) + exports.$set('binding', binding.generate());
diff --git a/chrome/renderer/safe_browsing/safe_browsing_url_loader_throttle.cc b/chrome/renderer/safe_browsing/renderer_url_loader_throttle.cc similarity index 73% rename from chrome/renderer/safe_browsing/safe_browsing_url_loader_throttle.cc rename to chrome/renderer/safe_browsing/renderer_url_loader_throttle.cc index 16837d5..d2ea46c 100644 --- a/chrome/renderer/safe_browsing/safe_browsing_url_loader_throttle.cc +++ b/chrome/renderer/safe_browsing/renderer_url_loader_throttle.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/renderer/safe_browsing/safe_browsing_url_loader_throttle.h" +#include "chrome/renderer/safe_browsing/renderer_url_loader_throttle.h" #include "base/logging.h" #include "mojo/public/cpp/bindings/interface_request.h" @@ -10,16 +10,16 @@ namespace safe_browsing { -SafeBrowsingURLLoaderThrottle::SafeBrowsingURLLoaderThrottle( +RendererURLLoaderThrottle::RendererURLLoaderThrottle( mojom::SafeBrowsing* safe_browsing, int render_frame_id) : safe_browsing_(safe_browsing), render_frame_id_(render_frame_id), weak_factory_(this) {} -SafeBrowsingURLLoaderThrottle::~SafeBrowsingURLLoaderThrottle() = default; +RendererURLLoaderThrottle::~RendererURLLoaderThrottle() = default; -void SafeBrowsingURLLoaderThrottle::WillStartRequest( +void RendererURLLoaderThrottle::WillStartRequest( const GURL& url, int load_flags, content::ResourceType resource_type, @@ -34,16 +34,15 @@ safe_browsing_->CreateCheckerAndCheck( render_frame_id_, mojo::MakeRequest(&url_checker_), url, load_flags, resource_type, - base::BindOnce(&SafeBrowsingURLLoaderThrottle::OnCheckUrlResult, + base::BindOnce(&RendererURLLoaderThrottle::OnCheckUrlResult, weak_factory_.GetWeakPtr())); safe_browsing_ = nullptr; - url_checker_.set_connection_error_handler( - base::Bind(&SafeBrowsingURLLoaderThrottle::OnConnectionError, - base::Unretained(this))); + url_checker_.set_connection_error_handler(base::Bind( + &RendererURLLoaderThrottle::OnConnectionError, base::Unretained(this))); } -void SafeBrowsingURLLoaderThrottle::WillRedirectRequest( +void RendererURLLoaderThrottle::WillRedirectRequest( const net::RedirectInfo& redirect_info, bool* defer) { // If |blocked_| is true, the resource load has been canceled and there @@ -58,11 +57,11 @@ pending_checks_++; url_checker_->CheckUrl( redirect_info.new_url, - base::BindOnce(&SafeBrowsingURLLoaderThrottle::OnCheckUrlResult, + base::BindOnce(&RendererURLLoaderThrottle::OnCheckUrlResult, base::Unretained(this))); } -void SafeBrowsingURLLoaderThrottle::WillProcessResponse(bool* defer) { +void RendererURLLoaderThrottle::WillProcessResponse(bool* defer) { // If |blocked_| is true, the resource load has been canceled and there // shouldn't be such a notification. DCHECK(!blocked_); @@ -71,7 +70,7 @@ *defer = true; } -void SafeBrowsingURLLoaderThrottle::OnCheckUrlResult(bool safe) { +void RendererURLLoaderThrottle::OnCheckUrlResult(bool safe) { if (blocked_ || !url_checker_) return; @@ -92,7 +91,7 @@ } } -void SafeBrowsingURLLoaderThrottle::OnConnectionError() { +void RendererURLLoaderThrottle::OnConnectionError() { DCHECK(!blocked_); // If a service-side disconnect happens, treat all URLs as if they are safe.
diff --git a/chrome/renderer/safe_browsing/renderer_url_loader_throttle.h b/chrome/renderer/safe_browsing/renderer_url_loader_throttle.h new file mode 100644 index 0000000..f332381 --- /dev/null +++ b/chrome/renderer/safe_browsing/renderer_url_loader_throttle.h
@@ -0,0 +1,54 @@ +// 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 CHROME_RENDERER_SAFE_BROWSING_RENDERER_URL_LOADER_THROTTLE_H_ +#define CHROME_RENDERER_SAFE_BROWSING_RENDERER_URL_LOADER_THROTTLE_H_ + +#include "base/memory/weak_ptr.h" +#include "components/safe_browsing/common/safe_browsing.mojom.h" +#include "content/public/common/url_loader_throttle.h" + +namespace safe_browsing { + +// RendererURLLoaderThrottle is used in renderer processes to query +// SafeBrowsing and determine whether a URL and its redirect URLs are safe to +// load. It defers response processing until all URL checks are completed; +// cancels the load if any URLs turn out to be bad. +class RendererURLLoaderThrottle : public content::URLLoaderThrottle { + public: + // |safe_browsing| must stay alive until WillStartRequest() (if it is called) + // or the end of this object. + // |render_frame_id| is used for displaying SafeBrowsing UI when necessary. + RendererURLLoaderThrottle(mojom::SafeBrowsing* safe_browsing, + int render_frame_id); + ~RendererURLLoaderThrottle() override; + + // content::URLLoaderThrottle implementation. + void WillStartRequest(const GURL& url, + int load_flags, + content::ResourceType resource_type, + bool* defer) override; + void WillRedirectRequest(const net::RedirectInfo& redirect_info, + bool* defer) override; + void WillProcessResponse(bool* defer) override; + + private: + void OnCheckUrlResult(bool safe); + + void OnConnectionError(); + + mojom::SafeBrowsing* safe_browsing_; + const int render_frame_id_; + + mojom::SafeBrowsingUrlCheckerPtr url_checker_; + + size_t pending_checks_ = 0; + bool blocked_ = false; + + base::WeakPtrFactory<RendererURLLoaderThrottle> weak_factory_; +}; + +} // namespace safe_browsing + +#endif // CHROME_RENDERER_SAFE_BROWSING_RENDERER_URL_LOADER_THROTTLE_H_
diff --git a/chrome/renderer/safe_browsing/safe_browsing_url_loader_throttle.h b/chrome/renderer/safe_browsing/safe_browsing_url_loader_throttle.h deleted file mode 100644 index 3cd284a..0000000 --- a/chrome/renderer/safe_browsing/safe_browsing_url_loader_throttle.h +++ /dev/null
@@ -1,60 +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 CHROME_RENDERER_SAFE_BROWSING_SAFE_BROWSING_URL_LOADER_THROTTLE_H_ -#define CHROME_RENDERER_SAFE_BROWSING_SAFE_BROWSING_URL_LOADER_THROTTLE_H_ - -#include "base/memory/weak_ptr.h" -#include "components/safe_browsing/common/safe_browsing.mojom.h" -#include "content/public/common/url_loader_throttle.h" - -namespace chrome { -namespace mojom { -class SafeBrowsing; -} -} - -namespace safe_browsing { - -// SafeBrowsingURLLoaderThrottle queries SafeBrowsing to determine whether the -// URL and also redirect URLs are safe to load. It defers response processing -// until all URL checks are completed; cancels the load if any URLs turn out to -// be bad. -class SafeBrowsingURLLoaderThrottle : public content::URLLoaderThrottle { - public: - // |safe_browsing| must stay alive until WillStartRequest() (if it is called) - // or the end of this object. - // |render_frame_id| is used for displaying SafeBrowsing UI when necessary. - SafeBrowsingURLLoaderThrottle(mojom::SafeBrowsing* safe_browsing, - int render_frame_id); - ~SafeBrowsingURLLoaderThrottle() override; - - // content::URLLoaderThrottle implementation. - void WillStartRequest(const GURL& url, - int load_flags, - content::ResourceType resource_type, - bool* defer) override; - void WillRedirectRequest(const net::RedirectInfo& redirect_info, - bool* defer) override; - void WillProcessResponse(bool* defer) override; - - private: - void OnCheckUrlResult(bool safe); - - void OnConnectionError(); - - mojom::SafeBrowsing* safe_browsing_; - const int render_frame_id_; - - mojom::SafeBrowsingUrlCheckerPtr url_checker_; - - size_t pending_checks_ = 0; - bool blocked_ = false; - - base::WeakPtrFactory<SafeBrowsingURLLoaderThrottle> weak_factory_; -}; - -} // namespace safe_browsing - -#endif // CHROME_RENDERER_SAFE_BROWSING_SAFE_BROWSING_URL_LOADER_THROTTLE_H_
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index bab75a5..9434f09 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1522,6 +1522,7 @@ "../browser/ui/toolbar/mock_component_toolbar_actions_factory.h", "../browser/ui/update_chrome_dialog_browsertest.cc", "../browser/ui/views/chrome_cleaner_dialog_browsertest_win.cc", + "../browser/ui/views/extensions/chooser_dialog_view_browsertest.cc", "../browser/ui/views/hung_renderer_view_browsertest.cc", "../browser/ui/webui/bidi_checker_web_ui_test.cc", "../browser/ui/webui/bidi_checker_web_ui_test.h",
diff --git a/chrome/test/data/webui/settings/device_page_tests.js b/chrome/test/data/webui/settings/device_page_tests.js index f02d8d0..227fcfe 100644 --- a/chrome/test/data/webui/settings/device_page_tests.js +++ b/chrome/test/data/webui/settings/device_page_tests.js
@@ -85,31 +85,11 @@ return { ash: { night_light: { - enabled: { - key: 'ash.night_light.enabled', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - color_temperature: { - key: 'ash.night_light.color_temperature', - type: chrome.settingsPrivate.PrefType.NUMBER, - value: 0, - }, schedule_type: { key: 'ash.night_light.schedule_type', type: chrome.settingsPrivate.PrefType.NUMBER, value: 0, }, - custom_start_time: { - key: 'ash.night_light.custom_start_time', - type: chrome.settingsPrivate.PrefType.NUMBER, - value: 0, - }, - custom_end_time: { - key: 'ash.night_light.custom_end_time', - type: chrome.settingsPrivate.PrefType.NUMBER, - value: 0, - }, }, }, settings: {
diff --git a/chrome/utility/extensions/extensions_handler.cc b/chrome/utility/extensions/extensions_handler.cc index c02c962..a55385e6 100644 --- a/chrome/utility/extensions/extensions_handler.cc +++ b/chrome/utility/extensions/extensions_handler.cc
@@ -21,7 +21,6 @@ #include "media/base/media.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/service_manager/public/cpp/bind_source_info.h" -#include "services/service_manager/public/cpp/binder_registry.h" #include "ui/base/ui_base_switches.h" #if !defined(MEDIA_DISABLE_FFMPEG)
diff --git a/chrome/utility/extensions/extensions_handler.h b/chrome/utility/extensions/extensions_handler.h index 6230fa8..f2e1141 100644 --- a/chrome/utility/extensions/extensions_handler.h +++ b/chrome/utility/extensions/extensions_handler.h
@@ -14,15 +14,12 @@ #include "chrome/utility/utility_message_handler.h" #include "extensions/features/features.h" #include "extensions/utility/utility_handler.h" +#include "services/service_manager/public/cpp/binder_registry.h" #if !BUILDFLAG(ENABLE_EXTENSIONS) #error "Extensions must be enabled" #endif -namespace service_manager { -class BinderRegistry; -} - namespace extensions { // Dispatches IPCs for Chrome extensions utility messages.
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn index 02f7185..97ab081 100644 --- a/chromecast/BUILD.gn +++ b/chromecast/BUILD.gn
@@ -309,8 +309,6 @@ additional_options = [ "--ozone-platform=headless --test-launcher-bot-mode" ] - build_tests = true - test_groups = [ ":cast_tests" ] if (chromecast_branding != "public") { @@ -336,7 +334,6 @@ build_list_path = "$root_out_dir/junit/build_junit_test_list.txt" runtime_deps_path = "$root_out_dir/junit/runtime_deps.json" run_list_path = "$root_out_dir/junit/run_junit_test_list.txt" - build_tests = true test_groups = [ ":cast_junit_tests" ] if (chromecast_branding != "public") { test_groups += [ "//chromecast/internal:internal_cast_junit_tests" ]
diff --git a/chromecast/base/cast_features.cc b/chromecast/base/cast_features.cc index 636f145..d65ce5f 100644 --- a/chromecast/base/cast_features.cc +++ b/chromecast/base/cast_features.cc
@@ -40,8 +40,79 @@ g_experiment_ids.Get().swap(ids); g_experiment_ids_initialized = true; } + } // namespace +// PLEASE READ! +// Cast Platform Features are listed below. These features may be +// toggled via configs fetched from DCS for devices in the field, or via +// command-line flags set by the developer. For the end-to-end details of the +// system design, please see go/dcs-experiments. +// +// Below are useful steps on how to use these features in your code. +// +// 1) Declaring and defining the feature. +// All Cast Platform Features should be declared in a common file with other +// Cast Platform Features (ex. chromecast/base/cast_features.h). When +// defining your feature, you will need to assign a default value. This is +// the value that the feature will hold until overriden by the server or the +// command line. Here's an exmaple: +// +// const base::Feature kSuperSecretSauce{ +// "enable-super-secret-sauce", base::FEATURE_DISABLED_BY_DEFAULT}; +// +// IMPORTANT NOTE: +// The first parameter that you pass in the definition is the feature's name. +// This MUST match the DCS experiement key for this feature. Use dashes (not +// underscores) in the names. +// +// 2) Using the feature in client code. +// Using these features in your code is easy. Here's an example: +// +// #include “base/feature_list.h” +// #include “chromecast/base/chromecast_switches.h” +// +// std::unique_ptr<Foo> CreateFoo() { +// if (base::FeatureList::IsEnabled(kSuperSecretSauce)) +// return base::MakeUnique<SuperSecretFoo>(); +// return base::MakeUnique<BoringOldFoo>(); +// } +// +// base::FeatureList can be called from any thread, in any process, at any +// time after PreCreateThreads(). It will return whether the feature is +// enabled. +// +// 3) Overriding the default value from the server. +// For devices in the field, DCS will issue different configs to different +// groups of devices, allowing us to run experiments on features. These +// feature settings will manifest on the next boot of cast_shell. In the +// example, if the latest config for a particular device set the value of +// kSuperSecretSauce to true, the appropriate code path would be taken. +// Otherwise, the default value, false, would be used. For more details on +// setting up experiments, see go/dcs-launch. +// +// 4) Overriding the default and server values from the command-line. +// While the server value trumps the default values, the command line trumps +// both. Enable features by passing this command line arg to cast_shell: +// +// --enable-features=enable-foo,enable-super-secret-sauce +// +// Features are separated by commas. Disable features by passing: +// +// --disable-features=enable-foo,enable-bar +// + +// Begin Chromecast Feature definitions. + +// Enables the use of QUIC in Cast-specific URLRequestContextGetters. See +// chromecast/browser/url_request_context_factory.cc for usage. +// NOTE: This feature has a legacy name - do not use it as your convention. +// Dashes, not underscores, should be used in Feature names. +const base::Feature kEnableQuic{"enable_quic", + base::FEATURE_DISABLED_BY_DEFAULT}; + +// End Chromecast Feature definitions. + // An iterator for a base::DictionaryValue. Use an alias for brevity in loops. using Iterator = base::DictionaryValue::Iterator;
diff --git a/chromecast/base/cast_features.h b/chromecast/base/cast_features.h index 928399a..138bd97 100644 --- a/chromecast/base/cast_features.h +++ b/chromecast/base/cast_features.h
@@ -20,6 +20,13 @@ namespace chromecast { +// Add Cast Features here. +extern const base::Feature kEnableQuic; + +// Below are utilities needed by the Cast receiver to persist feature +// information. Client code which is simply querying the status of a feature +// will not need to use these utilities. + // Initialize the global base::FeatureList instance, taking into account // overrides from DCS and the command line. |dcs_features| and // |dcs_experiment_ids| are read from the PrefService in the browser process.
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc index cd8783e..a72abae 100644 --- a/chromecast/browser/cast_browser_main_parts.cc +++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -514,11 +514,6 @@ cast_browser_process_->browser_context(), cast_browser_process_->pref_service(), url_request_context_factory_->GetSystemGetter(), - base::BindOnce(&URLRequestContextFactory::DisableQuic, - // Safe since |url_request_context_factory_| is owned - // by CastContentBrowserClient, which lives for the - // entire lifetime of cast_shell. - base::Unretained(url_request_context_factory_)), video_plane_controller_.get(), window_manager_.get())); cast_browser_process_->cast_service()->Initialize();
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc index d744703c..39b22c1 100644 --- a/chromecast/browser/cast_content_browser_client.cc +++ b/chromecast/browser/cast_content_browser_client.cc
@@ -60,7 +60,6 @@ #include "net/ssl/ssl_cert_request_info.h" #include "net/url_request/url_request_context_getter.h" #include "services/service_manager/public/cpp/bind_source_info.h" -#include "services/service_manager/public/cpp/binder_registry.h" #include "ui/base/resource/resource_bundle.h" #include "ui/display/display.h" #include "ui/display/screen.h" @@ -149,7 +148,6 @@ content::BrowserContext* browser_context, PrefService* pref_service, net::URLRequestContextGetter* request_context_getter, - DisableQuicClosure disable_quic_closure, media::VideoPlaneController* video_plane_controller, CastWindowManager* window_manager) { return base::MakeUnique<CastServiceSimple>(browser_context, pref_service,
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h index 27a6447..01278c15 100644 --- a/chromecast/browser/cast_content_browser_client.h +++ b/chromecast/browser/cast_content_browser_client.h
@@ -10,7 +10,6 @@ #include <string> #include <vector> -#include "base/callback_forward.h" #include "base/macros.h" #include "base/single_thread_task_runner.h" #include "build/build_config.h" @@ -18,6 +17,7 @@ #include "chromecast/chromecast_features.h" #include "content/public/browser/certificate_request_result_type.h" #include "content/public/browser/content_browser_client.h" +#include "services/service_manager/public/cpp/binder_registry.h" class PrefService; @@ -34,10 +34,6 @@ class X509Certificate; } -namespace service_manager { -class BinderRegistry; -} - namespace chromecast { class CastService; class CastWindowManager; @@ -58,8 +54,6 @@ class CastResourceDispatcherHostDelegate; class URLRequestContextFactory; -using DisableQuicClosure = base::OnceClosure; - class CastContentBrowserClient : public content::ContentBrowserClient { public: // Creates an implementation of CastContentBrowserClient. Platform should @@ -81,7 +75,6 @@ content::BrowserContext* browser_context, PrefService* pref_service, net::URLRequestContextGetter* request_context_getter, - DisableQuicClosure disable_quic_closure, media::VideoPlaneController* video_plane_controller, CastWindowManager* window_manager);
diff --git a/chromecast/browser/url_request_context_factory.cc b/chromecast/browser/url_request_context_factory.cc index 1305f99..f9a7eb76 100644 --- a/chromecast/browser/url_request_context_factory.cc +++ b/chromecast/browser/url_request_context_factory.cc
@@ -12,6 +12,7 @@ #include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/task_scheduler/post_task.h" +#include "chromecast/base/cast_features.h" #include "chromecast/base/chromecast_switches.h" #include "chromecast/browser/cast_browser_process.h" #include "chromecast/browser/cast_http_user_agent_settings.h" @@ -164,8 +165,7 @@ system_network_delegate_(CastNetworkDelegate::Create()), system_dependencies_initialized_(false), main_dependencies_initialized_(false), - media_dependencies_initialized_(false), - enable_quic_(true) {} + media_dependencies_initialized_(false) {} URLRequestContextFactory::~URLRequestContextFactory() { pref_proxy_config_tracker_impl_->DetachFromPrefService(); @@ -328,8 +328,12 @@ session_context->proxy_service = proxy_service_.get(); session_params->ignore_certificate_errors = ignore_certificate_errors; - LOG(INFO) << "Set HttpNetworkSessionParams.enable_quic = " << enable_quic_; - session_params->enable_quic = enable_quic_; + + // Enable QUIC if instructed by DCS. This remains constant for the lifetime of + // the process. + session_params->enable_quic = base::FeatureList::IsEnabled(kEnableQuic); + LOG(INFO) << "Set HttpNetworkSessionParams.enable_quic = " + << session_params->enable_quic; } net::URLRequestContext* URLRequestContextFactory::CreateSystemRequestContext() { @@ -437,43 +441,5 @@ LOG(INFO) << "Initialized system network delegate."; } -void URLRequestContextFactory::DisableQuic() { - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::Bind(&URLRequestContextFactory::DisableQuicOnBrowserIOThread, - base::Unretained(this))); -} - -void URLRequestContextFactory::DisableQuicOnBrowserIOThread() { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (!enable_quic_) - return; - - LOG(INFO) << "Disabled QUIC."; - - enable_quic_ = false; - - if (main_getter_) { - main_getter_->GetURLRequestContext() - ->http_transaction_factory() - ->GetSession() - ->DisableQuic(); - } - - if (system_getter_) { - system_getter_->GetURLRequestContext() - ->http_transaction_factory() - ->GetSession() - ->DisableQuic(); - } - - if (media_getter_) { - media_getter_->GetURLRequestContext() - ->http_transaction_factory() - ->GetSession() - ->DisableQuic(); - } -} - } // namespace shell } // namespace chromecast
diff --git a/chromecast/browser/url_request_context_factory.h b/chromecast/browser/url_request_context_factory.h index ba8deda..85814a4 100644 --- a/chromecast/browser/url_request_context_factory.h +++ b/chromecast/browser/url_request_context_factory.h
@@ -67,8 +67,6 @@ // after the CastService is created, but before any URL requests are made. void InitializeNetworkDelegates(); - void DisableQuic(); - private: class URLRequestContextGetter; class MainURLRequestContextGetter; @@ -86,7 +84,6 @@ bool ignore_certificate_errors, net::HttpNetworkSession::Params* session_params, net::HttpNetworkSession::Context* session_context); - void DisableQuicOnBrowserIOThread(); // These are called by the RequestContextGetters to create each // RequestContext. @@ -136,11 +133,6 @@ std::unique_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_impl_; - // Determines if QUIC is enabled for a URLContextGetter when it is created. - // QUIC can be disabled at runtime by calling DisableQuic() above. - // Only accessed on content::BrowserThread::IO thread. - bool enable_quic_; - net::NetLog* net_log_; };
diff --git a/chromecast/build/tests/cast_test.gni b/chromecast/build/tests/cast_test.gni index 2da7866..0621295 100644 --- a/chromecast/build/tests/cast_test.gni +++ b/chromecast/build/tests/cast_test.gni
@@ -70,6 +70,13 @@ import("//chromecast/chromecast.gni") import("//testing/test.gni") +declare_args() { + # Set this true to build all tests in a cast_test_group_list by default. This + # can be overriden in each cast_test_group_list instance by setting + # |build_tests|. + build_cast_tests_by_default = true +} + # Do not allow mixing of gtests and junit tests. All gtests must go into one # directory, while all junit tests must go into another directory. _gtest_gen_dir = "$root_gen_dir/chromecast/tests" @@ -308,9 +315,12 @@ # Options which are passed to the python script, and applied to every test # # build_tests (optional) -# Set this to true to build all of the tests included in |test_groups|. -# Defaults to false. Note that if this is set to true, the test targets -# will be built after all the lists are generated. +# If true, all of the tests included in |test_groups| will be built as +# dependencies of this target. If false, only the lists will be generated. +# If not explicitly set, this defaults to the value of +# |build_cast_tests_by_default|. Note that if this is set to true, +# the test targets will be built after all the lists are generated. +# # test_type (optional) # A string, which must be either "junit" or "gtest". If not defined, # defaults to "gtest". @@ -357,12 +367,18 @@ _filter_actions += [ _test_group + "_filters" ] } + # Decide whether tests are built as dependencies. + _build_cast_tests = build_cast_tests_by_default + if (defined(invoker.build_tests)) { + _build_cast_tests = invoker.build_tests + } + # Generate a list of the groups of targets, so that they can be depended upon # by the "pack_run" step and built when this target is invoked. - if (defined(invoker.build_tests) && invoker.build_tests) { - _build_tests = [] + if (_build_cast_tests) { + _build_test_targets = [] foreach(_test_group, invoker.test_groups) { - _build_tests += [ _test_group + "_build_tests" ] + _build_test_targets += [ _test_group + "_build_tests" ] } } @@ -429,10 +445,10 @@ # script executes. deps += _filter_actions - # If |build_tests| has been set to true, depend on the testing targets so - # that the tests are built. - if (defined(_build_tests)) { - deps += _build_tests + # If |_build_cast_tests| has been set to true, depend on the testing targets + # so that the tests are built. + if (_build_cast_tests) { + deps += _build_test_targets } if (chromecast_branding != "public") {
diff --git a/chromeos/components/tether/ble_scanner.cc b/chromeos/components/tether/ble_scanner.cc index 5ed761d..709e5f5 100644 --- a/chromeos/components/tether/ble_scanner.cc +++ b/chromeos/components/tether/ble_scanner.cc
@@ -228,7 +228,7 @@ std::string service_data_str; char* string_contents_ptr = base::WriteInto(&service_data_str, service_data->size() + 1); - memcpy(string_contents_ptr, service_data->data(), service_data->size() + 1); + memcpy(string_contents_ptr, service_data->data(), service_data->size()); CheckForMatchingScanFilters(bluetooth_device, service_data_str); }
diff --git a/components/autofill/core/browser/region_combobox_model.h b/components/autofill/core/browser/region_combobox_model.h index d148e53..e6a89b2 100644 --- a/components/autofill/core/browser/region_combobox_model.h +++ b/components/autofill/core/browser/region_combobox_model.h
@@ -43,6 +43,10 @@ bool failed_to_load_data() const { return failed_to_load_data_; } + const std::vector<std::pair<std::string, std::string>>& GetRegions() const { + return regions_; + } + // ui::ComboboxModel implementation: int GetItemCount() const override; base::string16 GetItemAt(int index) override;
diff --git a/components/cast_channel/cast_socket.cc b/components/cast_channel/cast_socket.cc index 555c5a0..e60004e 100644 --- a/components/cast_channel/cast_socket.cc +++ b/components/cast_channel/cast_socket.cc
@@ -26,6 +26,7 @@ #include "components/cast_channel/cast_framer.h" #include "components/cast_channel/cast_message_util.h" #include "components/cast_channel/cast_transport.h" +#include "components/cast_channel/keep_alive_delegate.h" #include "components/cast_channel/logger.h" #include "components/cast_channel/proto/cast_channel.pb.h" #include "net/base/address_list.h" @@ -87,29 +88,33 @@ CastSocketImpl::CastSocketImpl(const net::IPEndPoint& ip_endpoint, net::NetLog* net_log, - const base::TimeDelta& timeout, - bool keep_alive, + base::TimeDelta timeout, + base::TimeDelta liveness_timeout, + base::TimeDelta ping_interval, const scoped_refptr<Logger>& logger, uint64_t device_capabilities) : CastSocketImpl(ip_endpoint, net_log, timeout, - keep_alive, + liveness_timeout, + ping_interval, logger, device_capabilities, AuthContext::Create()) {} CastSocketImpl::CastSocketImpl(const net::IPEndPoint& ip_endpoint, net::NetLog* net_log, - const base::TimeDelta& timeout, - bool keep_alive, + base::TimeDelta timeout, + base::TimeDelta liveness_timeout, + base::TimeDelta ping_interval, const scoped_refptr<Logger>& logger, uint64_t device_capabilities, const AuthContext& auth_context) : channel_id_(0), ip_endpoint_(ip_endpoint), net_log_(net_log), - keep_alive_(keep_alive), + liveness_timeout_(liveness_timeout), + ping_interval_(ping_interval), logger_(logger), auth_context_(auth_context), connect_timeout_(timeout), @@ -156,7 +161,7 @@ } bool CastSocketImpl::keep_alive() const { - return keep_alive_; + return liveness_timeout_ > base::TimeDelta(); } bool CastSocketImpl::audio_only() const { @@ -529,6 +534,12 @@ if (error_state_ == ChannelError::NONE) { SetReadyState(ReadyState::OPEN); + if (keep_alive()) { + auto* keep_alive_delegate = + new KeepAliveDelegate(this, logger_, std::move(delegate_), + ping_interval_, liveness_timeout_); + delegate_.reset(keep_alive_delegate); + } transport_->SetReadDelegate(std::move(delegate_)); } else { CloseInternal();
diff --git a/components/cast_channel/cast_socket.h b/components/cast_channel/cast_socket.h index 7026710..6afee6a 100644 --- a/components/cast_channel/cast_socket.h +++ b/components/cast_channel/cast_socket.h
@@ -127,11 +127,14 @@ // |ip_endpoint|: IP address of the remote host. // |net_log|: Log of socket events. // |connect_timeout|: Connection timeout interval. + // |liveness_timeout|: Amount of idle time to wait before disconnecting. + // |ping_interval|: Amount of idle time to wait before pinging the receiver. // |logger|: Log of cast channel events. CastSocketImpl(const net::IPEndPoint& ip_endpoint, net::NetLog* net_log, - const base::TimeDelta& connect_timeout, - bool keep_alive, + base::TimeDelta connect_timeout, + base::TimeDelta liveness_timeout, + base::TimeDelta ping_interval, const scoped_refptr<Logger>& logger, uint64_t device_capabilities); @@ -139,8 +142,9 @@ // This constructor allows for setting a custom AuthContext. CastSocketImpl(const net::IPEndPoint& ip_endpoint, net::NetLog* net_log, - const base::TimeDelta& connect_timeout, - bool keep_alive, + base::TimeDelta connect_timeout, + base::TimeDelta liveness_timeout, + base::TimeDelta ping_interval, const scoped_refptr<Logger>& logger, uint64_t device_capabilities, const AuthContext& auth_context); @@ -282,8 +286,14 @@ net::NetLog* net_log_; // The NetLog source for this service. net::NetLogSource net_log_source_; - // True when keep-alive signaling should be handled for this socket. - bool keep_alive_; + + // Amount of idle time to wait before disconnecting. If |liveness_timeout_| is + // set, wraps |delegate_| with a KeepAliveDelegate. + base::TimeDelta liveness_timeout_; + + // Amount of idle time to wait before pinging the receiver, used to create + // KeepAliveDelegate. + base::TimeDelta ping_interval_; // Shared logging object, used to log CastSocket events for diagnostics. scoped_refptr<Logger> logger_;
diff --git a/components/cast_channel/cast_socket_unittest.cc b/components/cast_channel/cast_socket_unittest.cc index bf9f4ec..c05487885 100644 --- a/components/cast_channel/cast_socket_unittest.cc +++ b/components/cast_channel/cast_socket_unittest.cc
@@ -194,7 +194,8 @@ : CastSocketImpl(ip_endpoint, capturing_net_log, base::TimeDelta::FromMilliseconds(timeout_ms), - false, + base::TimeDelta(), + base::TimeDelta(), logger, device_capabilities, AuthContext::Create()),
diff --git a/components/download/content/internal/download_driver_impl.cc b/components/download/content/internal/download_driver_impl.cc index 0300deb..d6581da 100644 --- a/components/download/content/internal/download_driver_impl.cc +++ b/components/download/content/internal/download_driver_impl.cc
@@ -4,6 +4,9 @@ #include "components/download/content/internal/download_driver_impl.h" +#include <set> +#include <vector> + #include "components/download/internal/driver_entry.h" #include "content/public/browser/download_interrupt_reasons.h" #include "content/public/browser/download_url_parameters.h" @@ -152,6 +155,23 @@ return base::nullopt; } +std::set<std::string> DownloadDriverImpl::GetActiveDownloads() { + std::set<std::string> guids; + if (!download_manager_) + return guids; + + std::vector<content::DownloadItem*> items; + download_manager_->GetAllDownloads(&items); + + for (auto* item : items) { + DriverEntry::State state = ToDriverEntryState(item->GetState()); + if (state == DriverEntry::State::IN_PROGRESS) + guids.insert(item->GetGuid()); + } + + return guids; +} + void DownloadDriverImpl::OnDownloadUpdated(content::DownloadItem* item) { DCHECK(client_); @@ -168,6 +188,8 @@ } else if (reason != content::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_NONE) { client_->OnDownloadFailed(entry, static_cast<int>(reason)); + // TODO(dtrainor, xingliu): This actually might not be correct. What if we + // restart the download? item->RemoveObserver(this); } }
diff --git a/components/download/content/internal/download_driver_impl.h b/components/download/content/internal/download_driver_impl.h index 5330733..63acc5f 100644 --- a/components/download/content/internal/download_driver_impl.h +++ b/components/download/content/internal/download_driver_impl.h
@@ -43,6 +43,7 @@ void Pause(const std::string& guid) override; void Resume(const std::string& guid) override; base::Optional<DriverEntry> Find(const std::string& guid) override; + std::set<std::string> GetActiveDownloads() override; private: // content::DownloadItem::Observer implementation.
diff --git a/components/download/content/internal/download_driver_impl_unittest.cc b/components/download/content/internal/download_driver_impl_unittest.cc index 41a7198..5fc7c86b 100644 --- a/components/download/content/internal/download_driver_impl_unittest.cc +++ b/components/download/content/internal/download_driver_impl_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include <string> +#include "base/guid.h" #include "base/memory/ptr_util.h" #include "content/public/test/fake_download_item.h" #include "content/public/test/mock_download_manager.h" @@ -15,6 +16,7 @@ #include "testing/gtest/include/gtest/gtest.h" using testing::_; +using testing::Invoke; using testing::NiceMock; using testing::Return; @@ -22,6 +24,10 @@ namespace { +ACTION_P(PopulateVector, items) { + arg0->insert(arg0->begin(), items.begin(), items.end()); +} + const char kFakeGuid[] = "fake_guid"; // Matcher to compare driver entries. Not all the memeber fields are compared. @@ -126,4 +132,39 @@ ->OnDownloadUpdated(&fake_item); } +TEST_F(DownloadDriverImplTest, TestGetActiveDownloadsCall) { + using DownloadState = content::DownloadItem::DownloadState; + content::FakeDownloadItem item1; + item1.SetState(DownloadState::IN_PROGRESS); + item1.SetGuid(base::GenerateGUID()); + + content::FakeDownloadItem item2; + item2.SetState(DownloadState::CANCELLED); + item2.SetGuid(base::GenerateGUID()); + + content::FakeDownloadItem item3; + item3.SetState(DownloadState::COMPLETE); + item3.SetGuid(base::GenerateGUID()); + + content::FakeDownloadItem item4; + item4.SetState(DownloadState::INTERRUPTED); + item4.SetGuid(base::GenerateGUID()); + + std::vector<content::DownloadItem*> items{&item1, &item2, &item3, &item4}; + + ON_CALL(mock_manager_, GetAllDownloads(_)) + .WillByDefault(PopulateVector(items)); + + EXPECT_CALL(mock_manager_, IsManagerInitialized()) + .Times(1) + .WillOnce(Return(true)); + EXPECT_CALL(mock_client_, OnDriverReady(true)).Times(1); + driver_->Initialize(&mock_client_); + + auto guids = driver_->GetActiveDownloads(); + + EXPECT_EQ(1U, guids.size()); + EXPECT_NE(guids.end(), guids.find(item1.GetGuid())); +} + } // namespace download
diff --git a/components/download/internal/controller_impl.cc b/components/download/internal/controller_impl.cc index 136a145..46ac490 100644 --- a/components/download/internal/controller_impl.cc +++ b/components/download/internal/controller_impl.cc
@@ -72,13 +72,16 @@ model_(std::move(model)), device_status_listener_(std::move(device_status_listener)), scheduler_(std::move(scheduler)), - task_scheduler_(std::move(task_scheduler)) {} + task_scheduler_(std::move(task_scheduler)), + initializing_internals_(false), + weak_ptr_factory_(this) {} ControllerImpl::~ControllerImpl() = default; void ControllerImpl::Initialize() { DCHECK(!startup_status_.Complete()); + initializing_internals_ = true; driver_->Initialize(this); model_->Initialize(this); } @@ -90,6 +93,10 @@ void ControllerImpl::StartDownload(const DownloadParams& params) { DCHECK(startup_status_.Ok()); + // TODO(dtrainor): Check if there are any downloads we can cancel. We don't + // want to return a BACKOFF if we technically could time out a download to + // start this one. + if (start_callbacks_.find(params.guid) != start_callbacks_.end() || model_->Get(params.guid) != nullptr) { HandleStartDownloadResponse(params.client, params.guid, @@ -255,10 +262,13 @@ } void ControllerImpl::OnDownloadCreated(const DriverEntry& download) { + if (initializing_internals_) + return; + Entry* entry = model_->Get(download.guid); if (!entry) { - // TODO(xingliu): Log non download service initiated downloads. + HandleExternalDownload(download.guid, true); return; } @@ -273,35 +283,54 @@ } void ControllerImpl::OnDownloadFailed(const DriverEntry& download, int reason) { - Entry* entry = model_->Get(download.guid); - if (!entry) + if (initializing_internals_) return; + Entry* entry = model_->Get(download.guid); + if (!entry) { + HandleExternalDownload(download.guid, false); + return; + } + // TODO(dtrainor): Add retry logic here. Connect to restart code for tracking // number of retries. + // TODO(dtrainor, xingliu): We probably have to prevent cancel calls from + // coming through here as we remove downloads (especially through + // initialization). HandleCompleteDownload(CompletionType::FAIL, download.guid); } void ControllerImpl::OnDownloadSucceeded(const DriverEntry& download, const base::FilePath& path) { - Entry* entry = model_->Get(download.guid); - if (!entry) + if (initializing_internals_) return; + Entry* entry = model_->Get(download.guid); + if (!entry) { + HandleExternalDownload(download.guid, false); + return; + } + HandleCompleteDownload(CompletionType::SUCCEED, download.guid); } void ControllerImpl::OnDownloadUpdated(const DriverEntry& download) { - Entry* entry = model_->Get(download.guid); - if (!entry) + if (initializing_internals_) return; + Entry* entry = model_->Get(download.guid); + if (!entry) { + HandleExternalDownload(download.guid, !download.paused); + return; + } + DCHECK_EQ(download.state, DriverEntry::State::IN_PROGRESS); - download::Client* client = clients_->GetClient(entry->client); - if (client) - client->OnDownloadUpdated(download.guid, download.bytes_downloaded); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&ControllerImpl::SendOnDownloadUpdated, + weak_ptr_factory_.GetWeakPtr(), entry->client, + download.guid, download.bytes_downloaded)); } void ControllerImpl::OnModelReady(bool success) { @@ -374,17 +403,29 @@ } device_status_listener_->Start(this); + PollActiveDriverDownloads(); CancelOrphanedRequests(); ResolveInitialRequestStates(); - UpdateDriverStates(); - PullCurrentRequestStatus(); NotifyClientsOfStartup(); + + initializing_internals_ = false; + + UpdateDriverStates(); ProcessScheduledTasks(); // Pull the initial straw if active downloads haven't reach maximum. ActivateMoreDownloads(); } +void ControllerImpl::PollActiveDriverDownloads() { + std::set<std::string> guids = driver_->GetActiveDownloads(); + + for (auto guid : guids) { + if (!model_->Get(guid)) + externally_active_downloads_.insert(guid); + } +} + void ControllerImpl::CancelOrphanedRequests() { auto entries = model_->PeekEntries(); @@ -395,14 +436,124 @@ } for (const auto& guid : guids_to_remove) { - model_->Remove(guid); // TODO(xingliu): Use file monitor to delete the files. driver_->Remove(guid); + model_->Remove(guid); } } void ControllerImpl::ResolveInitialRequestStates() { - // TODO(dtrainor): Implement. + auto entries = model_->PeekEntries(); + for (auto* entry : entries) { + // Pull the initial Entry::State and DriverEntry::State. + Entry::State state = entry->state; + auto driver_entry = driver_->Find(entry->guid); + base::Optional<DriverEntry::State> driver_state; + if (driver_entry.has_value()) { + DCHECK_NE(DriverEntry::State::UNKNOWN, driver_entry->state); + driver_state = driver_entry->state; + } + + // Determine what the new Entry::State should be based on the two original + // states of the two different systems. + Entry::State new_state = state; + switch (state) { + case Entry::State::NEW: + // This means we shut down but may have not ACK'ed the download. That + // is OK, we will still notify the Client about the GUID when we send + // them our initialize method. + new_state = Entry::State::AVAILABLE; + break; + case Entry::State::COMPLETE: + // We're already in our end state. Just stay here. + new_state = Entry::State::COMPLETE; + break; + case Entry::State::AVAILABLE: // Intentional fallthrough. + case Entry::State::ACTIVE: // Intentional fallthrough. + case Entry::State::PAUSED: { + // All three of these states are effectively driven by the DriverEntry + // state. + if (!driver_state.has_value()) { + // If we don't have a DriverEntry::State, just leave the state alone. + new_state = state; + break; + } + + // If we have a real DriverEntry::State, we need to determine which of + // those states makes sense for our Entry. Our entry can either be in + // two states now: It's effective 'active' state (ACTIVE or PAUSED) or + // COMPLETE. + bool is_paused = state == Entry::State::PAUSED; + Entry::State active = + is_paused ? Entry::State::PAUSED : Entry::State::ACTIVE; + + switch (driver_state.value()) { + case DriverEntry::State::IN_PROGRESS: // Intentional fallthrough. + case DriverEntry::State::INTERRUPTED: + // The DriverEntry isn't done, so we need to set the Entry to the + // 'active' state. + new_state = active; + break; + case DriverEntry::State::COMPLETE: // Intentional fallthrough. + // TODO(dtrainor, xingliu) Revisit this CANCELLED state to make sure + // all embedders behave properly. + case DriverEntry::State::CANCELLED: + // The DriverEntry is done. We need to set the Entry to the + // COMPLETE state. + new_state = Entry::State::COMPLETE; + break; + default: + NOTREACHED(); + break; + } + break; + } + default: + NOTREACHED(); + break; + } + + // Update the Entry::State to the new correct state. + if (new_state != entry->state) { + stats::LogRecoveryOperation(new_state); + TransitTo(entry, new_state, model_.get()); + } + + // Given the new correct state, update the DriverEntry to reflect the Entry. + switch (new_state) { + case Entry::State::NEW: // Intentional fallthrough. + case Entry::State::AVAILABLE: // Intentional fallthrough. + // We should not have a DriverEntry here. + if (driver_entry.has_value()) + driver_->Remove(entry->guid); + break; + case Entry::State::ACTIVE: // Intentional fallthrough. + case Entry::State::PAUSED: + // We're in the correct state. Let UpdateDriverStates() restart us if + // it wants to. + break; + case Entry::State::COMPLETE: + if (state != Entry::State::COMPLETE) { + // We are changing states to COMPLETE. Handle this like a normal + // completed download. + + // Treat CANCELLED and INTERRUPTED as failures. We have to assume the + // DriverEntry might not have persisted in time. + CompletionType completion_type = + (!driver_entry.has_value() || + driver_entry->state == DriverEntry::State::CANCELLED || + driver_entry->state == DriverEntry::State::INTERRUPTED) + ? CompletionType::UNKNOWN + : CompletionType::SUCCEED; + HandleCompleteDownload(completion_type, entry->guid); + } else { + // We're staying in COMPLETE. Make sure there is no DriverEntry here. + if (driver_entry.has_value()) + driver_->Remove(entry->guid); + } + break; + } + } } void ControllerImpl::UpdateDriverStates() { @@ -413,46 +564,39 @@ } void ControllerImpl::UpdateDriverState(const Entry& entry) { + DCHECK(!initializing_internals_); + + if (entry.state != Entry::State::ACTIVE && + entry.state != Entry::State::PAUSED) { + return; + } + + // This method will need to figure out what to do with a failed download and + // either a) restart it or b) fail the download. + base::Optional<DriverEntry> driver_entry = driver_->Find(entry.guid); bool meets_device_criteria = device_status_listener_->CurrentDeviceStatus() .MeetsCondition(entry.scheduling_params) .MeetsRequirements(); - switch (entry.state) { - case Entry::State::ACTIVE: - if (!meets_device_criteria) { - driver_->Pause(entry.guid); - break; - } - // Start or resume the download if it should be running. - if (!driver_entry.has_value()) { - driver_->Start(entry.request_params, entry.guid, - NO_TRAFFIC_ANNOTATION_YET); - break; - } - if (driver_entry->state != DriverEntry::State::IN_PROGRESS) { - driver_->Resume(entry.guid); - } - break; - case Entry::State::PAUSED: - // Pause the in progress downloads that should not be running. - if (driver_entry.has_value() && - driver_entry->state == DriverEntry::State::IN_PROGRESS) { - driver_->Pause(entry.guid); - } - break; - // Fall through. - case Entry::State::AVAILABLE: - case Entry::State::NEW: - case Entry::State::COMPLETE: - break; - default: - NOTREACHED(); - } -} + bool force_pause = + !externally_active_downloads_.empty() && + entry.scheduling_params.priority != SchedulingParams::Priority::UI; + bool entry_paused = entry.state == Entry::State::PAUSED; -void ControllerImpl::PullCurrentRequestStatus() { - // TODO(dtrainor): Implement. + bool pause_driver = entry_paused || force_pause || !meets_device_criteria; + + if (pause_driver) { + if (driver_entry.has_value()) + driver_->Pause(entry.guid); + } else { + if (driver_entry.has_value()) { + driver_->Resume(entry.guid); + } else { + driver_->Start(entry.request_params, entry.guid, + NO_TRAFFIC_ANNOTATION_YET); + } + } } void ControllerImpl::NotifyClientsOfStartup() { @@ -505,20 +649,22 @@ return; } - auto* client = clients_->GetClient(entry->client); - DCHECK(client); - if (type == CompletionType::SUCCEED) { auto driver_entry = driver_->Find(guid); DCHECK(driver_entry.has_value()); // TODO(dtrainor): Move the FilePath generation to the controller and store // it in Entry. Then pass it into the DownloadDriver. - // TODO(dtrainor): PostTask this instead of putting it inline. - client->OnDownloadSucceeded(guid, base::FilePath(), - driver_entry->bytes_downloaded); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&ControllerImpl::SendOnDownloadSucceeded, + weak_ptr_factory_.GetWeakPtr(), entry->client, guid, + base::FilePath(), driver_entry->bytes_downloaded)); TransitTo(entry, Entry::State::COMPLETE, model_.get()); } else { - client->OnDownloadFailed(guid, FailureReasonFromCompletionType(type)); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&ControllerImpl::SendOnDownloadFailed, + weak_ptr_factory_.GetWeakPtr(), entry->client, + guid, FailureReasonFromCompletionType(type))); model_->Remove(guid); } @@ -526,6 +672,9 @@ } void ControllerImpl::ActivateMoreDownloads() { + if (initializing_internals_) + return; + // TODO(xingliu): Check the configuration to throttle downloads. Entry* next = scheduler_->Next( model_->PeekEntries(), device_status_listener_->CurrentDeviceStatus()); @@ -540,4 +689,44 @@ scheduler_->Reschedule(model_->PeekEntries()); } +void ControllerImpl::HandleExternalDownload(const std::string& guid, + bool active) { + if (active) { + externally_active_downloads_.insert(guid); + } else { + externally_active_downloads_.erase(guid); + } + + UpdateDriverStates(); +} + +void ControllerImpl::SendOnDownloadUpdated(DownloadClient client_id, + const std::string& guid, + uint64_t bytes_downloaded) { + if (!model_->Get(guid)) + return; + + auto* client = clients_->GetClient(client_id); + DCHECK(client); + client->OnDownloadUpdated(guid, bytes_downloaded); +} + +void ControllerImpl::SendOnDownloadSucceeded(DownloadClient client_id, + const std::string& guid, + const base::FilePath& path, + uint64_t size) { + auto* client = clients_->GetClient(client_id); + DCHECK(client); + client->OnDownloadSucceeded(guid, path, size); +} + +void ControllerImpl::SendOnDownloadFailed( + DownloadClient client_id, + const std::string& guid, + download::Client::FailureReason reason) { + auto* client = clients_->GetClient(client_id); + DCHECK(client); + client->OnDownloadFailed(guid, reason); +} + } // namespace download
diff --git a/components/download/internal/controller_impl.h b/components/download/internal/controller_impl.h index 0d94b35..0c20f9d 100644 --- a/components/download/internal/controller_impl.h +++ b/components/download/internal/controller_impl.h
@@ -7,8 +7,10 @@ #include <map> #include <memory> +#include <set> #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "base/optional.h" #include "components/download/internal/controller.h" #include "components/download/internal/download_driver.h" @@ -17,6 +19,7 @@ #include "components/download/internal/scheduler/device_status_listener.h" #include "components/download/internal/startup_status.h" #include "components/download/internal/stats.h" +#include "components/download/public/client.h" #include "components/download/public/download_params.h" #include "components/download/public/task_scheduler.h" @@ -89,6 +92,10 @@ // internal state initialization. void AttemptToFinalizeSetup(); + // Checks for all the currently active driver downloads. This lets us know + // which ones are active that we haven't tracked. + void PollActiveDriverDownloads(); + // Cancels and cleans upany requests that are no longer associated with a // Client in |clients_|. void CancelOrphanedRequests(); @@ -110,10 +117,6 @@ // DownloadClient. void NotifyClientsOfStartup(); - // Pulls the current state of requests from |model_| and |driver_| and sets - // the other internal states appropriately. - void PullCurrentRequestStatus(); - void HandleStartDownloadResponse(DownloadClient client, const std::string& guid, DownloadParams::StartResult result); @@ -137,6 +140,21 @@ // reached maximum. void ActivateMoreDownloads(); + void HandleExternalDownload(const std::string& guid, bool active); + + // Postable methods meant to just be pass throughs to Client APIs. This is + // meant to help prevent reentrancy. + void SendOnDownloadUpdated(DownloadClient client_id, + const std::string& guid, + uint64_t bytes_downloaded); + void SendOnDownloadSucceeded(DownloadClient client_id, + const std::string& guid, + const base::FilePath& path, + uint64_t size); + void SendOnDownloadFailed(DownloadClient client_id, + const std::string& guid, + download::Client::FailureReason reason); + Configuration* config_; // Owned Dependencies. @@ -148,10 +166,19 @@ std::unique_ptr<TaskScheduler> task_scheduler_; // Internal state. + // Is set to true if this class is currently in the process of initializing + // it's internal state. This will be false until |startup_status_| signals it + // is complete *and* all internal structures are set up. This is to prevent + // outside signals from triggering state updates before we are ready. + bool initializing_internals_; StartupStatus startup_status_; + std::set<std::string> externally_active_downloads_; std::map<std::string, DownloadParams::StartCallback> start_callbacks_; std::map<DownloadTaskType, TaskFinishedCallback> task_finished_callbacks_; + // Only used to post tasks on the same thread. + base::WeakPtrFactory<ControllerImpl> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(ControllerImpl); };
diff --git a/components/download/internal/controller_impl_unittest.cc b/components/download/internal/controller_impl_unittest.cc index b88ceae..48a27877 100644 --- a/components/download/internal/controller_impl_unittest.cc +++ b/components/download/internal/controller_impl_unittest.cc
@@ -33,6 +33,15 @@ namespace { +bool GuidInEntryList(const std::vector<Entry>& entries, + const std::string& guid) { + for (const auto& entry : entries) { + if (entry.guid == guid) + return true; + } + return false; +} + DriverEntry BuildDriverEntry(const Entry& entry, DriverEntry::State state) { DriverEntry dentry; dentry.guid = entry.guid; @@ -288,7 +297,7 @@ .Times(1); controller_->StartDownload(params); - EXPECT_TRUE(store_->updated_entries().empty()); + EXPECT_FALSE(GuidInEntryList(store_->updated_entries(), params.guid)); task_runner_->RunUntilIdle(); } @@ -317,8 +326,6 @@ .Times(1); controller_->StartDownload(params); - EXPECT_TRUE(store_->updated_entries().empty()); - task_runner_->RunUntilIdle(); } @@ -350,6 +357,8 @@ controller_->StartDownload(params); store_->TriggerUpdate(true); + EXPECT_TRUE(GuidInEntryList(store_->updated_entries(), params.guid)); + task_runner_->RunUntilIdle(); } @@ -611,6 +620,8 @@ OnDownloadUpdated(entry.guid, driver_entry.bytes_downloaded)); driver_->NotifyDownloadUpdate(driver_entry); EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entry.guid)->state); + + task_runner_->RunUntilIdle(); } TEST_F(DownloadServiceControllerImplTest, DownloadCompletionTest) { @@ -664,4 +675,286 @@ task_runner_->RunUntilIdle(); } +TEST_F(DownloadServiceControllerImplTest, StartupRecovery) { + EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + + std::vector<Entry> entries; + std::vector<DriverEntry> driver_entries; + entries.push_back(test::BuildBasicEntry(Entry::State::NEW)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::IN_PROGRESS)); + entries.push_back(test::BuildBasicEntry(Entry::State::NEW)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::COMPLETE)); + entries.push_back(test::BuildBasicEntry(Entry::State::NEW)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::CANCELLED)); + entries.push_back(test::BuildBasicEntry(Entry::State::NEW)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::INTERRUPTED)); + entries.push_back(test::BuildBasicEntry(Entry::State::NEW)); + + entries.push_back(test::BuildBasicEntry(Entry::State::AVAILABLE)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::IN_PROGRESS)); + entries.push_back(test::BuildBasicEntry(Entry::State::AVAILABLE)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::COMPLETE)); + entries.push_back(test::BuildBasicEntry(Entry::State::AVAILABLE)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::CANCELLED)); + entries.push_back(test::BuildBasicEntry(Entry::State::AVAILABLE)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::INTERRUPTED)); + entries.push_back(test::BuildBasicEntry(Entry::State::AVAILABLE)); + + entries.push_back(test::BuildBasicEntry(Entry::State::ACTIVE)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::IN_PROGRESS)); + entries.push_back(test::BuildBasicEntry(Entry::State::ACTIVE)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::COMPLETE)); + entries.push_back(test::BuildBasicEntry(Entry::State::ACTIVE)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::CANCELLED)); + entries.push_back(test::BuildBasicEntry(Entry::State::ACTIVE)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::INTERRUPTED)); + entries.push_back(test::BuildBasicEntry(Entry::State::ACTIVE)); + + entries.push_back(test::BuildBasicEntry(Entry::State::PAUSED)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::IN_PROGRESS)); + entries.push_back(test::BuildBasicEntry(Entry::State::PAUSED)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::COMPLETE)); + entries.push_back(test::BuildBasicEntry(Entry::State::PAUSED)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::CANCELLED)); + entries.push_back(test::BuildBasicEntry(Entry::State::PAUSED)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::INTERRUPTED)); + entries.push_back(test::BuildBasicEntry(Entry::State::PAUSED)); + + entries.push_back(test::BuildBasicEntry(Entry::State::COMPLETE)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::IN_PROGRESS)); + entries.push_back(test::BuildBasicEntry(Entry::State::COMPLETE)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::COMPLETE)); + entries.push_back(test::BuildBasicEntry(Entry::State::COMPLETE)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::CANCELLED)); + entries.push_back(test::BuildBasicEntry(Entry::State::COMPLETE)); + driver_entries.push_back( + BuildDriverEntry(entries.back(), DriverEntry::State::INTERRUPTED)); + entries.push_back(test::BuildBasicEntry(Entry::State::COMPLETE)); + + // Set up the Controller. + device_status_listener_->SetDeviceStatus( + DeviceStatus(BatteryStatus::CHARGING, NetworkStatus::UNMETERED)); + + controller_->Initialize(); + driver_->AddTestData(driver_entries); + driver_->MakeReady(); + store_->AutomaticallyTriggerAllFutureCallbacks(true); + store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries)); + + // Allow the initialization routines and persistent layers to do their thing. + task_runner_->RunUntilIdle(); + + // Validate Model and DownloadDriver states. + // Note that we are accessing the Model instead of the Store here to make it + // easier to query the states. + // TODO(dtrainor): Check more of the DriverEntry state to validate that the + // entries are either paused or resumed accordingly. + + // Entry::State::NEW. + EXPECT_EQ(Entry::State::AVAILABLE, model_->Get(entries[0].guid)->state); + EXPECT_EQ(Entry::State::AVAILABLE, model_->Get(entries[1].guid)->state); + EXPECT_EQ(Entry::State::AVAILABLE, model_->Get(entries[2].guid)->state); + EXPECT_EQ(Entry::State::AVAILABLE, model_->Get(entries[3].guid)->state); + EXPECT_EQ(Entry::State::AVAILABLE, model_->Get(entries[4].guid)->state); + EXPECT_EQ(base::nullopt, driver_->Find(entries[0].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[1].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[2].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[3].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[4].guid)); + + // Entry::State::AVAILABLE. + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entries[5].guid)->state); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[6].guid)->state); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[7].guid)->state); + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entries[8].guid)->state); + EXPECT_EQ(Entry::State::AVAILABLE, model_->Get(entries[9].guid)->state); + EXPECT_NE(base::nullopt, driver_->Find(entries[5].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[6].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[7].guid)); + EXPECT_NE(base::nullopt, driver_->Find(entries[8].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[9].guid)); + + // Entry::State::ACTIVE. + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entries[10].guid)->state); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[11].guid)->state); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[12].guid)->state); + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entries[13].guid)->state); + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entries[14].guid)->state); + EXPECT_NE(base::nullopt, driver_->Find(entries[10].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[11].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[12].guid)); + EXPECT_NE(base::nullopt, driver_->Find(entries[13].guid)); + EXPECT_NE(base::nullopt, driver_->Find(entries[14].guid)); + + // Entry::State::PAUSED. + EXPECT_EQ(Entry::State::PAUSED, model_->Get(entries[15].guid)->state); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[16].guid)->state); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[17].guid)->state); + EXPECT_EQ(Entry::State::PAUSED, model_->Get(entries[18].guid)->state); + EXPECT_EQ(Entry::State::PAUSED, model_->Get(entries[19].guid)->state); + EXPECT_NE(base::nullopt, driver_->Find(entries[15].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[16].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[17].guid)); + EXPECT_NE(base::nullopt, driver_->Find(entries[18].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[19].guid)); + + // prog, comp, canc, int, __ + // Entry::State::COMPLETE. + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[20].guid)->state); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[21].guid)->state); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[22].guid)->state); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[23].guid)->state); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[24].guid)->state); + EXPECT_EQ(base::nullopt, driver_->Find(entries[20].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[21].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[22].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[23].guid)); + EXPECT_EQ(base::nullopt, driver_->Find(entries[24].guid)); +} + +TEST_F(DownloadServiceControllerImplTest, ExistingExternalDownload) { + Entry entry1 = test::BuildBasicEntry(Entry::State::ACTIVE); + Entry entry2 = test::BuildBasicEntry(Entry::State::ACTIVE); + Entry entry3 = test::BuildBasicEntry(Entry::State::ACTIVE); + entry3.scheduling_params.priority = SchedulingParams::Priority::UI; + + // Simulate an existing download the service knows about and one it does not. + DriverEntry dentry1 = + BuildDriverEntry(entry2, DriverEntry::State::IN_PROGRESS); + DriverEntry dentry2; + dentry2.guid = base::GenerateGUID(); + dentry2.state = DriverEntry::State::IN_PROGRESS; + + std::vector<Entry> entries = {entry1, entry2, entry3}; + std::vector<DriverEntry> dentries = {dentry1, dentry2}; + + EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + + // Set up the Controller. + device_status_listener_->SetDeviceStatus( + DeviceStatus(BatteryStatus::CHARGING, NetworkStatus::UNMETERED)); + + driver_->AddTestData(dentries); + controller_->Initialize(); + store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries)); + driver_->MakeReady(); + task_runner_->RunUntilIdle(); + + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entry1.guid)->state); + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entry2.guid)->state); + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entry3.guid)->state); + + EXPECT_FALSE(driver_->Find(entry1.guid).has_value()); + + EXPECT_TRUE(driver_->Find(entry2.guid).has_value()); + EXPECT_TRUE(driver_->Find(entry2.guid).value().paused); + + EXPECT_TRUE(driver_->Find(entry3.guid).has_value()); + EXPECT_FALSE(driver_->Find(entry3.guid).value().paused); + + // Simulate a successful external download. + driver_->NotifyDownloadSucceeded(dentry2, base::FilePath()); + + EXPECT_TRUE(driver_->Find(entry1.guid).has_value()); + EXPECT_FALSE(driver_->Find(entry1.guid).value().paused); + EXPECT_FALSE(driver_->Find(entry2.guid).value().paused); + EXPECT_FALSE(driver_->Find(entry3.guid).value().paused); +} + +TEST_F(DownloadServiceControllerImplTest, NewExternalDownload) { + Entry entry1 = test::BuildBasicEntry(Entry::State::ACTIVE); + Entry entry2 = test::BuildBasicEntry(Entry::State::ACTIVE); + entry2.scheduling_params.priority = SchedulingParams::Priority::UI; + + DriverEntry dentry1 = + BuildDriverEntry(entry2, DriverEntry::State::IN_PROGRESS); + + std::vector<Entry> entries = {entry1, entry2}; + std::vector<DriverEntry> dentries = {dentry1}; + + EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + + // Set up the Controller. + device_status_listener_->SetDeviceStatus( + DeviceStatus(BatteryStatus::CHARGING, NetworkStatus::UNMETERED)); + + driver_->AddTestData(dentries); + controller_->Initialize(); + store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries)); + driver_->MakeReady(); + task_runner_->RunUntilIdle(); + + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entry1.guid)->state); + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entry2.guid)->state); + + EXPECT_TRUE(driver_->Find(entry1.guid).has_value()); + EXPECT_FALSE(driver_->Find(entry1.guid).value().paused); + EXPECT_TRUE(driver_->Find(entry2.guid).has_value()); + EXPECT_FALSE(driver_->Find(entry2.guid).value().paused); + + DriverEntry dentry2; + dentry2.guid = base::GenerateGUID(); + dentry2.state = DriverEntry::State::IN_PROGRESS; + + // Simulate a newly created external download. + driver_->Start(RequestParams(), dentry2.guid, NO_TRAFFIC_ANNOTATION_YET); + + EXPECT_TRUE(driver_->Find(entry1.guid).value().paused); + EXPECT_FALSE(driver_->Find(entry2.guid).value().paused); + + // Simulate a paused external download. + dentry2.paused = true; + driver_->NotifyDownloadUpdate(dentry2); + + EXPECT_FALSE(driver_->Find(entry1.guid).value().paused); + EXPECT_FALSE(driver_->Find(entry2.guid).value().paused); + + // Simulate a resumed external download. + dentry2.paused = false; + driver_->NotifyDownloadUpdate(dentry2); + + EXPECT_TRUE(driver_->Find(entry1.guid).value().paused); + EXPECT_FALSE(driver_->Find(entry2.guid).value().paused); + + // Simulate a failed external download. + dentry2.state = DriverEntry::State::INTERRUPTED; + driver_->NotifyDownloadFailed(dentry2, 1); + + EXPECT_FALSE(driver_->Find(entry1.guid).value().paused); + EXPECT_FALSE(driver_->Find(entry2.guid).value().paused); + + // Rebuild the download so we can simulate more. + dentry2.state = DriverEntry::State::IN_PROGRESS; + driver_->Start(RequestParams(), dentry2.guid, NO_TRAFFIC_ANNOTATION_YET); + + EXPECT_TRUE(driver_->Find(entry1.guid).value().paused); + EXPECT_FALSE(driver_->Find(entry2.guid).value().paused); + + // Simulate a successful external download. + dentry2.state = DriverEntry::State::COMPLETE; + driver_->NotifyDownloadSucceeded(dentry2, base::FilePath()); + + EXPECT_FALSE(driver_->Find(entry1.guid).value().paused); + EXPECT_FALSE(driver_->Find(entry2.guid).value().paused); +} + } // namespace download
diff --git a/components/download/internal/download_driver.h b/components/download/internal/download_driver.h index 149e4160..bf385696 100644 --- a/components/download/internal/download_driver.h +++ b/components/download/internal/download_driver.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_DOWNLOAD_INTERNAL_DOWNLOAD_DRIVER_H_ #define COMPONENTS_DOWNLOAD_INTERNAL_DOWNLOAD_DRIVER_H_ +#include <set> #include <string> #include "base/optional.h" @@ -75,6 +76,10 @@ // Finds a download record from low level download library. virtual base::Optional<DriverEntry> Find(const std::string& guid) = 0; + + // Called to query the current set of active downloads. This doesn't + // necessarily mean downloads started by the service. + virtual std::set<std::string> GetActiveDownloads() = 0; }; } // namespace download
diff --git a/components/download/internal/proto_conversions_unittest.cc b/components/download/internal/proto_conversions_unittest.cc index 1f39dbb..3d1605d 100644 --- a/components/download/internal/proto_conversions_unittest.cc +++ b/components/download/internal/proto_conversions_unittest.cc
@@ -34,8 +34,7 @@ TEST_F(ProtoConversionsTest, DownloadClientConversion) { DownloadClient clients[] = {DownloadClient::INVALID, DownloadClient::TEST, - DownloadClient::OFFLINE_PAGE_PREFETCH, - DownloadClient::BOUNDARY}; + DownloadClient::TEST_2, DownloadClient::BOUNDARY}; for (auto client : clients) { ASSERT_EQ(client, DownloadClientFromProto(DownloadClientToProto(client))); } @@ -135,8 +134,8 @@ std::vector<Entry> expected; expected.push_back( test::BuildEntry(DownloadClient::TEST, base::GenerateGUID())); - expected.push_back(test::BuildEntry(DownloadClient::OFFLINE_PAGE_PREFETCH, - base::GenerateGUID())); + expected.push_back( + test::BuildEntry(DownloadClient::TEST_2, base::GenerateGUID())); expected.push_back(test::BuildEntry( DownloadClient::TEST, base::GenerateGUID(), base::Time::Now(), SchedulingParams::NetworkRequirements::OPTIMISTIC,
diff --git a/components/download/internal/stats.cc b/components/download/internal/stats.cc index b532f879..b581c4d4 100644 --- a/components/download/internal/stats.cc +++ b/components/download/internal/stats.cc
@@ -38,5 +38,9 @@ // TODO(xingliu): Log completion. } +void LogRecoveryOperation(Entry::State to_state) { + // TODO(dtrainor): Log |to_state|. +} + } // namespace stats } // namespace download
diff --git a/components/download/internal/stats.h b/components/download/internal/stats.h index 7a9cecb..9997592 100644 --- a/components/download/internal/stats.h +++ b/components/download/internal/stats.h
@@ -6,6 +6,7 @@ #define COMPONENTS_DOWNLOAD_INTERNAL_STATS_H_ #include "components/download/internal/controller.h" +#include "components/download/internal/entry.h" #include "components/download/public/clients.h" #include "components/download/public/download_params.h" #include "components/download/public/download_task_types.h" @@ -96,6 +97,10 @@ // Logs download completion event. void LogDownloadCompletion(CompletionType type); +// Logs recovery operations that happened when we had to move from one state +// to another on startup. +void LogRecoveryOperation(Entry::State to_state); + } // namespace stats } // namespace download
diff --git a/components/download/internal/test/test_download_driver.cc b/components/download/internal/test/test_download_driver.cc index c9f11a4..440ed974 100644 --- a/components/download/internal/test/test_download_driver.cc +++ b/components/download/internal/test/test_download_driver.cc
@@ -104,5 +104,16 @@ return it->second; } +std::set<std::string> TestDownloadDriver::GetActiveDownloads() { + std::set<std::string> guids; + + for (auto& entry : entries_) { + if (entry.second.state == DriverEntry::State::IN_PROGRESS) + guids.insert(entry.second.guid); + } + + return guids; +} + } // namespace test } // namespace download
diff --git a/components/download/internal/test/test_download_driver.h b/components/download/internal/test/test_download_driver.h index 05fd808..95d9b55 100644 --- a/components/download/internal/test/test_download_driver.h +++ b/components/download/internal/test/test_download_driver.h
@@ -45,6 +45,7 @@ void Pause(const std::string& guid) override; void Resume(const std::string& guid) override; base::Optional<DriverEntry> Find(const std::string& guid) override; + std::set<std::string> GetActiveDownloads() override; private: bool is_ready_;
diff --git a/components/download/internal/test/test_store.cc b/components/download/internal/test/test_store.cc index c9e472b94..0b5648f 100644 --- a/components/download/internal/test/test_store.cc +++ b/components/download/internal/test/test_store.cc
@@ -4,6 +4,7 @@ #include "components/download/internal/test/test_store.h" +#include "base/memory/ptr_util.h" #include "components/download/internal/entry.h" namespace download { @@ -20,19 +21,32 @@ void TestStore::Initialize(InitCallback callback) { init_called_ = true; init_callback_ = std::move(callback); + + if (automatic_callback_response_.has_value()) + TriggerInit(automatic_callback_response_.value(), + base::MakeUnique<std::vector<Entry>>()); } void TestStore::Update(const Entry& entry, StoreCallback callback) { updated_entries_.push_back(entry); update_callback_ = std::move(callback); + + if (automatic_callback_response_.has_value()) + TriggerUpdate(automatic_callback_response_.value()); } void TestStore::Remove(const std::string& guid, StoreCallback callback) { removed_entries_.push_back(guid); remove_callback_ = std::move(callback); + + if (automatic_callback_response_.has_value()) + TriggerRemove(automatic_callback_response_.value()); } -// Callback trigger methods. +void TestStore::AutomaticallyTriggerAllFutureCallbacks(bool success) { + automatic_callback_response_ = success; +} + void TestStore::TriggerInit(bool success, std::unique_ptr<std::vector<Entry>> entries) { ready_ = success;
diff --git a/components/download/internal/test/test_store.h b/components/download/internal/test/test_store.h index 2cb5f57..d3b667e 100644 --- a/components/download/internal/test/test_store.h +++ b/components/download/internal/test/test_store.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/macros.h" +#include "base/optional.h" #include "components/download/internal/store.h" namespace download { @@ -30,6 +31,7 @@ void Remove(const std::string& guid, StoreCallback callback) override; // Callback trigger methods. + void AutomaticallyTriggerAllFutureCallbacks(bool success); void TriggerInit(bool success, std::unique_ptr<std::vector<Entry>> entries); void TriggerUpdate(bool success); void TriggerRemove(bool success); @@ -51,6 +53,7 @@ std::vector<Entry> updated_entries_; std::vector<std::string> removed_entries_; + base::Optional<bool> automatic_callback_response_; InitCallback init_callback_; StoreCallback update_callback_; StoreCallback remove_callback_;
diff --git a/components/handoff/handoff_manager.mm b/components/handoff/handoff_manager.mm index cdcb8f1..420eca0 100644 --- a/components/handoff/handoff_manager.mm +++ b/components/handoff/handoff_manager.mm
@@ -96,10 +96,11 @@ [self.userActivity invalidate]; Class aClass = NSClassFromString(@"NSUserActivity"); - NSUserActivity* userActivity = [[aClass performSelector:@selector(alloc)] - performSelector:@selector(initWithActivityType:) - withObject:handoff::kChromeHandoffActivityType]; - self.userActivity = base::scoped_nsobject<NSUserActivity>(userActivity); + base::scoped_nsobject<NSUserActivity> userActivity( + [[aClass performSelector:@selector(alloc)] + performSelector:@selector(initWithActivityType:) + withObject:handoff::kChromeHandoffActivityType]); + self.userActivity = userActivity; self.userActivity.webpageURL = net::NSURLWithGURL(_activeURL); NSString* origin = handoff::StringFromOrigin(_origin); DCHECK(origin);
diff --git a/components/navigation_interception/intercept_navigation_delegate.cc b/components/navigation_interception/intercept_navigation_delegate.cc index b8cd316..b6a3b11 100644 --- a/components/navigation_interception/intercept_navigation_delegate.cc +++ b/components/navigation_interception/intercept_navigation_delegate.cc
@@ -89,7 +89,7 @@ InterceptNavigationDelegate::CreateThrottleFor( content::NavigationHandle* handle) { return base::MakeUnique<InterceptNavigationThrottle>( - handle, base::Bind(&CheckIfShouldIgnoreNavigationOnUIThread), false); + handle, base::Bind(&CheckIfShouldIgnoreNavigationOnUIThread)); } // static
diff --git a/components/navigation_interception/intercept_navigation_throttle.cc b/components/navigation_interception/intercept_navigation_throttle.cc index a6bbcd0..db7a1dd1 100644 --- a/components/navigation_interception/intercept_navigation_throttle.cc +++ b/components/navigation_interception/intercept_navigation_throttle.cc
@@ -12,38 +12,11 @@ namespace navigation_interception { -namespace { - -using ChecksPerformedCallback = base::Callback<void(bool)>; - -// This is used to run |should_ignore_callback| if it can destroy the -// WebContents (and the InterceptNavigationThrottle along). In that case, -// |on_checks_performed_callback| will be a no-op. -void RunCallback( - content::WebContents* web_contents, - const NavigationParams& navigation_params, - InterceptNavigationThrottle::CheckCallback should_ignore_callback, - ChecksPerformedCallback on_checks_performed_callback, - base::WeakPtr<InterceptNavigationThrottle> throttle) { - bool should_ignore_navigation = - should_ignore_callback.Run(web_contents, navigation_params); - - // If the InterceptNavigationThrottle that called RunCallback is still alive - // after |should_ignore_callback| has run, this will run - // InterceptNavigationThrottle::OnAsynchronousChecksPerformed. - on_checks_performed_callback.Run(should_ignore_navigation); -} - -} // namespace - InterceptNavigationThrottle::InterceptNavigationThrottle( content::NavigationHandle* navigation_handle, - CheckCallback should_ignore_callback, - bool run_callback_synchronously) + CheckCallback should_ignore_callback) : content::NavigationThrottle(navigation_handle), - should_ignore_callback_(should_ignore_callback), - run_callback_synchronously_(run_callback_synchronously), - weak_factory_(this) {} + should_ignore_callback_(should_ignore_callback) {} InterceptNavigationThrottle::~InterceptNavigationThrottle() {} @@ -72,58 +45,11 @@ navigation_handle()->GetPageTransition(), is_redirect, navigation_handle()->IsExternalProtocol(), true, navigation_handle()->GetBaseURLForDataURL()); - - if (run_callback_synchronously_) { - bool should_ignore_navigation = should_ignore_callback_.Run( - navigation_handle()->GetWebContents(), navigation_params); - return should_ignore_navigation - ? content::NavigationThrottle::CANCEL_AND_IGNORE - : content::NavigationThrottle::PROCEED; - } - - // When the callback can potentially destroy the WebContents, along with the - // NavigationHandle and this InterceptNavigationThrottle, it should be run - // asynchronously. This will ensure that no objects on the stack can be - // deleted, and that the stack does not unwind through them in a deleted - // state. - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&InterceptNavigationThrottle::RunCallbackAsynchronously, - weak_factory_.GetWeakPtr(), navigation_params)); - return DEFER; -} - -void InterceptNavigationThrottle::RunCallbackAsynchronously( - const NavigationParams& navigation_params) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - // Run the callback in a helper function as it may lead ot the destruction of - // this InterceptNavigationThrottle. - RunCallback( - navigation_handle()->GetWebContents(), navigation_params, - should_ignore_callback_, - base::Bind(&InterceptNavigationThrottle::OnAsynchronousChecksPerformed, - weak_factory_.GetWeakPtr()), - weak_factory_.GetWeakPtr()); - - // DO NOT ADD CODE AFTER HERE: at this point the InterceptNavigationThrottle - // may have been destroyed by the |should_ignore_callback_|. Adding code here - // will cause use-after-free bugs. - // - // Code that needs to act on the result of the |should_ignore_callback_| - // should be put inside OnAsynchronousChecksPerformed. This function will be - // called after |should_ignore_callback_| has run, if this - // InterceptNavigationThrottle is still alive. -} - -void InterceptNavigationThrottle::OnAsynchronousChecksPerformed( - bool should_ignore_navigation) { - if (should_ignore_navigation) { - navigation_handle()->CancelDeferredNavigation( - content::NavigationThrottle::CANCEL_AND_IGNORE); - } else { - navigation_handle()->Resume(); - } + bool should_ignore_navigation = should_ignore_callback_.Run( + navigation_handle()->GetWebContents(), navigation_params); + return should_ignore_navigation + ? content::NavigationThrottle::CANCEL_AND_IGNORE + : content::NavigationThrottle::PROCEED; } } // namespace navigation_interception
diff --git a/components/navigation_interception/intercept_navigation_throttle.h b/components/navigation_interception/intercept_navigation_throttle.h index 09158b8..7607fd5f 100644 --- a/components/navigation_interception/intercept_navigation_throttle.h +++ b/components/navigation_interception/intercept_navigation_throttle.h
@@ -30,8 +30,7 @@ CheckCallback; InterceptNavigationThrottle(content::NavigationHandle* navigation_handle, - CheckCallback should_ignore_callback, - bool run_callback_synchronously); + CheckCallback should_ignore_callback); ~InterceptNavigationThrottle() override; // content::NavigationThrottle implementation: @@ -42,19 +41,8 @@ private: ThrottleCheckResult CheckIfShouldIgnoreNavigation(bool is_redirect); - // Called to perform the checks asynchronously - void RunCallbackAsynchronously(const NavigationParams& navigation_params); - void OnAsynchronousChecksPerformed(bool should_ignore_navigation); - CheckCallback should_ignore_callback_; - // Whether the callback will be run synchronously or not. If the callback can - // lead to the destruction of the WebContents, this should be false. - // Otherwise this should be true. - const bool run_callback_synchronously_; - - base::WeakPtrFactory<InterceptNavigationThrottle> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(InterceptNavigationThrottle); };
diff --git a/components/navigation_interception/intercept_navigation_throttle_unittest.cc b/components/navigation_interception/intercept_navigation_throttle_unittest.cc index a6d27c49..0b3ed14 100644 --- a/components/navigation_interception/intercept_navigation_throttle_unittest.cc +++ b/components/navigation_interception/intercept_navigation_throttle_unittest.cc
@@ -68,8 +68,7 @@ base::MakeUnique<InterceptNavigationThrottle>( test_handle.get(), base::Bind(&MockInterceptCallbackReceiver::ShouldIgnoreNavigation, - base::Unretained(mock_callback_receiver_.get())), - true)); + base::Unretained(mock_callback_receiver_.get())))); return test_handle->CallWillStartRequestForTesting( is_post, content::Referrer(), false, ui::PAGE_TRANSITION_LINK, false); } @@ -82,8 +81,7 @@ base::MakeUnique<InterceptNavigationThrottle>( test_handle.get(), base::Bind(&MockInterceptCallbackReceiver::ShouldIgnoreNavigation, - base::Unretained(mock_callback_receiver_.get())), - true)); + base::Unretained(mock_callback_receiver_.get())))); test_handle->CallWillStartRequestForTesting( true, content::Referrer(), false, ui::PAGE_TRANSITION_LINK, false); return test_handle->CallWillRedirectRequestForTesting(GURL(kTestUrl), false,
diff --git a/components/offline_pages/core/prefetch/BUILD.gn b/components/offline_pages/core/prefetch/BUILD.gn index 68e0e51..396615e 100644 --- a/components/offline_pages/core/prefetch/BUILD.gn +++ b/components/offline_pages/core/prefetch/BUILD.gn
@@ -22,8 +22,6 @@ "prefetch_gcm_app_handler.cc", "prefetch_gcm_app_handler.h", "prefetch_gcm_handler.h", - "prefetch_in_memory_store.cc", - "prefetch_in_memory_store.h", "prefetch_item.cc", "prefetch_item.h", "prefetch_proto_utils.cc", @@ -33,7 +31,6 @@ "prefetch_service.h", "prefetch_service_impl.cc", "prefetch_service_impl.h", - "prefetch_store.h", "prefetch_types.cc", "prefetch_types.h", "suggested_articles_observer.cc", @@ -85,7 +82,6 @@ "proto/offline_pages.proto", "proto/operation.proto", "proto/status.proto", - "proto/timestamp.proto", ] }
diff --git a/components/offline_pages/core/prefetch/README.md b/components/offline_pages/core/prefetch/README.md index 46e5a0e..bd1baf0 100644 --- a/components/offline_pages/core/prefetch/README.md +++ b/components/offline_pages/core/prefetch/README.md
@@ -1,6 +1,28 @@ -# Prefetching Offline Pages: development guidelines +# Prefetching Offline Pages -* Implementations that are injected dependencies should always provide - lightweight construction and postpone heavier initialization (i.e. DB +## Architecture overview + +### PrefetchService + +Is the ownership holder for the main components of the prefetching system and +controls their lifetime. + +### PrefetchDispatcher + +Manages the prefetching pipeline tasks. It receives signals from external +clients and creates the appropriate tasks to execute them. It _might_ at some +point execute advanced task management operations like canceling queued tasks or +changing their order of execution. + +### \*Task(s) (i.e. AddUniqueUrlsTask) + +They are the main wrapper of pipeline steps and interact with different +abstracted components (Downloads, persistent store, GCM, etc) to execute them. +They implement TaskQueue's Task API so that they can be exclusively executed. + +## Development guidelines + +* Implementations that are injected dependencies during service creation should + have lightweight construction and postpone heavier initialization (i.e. DB connection) to a later moment. Lazy initialization upon first actual usage is recommended.
diff --git a/components/offline_pages/core/prefetch/add_unique_urls_task.cc b/components/offline_pages/core/prefetch/add_unique_urls_task.cc index 58f46a0..e25cc54 100644 --- a/components/offline_pages/core/prefetch/add_unique_urls_task.cc +++ b/components/offline_pages/core/prefetch/add_unique_urls_task.cc
@@ -4,21 +4,55 @@ #include "components/offline_pages/core/prefetch/add_unique_urls_task.h" +#include <memory> +#include <utility> + #include "base/bind.h" +#include "base/callback.h" +#include "url/gurl.h" namespace offline_pages { +namespace { + +// Adds new prefetch item entries to the store using the URLs and client IDs +// from |prefetch_urls| and the client's |name_space|. Also cleans up entries in +// the Zombie state from the client's |name_space| except for the ones +// whose URL is contained in |prefetch_urls|. +// Returns the number of added prefecth items. +static int AddUrlsAndCleanupZombies( + const std::string& name_space, + const std::vector<PrefetchURL>& prefetch_urls) { + NOTIMPLEMENTED(); + return 1; +} + +// TODO(fgorski): replace this with the SQL executor. +static void Execute(base::RepeatingCallback<int()> command_callback, + base::OnceCallback<void(int)> result_callback) { + std::move(result_callback).Run(command_callback.Run()); +} +} + AddUniqueUrlsTask::AddUniqueUrlsTask( - PrefetchStore* store, + const std::string& name_space, const std::vector<PrefetchURL>& prefetch_urls) - : prefetch_store_(store), + : name_space_(name_space), prefetch_urls_(prefetch_urls), weak_ptr_factory_(this) {} AddUniqueUrlsTask::~AddUniqueUrlsTask() {} void AddUniqueUrlsTask::Run() { - CHECK(prefetch_store_); + Execute(base::BindRepeating(&AddUrlsAndCleanupZombies, name_space_, + prefetch_urls_), + base::BindOnce(&AddUniqueUrlsTask::OnUrlsAdded, + weak_ptr_factory_.GetWeakPtr())); +} + +void AddUniqueUrlsTask::OnUrlsAdded(int added_entry_count) { + // TODO(carlosk): schedule NWake here if at least one new entry was added to + // the store. TaskComplete(); }
diff --git a/components/offline_pages/core/prefetch/add_unique_urls_task.h b/components/offline_pages/core/prefetch/add_unique_urls_task.h index c7a1161..c265cd3b 100644 --- a/components/offline_pages/core/prefetch/add_unique_urls_task.h +++ b/components/offline_pages/core/prefetch/add_unique_urls_task.h
@@ -5,13 +5,12 @@ #ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_ADD_UNIQUE_URLS_TASK_H_ #define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_ADD_UNIQUE_URLS_TASK_H_ +#include <string> #include <vector> #include "base/memory/weak_ptr.h" -#include "components/offline_pages/core/prefetch/prefetch_store.h" #include "components/offline_pages/core/prefetch/prefetch_types.h" #include "components/offline_pages/core/task.h" -#include "url/gurl.h" namespace offline_pages { @@ -26,14 +25,16 @@ // from the store. class AddUniqueUrlsTask : public Task { public: - AddUniqueUrlsTask(PrefetchStore* store, + AddUniqueUrlsTask(const std::string& name_space, const std::vector<PrefetchURL>& prefetch_urls); ~AddUniqueUrlsTask() override; void Run() override; private: - PrefetchStore* prefetch_store_; + void OnUrlsAdded(int added_entry_count); + + const std::string& name_space_; std::vector<PrefetchURL> prefetch_urls_; base::WeakPtrFactory<AddUniqueUrlsTask> weak_ptr_factory_;
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher.h b/components/offline_pages/core/prefetch/prefetch_dispatcher.h index f5e0d63..033cd545 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher.h +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher.h
@@ -45,6 +45,7 @@ // with the client's unique namespace. URLs that are currently in the system // for this client are acceptable but ignored. virtual void AddCandidatePrefetchURLs( + const std::string& name_space, const std::vector<PrefetchURL>& prefetch_urls) = 0; // Called when all existing suggestions are no longer considered valid for a
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc index ae20c62..55b95a1 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
@@ -34,12 +34,13 @@ } void PrefetchDispatcherImpl::AddCandidatePrefetchURLs( + const std::string& name_space, const std::vector<PrefetchURL>& prefetch_urls) { if (!IsPrefetchingOfflinePagesEnabled()) return; - std::unique_ptr<Task> add_task = base::MakeUnique<AddUniqueUrlsTask>( - service_->GetPrefetchStore(), prefetch_urls); + std::unique_ptr<Task> add_task = + base::MakeUnique<AddUniqueUrlsTask>(name_space, prefetch_urls); task_queue_.AddTask(std::move(add_task)); }
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h index 4f2b5af..c3c5236 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h
@@ -24,6 +24,7 @@ // PrefetchDispatcher implementation: void SetService(PrefetchService* service) override; void AddCandidatePrefetchURLs( + const std::string& name_space, const std::vector<PrefetchURL>& prefetch_urls) override; void RemoveAllUnprocessedPrefetchURLs(const std::string& name_space) override; void RemovePrefetchURLsByClientId(const ClientId& client_id) override;
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc index 846f697..0572782 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc
@@ -12,12 +12,14 @@ #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/offline_event_logger.h" #include "components/offline_pages/core/offline_page_feature.h" -#include "components/offline_pages/core/prefetch/prefetch_in_memory_store.h" #include "components/offline_pages/core/prefetch/prefetch_service.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" namespace offline_pages { +namespace { + class TestScopedBackgroundTask : public PrefetchDispatcher::ScopedBackgroundTask { public: @@ -31,8 +33,12 @@ bool needs_reschedule_called = false; }; +} // namespace + class PrefetchDispatcherTest : public testing::Test, public PrefetchService { public: + const std::string TEST_NAMESPACE = "TestPrefetchClientNamespace"; + PrefetchDispatcherTest(); // Test implementation. @@ -44,7 +50,6 @@ OfflineMetricsCollector* GetOfflineMetricsCollector() override; PrefetchDispatcher* GetPrefetchDispatcher() override; PrefetchGCMHandler* GetPrefetchGCMHandler() override; - PrefetchStore* GetPrefetchStore() override; SuggestedArticlesObserver* GetSuggestedArticlesObserver() override; // KeyedService implementation. @@ -57,13 +62,13 @@ TaskQueue* dispatcher_task_queue() { return &dispatcher_impl_->task_queue_; } + protected: + std::vector<PrefetchURL> test_urls_; + private: + std::unique_ptr<PrefetchDispatcherImpl> dispatcher_impl_; OfflineEventLogger logger_; base::test::ScopedFeatureList feature_list_; - - std::unique_ptr<PrefetchInMemoryStore> in_memory_store_; - std::unique_ptr<PrefetchDispatcherImpl> dispatcher_impl_; - scoped_refptr<base::TestSimpleTaskRunner> task_runner_; base::ThreadTaskRunnerHandle task_runner_handle_; }; @@ -77,9 +82,12 @@ void PrefetchDispatcherTest::SetUp() { ASSERT_EQ(base::ThreadTaskRunnerHandle::Get(), task_runner_); ASSERT_FALSE(task_runner_->HasPendingTask()); - in_memory_store_ = base::MakeUnique<PrefetchInMemoryStore>(); dispatcher_impl_ = base::MakeUnique<PrefetchDispatcherImpl>(); dispatcher_impl_->SetService(this); + + ASSERT_TRUE(test_urls_.empty()); + test_urls_.push_back({"1", GURL("http://testurl.com/foo")}); + test_urls_.push_back({"2", GURL("https://testurl.com/bar")}); } void PrefetchDispatcherTest::TearDown() { @@ -104,10 +112,6 @@ return nullptr; } -PrefetchStore* PrefetchDispatcherTest::GetPrefetchStore() { - return in_memory_store_.get(); -} - SuggestedArticlesObserver* PrefetchDispatcherTest::GetSuggestedArticlesObserver() { NOTREACHED(); @@ -119,7 +123,7 @@ } TEST_F(PrefetchDispatcherTest, DispatcherDoesNotCrash) { - GetPrefetchDispatcher()->AddCandidatePrefetchURLs(std::vector<PrefetchURL>()); + GetPrefetchDispatcher()->AddCandidatePrefetchURLs(TEST_NAMESPACE, test_urls_); GetPrefetchDispatcher()->RemoveAllUnprocessedPrefetchURLs( kSuggestedArticlesNamespace); GetPrefetchDispatcher()->RemovePrefetchURLsByClientId( @@ -127,7 +131,7 @@ } TEST_F(PrefetchDispatcherTest, AddCandidatePrefetchURLsTask) { - GetPrefetchDispatcher()->AddCandidatePrefetchURLs(std::vector<PrefetchURL>()); + GetPrefetchDispatcher()->AddCandidatePrefetchURLs(TEST_NAMESPACE, test_urls_); EXPECT_TRUE(dispatcher_task_queue()->HasPendingTasks()); EXPECT_TRUE(dispatcher_task_queue()->HasRunningTask()); PumpLoop(); @@ -140,10 +144,9 @@ disabled_feature_list.InitAndDisableFeature(kPrefetchingOfflinePagesFeature); // Don't add a task for new prefetch URLs. - ClientId client_id("namespace", "id"); - PrefetchURL prefetch_url(client_id, GURL("https://www.chromium.org")); + PrefetchURL prefetch_url("id", GURL("https://www.chromium.org")); GetPrefetchDispatcher()->AddCandidatePrefetchURLs( - std::vector<PrefetchURL>(1, prefetch_url)); + TEST_NAMESPACE, std::vector<PrefetchURL>(1, prefetch_url)); EXPECT_FALSE(dispatcher_task_queue()->HasRunningTask()); // Do nothing with a new background task.
diff --git a/components/offline_pages/core/prefetch/prefetch_in_memory_store.cc b/components/offline_pages/core/prefetch/prefetch_in_memory_store.cc deleted file mode 100644 index efab3dba..0000000 --- a/components/offline_pages/core/prefetch/prefetch_in_memory_store.cc +++ /dev/null
@@ -1,13 +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/offline_pages/core/prefetch/prefetch_in_memory_store.h" - -namespace offline_pages { - -PrefetchInMemoryStore::PrefetchInMemoryStore() = default; - -PrefetchInMemoryStore::~PrefetchInMemoryStore() = default; - -} // namespace offline_pages \ No newline at end of file
diff --git a/components/offline_pages/core/prefetch/prefetch_in_memory_store.h b/components/offline_pages/core/prefetch/prefetch_in_memory_store.h deleted file mode 100644 index 700b3a8..0000000 --- a/components/offline_pages/core/prefetch/prefetch_in_memory_store.h +++ /dev/null
@@ -1,21 +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_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_IN_MEMORY_STORE_H_ -#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_IN_MEMORY_STORE_H_ - -#include "components/offline_pages/core/prefetch/prefetch_store.h" - -namespace offline_pages { - -// A PrefetchStore implementation that keeps all persisted data in memory. -class PrefetchInMemoryStore : public PrefetchStore { - public: - PrefetchInMemoryStore(); - ~PrefetchInMemoryStore() override; -}; - -} // namespace offline_pages - -#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_IN_MEMORY_STORE_H_
diff --git a/components/offline_pages/core/prefetch/prefetch_service.h b/components/offline_pages/core/prefetch/prefetch_service.h index 3d00d98..d797fa7 100644 --- a/components/offline_pages/core/prefetch/prefetch_service.h +++ b/components/offline_pages/core/prefetch/prefetch_service.h
@@ -12,7 +12,6 @@ class OfflineMetricsCollector; class PrefetchDispatcher; class PrefetchGCMHandler; -class PrefetchStore; class SuggestedArticlesObserver; // Main class and entry point for the Offline Pages Prefetching feature, that @@ -26,11 +25,10 @@ // The service manages lifetime, hookup and initialization of Prefetch // system that consists of multiple specialized objects, all vended by this // service. + virtual OfflineEventLogger* GetLogger() = 0; virtual OfflineMetricsCollector* GetOfflineMetricsCollector() = 0; virtual PrefetchDispatcher* GetPrefetchDispatcher() = 0; virtual PrefetchGCMHandler* GetPrefetchGCMHandler() = 0; - virtual PrefetchStore* GetPrefetchStore() = 0; - virtual OfflineEventLogger* GetLogger() = 0; // May be |nullptr| in tests. The PrefetchService does not depend on the // SuggestedArticlesObserver, it merely owns it for lifetime purposes.
diff --git a/components/offline_pages/core/prefetch/prefetch_service_impl.cc b/components/offline_pages/core/prefetch/prefetch_service_impl.cc index 11d1d6f..e84b846 100644 --- a/components/offline_pages/core/prefetch/prefetch_service_impl.cc +++ b/components/offline_pages/core/prefetch/prefetch_service_impl.cc
@@ -11,7 +11,6 @@ #include "components/offline_pages/core/prefetch/offline_metrics_collector.h" #include "components/offline_pages/core/prefetch/prefetch_dispatcher.h" #include "components/offline_pages/core/prefetch/prefetch_gcm_handler.h" -#include "components/offline_pages/core/prefetch/prefetch_store.h" #include "components/offline_pages/core/prefetch/suggested_articles_observer.h" namespace offline_pages { @@ -20,12 +19,10 @@ std::unique_ptr<OfflineMetricsCollector> offline_metrics_collector, std::unique_ptr<PrefetchDispatcher> dispatcher, std::unique_ptr<PrefetchGCMHandler> gcm_handler, - std::unique_ptr<PrefetchStore> store, std::unique_ptr<SuggestedArticlesObserver> suggested_articles_observer) : offline_metrics_collector_(std::move(offline_metrics_collector)), prefetch_dispatcher_(std::move(dispatcher)), prefetch_gcm_handler_(std::move(gcm_handler)), - prefetch_store_(std::move(store)), suggested_articles_observer_(std::move(suggested_articles_observer)) { prefetch_dispatcher_->SetService(this); prefetch_gcm_handler_->SetService(this); @@ -45,10 +42,6 @@ return prefetch_gcm_handler_.get(); } -PrefetchStore* PrefetchServiceImpl::GetPrefetchStore() { - return prefetch_store_.get(); -} - SuggestedArticlesObserver* PrefetchServiceImpl::GetSuggestedArticlesObserver() { return suggested_articles_observer_.get(); }
diff --git a/components/offline_pages/core/prefetch/prefetch_service_impl.h b/components/offline_pages/core/prefetch/prefetch_service_impl.h index eb70d04..800ac4ed 100644 --- a/components/offline_pages/core/prefetch/prefetch_service_impl.h +++ b/components/offline_pages/core/prefetch/prefetch_service_impl.h
@@ -23,7 +23,6 @@ std::unique_ptr<OfflineMetricsCollector> offline_metrics_collector, std::unique_ptr<PrefetchDispatcher> dispatcher, std::unique_ptr<PrefetchGCMHandler> gcm_handler, - std::unique_ptr<PrefetchStore> store, std::unique_ptr<SuggestedArticlesObserver> suggested_articles_observer); ~PrefetchServiceImpl() override; @@ -31,7 +30,6 @@ OfflineMetricsCollector* GetOfflineMetricsCollector() override; PrefetchDispatcher* GetPrefetchDispatcher() override; PrefetchGCMHandler* GetPrefetchGCMHandler() override; - PrefetchStore* GetPrefetchStore() override; SuggestedArticlesObserver* GetSuggestedArticlesObserver() override; OfflineEventLogger* GetLogger() override; @@ -44,7 +42,6 @@ std::unique_ptr<OfflineMetricsCollector> offline_metrics_collector_; std::unique_ptr<PrefetchDispatcher> prefetch_dispatcher_; std::unique_ptr<PrefetchGCMHandler> prefetch_gcm_handler_; - std::unique_ptr<PrefetchStore> prefetch_store_; std::unique_ptr<SuggestedArticlesObserver> suggested_articles_observer_; DISALLOW_COPY_AND_ASSIGN(PrefetchServiceImpl);
diff --git a/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc b/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc index 4161a07..96c6783 100644 --- a/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc +++ b/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc
@@ -10,7 +10,6 @@ #include "components/offline_pages/core/prefetch/prefetch_dispatcher.h" #include "components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h" #include "components/offline_pages/core/prefetch/prefetch_gcm_handler.h" -#include "components/offline_pages/core/prefetch/prefetch_in_memory_store.h" #include "components/offline_pages/core/prefetch/prefetch_service_impl.h" #include "components/offline_pages/core/prefetch/suggested_articles_observer.h" #include "components/offline_pages/core/prefetch/test_offline_metrics_collector.h" @@ -22,7 +21,6 @@ metrics_collector_ = base::MakeUnique<TestOfflineMetricsCollector>(); dispatcher_ = base::MakeUnique<PrefetchDispatcherImpl>(); gcm_handler_ = base::MakeUnique<TestPrefetchGCMHandler>(); - store_ = base::MakeUnique<PrefetchInMemoryStore>(); } PrefetchServiceTestTaco::~PrefetchServiceTestTaco() = default; @@ -45,12 +43,6 @@ gcm_handler_ = std::move(gcm_handler); } -void PrefetchServiceTestTaco::SetPrefetchStore( - std::unique_ptr<PrefetchStore> store) { - CHECK(!prefetch_service_); - store_ = std::move(store); -} - void PrefetchServiceTestTaco::SetSuggestedArticlesObserver( std::unique_ptr<SuggestedArticlesObserver> suggested_articles_observer) { CHECK(!prefetch_service_); @@ -60,8 +52,7 @@ void PrefetchServiceTestTaco::CreatePrefetchService() { prefetch_service_ = base::MakeUnique<PrefetchServiceImpl>( std::move(metrics_collector_), std::move(dispatcher_), - std::move(gcm_handler_), std::move(store_), - std::move(suggested_articles_observer_)); + std::move(gcm_handler_), std::move(suggested_articles_observer_)); } } // namespace offline_page
diff --git a/components/offline_pages/core/prefetch/prefetch_service_test_taco.h b/components/offline_pages/core/prefetch/prefetch_service_test_taco.h index 08ccfd6..69708f7 100644 --- a/components/offline_pages/core/prefetch/prefetch_service_test_taco.h +++ b/components/offline_pages/core/prefetch/prefetch_service_test_taco.h
@@ -14,7 +14,6 @@ class PrefetchDispatcher; class PrefetchGCMHandler; class PrefetchService; -class PrefetchStore; class SuggestedArticlesObserver; // The taco class acts as a wrapper around the prefetch service making @@ -27,7 +26,6 @@ // * TestOfflineMetricsCollector // * PrefetchDispatcherImpl // * TestPrefetchGCMHandler -// * PrefetchInMemoryStore // * |nullptr| SuggestedArticlesObserver, since this is default just a lifetime // arrangement. class PrefetchServiceTestTaco { @@ -41,7 +39,6 @@ std::unique_ptr<OfflineMetricsCollector> metrics_collector); void SetPrefetchDispatcher(std::unique_ptr<PrefetchDispatcher> dispatcher); void SetPrefetchGCMHandler(std::unique_ptr<PrefetchGCMHandler> gcm_handler); - void SetPrefetchStore(std::unique_ptr<PrefetchStore> prefetch_store); void SetSuggestedArticlesObserver( std::unique_ptr<SuggestedArticlesObserver> suggested_articles_observer); @@ -61,7 +58,6 @@ std::unique_ptr<OfflineMetricsCollector> metrics_collector_; std::unique_ptr<PrefetchDispatcher> dispatcher_; std::unique_ptr<PrefetchGCMHandler> gcm_handler_; - std::unique_ptr<PrefetchStore> store_; std::unique_ptr<SuggestedArticlesObserver> suggested_articles_observer_; std::unique_ptr<PrefetchService> prefetch_service_;
diff --git a/components/offline_pages/core/prefetch/prefetch_store.h b/components/offline_pages/core/prefetch/prefetch_store.h deleted file mode 100644 index 4f084d5e..0000000 --- a/components/offline_pages/core/prefetch/prefetch_store.h +++ /dev/null
@@ -1,18 +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_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_STORE_H_ -#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_STORE_H_ - -namespace offline_pages { - -// Persistent storage access class for prefetching offline pages data. -class PrefetchStore { - public: - virtual ~PrefetchStore() = default; -}; - -} // namespace offline_pages - -#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_STORE_H_
diff --git a/components/offline_pages/core/prefetch/prefetch_types.h b/components/offline_pages/core/prefetch/prefetch_types.h index 8fb4bbe4..20d9abea 100644 --- a/components/offline_pages/core/prefetch/prefetch_types.h +++ b/components/offline_pages/core/prefetch/prefetch_types.h
@@ -109,15 +109,15 @@ const std::string& operation_name, const std::vector<RenderPageInfo>& pages)>; -// Holds information about a new URL to be prefetched. +// Holds information about a suggested URL to be prefetched. struct PrefetchURL { - PrefetchURL(const ClientId& client_id, const GURL& url) - : client_id(client_id), url(url) {} + PrefetchURL(const std::string& id, const GURL& url) : id(id), url(url) {} - // Client provided ID to allow the matching of URLs to the respective work - // item in the prefetching system. It can be anything useful to identify the - // page . It will not be used internally for de-duplication. - ClientId client_id; + // Client provided ID to allow the matching of provided URLs to the respective + // work item in the prefetching system within that client's assigned + // namespace. It can be any string value and it will not be used internally + // for de-duplication. + std::string id; // This URL will be prefetched by the service. GURL url;
diff --git a/components/offline_pages/core/prefetch/proto/any.proto b/components/offline_pages/core/prefetch/proto/any.proto index bc71002..c575c70 100644 --- a/components/offline_pages/core/prefetch/proto/any.proto +++ b/components/offline_pages/core/prefetch/proto/any.proto
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -syntax = "proto3"; +syntax = "proto2"; option optimize_for = LITE_RUNTIME; package offline_pages.proto; message Any { - string type_url = 1; - bytes value = 2; + optional string type_url = 1; + optional bytes value = 2; }
diff --git a/components/offline_pages/core/prefetch/proto/offline_pages.proto b/components/offline_pages/core/prefetch/proto/offline_pages.proto index bffc766..37580909 100644 --- a/components/offline_pages/core/prefetch/proto/offline_pages.proto +++ b/components/offline_pages/core/prefetch/proto/offline_pages.proto
@@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -syntax = "proto3"; +syntax = "proto2"; option optimize_for = LITE_RUNTIME; package offline_pages.proto; import "status.proto"; -import "timestamp.proto"; // Type of transformation applied to a web page. enum Transformation { @@ -26,6 +25,19 @@ FORMAT_MHTML = 1; } +message Timestamp { + // Represents seconds of UTC time since Unix epoch + // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + // 9999-12-31T23:59:59Z inclusive. + optional int64 seconds = 1; + + // Non-negative fractions of a second at nanosecond resolution. Negative + // second values with fractions must still have non-negative nanos values + // that count forward in time. Must be from 0 to 999,999,999 + // inclusive. + optional int32 nanos = 2; +} + // Response to the GeneratePageBundle request. message PageBundle { // The list of archives in the bundle. The distribution of pages into archives @@ -40,49 +52,49 @@ // those that encountered an error or were elided due to size considerations. repeated PageInfo page_infos = 1; // Format of the body. - OutputFormat output_format = 2; + optional OutputFormat output_format = 2; // Resource name for the body which can be read via the ByteStream API. // This resource will remain available for a minimum of 24 hours after the // GeneratePageBundle request. - string body_name = 3; + optional string body_name = 3; // Length of the body in bytes. - int64 body_length = 4; + optional int64 body_length = 4; } // Information about a single returned offline page. message PageInfo { // The URL of the page that was rendered. - string url = 1; + optional string url = 1; // The final URL after redirects. Empty if the final URL is url. - string redirect_url = 2; + optional string redirect_url = 2; // Status of the render attempt. If status.code != OK, fields below this will // be unset. If the operation is still running, status is NotFound to // indicate the page is still being processed. // If the page was not returned due to bundle size limits, status is // FailedPrecondition. If the page failed to render for any other reason, // status is Unknown. - Status status = 3; + optional Status status = 3; // Transformation that was applied to the page. - Transformation transformation = 4; + optional Transformation transformation = 4; // Time the page was rendered. - Timestamp render_time = 5; + optional Timestamp render_time = 5; } // Request to return a list of pages in a format suitable for offline viewing. message GeneratePageBundleRequest { // The client's browser's user agent string. - string user_agent = 1; + optional string user_agent = 1; // Preferred browser language(s) as defined by // [IETF BCP 47](https://tools.ietf.org/html/bcp47). repeated string browser_languages = 2; // Desired format of the web page archive(s). - OutputFormat output_format = 3; + optional OutputFormat output_format = 3; // Maximum size of the generated body. If all pages' output would exceed this // size, only the first N pages are returned. - int64 max_bundle_size_bytes = 4; + optional int64 max_bundle_size_bytes = 4; // The GCM registration ID that can be used to inform the client // of LRO completion. - string gcm_registration_id = 5; + optional string gcm_registration_id = 5; // List of individual page requests, in order of priority. At most 100 pages // may be requested at a time. repeated PageParameters pages = 6; @@ -92,7 +104,7 @@ // viewing. message PageParameters { // URL of the web page to return. - string url = 1; + optional string url = 1; // Transformation to apply. Must not be TRANSFORMATION_UNSPECIFIED. - Transformation transformation = 2; + optional Transformation transformation = 2; }
diff --git a/components/offline_pages/core/prefetch/proto/operation.proto b/components/offline_pages/core/prefetch/proto/operation.proto index 77558d9f..db0b1eee 100644 --- a/components/offline_pages/core/prefetch/proto/operation.proto +++ b/components/offline_pages/core/prefetch/proto/operation.proto
@@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -syntax = "proto3"; +syntax = "proto2"; option optimize_for = LITE_RUNTIME; package offline_pages.proto; -; import "any.proto"; import "status.proto"; @@ -16,18 +15,18 @@ message Operation { // The server-assigned name, which is only unique within the same service that // originally returns it. - string name = 1; + optional string name = 1; // Service-specific metadata associated with the operation. It typically // contains progress information and common metadata such as create time. // Some services might not provide such metadata. Any method that returns a // long-running operation should document the metadata type, if any. - Any metadata = 2; + optional Any metadata = 2; // If the value is 'false', it means the operation is still in progress. // If true, the operation is completed, and either 'error' or 'response' is // available. - bool done = 3; + optional bool done = 3; // The operation result, which can be either an 'error' or a valid 'response'. // If 'done' == 'false', neither 'error' nor 'response' is set.
diff --git a/components/offline_pages/core/prefetch/proto/status.proto b/components/offline_pages/core/prefetch/proto/status.proto index f7187993..affec0b 100644 --- a/components/offline_pages/core/prefetch/proto/status.proto +++ b/components/offline_pages/core/prefetch/proto/status.proto
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -syntax = "proto3"; +syntax = "proto2"; option optimize_for = LITE_RUNTIME; package offline_pages.proto; @@ -18,10 +18,10 @@ message Status { // The status code. - int32 code = 1; + optional int32 code = 1; // A developer-facing error message, which should be in English. - string message = 2; + optional string message = 2; // A list of messages that carry the error details. There will be a // common set of message types for APIs to use.
diff --git a/components/offline_pages/core/prefetch/proto/timestamp.proto b/components/offline_pages/core/prefetch/proto/timestamp.proto deleted file mode 100644 index c9658e7..0000000 --- a/components/offline_pages/core/prefetch/proto/timestamp.proto +++ /dev/null
@@ -1,21 +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. - -syntax = "proto3"; -option optimize_for = LITE_RUNTIME; - -package offline_pages.proto; - -message Timestamp { - // Represents seconds of UTC time since Unix epoch - // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - // 9999-12-31T23:59:59Z inclusive. - int64 seconds = 1; - - // Non-negative fractions of a second at nanosecond resolution. Negative - // second values with fractions must still have non-negative nanos values - // that count forward in time. Must be from 0 to 999,999,999 - // inclusive. - int32 nanos = 2; -}
diff --git a/components/offline_pages/core/prefetch/suggested_articles_observer.cc b/components/offline_pages/core/prefetch/suggested_articles_observer.cc index e7225a5a..d0fb3ba 100644 --- a/components/offline_pages/core/prefetch/suggested_articles_observer.cc +++ b/components/offline_pages/core/prefetch/suggested_articles_observer.cc
@@ -28,10 +28,6 @@ return articles; } -ClientId CreateClientIDFromSuggestionId(const ContentSuggestion::ID& id) { - return ClientId(kSuggestedArticlesNamespace, id.id_within_category()); -} - } // namespace SuggestedArticlesObserver::SuggestedArticlesObserver( @@ -71,10 +67,11 @@ std::vector<PrefetchURL> prefetch_urls; for (const ContentSuggestion& suggestion : suggestions) { prefetch_urls.push_back( - {CreateClientIDFromSuggestionId(suggestion.id()), suggestion.url()}); + {suggestion.id().id_within_category(), suggestion.url()}); } - prefetch_dispatcher_->AddCandidatePrefetchURLs(prefetch_urls); + prefetch_dispatcher_->AddCandidatePrefetchURLs(kSuggestedArticlesNamespace, + prefetch_urls); } void SuggestedArticlesObserver::OnCategoryStatusChanged( @@ -96,8 +93,8 @@ void SuggestedArticlesObserver::OnSuggestionInvalidated( const ContentSuggestion::ID& suggestion_id) { - prefetch_dispatcher_->RemovePrefetchURLsByClientId( - CreateClientIDFromSuggestionId(suggestion_id)); + prefetch_dispatcher_->RemovePrefetchURLsByClientId(ClientId( + kSuggestedArticlesNamespace, suggestion_id.id_within_category())); } void SuggestedArticlesObserver::OnFullRefreshRequired() {
diff --git a/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc b/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc index 0338550..0b2febb 100644 --- a/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc +++ b/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc
@@ -76,9 +76,8 @@ EXPECT_EQ(1U, test_prefetch_dispatcher()->latest_prefetch_urls.size()); EXPECT_EQ(test_url_1, test_prefetch_dispatcher()->latest_prefetch_urls[0].url); - EXPECT_EQ( - kSuggestedArticlesNamespace, - test_prefetch_dispatcher()->latest_prefetch_urls[0].client_id.name_space); + EXPECT_EQ(kSuggestedArticlesNamespace, + test_prefetch_dispatcher()->latest_name_space); } TEST_F(OfflinePageSuggestedArticlesObserverTest, RemovesAllOnBadStatus) { @@ -119,9 +118,8 @@ EXPECT_NE(nullptr, test_prefetch_dispatcher()->last_removed_client_id.get()); EXPECT_EQ(test_url_1.spec(), test_prefetch_dispatcher()->last_removed_client_id->id); - EXPECT_EQ( - kSuggestedArticlesNamespace, - test_prefetch_dispatcher()->latest_prefetch_urls[0].client_id.name_space); + EXPECT_EQ(kSuggestedArticlesNamespace, + test_prefetch_dispatcher()->latest_name_space); } } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/test_prefetch_dispatcher.cc b/components/offline_pages/core/prefetch/test_prefetch_dispatcher.cc index da98463..c0a555e 100644 --- a/components/offline_pages/core/prefetch/test_prefetch_dispatcher.cc +++ b/components/offline_pages/core/prefetch/test_prefetch_dispatcher.cc
@@ -13,8 +13,10 @@ TestPrefetchDispatcher::~TestPrefetchDispatcher() = default; void TestPrefetchDispatcher::AddCandidatePrefetchURLs( - const std::vector<PrefetchURL>& suggested_urls) { - latest_prefetch_urls = suggested_urls; + const std::string& name_space, + const std::vector<PrefetchURL>& prefetch_urls) { + latest_name_space = name_space; + latest_prefetch_urls = prefetch_urls; new_suggestions_count++; }
diff --git a/components/offline_pages/core/prefetch/test_prefetch_dispatcher.h b/components/offline_pages/core/prefetch/test_prefetch_dispatcher.h index f768101..fb6620d5 100644 --- a/components/offline_pages/core/prefetch/test_prefetch_dispatcher.h +++ b/components/offline_pages/core/prefetch/test_prefetch_dispatcher.h
@@ -22,7 +22,8 @@ // PrefetchDispatcher implementation. void AddCandidatePrefetchURLs( - const std::vector<PrefetchURL>& suggested_urls) override; + const std::string& name_space, + const std::vector<PrefetchURL>& prefetch_urls) override; void RemoveAllUnprocessedPrefetchURLs(const std::string& name_space) override; void RemovePrefetchURLsByClientId(const ClientId& client_id) override; void BeginBackgroundTask(std::unique_ptr<ScopedBackgroundTask> task) override; @@ -32,6 +33,7 @@ const std::string& operation_name) override; void RequestFinishBackgroundTaskForTest() override; + std::string latest_name_space; std::vector<PrefetchURL> latest_prefetch_urls; std::unique_ptr<ClientId> last_removed_client_id; std::vector<std::string> operation_list;
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc index b5da7d5..7ce26936 100644 --- a/components/plugins/renderer/webview_plugin.cc +++ b/components/plugins/renderer/webview_plugin.cc
@@ -262,9 +262,7 @@ WebLocalFrame* web_frame = WebLocalFrame::Create( blink::WebTreeScopeType::kDocument, this, nullptr, nullptr); web_view_->SetMainFrame(web_frame); - // TODO(dcheng): The main frame widget currently has a special case. - // Eliminate this once WebView is no longer a WebWidget. - WebFrameWidget::Create(this, web_view_, web_frame); + WebFrameWidget::Create(this, web_frame); } WebViewPlugin::WebViewHelper::~WebViewHelper() {
diff --git a/components/printing/renderer/print_web_view_helper.cc b/components/printing/renderer/print_web_view_helper.cc index fba82e0..b7cce0b 100644 --- a/components/printing/renderer/print_web_view_helper.cc +++ b/components/printing/renderer/print_web_view_helper.cc
@@ -586,7 +586,7 @@ blink::WebTreeScopeType::kDocument, &frame_client, nullptr, nullptr); web_view->SetMainFrame(frame); blink::WebWidgetClient web_widget_client; - blink::WebFrameWidget::Create(&web_widget_client, web_view, frame); + blink::WebFrameWidget::Create(&web_widget_client, frame); base::Value html( base::UTF8ToUTF16(ResourceBundle::GetSharedInstance().GetRawDataResource( @@ -808,7 +808,7 @@ blink::WebLocalFrame* main_frame = blink::WebLocalFrame::Create( blink::WebTreeScopeType::kDocument, this, nullptr, nullptr); web_view->SetMainFrame(main_frame); - blink::WebFrameWidget::Create(this, web_view, main_frame); + blink::WebFrameWidget::Create(this, main_frame); frame_.Reset(web_view->MainFrame()->ToWebLocalFrame()); node_to_print_.Reset();
diff --git a/components/proximity_auth/webui/resources/common.css b/components/proximity_auth/webui/resources/common.css index 10c3e09..728a573 100644 --- a/components/proximity_auth/webui/resources/common.css +++ b/components/proximity_auth/webui/resources/common.css
@@ -31,7 +31,7 @@ /** CSS for controls panel */ #controls { - width: 60%; + width: 50%; display: flex; flex-direction: column; overflow-y: hidden; @@ -82,7 +82,7 @@ /** CSS for logs panel */ #logs-panel { - width: 40%; + width: 50%; display: flex; flex-direction: column; border-left: 1px solid rgba(0,0,0,0.12); @@ -92,20 +92,24 @@ flex-direction: row-reverse; } +#copy-logs-button, #clear-logs-button { - cursor: pointer; background-color: rgba(0,0,0,0); border: none; - font-size: 30px; - height: 100%; color: #fff; + cursor: pointer; + font-size: 20px; + height: 100%; + padding: 0 25px; } +#copy-logs-button:hover, #clear-logs-button:hover { cursor: pointer; color: #535553; } +#copy-logs-button:focus, #clear-logs-button:focus { outline: 0; }
diff --git a/components/proximity_auth/webui/resources/logs.js b/components/proximity_auth/webui/resources/logs.js index 2b4144c..8fec5ef1 100644 --- a/components/proximity_auth/webui/resources/logs.js +++ b/components/proximity_auth/webui/resources/logs.js
@@ -17,8 +17,20 @@ WebUI.clearLogs(); }; + var copyLogsButton = document.getElementById('copy-logs-button'); + copyLogsButton.onclick = () => { + this.copyLogsToClipboard(); + }; + WebUI.getLogMessages(); }, + + copyLogsToClipboard: function() { + window.getSelection().selectAllChildren( + document.getElementById('logs-list')); + document.execCommand('copy'); + window.getSelection().removeAllRanges(); + }, }; /**
diff --git a/components/proximity_auth/webui/resources/proximity_auth.html b/components/proximity_auth/webui/resources/proximity_auth.html index 83ee20d..87e55094 100644 --- a/components/proximity_auth/webui/resources/proximity_auth.html +++ b/components/proximity_auth/webui/resources/proximity_auth.html
@@ -88,7 +88,8 @@ <!-- Panel for logs list. --> <section id='logs-panel'> <header> - <button id='clear-logs-button'>∅</button> + <button id='clear-logs-button'>Clear</button> + <button id='copy-logs-button'>Copy to Clipboard</button> </header> <div id='logs-list'> </div> </section> @@ -119,7 +120,7 @@ <div class="flex"></div> <div class='item-source'></div> </div> - <pre class="item-text flex">This is an error.</pre> + <p class="item-text flex">This is an error.</p> </div> </template> </body>
diff --git a/components/safe_browsing/password_protection/BUILD.gn b/components/safe_browsing/password_protection/BUILD.gn index dcd862f..5bf08a8 100644 --- a/components/safe_browsing/password_protection/BUILD.gn +++ b/components/safe_browsing/password_protection/BUILD.gn
@@ -24,6 +24,7 @@ "//components/safe_browsing:csd_proto", "//components/safe_browsing_db:database_manager", "//components/safe_browsing_db:v4_protocol_manager_util", + "//components/safe_browsing_db:whitelist_checker_client", "//content/public/browser:browser", "//net:net", "//third_party/protobuf:protobuf_lite",
diff --git a/components/safe_browsing/password_protection/password_protection_request.cc b/components/safe_browsing/password_protection/password_protection_request.cc index 909c848..f58d30b 100644 --- a/components/safe_browsing/password_protection/password_protection_request.cc +++ b/components/safe_browsing/password_protection/password_protection_request.cc
@@ -1,6 +1,7 @@ // 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/safe_browsing/password_protection/password_protection_request.h" #include "base/memory/ptr_util.h" @@ -8,6 +9,7 @@ #include "base/metrics/histogram_macros.h" #include "components/data_use_measurement/core/data_use_user_data.h" #include "components/password_manager/core/browser/password_reuse_detector.h" +#include "components/safe_browsing_db/whitelist_checker_client.h" #include "content/public/browser/web_contents.h" #include "net/base/escape.h" #include "net/base/load_flags.h" @@ -50,26 +52,37 @@ void PasswordProtectionRequest::Start() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - CheckWhitelistOnUIThread(); + CheckWhitelist(); } -void PasswordProtectionRequest::CheckWhitelistOnUIThread() { +void PasswordProtectionRequest::CheckWhitelist() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - bool* match_whitelist = new bool(false); - tracker_.PostTaskAndReply( + // Start a task on the IO thread to check the whitelist. It may + // callback immediately on the IO thread or take some time if a full-hash- + // check is required. + auto result_callback = base::Bind(&OnWhitelistCheckDoneOnIO, GetWeakPtr()); + tracker_.PostTask( BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(), FROM_HERE, - base::Bind(&PasswordProtectionService::CheckCsdWhitelistOnIOThread, - base::Unretained(password_protection_service_), - main_frame_url_, match_whitelist), - base::Bind(&PasswordProtectionRequest::OnWhitelistCheckDone, this, - base::Owned(match_whitelist))); + base::Bind(&WhitelistCheckerClient::StartCheckCsdWhitelist, + password_protection_service_->database_manager(), + main_frame_url_, result_callback)); } -void PasswordProtectionRequest::OnWhitelistCheckDone( - const bool* match_whitelist) { +// static +void PasswordProtectionRequest::OnWhitelistCheckDoneOnIO( + base::WeakPtr<PasswordProtectionRequest> weak_request, + bool match_whitelist) { + // Don't access weak_request on IO thread. Move it back to UI thread first. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&PasswordProtectionRequest::OnWhitelistCheckDone, weak_request, + match_whitelist)); +} + +void PasswordProtectionRequest::OnWhitelistCheckDone(bool match_whitelist) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (*match_whitelist) + if (match_whitelist) Finish(PasswordProtectionService::MATCHED_WHITELIST, nullptr); else CheckCachedVerdicts();
diff --git a/components/safe_browsing/password_protection/password_protection_request.h b/components/safe_browsing/password_protection/password_protection_request.h index 721739b..4619011 100644 --- a/components/safe_browsing/password_protection/password_protection_request.h +++ b/components/safe_browsing/password_protection/password_protection_request.h
@@ -85,16 +85,16 @@ friend class base::DeleteHelper<PasswordProtectionRequest>; ~PasswordProtectionRequest() override; - void CheckWhitelistOnUIThread(); + // Start checking the whitelist. + void CheckWhitelist(); + + static void OnWhitelistCheckDoneOnIO( + base::WeakPtr<PasswordProtectionRequest> weak_request, + bool match_whitelist); // If |main_frame_url_| matches whitelist, call Finish() immediately; - // otherwise call CheckCachedVerdicts(). It is the task posted back to UI - // thread by the PostTaskAndReply() in CheckWhitelistOnUIThread(). - // |match_whitelist| boolean pointer is used to pass whitelist checking result - // between UI and IO thread. The object it points to will be deleted at the - // end of OnWhitelistCheckDone(), since base::Owned() transfers its ownership - // to this callback function. - void OnWhitelistCheckDone(const bool* match_whitelist); + // otherwise call CheckCachedVerdicts(). + void OnWhitelistCheckDone(bool match_whitelist); // Looks up cached verdicts. If verdict is already cached, call SendRequest(); // otherwise call Finish().
diff --git a/components/safe_browsing/password_protection/password_protection_service.cc b/components/safe_browsing/password_protection/password_protection_service.cc index c7ec2a9d..51d17e93 100644 --- a/components/safe_browsing/password_protection/password_protection_service.cc +++ b/components/safe_browsing/password_protection/password_protection_service.cc
@@ -18,6 +18,7 @@ #include "components/safe_browsing/password_protection/password_protection_request.h" #include "components/safe_browsing_db/database_manager.h" #include "components/safe_browsing_db/v4_protocol_manager_util.h" +#include "components/safe_browsing_db/whitelist_checker_client.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" #include "google_apis/google_api_keys.h" @@ -105,14 +106,6 @@ weak_factory_.InvalidateWeakPtrs(); } -void PasswordProtectionService::CheckCsdWhitelistOnIOThread( - const GURL& url, - bool* check_result) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - *check_result = - url.is_valid() ? database_manager_->MatchCsdWhitelistUrl(url) : true; -} - bool PasswordProtectionService::CanGetReputationOfURL(const GURL& url) { if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS()) return false;
diff --git a/components/safe_browsing/password_protection/password_protection_service_unittest.cc b/components/safe_browsing/password_protection/password_protection_service_unittest.cc index d297ef1..fb61afd5 100644 --- a/components/safe_browsing/password_protection/password_protection_service_unittest.cc +++ b/components/safe_browsing/password_protection/password_protection_service_unittest.cc
@@ -19,6 +19,10 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using testing::_; +using testing::ElementsAre; +using testing::Return; + namespace { const char kFormActionUrl[] = "https://form_action.com/"; @@ -36,7 +40,8 @@ public: MockSafeBrowsingDatabaseManager() {} - MOCK_METHOD1(MatchCsdWhitelistUrl, bool(const GURL&)); + MOCK_METHOD2(CheckCsdWhitelistUrl, + AsyncMatch(const GURL&, SafeBrowsingDatabaseManager::Client*)); protected: ~MockSafeBrowsingDatabaseManager() override {} @@ -167,8 +172,9 @@ void InitializeAndStartPasswordOnFocusRequest(bool match_whitelist, int timeout_in_ms) { GURL target_url(kTargetUrl); - EXPECT_CALL(*database_manager_.get(), MatchCsdWhitelistUrl(target_url)) - .WillRepeatedly(testing::Return(match_whitelist)); + EXPECT_CALL(*database_manager_.get(), CheckCsdWhitelistUrl(target_url, _)) + .WillRepeatedly( + Return(match_whitelist ? AsyncMatch::MATCH : AsyncMatch::NO_MATCH)); request_ = new PasswordProtectionRequest( nullptr, target_url, GURL(kFormActionUrl), GURL(kPasswordFrameUrl), @@ -181,8 +187,9 @@ bool match_whitelist, int timeout_in_ms) { GURL target_url(kTargetUrl); - EXPECT_CALL(*database_manager_.get(), MatchCsdWhitelistUrl(target_url)) - .WillRepeatedly(testing::Return(match_whitelist)); + EXPECT_CALL(*database_manager_.get(), CheckCsdWhitelistUrl(target_url, _)) + .WillRepeatedly( + Return(match_whitelist ? AsyncMatch::MATCH : AsyncMatch::NO_MATCH)); request_ = new PasswordProtectionRequest( nullptr, target_url, GURL(), GURL(), saved_domain, @@ -449,7 +456,7 @@ EXPECT_EQ(nullptr, password_protection_service_->latest_response()); EXPECT_THAT( histograms_.GetAllSamples(kPasswordOnFocusRequestOutcomeHistogramName), - testing::ElementsAre(base::Bucket(4 /* MATCHED_WHITELIST */, 1))); + ElementsAre(base::Bucket(4 /* MATCHED_WHITELIST */, 1))); } TEST_F(PasswordProtectionServiceTest, TestNoRequestSentIfVerdictAlreadyCached) { @@ -461,7 +468,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_THAT( histograms_.GetAllSamples(kPasswordOnFocusRequestOutcomeHistogramName), - testing::ElementsAre(base::Bucket(5 /* RESPONSE_ALREADY_CACHED */, 1))); + ElementsAre(base::Bucket(5 /* RESPONSE_ALREADY_CACHED */, 1))); EXPECT_EQ(LoginReputationClientResponse::LOW_REPUTATION, password_protection_service_->latest_response()->verdict_type()); } @@ -480,7 +487,7 @@ EXPECT_EQ(nullptr, password_protection_service_->latest_response()); EXPECT_THAT( histograms_.GetAllSamples(kPasswordOnFocusRequestOutcomeHistogramName), - testing::ElementsAre(base::Bucket(9 /* FETCH_FAILED */, 1))); + ElementsAre(base::Bucket(9 /* FETCH_FAILED */, 1))); } TEST_F(PasswordProtectionServiceTest, TestMalformedResponse) { @@ -499,7 +506,7 @@ EXPECT_EQ(nullptr, password_protection_service_->latest_response()); EXPECT_THAT( histograms_.GetAllSamples(kPasswordOnFocusRequestOutcomeHistogramName), - testing::ElementsAre(base::Bucket(10 /* RESPONSE_MALFORMED */, 1))); + ElementsAre(base::Bucket(10 /* RESPONSE_MALFORMED */, 1))); } TEST_F(PasswordProtectionServiceTest, TestRequestTimedout) { @@ -510,7 +517,7 @@ EXPECT_EQ(nullptr, password_protection_service_->latest_response()); EXPECT_THAT( histograms_.GetAllSamples(kPasswordOnFocusRequestOutcomeHistogramName), - testing::ElementsAre(base::Bucket(3 /* TIMEDOUT */, 1))); + ElementsAre(base::Bucket(3 /* TIMEDOUT */, 1))); } TEST_F(PasswordProtectionServiceTest, TestRequestAndResponseSuccessfull) { @@ -530,9 +537,9 @@ base::RunLoop().RunUntilIdle(); EXPECT_THAT( histograms_.GetAllSamples(kPasswordOnFocusRequestOutcomeHistogramName), - testing::ElementsAre(base::Bucket(1 /* SUCCEEDED */, 1))); + ElementsAre(base::Bucket(1 /* SUCCEEDED */, 1))); EXPECT_THAT(histograms_.GetAllSamples(kVerdictHistogramName), - testing::ElementsAre(base::Bucket(3 /* PHISHING */, 1))); + ElementsAre(base::Bucket(3 /* PHISHING */, 1))); LoginReputationClientResponse* actual_response = password_protection_service_->latest_response(); EXPECT_EQ(expected_response.verdict_type(), actual_response->verdict_type()); @@ -545,8 +552,8 @@ TEST_F(PasswordProtectionServiceTest, TestTearDownWithPendingRequests) { histograms_.ExpectTotalCount(kPasswordOnFocusRequestOutcomeHistogramName, 0); GURL target_url(kTargetUrl); - EXPECT_CALL(*database_manager_.get(), MatchCsdWhitelistUrl(target_url)) - .WillRepeatedly(testing::Return(false)); + EXPECT_CALL(*database_manager_.get(), CheckCsdWhitelistUrl(target_url, _)) + .WillRepeatedly(Return(AsyncMatch::NO_MATCH)); password_protection_service_->StartRequest( nullptr, target_url, GURL("http://foo.com/submit"), GURL("http://foo.com/frame"), std::string(), @@ -558,7 +565,7 @@ EXPECT_THAT( histograms_.GetAllSamples(kPasswordOnFocusRequestOutcomeHistogramName), - testing::ElementsAre(base::Bucket(2 /* CANCELED */, 1))); + ElementsAre(base::Bucket(2 /* CANCELED */, 1))); } TEST_F(PasswordProtectionServiceTest, TestCleanUpExpiredVerdict) {
diff --git a/components/safe_browsing_db/BUILD.gn b/components/safe_browsing_db/BUILD.gn index 5eeacf1..28fd0e30 100644 --- a/components/safe_browsing_db/BUILD.gn +++ b/components/safe_browsing_db/BUILD.gn
@@ -72,6 +72,10 @@ "//net", "//url", ] + + public_deps = [ + ":safebrowsing_proto", + ] } static_library("hit_report") { @@ -406,6 +410,7 @@ "util_unittest.cc", "v4_get_hash_protocol_manager_unittest.cc", "v4_protocol_manager_util_unittest.cc", + "whitelist_checker_client_unittest.cc", ] deps = [ ":database_manager", @@ -416,6 +421,7 @@ ":v4_get_hash_protocol_manager", ":v4_protocol_manager_util", ":v4_test_util", + ":whitelist_checker_client", "//base", "//content/public/browser", "//content/test:test_support", @@ -489,3 +495,30 @@ cflags = [ "/wd4267" ] # Conversion from size_t to 'type'. } } + +static_library("whitelist_checker_client") { + sources = [ + "whitelist_checker_client.cc", + "whitelist_checker_client.h", + ] + deps = [ + ":database_manager", + "//base:base", + ] +} + +source_set("whitelist_checker_client_unittest") { + testonly = true + sources = [ + "whitelist_checker_client_unittest.cc", + ] + deps = [ + ":database_manager", + ":test_database_manager", + ":whitelist_checker_client", + "//base:base", + "//base/test:test_support", + "//testing/gmock:gmock", + "//testing/gtest:gtest", + ] +}
diff --git a/components/safe_browsing_db/whitelist_checker_client.cc b/components/safe_browsing_db/whitelist_checker_client.cc new file mode 100644 index 0000000..2e6464bd --- /dev/null +++ b/components/safe_browsing_db/whitelist_checker_client.cc
@@ -0,0 +1,64 @@ +// 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/safe_browsing_db/whitelist_checker_client.h" + +#include "base/bind.h" + +namespace safe_browsing { + +// Static +void WhitelistCheckerClient::StartCheckCsdWhitelist( + scoped_refptr<SafeBrowsingDatabaseManager> database_manager, + const GURL& url, + base::Callback<void(bool)> callback_for_result) { + // TODO(nparker): Maybe also call SafeBrowsingDatabaseManager::CanCheckUrl() + if (!url.is_valid()) { + callback_for_result.Run(true /* is_whitelisted */); + return; + } + + // Make a client for each request. The caller could have several in + // flight at once. + std::unique_ptr<WhitelistCheckerClient> client = + base::MakeUnique<WhitelistCheckerClient>(callback_for_result); + AsyncMatch match = database_manager->CheckCsdWhitelistUrl(url, client.get()); + + switch (match) { + case AsyncMatch::MATCH: + callback_for_result.Run(true /* is_whitelisted */); + break; + case AsyncMatch::NO_MATCH: + callback_for_result.Run(false /* is_whitelisted */); + break; + case AsyncMatch::ASYNC: + // Client is now self-owned. When it gets called back with the result, + // it will delete itself. + client.release(); + break; + } +} + +WhitelistCheckerClient::WhitelistCheckerClient( + base::Callback<void(bool)> callback_for_result) + : callback_for_result_(callback_for_result), weak_factory_(this) { + // Set a timer to fail open, i.e. call it "whitelisted", if the full + // check takes too long. + auto timeout_callback = + base::Bind(&WhitelistCheckerClient::OnCheckWhitelistUrlResult, + weak_factory_.GetWeakPtr(), true /* is_whitelisted */); + timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kTimeoutMsec), + timeout_callback); +} + +WhitelistCheckerClient::~WhitelistCheckerClient() {} + +// SafeBrowsingDatabaseMananger::Client impl +void WhitelistCheckerClient::OnCheckWhitelistUrlResult(bool is_whitelisted) { + // This method is invoked only if we're already self-owned. + callback_for_result_.Run(is_whitelisted); + delete this; +} + +} // namespace safe_browsing
diff --git a/components/safe_browsing_db/whitelist_checker_client.h b/components/safe_browsing_db/whitelist_checker_client.h new file mode 100644 index 0000000..40bd669 --- /dev/null +++ b/components/safe_browsing_db/whitelist_checker_client.h
@@ -0,0 +1,49 @@ +// 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_SAFE_BROWSING_DB_WHITELIST_CHECKER_CLIENT_H_ +#define COMPONENTS_SAFE_BROWSING_DB_WHITELIST_CHECKER_CLIENT_H_ + +#include "base/memory/ptr_util.h" +#include "base/memory/weak_ptr.h" +#include "base/timer/timer.h" +#include "components/safe_browsing_db/database_manager.h" + +namespace safe_browsing { + +// This provides a simpler interface to +// SafeBrowsingDatabaseManager::CheckCsdWhitelistUrl() for callers that +// don't want to track their own clients. + +class WhitelistCheckerClient : public SafeBrowsingDatabaseManager::Client { + public: + using BoolCallback = base::Callback<void(bool /* is_whitelisted */)>; + + // Static method to instantiate and start a check. The callback will + // be invoked when it's done, times out, or if database_manager gets + // shut down. Must be called on IO thread. + static void StartCheckCsdWhitelist( + scoped_refptr<SafeBrowsingDatabaseManager> database_manager, + const GURL& url, + BoolCallback callback_for_result); + + WhitelistCheckerClient(BoolCallback callback_for_result); + ~WhitelistCheckerClient() override; + + // SafeBrowsingDatabaseMananger::Client impl + void OnCheckWhitelistUrlResult(bool is_whitelisted) override; + + protected: + static const int kTimeoutMsec = 5000; + base::OneShotTimer timer_; + BoolCallback callback_for_result_; + base::WeakPtrFactory<WhitelistCheckerClient> weak_factory_; + + private: + WhitelistCheckerClient(); +}; + +} // namespace safe_browsing + +#endif // COMPONENTS_SAFE_BROWSING_DB_WHITELIST_CHECKER_CLIENT_H_
diff --git a/components/safe_browsing_db/whitelist_checker_client_unittest.cc b/components/safe_browsing_db/whitelist_checker_client_unittest.cc new file mode 100644 index 0000000..8835a96c --- /dev/null +++ b/components/safe_browsing_db/whitelist_checker_client_unittest.cc
@@ -0,0 +1,116 @@ +// 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/safe_browsing_db/whitelist_checker_client.h" + +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/test/mock_callback.h" +#include "base/test/test_mock_time_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/safe_browsing_db/test_database_manager.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace safe_browsing { + +using base::TimeDelta; +using testing::_; +using testing::Return; +using testing::SaveArg; + +using BoolCallback = base::Callback<void(bool /* is_whitelisted */)>; +using MockBoolCallback = testing::StrictMock<base::MockCallback<BoolCallback>>; + +class MockSafeBrowsingDatabaseManager : public TestSafeBrowsingDatabaseManager { + public: + MockSafeBrowsingDatabaseManager(){}; + + MOCK_METHOD2(CheckCsdWhitelistUrl, + AsyncMatch(const GURL&, SafeBrowsingDatabaseManager::Client*)); + + protected: + ~MockSafeBrowsingDatabaseManager() override {} + + private: + DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingDatabaseManager); +}; + +class WhitelistCheckerClientTest : public testing::Test { + public: + WhitelistCheckerClientTest() : target_url_("http://foo.bar"){}; + + void SetUp() override { + database_manager_ = new MockSafeBrowsingDatabaseManager; + task_runner_ = new base::TestMockTimeTaskRunner(base::Time::Now(), + base::TimeTicks::Now()); + message_loop_.reset(new base::MessageLoop); + message_loop_->SetTaskRunner(task_runner_); + } + + void TearDown() override { + // Verify no callback is remaining. + // TODO(nparker): We should somehow EXPECT that no entry is remaining, + // rather than just invoking it. + task_runner_->FastForwardUntilNoTasksRemain(); + } + + protected: + GURL target_url_; + scoped_refptr<MockSafeBrowsingDatabaseManager> database_manager_; + + std::unique_ptr<base::MessageLoop> message_loop_; + scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; +}; + +TEST_F(WhitelistCheckerClientTest, TestMatch) { + EXPECT_CALL(*database_manager_.get(), CheckCsdWhitelistUrl(target_url_, _)) + .WillOnce(Return(AsyncMatch::MATCH)); + + MockBoolCallback callback; + EXPECT_CALL(callback, Run(true /* is_whitelisted */)); + WhitelistCheckerClient::StartCheckCsdWhitelist(database_manager_, target_url_, + callback.Get()); +} + +TEST_F(WhitelistCheckerClientTest, TestNoMatch) { + EXPECT_CALL(*database_manager_.get(), CheckCsdWhitelistUrl(target_url_, _)) + .WillOnce(Return(AsyncMatch::NO_MATCH)); + + MockBoolCallback callback; + EXPECT_CALL(callback, Run(false /* is_whitelisted */)); + WhitelistCheckerClient::StartCheckCsdWhitelist(database_manager_, target_url_, + callback.Get()); +} + +TEST_F(WhitelistCheckerClientTest, TestAsyncNoMatch) { + SafeBrowsingDatabaseManager::Client* client; + EXPECT_CALL(*database_manager_.get(), CheckCsdWhitelistUrl(target_url_, _)) + .WillOnce(DoAll(SaveArg<1>(&client), Return(AsyncMatch::ASYNC))); + + MockBoolCallback callback; + WhitelistCheckerClient::StartCheckCsdWhitelist(database_manager_, target_url_, + callback.Get()); + // Callback should not be called yet. + + EXPECT_CALL(callback, Run(false /* is_whitelisted */)); + // The self-owned client deletes itself here. + client->OnCheckWhitelistUrlResult(false); +} + +TEST_F(WhitelistCheckerClientTest, TestAsyncTimeout) { + EXPECT_CALL(*database_manager_.get(), CheckCsdWhitelistUrl(target_url_, _)) + .WillOnce(Return(AsyncMatch::ASYNC)); + + MockBoolCallback callback; + WhitelistCheckerClient::StartCheckCsdWhitelist(database_manager_, target_url_, + callback.Get()); + task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1)); + // No callback yet. + + EXPECT_CALL(callback, Run(true /* is_whitelisted */)); + task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(5)); +} + +} // namespace safe_browsing
diff --git a/components/search_engines/template_url_service.h b/components/search_engines/template_url_service.h index 058b0a0..884c582 100644 --- a/components/search_engines/template_url_service.h +++ b/components/search_engines/template_url_service.h
@@ -257,7 +257,9 @@ // Returns the default search provider. If the TemplateURLService hasn't been // loaded, the default search provider is pulled from preferences. // - // NOTE: At least in unittest mode, this may return NULL. + // NOTE: This may return null in certain circumstances such as: + // 1.) Unit test mode + // 2.) The default search engine is disabled by policy. const TemplateURL* GetDefaultSearchProvider() const; // Returns true if the |url| is a search results page from the default search
diff --git a/components/subresource_filter/content/browser/async_document_subresource_filter.cc b/components/subresource_filter/content/browser/async_document_subresource_filter.cc index 0ed9d1c..3b0b7cc 100644 --- a/components/subresource_filter/content/browser/async_document_subresource_filter.cc +++ b/components/subresource_filter/content/browser/async_document_subresource_filter.cc
@@ -27,6 +27,12 @@ "SubresourceFilter.DocumentLoad.Activation.WallDuration"); SCOPED_UMA_HISTOGRAM_MICRO_THREAD_TIMER( "SubresourceFilter.DocumentLoad.Activation.CPUDuration"); + if (parent_document_origin.unique()) { + SCOPED_UMA_HISTOGRAM_MICRO_TIMER( + "SubresourceFilter.PageLoad.Activation.WallDuration"); + SCOPED_UMA_HISTOGRAM_MICRO_THREAD_TIMER( + "SubresourceFilter.PageLoad.Activation.CPUDuration"); + } IndexedRulesetMatcher matcher(ruleset->data(), ruleset->length()); ActivationState activation_state = parent_activation_state;
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc index 6c1cff4..a61a90d 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc +++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h" @@ -130,6 +131,10 @@ kActivationConsoleMessage); } } + ActivationLevel level = filter ? filter->activation_state().activation_level + : ActivationLevel::DISABLED; + UMA_HISTOGRAM_ENUMERATION("SubresourceFilter.PageLoad.ActivationState", + level, ActivationLevel::LAST); } // Make sure |activated_frame_hosts_| is updated or cleaned up depending on
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc index fbd140e..fc7b8e4 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc +++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
@@ -14,6 +14,7 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" +#include "base/test/histogram_tester.h" #include "base/test/test_simple_task_runner.h" #include "components/subresource_filter/content/browser/async_document_subresource_filter.h" #include "components/subresource_filter/content/browser/subresource_filter_observer_manager.h" @@ -676,6 +677,37 @@ EXPECT_EQ(0, disallowed_notification_count()); } +TEST_F(ContentSubresourceFilterThrottleManagerTest, LogActivation) { + base::HistogramTester tester; + NavigateAndCommitMainFrame(GURL(kTestURLWithActivation)); + const char kActivationStateHistogram[] = + "SubresourceFilter.PageLoad.ActivationState"; + tester.ExpectBucketCount(kActivationStateHistogram, + static_cast<int>(ActivationLevel::ENABLED), 1); + + NavigateAndCommitMainFrame(GURL(kTestURLWithDryRun)); + tester.ExpectBucketCount(kActivationStateHistogram, + static_cast<int>(ActivationLevel::DRYRUN), 1); + + NavigateAndCommitMainFrame(GURL(kTestURLWithNoActivation)); + tester.ExpectBucketCount(kActivationStateHistogram, + static_cast<int>(ActivationLevel::DISABLED), 1); + + // Navigate a subframe that is not filtered, but should still activate. + CreateSubframeWithTestNavigation(GURL("https://whitelist.com"), main_rfh()); + SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED); + content::RenderFrameHost* subframe1 = + SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED); + ExpectActivationSignalForFrame(subframe1, true /* expect_activation */); + + tester.ExpectTotalCount(kActivationStateHistogram, 3); + // Only those with page level activation do ruleset lookups. + tester.ExpectTotalCount("SubresourceFilter.PageLoad.Activation.WallDuration", + 2); + tester.ExpectTotalCount("SubresourceFilter.PageLoad.Activation.CPUDuration", + 2); +} + // TODO(csharrison): Make sure the following conditions are exercised in tests: // // - Synchronous navigations to about:blank. These hit issues with the
diff --git a/content/browser/devtools/protocol/storage_handler.cc b/content/browser/devtools/protocol/storage_handler.cc index 1d2ecba..ccaaa90 100644 --- a/content/browser/devtools/protocol/storage_handler.cc +++ b/content/browser/devtools/protocol/storage_handler.cc
@@ -4,14 +4,16 @@ #include "content/browser/devtools/protocol/storage_handler.h" -#include <string> #include <unordered_set> +#include <utility> #include <vector> #include "base/strings/string_split.h" #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" +#include "storage/browser/quota/quota_manager.h" +#include "storage/common/quota/quota_status_code.h" namespace content { namespace protocol { @@ -27,8 +29,44 @@ static const char kServiceWorkers[] = "service_workers"; static const char kCacheStorage[] = "cache_storage"; static const char kAll[] = "all"; + +void ReportUsageAndQuotaDataOnUIThread( + std::unique_ptr<StorageHandler::GetUsageAndQuotaCallback> callback, + storage::QuotaStatusCode code, + int64_t usage, + int64_t quota) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (code != storage::kQuotaStatusOk) { + return callback->sendFailure( + Response::Error("Quota information is not available")); + } + callback->sendSuccess(usage, quota); } +void GotUsageAndQuotaDataCallback( + std::unique_ptr<StorageHandler::GetUsageAndQuotaCallback> callback, + storage::QuotaStatusCode code, + int64_t usage, + int64_t quota) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(ReportUsageAndQuotaDataOnUIThread, + base::Passed(std::move(callback)), code, usage, quota)); +} + +void GetUsageAndQuotaOnIOThread( + storage::QuotaManager* manager, + const GURL& url, + std::unique_ptr<StorageHandler::GetUsageAndQuotaCallback> callback) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + manager->GetUsageAndQuotaForWebApps( + url, storage::kStorageTypeTemporary, + base::Bind(&GotUsageAndQuotaDataCallback, + base::Passed(std::move(callback)))); +} +} // namespace + StorageHandler::StorageHandler() : DevToolsDomainHandler(Storage::Metainfo::domainName), host_(nullptr) { @@ -88,5 +126,25 @@ return Response::OK(); } +void StorageHandler::GetUsageAndQuota( + const String& origin, + std::unique_ptr<GetUsageAndQuotaCallback> callback) { + if (!host_) + return callback->sendFailure(Response::InternalError()); + + GURL origin_url(origin); + if (!origin_url.is_valid()) { + return callback->sendFailure( + Response::Error(origin + " is not a valid URL")); + } + + storage::QuotaManager* manager = + host_->GetProcess()->GetStoragePartition()->GetQuotaManager(); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&GetUsageAndQuotaOnIOThread, manager, origin_url, + base::Passed(std::move(callback)))); +} + } // namespace protocol } // namespace content
diff --git a/content/browser/devtools/protocol/storage_handler.h b/content/browser/devtools/protocol/storage_handler.h index b5c9db6..23731d2 100644 --- a/content/browser/devtools/protocol/storage_handler.h +++ b/content/browser/devtools/protocol/storage_handler.h
@@ -5,6 +5,9 @@ #ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_STORAGE_HANDLER_H_ #define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_STORAGE_HANDLER_H_ +#include <memory> +#include <string> + #include "base/macros.h" #include "content/browser/devtools/protocol/devtools_domain_handler.h" #include "content/browser/devtools/protocol/storage.h" @@ -27,6 +30,9 @@ Response ClearDataForOrigin( const std::string& origin, const std::string& storage_types) override; + void GetUsageAndQuota( + const String& origin, + std::unique_ptr<GetUsageAndQuotaCallback> callback) override; private: RenderFrameHostImpl* host_;
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json index 2b3209c2..5d58560 100644 --- a/content/browser/devtools/protocol_config.json +++ b/content/browser/devtools/protocol_config.json
@@ -67,7 +67,8 @@ "domain": "ServiceWorker" }, { - "domain": "Storage" + "domain": "Storage", + "async": ["getUsageAndQuota"] }, { "domain": "SystemInfo",
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 58e04bd..1b862ad 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -133,7 +133,6 @@ #if defined(OS_WIN) switches::kEnableAcceleratedVpxDecode, #endif - switches::kEnableColorCorrectRendering, switches::kEnableGpuRasterization, switches::kEnableHeapProfiling, switches::kEnableLogging,
diff --git a/content/browser/loader/navigation_url_loader_network_service.cc b/content/browser/loader/navigation_url_loader_network_service.cc index 8947d37..df66bde 100644 --- a/content/browser/loader/navigation_url_loader_network_service.cc +++ b/content/browser/loader/navigation_url_loader_network_service.cc
@@ -26,8 +26,11 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/webui/url_data_manager_backend.h" #include "content/browser/webui/web_ui_url_loader_factory.h" +#include "content/common/throttling_url_loader.h" +#include "content/common/url_loader_factory.mojom.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/content_browser_client.h" #include "content/public/browser/global_request_id.h" #include "content/public/browser/navigation_data.h" #include "content/public/browser/navigation_ui_data.h" @@ -35,10 +38,10 @@ #include "content/public/browser/stream_handle.h" #include "content/public/common/referrer.h" #include "content/public/common/url_constants.h" -#include "mojo/public/cpp/bindings/strong_binding.h" #include "net/base/load_flags.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request_context.h" +#include "services/service_manager/public/cpp/connector.h" namespace content { @@ -58,43 +61,6 @@ return WebContentsImpl::FromFrameTreeNode(frame_tree_node); } -class AssociatedURLLoaderWrapper final : public mojom::URLLoader { - public: - static void CreateLoaderAndStart( - mojom::URLLoaderFactory* factory, - mojom::URLLoaderRequest request, - uint32_t options, - const ResourceRequest& resource_request, - mojom::URLLoaderClientPtr client, - const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { - mojom::URLLoaderAssociatedPtr associated_ptr; - mojom::URLLoaderAssociatedRequest associated_request = - mojo::MakeRequest(&associated_ptr); - factory->CreateLoaderAndStart( - std::move(associated_request), 0 /* routing_id */, 0 /* request_id */, - options, resource_request, std::move(client), traffic_annotation); - mojo::MakeStrongBinding( - base::MakeUnique<AssociatedURLLoaderWrapper>(std::move(associated_ptr)), - std::move(request)); - } - - explicit AssociatedURLLoaderWrapper( - mojom::URLLoaderAssociatedPtr associated_ptr) - : associated_ptr_(std::move(associated_ptr)) {} - ~AssociatedURLLoaderWrapper() override {} - - void FollowRedirect() override { associated_ptr_->FollowRedirect(); } - - void SetPriority(net::RequestPriority priority, - int intra_priority_value) override { - associated_ptr_->SetPriority(priority, intra_priority_value); - } - - private: - mojom::URLLoaderAssociatedPtr associated_ptr_; - DISALLOW_COPY_AND_ASSIGN(AssociatedURLLoaderWrapper); -}; - } // namespace // Kept around during the lifetime of the navigation request, and is @@ -103,17 +69,20 @@ // of URLLoaderRequestHandler's and successively calls MaybeCreateLoader // on each until the request is successfully handled. The same sequence // may be performed multiple times when redirects happen. -class NavigationURLLoaderNetworkService::URLLoaderRequestController { +class NavigationURLLoaderNetworkService::URLLoaderRequestController + : public mojom::URLLoaderClient { public: URLLoaderRequestController( std::unique_ptr<ResourceRequest> resource_request, ResourceContext* resource_context, - scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter) + scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter, + const base::WeakPtr<NavigationURLLoaderNetworkService>& owner) : resource_request_(std::move(resource_request)), resource_context_(resource_context), - url_loader_factory_getter_(url_loader_factory_getter) {} + url_loader_factory_getter_(url_loader_factory_getter), + owner_(owner) {} - virtual ~URLLoaderRequestController() { + ~URLLoaderRequestController() override { DCHECK_CURRENTLY_ON(BrowserThread::IO); } @@ -123,11 +92,9 @@ std::unique_ptr<NavigationRequestInfo> request_info, mojom::URLLoaderFactoryPtrInfo factory_for_webui, const base::Callback<WebContents*(void)>& web_contents_getter, - mojom::URLLoaderRequest url_loader_request, - mojom::URLLoaderClientPtrInfo url_loader_client_ptr_info, std::unique_ptr<service_manager::Connector> connector) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - url_loader_client_ptr_.Bind(std::move(url_loader_client_ptr_info)); + web_contents_getter_ = web_contents_getter; const ResourceType resource_type = request_info->is_main_frame ? RESOURCE_TYPE_MAIN_FRAME : RESOURCE_TYPE_SUB_FRAME; @@ -140,12 +107,13 @@ // Requests to WebUI scheme won't get redirected to/from other schemes // or be intercepted, so we just let it go here. if (factory_for_webui.is_valid()) { - mojom::URLLoaderFactoryPtr factory_ptr; - factory_ptr.Bind(std::move(factory_for_webui)); - AssociatedURLLoaderWrapper::CreateLoaderAndStart( - factory_ptr.get(), std::move(url_loader_request), - mojom::kURLLoadOptionSendSSLInfo, *resource_request_, - std::move(url_loader_client_ptr_), + webui_factory_ptr_.Bind(std::move(factory_for_webui)); + url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( + webui_factory_ptr_.get(), + GetContentClient()->browser()->CreateURLLoaderThrottles( + web_contents_getter_), + 0 /* routing_id? */, 0 /* request_id? */, + mojom::kURLLoadOptionSendSSLInfo, *resource_request_, this, net::MutableNetworkTrafficAnnotationTag(NO_TRAFFIC_ANNOTATION_YET)); return; } @@ -178,25 +146,22 @@ handlers_.push_back(std::move(appcache_handler)); } - Restart(std::move(url_loader_request), std::move(url_loader_client_ptr_)); + Restart(); } // This could be called multiple times. - void Restart(mojom::URLLoaderRequest url_loader_request, - mojom::URLLoaderClientPtr url_loader_client_ptr) { - url_loader_request_ = std::move(url_loader_request); - url_loader_client_ptr_ = std::move(url_loader_client_ptr); + void Restart() { handler_index_ = 0; MaybeStartLoader(StartLoaderCallback()); } void MaybeStartLoader(StartLoaderCallback start_loader_callback) { - DCHECK(url_loader_client_ptr_.is_bound()); - if (start_loader_callback) { - std::move(start_loader_callback) - .Run(std::move(url_loader_request_), - std::move(url_loader_client_ptr_)); + url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( + std::move(start_loader_callback), + GetContentClient()->browser()->CreateURLLoaderThrottles( + web_contents_getter_), + *resource_request_, this); return; } @@ -215,25 +180,84 @@ } else { factory = url_loader_factory_getter_->GetNetworkFactory()->get(); } - AssociatedURLLoaderWrapper::CreateLoaderAndStart( - factory, std::move(url_loader_request_), - mojom::kURLLoadOptionSendSSLInfo, *resource_request_, - std::move(url_loader_client_ptr_), + url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( + factory, + GetContentClient()->browser()->CreateURLLoaderThrottles( + web_contents_getter_), + 0 /* routing_id? */, 0 /* request_id? */, + mojom::kURLLoadOptionSendSSLInfo, *resource_request_, this, net::MutableNetworkTrafficAnnotationTag(NO_TRAFFIC_ANNOTATION_YET)); } + void FollowRedirect() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(url_loader_); + + url_loader_->FollowRedirect(); + } + private: + // mojom::URLLoaderClient implementation: + void OnReceiveResponse( + const ResourceResponseHead& head, + const base::Optional<net::SSLInfo>& ssl_info, + mojom::DownloadedTempFilePtr downloaded_file) override { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&NavigationURLLoaderNetworkService::OnReceiveResponse, + owner_, head, ssl_info, base::Passed(&downloaded_file))); + } + + void OnReceiveRedirect(const net::RedirectInfo& redirect_info, + const ResourceResponseHead& head) override { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&NavigationURLLoaderNetworkService::OnReceiveRedirect, + owner_, redirect_info, head)); + } + + void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {} + + void OnUploadProgress(int64_t current_position, + int64_t total_size, + OnUploadProgressCallback callback) override {} + + void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {} + + void OnTransferSizeUpdated(int32_t transfer_size_diff) override {} + + void OnStartLoadingResponseBody( + mojo::ScopedDataPipeConsumerHandle body) override { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind( + &NavigationURLLoaderNetworkService::OnStartLoadingResponseBody, + owner_, base::Passed(&body))); + } + + void OnComplete( + const ResourceRequestCompletionStatus& completion_status) override { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&NavigationURLLoaderNetworkService::OnComplete, owner_, + completion_status)); + } + std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_; size_t handler_index_ = 0; std::unique_ptr<ResourceRequest> resource_request_; ResourceContext* resource_context_; + base::Callback<WebContents*()> web_contents_getter_; scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_; - // Kept around until we create a loader. - mojom::URLLoaderRequest url_loader_request_; - mojom::URLLoaderClientPtr url_loader_client_ptr_; + mojom::URLLoaderFactoryPtr webui_factory_ptr_; + + std::unique_ptr<ThrottlingURLLoader> url_loader_; + + // This is referenced only on the UI thread. + base::WeakPtr<NavigationURLLoaderNetworkService> owner_; DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController); }; @@ -246,7 +270,7 @@ ServiceWorkerNavigationHandle* service_worker_navigation_handle, AppCacheNavigationHandle* appcache_handle, NavigationURLLoaderDelegate* delegate) - : delegate_(delegate), binding_(this) { + : delegate_(delegate), weak_factory_(this) { DCHECK_CURRENTLY_ON(BrowserThread::UI); TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( @@ -286,10 +310,6 @@ int frame_tree_node_id = request_info->frame_tree_node_id; - mojom::URLLoaderRequest loader_request = mojo::MakeRequest(&url_loader_ptr_); - mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass; - binding_.Bind(mojo::MakeRequest(&url_loader_client_ptr_to_pass)); - // Check if a web UI scheme wants to handle this request. mojom::URLLoaderFactoryPtrInfo factory_for_webui; const auto& schemes = URLDataManagerBackend::GetWebUISchemes(); @@ -306,7 +326,8 @@ request_controller_ = base::MakeUnique<URLLoaderRequestController>( std::move(new_request), resource_context, static_cast<StoragePartitionImpl*>(storage_partition) - ->url_loader_factory_getter()); + ->url_loader_factory_getter(), + weak_factory_.GetWeakPtr()); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind( @@ -319,8 +340,6 @@ base::Passed(std::move(request_info)), base::Passed(std::move(factory_for_webui)), base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id), - base::Passed(std::move(loader_request)), - base::Passed(url_loader_client_ptr_to_pass.PassInterface()), base::Passed(ServiceManagerConnection::GetForProcess() ->GetConnector() ->Clone()))); @@ -332,7 +351,10 @@ } void NavigationURLLoaderNetworkService::FollowRedirect() { - url_loader_ptr_->FollowRedirect(); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&URLLoaderRequestController::FollowRedirect, + base::Unretained(request_controller_.get()))); } void NavigationURLLoaderNetworkService::ProceedWithResponse() {} @@ -361,21 +383,6 @@ delegate_->OnRequestRedirected(redirect_info, response); } -void NavigationURLLoaderNetworkService::OnDataDownloaded( - int64_t data_length, - int64_t encoded_length) {} - -void NavigationURLLoaderNetworkService::OnUploadProgress( - int64_t current_position, - int64_t total_size, - OnUploadProgressCallback callback) {} - -void NavigationURLLoaderNetworkService::OnReceiveCachedMetadata( - const std::vector<uint8_t>& data) {} - -void NavigationURLLoaderNetworkService::OnTransferSizeUpdated( - int32_t transfer_size_diff) {} - void NavigationURLLoaderNetworkService::OnStartLoadingResponseBody( mojo::ScopedDataPipeConsumerHandle body) { DCHECK(response_);
diff --git a/content/browser/loader/navigation_url_loader_network_service.h b/content/browser/loader/navigation_url_loader_network_service.h index 204e4f4..6e57f8f 100644 --- a/content/browser/loader/navigation_url_loader_network_service.h +++ b/content/browser/loader/navigation_url_loader_network_service.h
@@ -6,12 +6,10 @@ #define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_NETWORK_SERVICE_H_ #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "content/browser/loader/navigation_url_loader.h" #include "content/common/url_loader.mojom.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/browser/ssl_status.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "services/service_manager/public/cpp/connector.h" namespace net { struct RedirectInfo; @@ -24,8 +22,7 @@ // This is an implementation of NavigationURLLoader used when // --enable-network-service is used. -class NavigationURLLoaderNetworkService : public NavigationURLLoader, - public mojom::URLLoaderClient { +class NavigationURLLoaderNetworkService : public NavigationURLLoader { public: // The caller is responsible for ensuring that |delegate| outlives the loader. NavigationURLLoaderNetworkService( @@ -42,36 +39,27 @@ void FollowRedirect() override; void ProceedWithResponse() override; - // mojom::URLLoaderClient implementation: void OnReceiveResponse(const ResourceResponseHead& head, const base::Optional<net::SSLInfo>& ssl_info, - mojom::DownloadedTempFilePtr downloaded_file) override; + mojom::DownloadedTempFilePtr downloaded_file); void OnReceiveRedirect(const net::RedirectInfo& redirect_info, - const ResourceResponseHead& head) override; - void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override; - void OnUploadProgress(int64_t current_position, - int64_t total_size, - OnUploadProgressCallback callback) override; - void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override; - void OnTransferSizeUpdated(int32_t transfer_size_diff) override; - void OnStartLoadingResponseBody( - mojo::ScopedDataPipeConsumerHandle body) override; - void OnComplete( - const ResourceRequestCompletionStatus& completion_status) override; + const ResourceResponseHead& head); + void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle body); + void OnComplete(const ResourceRequestCompletionStatus& completion_status); private: class URLLoaderRequestController; NavigationURLLoaderDelegate* delegate_; - mojo::Binding<mojom::URLLoaderClient> binding_; - mojom::URLLoaderPtr url_loader_ptr_; scoped_refptr<ResourceResponse> response_; SSLStatus ssl_status_; // Lives on the IO thread. std::unique_ptr<URLLoaderRequestController> request_controller_; + base::WeakPtrFactory<NavigationURLLoaderNetworkService> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(NavigationURLLoaderNetworkService); };
diff --git a/content/browser/media/media_internals.cc b/content/browser/media/media_internals.cc index 61d5aea..e1e43dd 100644 --- a/content/browser/media/media_internals.cc +++ b/content/browser/media/media_internals.cc
@@ -962,28 +962,26 @@ const media::MediaLogEvent& event) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - // Do not save instantaneous events that happen frequently and have little - // value in the future. - if (event.type == media::MediaLogEvent::NETWORK_ACTIVITY_SET || - event.type == media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED) { - return; - } +// Save the event and limit the total number per renderer. At the time of +// writing, 512 events of the kind: { "property": value } together consume +// ~88kb of memory on linux. +#if defined(OS_ANDROID) + const size_t kEventLimit = 128; +#else + const size_t kEventLimit = 512; +#endif - // Save the event and limit the total number per renderer. At the time of - // writing, 512 events of the kind: { "property": value } together consume - // ~88kb of memory on linux. - std::list<media::MediaLogEvent>& saved_events = - saved_events_by_process_[process_id]; + auto& saved_events = saved_events_by_process_[process_id]; saved_events.push_back(event); - if (saved_events.size() > 512) { + if (saved_events.size() > kEventLimit) { // Remove all events for a given player as soon as we have to remove a // single event for that player to avoid showing incomplete players. - int id_to_remove = saved_events.front().id; - auto new_end = std::remove_if(saved_events.begin(), saved_events.end(), - [&](const media::MediaLogEvent& event) { - return event.id == id_to_remove; - }); - saved_events.erase(new_end, saved_events.end()); + const int id_to_remove = saved_events.front().id; + saved_events.erase(std::remove_if(saved_events.begin(), saved_events.end(), + [&](const media::MediaLogEvent& event) { + return event.id == id_to_remove; + }), + saved_events.end()); } }
diff --git a/content/browser/media/media_internals_proxy.cc b/content/browser/media/media_internals_proxy.cc index f180589a..5b62036 100644 --- a/content/browser/media/media_internals_proxy.cc +++ b/content/browser/media/media_internals_proxy.cc
@@ -20,22 +20,9 @@ #include "content/public/browser/notification_types.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_ui.h" -#include "net/log/net_log_capture_mode.h" -#include "net/log/net_log_entry.h" -#include "net/log/net_log_event_type.h" namespace content { -static const int kMediaInternalsProxyEventDelayMilliseconds = 100; - -static const net::NetLogEventType kNetEventTypeFilter[] = { - net::NetLogEventType::DISK_CACHE_ENTRY_IMPL, - net::NetLogEventType::SPARSE_READ, - net::NetLogEventType::SPARSE_WRITE, - net::NetLogEventType::URL_REQUEST_START_JOB, - net::NetLogEventType::HTTP_TRANSACTION_READ_RESPONSE_HEADERS, -}; - MediaInternalsProxy::MediaInternalsProxy() { registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, NotificationService::AllBrowserContextsAndSources()); @@ -58,22 +45,13 @@ handler_ = handler; update_callback_ = base::Bind(&MediaInternalsProxy::UpdateUIOnUIThread, this); MediaInternals::GetInstance()->AddUpdateCallback(update_callback_); - - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&MediaInternalsProxy::ObserveMediaInternalsOnIOThread, this)); } void MediaInternalsProxy::Detach() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - handler_ = NULL; + handler_ = nullptr; MediaInternals::GetInstance()->RemoveUpdateCallback(update_callback_); - - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind( - &MediaInternalsProxy::StopObservingMediaInternalsOnIOThread, this)); } void MediaInternalsProxy::GetEverything() { @@ -85,67 +63,10 @@ BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&MediaInternalsProxy::GetEverythingOnIOThread, this)); - - // Send the page names for constants. - CallJavaScriptFunctionOnUIThread("media.onReceiveConstants", GetConstants()); -} - -void MediaInternalsProxy::OnAddEntry(const net::NetLogEntry& entry) { - bool is_event_interesting = false; - for (size_t i = 0; i < arraysize(kNetEventTypeFilter); i++) { - if (entry.type() == kNetEventTypeFilter[i]) { - is_event_interesting = true; - break; - } - } - - if (!is_event_interesting) - return; - - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&MediaInternalsProxy::AddNetEventOnUIThread, this, - base::Passed(entry.ToValue()))); } MediaInternalsProxy::~MediaInternalsProxy() {} -std::unique_ptr<base::Value> MediaInternalsProxy::GetConstants() { - auto event_phases = base::MakeUnique<base::DictionaryValue>(); - event_phases->SetInteger( - net::NetLog::EventPhaseToString(net::NetLogEventPhase::NONE), - static_cast<int>(net::NetLogEventPhase::NONE)); - event_phases->SetInteger( - net::NetLog::EventPhaseToString(net::NetLogEventPhase::BEGIN), - static_cast<int>(net::NetLogEventPhase::BEGIN)); - event_phases->SetInteger( - net::NetLog::EventPhaseToString(net::NetLogEventPhase::END), - static_cast<int>(net::NetLogEventPhase::END)); - - auto constants = base::MakeUnique<base::DictionaryValue>(); - constants->Set("eventTypes", net::NetLog::GetEventTypesAsValue()); - constants->Set("eventPhases", std::move(event_phases)); - - return std::move(constants); -} - -void MediaInternalsProxy::ObserveMediaInternalsOnIOThread() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (GetContentClient()->browser()->GetNetLog()) { - net::NetLog* net_log = GetContentClient()->browser()->GetNetLog(); - net_log->DeprecatedAddObserver( - this, net::NetLogCaptureMode::IncludeCookiesAndCredentials()); - } -} - -void MediaInternalsProxy::StopObservingMediaInternalsOnIOThread() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (GetContentClient()->browser()->GetNetLog()) { - net::NetLog* net_log = GetContentClient()->browser()->GetNetLog(); - net_log->DeprecatedRemoveObserver(this); - } -} - void MediaInternalsProxy::GetEverythingOnIOThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO); // TODO(xhwang): Investigate whether we can update on UI thread directly. @@ -160,29 +81,6 @@ handler_->OnUpdate(update); } -void MediaInternalsProxy::AddNetEventOnUIThread( - std::unique_ptr<base::Value> entry) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - // Send the updates to the page in kMediaInternalsProxyEventDelayMilliseconds - // if an update is not already pending. - if (!pending_net_updates_) { - pending_net_updates_.reset(new base::ListValue()); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&MediaInternalsProxy::SendNetEventsOnUIThread, this), - base::TimeDelta::FromMilliseconds( - kMediaInternalsProxyEventDelayMilliseconds)); - } - pending_net_updates_->Append(std::move(entry)); -} - -void MediaInternalsProxy::SendNetEventsOnUIThread() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - CallJavaScriptFunctionOnUIThread("media.onNetUpdate", - std::move(pending_net_updates_)); -} - void MediaInternalsProxy::CallJavaScriptFunctionOnUIThread( const std::string& function, std::unique_ptr<base::Value> args) {
diff --git a/content/browser/media/media_internals_proxy.h b/content/browser/media/media_internals_proxy.h index a9dbba4..47b7db4d 100644 --- a/content/browser/media/media_internals_proxy.h +++ b/content/browser/media/media_internals_proxy.h
@@ -14,12 +14,10 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" -#include "net/log/net_log.h" namespace base { -class ListValue; class Value; -} +} // namespace base namespace content { class MediaInternalsMessageHandler; @@ -29,10 +27,8 @@ // It is ref_counted to ensure that it completes all pending Tasks on both // threads before destruction. class MediaInternalsProxy - : public base::RefCountedThreadSafe< - MediaInternalsProxy, - BrowserThread::DeleteOnUIThread>, - public net::NetLog::ThreadSafeObserver, + : public base::RefCountedThreadSafe<MediaInternalsProxy, + BrowserThread::DeleteOnUIThread>, public NotificationObserver { public: MediaInternalsProxy(); @@ -51,36 +47,21 @@ // Have MediaInternals send all the data it has. void GetEverything(); - // net::NetLog::ThreadSafeObserver implementation. Callable from any thread: - void OnAddEntry(const net::NetLogEntry& entry) override; - private: friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; friend class base::DeleteHelper<MediaInternalsProxy>; ~MediaInternalsProxy() override; - // Build a dictionary mapping constant names to values. - std::unique_ptr<base::Value> GetConstants(); - - void ObserveMediaInternalsOnIOThread(); - void StopObservingMediaInternalsOnIOThread(); void GetEverythingOnIOThread(); // Callback for MediaInternals to update. Must be called on UI thread. void UpdateUIOnUIThread(const base::string16& update); - // Put |entry| on a list of events to be sent to the page. - void AddNetEventOnUIThread(std::unique_ptr<base::Value> entry); - - // Send all pending events to the page. - void SendNetEventsOnUIThread(); - // Call a JavaScript function on the page. void CallJavaScriptFunctionOnUIThread(const std::string& function, std::unique_ptr<base::Value> args); MediaInternalsMessageHandler* handler_; - std::unique_ptr<base::ListValue> pending_net_updates_; NotificationRegistrar registrar_; MediaInternals::UpdateCallback update_callback_;
diff --git a/content/browser/renderer_host/media/service_launched_video_capture_device.cc b/content/browser/renderer_host/media/service_launched_video_capture_device.cc index dc58efa..07194411 100644 --- a/content/browser/renderer_host/media/service_launched_video_capture_device.cc +++ b/content/browser/renderer_host/media/service_launched_video_capture_device.cc
@@ -24,7 +24,8 @@ void ServiceLaunchedVideoCaptureDevice::GetPhotoState( media::VideoCaptureDevice::GetPhotoStateCallback callback) const { DCHECK(sequence_checker_.CalledOnValidSequence()); - NOTIMPLEMENTED(); + // Not yet implemented on service side, but is called during + // JsLevelVideoCaptureBrowserTest. Do nothing here. } void ServiceLaunchedVideoCaptureDevice::SetPhotoOptions(
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 2c2d83dc..51cd76d4 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -695,7 +695,14 @@ std::map<ProcessID, Count>& counts_per_process = result->second; for (auto iter : counts_per_process) { RenderProcessHost* host = RenderProcessHost::FromID(iter.first); - DCHECK(host); + if (!host) { + // TODO(clamy): This shouldn't happen but we are getting reports from + // the field that this is happening. We need to figure out why some + // RenderProcessHosts are not taken out of the map when they're + // destroyed. + NOTREACHED(); + continue; + } if (host->VisibleWidgetCount()) foreground_processes->insert(host); else @@ -2149,7 +2156,6 @@ switches::kDomAutomationController, switches::kEnableBlinkFeatures, switches::kEnableBrowserSideNavigation, - switches::kEnableColorCorrectRendering, switches::kEnableDisplayList2dCanvas, switches::kEnableDistanceFieldText, switches::kEnableExperimentalCanvasFeatures,
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 2b9c1d5..006dab2 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -332,10 +332,8 @@ force_srgb_image_decode_color_space = true; // When color correct rendering is enabled, the image_decode_color_space // parameter should not be used (and all users of it should be using sRGB). - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableColorCorrectRendering)) { + if (base::FeatureList::IsEnabled(features::kColorCorrectRendering)) force_srgb_image_decode_color_space = true; - } if (force_srgb_image_decode_color_space) { gfx::ColorSpace::CreateSRGB().GetICCProfile( ¶ms->image_decode_color_space); @@ -514,7 +512,7 @@ command_line.HasSwitch(switches::kMainFrameResizesAreOrientationChanges); prefs.color_correct_rendering_enabled = - command_line.HasSwitch(switches::kEnableColorCorrectRendering); + base::FeatureList::IsEnabled(features::kColorCorrectRendering); prefs.spatial_navigation_enabled = command_line.HasSwitch( switches::kEnableSpatialNavigation);
diff --git a/content/browser/resources/media/cache_entry.js b/content/browser/resources/media/cache_entry.js deleted file mode 100644 index 2286fe03..0000000 --- a/content/browser/resources/media/cache_entry.js +++ /dev/null
@@ -1,243 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -cr.define('media', function() { - 'use strict'; - - /** - * This class represents a file cached by net. - */ - function CacheEntry() { - this.read_ = new media.DisjointRangeSet; - this.written_ = new media.DisjointRangeSet; - this.available_ = new media.DisjointRangeSet; - - // Set to true when we know the entry is sparse. - this.sparse = false; - this.key = null; - this.size = null; - - // The <details> element representing this CacheEntry. - this.details_ = document.createElement('details'); - this.details_.className = 'cache-entry'; - this.details_.open = false; - - // The <details> summary line. It contains a chart of requested file ranges - // and the url if we know it. - var summary = document.createElement('summary'); - - this.summaryText_ = document.createTextNode(''); - summary.appendChild(this.summaryText_); - - summary.appendChild(document.createTextNode(' ')); - - // Controls to modify this CacheEntry. - var controls = document.createElement('span'); - controls.className = 'cache-entry-controls'; - summary.appendChild(controls); - summary.appendChild(document.createElement('br')); - - // A link to clear recorded data from this CacheEntry. - var clearControl = document.createElement('a'); - clearControl.href = 'javascript:void(0)'; - clearControl.onclick = this.clear.bind(this); - clearControl.textContent = '(clear entry)'; - controls.appendChild(clearControl); - - this.details_.appendChild(summary); - - // The canvas for drawing cache writes. - this.writeCanvas = document.createElement('canvas'); - this.writeCanvas.width = media.BAR_WIDTH; - this.writeCanvas.height = media.BAR_HEIGHT; - this.details_.appendChild(this.writeCanvas); - - // The canvas for drawing cache reads. - this.readCanvas = document.createElement('canvas'); - this.readCanvas.width = media.BAR_WIDTH; - this.readCanvas.height = media.BAR_HEIGHT; - this.details_.appendChild(this.readCanvas); - - // A tabular representation of the data in the above canvas. - this.detailTable_ = document.createElement('table'); - this.detailTable_.className = 'cache-table'; - this.details_.appendChild(this.detailTable_); - } - - CacheEntry.prototype = { - /** - * Mark a range of bytes as read from the cache. - * @param {int} start The first byte read. - * @param {int} length The number of bytes read. - */ - readBytes: function(start, length) { - start = parseInt(start); - length = parseInt(length); - this.read_.add(start, start + length); - this.available_.add(start, start + length); - this.sparse = true; - }, - - /** - * Mark a range of bytes as written to the cache. - * @param {int} start The first byte written. - * @param {int} length The number of bytes written. - */ - writeBytes: function(start, length) { - start = parseInt(start); - length = parseInt(length); - this.written_.add(start, start + length); - this.available_.add(start, start + length); - this.sparse = true; - }, - - /** - * Merge this CacheEntry with another, merging recorded ranges and flags. - * @param {CacheEntry} other The CacheEntry to merge into this one. - */ - merge: function(other) { - this.read_.merge(other.read_); - this.written_.merge(other.written_); - this.available_.merge(other.available_); - this.sparse = this.sparse || other.sparse; - this.key = this.key || other.key; - this.size = this.size || other.size; - }, - - /** - * Clear all recorded ranges from this CacheEntry and redraw this.details_. - */ - clear: function() { - this.read_ = new media.DisjointRangeSet; - this.written_ = new media.DisjointRangeSet; - this.available_ = new media.DisjointRangeSet; - this.generateDetails(); - }, - - /** - * Helper for drawCacheReadsToCanvas() and drawCacheWritesToCanvas(). - * - * Accepts the entries to draw, a canvas fill style, and the canvas to - * draw on. - */ - drawCacheEntriesToCanvas: function(entries, fillStyle, canvas) { - // Don't bother drawing anything if we don't know the total size. - if (!this.size) { - return; - } - - var width = canvas.width; - var height = canvas.height; - var context = canvas.getContext('2d'); - var fileSize = this.size; - - context.fillStyle = '#aaa'; - context.fillRect(0, 0, width, height); - - function drawRange(start, end) { - var left = start / fileSize * width; - var right = end / fileSize * width; - context.fillRect(left, 0, right - left, height); - } - - context.fillStyle = fillStyle; - entries.map(function(start, end) { - drawRange(start, end); - }); - }, - - /** - * Draw cache writes to the given canvas. - * - * It should consist of a horizontal bar with highlighted sections to - * represent which parts of a file have been written to the cache. - * - * e.g. |xxxxxx----------x| - */ - drawCacheWritesToCanvas: function(canvas) { - this.drawCacheEntriesToCanvas(this.written_, '#00a', canvas); - }, - - /** - * Draw cache reads to the given canvas. - * - * It should consist of a horizontal bar with highlighted sections to - * represent which parts of a file have been read from the cache. - * - * e.g. |xxxxxx----------x| - */ - drawCacheReadsToCanvas: function(canvas) { - this.drawCacheEntriesToCanvas(this.read_, '#0a0', canvas); - }, - - /** - * Update this.details_ to contain everything we currently know about - * this file. - */ - generateDetails: function() { - function makeElement(tag, content) { - var toReturn = document.createElement(tag); - toReturn.textContent = content; - return toReturn; - } - - this.details_.id = this.key; - this.summaryText_.textContent = this.key || 'Unknown File'; - - this.detailTable_.textContent = ''; - var header = document.createElement('thead'); - var footer = document.createElement('tfoot'); - var body = document.createElement('tbody'); - this.detailTable_.appendChild(header); - this.detailTable_.appendChild(footer); - this.detailTable_.appendChild(body); - - var headerRow = document.createElement('tr'); - headerRow.appendChild(makeElement('th', 'Read From Cache')); - headerRow.appendChild(makeElement('th', 'Written To Cache')); - header.appendChild(headerRow); - - var footerRow = document.createElement('tr'); - var footerCell = document.createElement('td'); - footerCell.textContent = 'Out of ' + (this.size || 'unknown size'); - footerCell.setAttribute('colspan', 2); - footerRow.appendChild(footerCell); - footer.appendChild(footerRow); - - var read = this.read_.map(function(start, end) { - return start + ' - ' + end; - }); - var written = this.written_.map(function(start, end) { - return start + ' - ' + end; - }); - - var length = Math.max(read.length, written.length); - for (var i = 0; i < length; i++) { - var row = document.createElement('tr'); - row.appendChild(makeElement('td', read[i] || '')); - row.appendChild(makeElement('td', written[i] || '')); - body.appendChild(row); - } - - this.drawCacheWritesToCanvas(this.writeCanvas); - this.drawCacheReadsToCanvas(this.readCanvas); - }, - - /** - * Render this CacheEntry as a <li>. - * @return {HTMLElement} A <li> representing this CacheEntry. - */ - toListItem: function() { - this.generateDetails(); - - var result = document.createElement('li'); - result.appendChild(this.details_); - return result; - } - }; - - return { - CacheEntry: CacheEntry - }; -});
diff --git a/content/browser/resources/media/client_renderer.js b/content/browser/resources/media/client_renderer.js index adfa319a..3206ac9 100644 --- a/content/browser/resources/media/client_renderer.js +++ b/content/browser/resources/media/client_renderer.js
@@ -24,11 +24,6 @@ this.filterFunction = function() { return true; }; this.filterText = document.getElementById('filter-text'); this.filterText.onkeyup = this.onTextChange_.bind(this); - - this.bufferCanvas = document.createElement('canvas'); - this.bufferCanvas.width = media.BAR_WIDTH; - this.bufferCanvas.height = media.BAR_HEIGHT; - this.clipboardDialog = document.getElementById('clipboard-dialog'); this.clipboardTextarea = document.getElementById('clipboard-textarea'); @@ -55,7 +50,8 @@ ClientRenderer.Css_ = { NO_PLAYERS_SELECTED: 'no-players-selected', NO_COMPONENTS_SELECTED: 'no-components-selected', - SELECTABLE_BUTTON: 'selectable-button' + SELECTABLE_BUTTON: 'selectable-button', + DESTRUCTED_PLAYER: 'destructed-player' }; function removeChildren(element) { @@ -64,7 +60,8 @@ } }; - function createSelectableButton(id, groupName, text, select_cb) { + function createSelectableButton(id, groupName, text, select_cb, + isDestructed) { // For CSS styling. var radioButton = document.createElement('input'); radioButton.classList.add(ClientRenderer.Css_.SELECTABLE_BUTTON); @@ -74,6 +71,8 @@ var buttonLabel = document.createElement('label'); buttonLabel.classList.add(ClientRenderer.Css_.SELECTABLE_BUTTON); + if (isDestructed) + buttonLabel.classList.add(ClientRenderer.Css_.DESTRUCTED_PLAYER); buttonLabel.setAttribute('for', radioButton.id); buttonLabel.appendChild(document.createTextNode(text)); @@ -177,11 +176,16 @@ if (player === this.selectedPlayer) { this.drawProperties_(player.properties, this.playerPropertiesTable); this.drawLog_(); - this.drawGraphs_(); } if (key === 'name' || key === 'url') { this.redrawPlayerList_(players); } + if (key === 'event' && value === 'WEBMEDIAPLAYER_DESTROYED') { + player.destructed = true; + document.querySelector( + "label.selectable-button[for='" + player.id + "']").classList.add( + ClientRenderer.Css_.DESTRUCTED_PLAYER); + } }, createVideoCaptureFormatTable: function(formats) { @@ -351,7 +355,7 @@ var li = document.createElement('li'); var button_cb = this.selectPlayer_.bind(this, player); li.appendChild(createSelectableButton( - id, buttonGroupName, usableName, button_cb)); + id, buttonGroupName, usableName, button_cb, player.destructed)); fragment.appendChild(li); } removeChildren(this.playerListElement); @@ -378,7 +382,6 @@ removeChildren(this.logTable); removeChildren(this.graphElement); this.drawLog_(); - this.drawGraphs_(); }, drawProperties_: function(propertyMap, propertiesTable) { @@ -428,76 +431,6 @@ downloadLog(JSON.stringify(strippedPlayers, null, 2)); }, - drawGraphs_: function() { - function addToGraphs(name, graph, graphElement) { - var li = document.createElement('li'); - li.appendChild(graph); - li.appendChild(document.createTextNode(name)); - graphElement.appendChild(li); - } - - var url = this.selectedPlayer.properties.url; - if (!url) { - return; - } - - var cache = media.cacheForUrl(url); - - var player = this.selectedPlayer; - var props = player.properties; - - var cacheExists = false; - var bufferExists = false; - - if (props['buffer_start'] !== undefined && - props['buffer_current'] !== undefined && - props['buffer_end'] !== undefined && - props['total_bytes'] !== undefined) { - this.drawBufferGraph_(props['buffer_start'], - props['buffer_current'], - props['buffer_end'], - props['total_bytes']); - bufferExists = true; - } - - if (cache) { - if (player.properties['total_bytes']) { - cache.size = Number(player.properties['total_bytes']); - } - cache.generateDetails(); - cacheExists = true; - - } - - if (!this.graphElement.hasChildNodes()) { - if (bufferExists) { - addToGraphs('buffer', this.bufferCanvas, this.graphElement); - } - if (cacheExists) { - addToGraphs('cache read', cache.readCanvas, this.graphElement); - addToGraphs('cache write', cache.writeCanvas, this.graphElement); - } - } - }, - - drawBufferGraph_: function(start, current, end, size) { - var ctx = this.bufferCanvas.getContext('2d'); - var width = this.bufferCanvas.width; - var height = this.bufferCanvas.height; - ctx.fillStyle = '#aaa'; - ctx.fillRect(0, 0, width, height); - - var scale_factor = width / size; - var left = start * scale_factor; - var middle = current * scale_factor; - var right = end * scale_factor; - - ctx.fillStyle = '#a0a'; - ctx.fillRect(left, 0, middle - left, height); - ctx.fillStyle = '#aa0'; - ctx.fillRect(middle, 0, right - middle, height); - }, - showClipboard: function(string) { this.clipboardTextarea.value = string; this.clipboardDialog.showModal(); @@ -506,7 +439,8 @@ }, hideClipboard_: function() { - this.clipboardDialog.close(); + if (this.clipboardDialog.open) + this.clipboardDialog.close(); }, copyToClipboard_: function() { @@ -546,7 +480,6 @@ if (this.selectedPlayer) { removeChildren(this.logTable); this.selectedPlayerLogIndex = 0; - this.drawLog_(); } }, };
diff --git a/content/browser/resources/media/disjoint_range_set.js b/content/browser/resources/media/disjoint_range_set.js deleted file mode 100644 index bd504bb..0000000 --- a/content/browser/resources/media/disjoint_range_set.js +++ /dev/null
@@ -1,145 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -cr.define('media', function() { - - /** - * This class represents a collection of non-intersecting ranges. Ranges - * specified by (start, end) can be added and removed at will. It is used to - * record which sections of a media file have been cached, e.g. the first and - * last few kB plus several MB in the middle. - * - * Example usage: - * someRange.add(0, 100); // Contains 0-100. - * someRange.add(150, 200); // Contains 0-100, 150-200. - * someRange.remove(25, 75); // Contains 0-24, 76-100, 150-200. - * someRange.add(25, 149); // Contains 0-200. - */ - function DisjointRangeSet() { - this.ranges_ = {}; - } - - DisjointRangeSet.prototype = { - /** - * Deletes all ranges intersecting with (start ... end) and returns the - * extents of the cleared area. - * @param {int} start The start of the range to remove. - * @param {int} end The end of the range to remove. - * @param {int} sloppiness 0 removes only strictly overlapping ranges, and - * 1 removes adjacent ones. - * @return {Object} The start and end of the newly cleared range. - */ - clearRange: function(start, end, sloppiness) { - var ranges = this.ranges_; - var result = {start: start, end: end}; - - for (var rangeStart in this.ranges_) { - rangeEnd = this.ranges_[rangeStart]; - // A range intersects another if its start lies within the other range - // or vice versa. - if ((rangeStart >= start && rangeStart <= (end + sloppiness)) || - (start >= rangeStart && start <= (rangeEnd + sloppiness))) { - delete ranges[rangeStart]; - result.start = Math.min(result.start, rangeStart); - result.end = Math.max(result.end, rangeEnd); - } - } - - return result; - }, - - /** - * Adds a range to this DisjointRangeSet. - * Joins adjacent and overlapping ranges together. - * @param {int} start The beginning of the range to add, inclusive. - * @param {int} end The end of the range to add, inclusive. - */ - add: function(start, end) { - if (end < start) - return; - - // Remove all touching ranges. - result = this.clearRange(start, end, 1); - // Add back a single contiguous range. - this.ranges_[Math.min(start, result.start)] = Math.max(end, result.end); - }, - - /** - * Combines a DisjointRangeSet with this one. - * @param {DisjointRangeSet} ranges A DisjointRangeSet to be squished into - * this one. - */ - merge: function(other) { - var ranges = this; - other.forEach(function(start, end) { ranges.add(start, end); }); - }, - - /** - * Removes a range from this DisjointRangeSet. - * Will split existing ranges if necessary. - * @param {int} start The beginning of the range to remove, inclusive. - * @param {int} end The end of the range to remove, inclusive. - */ - remove: function(start, end) { - if (end < start) - return; - - // Remove instersecting ranges. - result = this.clearRange(start, end, 0); - - // Add back non-overlapping ranges. - if (result.start < start) - this.ranges_[result.start] = start - 1; - if (result.end > end) - this.ranges_[end + 1] = result.end; - }, - - /** - * Iterates over every contiguous range in this DisjointRangeSet, calling a - * function for each (start, end). - * @param {function(int, int)} iterator The function to call on each range. - */ - forEach: function(iterator) { - for (var start in this.ranges_) - iterator(start, this.ranges_[start]); - }, - - /** - * Maps this DisjointRangeSet to an array by calling a given function on the - * start and end of each contiguous range, sorted by start. - * @param {function(int, int)} mapper Maps a range to an array element. - * @return {Array} An array of each mapper(range). - */ - map: function(mapper) { - var starts = []; - for (var start in this.ranges_) - starts.push(parseInt(start)); - starts.sort(function(a, b) { - return a - b; - }); - - var ranges = this.ranges_; - var results = starts.map(function(s) { - return mapper(s, ranges[s]); - }); - - return results; - }, - - /** - * Finds the maximum value present in any of the contained ranges. - * @return {int} The maximum value contained by this DisjointRangeSet. - */ - max: function() { - var max = -Infinity; - for (var start in this.ranges_) - max = Math.max(max, this.ranges_[start]); - return max; - }, - }; - - return { - DisjointRangeSet: DisjointRangeSet - }; -});
diff --git a/content/browser/resources/media/disjoint_range_set_test.html b/content/browser/resources/media/disjoint_range_set_test.html deleted file mode 100644 index 424fc65..0000000 --- a/content/browser/resources/media/disjoint_range_set_test.html +++ /dev/null
@@ -1,96 +0,0 @@ -<!doctype html> -<html> -<!-- -Copyright (c) 2011 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - <head> - <title></title> - <script src="https://cdn.rawgit.com/google/closure-library/master/closure/goog/base.js"></script> - <script src="../../../../ui/webui/resources/js/cr.js"></script> - <script src="disjoint_range_set.js"></script> - <script> - goog.require('goog.testing.jsunit'); - </script> - </head> - <body> - <script> - - var range; - - function assertRangeEquals(ranges) { - assertArrayEquals( - ranges, range.map(function(start, end) { return [start, end]; })); - }; - - function setUp() { - range = new media.DisjointRangeSet; - }; - - function testAdd() { - range.add(1, 6); - assertRangeEquals([[1, 6]]); - range.add(-5, -3); - assertRangeEquals([[-5, -3], [1, 6]]); - }; - - function testAddAdjacent() { - range.add(3, 6); - assertRangeEquals([[3, 6]]); - range.add(1, 2); - assertRangeEquals([[1, 6]]); - range.add(7, 9); - assertRangeEquals([[1, 9]]); - }; - - function testAddNotQuiteAdjacent() { - range.add(3, 6); - assertRangeEquals([[3, 6]]); - range.add(0, 1); - assertRangeEquals([[0, 1], [3, 6]]); - range.add(8, 9); - assertRangeEquals([[0, 1], [3, 6], [8, 9]]); - }; - - function testAddOverlapping() { - range.add(1, 6); - assertRangeEquals([[1, 6]]); - range.add(5, 8); - assertRangeEquals([[1, 8]]); - range.add(0, 1); - assertRangeEquals([[0, 8]]); - }; - - function testMax() { - assertNull(range.max()); - range.add(1, 6); - assertEquals(range.max(), 6); - range.add(3, 8); - assertEquals(range.max(), 8); - range.remove(2, 3); - assertEquals(range.max(), 8); - range.remove(4, 10); - assertEquals(range.max(), 1); - range.remove(1, 1); - assertNull(range.max()); - }; - - function testRemove() { - range.add(1, 20); - assertRangeEquals([[1, 20]]); - range.remove(0, 3); - assertRangeEquals([[4, 20]]); - range.remove(18, 20); - assertRangeEquals([[4, 17]]); - range.remove(5, 16); - assertRangeEquals([[4, 4], [17, 17]]); - }; - - function testStartsEmpty() { - assertRangeEquals([]); - }; - - </script> - </body> -</html>
diff --git a/content/browser/resources/media/main.js b/content/browser/resources/media/main.js index 5ca4bed..65bbaca 100644 --- a/content/browser/resources/media/main.js +++ b/content/browser/resources/media/main.js
@@ -10,28 +10,6 @@ var manager = null; - // A number->string mapping that is populated through the backend that - // describes the phase that the network entity is in. - var eventPhases = {}; - - // A number->string mapping that is populated through the backend that - // describes the type of event sent from the network. - var eventTypes = {}; - - // A mapping of number->CacheEntry where the number is a unique id for that - // network request. - var cacheEntries = {}; - - // A mapping of url->CacheEntity where the url is the url of the resource. - var cacheEntriesByKey = {}; - - var requrestURLs = {}; - - var media = { - BAR_WIDTH: 200, - BAR_HEIGHT: 25 - }; - /** * Users of |media| must call initialize prior to calling other methods. */ @@ -49,76 +27,6 @@ manager.updateVideoCaptureCapabilities(videoCaptureCapabilities) } - media.onReceiveConstants = function(constants) { - for (var key in constants.eventTypes) { - var value = constants.eventTypes[key]; - eventTypes[value] = key; - } - - for (var key in constants.eventPhases) { - var value = constants.eventPhases[key]; - eventPhases[value] = key; - } - }; - - media.cacheForUrl = function(url) { - return cacheEntriesByKey[url]; - }; - - media.onNetUpdate = function(updates) { - updates.forEach(function(update) { - var id = update.source.id; - if (!cacheEntries[id]) - cacheEntries[id] = new media.CacheEntry; - - switch (eventPhases[update.phase] + '.' + eventTypes[update.type]) { - case 'PHASE_BEGIN.DISK_CACHE_ENTRY_IMPL': - var key = update.params.key; - - // Merge this source with anything we already know about this key. - if (cacheEntriesByKey[key]) { - cacheEntriesByKey[key].merge(cacheEntries[id]); - cacheEntries[id] = cacheEntriesByKey[key]; - } else { - cacheEntriesByKey[key] = cacheEntries[id]; - } - cacheEntriesByKey[key].key = key; - break; - - case 'PHASE_BEGIN.SPARSE_READ': - cacheEntries[id].readBytes(update.params.offset, - update.params.buff_len); - cacheEntries[id].sparse = true; - break; - - case 'PHASE_BEGIN.SPARSE_WRITE': - cacheEntries[id].writeBytes(update.params.offset, - update.params.buff_len); - cacheEntries[id].sparse = true; - break; - - case 'PHASE_BEGIN.URL_REQUEST_START_JOB': - requrestURLs[update.source.id] = update.params.url; - break; - - case 'PHASE_NONE.HTTP_TRANSACTION_READ_RESPONSE_HEADERS': - // Record the total size of the file if this was a range request. - var range = /content-range:\s*bytes\s*\d+-\d+\/(\d+)/i.exec( - update.params.headers); - var key = requrestURLs[update.source.id]; - delete requrestURLs[update.source.id]; - if (range && key) { - if (!cacheEntriesByKey[key]) { - cacheEntriesByKey[key] = new media.CacheEntry; - cacheEntriesByKey[key].key = key; - } - cacheEntriesByKey[key].size = range[1]; - } - break; - } - }); - }; - media.onRendererTerminated = function(renderId) { util.object.forEach(manager.players_, function(playerInfo, id) { if (playerInfo.properties['render_id'] == renderId) { @@ -159,18 +67,7 @@ var propertyCount = 0; util.object.forEach(event.params, function(value, key) { key = key.trim(); - - // These keys get spammed *a lot*, so put them on the display - // but don't log list. - if (key === 'buffer_start' || - key === 'buffer_end' || - key === 'buffer_current' || - key === 'is_downloading_data') { - manager.updatePlayerInfoNoRecord( - source, event.ticksMillis, key, value); - } else { - manager.updatePlayerInfo(source, event.ticksMillis, key, value); - } + manager.updatePlayerInfo(source, event.ticksMillis, key, value); propertyCount += 1; });
diff --git a/content/browser/resources/media/media_internals.css b/content/browser/resources/media/media_internals.css index 33f969d..372d2a8 100644 --- a/content/browser/resources/media/media_internals.css +++ b/content/browser/resources/media/media_internals.css
@@ -193,6 +193,10 @@ color: white; } +label.destructed-player { + background-color: #E4854A; +} + .no-players-selected #players .property-wrapper, .no-players-selected #players #log-wrapper { display: none;
diff --git a/content/browser/resources/media/media_internals.js b/content/browser/resources/media/media_internals.js index cad5797..b285a4c 100644 --- a/content/browser/resources/media/media_internals.js +++ b/content/browser/resources/media/media_internals.js
@@ -6,8 +6,6 @@ // <include src="main.js"> // <include src="util.js"> -// <include src="cache_entry.js"> -// <include src="disjoint_range_set.js"> // <include src="player_info.js"> // <include src="manager.js"> // <include src="client_renderer.js">
diff --git a/content/browser/webrtc/webrtc_video_capture_browsertest.cc b/content/browser/webrtc/webrtc_video_capture_browsertest.cc new file mode 100644 index 0000000..884551c --- /dev/null +++ b/content/browser/webrtc/webrtc_video_capture_browsertest.cc
@@ -0,0 +1,99 @@ +// 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/command_line.h" +#include "build/build_config.h" +#include "content/browser/webrtc/webrtc_webcam_browsertest.h" +#include "content/public/browser/browser_child_process_host.h" +#include "content/public/common/child_process_host.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/service_manager_connection.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/content_browser_test_utils.h" +#include "content/shell/browser/shell.h" +#include "media/base/media_switches.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/constants.h" +#include "services/video_capture/public/interfaces/constants.mojom.h" +#include "services/video_capture/public/interfaces/testing_controls.mojom.h" + +namespace content { + +#if defined(OS_ANDROID) +// Mojo video capture is currently not supported on Android +// TODO(chfremer): Enable as soon as https://crbug.com/720500 is resolved. +#define MAYBE_RecoverFromCrashInVideoCaptureProcess \ + DISABLED_RecoverFromCrashInVideoCaptureProcess +#else +#define MAYBE_RecoverFromCrashInVideoCaptureProcess \ + RecoverFromCrashInVideoCaptureProcess +#endif // defined(OS_ANDROID) + +namespace { + +static const char kVideoCaptureHtmlFile[] = "/media/video_capture_test.html"; +static const char kStartVideoCaptureAndVerifySize[] = + "startVideoCaptureAndVerifySize()"; +static const char kWaitForVideoToTurnBlack[] = "waitForVideoToTurnBlack()"; +static const char kVerifyHasReceivedTrackEndedEvent[] = + "verifyHasReceivedTrackEndedEvent()"; + +} // anonymous namespace + +// Integration test that exercises video capture functionality from the +// JavaScript level. +class WebRtcVideoCaptureBrowserTest : public ContentBrowserTest { + protected: + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); + command_line->AppendSwitchASCII(switches::kEnableFeatures, + video_capture::kMojoVideoCapture.name); + command_line->AppendSwitch(switches::kUseFakeUIForMediaStream); + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kEnableBlinkFeatures, "GetUserMedia"); + } + + void SetUp() override { + ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); + EnablePixelOutput(); + ContentBrowserTest::SetUp(); + } +}; + +IN_PROC_BROWSER_TEST_F(WebRtcVideoCaptureBrowserTest, + MAYBE_RecoverFromCrashInVideoCaptureProcess) { + embedded_test_server()->StartAcceptingConnections(); + GURL url(embedded_test_server()->GetURL(kVideoCaptureHtmlFile)); + NavigateToURL(shell(), url); + + std::string result; + // Start video capture and wait until it started rendering + ASSERT_TRUE(ExecuteScriptAndExtractString( + shell(), kStartVideoCaptureAndVerifySize, &result)); + ASSERT_EQ("OK", result); + + // Simulate crash in video capture process + service_manager::Connector* connector = + ServiceManagerConnection::GetForProcess()->GetConnector(); + video_capture::mojom::TestingControlsPtr service_controls; + connector->BindInterface(video_capture::mojom::kServiceName, + mojo::MakeRequest(&service_controls)); + service_controls->Crash(); + + // Wait for video element to turn black + ASSERT_TRUE(ExecuteScriptAndExtractString(shell(), kWaitForVideoToTurnBlack, + &result)); + ASSERT_EQ("OK", result); + ASSERT_TRUE(ExecuteScriptAndExtractString( + shell(), kVerifyHasReceivedTrackEndedEvent, &result)); + ASSERT_EQ("OK", result); + + // Start capturing again and expect it to work. + ASSERT_TRUE(ExecuteScriptAndExtractString( + shell(), kStartVideoCaptureAndVerifySize, &result)); + ASSERT_EQ("OK", result); +} + +} // namespace content
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc index a2d633f7..f1fc6813 100644 --- a/content/child/resource_dispatcher.cc +++ b/content/child/resource_dispatcher.cc
@@ -670,7 +670,7 @@ std::unique_ptr<ThrottlingURLLoader> url_loader = ThrottlingURLLoader::CreateLoaderAndStart( url_loader_factory, std::move(throttles), routing_id, request_id, - mojom::kURLLoadOptionNone, std::move(request), client.get(), + mojom::kURLLoadOptionNone, *request, client.get(), net::MutableNetworkTrafficAnnotationTag(NO_TRAFFIC_ANNOTATION_YET), std::move(task_runner)); pending_requests_[request_id]->url_loader = std::move(url_loader);
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index 1987286..738e06d 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -263,6 +263,7 @@ "platform_notification_messages.h", "plugin_list.cc", "plugin_list.h", + "possibly_associated_interface_ptr.h", "presentation/presentation_struct_traits.cc", "presentation/presentation_struct_traits.h", "process_type.cc",
diff --git a/content/common/media/cdm_host_files.cc b/content/common/media/cdm_host_files.cc index c3ce8e6..49c5562 100644 --- a/content/common/media/cdm_host_files.cc +++ b/content/common/media/cdm_host_files.cc
@@ -134,8 +134,9 @@ return cdm_host_files; } -bool CdmHostFiles::InitVerification(base::NativeLibrary cdm_adapter_library, - const base::FilePath& cdm_adapter_path) { +CdmHostFiles::Status CdmHostFiles::InitVerification( + base::NativeLibrary cdm_adapter_library, + const base::FilePath& cdm_adapter_path) { DVLOG(1) << __func__; DCHECK(cdm_adapter_library); @@ -161,7 +162,7 @@ if (!scoped_cdm_library.is_valid()) { LOG(ERROR) << "Failed to load CDM (error: " << error.ToString() << ")"; CloseAllFiles(); - return true; + return Status::kCdmLoadFailed; } cdm_library = scoped_cdm_library.get(); #endif @@ -173,7 +174,7 @@ if (!init_verification_func) { LOG(ERROR) << "Function " << kInitVerificationFuncName << " not found."; CloseAllFiles(); - return true; + return Status::kGetFunctionFailed; } // Fills |cdm_host_files| with common and CDM specific files for @@ -199,12 +200,12 @@ if (!init_verification_func(cdm_host_files_ptr, cdm_host_files.size())) { DVLOG(1) << "Failed to verify CDM host."; CloseAllFiles(); - return false; + return Status::kInitVerificationFailed; } // Close all files not passed to the CDM. CloseAllFiles(); - return true; + return Status::kSuccess; } #if defined(POSIX_WITH_ZYGOTE)
diff --git a/content/common/media/cdm_host_files.h b/content/common/media/cdm_host_files.h index 48311c1f..a1f5849 100644 --- a/content/common/media/cdm_host_files.h +++ b/content/common/media/cdm_host_files.h
@@ -59,15 +59,23 @@ static std::unique_ptr<CdmHostFiles> Create( const base::FilePath& cdm_adapter_path); + // Status of CDM host verification. + // Note: Reported to UMA. Do not change the values. + enum class Status { + kNotCalled = 0, + kSuccess = 1, + kCdmLoadFailed = 2, + kGetFunctionFailed = 3, + kInitVerificationFailed = 4, + kStatusCount + }; + // Initializes the verification of CDM files by calling the function exported // by the CDM. If unexpected error happens, all files will be closed. // Otherwise, the PlatformFiles are passed to the CDM which will close the // files later. - // Only returns false if the CDM returns false (when there's an immediate - // failure). Otherwise always returns true for backward compatibility, e.g. - // when using an old CDM which doesn't implement the verification API. - bool InitVerification(base::NativeLibrary cdm_adapter_library, - const base::FilePath& cdm_adapter_path); + Status InitVerification(base::NativeLibrary cdm_adapter_library, + const base::FilePath& cdm_adapter_path); private: #if defined(POSIX_WITH_ZYGOTE)
diff --git a/content/renderer/possibly_associated_interface_ptr.h b/content/common/possibly_associated_interface_ptr.h similarity index 90% rename from content/renderer/possibly_associated_interface_ptr.h rename to content/common/possibly_associated_interface_ptr.h index 9e30892b..4d1bf57e 100644 --- a/content/renderer/possibly_associated_interface_ptr.h +++ b/content/common/possibly_associated_interface_ptr.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_POSSIBLY_ASSOCIATED_INTERFACE_PTR_H_ -#define CONTENT_RENDERER_POSSIBLY_ASSOCIATED_INTERFACE_PTR_H_ +#ifndef CONTENT_COMMON_POSSIBLY_ASSOCIATED_INTERFACE_PTR_H_ +#define CONTENT_COMMON_POSSIBLY_ASSOCIATED_INTERFACE_PTR_H_ #include "base/macros.h" #include "mojo/public/cpp/bindings/associated_interface_ptr.h" @@ -54,4 +54,4 @@ } // namespace content -#endif // CONTENT_RENDERER_POSSIBLY_ASSOCIATED_INTERFACE_PTR_H_ +#endif // CONTENT_COMMON_POSSIBLY_ASSOCIATED_INTERFACE_PTR_H_
diff --git a/content/common/throttling_url_loader.cc b/content/common/throttling_url_loader.cc index 52614ef5..8fed870 100644 --- a/content/common/throttling_url_loader.cc +++ b/content/common/throttling_url_loader.cc
@@ -13,13 +13,15 @@ int32_t in_routing_id, int32_t in_request_id, uint32_t in_options, - std::unique_ptr<ResourceRequest> in_url_request, + StartLoaderCallback in_start_loader_callback, + const ResourceRequest& in_url_request, scoped_refptr<base::SingleThreadTaskRunner> in_task_runner) : url_loader_factory(in_url_loader_factory), routing_id(in_routing_id), request_id(in_request_id), options(in_options), - url_request(std::move(in_url_request)), + start_loader_callback(std::move(in_start_loader_callback)), + url_request(in_url_request), task_runner(std::move(in_task_runner)) {} ThrottlingURLLoader::StartInfo::~StartInfo() = default; @@ -55,14 +57,29 @@ int32_t routing_id, int32_t request_id, uint32_t options, - std::unique_ptr<ResourceRequest> url_request, + const ResourceRequest& url_request, mojom::URLLoaderClient* client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { std::unique_ptr<ThrottlingURLLoader> loader(new ThrottlingURLLoader( std::move(throttles), client, traffic_annotation)); - loader->Start(factory, routing_id, request_id, options, - std::move(url_request), std::move(task_runner)); + loader->Start(factory, routing_id, request_id, options, StartLoaderCallback(), + url_request, std::move(task_runner)); + return loader; +} + +// static +std::unique_ptr<ThrottlingURLLoader> ThrottlingURLLoader::CreateLoaderAndStart( + StartLoaderCallback start_loader_callback, + std::vector<std::unique_ptr<URLLoaderThrottle>> throttles, + const ResourceRequest& url_request, + mojom::URLLoaderClient* client, + scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + std::unique_ptr<ThrottlingURLLoader> loader(new ThrottlingURLLoader( + std::move(throttles), client, net::MutableNetworkTrafficAnnotationTag())); + loader->Start(nullptr, 0, 0, mojom::kURLLoadOptionNone, + std::move(start_loader_callback), url_request, + std::move(task_runner)); return loader; } @@ -106,32 +123,61 @@ int32_t routing_id, int32_t request_id, uint32_t options, - std::unique_ptr<ResourceRequest> url_request, + StartLoaderCallback start_loader_callback, + const ResourceRequest& url_request, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { DCHECK_EQ(DEFERRED_NONE, deferred_stage_); DCHECK(!cancelled_by_throttle_); if (throttle_) { bool deferred = false; - throttle_->WillStartRequest(url_request->url, url_request->load_flags, - url_request->resource_type, &deferred); + throttle_->WillStartRequest(url_request.url, url_request.load_flags, + url_request.resource_type, &deferred); if (cancelled_by_throttle_) return; if (deferred) { deferred_stage_ = DEFERRED_START; - start_info_ = base::MakeUnique<StartInfo>(factory, routing_id, request_id, - options, std::move(url_request), - std::move(task_runner)); + start_info_ = + base::MakeUnique<StartInfo>(factory, routing_id, request_id, options, + std::move(start_loader_callback), + url_request, std::move(task_runner)); return; } } + StartNow(factory, routing_id, request_id, options, + std::move(start_loader_callback), url_request, + std::move(task_runner)); +} + +void ThrottlingURLLoader::StartNow( + mojom::URLLoaderFactory* factory, + int32_t routing_id, + int32_t request_id, + uint32_t options, + StartLoaderCallback start_loader_callback, + const ResourceRequest& url_request, + scoped_refptr<base::SingleThreadTaskRunner> task_runner) { mojom::URLLoaderClientPtr client; client_binding_.Bind(mojo::MakeRequest(&client), std::move(task_runner)); - factory->CreateLoaderAndStart(mojo::MakeRequest(&url_loader_), routing_id, - request_id, options, *url_request, - std::move(client), traffic_annotation_); + + if (factory) { + DCHECK(!start_loader_callback); + + mojom::URLLoaderAssociatedPtr url_loader; + auto url_loader_request = mojo::MakeRequest(&url_loader); + url_loader_ = std::move(url_loader); + factory->CreateLoaderAndStart(std::move(url_loader_request), routing_id, + request_id, options, url_request, + std::move(client), traffic_annotation_); + } else { + mojom::URLLoaderPtr url_loader; + auto url_loader_request = mojo::MakeRequest(&url_loader); + url_loader_ = std::move(url_loader); + std::move(start_loader_callback) + .Run(std::move(url_loader_request), std::move(client)); + } } void ThrottlingURLLoader::OnReceiveResponse( @@ -248,7 +294,7 @@ deferred_stage_ = DEFERRED_NONE; client_binding_.Close(); - url_loader_.reset(); + url_loader_ = nullptr; forwarding_client_->OnComplete(request_complete_data); } @@ -259,13 +305,10 @@ switch (deferred_stage_) { case DEFERRED_START: { - mojom::URLLoaderClientPtr client; - client_binding_.Bind( - mojo::MakeRequest(&client), std::move(start_info_->task_runner)); - start_info_->url_loader_factory->CreateLoaderAndStart( - mojo::MakeRequest(&url_loader_), start_info_->routing_id, - start_info_->request_id, start_info_->options, - *start_info_->url_request, std::move(client), traffic_annotation_); + StartNow(start_info_->url_loader_factory, start_info_->routing_id, + start_info_->request_id, start_info_->options, + std::move(start_info_->start_loader_callback), + start_info_->url_request, std::move(start_info_->task_runner)); if (priority_info_) { auto priority_info = std::move(priority_info_);
diff --git a/content/common/throttling_url_loader.h b/content/common/throttling_url_loader.h index 00f603c..11e34a2 100644 --- a/content/common/throttling_url_loader.h +++ b/content/common/throttling_url_loader.h
@@ -7,9 +7,11 @@ #include <memory> +#include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/threading/thread_task_runner_handle.h" #include "content/common/content_export.h" +#include "content/common/possibly_associated_interface_ptr.h" #include "content/common/url_loader.mojom.h" #include "content/common/url_loader_factory.mojom.h" #include "content/public/common/url_loader_throttle.h" @@ -33,18 +35,35 @@ public: // |factory| and |client| must stay alive during the lifetime of the returned // object. + // Please note that the request may not start immediately since it could be + // deferred by throttles. static std::unique_ptr<ThrottlingURLLoader> CreateLoaderAndStart( mojom::URLLoaderFactory* factory, std::vector<std::unique_ptr<URLLoaderThrottle>> throttles, int32_t routing_id, int32_t request_id, uint32_t options, - std::unique_ptr<ResourceRequest> url_request, + const ResourceRequest& url_request, mojom::URLLoaderClient* client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, scoped_refptr<base::SingleThreadTaskRunner> task_runner = base::ThreadTaskRunnerHandle::Get()); + using StartLoaderCallback = + base::OnceCallback<void(mojom::URLLoaderRequest request, + mojom::URLLoaderClientPtr client)>; + + // Similar to the method above, but uses a |start_loader_callback| instead of + // a mojom::URLLoaderFactory to start the loader. The callback must be safe + // to call during the lifetime of the returned object. + static std::unique_ptr<ThrottlingURLLoader> CreateLoaderAndStart( + StartLoaderCallback start_loader_callback, + std::vector<std::unique_ptr<URLLoaderThrottle>> throttles, + const ResourceRequest& url_request, + mojom::URLLoaderClient* client, + scoped_refptr<base::SingleThreadTaskRunner> task_runner = + base::ThreadTaskRunnerHandle::Get()); + ~ThrottlingURLLoader() override; void FollowRedirect(); @@ -56,13 +75,25 @@ mojom::URLLoaderClient* client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation); + // Either of the two sets of arguments below is valid but not both: + // - |factory|, |routing_id|, |request_id| and |options|; + // - |start_loader_callback|. void Start(mojom::URLLoaderFactory* factory, int32_t routing_id, int32_t request_id, uint32_t options, - std::unique_ptr<ResourceRequest> url_request, + StartLoaderCallback start_loader_callback, + const ResourceRequest& url_request, scoped_refptr<base::SingleThreadTaskRunner> task_runner); + void StartNow(mojom::URLLoaderFactory* factory, + int32_t routing_id, + int32_t request_id, + uint32_t options, + StartLoaderCallback start_loader_callback, + const ResourceRequest& url_request, + scoped_refptr<base::SingleThreadTaskRunner> task_runner); + // mojom::URLLoaderClient implementation: void OnReceiveResponse(const ResourceResponseHead& response_head, const base::Optional<net::SSLInfo>& ssl_info, @@ -97,14 +128,15 @@ mojom::URLLoaderClient* forwarding_client_; mojo::Binding<mojom::URLLoaderClient> client_binding_; - mojom::URLLoaderAssociatedPtr url_loader_; + PossiblyAssociatedInterfacePtr<mojom::URLLoader> url_loader_; struct StartInfo { StartInfo(mojom::URLLoaderFactory* in_url_loader_factory, int32_t in_routing_id, int32_t in_request_id, uint32_t in_options, - std::unique_ptr<ResourceRequest> in_url_request, + StartLoaderCallback in_start_loader_callback, + const ResourceRequest& in_url_request, scoped_refptr<base::SingleThreadTaskRunner> in_task_runner); ~StartInfo(); @@ -112,7 +144,10 @@ int32_t routing_id; int32_t request_id; uint32_t options; - std::unique_ptr<ResourceRequest> url_request; + + StartLoaderCallback start_loader_callback; + + ResourceRequest url_request; // |task_runner_| is used to set up |client_binding_|. scoped_refptr<base::SingleThreadTaskRunner> task_runner; };
diff --git a/content/common/throttling_url_loader_unittest.cc b/content/common/throttling_url_loader_unittest.cc index fa0355a..cf9913c 100644 --- a/content/common/throttling_url_loader_unittest.cc +++ b/content/common/throttling_url_loader_unittest.cc
@@ -208,11 +208,11 @@ } void CreateLoaderAndStart() { - auto request = base::MakeUnique<ResourceRequest>(); - request->url = GURL("http://example.org"); + ResourceRequest request; + request.url = GURL("http://example.org"); loader_ = ThrottlingURLLoader::CreateLoaderAndStart( - factory_.factory_ptr().get(), std::move(throttles_), 0, 0, 0, - std::move(request), &client_, + factory_.factory_ptr().get(), std::move(throttles_), 0, 0, 0, request, + &client_, net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); factory_.factory_ptr().FlushForTesting(); }
diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc index 39c079d..bbdebce 100644 --- a/content/ppapi_plugin/ppapi_thread.cc +++ b/content/ppapi_plugin/ppapi_thread.cc
@@ -362,6 +362,7 @@ // Use a local instance of CdmHostFiles so that if we return early for any // error, all files will closed automatically. std::unique_ptr<CdmHostFiles> cdm_host_files; + CdmHostFiles::Status cdm_status = CdmHostFiles::Status::kNotCalled; #if defined(OS_WIN) || defined(OS_MACOSX) // Open CDM host files before the process is sandboxed. @@ -377,8 +378,11 @@ // On Windows, initialize CDM host verification unsandboxed. On other // platforms, this is called sandboxed below. if (cdm_host_files) { - DCHECK(IsCdm(path)); - if (!cdm_host_files->InitVerification(library.get(), path)) { + DCHECK(!is_broker_ && IsCdm(path)); + cdm_status = cdm_host_files->InitVerification(library.get(), path); + // Ignore other failures for backward compatibility, e.g. when using an old + // CDM which doesn't implement the verification API. + if (cdm_status == CdmHostFiles::Status::kInitVerificationFailed) { LOG(WARNING) << "CDM host verification failed."; // TODO(xhwang): Add a new load result if needed. ReportLoadResult(path, INIT_FAILED); @@ -460,17 +464,26 @@ CHECK(InitializeSandbox()); #endif -#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION) && !defined(OS_WIN) +#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION) +#if !defined(OS_WIN) // Now we are sandboxed, initialize CDM host verification. if (cdm_host_files) { - DCHECK(IsCdm(path)); - if (!cdm_host_files->InitVerification(library.get(), path)) { + DCHECK(!is_broker_ && IsCdm(path)); + cdm_status = cdm_host_files->InitVerification(library.get(), path); + // Ignore other failures for backward compatibility, e.g. when using an + // old CDM which doesn't implement the verification API. + if (cdm_status == CdmHostFiles::Status::kInitVerificationFailed) { LOG(WARNING) << "CDM host verification failed."; // TODO(xhwang): Add a new load result if needed. ReportLoadResult(path, INIT_FAILED); return; } } +#endif // !defined(OS_WIN) + if (!is_broker_ && IsCdm(path)) { + UMA_HISTOGRAM_ENUMERATION("Media.EME.CdmHostVerificationStatus", + cdm_status, CdmHostFiles::Status::kStatusCount); + } #endif // BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION) && !defined(OS_WIN) int32_t init_error = plugin_entry_points_.initialize_module(
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json index cfedb98a..0326e861 100644 --- a/content/public/app/mojo/content_browser_manifest.json +++ b/content/public/app/mojo/content_browser_manifest.json
@@ -86,7 +86,7 @@ ], "resource_coordinator": [ "coordination_unit" ], - "video_capture": [ "capture" ] + "video_capture": [ "capture", "tests" ] } }, "navigation:frame": {
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 2c4c7000..330e772 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -15,6 +15,7 @@ #include "content/public/browser/navigation_ui_data.h" #include "content/public/browser/vpn_service_proxy.h" #include "content/public/common/sandbox_type.h" +#include "content/public/common/url_loader_throttle.h" #include "media/audio/audio_manager.h" #include "media/base/cdm_factory.h" #include "media/media_features.h" @@ -459,4 +460,10 @@ return nullptr; } +std::vector<std::unique_ptr<URLLoaderThrottle>> +ContentBrowserClient::CreateURLLoaderThrottles( + const base::Callback<WebContents*()>& wc_getter) { + return std::vector<std::unique_ptr<URLLoaderThrottle>>(); +} + } // namespace content
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index aa5e8ce9..758773b25 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -30,6 +30,7 @@ #include "media/mojo/interfaces/remoting.mojom.h" #include "net/base/mime_util.h" #include "net/cookies/canonical_cookie.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/quota/quota_manager.h" #include "third_party/WebKit/public/platform/WebPageVisibilityState.h" @@ -67,7 +68,6 @@ } namespace service_manager { -class BinderRegistry; class Service; struct BindSourceInfo; } @@ -129,6 +129,7 @@ class SpeechRecognitionManagerDelegate; class StoragePartition; class TracingDelegate; +class URLLoaderThrottle; class VpnServiceProxy; class WebContents; class WebContentsViewDelegate; @@ -796,6 +797,12 @@ // params are used if this returns nullptr. virtual std::unique_ptr<base::TaskScheduler::InitParams> GetTaskSchedulerInitParams(); + + // Allows the embedder to register one or more URLLoaderThrottles for a + // URL request. This is used only when --enable-network-service is in effect. + // This is called on the IO thread. + virtual std::vector<std::unique_ptr<URLLoaderThrottle>> + CreateURLLoaderThrottles(const base::Callback<WebContents*()>& wc_getter); }; } // namespace content
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h index 4d0f3fe8..49baa59 100644 --- a/content/public/browser/render_frame_host.h +++ b/content/public/browser/render_frame_host.h
@@ -15,6 +15,7 @@ #include "content/public/common/file_chooser_params.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_sender.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "third_party/WebKit/public/platform/WebPageVisibilityState.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/native_widget_types.h" @@ -34,7 +35,6 @@ } namespace service_manager { -class BinderRegistry; class InterfaceProvider; }
diff --git a/content/public/common/simple_connection_filter.cc b/content/public/common/simple_connection_filter.cc index 6ecfde4..da56a81b 100644 --- a/content/public/common/simple_connection_filter.cc +++ b/content/public/common/simple_connection_filter.cc
@@ -5,7 +5,6 @@ #include "content/public/common/simple_connection_filter.h" #include "services/service_manager/public/cpp/bind_source_info.h" -#include "services/service_manager/public/cpp/binder_registry.h" namespace content {
diff --git a/content/public/common/simple_connection_filter.h b/content/public/common/simple_connection_filter.h index 9aca000f..c1a1fec 100644 --- a/content/public/common/simple_connection_filter.h +++ b/content/public/common/simple_connection_filter.h
@@ -10,10 +10,7 @@ #include "content/common/content_export.h" #include "content/public/common/connection_filter.h" - -namespace service_manager { -class BinderRegistry; -} +#include "services/service_manager/public/cpp/binder_registry.h" namespace content {
diff --git a/content/public/gpu/content_gpu_client.h b/content/public/gpu/content_gpu_client.h index e3126e8b..2f9fad53 100644 --- a/content/public/gpu/content_gpu_client.h +++ b/content/public/gpu/content_gpu_client.h
@@ -7,16 +7,13 @@ #include "base/metrics/field_trial.h" #include "content/public/common/content_client.h" +#include "services/service_manager/public/cpp/binder_registry.h" namespace gpu { class SyncPointManager; struct GpuPreferences; } -namespace service_manager { -class BinderRegistry; -} - namespace content { // Embedder API for participating in gpu logic.
diff --git a/content/public/renderer/render_frame.h b/content/public/renderer/render_frame.h index 2ff0b2c1..e9f20c0 100644 --- a/content/public/renderer/render_frame.h +++ b/content/public/renderer/render_frame.h
@@ -17,6 +17,7 @@ #include "ipc/ipc_listener.h" #include "ipc/ipc_sender.h" #include "ppapi/features/features.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "third_party/WebKit/public/platform/WebPageVisibilityState.h" #include "third_party/WebKit/public/web/WebNavigationPolicy.h" @@ -38,7 +39,6 @@ } namespace service_manager { -class BinderRegistry; class InterfaceProvider; }
diff --git a/content/public/utility/content_utility_client.h b/content/public/utility/content_utility_client.h index 0d552bf..25f262a 100644 --- a/content/public/utility/content_utility_client.h +++ b/content/public/utility/content_utility_client.h
@@ -11,9 +11,9 @@ #include "base/callback_forward.h" #include "content/public/common/content_client.h" #include "content/public/common/service_info.h" +#include "services/service_manager/public/cpp/binder_registry.h" namespace service_manager { -class BinderRegistry; class InterfaceRegistry; }
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index f2f14ba..3da9f2ac 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -294,7 +294,6 @@ "pepper/fullscreen_container.h", "peripheral_content_heuristic.cc", "peripheral_content_heuristic.h", - "possibly_associated_interface_ptr.h", "presentation/presentation_connection_proxy.cc", "presentation/presentation_connection_proxy.h", "presentation/presentation_dispatcher.cc",
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index e6fd186..68172ceb 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -392,7 +392,7 @@ settings.resource_settings.use_gpu_memory_buffer_resources = compositor_deps->IsGpuMemoryBufferCompositorResourcesEnabled(); settings.enable_color_correct_rasterization = - cmd.HasSwitch(switches::kEnableColorCorrectRendering); + base::FeatureList::IsEnabled(features::kColorCorrectRendering); settings.resource_settings.buffer_to_texture_target_map = compositor_deps->GetBufferToTextureTargetMap();
diff --git a/content/renderer/media/render_media_log.cc b/content/renderer/media/render_media_log.cc index 66708ecf..0a3e4529 100644 --- a/content/renderer/media/render_media_log.cc +++ b/content/renderer/media/render_media_log.cc
@@ -29,10 +29,8 @@ event->type == media::MediaLogEvent::MEDIA_ERROR_LOG_ENTRY) { LOG(ERROR) << "MediaEvent: " << media::MediaLog::MediaEventToLogString(*event); - } else if (event->type != media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED && - event->type != media::MediaLogEvent::PROPERTY_CHANGE && - event->type != media::MediaLogEvent::WATCH_TIME_UPDATE && - event->type != media::MediaLogEvent::NETWORK_ACTIVITY_SET) { + } else if (event->type != media::MediaLogEvent::PROPERTY_CHANGE && + event->type != media::MediaLogEvent::WATCH_TIME_UPDATE) { MEDIA_EVENT_LOG_UTILITY << "MediaEvent: " << media::MediaLog::MediaEventToLogString(*event); } @@ -77,15 +75,6 @@ base::AutoLock auto_lock(lock_); switch (event->type) { - case media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED: - // Keep track of the latest buffered extents properties to avoid sending - // thousands of events over IPC. See http://crbug.com/352585 for - // details. - last_buffered_extents_changed_event_.swap(event); - // SendQueuedMediaEvents() will enqueue the most recent event of this - // kind, if any, prior to sending the event batch. - break; - case media::MediaLogEvent::DURATION_SET: // Similar to the extents changed message, this may fire many times for // badly muxed media. Suppress within our rate limits here. @@ -178,11 +167,6 @@ DCHECK(ipc_send_pending_); ipc_send_pending_ = false; - if (last_buffered_extents_changed_event_) { - queued_media_events_.push_back(*last_buffered_extents_changed_event_); - last_buffered_extents_changed_event_.reset(); - } - if (last_duration_changed_event_) { queued_media_events_.push_back(*last_duration_changed_event_); last_duration_changed_event_.reset();
diff --git a/content/renderer/media/render_media_log.h b/content/renderer/media/render_media_log.h index f13e021..62c1256 100644 --- a/content/renderer/media/render_media_log.h +++ b/content/renderer/media/render_media_log.h
@@ -70,7 +70,6 @@ bool ipc_send_pending_; // Limits the number of events we send over IPC to one. - std::unique_ptr<media::MediaLogEvent> last_buffered_extents_changed_event_; std::unique_ptr<media::MediaLogEvent> last_duration_changed_event_; // Holds the earliest MEDIA_ERROR_LOG_ENTRY event added to this log. This is
diff --git a/content/renderer/media/render_media_log_unittest.cc b/content/renderer/media/render_media_log_unittest.cc index e4db4d4..410c8df 100644 --- a/content/renderer/media/render_media_log_unittest.cc +++ b/content/renderer/media/render_media_log_unittest.cc
@@ -101,29 +101,6 @@ EXPECT_EQ(2, message_count()); } -TEST_F(RenderMediaLogTest, BufferedExtents) { - AddEvent(media::MediaLogEvent::LOAD); - AddEvent(media::MediaLogEvent::SEEK); - - // This event is handled separately and should always appear last regardless - // of how many times we see it. - AddEvent(media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED); - AddEvent(media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED); - AddEvent(media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED); - - EXPECT_EQ(0, message_count()); - Advance(base::TimeDelta::FromMilliseconds(1000)); - EXPECT_EQ(1, message_count()); - - // Verify contents. There should only be a single buffered extents changed - // event. - std::vector<media::MediaLogEvent> events = GetMediaLogEvents(); - ASSERT_EQ(3u, events.size()); - EXPECT_EQ(media::MediaLogEvent::LOAD, events[0].type); - EXPECT_EQ(media::MediaLogEvent::SEEK, events[1].type); - EXPECT_EQ(media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED, events[2].type); -} - TEST_F(RenderMediaLogTest, DurationChanged) { AddEvent(media::MediaLogEvent::LOAD); AddEvent(media::MediaLogEvent::SEEK);
diff --git a/content/renderer/mojo/blink_interface_registry_impl.cc b/content/renderer/mojo/blink_interface_registry_impl.cc index 2f24cf9..9f53ede 100644 --- a/content/renderer/mojo/blink_interface_registry_impl.cc +++ b/content/renderer/mojo/blink_interface_registry_impl.cc
@@ -8,7 +8,6 @@ #include "base/bind.h" #include "mojo/public/cpp/system/message_pipe.h" -#include "services/service_manager/public/cpp/binder_registry.h" namespace content {
diff --git a/content/renderer/mojo/blink_interface_registry_impl.h b/content/renderer/mojo/blink_interface_registry_impl.h index 09a16e9..c955ac5 100644 --- a/content/renderer/mojo/blink_interface_registry_impl.h +++ b/content/renderer/mojo/blink_interface_registry_impl.h
@@ -7,12 +7,10 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "services/service_manager/public/cpp/bind_source_info.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "third_party/WebKit/public/platform/InterfaceRegistry.h" -namespace service_manager { -class BinderRegistry; -} - namespace content { class BlinkInterfaceRegistryImpl : public blink::InterfaceRegistry {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 6298784f..9ed25956 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -116,7 +116,6 @@ } namespace service_manager { -class BinderRegistry; class InterfaceProvider; }
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 0cc1871..0577102e 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -489,11 +489,6 @@ blink::WebFrameWidget* RenderWidget::CreateWebFrameWidget( RenderWidget* render_widget, blink::WebLocalFrame* frame) { - if (!frame->Parent()) { - // TODO(dcheng): The main frame widget currently has a special case. - // Eliminate this once WebView is no longer a WebWidget. - return blink::WebFrameWidget::Create(render_widget, frame->View(), frame); - } return blink::WebFrameWidget::Create(render_widget, frame); }
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h index e0821e2..7884354 100644 --- a/content/renderer/renderer_blink_platform_impl.h +++ b/content/renderer/renderer_blink_platform_impl.h
@@ -17,9 +17,9 @@ #include "cc/blink/web_compositor_support_impl.h" #include "content/child/blink_platform_impl.h" #include "content/common/content_export.h" +#include "content/common/possibly_associated_interface_ptr.h" #include "content/common/url_loader_factory.mojom.h" #include "content/renderer/origin_trials/web_trial_token_validator_impl.h" -#include "content/renderer/possibly_associated_interface_ptr.h" #include "content/renderer/top_level_blame_context.h" #include "content/renderer/webpublicsuffixlist_impl.h" #include "services/ui/public/cpp/bitmap/child_shared_bitmap_manager.h"
diff --git a/content/shell/app/shell_main_delegate.cc b/content/shell/app/shell_main_delegate.cc index f496af7..6cfffb6 100644 --- a/content/shell/app/shell_main_delegate.cc +++ b/content/shell/app/shell_main_delegate.cc
@@ -213,9 +213,7 @@ command_line.AppendSwitch(switches::kDisableGpuRasterization); } - // Enable color correct rendering. If the virtual test suite didn't specify - // a color space, then use sRGB. - command_line.AppendSwitch(switches::kEnableColorCorrectRendering); + // If the virtual test suite didn't specify a color space, then force sRGB. if (!command_line.HasSwitch(switches::kForceColorProfile)) command_line.AppendSwitchASCII(switches::kForceColorProfile, "srgb"); @@ -234,6 +232,13 @@ *exit_code = 1; return true; } + + // Enable additional base::Features. Note that there already may exist a + // list of enabled features from the virtual or physical test suite. + std::string enabled_features = + command_line.GetSwitchValueASCII(switches::kEnableFeatures); + enabled_features = "ColorCorrectRendering," + enabled_features; + command_line.AppendSwitchASCII(switches::kEnableFeatures, enabled_features); } content_client_.reset(base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 45103a4..4027e5722 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -801,6 +801,7 @@ "//services/ui/gpu/interfaces", "//services/ui/public/cpp/gpu", "//services/video_capture/public/cpp", + "//services/video_capture/public/interfaces:constants", "//storage/browser", "//testing/gmock", "//testing/gtest", @@ -967,6 +968,7 @@ "../browser/webrtc/webrtc_internals_browsertest.cc", "../browser/webrtc/webrtc_ip_permissions_browsertest.cc", "../browser/webrtc/webrtc_media_recorder_browsertest.cc", + "../browser/webrtc/webrtc_video_capture_browsertest.cc", "../browser/webrtc/webrtc_webcam_browsertest.cc", "../browser/webrtc/webrtc_webcam_browsertest.h", ]
diff --git a/content/test/data/media/video_capture_test.html b/content/test/data/media/video_capture_test.html new file mode 100644 index 0000000..faf8a28cf --- /dev/null +++ b/content/test/data/media/video_capture_test.html
@@ -0,0 +1,74 @@ +<html> +<head> + <script type="text/javascript" src="webrtc_test_utilities.js"></script> + <script type="text/javascript"> + $ = function(id) { + return document.getElementById(id); + }; + + const WIDTH = 320; + var CONSTRAINTS = { video: { width: { exact : WIDTH } } }; + var hasReceivedTrackEndedEvent = false; + + function startVideoCaptureAndVerifySize() { + console.log('Calling getUserMediaAndWaitForVideoRendering.'); + navigator.webkitGetUserMedia( + CONSTRAINTS, + gotStreamCallback, + failedCallback); + } + + function failedCallback(error) { + failTest('GetUserMedia call failed with code ' + error.code); + } + + function gotStreamCallback(stream) { + var localView = $('local-view'); + localView.src = URL.createObjectURL(stream); + + var videoTracks = stream.getVideoTracks(); + if (videoTracks.length == 0) { + failTest('Did not receive any video tracks'); + } + var videoTrack = videoTracks[0]; + videoTrack.onended = function() { + hasReceivedTrackEndedEvent = true; + }; + + detectVideoPlaying('local-view', function() { + if (localView.videoWidth == WIDTH) { + reportTestSuccess(); + } else { + failTest('Video has unexpected width.'); + } + }); + } + + function waitForVideoToTurnBlack() { + detectBlackVideo('local-view', function() { + reportTestSuccess(); + }); + } + + function verifyHasReceivedTrackEndedEvent() { + if (hasReceivedTrackEndedEvent) { + reportTestSuccess(); + } else { + failTest('Did not receive ended event from track.'); + } + } + + </script> +</head> +<body> + <table border="0"> + <tr> + <td><video id="local-view" width="96" height="96" autoplay + style="display:none"></video></td> + <!-- The canvas is used to detect when video starts and stops. --> + <td><canvas id="local-view-canvas" width="96" height="96" + style="display:none"></canvas></td> + </tr> + </table> +</body> +</html>
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index f05de6ab..8748000 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -186,15 +186,15 @@ self.Flaky('deqp/*', ['win', 'intel', 'd3d11'], bug=628395) # Passthrough command decoder / D3D11 - self.Fail('conformance/textures/image_bitmap_from_video/*', + self.Skip('conformance/textures/image_bitmap_from_video/*', ['win', 'passthrough', 'd3d11'], bug=602688) - self.Fail('conformance/textures/video/*', + self.Skip('conformance/textures/video/*', ['win', 'passthrough', 'd3d11'], bug=602688) - self.Fail('conformance/textures/misc/texture-corner-case-videos.html', + self.Skip('conformance/textures/misc/texture-corner-case-videos.html', ['win', 'passthrough', 'd3d11'], bug=602688) - self.Fail('conformance2/textures/image_bitmap_from_video/*', + self.Skip('conformance2/textures/image_bitmap_from_video/*', ['win', 'passthrough', 'd3d11'], bug=602688) - self.Fail('conformance2/textures/video/*', + self.Skip('conformance2/textures/video/*', ['win', 'passthrough', 'd3d11'], bug=602688) self.Fail('conformance2/glsl3/no-attribute-vertex-shader.html',
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc index 43bf078..a3aa9a0 100644 --- a/content/test/layouttest_support.cc +++ b/content/test/layouttest_support.cc
@@ -345,7 +345,7 @@ cc::RendererSettings renderer_settings; base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); renderer_settings.enable_color_correct_rendering = - cmd->HasSwitch(switches::kEnableColorCorrectRendering); + base::FeatureList::IsEnabled(features::kColorCorrectRendering); renderer_settings.allow_antialiasing &= !cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing); renderer_settings.highp_threshold_min = 2048;
diff --git a/device/BUILD.gn b/device/BUILD.gn index 458c5eb..bd989961 100644 --- a/device/BUILD.gn +++ b/device/BUILD.gn
@@ -158,8 +158,8 @@ "usb/mojo/device_manager_impl_unittest.cc", "usb/mojo/mock_permission_provider.cc", "usb/mojo/mock_permission_provider.h", + "usb/public/cpp/filter_utils_unittest.cc", "usb/usb_descriptors_unittest.cc", - "usb/usb_device_filter_unittest.cc", "usb/usb_device_handle_unittest.cc", "usb/usb_ids_unittest.cc", "usb/usb_service_unittest.cc", @@ -171,6 +171,7 @@ "//device/usb", "//device/usb:test_support", "//device/usb/mojo", + "//device/usb/public/cpp", "//device/usb/public/interfaces", "//net:test_support", ]
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn index 25dd04f..f4e2b6c 100644 --- a/device/bluetooth/BUILD.gn +++ b/device/bluetooth/BUILD.gn
@@ -49,8 +49,6 @@ "test/fake_central.h", "test/fake_peripheral.cc", "test/fake_peripheral.h", - "test/fake_remote_gatt_service.cc", - "test/fake_remote_gatt_service.h", ] deps = [
diff --git a/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom b/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom index bba5e49..1e7b4bf 100644 --- a/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom +++ b/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom
@@ -88,11 +88,4 @@ // This method aims to simulate the response once all of these procedures // have completed or if there was an error during any of them. SetNextGATTDiscoveryResponse(string address, uint16 code) => (bool success); - - // Adds a fake GATT Service with |service_uuid| to be found when - // discovering the peripheral's GATT Attributes. Runs its callback with - // the fake service's Id. Runs its callback with nullopt if it failed to - // add the fake service. - AddFakeService(string peripheral_address, UUID service_uuid) - => (string? service_id); };
diff --git a/device/bluetooth/test/fake_central.cc b/device/bluetooth/test/fake_central.cc index a3e8cf6..74adb7b95 100644 --- a/device/bluetooth/test/fake_central.cc +++ b/device/bluetooth/test/fake_central.cc
@@ -7,7 +7,6 @@ #include <memory> #include <string> #include <utility> -#include <vector> #include "device/bluetooth/bluetooth_device.h" #include "device/bluetooth/bluetooth_discovery_filter.h" @@ -76,19 +75,6 @@ std::move(callback).Run(true); } -void FakeCentral::AddFakeService(const std::string& peripheral_address, - const device::BluetoothUUID& service_uuid, - AddFakeServiceCallback callback) { - auto device_iter = devices_.find(peripheral_address); - if (device_iter == devices_.end()) { - std::move(callback).Run(base::nullopt); - } - - FakePeripheral* fake_peripheral = - static_cast<FakePeripheral*>(device_iter->second.get()); - std::move(callback).Run(fake_peripheral->AddFakeService(service_uuid)); -} - std::string FakeCentral::GetAddress() const { NOTREACHED(); return std::string();
diff --git a/device/bluetooth/test/fake_central.h b/device/bluetooth/test/fake_central.h index 4786038..828cdb3 100644 --- a/device/bluetooth/test/fake_central.h +++ b/device/bluetooth/test/fake_central.h
@@ -6,7 +6,6 @@ #include <memory> #include <string> -#include <vector> #include "base/compiler_specific.h" #include "device/bluetooth/bluetooth_adapter.h" @@ -38,9 +37,6 @@ const std::string& address, uint16_t code, SetNextGATTDiscoveryResponseCallback callback) override; - void AddFakeService(const std::string& peripheral_address, - const device::BluetoothUUID& service_uuid, - AddFakeServiceCallback callback) override; // BluetoothAdapter overrides: std::string GetAddress() const override;
diff --git a/device/bluetooth/test/fake_peripheral.cc b/device/bluetooth/test/fake_peripheral.cc index 3eba213..3a0e0e7 100644 --- a/device/bluetooth/test/fake_peripheral.cc +++ b/device/bluetooth/test/fake_peripheral.cc
@@ -4,12 +4,7 @@ #include "device/bluetooth/test/fake_peripheral.h" -#include <utility> - #include "base/memory/weak_ptr.h" -#include "base/strings/string_number_conversions.h" -#include "device/bluetooth/bluetooth_uuid.h" -#include "device/bluetooth/test/fake_remote_gatt_service.h" namespace bluetooth { @@ -47,22 +42,6 @@ next_discovery_response_ = code; } -std::string FakePeripheral::AddFakeService( - const device::BluetoothUUID& service_uuid) { - std::string new_service_id = base::SizeTToString(++last_service_id_); - - GattServiceMap::iterator it; - bool inserted; - - std::tie(it, inserted) = gatt_services_.emplace( - new_service_id, - base::MakeUnique<FakeRemoteGattService>(new_service_id, service_uuid, - true /* is_primary */, this)); - - DCHECK(inserted); - return it->second->GetIdentifier(); -} - uint32_t FakePeripheral::GetBluetoothClass() const { NOTREACHED(); return 0;
diff --git a/device/bluetooth/test/fake_peripheral.h b/device/bluetooth/test/fake_peripheral.h index a23e86d..b42a4b2 100644 --- a/device/bluetooth/test/fake_peripheral.h +++ b/device/bluetooth/test/fake_peripheral.h
@@ -12,7 +12,6 @@ #include "base/optional.h" #include "device/bluetooth/bluetooth_device.h" #include "device/bluetooth/test/fake_central.h" -#include "device/bluetooth/test/fake_remote_gatt_service.h" namespace bluetooth { @@ -46,10 +45,6 @@ // after IsGattDiscoveryComplete is called. void SetNextGATTDiscoveryResponse(uint16_t code); - // Adds a fake primary service with |service_uuid| to this peripheral. - // Returns the service's Id. - std::string AddFakeService(const device::BluetoothUUID& service_uuid); - // BluetoothDevice overrides: uint32_t GetBluetoothClass() const override; #if defined(OS_CHROMEOS) || defined(OS_LINUX) @@ -119,10 +114,6 @@ // True when this Bluetooth interface is connected to the device. bool gatt_connected_; - // Keeps track of the last Id used to create a fake service. Incremented - // every time a new fake service is added. - size_t last_service_id_; - // Used to simulate a GATT Discovery procedure. // Mutable because IsGattServicesDiscoveryComplete needs to set this but // is const.
diff --git a/device/bluetooth/test/fake_remote_gatt_service.cc b/device/bluetooth/test/fake_remote_gatt_service.cc deleted file mode 100644 index 151c544..0000000 --- a/device/bluetooth/test/fake_remote_gatt_service.cc +++ /dev/null
@@ -1,60 +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 "device/bluetooth/test/fake_remote_gatt_service.h" - -#include <vector> - -#include "device/bluetooth/bluetooth_device.h" -#include "device/bluetooth/bluetooth_uuid.h" - -namespace bluetooth { - -FakeRemoteGattService::FakeRemoteGattService( - const std::string& service_id, - const device::BluetoothUUID& service_uuid, - bool is_primary, - device::BluetoothDevice* device) - : service_id_(service_id), - service_uuid_(service_uuid), - is_primary_(is_primary), - device_(device) {} - -FakeRemoteGattService::~FakeRemoteGattService() {} - -std::string FakeRemoteGattService::GetIdentifier() const { - return service_id_; -} - -device::BluetoothUUID FakeRemoteGattService::GetUUID() const { - return service_uuid_; -} - -bool FakeRemoteGattService::IsPrimary() const { - return is_primary_; -} - -device::BluetoothDevice* FakeRemoteGattService::GetDevice() const { - return device_; -} - -std::vector<device::BluetoothRemoteGattCharacteristic*> -FakeRemoteGattService::GetCharacteristics() const { - NOTREACHED(); - return std::vector<device::BluetoothRemoteGattCharacteristic*>(); -} - -std::vector<device::BluetoothRemoteGattService*> -FakeRemoteGattService::GetIncludedServices() const { - NOTREACHED(); - return std::vector<device::BluetoothRemoteGattService*>(); -} - -device::BluetoothRemoteGattCharacteristic* -FakeRemoteGattService::GetCharacteristic(const std::string& identifier) const { - NOTREACHED(); - return nullptr; -} - -} // namespace bluetooth
diff --git a/device/bluetooth/test/fake_remote_gatt_service.h b/device/bluetooth/test/fake_remote_gatt_service.h deleted file mode 100644 index fda3bfe6..0000000 --- a/device/bluetooth/test/fake_remote_gatt_service.h +++ /dev/null
@@ -1,54 +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 DEVICE_BLUETOOTH_TEST_FAKE_REMOTE_GATT_SERVICE_H_ -#define DEVICE_BLUETOOTH_TEST_FAKE_REMOTE_GATT_SERVICE_H_ - -#include <string> -#include <vector> - -#include "device/bluetooth/bluetooth_remote_gatt_service.h" -#include "device/bluetooth/bluetooth_uuid.h" - -namespace device { -class BluetoothDevice; -class BluetoothRemoteGattService; -class BluetoothRemoteGattCharacteristic; -} - -namespace bluetooth { - -// Implements device::BluetoothRemoteGattService. Meant to be used by -// FakePeripheral to keep track of the service's state and attributes. -class FakeRemoteGattService : public device::BluetoothRemoteGattService { - public: - FakeRemoteGattService(const std::string& service_id, - const device::BluetoothUUID& service_uuid, - bool is_primary, - device::BluetoothDevice* device); - ~FakeRemoteGattService() override; - - // device::BluetoothGattService overrides: - std::string GetIdentifier() const override; - device::BluetoothUUID GetUUID() const override; - bool IsPrimary() const override; - - // device::BluetoothRemoteGattService overrides: - device::BluetoothDevice* GetDevice() const override; - std::vector<device::BluetoothRemoteGattCharacteristic*> GetCharacteristics() - const override; - std::vector<device::BluetoothRemoteGattService*> GetIncludedServices() - const override; - device::BluetoothRemoteGattCharacteristic* GetCharacteristic( - const std::string& identifier) const override; - - private: - const std::string service_id_; - const device::BluetoothUUID service_uuid_; - const bool is_primary_; - device::BluetoothDevice* device_; -}; - -} // namespace bluetooth - -#endif // DEVICE_BLUETOOTH_TEST_FAKE_REMOTE_GATT_SERVICE_H_
diff --git a/device/usb/BUILD.gn b/device/usb/BUILD.gn index 83ff8c11..5cb128f 100644 --- a/device/usb/BUILD.gn +++ b/device/usb/BUILD.gn
@@ -26,8 +26,6 @@ "usb_device.h", "usb_device_android.cc", "usb_device_android.h", - "usb_device_filter.cc", - "usb_device_filter.h", "usb_device_handle.cc", "usb_device_handle.h", "usb_device_handle_android.cc", @@ -60,17 +58,13 @@ "//base/third_party/dynamic_annotations", "//components/device_event_log", "//device/base", + "//device/usb/public/interfaces", "//net", ] public_deps = [ "//base", "//url", - - # Depend on the header generation target only to avoid the circular - # dependency caused by both using enums defined in the mojom headers and - # typemappings linking against this target. - "public/interfaces:interfaces__generator", ] if (use_udev) {
diff --git a/device/usb/mojo/BUILD.gn b/device/usb/mojo/BUILD.gn index 25e916b..7d13939 100644 --- a/device/usb/mojo/BUILD.gn +++ b/device/usb/mojo/BUILD.gn
@@ -17,6 +17,7 @@ deps = [ "//device/base", "//device/usb", + "//device/usb/public/cpp", "//device/usb/public/interfaces", "//mojo/common", "//mojo/public/cpp/bindings",
diff --git a/device/usb/mojo/device_manager_impl.cc b/device/usb/mojo/device_manager_impl.cc index 31a08beb..539ea3a1 100644 --- a/device/usb/mojo/device_manager_impl.cc +++ b/device/usb/mojo/device_manager_impl.cc
@@ -17,9 +17,9 @@ #include "device/usb/mojo/device_impl.h" #include "device/usb/mojo/permission_provider.h" #include "device/usb/mojo/type_converters.h" +#include "device/usb/public/cpp/filter_utils.h" #include "device/usb/public/interfaces/device.mojom.h" #include "device/usb/usb_device.h" -#include "device/usb/usb_device_filter.h" #include "device/usb/usb_service.h" namespace device { @@ -84,13 +84,13 @@ mojom::UsbEnumerationOptionsPtr options, const GetDevicesCallback& callback, const std::vector<scoped_refptr<UsbDevice>>& devices) { - std::vector<UsbDeviceFilter> filters; - if (options && options->filters) - filters.swap(*options->filters); + std::vector<mojom::UsbDeviceFilterPtr> filters; + if (options) + filters.swap(options->filters); std::vector<mojom::UsbDeviceInfoPtr> device_infos; for (const auto& device : devices) { - if (UsbDeviceFilter::MatchesAny(*device, filters)) { + if (UsbDeviceFilterMatchesAny(filters, *device)) { if (permission_provider_ && permission_provider_->HasDevicePermission(device)) { device_infos.push_back(mojom::UsbDeviceInfo::From(*device));
diff --git a/device/usb/mojo/device_manager_impl_unittest.cc b/device/usb/mojo/device_manager_impl_unittest.cc index 0b41511..1cd3fa7 100644 --- a/device/usb/mojo/device_manager_impl_unittest.cc +++ b/device/usb/mojo/device_manager_impl_unittest.cc
@@ -122,11 +122,11 @@ UsbDeviceManagerPtr device_manager = ConnectToDeviceManager(); + auto filter = mojom::UsbDeviceFilter::New(); + filter->has_vendor_id = true; + filter->vendor_id = 0x1234; UsbEnumerationOptionsPtr options = mojom::UsbEnumerationOptions::New(); - UsbDeviceFilter filter; - filter.vendor_id = 0x1234; - options->filters.emplace(); - options->filters->push_back(filter); + options->filters.push_back(std::move(filter)); std::set<std::string> guids; guids.insert(device0->guid());
diff --git a/device/usb/mojo/type_converters.h b/device/usb/mojo/type_converters.h index cb9514c..fc26bb75 100644 --- a/device/usb/mojo/type_converters.h +++ b/device/usb/mojo/type_converters.h
@@ -10,7 +10,6 @@ #include "device/usb/public/interfaces/device.mojom.h" #include "device/usb/public/interfaces/device_manager.mojom.h" #include "device/usb/usb_descriptors.h" -#include "device/usb/usb_device_filter.h" #include "device/usb/usb_device_handle.h" #include "mojo/public/cpp/bindings/type_converter.h"
diff --git a/device/usb/public/cpp/BUILD.gn b/device/usb/public/cpp/BUILD.gn new file mode 100644 index 0000000..717c2a9 --- /dev/null +++ b/device/usb/public/cpp/BUILD.gn
@@ -0,0 +1,16 @@ +# 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. + +source_set("cpp") { + sources = [ + "filter_utils.cc", + "filter_utils.h", + ] + + deps = [ + "//base", + "//device/usb", + "//device/usb/public/interfaces", + ] +}
diff --git a/device/usb/public/cpp/filter_utils.cc b/device/usb/public/cpp/filter_utils.cc new file mode 100644 index 0000000..021af336 --- /dev/null +++ b/device/usb/public/cpp/filter_utils.cc
@@ -0,0 +1,59 @@ +// 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 "device/usb/public/cpp/filter_utils.h" + +#include "base/strings/utf_string_conversions.h" +#include "device/usb/usb_device.h" + +namespace device { + +bool UsbDeviceFilterMatches(const mojom::UsbDeviceFilter& filter, + const UsbDevice& device) { + if (filter.has_vendor_id) { + if (device.vendor_id() != filter.vendor_id) + return false; + + if (filter.has_product_id && device.product_id() != filter.product_id) + return false; + } + + if (filter.serial_number && + device.serial_number() != base::UTF8ToUTF16(*filter.serial_number)) { + return false; + } + + if (filter.has_class_code) { + for (const UsbConfigDescriptor& config : device.configurations()) { + for (const UsbInterfaceDescriptor& iface : config.interfaces) { + if (iface.interface_class == filter.class_code && + (!filter.has_subclass_code || + (iface.interface_subclass == filter.subclass_code && + (!filter.has_protocol_code || + iface.interface_protocol == filter.protocol_code)))) { + return true; + } + } + } + + return false; + } + + return true; +} + +bool UsbDeviceFilterMatchesAny( + const std::vector<mojom::UsbDeviceFilterPtr>& filters, + const UsbDevice& device) { + if (filters.empty()) + return true; + + for (const auto& filter : filters) { + if (UsbDeviceFilterMatches(*filter, device)) + return true; + } + return false; +} + +} // namespace device
diff --git a/device/usb/public/cpp/filter_utils.h b/device/usb/public/cpp/filter_utils.h new file mode 100644 index 0000000..017917b --- /dev/null +++ b/device/usb/public/cpp/filter_utils.h
@@ -0,0 +1,25 @@ +// 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 DEVICE_USB_PUBLIC_CPP_FILTER_UTILS_H_ +#define DEVICE_USB_PUBLIC_CPP_FILTER_UTILS_H_ + +#include <vector> + +#include "device/usb/public/interfaces/device_manager.mojom.h" + +namespace device { + +class UsbDevice; + +bool UsbDeviceFilterMatches(const mojom::UsbDeviceFilter& filter, + const UsbDevice& device); + +bool UsbDeviceFilterMatchesAny( + const std::vector<mojom::UsbDeviceFilterPtr>& filters, + const UsbDevice& device); + +} // namespace device + +#endif // DEVICE_USB_PUBLIC_CPP_FILTER_UTILS_H_
diff --git a/device/usb/public/cpp/filter_utils_unittest.cc b/device/usb/public/cpp/filter_utils_unittest.cc new file mode 100644 index 0000000..eeaf007 --- /dev/null +++ b/device/usb/public/cpp/filter_utils_unittest.cc
@@ -0,0 +1,163 @@ +// 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 <string> +#include <vector> + +#include "base/memory/ref_counted.h" +#include "device/usb/mock_usb_device.h" +#include "device/usb/public/cpp/filter_utils.h" +#include "device/usb/usb_descriptors.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace device { + +namespace { + +using testing::Return; + +class UsbFilterTest : public testing::Test { + public: + void SetUp() override { + UsbConfigDescriptor config(1, false, false, 0); + config.interfaces.emplace_back(1, 0, 0xff, 0x42, 0x01); + + android_phone_ = new MockUsbDevice(0x18d1, 0x4ee2, "Google Inc.", "Nexus 5", + "ABC123", {config}); + } + + protected: + scoped_refptr<MockUsbDevice> android_phone_; +}; + +TEST_F(UsbFilterTest, MatchAny) { + auto filter = mojom::UsbDeviceFilter::New(); + EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchVendorId) { + auto filter = mojom::UsbDeviceFilter::New(); + filter->has_vendor_id = true; + filter->vendor_id = 0x18d1; + EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchVendorIdNegative) { + auto filter = mojom::UsbDeviceFilter::New(); + filter->has_vendor_id = true; + filter->vendor_id = 0x1d6b; + EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchProductId) { + auto filter = mojom::UsbDeviceFilter::New(); + filter->has_vendor_id = true; + filter->vendor_id = 0x18d1; + filter->has_product_id = true; + filter->product_id = 0x4ee2; + EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchProductIdNegative) { + auto filter = mojom::UsbDeviceFilter::New(); + filter->has_vendor_id = true; + filter->vendor_id = 0x18d1; + filter->has_product_id = true; + filter->product_id = 0x4ee1; + EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchInterfaceClass) { + auto filter = mojom::UsbDeviceFilter::New(); + filter->has_class_code = true; + filter->class_code = 0xff; + EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchInterfaceClassNegative) { + auto filter = mojom::UsbDeviceFilter::New(); + filter->has_class_code = true; + filter->class_code = 0xe0; + EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchInterfaceSubclass) { + auto filter = mojom::UsbDeviceFilter::New(); + filter->has_class_code = true; + filter->class_code = 0xff; + filter->has_subclass_code = true; + filter->subclass_code = 0x42; + EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchInterfaceSubclassNegative) { + auto filter = mojom::UsbDeviceFilter::New(); + filter->has_class_code = true; + filter->class_code = 0xff; + filter->has_subclass_code = true; + filter->subclass_code = 0x01; + EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchInterfaceProtocol) { + auto filter = mojom::UsbDeviceFilter::New(); + filter->has_class_code = true; + filter->class_code = 0xff; + filter->has_subclass_code = true; + filter->subclass_code = 0x42; + filter->has_protocol_code = true; + filter->protocol_code = 0x01; + EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchInterfaceProtocolNegative) { + auto filter = mojom::UsbDeviceFilter::New(); + filter->has_class_code = true; + filter->class_code = 0xff; + filter->has_subclass_code = true; + filter->subclass_code = 0x42; + filter->has_protocol_code = true; + filter->protocol_code = 0x02; + EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchSerialNumber) { + auto filter = mojom::UsbDeviceFilter::New(); + filter->serial_number = std::string("ABC123"); + EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_)); + filter->has_vendor_id = true; + filter->vendor_id = 0x18d1; + EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_)); + filter->vendor_id = 0x18d2; + EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_)); + filter->vendor_id = 0x18d1; + filter->serial_number = std::string("DIFFERENT"); + EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchAnyEmptyList) { + std::vector<mojom::UsbDeviceFilterPtr> filters; + ASSERT_TRUE(UsbDeviceFilterMatchesAny(filters, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchesAnyVendorId) { + std::vector<mojom::UsbDeviceFilterPtr> filters; + filters.push_back(mojom::UsbDeviceFilter::New()); + filters.back()->has_vendor_id = true; + filters.back()->vendor_id = 0x18d1; + ASSERT_TRUE(UsbDeviceFilterMatchesAny(filters, *android_phone_)); +} + +TEST_F(UsbFilterTest, MatchesAnyVendorIdNegative) { + std::vector<mojom::UsbDeviceFilterPtr> filters; + filters.push_back(mojom::UsbDeviceFilter::New()); + filters.back()->has_vendor_id = true; + filters.back()->vendor_id = 0x1d6b; + ASSERT_FALSE(UsbDeviceFilterMatchesAny(filters, *android_phone_)); +} + +} // namespace + +} // namespace device
diff --git a/device/usb/public/interfaces/OWNERS b/device/usb/public/interfaces/OWNERS index fda0d85..08850f4 100644 --- a/device/usb/public/interfaces/OWNERS +++ b/device/usb/public/interfaces/OWNERS
@@ -1,8 +1,2 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS - -per-file *_struct_traits*.*=set noparent -per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS - -per-file *.typemap=set noparent -per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/device/usb/public/interfaces/device_manager.mojom b/device/usb/public/interfaces/device_manager.mojom index 9e90681..4a4ec72 100644 --- a/device/usb/public/interfaces/device_manager.mojom +++ b/device/usb/public/interfaces/device_manager.mojom
@@ -26,7 +26,7 @@ }; struct UsbEnumerationOptions { - array<UsbDeviceFilter>? filters; + array<UsbDeviceFilter> filters; }; interface UsbDeviceManager {
diff --git a/device/usb/public/interfaces/device_manager.typemap b/device/usb/public/interfaces/device_manager.typemap deleted file mode 100644 index 088ee80..0000000 --- a/device/usb/public/interfaces/device_manager.typemap +++ /dev/null
@@ -1,15 +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. - -mojom = "//device/usb/public/interfaces/device_manager.mojom" -public_headers = [ "//device/usb/usb_device_filter.h" ] -traits_headers = - [ "//device/usb/public/interfaces/device_manager_struct_traits.h" ] -sources = [ - "//device/usb/public/interfaces/device_manager_struct_traits.cc", -] -deps = [ - "//device/usb", -] -type_mappings = [ "device.mojom.UsbDeviceFilter=device::UsbDeviceFilter" ]
diff --git a/device/usb/public/interfaces/device_manager_struct_traits.cc b/device/usb/public/interfaces/device_manager_struct_traits.cc deleted file mode 100644 index 8198152e..0000000 --- a/device/usb/public/interfaces/device_manager_struct_traits.cc +++ /dev/null
@@ -1,27 +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 "device/usb/public/interfaces/device_manager_struct_traits.h" - -namespace mojo { - -// static -bool StructTraits< - device::mojom::UsbDeviceFilterDataView, - device::UsbDeviceFilter>::Read(device::mojom::UsbDeviceFilterDataView input, - device::UsbDeviceFilter* output) { - if (input.has_vendor_id()) - output->vendor_id = input.vendor_id(); - if (input.has_product_id()) - output->product_id = input.product_id(); - if (input.has_class_code()) - output->interface_class = input.class_code(); - if (input.has_subclass_code()) - output->interface_subclass = input.subclass_code(); - if (input.has_protocol_code()) - output->interface_protocol = input.protocol_code(); - return input.ReadSerialNumber(&output->serial_number); -} - -} // namespace mojo
diff --git a/device/usb/public/interfaces/device_manager_struct_traits.h b/device/usb/public/interfaces/device_manager_struct_traits.h deleted file mode 100644 index 1028f66..0000000 --- a/device/usb/public/interfaces/device_manager_struct_traits.h +++ /dev/null
@@ -1,67 +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 DEVICE_USB_PUBLIC_INTERFACES_DEVICE_MANAGER_STRUCT_TRAITS_H_ -#define DEVICE_USB_PUBLIC_INTERFACES_DEVICE_MANAGER_STRUCT_TRAITS_H_ - -#include "device/usb/public/interfaces/device_manager.mojom.h" -#include "device/usb/usb_device_filter.h" - -namespace mojo { - -template <> -struct StructTraits<device::mojom::UsbDeviceFilterDataView, - device::UsbDeviceFilter> { - static bool has_vendor_id(const device::UsbDeviceFilter& filter) { - return filter.vendor_id.has_value(); - } - - static uint16_t vendor_id(const device::UsbDeviceFilter& filter) { - return filter.vendor_id.value_or(0); - } - - static bool has_product_id(const device::UsbDeviceFilter& filter) { - return filter.product_id.has_value(); - } - - static uint16_t product_id(const device::UsbDeviceFilter& filter) { - return filter.product_id.value_or(0); - } - - static bool has_class_code(const device::UsbDeviceFilter& filter) { - return filter.interface_class.has_value(); - } - - static uint8_t class_code(const device::UsbDeviceFilter& filter) { - return filter.interface_class.value_or(0); - } - - static bool has_subclass_code(const device::UsbDeviceFilter& filter) { - return filter.interface_subclass.has_value(); - } - - static uint8_t subclass_code(const device::UsbDeviceFilter& filter) { - return filter.interface_subclass.value_or(0); - } - - static bool has_protocol_code(const device::UsbDeviceFilter& filter) { - return filter.interface_protocol.has_value(); - } - - static uint8_t protocol_code(const device::UsbDeviceFilter& filter) { - return filter.interface_protocol.value_or(0); - } - - static const base::Optional<std::string>& serial_number( - const device::UsbDeviceFilter& filter) { - return filter.serial_number; - } - - static bool Read(device::mojom::UsbDeviceFilterDataView input, - device::UsbDeviceFilter* output); -}; - -} // namespace mojo - -#endif // DEVICE_USB_PUBLIC_INTERFACES_DEVICE_MANAGER_STRUCT_TRAITS_H_
diff --git a/device/usb/public/interfaces/typemaps.gni b/device/usb/public/interfaces/typemaps.gni deleted file mode 100644 index 6938fc9a..0000000 --- a/device/usb/public/interfaces/typemaps.gni +++ /dev/null
@@ -1,5 +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. - -typemaps = [ "//device/usb/public/interfaces/device_manager.typemap" ]
diff --git a/device/usb/usb_device_filter.cc b/device/usb/usb_device_filter.cc deleted file mode 100644 index 3d637228..0000000 --- a/device/usb/usb_device_filter.cc +++ /dev/null
@@ -1,101 +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 "device/usb/usb_device_filter.h" - -#include <memory> -#include <utility> - -#include "base/memory/ptr_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/values.h" -#include "device/usb/usb_descriptors.h" -#include "device/usb/usb_device.h" - -namespace device { - -namespace { - -const char kProductIdKey[] = "productId"; -const char kVendorIdKey[] = "vendorId"; -const char kInterfaceClassKey[] = "interfaceClass"; -const char kInterfaceSubclassKey[] = "interfaceSubclass"; -const char kInterfaceProtocolKey[] = "interfaceProtocol"; - -} // namespace - -UsbDeviceFilter::UsbDeviceFilter() = default; - -UsbDeviceFilter::UsbDeviceFilter(const UsbDeviceFilter& other) = default; - -UsbDeviceFilter::~UsbDeviceFilter() = default; - -bool UsbDeviceFilter::Matches(const UsbDevice& device) const { - if (vendor_id) { - if (device.vendor_id() != *vendor_id) - return false; - - if (product_id && device.product_id() != *product_id) - return false; - } - - if (serial_number && - device.serial_number() != base::UTF8ToUTF16(*serial_number)) { - return false; - } - - if (interface_class) { - for (const UsbConfigDescriptor& config : device.configurations()) { - for (const UsbInterfaceDescriptor& iface : config.interfaces) { - if (iface.interface_class == *interface_class && - (!interface_subclass || - (iface.interface_subclass == *interface_subclass && - (!interface_protocol || - iface.interface_protocol == *interface_protocol)))) { - return true; - } - } - } - - return false; - } - - return true; -} - -std::unique_ptr<base::Value> UsbDeviceFilter::ToValue() const { - auto obj = base::MakeUnique<base::DictionaryValue>(); - - if (vendor_id) { - obj->SetInteger(kVendorIdKey, *vendor_id); - if (product_id) - obj->SetInteger(kProductIdKey, *product_id); - } - - if (interface_class) { - obj->SetInteger(kInterfaceClassKey, *interface_class); - if (interface_subclass) { - obj->SetInteger(kInterfaceSubclassKey, *interface_subclass); - if (interface_protocol) - obj->SetInteger(kInterfaceProtocolKey, *interface_protocol); - } - } - - return std::move(obj); -} - -// static -bool UsbDeviceFilter::MatchesAny(const UsbDevice& device, - const std::vector<UsbDeviceFilter>& filters) { - if (filters.empty()) - return true; - - for (const auto& filter : filters) { - if (filter.Matches(device)) - return true; - } - return false; -} - -} // namespace device
diff --git a/device/usb/usb_device_filter.h b/device/usb/usb_device_filter.h deleted file mode 100644 index 666f732..0000000 --- a/device/usb/usb_device_filter.h +++ /dev/null
@@ -1,48 +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. - -#ifndef DEVICE_USB_USB_DEVICE_FILTER_H_ -#define DEVICE_USB_USB_DEVICE_FILTER_H_ - -#include <stdint.h> - -#include <memory> -#include <string> -#include <vector> - -#include "base/optional.h" - -namespace base { -class Value; -} - -namespace device { - -class UsbDevice; - -struct UsbDeviceFilter { - UsbDeviceFilter(); - UsbDeviceFilter(const UsbDeviceFilter& other); - ~UsbDeviceFilter(); - - // Returns true if |device| matches this filter. - bool Matches(const UsbDevice& device) const; - std::unique_ptr<base::Value> ToValue() const; - - // Returns true if device matches any filter in |filters|, or if |filters| is - // empty. - static bool MatchesAny(const UsbDevice& device, - const std::vector<UsbDeviceFilter>& filters); - - base::Optional<uint16_t> vendor_id; - base::Optional<uint16_t> product_id; - base::Optional<uint8_t> interface_class; - base::Optional<uint8_t> interface_subclass; - base::Optional<uint8_t> interface_protocol; - base::Optional<std::string> serial_number; -}; - -} // namespace device - -#endif // DEVICE_USB_USB_DEVICE_FILTER_H_
diff --git a/device/usb/usb_device_filter_unittest.cc b/device/usb/usb_device_filter_unittest.cc deleted file mode 100644 index dd7840e0..0000000 --- a/device/usb/usb_device_filter_unittest.cc +++ /dev/null
@@ -1,140 +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 <string> -#include <vector> - -#include "base/memory/ref_counted.h" -#include "device/usb/mock_usb_device.h" -#include "device/usb/usb_descriptors.h" -#include "device/usb/usb_device_filter.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace device { - -namespace { - -using testing::Return; - -class UsbFilterTest : public testing::Test { - public: - void SetUp() override { - UsbConfigDescriptor config(1, false, false, 0); - config.interfaces.emplace_back(1, 0, 0xff, 0x42, 0x01); - - android_phone_ = new MockUsbDevice(0x18d1, 0x4ee2, "Google Inc.", "Nexus 5", - "ABC123", {config}); - } - - protected: - scoped_refptr<MockUsbDevice> android_phone_; -}; - -TEST_F(UsbFilterTest, MatchAny) { - UsbDeviceFilter filter; - ASSERT_TRUE(filter.Matches(*android_phone_)); -} - -TEST_F(UsbFilterTest, MatchVendorId) { - UsbDeviceFilter filter; - filter.vendor_id = 0x18d1; - ASSERT_TRUE(filter.Matches(*android_phone_)); -} - -TEST_F(UsbFilterTest, MatchVendorIdNegative) { - UsbDeviceFilter filter; - filter.vendor_id = 0x1d6b; - ASSERT_FALSE(filter.Matches(*android_phone_)); -} - -TEST_F(UsbFilterTest, MatchProductId) { - UsbDeviceFilter filter; - filter.vendor_id = 0x18d1; - filter.product_id = 0x4ee2; - ASSERT_TRUE(filter.Matches(*android_phone_)); -} - -TEST_F(UsbFilterTest, MatchProductIdNegative) { - UsbDeviceFilter filter; - filter.vendor_id = 0x18d1; - filter.product_id = 0x4ee1; - ASSERT_FALSE(filter.Matches(*android_phone_)); -} - -TEST_F(UsbFilterTest, MatchInterfaceClass) { - UsbDeviceFilter filter; - filter.interface_class = 0xff; - ASSERT_TRUE(filter.Matches(*android_phone_)); -} - -TEST_F(UsbFilterTest, MatchInterfaceClassNegative) { - UsbDeviceFilter filter; - filter.interface_class = 0xe0; - ASSERT_FALSE(filter.Matches(*android_phone_)); -} - -TEST_F(UsbFilterTest, MatchInterfaceSubclass) { - UsbDeviceFilter filter; - filter.interface_class = 0xff; - filter.interface_subclass = 0x42; - ASSERT_TRUE(filter.Matches(*android_phone_)); -} - -TEST_F(UsbFilterTest, MatchInterfaceSubclassNegative) { - UsbDeviceFilter filter; - filter.interface_class = 0xff; - filter.interface_subclass = 0x01; - ASSERT_FALSE(filter.Matches(*android_phone_)); -} - -TEST_F(UsbFilterTest, MatchInterfaceProtocol) { - UsbDeviceFilter filter; - filter.interface_class = 0xff; - filter.interface_subclass = 0x42; - filter.interface_protocol = 0x01; - ASSERT_TRUE(filter.Matches(*android_phone_)); -} - -TEST_F(UsbFilterTest, MatchInterfaceProtocolNegative) { - UsbDeviceFilter filter; - filter.interface_class = 0xff; - filter.interface_subclass = 0x42; - filter.interface_protocol = 0x02; - ASSERT_FALSE(filter.Matches(*android_phone_)); -} - -TEST_F(UsbFilterTest, MatchSerialNumber) { - UsbDeviceFilter filter; - filter.serial_number = std::string("ABC123"); - EXPECT_TRUE(filter.Matches(*android_phone_)); - filter.vendor_id = 0x18d1; - EXPECT_TRUE(filter.Matches(*android_phone_)); - filter.vendor_id = 0x18d2; - EXPECT_FALSE(filter.Matches(*android_phone_)); - filter.vendor_id = 0x18d1; - filter.serial_number = std::string("DIFFERENT"); - EXPECT_FALSE(filter.Matches(*android_phone_)); -} - -TEST_F(UsbFilterTest, MatchAnyEmptyList) { - std::vector<UsbDeviceFilter> filters; - ASSERT_TRUE(UsbDeviceFilter::MatchesAny(*android_phone_, filters)); -} - -TEST_F(UsbFilterTest, MatchesAnyVendorId) { - std::vector<UsbDeviceFilter> filters(1); - filters.back().vendor_id = 0x18d1; - ASSERT_TRUE(UsbDeviceFilter::MatchesAny(*android_phone_, filters)); -} - -TEST_F(UsbFilterTest, MatchesAnyVendorIdNegative) { - std::vector<UsbDeviceFilter> filters(1); - filters.back().vendor_id = 0x1d6b; - ASSERT_FALSE(UsbDeviceFilter::MatchesAny(*android_phone_, filters)); -} - -} // namespace - -} // namespace device
diff --git a/docs/speed/README.md b/docs/speed/README.md index 7c7ac07c..7421f550 100644 --- a/docs/speed/README.md +++ b/docs/speed/README.md
@@ -3,9 +3,11 @@ ## Contact information * **Contact**: **speed@chromium.org** - * **Escalation**: rschoen@chromium.org (PM), benhenry@chromium.org (TPM), - parisa@chromium.org (eng director) - * **[File a bug](https://bugs.chromium.org/p/chromium/issues/entry?template=Speed%20Bug)** + * **Escalation**: + * benhenry@chromium.org (TPM) + * rschoen@chromium.org (PM) + * parisa@chromium.org (eng director) + * **File a bug**: [template](https://bugs.chromium.org/p/chromium/issues/entry?template=Speed%20Bug) * **Regression postmortem**: [template](https://docs.google.com/document/d/1fvfhFNOoUL9rB0XAEe1MYefyM_9yriR1IPjdxdm7PaQ/edit?disco=AAAABKdHwCg) ## User Docs @@ -19,7 +21,7 @@ ## Core Teams and Work - * **[Performance tracks](performance_tracks.md)**: Most of the performance + * **[Speed tracks](speed_tracks.md)**: Most of the speed work on Chrome is organized into these tracks. * **[Chrome Speed Operations](chrome_speed_operations.md)**: provides the benchmarks, infrastructure, and releasing oversight to track regressions. @@ -30,4 +32,4 @@ * Performance dashboard, bisect, try jobs: speed-services-dev@chromium.org * **[Chrome Speed Metrics](https://docs.google.com/document/d/1wBT5fauGf8bqW2Wcg2A5Z-3_ZvgPhE8fbp1Xe6xfGRs/edit#heading=h.8ieoiiwdknwt)**: provides a set of high-quality metrics that represent real-world user experience, and exposes these metrics to both Chrome and Web Developers. * General discussion: progressive-web-metrics@chromium.org - * The actual metrics: [tracking](https://docs.google.com/spreadsheets/d/1gY5hkKPp8RNVqmOw1d-bo-f9EXLqtq4wa3Z7Q8Ek9Tk/edit#gid=0) \ No newline at end of file + * The actual metrics: [tracking](https://docs.google.com/spreadsheets/d/1gY5hkKPp8RNVqmOw1d-bo-f9EXLqtq4wa3Z7Q8Ek9Tk/edit#gid=0)
diff --git a/docs/speed/adding_tests_bots.md b/docs/speed/adding_tests_bots.md new file mode 100644 index 0000000..259a34f0 --- /dev/null +++ b/docs/speed/adding_tests_bots.md
@@ -0,0 +1,11 @@ +# Adding tests and bots + +## Adding performance tests + +See the +[new benchmark policy](https://docs.google.com/document/d/1ni2MIeVnlH4bTj4yvEDMVNxgL73PqK_O9_NUm3NW3BA/edit) + +## Adding hardware + +This documentation is under construction. In the meantime, please reach out to +benchmarking-dev@chromium.org. \ No newline at end of file
diff --git a/docs/speed/addressing_performance_regressions.md b/docs/speed/addressing_performance_regressions.md index dd75ce1..f012a04 100644 --- a/docs/speed/addressing_performance_regressions.md +++ b/docs/speed/addressing_performance_regressions.md
@@ -3,6 +3,8 @@ The bisect bot just picked your CL as the culprit in a performance regression and assigned a bug to you! What should you do? Read on... +[TOC] + ## About our performance tests The [chromium.perf waterfall](perf_waterfall.md) is a continuous build which @@ -12,7 +14,7 @@ than what you tested locally before landing your CL. Each test has an owner, named in -[this spreasheet](https://docs.google.com/spreadsheets/d/1xaAo0_SU3iDfGdqDJZX_jRV0QtkufwHUKH3kQKF3YQs/edit#gid=0), +[this spreadsheet](https://docs.google.com/spreadsheets/d/1xaAo0_SU3iDfGdqDJZX_jRV0QtkufwHUKH3kQKF3YQs/edit#gid=0), who you can cc on a performance bug if you have questions. ## Understanding the bisect results @@ -61,7 +63,7 @@ * **How do I run that locally?** Follow the instructions under `To Run This Test`. But be aware that if it regressed on Android and you're developing on Windows, you may not be able to reproduce locally. - (See Debugging regressions below) + (See [Debugging regressions](#Debugging-regressions) below) * **What is this testing?** Generally the metric (`timeToFirstContentfulPaint_avg`) gives some information. If you're not familiar, you can cc the [benchmark owner](https://docs.google.com/spreadsheets/d/1xaAo0_SU3iDfGdqDJZX_jRV0QtkufwHUKH3kQKF3YQs/edit#gid=0) @@ -178,7 +180,7 @@ be measured well in benchmarks. If you believe your case falls into this category, you can show that end users are not affected via a finch trial. See the "End-user metrics" section of - [How does Chrome measure performance](how_does_chrome_measure_performance.md) + [How Chrome measures performance](how_does_chrome_measure_performance.md#End_user-metrics) * **Your change is a critical correctness or security fix.** It's true that sometimes something was "fast" because it was implemented incorrectly. In this case, a justification should clarify the performance
diff --git a/docs/speed/bisects.md b/docs/speed/bisects.md new file mode 100644 index 0000000..91ced32 --- /dev/null +++ b/docs/speed/bisects.md
@@ -0,0 +1,126 @@ +# Bisecting Performance Regressions + +[TOC] + +## What are performance bisects? + +The perf tests on chromium's continuous build are very long-running, so we +cannot run them on every revision. Further, separate repositories like v8 +and skia sometimes roll multiple performance-sensitive changes into chromium +at once. For these reasons, we need a tool that can bisect the root cause of +performance regressions over a CL range, descending into third_party +repositories as necessary. This is what the performance bisect bots do. + +The team is currently working on a new version of performance biscect called +[pinpoint](https://docs.google.com/document/d/1FKPRNU2kbPJ15p6XHO0itCjYtfvCpGt2IHblriTX1tg/edit) + +## Starting a perf bisect + +Performance bisects are tightly integrated with the +[Chrome Performance Dashboard](https://chromeperf.appspot.com/alerts) and +[monorail](https://bugs.chromium.org/p/chromium/issues/list). Users kick off +perf bisects on the perf dashboard and view results in monorail. + +You can kick off a perf bisect anywhere you see a performance graph on the perf +dashboard (except for some tests which don't bisect, because they do not run on +the [chromium.perf waterfall](https://build.chromium.org/p/chromium.perf/waterfall)). + +### To get to a graph, use one of the following methods: + + * From a perf sheriff-filed bug, follow the link in #1 that looks like + `https://chromeperf.appspot.com/group_report?bug_id=XXXXXX`. Check the + boxes next to alerts in the table to display graphs. + * From the [alerts page](https://chromeperf.appspot.com/alerts), check the + box next to an alert and click the `Graph` button. + * From the [report page](https://chromeperf.appspot.com/report), use the menu + to navigate to the graph you want. + +### To kick off a bisect from the graph: + + + + + 1. Click on a data point in the graph. + 2. In the tooltip that shows up, click the `BISECT` button. + 3. Make sure to enter a Bug ID in the dialog that comes up. + 4. Click the `START BISECT` button. + +### What are all the boxes in the form? + + * **Bisect bot**: The name of the configuration in the perf lab to bisect on. + This has been prefilled to match the bot that generated the graph as + closely as possible. + * **Metric**: The metric of the performance test to bisect. This defaults to + the metric shown on the graph. It shows a list of other related metrics + (for example, if average page load time increased, the drop down will show + a list of individual pages which were measured). + * **Story filter**: This is a flag specific to + [telemetry](https://github.com/catapult-project/catapult/blob/master/telemetry/README.md). + It tells telemetry to only run a specific test case, instead of running all + the test cases in the suite. This dramatically reduces bisect time for + large test suites. The dashboard will prefill this box based on the graph + you clicked on. If you suspect that test cases in the benchmark are not + independent, you can try bisecting with this box cleared. + * **Bug ID**: The bug number in monorail. It's very important to fill in + this field, as this is where bisect results will be posted. + * **Earlier revision**: The chromium commit pos to start bisecting from. This + is prefilled by the dashboard to the start of the revision range for the + point you clicked on. You can set it to an earlier commit position to + bisect a larger range. + * **Later revision**: The chromium commit pos to bisect to. This is prefilled + by the dashboard to the end of the revision range for the point you clicked + on. You can set it to a later commit pos to bisect a larger range. + * **Launch on staging bots**: This is an internal feature, which allows the + bisect team to launch a bisect on a test configuration. You likely don't + want to check this box unless instructed by the bisect team. + * **Bisect mode**: use "mean" to bisect the mean value of the performance + test. See below for "return_code". + +## Bisecting test failures + +The perf bisect bots can also be used to bisect performance test failures. +See details in [Triaging Data Stoppage Alerts](triaging_data_stoppage_alerts.md). + +## Interpreting the results + +The bisect bot will output a comment on the bug you input into the dialog when +bisection is complete. See the +[Understanding the Bisect Results](addressing_performance_regressions.md#Understanding-the-bisect-results) +section of the Addressing Performance Regressions doc for details on how to +interpret the results. + +## Getting more debugging data + +The bisect outputs some additional data which might be useful for really tough +regressions or confusing results. + +### Traces + +Chrome traces are generated by most bisects and uploaded to cloud storage, but +they're not very visible in the UI. We plan to address this in +[pinpoint](https://docs.google.com/document/d/1FKPRNU2kbPJ15p6XHO0itCjYtfvCpGt2IHblriTX1tg/edit), +but in the short term here are the steps to get the traces from a bisect: + + 1. The bisect comment should have a "Debug Info" link that looks like this: + `https://chromeperf.appspot.com/buildbucket_job_status/8980436717323504240` + Click it. + 2. In the debug info, you should see a "Buildbot link" that looks like this: + `https://build.chromium.org/p/tryserver.chromium.perf/builders/android_nexus7_perf_bisect/builds/4097` + Click it. + 3. There will be several steps on the buildbot status page named "Bisecting + Revision". Each has an annotation like "Revision: chromium@474894" so you + can tell which revision it ran. Pick the commit position you want the + trace from (usually the one at your CL and the one immediately before). + Click the arrow by "> Nested step(s) for: Bisecting revision..." on those + steps. + 4. In the nested steps, you'll see several steps titled "Bisecting + revision.Performance Test X of Y". These are the actual perf test runs. + Click the "stdout" link for one of these steps. + 5. In the output, do a text search for "View generated trace files online" + and you'll see a link to a trace that looks like this: + `https://console.developers.google.com/m/cloudstorage/b/chrome-telemetry-output/o/trace-file-id_0-2017-05-05_05-41-49-83206.html` + +Here are some screenshots showing what to click on: + + + \ No newline at end of file
diff --git a/docs/speed/help_improve_performance.md b/docs/speed/help_improve_performance.md new file mode 100644 index 0000000..0003608 --- /dev/null +++ b/docs/speed/help_improve_performance.md
@@ -0,0 +1,23 @@ +# Chrome is slow, what do I do? + +## How to file a bug + + * **File a bug.** To file a bug, please use +**[the speed bug template](https://bugs.chromium.org/p/chromium/issues/entry?template=Speed%20Bug)**. + * **Attach a trace.** The best way to get performance data to developers is to include a trace, + so please [follow these instructions](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool/recording-tracing-runs) + to record a trace and attach it to the bug. + * **Try TraceOnTap** the [TraceOnTap Extension](http://goto.google.com/traceontap) + makes it easier to record traces and attach them to bugs. + [Source code](https://github.com/catapult-project/catapult/tree/master/experimental/trace_on_tap) + +<!--- TODO: ## Bug SLO for perf bugs --> + +<!--- TODO: ## Bug Triage +### High level +### Best practices +### 3 step approach to Speed Triage +### Rotation Documentation +### Bug Dashboards +### Fixits +--> \ No newline at end of file
diff --git a/docs/speed/how_does_chrome_measure_performance.md b/docs/speed/how_does_chrome_measure_performance.md index 6b61984..5f93a6e6 100644 --- a/docs/speed/how_does_chrome_measure_performance.md +++ b/docs/speed/how_does_chrome_measure_performance.md
@@ -10,8 +10,8 @@ like loading, memory, and power. Each track has high-level metrics associated with it. - * **[An overview of tracks](performance_tracks.md)**: lists the tracks and key contact points. - * **[Speed Launch Metrics](https://docs.google.com/document/d/1Ww487ZskJ-xBmJGwPO-XPz_QcJvw-kSNffm0nPhVpj8/edit): + * **[An overview of tracks](speed_tracks.md)**: lists the tracks and key contact points. + * **[Speed Launch Metrics](https://docs.google.com/document/d/1Ww487ZskJ-xBmJGwPO-XPz_QcJvw-kSNffm0nPhVpj8/edit)**: the important high-level metrics we measure for each track. ## Laboratory Metrics @@ -26,11 +26,11 @@ * **[What is the perf waterfall?](perf_waterfall.md)** An overview of the waterfall that runs the continuous build. - * **[How telemetry works](https://github.com/catapult-project/catapult/blob/master/telemetry/README.md): + * **[How telemetry works](https://github.com/catapult-project/catapult/blob/master/telemetry/README.md)**: An overview of telemetry, our performance testing harness. - * **[How perf bisects work](bisects.md): An overview of the bisect bots, + * **[How perf bisects work](bisects.md)**: An overview of the bisect bots, which narrow down regressions over a CL range to a specific commit. - * **Benchmarks* + * **Benchmarks** * **[Benchmark Policy](https://docs.google.com/document/d/1ni2MIeVnlH4bTj4yvEDMVNxgL73PqK_O9_NUm3NW3BA/edit)**: An overview of the benchmark harnesses available in Chrome, and how to find the right place to add a new test case. @@ -60,4 +60,4 @@ The **[Speed Launch Metrics](https://docs.google.com/document/d/1Ww487ZskJ-xBmJGwPO-XPz_QcJvw-kSNffm0nPhVpj8/edit)** doc explains metrics available in UMA for end user performance. If you want to test how your change impacts these metrics for end users, you'll probably want -to **[Run a Finch Trial](http://goto.google.com/finch101)**. \ No newline at end of file +to **[Run a Finch Trial](http://goto.google.com/finch101)**.
diff --git a/docs/speed/images/bisect_dialog.png b/docs/speed/images/bisect_dialog.png new file mode 100644 index 0000000..f2c4edb --- /dev/null +++ b/docs/speed/images/bisect_dialog.png Binary files differ
diff --git a/docs/speed/images/bisect_graph.png b/docs/speed/images/bisect_graph.png new file mode 100644 index 0000000..1db1be46 --- /dev/null +++ b/docs/speed/images/bisect_graph.png Binary files differ
diff --git a/docs/speed/images/bisect_stdout.png b/docs/speed/images/bisect_stdout.png new file mode 100644 index 0000000..51b1970 --- /dev/null +++ b/docs/speed/images/bisect_stdout.png Binary files differ
diff --git a/docs/speed/images/bisecting_revision_step.png b/docs/speed/images/bisecting_revision_step.png new file mode 100644 index 0000000..b1379baf --- /dev/null +++ b/docs/speed/images/bisecting_revision_step.png Binary files differ
diff --git a/docs/speed/perf_trybots.md b/docs/speed/perf_trybots.md new file mode 100644 index 0000000..181b9e3 --- /dev/null +++ b/docs/speed/perf_trybots.md
@@ -0,0 +1,94 @@ +# Perf Try Bots + +[TOC] + +## What are perf try bots? + +Chrome has a performance lab with dozens of device and OS configurations. You +can run performance tests on an unsubmitted CL on these devices using the +perf try bots. + +## Supported platforms + +The platforms available in the lab change over time. To find the currently +available platforms, run `tools/perf/run_benchmark try --help`. + +Example output: + +``` +> tools/perf/run_benchmark try --help +usage: Run telemetry benchmarks on trybot. You can add all the benchmark options available except the --browser option + [-h] [--repo_path <repo path>] [--deps_revision <deps revision>] + <trybot name> <benchmark name> + +positional arguments: + <trybot name> specify which bots to run telemetry benchmarks on. Allowed values are: + Mac Builder + all + all-android + all-linux + all-mac + all-win + android-fyi + android-nexus5 + android-nexus5X + android-nexus6 + android-nexus7 + android-one + android-webview-arm64-aosp + android-webview-nexus6-aosp + linux + mac-10-11 + mac-10-12 + mac-10-12-mini-8gb + mac-air + mac-pro + mac-retina + staging-android-nexus5X + staging-linux + staging-mac-10-12 + staging-win + win + win-8 + win-x64 + winx64-10 + winx64-high-dpi + winx64-zen + winx64ati + winx64intel + winx64nvidia + +``` + +## Supported benchmarks + +All the telemetry benchmarks are supported by the perf trybots. To get a full +list, run `tools/perf/run_benchmark list`. + +To learn more about the benchmark, you can read about the +[system health benchmarks](https://docs.google.com/document/d/1BM_6lBrPzpMNMtcyi2NFKGIzmzIQ1oH3OlNG27kDGNU/edit?ts=57e92782), +which test Chrome's performance at a high level, and the +[benchmark harnesses](https://docs.google.com/spreadsheets/d/1ZdQ9OHqEjF5v8dqNjd7lGUjJnK6sgi8MiqO7eZVMgD0/edit#gid=0), +which cover more specific areas. + +## Starting a perf try job + +Use this command line: + +`tools/perf/run_benchmark try <trybot_name> <benchmark_name>` + +See above for how to choose a trybot and benchmark. + +Run `tools/perf/run_benchmark try --help` for more information about available +options. + +## Interpreting the results + +Perf trybots create a code review under the covers to hold the trybot results. +The code review will list links to buildbot status pages for the try jobs. +On each buildbot status page, you will see a "HTML Results" link. You can click +it to see detailed information about the performance test results with and +without your patch. + +**[Here is the documentation](https://github.com/catapult-project/catapult/blob/master/docs/metrics-results-ui.md)** +on reading the results. \ No newline at end of file
diff --git a/docs/speed/perf_waterfall.md b/docs/speed/perf_waterfall.md new file mode 100644 index 0000000..a8df529 --- /dev/null +++ b/docs/speed/perf_waterfall.md
@@ -0,0 +1,30 @@ +# chromium.perf Waterfall + +## Overview + +The [chromium.perf waterfall](http://build.chromium.org/p/chromium.perf/waterfall) +continuously builds and runs our performance tests on real Android, Windows, +Mac, and Linux hardware. Results are reported to the +[Performance Dashboard](https://chromeperf.appspot.com/) for analysis. The +[Perfbot Health Sheriffing Rotation](perf_bot_sheriffing.md) keeps the build +green and files bugs on regressions. They maintain +[Chrome's Core Principles](https://www.chromium.org/developers/core-principles) +of speed: + +> "If you make a change that regresses measured performance, you will be +> required to fix it or revert". + +## Contact + + * You can reach the Chromium performance sheriffs at perf-sheriffs@chromium.org. + * Bugs on waterfall issues should have Component: + [Speed>Benchmarks>Waterfall](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=component%3ASpeed%3EBenchmarks%3EWaterfall+&colspec=ID+Pri+M+Stars+ReleaseBlock+Component+Status+Owner+Summary+OS+Modified&x=m&y=releaseblock&cells=ids). + +## Links + + * [Perfbot Health Sheriffing Rotation](perf_bot_sheriffing.md) + * [Debugging an Android Perf Failure](perf_bot_sheriffing.md#Android-Device-failures) + * TODO: Page on how to repro failures locally + * TODO: Page on how to connect to bot in lab + * TODO: Page on how to hack on buildbot/recipe code + * TODO: Page on bringing up new hardware \ No newline at end of file
diff --git a/docs/speed/speed_tracks.md b/docs/speed/speed_tracks.md new file mode 100644 index 0000000..daf5e27a --- /dev/null +++ b/docs/speed/speed_tracks.md
@@ -0,0 +1,98 @@ +# Speed Tracks + +We've organized our focus into tracks to address the following concerns: + + * Utilize domain expertise to manage incoming bugs and regression reports + * Have a clear escalation paths + * Organize optimization efforts as needed + * Identify opportunities for improvement and to manage projects + +## Tracks Organization + +### Memory + +This track deals with memory use by Chrome on all platforms. Primary focus is: + + * Gracefully deal with situations where user is out of memory (OOM) + * Manage memory for idle and backgrounded tabs + +#### Links + + * [Mailing List](https://groups.google.com/a/chromium.org/forum/#!forum/memory-dev) + * Performance-Memory [Bug + Queue](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=Performance%3DMemory) + * [Docs](https://chromium.googlesource.com/chromium/src/+/master/docs/memory) + +### Power + +The Power track is concerned with improving power usage for our users. +Collectively, our product has an impact on global greenhouse gas imitions and we +want to do our best to make that efficient. If we can give users a good +experience of not burning laps/hands or making fan noises, we feel like we did a +good job. + +#### Links + + * Performance-Power [Bug + Queue](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=Performance%3DPower) + +### Loading + +The Loading track focuses on the time between click to the time when you can +interact with a website. + +#### Links + + * [Mailing + List](https://groups.google.com/a/chromium.org/forum/#!forum/loading-dev) + * Performance-Loading [Bug + Queue](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=Performance%3DLoading) + +### Responsiveness + +Responsiveness track focuses on making sure all websites have smooth transitions +by serving 60fps, and that the click to action time is not noticible. + +#### Links + + * Performance-Responsiveness [Bug + Queue](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=Performance%3DResponsiveness) + +### Binary Size + +Chrome has an update for you at least every six weeks. Since we do that for all +of our users, we want to be nice to our users where downloading updates costs +real money. We also don't want to hog all of the disk space on low end phones. +So we focus attention on making sure we don't include bits in our update that +are not necessary for users. + +#### Links + + * [Mailing List](://groups.google.com/a/chromium.org/forum/#!forum/binary-size) + * Performance-Size [Bug + Queue](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=Performance%3DSize) + +### Data Usage + +Data Usage is a focus on the question: Do the user see or need every byte +downloaded? By looking at this, we can save user's cost of data, time to load, +memory and power. + +#### Links + + * Performance-Data [Bug + Queue](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=Performance%3DData) + +### Startup, Omnibox, Browser UI, etc. + +There are a handful of performance angles that don't fit into the tracks already +mentioned. Historically, we've put these into a "Browser" bucket as that's +descriptive of what's left over. These are things like making sure the Omnibox +experience on Chrome is fast, making sure all of the Chrome UI, e.g. Settings, +is fast and that the browser startup and session restore doesn't allow users to +make coffee before they use the browser. + +#### Links + + * Performance-Browser [Bug + Queue](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=Performance%3DBrowser)
diff --git a/docs/webui_explainer.md b/docs/webui_explainer.md index bd298d96..e9a9284 100644 --- a/docs/webui_explainer.md +++ b/docs/webui_explainer.md
@@ -118,8 +118,8 @@ ```c++ // RenderFrameHostImpl::AllowBindings(): if (bindings_flags & BINDINGS_POLICY_WEB_UI) { - ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings( - GetProcess()->GetID()); + ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings( + GetProcess()->GetID()); } ``` @@ -449,7 +449,7 @@ ```c++ // WebUIMessageHandler::RejectJavascriptCallback(): CallJavascriptFunction("cr.webUIResponse", callback_id, base::Value(false), - response); + response); ``` See also: [`ResolveJavascriptCallback`](#ResolveJavascriptCallback) @@ -503,10 +503,10 @@ ```c++ // WebUIExtension::Install(): v8::Local<v8::Object> chrome = - GetOrCreateChromeObject(isolate, context->Global()); + GetOrCreateChromeObject(isolate, context->Global()); chrome->Set(gin::StringToSymbol(isolate, "send"), - gin::CreateFunctionTemplate( - isolate, base::Bind(&WebUIExtension::Send))->GetFunction()); + gin::CreateFunctionTemplate( + isolate, base::Bind(&WebUIExtension::Send))->GetFunction()); ``` The `chrome.send()` method takes a message name and argument list. @@ -521,8 +521,8 @@ ```c++ // In the renderer (WebUIExtension::Send()): render_view->Send(new ViewHostMsg_WebUISend(render_view->GetRoutingID(), - frame->GetDocument().Url(), - message, *content)); + frame->GetDocument().Url(), + message, *content)); ``` ```c++ // In the browser (WebUIImpl::OnMessageReceived()):
diff --git a/extensions/browser/api/cast_channel/cast_channel_api.cc b/extensions/browser/api/cast_channel/cast_channel_api.cc index 89273a0..bdbea33 100644 --- a/extensions/browser/api/cast_channel/cast_channel_api.cc +++ b/extensions/browser/api/cast_channel/cast_channel_api.cc
@@ -164,15 +164,6 @@ return browser_context_; } -void CastChannelAPI::SetPingTimeoutTimerForTest( - std::unique_ptr<base::Timer> timer) { - injected_timeout_timer_ = std::move(timer); -} - -std::unique_ptr<base::Timer> CastChannelAPI::GetInjectedTimeoutTimerForTest() { - return std::move(injected_timeout_timer_); -} - CastChannelAPI::~CastChannelAPI() {} CastChannelAsyncApiFunction::CastChannelAsyncApiFunction() @@ -297,7 +288,7 @@ base::TimeDelta::FromMilliseconds(connect_info.timeout.get() ? *connect_info.timeout : kDefaultConnectTimeoutMillis), - liveness_timeout_ > base::TimeDelta(), api_->GetLogger(), + liveness_timeout_, ping_interval_, api_->GetLogger(), connect_info.capabilities.get() ? *connect_info.capabilities : CastDeviceCapability::NONE); } @@ -309,20 +300,6 @@ base::Bind(&CastChannelAPI::SendEvent, api_->AsWeakPtr(), extension_->id()), socket, api_->GetLogger())); - if (socket->keep_alive()) { - // Wrap read delegate in a KeepAliveDelegate for timeout handling. - KeepAliveDelegate* keep_alive = - new KeepAliveDelegate(socket, api_->GetLogger(), std::move(delegate), - ping_interval_, liveness_timeout_); - std::unique_ptr<base::Timer> injected_timer = - api_->GetInjectedTimeoutTimerForTest(); - if (injected_timer) { - keep_alive->SetTimersForTest(base::MakeUnique<base::Timer>(false, false), - std::move(injected_timer)); - } - delegate.reset(keep_alive); - } - socket->Connect(std::move(delegate), base::Bind(&CastChannelOpenFunction::OnOpen, this)); }
diff --git a/extensions/browser/api/cast_channel/cast_channel_api.h b/extensions/browser/api/cast_channel/cast_channel_api.h index 6ac7eff..baecc33 100644 --- a/extensions/browser/api/cast_channel/cast_channel_api.h +++ b/extensions/browser/api/cast_channel/cast_channel_api.h
@@ -65,13 +65,6 @@ // Returns the API browser context. content::BrowserContext* GetBrowserContext() const; - // Sets injected ping timeout timer for testing. - void SetPingTimeoutTimerForTest(std::unique_ptr<base::Timer> timer); - - // Gets the injected ping timeout timer, if set. - // Returns a null scoped ptr if there is no injected timer. - std::unique_ptr<base::Timer> GetInjectedTimeoutTimerForTest(); - // Sends an event to the extension's EventRouter, if it exists. void SendEvent(const std::string& extension_id, std::unique_ptr<Event> event); @@ -88,7 +81,6 @@ content::BrowserContext* const browser_context_; scoped_refptr<cast_channel::Logger> logger_; std::unique_ptr<cast_channel::CastSocket> socket_for_test_; - std::unique_ptr<base::Timer> injected_timeout_timer_; DISALLOW_COPY_AND_ASSIGN(CastChannelAPI); };
diff --git a/extensions/browser/api/cast_channel/cast_channel_apitest.cc b/extensions/browser/api/cast_channel/cast_channel_apitest.cc index b1547902..06d2c82 100644 --- a/extensions/browser/api/cast_channel/cast_channel_apitest.cc +++ b/extensions/browser/api/cast_channel/cast_channel_apitest.cc
@@ -90,8 +90,6 @@ void SetUpMockCastSocket() { extensions::CastChannelAPI* api = GetApi(); - timeout_timer_ = new base::MockTimer(true, false); - api->SetPingTimeoutTimerForTest(base::WrapUnique(timeout_timer_)); net::IPEndPoint ip_endpoint(net::IPAddress(192, 168, 1, 1), 8009); mock_cast_socket_ = new MockCastSocket; @@ -187,7 +185,9 @@ void FireTimeout() { content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&base::MockTimer::Fire, base::Unretained(timeout_timer_))); + base::Bind(&CastTransport::Delegate::OnError, + base::Unretained(message_delegate_), + cast_channel::ChannelError::PING_TIMEOUT)); } extensions::CastChannelOpenFunction* CreateOpenFunction( @@ -207,7 +207,6 @@ } MockCastSocket* mock_cast_socket_; - base::MockTimer* timeout_timer_; net::IPEndPoint ip_endpoint_; LastError last_error_; CastTransport::Delegate* message_delegate_;
diff --git a/extensions/browser/api/device_permissions_prompt.cc b/extensions/browser/api/device_permissions_prompt.cc index 5826de3..eea7746 100644 --- a/extensions/browser/api/device_permissions_prompt.cc +++ b/extensions/browser/api/device_permissions_prompt.cc
@@ -16,8 +16,8 @@ #include "device/hid/hid_device_filter.h" #include "device/hid/hid_device_info.h" #include "device/hid/hid_service.h" +#include "device/usb/public/cpp/filter_utils.h" #include "device/usb/usb_device.h" -#include "device/usb/usb_device_filter.h" #include "device/usb/usb_ids.h" #include "device/usb/usb_service.h" #include "extensions/browser/api/device_permissions_manager.h" @@ -33,7 +33,7 @@ using device::HidDeviceFilter; using device::HidService; using device::UsbDevice; -using device::UsbDeviceFilter; +using device::mojom::UsbDeviceFilterPtr; using device::UsbService; namespace extensions { @@ -73,10 +73,10 @@ const Extension* extension, content::BrowserContext* context, bool multiple, - const std::vector<UsbDeviceFilter>& filters, + std::vector<UsbDeviceFilterPtr> filters, const DevicePermissionsPrompt::UsbDevicesCallback& callback) : Prompt(extension, context, multiple), - filters_(filters), + filters_(std::move(filters)), callback_(callback), service_observer_(this) {} @@ -120,7 +120,7 @@ // device::UsbService::Observer implementation: void OnDeviceAdded(scoped_refptr<UsbDevice> device) override { - if (!UsbDeviceFilter::MatchesAny(*device, filters_)) + if (!UsbDeviceFilterMatchesAny(filters_, *device)) return; std::unique_ptr<DeviceInfo> device_info(new UsbDeviceInfo(device)); @@ -151,7 +151,7 @@ } } - std::vector<UsbDeviceFilter> filters_; + std::vector<UsbDeviceFilterPtr> filters_; DevicePermissionsPrompt::UsbDevicesCallback callback_; ScopedObserver<UsbService, UsbService::Observer> service_observer_; }; @@ -350,10 +350,10 @@ const Extension* extension, content::BrowserContext* context, bool multiple, - const std::vector<UsbDeviceFilter>& filters, + std::vector<UsbDeviceFilterPtr> filters, const UsbDevicesCallback& callback) { prompt_ = new UsbDevicePermissionsPrompt(extension, context, multiple, - filters, callback); + std::move(filters), callback); ShowDialog(); } @@ -382,7 +382,7 @@ DevicePermissionsPrompt::CreateUsbPromptForTest(const Extension* extension, bool multiple) { return make_scoped_refptr(new UsbDevicePermissionsPrompt( - extension, nullptr, multiple, std::vector<UsbDeviceFilter>(), + extension, nullptr, multiple, std::vector<UsbDeviceFilterPtr>(), base::Bind(&NoopUsbCallback))); }
diff --git a/extensions/browser/api/device_permissions_prompt.h b/extensions/browser/api/device_permissions_prompt.h index 40d29dc2..d2502f5 100644 --- a/extensions/browser/api/device_permissions_prompt.h +++ b/extensions/browser/api/device_permissions_prompt.h
@@ -15,6 +15,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/strings/string16.h" +#include "device/usb/public/interfaces/device_manager.mojom.h" namespace content { class BrowserContext; @@ -25,7 +26,6 @@ class HidDeviceFilter; class HidDeviceInfo; class UsbDevice; -struct UsbDeviceFilter; } namespace extensions { @@ -129,7 +129,7 @@ void AskForUsbDevices(const Extension* extension, content::BrowserContext* context, bool multiple, - const std::vector<device::UsbDeviceFilter>& filters, + std::vector<device::mojom::UsbDeviceFilterPtr> filters, const UsbDevicesCallback& callback); void AskForHidDevices(const Extension* extension,
diff --git a/extensions/browser/api/usb/BUILD.gn b/extensions/browser/api/usb/BUILD.gn index 1f90d05..622efa0 100644 --- a/extensions/browser/api/usb/BUILD.gn +++ b/extensions/browser/api/usb/BUILD.gn
@@ -28,6 +28,8 @@ "//content/public/browser", "//content/public/common", "//device/usb", + "//device/usb/public/cpp", + "//device/usb/public/interfaces", "//extensions/common/api", ]
diff --git a/extensions/browser/api/usb/usb_api.cc b/extensions/browser/api/usb/usb_api.cc index c829565..2503c0c 100644 --- a/extensions/browser/api/usb/usb_api.cc +++ b/extensions/browser/api/usb/usb_api.cc
@@ -16,6 +16,8 @@ #include "base/memory/ptr_util.h" #include "base/values.h" #include "device/base/device_client.h" +#include "device/usb/public/cpp/filter_utils.h" +#include "device/usb/public/interfaces/device_manager.mojom.h" #include "device/usb/usb_descriptors.h" #include "device/usb/usb_device_handle.h" #include "device/usb/usb_service.h" @@ -50,11 +52,11 @@ namespace SetInterfaceAlternateSetting = usb::SetInterfaceAlternateSetting; using content::BrowserThread; +using device::mojom::UsbDeviceFilterPtr; using device::UsbConfigDescriptor; using device::UsbControlTransferRecipient; using device::UsbControlTransferType; using device::UsbDevice; -using device::UsbDeviceFilter; using device::UsbDeviceHandle; using device::UsbEndpointDescriptor; using device::UsbInterfaceDescriptor; @@ -369,18 +371,30 @@ return output; } -void ConvertDeviceFilter(const usb::DeviceFilter& input, - UsbDeviceFilter* output) { - if (input.vendor_id) +device::mojom::UsbDeviceFilterPtr ConvertDeviceFilter( + const usb::DeviceFilter& input) { + auto output = device::mojom::UsbDeviceFilter::New(); + if (input.vendor_id) { + output->has_vendor_id = true; output->vendor_id = *input.vendor_id; - if (input.product_id) + } + if (input.product_id) { + output->has_product_id = true; output->product_id = *input.product_id; - if (input.interface_class) - output->interface_class = *input.interface_class; - if (input.interface_subclass) - output->interface_subclass = *input.interface_subclass; - if (input.interface_protocol) - output->interface_protocol = *input.interface_protocol; + } + if (input.interface_class) { + output->has_class_code = true; + output->class_code = *input.interface_class; + } + if (input.interface_subclass) { + output->has_subclass_code = true; + output->subclass_code = *input.interface_subclass; + } + if (input.interface_protocol) { + output->has_protocol_code = true; + output->protocol_code = *input.interface_protocol; + } + return output; } } // namespace @@ -590,16 +604,19 @@ EXTENSION_FUNCTION_VALIDATE(parameters.get()); if (parameters->options.filters) { - filters_.resize(parameters->options.filters->size()); - for (size_t i = 0; i < parameters->options.filters->size(); ++i) { - ConvertDeviceFilter(parameters->options.filters->at(i), &filters_[i]); - } + filters_.reserve(parameters->options.filters->size()); + for (const auto& filter : *parameters->options.filters) + filters_.push_back(ConvertDeviceFilter(filter)); } if (parameters->options.vendor_id) { - filters_.resize(filters_.size() + 1); - filters_.back().vendor_id = *parameters->options.vendor_id; - if (parameters->options.product_id) - filters_.back().product_id = *parameters->options.product_id; + auto filter = device::mojom::UsbDeviceFilter::New(); + filter->has_vendor_id = true; + filter->vendor_id = *parameters->options.vendor_id; + if (parameters->options.product_id) { + filter->has_product_id = true; + filter->product_id = *parameters->options.product_id; + } + filters_.push_back(std::move(filter)); } UsbService* service = device::DeviceClient::Get()->GetUsbService(); @@ -617,7 +634,7 @@ std::unique_ptr<base::ListValue> result(new base::ListValue()); UsbGuidMap* guid_map = UsbGuidMap::Get(browser_context()); for (const scoped_refptr<UsbDevice>& device : devices) { - if (UsbDeviceFilter::MatchesAny(*device, filters_) && + if (UsbDeviceFilterMatchesAny(filters_, *device) && HasDevicePermission(device)) { Device api_device; guid_map->GetApiDevice(device, &api_device); @@ -648,12 +665,11 @@ multiple = *parameters->options.multiple; } - std::vector<UsbDeviceFilter> filters; + std::vector<UsbDeviceFilterPtr> filters; if (parameters->options.filters) { - filters.resize(parameters->options.filters->size()); - for (size_t i = 0; i < parameters->options.filters->size(); ++i) { - ConvertDeviceFilter(parameters->options.filters->at(i), &filters[i]); - } + filters.reserve(parameters->options.filters->size()); + for (const auto& filter : *parameters->options.filters) + filters.push_back(ConvertDeviceFilter(filter)); } prompt_ = ExtensionsAPIClient::Get()->CreateDevicePermissionsPrompt( @@ -663,7 +679,7 @@ } prompt_->AskForUsbDevices( - extension(), browser_context(), multiple, filters, + extension(), browser_context(), multiple, std::move(filters), base::Bind(&UsbGetUserSelectedDevicesFunction::OnDevicesChosen, this)); return RespondLater(); }
diff --git a/extensions/browser/api/usb/usb_api.h b/extensions/browser/api/usb/usb_api.h index ef2086d5..17ad3538 100644 --- a/extensions/browser/api/usb/usb_api.h +++ b/extensions/browser/api/usb/usb_api.h
@@ -14,8 +14,8 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "device/usb/public/interfaces/device_manager.mojom.h" #include "device/usb/usb_device.h" -#include "device/usb/usb_device_filter.h" #include "device/usb/usb_device_handle.h" #include "extensions/browser/api/api_resource_manager.h" #include "extensions/browser/extension_function.h" @@ -102,7 +102,7 @@ void OnGetDevicesComplete( const std::vector<scoped_refptr<device::UsbDevice>>& devices); - std::vector<device::UsbDeviceFilter> filters_; + std::vector<device::mojom::UsbDeviceFilterPtr> filters_; DISALLOW_COPY_AND_ASSIGN(UsbGetDevicesFunction); };
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index 1e0b269..c1edae4 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn
@@ -293,6 +293,7 @@ "//crypto", "//device/bluetooth", "//device/usb", + "//device/usb/public/cpp", "//extensions:extensions_resources", "//extensions/common/api", "//extensions/strings",
diff --git a/extensions/common/api/printer_provider/usb_printer_manifest_data.cc b/extensions/common/api/printer_provider/usb_printer_manifest_data.cc index fc5c466..3812a32 100644 --- a/extensions/common/api/printer_provider/usb_printer_manifest_data.cc +++ b/extensions/common/api/printer_provider/usb_printer_manifest_data.cc
@@ -5,16 +5,16 @@ #include "extensions/common/api/printer_provider/usb_printer_manifest_data.h" #include <memory> +#include <utility> #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" +#include "device/usb/public/cpp/filter_utils.h" +#include "device/usb/public/interfaces/device_manager.mojom.h" #include "device/usb/usb_device.h" -#include "device/usb/usb_device_filter.h" #include "extensions/common/api/extensions_manifest_types.h" #include "extensions/common/manifest_constants.h" -using device::UsbDeviceFilter; - namespace extensions { UsbPrinterManifestData::UsbPrinterManifestData() { @@ -48,30 +48,37 @@ return nullptr; } - UsbDeviceFilter output; - output.vendor_id = input.vendor_id; + auto output = device::mojom::UsbDeviceFilter::New(); + output->has_vendor_id = true; + output->vendor_id = input.vendor_id; - if (input.product_id) - output.product_id = *input.product_id; + if (input.product_id) { + output->has_product_id = true; + output->product_id = *input.product_id; + } if (input.interface_class) { - output.interface_class = *input.interface_class; + output->has_class_code = true; + output->class_code = *input.interface_class; if (input.interface_subclass) { - output.interface_subclass = *input.interface_subclass; - if (input.interface_protocol) - output.interface_protocol = *input.interface_protocol; + output->has_subclass_code = true; + output->subclass_code = *input.interface_subclass; + if (input.interface_protocol) { + output->has_protocol_code = true; + output->protocol_code = *input.interface_protocol; + } } } - result->filters_.push_back(output); + result->filters_.push_back(std::move(output)); } return result; } bool UsbPrinterManifestData::SupportsDevice( - const scoped_refptr<device::UsbDevice>& device) const { + const device::UsbDevice& device) const { for (const auto& filter : filters_) { - if (filter.Matches(*device)) + if (UsbDeviceFilterMatches(*filter, device)) return true; }
diff --git a/extensions/common/api/printer_provider/usb_printer_manifest_data.h b/extensions/common/api/printer_provider/usb_printer_manifest_data.h index b4d3650..486c761 100644 --- a/extensions/common/api/printer_provider/usb_printer_manifest_data.h +++ b/extensions/common/api/printer_provider/usb_printer_manifest_data.h
@@ -7,11 +7,11 @@ #include <vector> +#include "device/usb/public/interfaces/device_manager.mojom.h" #include "extensions/common/extension.h" namespace device { class UsbDevice; -struct UsbDeviceFilter; } namespace extensions { @@ -32,14 +32,12 @@ const base::Value& value, base::string16* error); - bool SupportsDevice(const scoped_refptr<device::UsbDevice>& device) const; - - const std::vector<device::UsbDeviceFilter>& filters() const { - return filters_; - } + bool SupportsDevice(const device::UsbDevice& device) const; private: - std::vector<device::UsbDeviceFilter> filters_; + FRIEND_TEST_ALL_PREFIXES(UsbPrinterManifestTest, Filters); + + std::vector<device::mojom::UsbDeviceFilterPtr> filters_; }; } // namespace extensions
diff --git a/extensions/common/api/printer_provider/usb_printer_manifest_unittest.cc b/extensions/common/api/printer_provider/usb_printer_manifest_unittest.cc index cd35af1..35b339d 100644 --- a/extensions/common/api/printer_provider/usb_printer_manifest_unittest.cc +++ b/extensions/common/api/printer_provider/usb_printer_manifest_unittest.cc
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "device/usb/usb_device_filter.h" #include "extensions/common/api/printer_provider/usb_printer_manifest_data.h" #include "extensions/common/manifest_test.h" #include "extensions/common/value_builder.h" @@ -21,19 +20,27 @@ const UsbPrinterManifestData* manifest_data = UsbPrinterManifestData::Get(extension.get()); ASSERT_TRUE(manifest_data); - EXPECT_EQ(2u, manifest_data->filters().size()); - EXPECT_TRUE(DictionaryBuilder() - .Set("vendorId", 1) - .Set("productId", 2) - .Build() - ->Equals(manifest_data->filters()[0].ToValue().get())); - EXPECT_TRUE(DictionaryBuilder() - .Set("vendorId", 1) - .Set("interfaceClass", 2) - .Set("interfaceSubclass", 3) - .Set("interfaceProtocol", 4) - .Build() - ->Equals(manifest_data->filters()[1].ToValue().get())); + ASSERT_EQ(2u, manifest_data->filters_.size()); + + { + const device::mojom::UsbDeviceFilter& filter = *manifest_data->filters_[0]; + EXPECT_TRUE(filter.has_vendor_id); + EXPECT_EQ(1, filter.vendor_id); + EXPECT_TRUE(filter.has_product_id); + EXPECT_EQ(2, filter.product_id); + } + + { + const device::mojom::UsbDeviceFilter& filter = *manifest_data->filters_[1]; + EXPECT_TRUE(filter.has_vendor_id); + EXPECT_EQ(1, filter.vendor_id); + EXPECT_TRUE(filter.has_class_code); + EXPECT_EQ(2, filter.class_code); + EXPECT_TRUE(filter.has_subclass_code); + EXPECT_EQ(3, filter.subclass_code); + EXPECT_TRUE(filter.has_protocol_code); + EXPECT_EQ(4, filter.protocol_code); + } } TEST_F(UsbPrinterManifestTest, InvalidFilter) {
diff --git a/extensions/utility/utility_handler.cc b/extensions/utility/utility_handler.cc index ff3299d..d63e9ec 100644 --- a/extensions/utility/utility_handler.cc +++ b/extensions/utility/utility_handler.cc
@@ -18,7 +18,6 @@ #include "extensions/utility/unpacker.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/service_manager/public/cpp/bind_source_info.h" -#include "services/service_manager/public/cpp/binder_registry.h" #include "third_party/zlib/google/zip.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_base_switches.h"
diff --git a/extensions/utility/utility_handler.h b/extensions/utility/utility_handler.h index c2a70e92..d04b3cb 100644 --- a/extensions/utility/utility_handler.h +++ b/extensions/utility/utility_handler.h
@@ -5,9 +5,7 @@ #ifndef EXTENSIONS_UTILITY_UTILITY_HANDLER_H_ #define EXTENSIONS_UTILITY_UTILITY_HANDLER_H_ -namespace service_manager { -class BinderRegistry; -} +#include "services/service_manager/public/cpp/binder_registry.h" namespace extensions {
diff --git a/gpu/command_buffer/service/gl_context_virtual.cc b/gpu/command_buffer/service/gl_context_virtual.cc index 2582d00..9615f23 100644 --- a/gpu/command_buffer/service/gl_context_virtual.cc +++ b/gpu/command_buffer/service/gl_context_virtual.cc
@@ -100,6 +100,10 @@ return shared_context_->GetYUVToRGBConverter(); } +void GLContextVirtual::ForceReleaseVirtuallyCurrent() { + shared_context_->OnReleaseVirtuallyCurrent(this); +} + GLContextVirtual::~GLContextVirtual() { Destroy(); }
diff --git a/gpu/command_buffer/service/gl_context_virtual.h b/gpu/command_buffer/service/gl_context_virtual.h index d8c7c91..7af79b8 100644 --- a/gpu/command_buffer/service/gl_context_virtual.h +++ b/gpu/command_buffer/service/gl_context_virtual.h
@@ -47,6 +47,7 @@ bool WasAllocatedUsingRobustnessExtension() override; void SetUnbindFboOnMakeCurrent() override; gl::YUVToRGBConverter* GetYUVToRGBConverter() override; + void ForceReleaseVirtuallyCurrent() override; protected: ~GLContextVirtual() override;
diff --git a/gpu/ipc/service/gpu_command_buffer_stub.cc b/gpu/ipc/service/gpu_command_buffer_stub.cc index 8c5705e8..cf8634c 100644 --- a/gpu/ipc/service/gpu_command_buffer_stub.cc +++ b/gpu/ipc/service/gpu_command_buffer_stub.cc
@@ -791,10 +791,10 @@ // is in an indeterminate state, since the GLStateRestorer was not // initialized at the time the GLContextVirtual was made current. In // the case that this command decoder is the next one to be - // processed, force a "full" MakeCurrent to be performed. Note that - // GpuChannel's initialization of the gpu::Capabilities expects the - // context to be left current. - context->ReleaseCurrent(surface_.get()); + // processed, force a "full virtual" MakeCurrent to be performed. + // Note that GpuChannel's initialization of the gpu::Capabilities + // expects the context to be left current. + context->ForceReleaseVirtuallyCurrent(); if (!context->MakeCurrent(surface_.get())) { LOG(ERROR) << "Failed to make context current after initialization."; return false;
diff --git a/ios/chrome/browser/upgrade/upgrade_center.mm b/ios/chrome/browser/upgrade/upgrade_center.mm index 611868da..cc1657e 100644 --- a/ios/chrome/browser/upgrade/upgrade_center.mm +++ b/ios/chrome/browser/upgrade/upgrade_center.mm
@@ -218,7 +218,7 @@ // Stores the clients of the upgrade center. These objectiveC objects are not // retained. __strong NSHashTable<id<UpgradeCenterClientProtocol>>* clients_; -#ifndef NDEBUG +#if DCHECK_IS_ON() BOOL inCallback_; #endif } @@ -295,7 +295,7 @@ } - (void)unregisterClient:(id<UpgradeCenterClientProtocol>)client { -#ifndef NDEBUG +#if DCHECK_IS_ON() DCHECK(!inCallback_); #endif [clients_ removeObject:client]; @@ -375,13 +375,13 @@ - (void)showUpgradeInfoBars { // Add an infobar on all the open tabs. -#ifndef NDEBUG +#if DCHECK_IS_ON() inCallback_ = YES; #endif upgradeInfoBarIsVisible_ = YES; for (id<UpgradeCenterClientProtocol> upgradeClient in clients_) [upgradeClient showUpgrade:self]; -#ifndef NDEBUG +#if DCHECK_IS_ON() inCallback_ = NO; #endif
diff --git a/ios/net/cookies/cookie_store_ios_persistent_unittest.mm b/ios/net/cookies/cookie_store_ios_persistent_unittest.mm index 1a41211..85706f6 100644 --- a/ios/net/cookies/cookie_store_ios_persistent_unittest.mm +++ b/ios/net/cookies/cookie_store_ios_persistent_unittest.mm
@@ -30,6 +30,7 @@ static const bool preserves_trailing_dots = true; static const bool filters_schemes = false; static const bool has_path_prefix_bug = false; + static const bool forbids_setting_empty_name = false; static const int creation_time_granularity_in_ms = 0; static const int enforces_prefixes = true; static const bool enforce_strict_secure = false; @@ -125,4 +126,4 @@ EXPECT_EQ("a=b", callback.cookie_line()); } -} // namespace net \ No newline at end of file +} // namespace net
diff --git a/ios/net/cookies/cookie_store_ios_unittest.mm b/ios/net/cookies/cookie_store_ios_unittest.mm index 329e846..514738b 100644 --- a/ios/net/cookies/cookie_store_ios_unittest.mm +++ b/ios/net/cookies/cookie_store_ios_unittest.mm
@@ -33,6 +33,7 @@ static const bool preserves_trailing_dots = false; static const bool filters_schemes = false; static const bool has_path_prefix_bug = true; + static const bool forbids_setting_empty_name = true; static const int creation_time_granularity_in_ms = 1000; base::MessageLoop loop_;
diff --git a/ios/third_party/material_components_ios/README.chromium b/ios/third_party/material_components_ios/README.chromium index 01c9601a..34f53ef4 100644 --- a/ios/third_party/material_components_ios/README.chromium +++ b/ios/third_party/material_components_ios/README.chromium
@@ -1,7 +1,7 @@ Name: Material Components for iOS URL: https://github.com/material-components/material-components-ios Version: 0 -Revision: 6d5844642b004594ba1607916032616f85c7c045 +Revision: b452b1e7fb85cc9aeef2df2b6a44cbe0e8594560 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/ios/web_view/test/BUILD.gn b/ios/web_view/test/BUILD.gn index 8b22400c..4b55e70 100644 --- a/ios/web_view/test/BUILD.gn +++ b/ios/web_view/test/BUILD.gn
@@ -16,10 +16,10 @@ test("ios_web_view_inttests") { testonly = true sources = [ - "chrome_web_view_kvo_inttest.mm", - "chrome_web_view_restorable_state_inttest.mm", - "chrome_web_view_test.h", - "chrome_web_view_test.mm", + "web_view_kvo_inttest.mm", + "web_view_restorable_state_inttest.mm", + "web_view_test.h", + "web_view_test.mm", ] deps = [
diff --git a/ios/web_view/test/chrome_web_view_kvo_inttest.mm b/ios/web_view/test/web_view_kvo_inttest.mm similarity index 96% rename from ios/web_view/test/chrome_web_view_kvo_inttest.mm rename to ios/web_view/test/web_view_kvo_inttest.mm index 4cbd0c2..03d6b667 100644 --- a/ios/web_view/test/chrome_web_view_kvo_inttest.mm +++ b/ios/web_view/test/web_view_kvo_inttest.mm
@@ -8,8 +8,8 @@ #include "base/strings/stringprintf.h" #import "base/strings/sys_string_conversions.h" #import "ios/testing/wait_util.h" -#import "ios/web_view/test/chrome_web_view_test.h" #import "ios/web_view/test/observer.h" +#import "ios/web_view/test/web_view_test.h" #import "ios/web_view/test/web_view_test_util.h" #import "net/base/mac/url_conversions.h" #include "testing/gtest_mac.h" @@ -23,10 +23,10 @@ // Tests that the KVO compliant properties of CWVWebView correctly report // changes. -typedef ios_web_view::ChromeWebViewTest ChromeWebViewKvoTest; +typedef ios_web_view::WebViewTest WebViewKvoTest; // Tests that CWVWebView correctly reports |canGoBack| and |canGoForward| state. -TEST_F(ChromeWebViewKvoTest, CanGoBackForward) { +TEST_F(WebViewKvoTest, CanGoBackForward) { Observer* back_observer = [[Observer alloc] init]; [back_observer setObservedObject:web_view_ keyPath:@"canGoBack"]; @@ -84,7 +84,7 @@ } // Tests that CWVWebView correctly reports current |title|. -TEST_F(ChromeWebViewKvoTest, Title) { +TEST_F(WebViewKvoTest, Title) { Observer* observer = [[Observer alloc] init]; [observer setObservedObject:web_view_ keyPath:@"title"]; @@ -113,7 +113,7 @@ } // Tests that CWVWebView correctly reports |isLoading| value. -TEST_F(ChromeWebViewKvoTest, Loading) { +TEST_F(WebViewKvoTest, Loading) { Observer* observer = [[Observer alloc] init]; [observer setObservedObject:web_view_ keyPath:@"loading"]; @@ -141,7 +141,7 @@ } // Tests that CWVWebView correctly reports |visibleURL| and |lastCommittedURL|. -TEST_F(ChromeWebViewKvoTest, URLs) { +TEST_F(WebViewKvoTest, URLs) { Observer* last_committed_url_observer = [[Observer alloc] init]; [last_committed_url_observer setObservedObject:web_view_ keyPath:@"lastCommittedURL"];
diff --git a/ios/web_view/test/chrome_web_view_restorable_state_inttest.mm b/ios/web_view/test/web_view_restorable_state_inttest.mm similarity index 92% rename from ios/web_view/test/chrome_web_view_restorable_state_inttest.mm rename to ios/web_view/test/web_view_restorable_state_inttest.mm index 0c682e0..ab20268 100644 --- a/ios/web_view/test/chrome_web_view_restorable_state_inttest.mm +++ b/ios/web_view/test/web_view_restorable_state_inttest.mm
@@ -4,7 +4,7 @@ #import <ChromeWebView/ChromeWebView.h> -#import "ios/web_view/test/chrome_web_view_test.h" +#import "ios/web_view/test/web_view_test.h" #import "ios/web_view/test/web_view_test_util.h" #include "testing/gtest_mac.h" @@ -34,8 +34,8 @@ // Tests encodeRestorableStateWithCoder: and decodeRestorableStateWithCoder: // methods. -typedef ios_web_view::ChromeWebViewTest ChromeWebViewRestorableStateTest; -TEST_F(ChromeWebViewRestorableStateTest, EncodeDecode) { +typedef ios_web_view::WebViewTest WebViewRestorableStateTest; +TEST_F(WebViewRestorableStateTest, EncodeDecode) { // Load 2 URLs to create non-default state. ASSERT_FALSE([web_view_ lastCommittedURL]); ASSERT_FALSE([web_view_ visibleURL]);
diff --git a/ios/web_view/test/chrome_web_view_test.h b/ios/web_view/test/web_view_test.h similarity index 85% rename from ios/web_view/test/chrome_web_view_test.h rename to ios/web_view/test/web_view_test.h index d6e73534..6ae8988b 100644 --- a/ios/web_view/test/chrome_web_view_test.h +++ b/ios/web_view/test/web_view_test.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_WEB_VIEW_TEST_CHROME_WEB_VIEW_TEST_H_ -#define IOS_WEB_VIEW_TEST_CHROME_WEB_VIEW_TEST_H_ +#ifndef IOS_WEB_VIEW_TEST_WEB_VIEW_TEST_H_ +#define IOS_WEB_VIEW_TEST_WEB_VIEW_TEST_H_ #include <memory> #include <string> @@ -26,10 +26,10 @@ // A test fixture for testing CWVWebView. A test server is also created to // support loading content. The server supports the urls returned by the GetUrl* // methods below. -class ChromeWebViewTest : public PlatformTest { +class WebViewTest : public PlatformTest { protected: - ChromeWebViewTest(); - ~ChromeWebViewTest() override; + WebViewTest(); + ~WebViewTest() override; // Returns URL to an html page with title set to |title|. GURL GetUrlForPageWithTitle(const std::string& title); @@ -56,4 +56,4 @@ } // namespace ios_web_view -#endif // IOS_WEB_VIEW_TEST_CHROME_WEB_VIEW_TEST_H_ +#endif // IOS_WEB_VIEW_TEST_WEB_VIEW_TEST_H_
diff --git a/ios/web_view/test/chrome_web_view_test.mm b/ios/web_view/test/web_view_test.mm similarity index 89% rename from ios/web_view/test/chrome_web_view_test.mm rename to ios/web_view/test/web_view_test.mm index 039eee4..e0728e5 100644 --- a/ios/web_view/test/chrome_web_view_test.mm +++ b/ios/web_view/test/web_view_test.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/web_view/test/chrome_web_view_test.h" +#import "ios/web_view/test/web_view_test.h" #import <ChromeWebView/ChromeWebView.h> #import <Foundation/Foundation.h> @@ -96,30 +96,30 @@ namespace ios_web_view { -ChromeWebViewTest::ChromeWebViewTest() +WebViewTest::WebViewTest() : web_view_(test::CreateWebView()), test_server_(base::MakeUnique<net::EmbeddedTestServer>( net::test_server::EmbeddedTestServer::TYPE_HTTP)) { test_server_->RegisterRequestHandler(base::Bind(&TestRequestHandler)); } -ChromeWebViewTest::~ChromeWebViewTest() = default; +WebViewTest::~WebViewTest() = default; -void ChromeWebViewTest::SetUp() { +void WebViewTest::SetUp() { PlatformTest::SetUp(); ASSERT_TRUE(test_server_->Start()); } -GURL ChromeWebViewTest::GetUrlForPageWithTitle(const std::string& title) { +GURL WebViewTest::GetUrlForPageWithTitle(const std::string& title) { return GetUrlForPageWithTitleAndBody(title, std::string()); } -GURL ChromeWebViewTest::GetUrlForPageWithHtmlBody(const std::string& html) { +GURL WebViewTest::GetUrlForPageWithHtmlBody(const std::string& html) { return GetUrlForPageWithTitleAndBody(std::string(), html); } -GURL ChromeWebViewTest::GetUrlForPageWithTitleAndBody(const std::string& title, - const std::string& body) { +GURL WebViewTest::GetUrlForPageWithTitleAndBody(const std::string& title, + const std::string& body) { GURL url = test_server_->GetURL(kPageHtmlPath); // Encode |title| and |body| in url query in order to build the server
diff --git a/media/base/media_log.cc b/media/base/media_log.cc index abba917..df26788f 100644 --- a/media/base/media_log.cc +++ b/media/base/media_log.cc
@@ -65,16 +65,10 @@ return "VIDEO_SIZE_SET"; case MediaLogEvent::DURATION_SET: return "DURATION_SET"; - case MediaLogEvent::TOTAL_BYTES_SET: - return "TOTAL_BYTES_SET"; - case MediaLogEvent::NETWORK_ACTIVITY_SET: - return "NETWORK_ACTIVITY_SET"; case MediaLogEvent::ENDED: return "ENDED"; case MediaLogEvent::TEXT_ENDED: return "TEXT_ENDED"; - case MediaLogEvent::BUFFERED_EXTENTS_CHANGED: - return "BUFFERED_EXTENTS_CHANGED"; case MediaLogEvent::MEDIA_ERROR_LOG_ENTRY: return "MEDIA_ERROR_LOG_ENTRY"; case MediaLogEvent::MEDIA_INFO_LOG_ENTRY: @@ -269,20 +263,6 @@ return event; } -std::unique_ptr<MediaLogEvent> MediaLog::CreateBufferedExtentsChangedEvent( - int64_t start, - int64_t current, - int64_t end) { - std::unique_ptr<MediaLogEvent> event( - CreateEvent(MediaLogEvent::BUFFERED_EXTENTS_CHANGED)); - // These values are headed to JS where there is no int64_t so we use a double - // and accept loss of precision above 2^53 bytes (8 Exabytes). - event->params.SetDouble("buffer_start", start); - event->params.SetDouble("buffer_current", current); - event->params.SetDouble("buffer_end", end); - return event; -} - std::unique_ptr<MediaLogEvent> MediaLog::CreateBufferingStateChangedEvent( const std::string& property, BufferingState state) {
diff --git a/media/base/media_log.h b/media/base/media_log.h index 9899018..d138fd6 100644 --- a/media/base/media_log.h +++ b/media/base/media_log.h
@@ -89,11 +89,6 @@ std::unique_ptr<MediaLogEvent> CreatePipelineErrorEvent(PipelineStatus error); std::unique_ptr<MediaLogEvent> CreateVideoSizeSetEvent(size_t width, size_t height); - std::unique_ptr<MediaLogEvent> CreateBufferedExtentsChangedEvent( - int64_t start, - int64_t current, - int64_t end); - std::unique_ptr<MediaLogEvent> CreateBufferingStateChangedEvent( const std::string& property, BufferingState state);
diff --git a/media/base/media_log_event.h b/media/base/media_log_event.h index 73d81dc..9b7be60 100644 --- a/media/base/media_log_event.h +++ b/media/base/media_log_event.h
@@ -65,8 +65,6 @@ // These take a single parameter based upon the name of the event and of // the appropriate type. e.g. DURATION_SET: "duration" of type TimeDelta. DURATION_SET, - TOTAL_BYTES_SET, - NETWORK_ACTIVITY_SET, // Audio/Video stream playback has ended. ENDED, @@ -74,12 +72,6 @@ // Text stream playback has ended. TEXT_ENDED, - // The extents of the sliding buffer have changed. - // params: "buffer_start": <first buffered byte>. - // "buffer_current": <current offset>. - // "buffer_end": <last buffered byte>. - BUFFERED_EXTENTS_CHANGED, - // Error log reported by media code such as reasons of playback error. MEDIA_ERROR_LOG_ENTRY, // params: "error": Error string describing the error detected.
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 073decac..0b3c60a 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -1748,9 +1748,6 @@ SetNetworkState(WebMediaPlayer::kNetworkStateLoading); if (ready_state_ == ReadyState::kReadyStateHaveFutureData && !is_downloading) SetReadyState(WebMediaPlayer::kReadyStateHaveEnoughData); - media_log_->AddEvent( - media_log_->CreateBooleanEvent(MediaLogEvent::NETWORK_ACTIVITY_SET, - "is_downloading_data", is_downloading)); } void WebMediaPlayerImpl::OnSurfaceCreated(int surface_id) {
diff --git a/mojo/edk/embedder/entrypoints.cc b/mojo/edk/embedder/entrypoints.cc index 6995a52..262f919 100644 --- a/mojo/edk/embedder/entrypoints.cc +++ b/mojo/edk/embedder/entrypoints.cc
@@ -58,14 +58,6 @@ return g_core->CancelWatch(watcher_handle, context); } -MojoResult MojoAllocMessageImpl(uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoAllocMessageFlags flags, - MojoMessageHandle* message) { - return g_core->AllocMessage(num_bytes, handles, num_handles, flags, message); -} - MojoResult MojoCreateMessageImpl(uintptr_t context, const MojoMessageOperationThunks* thunks, MojoMessageHandle* message) { @@ -105,35 +97,15 @@ } MojoResult MojoWriteMessageImpl(MojoHandle message_pipe_handle, - const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, + MojoMessageHandle message, MojoWriteMessageFlags flags) { - return g_core->WriteMessage(message_pipe_handle, bytes, num_bytes, handles, - num_handles, flags); -} - -MojoResult MojoWriteMessageNewImpl(MojoHandle message_pipe_handle, - MojoMessageHandle message, - MojoWriteMessageFlags flags) { - return g_core->WriteMessageNew(message_pipe_handle, message, flags); + return g_core->WriteMessage(message_pipe_handle, message, flags); } MojoResult MojoReadMessageImpl(MojoHandle message_pipe_handle, - void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, + MojoMessageHandle* message, MojoReadMessageFlags flags) { - return g_core->ReadMessage( - message_pipe_handle, bytes, num_bytes, handles, num_handles, flags); -} - -MojoResult MojoReadMessageNewImpl(MojoHandle message_pipe_handle, - MojoMessageHandle* message, - MojoReadMessageFlags flags) { - return g_core->ReadMessageNew(message_pipe_handle, message, flags); + return g_core->ReadMessage(message_pipe_handle, message, flags); } MojoResult MojoFuseMessagePipesImpl(MojoHandle handle0, MojoHandle handle1) { @@ -283,9 +255,6 @@ MojoCancelWatchImpl, MojoArmWatcherImpl, MojoFuseMessagePipesImpl, - MojoWriteMessageNewImpl, - MojoReadMessageNewImpl, - MojoAllocMessageImpl, MojoCreateMessageImpl, MojoFreeMessageImpl, MojoSerializeMessageImpl,
diff --git a/mojo/edk/js/core.cc b/mojo/edk/js/core.cc index a04a960..bf8933a 100644 --- a/mojo/edk/js/core.cc +++ b/mojo/edk/js/core.cc
@@ -135,7 +135,7 @@ MojoReadMessageFlags flags) { MojoMessageHandle message; MojoResult result = - MojoReadMessageNew(handle.value(), &message, MOJO_READ_MESSAGE_FLAG_NONE); + MojoReadMessage(handle.value(), &message, MOJO_READ_MESSAGE_FLAG_NONE); if (result != MOJO_RESULT_OK) { gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); dictionary.Set("result", result); @@ -435,8 +435,6 @@ .SetValue("WRITE_MESSAGE_FLAG_NONE", MOJO_WRITE_MESSAGE_FLAG_NONE) .SetValue("READ_MESSAGE_FLAG_NONE", MOJO_READ_MESSAGE_FLAG_NONE) - .SetValue("READ_MESSAGE_FLAG_MAY_DISCARD", - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD) .SetValue("CREATE_DATA_PIPE_OPTIONS_FLAG_NONE", MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE)
diff --git a/mojo/edk/js/tests/BUILD.gn b/mojo/edk/js/tests/BUILD.gn index b3b87392..21c9bfc4 100644 --- a/mojo/edk/js/tests/BUILD.gn +++ b/mojo/edk/js/tests/BUILD.gn
@@ -15,10 +15,44 @@ group("tests") { testonly = true deps = [ + ":mojo_js_integration_tests", ":mojo_js_unittests", ] } +test("mojo_js_integration_tests") { + deps = [ + ":js_to_cpp_bindings", + "//base/test:test_support", + "//gin:gin_test", + "//mojo/common", + "//mojo/edk/js", + "//mojo/edk/test:run_all_unittests", + "//mojo/public/cpp/bindings", + "//mojo/public/cpp/system", + "//mojo/public/js:bindings", + ] + + sources = [ + "js_to_cpp_tests.cc", + ] + + data = [ + "js_to_cpp_tests.js", + ] + + configs += [ "//v8:external_startup_data" ] +} + +mojom("js_to_cpp_bindings") { + sources = [ + "js_to_cpp.mojom", + ] + + # TODO(crbug.com/699569): Convert to use the new JS bindings. + use_new_js_bindings = false +} + test("mojo_js_unittests") { deps = [ "//base",
diff --git a/third_party/WebKit/Source/core/mojo/tests/JsToCpp.mojom b/mojo/edk/js/tests/js_to_cpp.mojom similarity index 100% rename from third_party/WebKit/Source/core/mojo/tests/JsToCpp.mojom rename to mojo/edk/js/tests/js_to_cpp.mojom
diff --git a/mojo/edk/js/tests/js_to_cpp_tests.cc b/mojo/edk/js/tests/js_to_cpp_tests.cc new file mode 100644 index 0000000..0ce95e8 --- /dev/null +++ b/mojo/edk/js/tests/js_to_cpp_tests.cc
@@ -0,0 +1,459 @@ +// 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 <stddef.h> +#include <stdint.h> + +#include <string> +#include <utility> +#include <vector> + +#include "base/at_exit.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/macros.h" +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_environment.h" +#include "base/threading/thread_task_runner_handle.h" +#include "gin/array_buffer.h" +#include "gin/public/isolate_holder.h" +#include "gin/v8_initializer.h" +#include "mojo/common/data_pipe_utils.h" +#include "mojo/edk/js/mojo_runner_delegate.h" +#include "mojo/edk/js/tests/js_to_cpp.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/lib/validation_errors.h" +#include "mojo/public/cpp/system/core.h" +#include "mojo/public/cpp/system/wait.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace edk { +namespace js { + +// Global value updated by some checks to prevent compilers from optimizing +// reads out of existence. +uint32_t g_waste_accumulator = 0; + +namespace { + +// Negative numbers with different values in each byte, the last of +// which can survive promotion to double and back. +const int8_t kExpectedInt8Value = -65; +const int16_t kExpectedInt16Value = -16961; +const int32_t kExpectedInt32Value = -1145258561; +const int64_t kExpectedInt64Value = -77263311946305LL; + +// Positive numbers with different values in each byte, the last of +// which can survive promotion to double and back. +const uint8_t kExpectedUInt8Value = 65; +const uint16_t kExpectedUInt16Value = 16961; +const uint32_t kExpectedUInt32Value = 1145258561; +const uint64_t kExpectedUInt64Value = 77263311946305LL; + +// Double/float values, including special case constants. +const double kExpectedDoubleVal = 3.14159265358979323846; +const double kExpectedDoubleInf = std::numeric_limits<double>::infinity(); +const double kExpectedDoubleNan = std::numeric_limits<double>::quiet_NaN(); +const float kExpectedFloatVal = static_cast<float>(kExpectedDoubleVal); +const float kExpectedFloatInf = std::numeric_limits<float>::infinity(); +const float kExpectedFloatNan = std::numeric_limits<float>::quiet_NaN(); + +// NaN has the property that it is not equal to itself. +#define EXPECT_NAN(x) EXPECT_NE(x, x) + +void CheckDataPipe(ScopedDataPipeConsumerHandle data_pipe_handle) { + std::string buffer; + bool result = common::BlockingCopyToString(std::move(data_pipe_handle), + &buffer); + EXPECT_TRUE(result); + EXPECT_EQ(64u, buffer.size()); + for (int i = 0; i < 64; ++i) { + EXPECT_EQ(i, buffer[i]); + } +} + +void CheckMessagePipe(MessagePipeHandle message_pipe_handle) { + MojoResult result = Wait(message_pipe_handle, MOJO_HANDLE_SIGNAL_READABLE); + EXPECT_EQ(MOJO_RESULT_OK, result); + std::vector<uint8_t> bytes; + std::vector<ScopedHandle> handles; + result = ReadMessageRaw(message_pipe_handle, &bytes, &handles, 0); + EXPECT_EQ(MOJO_RESULT_OK, result); + EXPECT_EQ(64u, bytes.size()); + for (int i = 0; i < 64; ++i) { + EXPECT_EQ(255 - i, bytes[i]); + } +} + +js_to_cpp::EchoArgsPtr BuildSampleEchoArgs() { + js_to_cpp::EchoArgsPtr args(js_to_cpp::EchoArgs::New()); + args->si64 = kExpectedInt64Value; + args->si32 = kExpectedInt32Value; + args->si16 = kExpectedInt16Value; + args->si8 = kExpectedInt8Value; + args->ui64 = kExpectedUInt64Value; + args->ui32 = kExpectedUInt32Value; + args->ui16 = kExpectedUInt16Value; + args->ui8 = kExpectedUInt8Value; + args->float_val = kExpectedFloatVal; + args->float_inf = kExpectedFloatInf; + args->float_nan = kExpectedFloatNan; + args->double_val = kExpectedDoubleVal; + args->double_inf = kExpectedDoubleInf; + args->double_nan = kExpectedDoubleNan; + args->name.emplace("coming"); + args->string_array.emplace(3); + (*args->string_array)[0] = "one"; + (*args->string_array)[1] = "two"; + (*args->string_array)[2] = "three"; + return args; +} + +void CheckSampleEchoArgs(js_to_cpp::EchoArgsPtr arg) { + EXPECT_EQ(kExpectedInt64Value, arg->si64); + EXPECT_EQ(kExpectedInt32Value, arg->si32); + EXPECT_EQ(kExpectedInt16Value, arg->si16); + EXPECT_EQ(kExpectedInt8Value, arg->si8); + EXPECT_EQ(kExpectedUInt64Value, arg->ui64); + EXPECT_EQ(kExpectedUInt32Value, arg->ui32); + EXPECT_EQ(kExpectedUInt16Value, arg->ui16); + EXPECT_EQ(kExpectedUInt8Value, arg->ui8); + EXPECT_EQ(kExpectedFloatVal, arg->float_val); + EXPECT_EQ(kExpectedFloatInf, arg->float_inf); + EXPECT_NAN(arg->float_nan); + EXPECT_EQ(kExpectedDoubleVal, arg->double_val); + EXPECT_EQ(kExpectedDoubleInf, arg->double_inf); + EXPECT_NAN(arg->double_nan); + EXPECT_EQ(std::string("coming"), *arg->name); + EXPECT_EQ(std::string("one"), (*arg->string_array)[0]); + EXPECT_EQ(std::string("two"), (*arg->string_array)[1]); + EXPECT_EQ(std::string("three"), (*arg->string_array)[2]); + CheckDataPipe(std::move(arg->data_handle)); + CheckMessagePipe(arg->message_handle.get()); +} + +void CheckSampleEchoArgsList(const js_to_cpp::EchoArgsListPtr& list) { + if (list.is_null()) + return; + CheckSampleEchoArgs(std::move(list->item)); + CheckSampleEchoArgsList(list->next); +} + +// More forgiving checks are needed in the face of potentially corrupt +// messages. The values don't matter so long as all accesses are within +// bounds. +void CheckCorruptedString(const std::string& arg) { + for (size_t i = 0; i < arg.size(); ++i) + g_waste_accumulator += arg[i]; +} + +void CheckCorruptedString(const base::Optional<std::string>& arg) { + if (!arg) + return; + CheckCorruptedString(*arg); +} + +void CheckCorruptedStringArray( + const base::Optional<std::vector<std::string>>& string_array) { + if (!string_array) + return; + for (size_t i = 0; i < string_array->size(); ++i) + CheckCorruptedString((*string_array)[i]); +} + +void CheckCorruptedDataPipe(MojoHandle data_pipe_handle) { + unsigned char buffer[100]; + uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); + MojoResult result = MojoReadData( + data_pipe_handle, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE); + if (result != MOJO_RESULT_OK) + return; + for (uint32_t i = 0; i < buffer_size; ++i) + g_waste_accumulator += buffer[i]; +} + +void CheckCorruptedMessagePipe(MojoHandle message_pipe_handle) { + std::vector<uint8_t> bytes; + std::vector<ScopedHandle> handles; + MojoResult result = ReadMessageRaw(MessagePipeHandle(message_pipe_handle), + &bytes, &handles, 0); + if (result != MOJO_RESULT_OK) + return; + for (uint32_t i = 0; i < bytes.size(); ++i) + g_waste_accumulator += bytes[i]; +} + +void CheckCorruptedEchoArgs(const js_to_cpp::EchoArgsPtr& arg) { + if (arg.is_null()) + return; + CheckCorruptedString(arg->name); + CheckCorruptedStringArray(arg->string_array); + if (arg->data_handle.is_valid()) + CheckCorruptedDataPipe(arg->data_handle.get().value()); + if (arg->message_handle.is_valid()) + CheckCorruptedMessagePipe(arg->message_handle.get().value()); +} + +void CheckCorruptedEchoArgsList(const js_to_cpp::EchoArgsListPtr& list) { + if (list.is_null()) + return; + CheckCorruptedEchoArgs(list->item); + CheckCorruptedEchoArgsList(list->next); +} + +// Base Provider implementation class. It's expected that tests subclass and +// override the appropriate Provider functions. When test is done quit the +// run_loop(). +class CppSideConnection : public js_to_cpp::CppSide { + public: + CppSideConnection() + : run_loop_(nullptr), + js_side_(nullptr), + mishandled_messages_(0), + binding_(this) {} + ~CppSideConnection() override {} + + void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; } + base::RunLoop* run_loop() { return run_loop_; } + + void set_js_side(js_to_cpp::JsSide* js_side) { js_side_ = js_side; } + js_to_cpp::JsSide* js_side() { return js_side_; } + + void Bind(InterfaceRequest<js_to_cpp::CppSide> request) { + binding_.Bind(std::move(request)); + // Keep the pipe open even after validation errors. + binding_.EnableTestingMode(); + } + + // js_to_cpp::CppSide: + void StartTest() override { NOTREACHED(); } + + void TestFinished() override { NOTREACHED(); } + + void PingResponse() override { mishandled_messages_ += 1; } + + void EchoResponse(js_to_cpp::EchoArgsListPtr list) override { + mishandled_messages_ += 1; + } + + void BitFlipResponse( + js_to_cpp::EchoArgsListPtr list, + js_to_cpp::ForTestingAssociatedPtrInfo not_used) override { + mishandled_messages_ += 1; + } + + void BackPointerResponse(js_to_cpp::EchoArgsListPtr list) override { + mishandled_messages_ += 1; + } + + protected: + base::RunLoop* run_loop_; + js_to_cpp::JsSide* js_side_; + int mishandled_messages_; + mojo::Binding<js_to_cpp::CppSide> binding_; + + private: + DISALLOW_COPY_AND_ASSIGN(CppSideConnection); +}; + +// Trivial test to verify a message sent from JS is received. +class PingCppSideConnection : public CppSideConnection { + public: + PingCppSideConnection() : got_message_(false) {} + ~PingCppSideConnection() override {} + + // js_to_cpp::CppSide: + void StartTest() override { js_side_->Ping(); } + + void PingResponse() override { + got_message_ = true; + run_loop()->Quit(); + } + + bool DidSucceed() { + return got_message_ && !mishandled_messages_; + } + + private: + bool got_message_; + DISALLOW_COPY_AND_ASSIGN(PingCppSideConnection); +}; + +// Test that parameters are passed with correct values. +class EchoCppSideConnection : public CppSideConnection { + public: + EchoCppSideConnection() : + message_count_(0), + termination_seen_(false) { + } + ~EchoCppSideConnection() override {} + + // js_to_cpp::CppSide: + void StartTest() override { + js_side_->Echo(kExpectedMessageCount, BuildSampleEchoArgs()); + } + + void EchoResponse(js_to_cpp::EchoArgsListPtr list) override { + const js_to_cpp::EchoArgsPtr& special_arg = list->item; + message_count_ += 1; + EXPECT_EQ(-1, special_arg->si64); + EXPECT_EQ(-1, special_arg->si32); + EXPECT_EQ(-1, special_arg->si16); + EXPECT_EQ(-1, special_arg->si8); + EXPECT_EQ(std::string("going"), *special_arg->name); + CheckSampleEchoArgsList(list->next); + } + + void TestFinished() override { + termination_seen_ = true; + run_loop()->Quit(); + } + + bool DidSucceed() { + return termination_seen_ && + !mishandled_messages_ && + message_count_ == kExpectedMessageCount; + } + + private: + static const int kExpectedMessageCount = 10; + int message_count_; + bool termination_seen_; + DISALLOW_COPY_AND_ASSIGN(EchoCppSideConnection); +}; + +// Test that corrupted messages don't wreak havoc. +class BitFlipCppSideConnection : public CppSideConnection { + public: + BitFlipCppSideConnection() : termination_seen_(false) {} + ~BitFlipCppSideConnection() override {} + + // js_to_cpp::CppSide: + void StartTest() override { js_side_->BitFlip(BuildSampleEchoArgs()); } + + void BitFlipResponse( + js_to_cpp::EchoArgsListPtr list, + js_to_cpp::ForTestingAssociatedPtrInfo not_used) override { + CheckCorruptedEchoArgsList(list); + } + + void TestFinished() override { + termination_seen_ = true; + run_loop()->Quit(); + } + + bool DidSucceed() { + return termination_seen_; + } + + private: + bool termination_seen_; + DISALLOW_COPY_AND_ASSIGN(BitFlipCppSideConnection); +}; + +// Test that severely random messages don't wreak havoc. +class BackPointerCppSideConnection : public CppSideConnection { + public: + BackPointerCppSideConnection() : termination_seen_(false) {} + ~BackPointerCppSideConnection() override {} + + // js_to_cpp::CppSide: + void StartTest() override { js_side_->BackPointer(BuildSampleEchoArgs()); } + + void BackPointerResponse(js_to_cpp::EchoArgsListPtr list) override { + CheckCorruptedEchoArgsList(list); + } + + void TestFinished() override { + termination_seen_ = true; + run_loop()->Quit(); + } + + bool DidSucceed() { + return termination_seen_; + } + + private: + bool termination_seen_; + DISALLOW_COPY_AND_ASSIGN(BackPointerCppSideConnection); +}; + +} // namespace + +class JsToCppTest : public testing::Test { + public: + JsToCppTest() {} + + void RunTest(const std::string& test, CppSideConnection* cpp_side) { + cpp_side->set_run_loop(&run_loop_); + + js_to_cpp::JsSidePtr js_side; + auto js_side_proxy = MakeRequest(&js_side); + + cpp_side->set_js_side(js_side.get()); + js_to_cpp::CppSidePtr cpp_side_ptr; + cpp_side->Bind(MakeRequest(&cpp_side_ptr)); + + js_side->SetCppSide(std::move(cpp_side_ptr)); + +#ifdef V8_USE_EXTERNAL_STARTUP_DATA + gin::V8Initializer::LoadV8Snapshot(); + gin::V8Initializer::LoadV8Natives(); +#endif + + gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode, + gin::IsolateHolder::kStableV8Extras, + gin::ArrayBufferAllocator::SharedInstance()); + gin::IsolateHolder instance(base::ThreadTaskRunnerHandle::Get()); + MojoRunnerDelegate delegate; + gin::ShellRunner runner(&delegate, instance.isolate()); + delegate.Start(&runner, js_side_proxy.PassMessagePipe().release().value(), + test); + + run_loop_.Run(); + } + + private: + base::ShadowingAtExitManager at_exit_; + base::test::ScopedTaskEnvironment scoped_task_environment_; + base::RunLoop run_loop_; + + DISALLOW_COPY_AND_ASSIGN(JsToCppTest); +}; + +TEST_F(JsToCppTest, Ping) { + PingCppSideConnection cpp_side_connection; + RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); + EXPECT_TRUE(cpp_side_connection.DidSucceed()); +} + +TEST_F(JsToCppTest, Echo) { + EchoCppSideConnection cpp_side_connection; + RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); + EXPECT_TRUE(cpp_side_connection.DidSucceed()); +} + +TEST_F(JsToCppTest, BitFlip) { + // These tests generate a lot of expected validation errors. Suppress logging. + mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression; + + BitFlipCppSideConnection cpp_side_connection; + RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); + EXPECT_TRUE(cpp_side_connection.DidSucceed()); +} + +TEST_F(JsToCppTest, BackPointer) { + // These tests generate a lot of expected validation errors. Suppress logging. + mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression; + + BackPointerCppSideConnection cpp_side_connection; + RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); + EXPECT_TRUE(cpp_side_connection.DidSucceed()); +} + +} // namespace js +} // namespace edk +} // namespace mojo
diff --git a/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.js b/mojo/edk/js/tests/js_to_cpp_tests.js similarity index 74% rename from third_party/WebKit/Source/core/mojo/tests/JsToCppTest.js rename to mojo/edk/js/tests/js_to_cpp_tests.js index 139687a..6ffce09 100644 --- a/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.js +++ b/mojo/edk/js/tests/js_to_cpp_tests.js
@@ -2,18 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -(function () { +define('mojo/edk/js/tests/js_to_cpp_tests', [ + 'console', + 'mojo/edk/js/tests/js_to_cpp.mojom', + 'mojo/public/js/bindings', + 'mojo/public/js/connector', + 'mojo/public/js/core', +], function (console, jsToCpp, bindings, connector, core) { var retainedJsSide; + var retainedJsSideStub; var sampleData; var sampleMessage; var BAD_VALUE = 13; var DATA_PIPE_PARAMS = { + flags: core.CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, elementNumBytes: 1, capacityNumBytes: 64 }; function JsSideConnection() { - this.binding = new mojo.Binding(jsToCpp.JsSide, this); + this.binding = new bindings.Binding(jsToCpp.JsSide, this); } JsSideConnection.prototype.setCppSide = function(cppSide) { @@ -47,13 +55,13 @@ arg.si8 = BAD_VALUE; for (i = 0; i < numIterations; ++i) { - dataPipe1 = Mojo.createDataPipe(DATA_PIPE_PARAMS); - dataPipe2 = Mojo.createDataPipe(DATA_PIPE_PARAMS); - messagePipe1 = Mojo.createMessagePipe(); - messagePipe2 = Mojo.createMessagePipe(); + dataPipe1 = core.createDataPipe(DATA_PIPE_PARAMS); + dataPipe2 = core.createDataPipe(DATA_PIPE_PARAMS); + messagePipe1 = core.createMessagePipe(); + messagePipe2 = core.createMessagePipe(); - arg.dataHandle = dataPipe1.consumer; - arg.messageHandle = messagePipe1.handle1; + arg.data_handle = dataPipe1.consumerHandle; + arg.message_handle = messagePipe1.handle1; specialArg = new jsToCpp.EchoArgs(); specialArg.si64 = -1; @@ -61,19 +69,20 @@ specialArg.si16 = -1; specialArg.si8 = -1; specialArg.name = 'going'; - specialArg.dataHandle = dataPipe2.consumer; - specialArg.messageHandle = messagePipe2.handle1; + specialArg.data_handle = dataPipe2.consumerHandle; + specialArg.message_handle = messagePipe2.handle1; writeDataPipe(dataPipe1, sampleData); writeDataPipe(dataPipe2, sampleData); writeMessagePipe(messagePipe1, sampleMessage); writeMessagePipe(messagePipe2, sampleMessage); + this.cppSide_.echoResponse(createEchoArgsList(specialArg, arg)); - dataPipe1.producer.close(); - dataPipe2.producer.close(); - messagePipe1.handle0.close(); - messagePipe2.handle0.close(); + core.close(dataPipe1.producerHandle); + core.close(dataPipe2.producerHandle); + core.close(messagePipe1.handle0); + core.close(messagePipe2.handle0); } this.cppSide_.testFinished(); }; @@ -82,7 +91,7 @@ var iteration = 0; var dataPipe; var messagePipe; - var proto = mojo.internal.Connector.prototype; + var proto = connector.Connector.prototype; var stopSignalled = false; proto.realAccept = proto.accept; @@ -101,13 +110,13 @@ }; while (!stopSignalled) { - messagePipe = Mojo.createMessagePipe(); + messagePipe = core.createMessagePipe(); writeMessagePipe(messagePipe, sampleMessage); - arg.messageHandle = messagePipe.handle1; + arg.message_handle = messagePipe.handle1; this.cppSide_.bitFlipResponse(createEchoArgsList(arg), null); - messagePipe.handle0.close(); + core.close(messagePipe.handle0); iteration += 1; } @@ -120,7 +129,7 @@ var iteration = 0; var dataPipe; var messagePipe; - var proto = mojo.internal.Connector.prototype; + var proto = connector.Connector.prototype; var stopSignalled = false; proto.realAccept = proto.accept; @@ -137,13 +146,13 @@ }; while (!stopSignalled) { - messagePipe = Mojo.createMessagePipe(); + messagePipe = core.createMessagePipe(); writeMessagePipe(messagePipe, sampleMessage); - arg.messageHandle = messagePipe.handle1; + arg.message_handle = messagePipe.handle1; this.cppSide_.backPointerResponse(createEchoArgsList(arg)); - messagePipe.handle0.close(); + core.close(messagePipe.handle0); iteration += 1; } @@ -153,9 +162,10 @@ }; function writeDataPipe(pipe, data) { - var writeResult = pipe.producer.writeData(data); + var writeResult = core.writeData( + pipe.producerHandle, data, core.WRITE_DATA_FLAG_ALL_OR_NONE); - if (writeResult.result != Mojo.RESULT_OK) { + if (writeResult.result != core.RESULT_OK) { console.log('ERROR: Data pipe write result was ' + writeResult.result); return false; } @@ -167,8 +177,8 @@ } function writeMessagePipe(pipe, arrayBuffer) { - var result = pipe.handle0.writeMessage(arrayBuffer, []); - if (result != Mojo.RESULT_OK) { + var result = core.writeMessage(pipe.handle0, arrayBuffer, [], 0); + if (result != core.RESULT_OK) { console.log('ERROR: Message pipe write result was ' + result); return false; } @@ -202,4 +212,4 @@ retainedJsSide = new JsSideConnection; retainedJsSide.binding.bind(jsSideRequestHandle); }; -})(); +});
diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc index 1595add..a9a1d90f 100644 --- a/mojo/edk/system/core.cc +++ b/mojo/edk/system/core.cc
@@ -462,53 +462,6 @@ ready_signals_states); } -MojoResult Core::AllocMessage(uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoAllocMessageFlags flags, - MojoMessageHandle* message_handle) { - if (!message_handle) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (num_handles == 0) { // Fast path: no handles. - std::unique_ptr<ports::UserMessageEvent> message; - MojoResult rv = UserMessageImpl::CreateEventForNewSerializedMessage( - num_bytes, nullptr, 0, &message); - if (rv != MOJO_RESULT_OK) - return rv; - - *message_handle = reinterpret_cast<MojoMessageHandle>(message.release()); - return MOJO_RESULT_OK; - } - - if (!handles) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (num_handles > kMaxHandlesPerMessage) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - // If serialization fails below this point, one or more handles may be closed. - // This requires an active RequestContext. - RequestContext request_context; - - std::vector<Dispatcher::DispatcherInTransit> dispatchers; - MojoResult acquire_result = - AcquireDispatchersForTransit(handles, num_handles, &dispatchers); - if (acquire_result != MOJO_RESULT_OK) - return acquire_result; - - DCHECK_EQ(num_handles, dispatchers.size()); - std::unique_ptr<ports::UserMessageEvent> message; - MojoResult rv = UserMessageImpl::CreateEventForNewSerializedMessage( - num_bytes, dispatchers.data(), num_handles, &message); - - ReleaseDispatchersForTransit(dispatchers, rv == MOJO_RESULT_OK); - if (rv == MOJO_RESULT_OK) - *message_handle = reinterpret_cast<MojoMessageHandle>(message.release()); - - return rv; -} - MojoResult Core::CreateMessage(uintptr_t context, const MojoMessageOperationThunks* thunks, MojoMessageHandle* message_handle) { @@ -572,19 +525,20 @@ return MOJO_RESULT_RESOURCE_EXHAUSTED; *buffer = message->user_payload(); + } else if (buffer) { + *buffer = nullptr; } - if (flags & MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_IGNORE_HANDLES) - return MOJO_RESULT_OK; - uint32_t max_num_handles = 0; if (num_handles) { max_num_handles = *num_handles; *num_handles = static_cast<uint32_t>(message->num_handles()); } - if (message->num_handles() > max_num_handles) + if (message->num_handles() > max_num_handles || + message->num_handles() > kMaxHandlesPerMessage) { return MOJO_RESULT_RESOURCE_EXHAUSTED; + } return message->ExtractSerializedHandles( UserMessageImpl::ExtractBadHandlePolicy::kAbort, handles); @@ -649,32 +603,8 @@ } MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, - const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, + MojoMessageHandle message_handle, MojoWriteMessageFlags flags) { - if (num_bytes && !bytes) - return MOJO_RESULT_INVALID_ARGUMENT; - - MojoMessageHandle message_handle; - MojoResult rv = AllocMessage(num_bytes, handles, num_handles, - MOJO_ALLOC_MESSAGE_FLAG_NONE, &message_handle); - if (rv != MOJO_RESULT_OK) - return rv; - - if (num_bytes) { - auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle) - ->GetMessage<UserMessageImpl>(); - memcpy(message->user_payload(), bytes, num_bytes); - } - - return WriteMessageNew(message_pipe_handle, message_handle, flags); -} - -MojoResult Core::WriteMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle message_handle, - MojoWriteMessageFlags flags) { RequestContext request_context; if (!message_handle) return MOJO_RESULT_INVALID_ARGUMENT; @@ -687,73 +617,18 @@ } MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, - void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, + MojoMessageHandle* message_handle, MojoReadMessageFlags flags) { - DCHECK((!num_handles || !*num_handles || handles) && - (!num_bytes || !*num_bytes || bytes)); - RequestContext request_context; - auto dispatcher = GetDispatcher(message_pipe_handle); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - std::unique_ptr<ports::UserMessageEvent> message_event; - const uint32_t max_payload_size = num_bytes ? *num_bytes : 0; - const uint32_t max_num_handles = num_handles ? *num_handles : 0; - auto discard_policy = flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD - ? Dispatcher::ReadMessageDiscardPolicy::kMayDiscard - : Dispatcher::ReadMessageDiscardPolicy::kNoDiscard; - MojoResult rv = - dispatcher->ReadMessage(Dispatcher::ReadMessageSizePolicy::kLimitedSize, - discard_policy, max_payload_size, max_num_handles, - &message_event, num_bytes, num_handles); - if (rv != MOJO_RESULT_OK) - return rv; - - // Some tests use fake message pipe dispatchers which return null events. - // - // TODO(rockot): Fix the tests, because this is weird. - if (!message_event) - return MOJO_RESULT_OK; - - auto* message = message_event->GetMessage<UserMessageImpl>(); - DCHECK(message->IsSerialized()); - if (message->num_handles()) { - DCHECK_LE(message->num_handles(), max_num_handles); - MojoResult extract_result = message->ExtractSerializedHandles( - UserMessageImpl::ExtractBadHandlePolicy::kAbort, handles); - if (extract_result != MOJO_RESULT_OK) - return extract_result; - } - if (message->user_payload_size()) { - DCHECK_LE(message->user_payload_size(), max_payload_size); - memcpy(bytes, message->user_payload(), message->user_payload_size()); - } - return MOJO_RESULT_OK; -} - -MojoResult Core::ReadMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle* message_handle, - MojoReadMessageFlags flags) { RequestContext request_context; auto dispatcher = GetDispatcher(message_pipe_handle); if (!dispatcher || !message_handle) return MOJO_RESULT_INVALID_ARGUMENT; std::unique_ptr<ports::UserMessageEvent> message_event; - MojoResult rv = - dispatcher->ReadMessage(Dispatcher::ReadMessageSizePolicy::kAnySize, - Dispatcher::ReadMessageDiscardPolicy::kNoDiscard, - 0, 0, &message_event, nullptr, nullptr); + MojoResult rv = dispatcher->ReadMessage(&message_event); if (rv != MOJO_RESULT_OK) return rv; - // If there's nowhere to store the message handle and discard is allowed by - // the caller, we simply drop the message event. - if (flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD && !message_handle) - return MOJO_RESULT_OK; - *message_handle = reinterpret_cast<MojoMessageHandle>(message_event.release()); return MOJO_RESULT_OK;
diff --git a/mojo/edk/system/core.h b/mojo/edk/system/core.h index 5dd074e..ca95c63a 100644 --- a/mojo/edk/system/core.h +++ b/mojo/edk/system/core.h
@@ -190,11 +190,6 @@ uintptr_t* ready_contexts, MojoResult* ready_results, MojoHandleSignalsState* ready_signals_states); - MojoResult AllocMessage(uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoAllocMessageFlags flags, - MojoMessageHandle* message_handle); MojoResult CreateMessage(uintptr_t context, const MojoMessageOperationThunks* thunks, MojoMessageHandle* message_handle); @@ -218,23 +213,11 @@ MojoHandle* message_pipe_handle0, MojoHandle* message_pipe_handle1); MojoResult WriteMessage(MojoHandle message_pipe_handle, - const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, + MojoMessageHandle message_handle, MojoWriteMessageFlags flags); - MojoResult WriteMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle message_handle, - MojoWriteMessageFlags flags); MojoResult ReadMessage(MojoHandle message_pipe_handle, - void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, + MojoMessageHandle* message_handle, MojoReadMessageFlags flags); - MojoResult ReadMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle* message_handle, - MojoReadMessageFlags flags); MojoResult FuseMessagePipes(MojoHandle handle0, MojoHandle handle1); MojoResult NotifyBadMessage(MojoMessageHandle message_handle, const char* error,
diff --git a/mojo/edk/system/core_test_base.cc b/mojo/edk/system/core_test_base.cc index 86e484f3..05a7f45 100644 --- a/mojo/edk/system/core_test_base.cc +++ b/mojo/edk/system/core_test_base.cc
@@ -49,13 +49,7 @@ } MojoResult ReadMessage( - ReadMessageSizePolicy size_policy, - ReadMessageDiscardPolicy discard_policy, - uint32_t max_payload_size, - uint32_t max_num_handles, - std::unique_ptr<ports::UserMessageEvent>* message_event, - uint32_t* actual_payload_size, - uint32_t* actual_num_handles) override { + std::unique_ptr<ports::UserMessageEvent>* message_event) override { info_->IncrementReadMessageCallCount(); return MOJO_RESULT_OK; }
diff --git a/mojo/edk/system/core_unittest.cc b/mojo/edk/system/core_unittest.cc index 60057e3..13d67f89 100644 --- a/mojo/edk/system/core_unittest.cc +++ b/mojo/edk/system/core_unittest.cc
@@ -30,6 +30,28 @@ using CoreTest = test::CoreTestBase; +void UnusedGetSerializedSize(uintptr_t context, + size_t* num_bytes, + size_t* num_handles) {} +void UnusedSerializeHandles(uintptr_t context, MojoHandle* handles) {} +void UnusedSerializePayload(uintptr_t context, void* buffer) {} +void IgnoreDestroyMessage(uintptr_t context) {} + +const MojoMessageOperationThunks kUnusedMessageThunks = { + sizeof(MojoMessageOperationThunks), + &UnusedGetSerializedSize, + &UnusedSerializeHandles, + &UnusedSerializePayload, + &IgnoreDestroyMessage, +}; + +MojoMessageHandle CreateTestMessageHandle(Core* core, uintptr_t context) { + MojoMessageHandle handle; + CHECK_EQ(MOJO_RESULT_OK, + core->CreateMessage(context, &kUnusedMessageThunks, &handle)); + return handle; +} + TEST_F(CoreTest, GetTimeTicksNow) { const MojoTimeTicks start = core()->GetTimeTicksNow(); ASSERT_NE(static_cast<MojoTimeTicks>(0), start) @@ -53,15 +75,16 @@ MojoMessageHandle message; ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(42, nullptr, &message)); ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteMessageNew(h, message, MOJO_WRITE_MESSAGE_FLAG_NONE)); + core()->WriteMessage(h, CreateTestMessageHandle(core(), 42), + MOJO_WRITE_MESSAGE_FLAG_NONE)); ASSERT_EQ(1u, info.GetWriteMessageCallCount()); ASSERT_EQ(0u, info.GetReadMessageCallCount()); ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadMessageNew(h, &message, MOJO_READ_MESSAGE_FLAG_NONE)); + core()->ReadMessage(h, &message, MOJO_READ_MESSAGE_FLAG_NONE)); ASSERT_EQ(1u, info.GetReadMessageCallCount()); ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadMessageNew(h, &message, MOJO_READ_MESSAGE_FLAG_NONE)); + core()->ReadMessage(h, &message, MOJO_READ_MESSAGE_FLAG_NONE)); ASSERT_EQ(2u, info.GetReadMessageCallCount()); ASSERT_EQ(0u, info.GetWriteDataCallCount()); @@ -125,8 +148,8 @@ // |num_handles|. { ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessageNew(MOJO_HANDLE_INVALID, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); + core()->WriteMessage(MOJO_HANDLE_INVALID, 0, + MOJO_WRITE_MESSAGE_FLAG_NONE)); } // |ReadMessageNew()|: @@ -134,12 +157,12 @@ // |num_handles|. { ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->ReadMessageNew(MOJO_HANDLE_INVALID, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); + core()->ReadMessage(MOJO_HANDLE_INVALID, nullptr, + MOJO_READ_MESSAGE_FLAG_NONE)); MockHandleInfo info; MojoHandle h = CreateMockHandle(&info); ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->ReadMessageNew(h, nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); + core()->ReadMessage(h, nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); // Checked by |Core|, shouldn't go through to the dispatcher. ASSERT_EQ(0u, info.GetReadMessageCallCount()); ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h)); @@ -168,24 +191,23 @@ // Try to read anyway. MojoMessageHandle message; - ASSERT_EQ( - MOJO_RESULT_SHOULD_WAIT, - core()->ReadMessageNew(h[0], &message, MOJO_READ_MESSAGE_FLAG_NONE)); + ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, + core()->ReadMessage(h[0], &message, MOJO_READ_MESSAGE_FLAG_NONE)); // Write to |h[1]|. const uintptr_t kTestMessageContext = 123; ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(kTestMessageContext, nullptr, &message)); - ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessageNew( - h[1], message, MOJO_WRITE_MESSAGE_FLAG_NONE)); + ASSERT_EQ(MOJO_RESULT_OK, + core()->WriteMessage(h[1], message, MOJO_WRITE_MESSAGE_FLAG_NONE)); // Wait for |h[0]| to become readable. EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h[0]), MOJO_HANDLE_SIGNAL_READABLE, &hss[0])); // Read from |h[0]|. - ASSERT_EQ(MOJO_RESULT_OK, core()->ReadMessageNew( - h[0], &message, MOJO_READ_MESSAGE_FLAG_NONE)); + ASSERT_EQ(MOJO_RESULT_OK, + core()->ReadMessage(h[0], &message, MOJO_READ_MESSAGE_FLAG_NONE)); uintptr_t context; ASSERT_EQ(MOJO_RESULT_OK, core()->ReleaseMessageContext(message, &context)); ASSERT_EQ(kTestMessageContext, context); @@ -200,8 +222,8 @@ // Write to |h[0]|. ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(kTestMessageContext, nullptr, &message)); - ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessageNew( - h[0], message, MOJO_WRITE_MESSAGE_FLAG_NONE)); + ASSERT_EQ(MOJO_RESULT_OK, + core()->WriteMessage(h[0], message, MOJO_WRITE_MESSAGE_FLAG_NONE)); // Close |h[0]|. ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h[0])); @@ -224,8 +246,8 @@ hss[1].satisfiable_signals); // Discard a message from |h[1]|. - ASSERT_EQ(MOJO_RESULT_OK, core()->ReadMessageNew( - h[1], &message, MOJO_READ_MESSAGE_FLAG_NONE)); + ASSERT_EQ(MOJO_RESULT_OK, + core()->ReadMessage(h[1], &message, MOJO_READ_MESSAGE_FLAG_NONE)); ASSERT_EQ(MOJO_RESULT_OK, core()->FreeMessage(message)); // |h[1]| is no longer readable (and will never be). @@ -237,9 +259,8 @@ // Try writing to |h[1]|. ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(kTestMessageContext, nullptr, &message)); - ASSERT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WriteMessageNew(h[1], message, MOJO_WRITE_MESSAGE_FLAG_NONE)); + ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, + core()->WriteMessage(h[1], message, MOJO_WRITE_MESSAGE_FLAG_NONE)); ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h[1])); } @@ -256,9 +277,8 @@ MojoMessageHandle message; ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(kTestMessageContext, nullptr, &message)); - ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteMessageNew(h_passing[0], message, - MOJO_WRITE_MESSAGE_FLAG_NONE)); + ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h_passing[0], message, + MOJO_WRITE_MESSAGE_FLAG_NONE)); hss = kEmptyMojoHandleSignalsState; EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h_passing[1]), MOJO_HANDLE_SIGNAL_READABLE, &hss)); @@ -266,9 +286,8 @@ hss.satisfied_signals); ASSERT_EQ(kAllSignals, hss.satisfiable_signals); MojoMessageHandle message_handle; - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadMessageNew(h_passing[1], &message_handle, - MOJO_READ_MESSAGE_FLAG_NONE)); + ASSERT_EQ(MOJO_RESULT_OK, core()->ReadMessage(h_passing[1], &message_handle, + MOJO_READ_MESSAGE_FLAG_NONE)); uintptr_t context; ASSERT_EQ(MOJO_RESULT_OK, core()->ReleaseMessageContext(message_handle, &context));
diff --git a/mojo/edk/system/dispatcher.cc b/mojo/edk/system/dispatcher.cc index f5cd9d3..027c518 100644 --- a/mojo/edk/system/dispatcher.cc +++ b/mojo/edk/system/dispatcher.cc
@@ -47,13 +47,7 @@ } MojoResult Dispatcher::ReadMessage( - ReadMessageSizePolicy size_policy, - ReadMessageDiscardPolicy discard_policy, - uint32_t max_payload_size, - uint32_t max_num_handles, - std::unique_ptr<ports::UserMessageEvent>* message, - uint32_t* actual_payload_size, - uint32_t* actual_num_handles) { + std::unique_ptr<ports::UserMessageEvent>* message) { return MOJO_RESULT_INVALID_ARGUMENT; }
diff --git a/mojo/edk/system/dispatcher.h b/mojo/edk/system/dispatcher.h index 8275202..60eff86 100644 --- a/mojo/edk/system/dispatcher.h +++ b/mojo/edk/system/dispatcher.h
@@ -63,35 +63,6 @@ PLATFORM_HANDLE = -1, }; - // Transitional enum so that ReadMessage can service both MojoReadMessage and - // MojoReadMessageNew. To be deleted once MojoReadMessageNew replaces - // MojoReadMessage. This is used to decide whether ReadMessage should restrict - // the size of the next message it reads, according to its other arguments. - enum class ReadMessageSizePolicy { - // ReadMessage ignores its sizing arguments and reads any available message. - kAnySize, - - // ReadMessage only reads the next available message if it fits within the - // size constraints given. - kLimitedSize, - }; - - // Transitional enum so that ReadMessage can service both MojoReadMessage and - // MojoReadMessageNew. To be deleted once MojoReadMessageNew replaces - // MojoReadMessage. If the selected |ReadMessageSizePolicy| is |kLimitedSize|, - // this chooses how to proceed when the provided size constraints are exceeded - // by the next available message. If |ReadMessageSizePolicy| is |kAnySize| - // this argument is ignored. - enum class ReadMessageDiscardPolicy { - // Never discard a message. ReadMessage will return an appropriate error - // code if the next available message exceeds the given size constraints. - kNoDiscard, - - // Discards the next available message if it exceeds the given size - // constraints. - kMayDiscard, - }; - // All Dispatchers must minimally implement these methods. virtual Type GetType() const = 0; @@ -115,13 +86,7 @@ MojoWriteMessageFlags flags); virtual MojoResult ReadMessage( - ReadMessageSizePolicy size_policy, - ReadMessageDiscardPolicy discard_policy, - uint32_t max_payload_size, - uint32_t max_num_handles, - std::unique_ptr<ports::UserMessageEvent>* message, - uint32_t* actual_payload_size, - uint32_t* actual_num_handles); + std::unique_ptr<ports::UserMessageEvent>* message); ///////////// Shared buffer API /////////////
diff --git a/mojo/edk/system/message_pipe_dispatcher.cc b/mojo/edk/system/message_pipe_dispatcher.cc index 2c313e9..e18998f 100644 --- a/mojo/edk/system/message_pipe_dispatcher.cc +++ b/mojo/edk/system/message_pipe_dispatcher.cc
@@ -165,26 +165,35 @@ } MojoResult MessagePipeDispatcher::ReadMessage( - ReadMessageSizePolicy size_policy, - ReadMessageDiscardPolicy discard_policy, - uint32_t max_payload_size, - uint32_t max_num_handles, - std::unique_ptr<ports::UserMessageEvent>* message, - uint32_t* actual_payload_size, - uint32_t* actual_num_handles) { + std::unique_ptr<ports::UserMessageEvent>* message) { // We can't read from a port that's closed or in transit! if (port_closed_ || in_transit_) return MOJO_RESULT_INVALID_ARGUMENT; - MojoResult rv = UserMessageImpl::ReadMessageEventFromPort( - port_, size_policy, discard_policy, max_payload_size, max_num_handles, - message, actual_payload_size, actual_num_handles); + int rv = node_controller_->node()->GetMessage(port_, message, nullptr); + if (rv != ports::OK && rv != ports::ERROR_PORT_PEER_CLOSED) { + if (rv == ports::ERROR_PORT_UNKNOWN || + rv == ports::ERROR_PORT_STATE_UNEXPECTED) + return MOJO_RESULT_INVALID_ARGUMENT; + + NOTREACHED(); + return MOJO_RESULT_UNKNOWN; + } + + if (!*message) { + // No message was available in queue. + if (rv == ports::OK) + return MOJO_RESULT_SHOULD_WAIT; + // Peer is closed and there are no more messages to read. + DCHECK_EQ(rv, ports::ERROR_PORT_PEER_CLOSED); + return MOJO_RESULT_FAILED_PRECONDITION; + } // We may need to update anyone watching our signals in case we just read the // last available message. base::AutoLock lock(signal_lock_); watchers_.NotifyState(GetHandleSignalsStateNoLock()); - return rv; + return MOJO_RESULT_OK; } HandleSignalsState
diff --git a/mojo/edk/system/message_pipe_dispatcher.h b/mojo/edk/system/message_pipe_dispatcher.h index 24cf42f..8d8f045 100644 --- a/mojo/edk/system/message_pipe_dispatcher.h +++ b/mojo/edk/system/message_pipe_dispatcher.h
@@ -49,13 +49,8 @@ MojoResult Close() override; MojoResult WriteMessage(std::unique_ptr<ports::UserMessageEvent> message, MojoWriteMessageFlags flags) override; - MojoResult ReadMessage(ReadMessageSizePolicy size_policy, - ReadMessageDiscardPolicy discard_policy, - uint32_t max_payload_size, - uint32_t max_num_handles, - std::unique_ptr<ports::UserMessageEvent>* message, - uint32_t* actual_payload_size, - uint32_t* actual_num_handles) override; + MojoResult ReadMessage( + std::unique_ptr<ports::UserMessageEvent>* message) override; HandleSignalsState GetHandleSignalsState() const override; MojoResult AddWatcherRef(const scoped_refptr<WatcherDispatcher>& watcher, uintptr_t context) override;
diff --git a/mojo/edk/system/message_pipe_unittest.cc b/mojo/edk/system/message_pipe_unittest.cc index fb7c6365..eb15d96 100644 --- a/mojo/edk/system/message_pipe_unittest.cc +++ b/mojo/edk/system/message_pipe_unittest.cc
@@ -53,8 +53,8 @@ uint32_t* num_bytes, bool may_discard = false) { MojoMessageHandle message_handle; - MojoResult rv = MojoReadMessageNew(message_pipe_handle, &message_handle, - MOJO_READ_MESSAGE_FLAG_NONE); + MojoResult rv = MojoReadMessage(message_pipe_handle, &message_handle, + MOJO_READ_MESSAGE_FLAG_NONE); if (rv != MOJO_RESULT_OK) return rv;
diff --git a/mojo/edk/system/message_unittest.cc b/mojo/edk/system/message_unittest.cc index b9b4398..8078b01 100644 --- a/mojo/edk/system/message_unittest.cc +++ b/mojo/edk/system/message_unittest.cc
@@ -143,24 +143,22 @@ }; TEST_F(MessageTest, InvalidMessageObjects) { - // null message ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoFreeMessage(MOJO_MESSAGE_HANDLE_INVALID)); - // null message ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoGetSerializedMessageContents( MOJO_MESSAGE_HANDLE_INVALID, nullptr, nullptr, nullptr, nullptr, MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE)); - // null message ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoSerializeMessage(MOJO_MESSAGE_HANDLE_INVALID)); - // Non-zero num_handles with null handles array. - ASSERT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - MojoAllocMessage(0, nullptr, 1, MOJO_ALLOC_MESSAGE_FLAG_NONE, nullptr)); + MojoMessageHandle message_handle; + ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + MojoCreateMessage(0, nullptr, &message_handle)); + ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + MojoCreateMessage(1234, nullptr, nullptr)); } TEST_F(MessageTest, SendLocalMessageWithContext) { @@ -172,14 +170,14 @@ MojoHandle a, b; CreateMessagePipe(&a, &b); EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessageNew( + MojoWriteMessage( a, TestMessageBase::MakeMessageHandle(std::move(message)), MOJO_WRITE_MESSAGE_FLAG_NONE)); EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE)); MojoMessageHandle read_message_handle; - EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessageNew(b, &read_message_handle, - MOJO_READ_MESSAGE_FLAG_NONE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(b, &read_message_handle, + MOJO_READ_MESSAGE_FLAG_NONE)); message = TestMessageBase::UnwrapMessageHandle<NeverSerializedMessage>( &read_message_handle); EXPECT_EQ(original_message, message.get()); @@ -217,8 +215,8 @@ TEST_F(MessageTest, SerializeSimpleMessageNoHandlesWithContext) { RUN_CHILD_ON_PIPE(ReceiveMessageNoHandles, h) auto message = base::MakeUnique<SimpleMessage>(kTestMessageWithContext1); - MojoWriteMessageNew(h, TestMessageBase::MakeMessageHandle(std::move(message)), - MOJO_WRITE_MESSAGE_FLAG_NONE); + MojoWriteMessage(h, TestMessageBase::MakeMessageHandle(std::move(message)), + MOJO_WRITE_MESSAGE_FLAG_NONE); END_CHILD() } @@ -235,8 +233,8 @@ auto message = base::MakeUnique<SimpleMessage>(kTestMessageWithContext1); mojo::MessagePipe pipe; message->AddMessagePipe(std::move(pipe.handle0)); - MojoWriteMessageNew(h, TestMessageBase::MakeMessageHandle(std::move(message)), - MOJO_WRITE_MESSAGE_FLAG_NONE); + MojoWriteMessage(h, TestMessageBase::MakeMessageHandle(std::move(message)), + MOJO_WRITE_MESSAGE_FLAG_NONE); EXPECT_EQ(kTestMessageWithContext2, MojoTestBase::ReadMessage(pipe.handle1.get().value())); END_CHILD() @@ -261,8 +259,8 @@ message->AddMessagePipe(std::move(pipes[1].handle0)); message->AddMessagePipe(std::move(pipes[2].handle0)); message->AddMessagePipe(std::move(pipes[3].handle0)); - MojoWriteMessageNew(h, TestMessageBase::MakeMessageHandle(std::move(message)), - MOJO_WRITE_MESSAGE_FLAG_NONE); + MojoWriteMessage(h, TestMessageBase::MakeMessageHandle(std::move(message)), + MOJO_WRITE_MESSAGE_FLAG_NONE); EXPECT_EQ(kTestMessageWithContext1, MojoTestBase::ReadMessage(pipes[0].handle1.get().value())); EXPECT_EQ(kTestMessageWithContext2, @@ -292,14 +290,14 @@ MojoHandle a, b; CreateMessagePipe(&a, &b); EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessageNew( + MojoWriteMessage( a, TestMessageBase::MakeMessageHandle(std::move(message)), MOJO_WRITE_MESSAGE_FLAG_NONE)); EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE)); MojoMessageHandle read_message_handle; - EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessageNew(b, &read_message_handle, - MOJO_READ_MESSAGE_FLAG_NONE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(b, &read_message_handle, + MOJO_READ_MESSAGE_FLAG_NONE)); message = TestMessageBase::UnwrapMessageHandle<SimpleMessage>(&read_message_handle); EXPECT_EQ(original_message, message.get()); @@ -328,7 +326,7 @@ MojoHandle a, b; CreateMessagePipe(&a, &b); EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessageNew( + MojoWriteMessage( a, TestMessageBase::MakeMessageHandle(std::move(message)), MOJO_WRITE_MESSAGE_FLAG_NONE)); MojoClose(a); @@ -349,14 +347,14 @@ MojoHandle a, b; CreateMessagePipe(&a, &b); EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessageNew( + MojoWriteMessage( a, TestMessageBase::MakeMessageHandle(std::move(message)), MOJO_WRITE_MESSAGE_FLAG_NONE)); EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE)); MojoMessageHandle message_handle; - EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessageNew(b, &message_handle, - MOJO_READ_MESSAGE_FLAG_NONE)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoReadMessage(b, &message_handle, MOJO_READ_MESSAGE_FLAG_NONE)); EXPECT_FALSE(message_was_destroyed); // Not a serialized message, so we can't get serialized contents. @@ -383,8 +381,8 @@ EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE)); MojoMessageHandle message_handle; - EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessageNew(b, &message_handle, - MOJO_READ_MESSAGE_FLAG_NONE)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoReadMessage(b, &message_handle, MOJO_READ_MESSAGE_FLAG_NONE)); uintptr_t context; EXPECT_EQ(MOJO_RESULT_NOT_FOUND, MojoReleaseMessageContext(message_handle, &context)); @@ -441,10 +439,6 @@ MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE)); EXPECT_EQ(MOJO_RESULT_OK, MojoGetSerializedMessageContents( - message_handle, &buffer, &num_bytes, nullptr, nullptr, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_IGNORE_HANDLES)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoGetSerializedMessageContents( message_handle, &buffer, &num_bytes, &extracted_handle, &num_handles, MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE)); EXPECT_EQ(std::string(kTestMessageWithContext1).size(), num_bytes); @@ -482,13 +476,13 @@ // message object from a pipe. MessagePipe pipe; EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessageNew(pipe.handle0->value(), message_handle, - MOJO_WRITE_MESSAGE_FLAG_NONE)); + MojoWriteMessage(pipe.handle0->value(), message_handle, + MOJO_WRITE_MESSAGE_FLAG_NONE)); EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(pipe.handle1->value(), MOJO_HANDLE_SIGNAL_READABLE)); EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessageNew(pipe.handle1->value(), &message_handle, - MOJO_READ_MESSAGE_FLAG_NONE)); + MojoReadMessage(pipe.handle1->value(), &message_handle, + MOJO_READ_MESSAGE_FLAG_NONE)); EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, MojoSerializeMessage(message_handle));
diff --git a/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/mojo/edk/system/multiprocess_message_pipe_unittest.cc index 0087cc5..141acb5 100644 --- a/mojo/edk/system/multiprocess_message_pipe_unittest.cc +++ b/mojo/edk/system/multiprocess_message_pipe_unittest.cc
@@ -1371,7 +1371,7 @@ ASSERT_EQ(MOJO_RESULT_OK, WaitForSignals(a, MOJO_HANDLE_SIGNAL_READABLE)); MojoMessageHandle message; ASSERT_EQ(MOJO_RESULT_OK, - MojoReadMessageNew(a, &message, MOJO_READ_MESSAGE_FLAG_NONE)); + ::MojoReadMessage(a, &message, MOJO_READ_MESSAGE_FLAG_NONE)); EXPECT_EQ(MOJO_RESULT_OK, MojoNotifyBadMessage(message, kFirstErrorMessage.data(), kFirstErrorMessage.size())); @@ -1380,7 +1380,7 @@ // Read a message from the pipe we sent to child2 and flag it as bad. ASSERT_EQ(MOJO_RESULT_OK, WaitForSignals(c, MOJO_HANDLE_SIGNAL_READABLE)); ASSERT_EQ(MOJO_RESULT_OK, - MojoReadMessageNew(c, &message, MOJO_READ_MESSAGE_FLAG_NONE)); + ::MojoReadMessage(c, &message, MOJO_READ_MESSAGE_FLAG_NONE)); EXPECT_EQ(MOJO_RESULT_OK, MojoNotifyBadMessage(message, kSecondErrorMessage.data(), kSecondErrorMessage.size()));
diff --git a/mojo/edk/system/user_message_impl.cc b/mojo/edk/system/user_message_impl.cc index 72334e09..727a4d2 100644 --- a/mojo/edk/system/user_message_impl.cc +++ b/mojo/edk/system/user_message_impl.cc
@@ -172,93 +172,6 @@ } // namespace -// A MessageFilter used by UserMessageImpl::ReadMessageEventFromPort to -// determine whether a message should actually be consumed yet. -class UserMessageImpl::ReadMessageFilter : public ports::MessageFilter { - public: - // Creates a new ReadMessageFilter which captures and potentially modifies - // various (unowned) local state within - // UserMessageImpl::ReadMessageEventFromPort. - ReadMessageFilter(Dispatcher::ReadMessageSizePolicy size_policy, - Dispatcher::ReadMessageDiscardPolicy discard_policy, - uint32_t max_payload_size, - uint32_t max_num_handles, - uint32_t* actual_payload_size, - uint32_t* actual_num_handles, - bool* exceeds_size_limit_flag, - bool* invalid_message_flag) - : size_policy_(size_policy), - discard_policy_(discard_policy), - max_payload_size_(max_payload_size), - max_num_handles_(max_num_handles), - actual_payload_size_(actual_payload_size), - actual_num_handles_(actual_num_handles), - exceeds_size_limit_flag_(exceeds_size_limit_flag), - invalid_message_flag_(invalid_message_flag) {} - - ~ReadMessageFilter() override {} - - // ports::MessageFilter: - bool Match(const ports::UserMessageEvent& event) override { - const auto* message = event.GetMessage<UserMessageImpl>(); - if (!message->IsSerialized()) { - // Not a serialized message, so there's nothing to validate or filter - // against. We only ensure that the caller expected a message object and - // not a specific serialized buffer size. - if (size_policy_ != Dispatcher::ReadMessageSizePolicy::kAnySize) { - *invalid_message_flag_ = true; - return false; - } - return true; - } - - // All messages which reach this filter have already had a basic level of - // validation applied by UserMessageImpl::CreateFromChannelMessage() - // so we know there is at least well-formed header. - DCHECK(message->header_); - auto* header = static_cast<MessageHeader*>(message->header_); - - base::CheckedNumeric<uint32_t> checked_bytes_available = - message->user_payload_size(); - if (!checked_bytes_available.IsValid()) { - *invalid_message_flag_ = true; - return true; - } - const uint32_t bytes_available = checked_bytes_available.ValueOrDie(); - const uint32_t bytes_to_read = std::min(max_payload_size_, bytes_available); - if (actual_payload_size_) - *actual_payload_size_ = bytes_available; - - const uint32_t handles_available = header->num_dispatchers; - const uint32_t handles_to_read = - std::min(max_num_handles_, handles_available); - if (actual_num_handles_) - *actual_num_handles_ = handles_available; - - if ((handles_to_read < handles_available || - bytes_to_read < bytes_available) && - size_policy_ == Dispatcher::ReadMessageSizePolicy::kLimitedSize) { - *exceeds_size_limit_flag_ = true; - return discard_policy_ == - Dispatcher::ReadMessageDiscardPolicy::kMayDiscard; - } - - return true; - } - - private: - const Dispatcher::ReadMessageSizePolicy size_policy_; - const Dispatcher::ReadMessageDiscardPolicy discard_policy_; - const uint32_t max_payload_size_; - const uint32_t max_num_handles_; - uint32_t* const actual_payload_size_; - uint32_t* const actual_num_handles_; - bool* const exceeds_size_limit_flag_; - bool* const invalid_message_flag_; - - DISALLOW_COPY_AND_ASSIGN(ReadMessageFilter); -}; - // static const ports::UserMessage::TypeInfo UserMessageImpl::kUserMessageTypeInfo = {}; @@ -339,58 +252,6 @@ } // static -MojoResult UserMessageImpl::ReadMessageEventFromPort( - const ports::PortRef& port, - Dispatcher::ReadMessageSizePolicy size_policy, - Dispatcher::ReadMessageDiscardPolicy discard_policy, - uint32_t max_payload_size, - uint32_t max_num_handles, - std::unique_ptr<ports::UserMessageEvent>* out_event, - uint32_t* actual_payload_size, - uint32_t* actual_num_handles) { - bool exceeds_size_limit = false; - bool invalid_message = false; - ReadMessageFilter filter(size_policy, discard_policy, max_payload_size, - max_num_handles, actual_payload_size, - actual_num_handles, &exceeds_size_limit, - &invalid_message); - std::unique_ptr<ports::UserMessageEvent> message_event; - int rv = internal::g_core->GetNodeController()->node()->GetMessage( - port, &message_event, &filter); - if (invalid_message) - return MOJO_RESULT_NOT_FOUND; - - if (rv != ports::OK && rv != ports::ERROR_PORT_PEER_CLOSED) { - if (rv == ports::ERROR_PORT_UNKNOWN || - rv == ports::ERROR_PORT_STATE_UNEXPECTED) - return MOJO_RESULT_INVALID_ARGUMENT; - - NOTREACHED(); - return MOJO_RESULT_UNKNOWN; - } - - if (exceeds_size_limit) { - // |size_policy| is |kLimitedSize| and the next available message exceeded - // the constraints specified by |max_payload_size| and/or |max_num_handles|. - // The message may or may not have been read off the pipe, depending on the - // given value of |discard_policy|. - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - - if (!message_event) { - // No message was available in queue. - if (rv == ports::OK) - return MOJO_RESULT_SHOULD_WAIT; - // Peer is closed and there are no more messages to read. - DCHECK_EQ(rv, ports::ERROR_PORT_PEER_CLOSED); - return MOJO_RESULT_FAILED_PRECONDITION; - } - - *out_event = std::move(message_event); - return MOJO_RESULT_OK; -} - -// static Channel::MessagePtr UserMessageImpl::FinalizeEventMessage( std::unique_ptr<ports::UserMessageEvent> message_event) { auto* message = message_event->GetMessage<UserMessageImpl>();
diff --git a/mojo/edk/system/user_message_impl.h b/mojo/edk/system/user_message_impl.h index ce851b46..461e4e2 100644 --- a/mojo/edk/system/user_message_impl.h +++ b/mojo/edk/system/user_message_impl.h
@@ -78,17 +78,6 @@ void* payload, size_t payload_size); - // Attempts to read a message from the given |port|. - static MojoResult ReadMessageEventFromPort( - const ports::PortRef& port, - Dispatcher::ReadMessageSizePolicy size_policy, - Dispatcher::ReadMessageDiscardPolicy discard_policy, - uint32_t max_payload_size, - uint32_t max_num_handles, - std::unique_ptr<ports::UserMessageEvent>* out_event, - uint32_t* actual_payload_size, - uint32_t* actual_num_handles); - // Extracts the serialized Channel::Message from the UserMessageEvent in // |event|. |event| must have a serialized UserMessageImpl instance attached. // |message_event| is serialized into the front of the message payload before @@ -147,8 +136,6 @@ MojoHandle* handles); private: - class ReadMessageFilter; - // Creates an unserialized UserMessageImpl with an associated |context| and // |thunks|. If the message is ever going to be routed to another node (see // |WillBeRoutedExternally()| below), it will be serialized at that time using
diff --git a/mojo/public/c/system/message_pipe.h b/mojo/public/c/system/message_pipe.h index 68316d2..58f224b 100644 --- a/mojo/public/c/system/message_pipe.h +++ b/mojo/public/c/system/message_pipe.h
@@ -15,9 +15,7 @@ #include "mojo/public/c/system/system_export.h" #include "mojo/public/c/system/types.h" -// |MojoMessageHandle|: Used to refer to message objects created by -// |MojoAllocMessage()| and transferred by |MojoWriteMessageNew()| or -// |MojoReadMessageNew()|. +// |MojoMessageHandle|: Used to refer to message objects. typedef uintptr_t MojoMessageHandle; @@ -69,50 +67,27 @@ // |MojoReadMessageFlags|: Used to specify different modes to // |MojoReadMessage()|. // |MOJO_READ_MESSAGE_FLAG_NONE| - No flags; default mode. -// |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| - If the message is unable to be read -// for whatever reason (e.g., the caller-supplied buffer is too small), -// discard the message (i.e., simply dequeue it). typedef uint32_t MojoReadMessageFlags; #ifdef __cplusplus const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_NONE = 0; -const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_MAY_DISCARD = 1 << 0; #else #define MOJO_READ_MESSAGE_FLAG_NONE ((MojoReadMessageFlags)0) -#define MOJO_READ_MESSAGE_FLAG_MAY_DISCARD ((MojoReadMessageFlags)1 << 0) -#endif - -// |MojoAllocMessageFlags|: Used to specify different options for -// |MojoAllocMessage()|. -// |MOJO_ALLOC_MESSAGE_FLAG_NONE| - No flags; default mode. - -typedef uint32_t MojoAllocMessageFlags; - -#ifdef __cplusplus -const MojoAllocMessageFlags MOJO_ALLOC_MESSAGE_FLAG_NONE = 0; -#else -#define MOJO_ALLOC_MESSAGE_FLAG_NONE ((MojoAllocMessageFlags)0) #endif // |MojoGetSerializedMessageContentsFlags|: Used to specify different options // |MojoGetSerializedMessageContents()|. // |MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE| - No flags; default mode. -// |MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_IGNORE_HANDLES| - Don't attempt -// to extract any handles from the serialized message. typedef uint32_t MojoGetSerializedMessageContentsFlags; #ifdef __cplusplus const MojoGetSerializedMessageContentsFlags MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE = 0; -const MojoGetSerializedMessageContentsFlags - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_IGNORE_HANDLES = 1 << 0; #else #define MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE \ ((MojoGetSerializedMessageContentsFlags)0) -#define MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_IGNORE_HANDLES \ - ((MojoGetSerializedMessageContentsFlags)1 << 0) #endif #ifdef __cplusplus @@ -192,112 +167,41 @@ MojoHandle* message_pipe_handle0, // Out. MojoHandle* message_pipe_handle1); // Out. -// Writes a message to the message pipe endpoint given by |message_pipe_handle|, -// with message data specified by |bytes| of size |num_bytes| and attached -// handles specified by |handles| of count |num_handles|, and options specified -// by |flags|. If there is no message data, |bytes| may be null, in which case -// |num_bytes| must be zero. If there are no attached handles, |handles| may be -// null, in which case |num_handles| must be zero. +// Writes a message to the message pipe endpoint given by |message_pipe_handle|. // -// If handles are attached, the handles will no longer be valid (on success the -// receiver will receive equivalent, but logically different, handles). Handles -// to be sent should not be in simultaneous use (e.g., on another thread). +// Note that regardless of success or failure, |message| is freed by this call +// and therefore invalidated. // // Returns: // |MOJO_RESULT_OK| on success (i.e., the message was enqueued). -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if -// |message_pipe_handle| is not a valid handle, or some of the -// requirements above are not satisfied). -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if some system limit has been reached, or -// the number of handles to send is too large (TODO(vtl): reconsider the -// latter case). +// |MOJO_RESULT_INVALID_ARGUMENT| if |message_pipe_handle| or |message| is +// invalid. // |MOJO_RESULT_FAILED_PRECONDITION| if the other endpoint has been closed. // Note that closing an endpoint is not necessarily synchronous (e.g., // across processes), so this function may succeed even if the other // endpoint has been closed (in which case the message would be dropped). -// |MOJO_RESULT_UNIMPLEMENTED| if an unsupported flag was set in |*options|. -// |MOJO_RESULT_BUSY| if some handle to be sent is currently in use. -// -// DEPRECATED: Use |MojoWriteMessageNew()|. -MOJO_SYSTEM_EXPORT MojoResult - MojoWriteMessage(MojoHandle message_pipe_handle, - const void* bytes, // Optional. - uint32_t num_bytes, - const MojoHandle* handles, // Optional. - uint32_t num_handles, - MojoWriteMessageFlags flags); +MOJO_SYSTEM_EXPORT MojoResult MojoWriteMessage(MojoHandle message_pipe_handle, + MojoMessageHandle message, + MojoWriteMessageFlags flags); -// Writes a message to the message pipe endpoint given by |message_pipe_handle|. -// -// |message|: A message object allocated by |MojoAllocMessage()| or -// |MojoCreateMessage()|. Ownership of the message is passed into Mojo. -// -// Returns results corresponding to |MojoWriteMessage()| above. -MOJO_SYSTEM_EXPORT MojoResult - MojoWriteMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle message, - MojoWriteMessageFlags); - -// Reads the next message from a message pipe, or indicates the size of the -// message if it cannot fit in the provided buffers. The message will be read -// in its entirety or not at all; if it is not, it will remain enqueued unless -// the |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| flag was passed. At most one -// message will be consumed from the queue, and the return value will indicate -// whether a message was successfully read. -// -// |num_bytes| and |num_handles| are optional in/out parameters that on input -// must be set to the sizes of the |bytes| and |handles| arrays, and on output -// will be set to the actual number of bytes or handles contained in the -// message (even if the message was not retrieved due to being too large). -// Either |num_bytes| or |num_handles| may be null if the message is not -// expected to contain the corresponding type of data, but such a call would -// fail with |MOJO_RESULT_RESOURCE_EXHAUSTED| if the message in fact did -// contain that type of data. -// -// |bytes| and |handles| will receive the contents of the message, if it is -// retrieved. Either or both may be null, in which case the corresponding size -// parameter(s) must also be set to zero or passed as null. -// -// Returns: -// |MOJO_RESULT_OK| on success (i.e., a message was actually read). -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid. -// |MOJO_RESULT_FAILED_PRECONDITION| if the other endpoint has been closed. -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if the message was too large to fit in the -// provided buffer(s). The message will have been left in the queue or -// discarded, depending on flags. -// |MOJO_RESULT_SHOULD_WAIT| if no message was available to be read. -// |MOJO_RESULT_NOT_FOUND| if a message was read from the pipe but could not -// be extracted into the provided buffers because it was not already in a -// serialized form. -// -// DEPRECATED: Use |MojoReadMessageNew()|. -MOJO_SYSTEM_EXPORT MojoResult - MojoReadMessage(MojoHandle message_pipe_handle, - void* bytes, // Optional out. - uint32_t* num_bytes, // Optional in/out. - MojoHandle* handles, // Optional out. - uint32_t* num_handles, // Optional in/out. - MojoReadMessageFlags flags); - -// Reads the next message from a message pipe and returns a message containing -// the message bytes. The returned message must eventually be freed using +// Reads the next message from a message pipe and returns a message as an opaque +// message handle. The returned message must eventually be destroyed using // |MojoFreeMessage()|. // // Message payload and handles can be accessed using // |MojoGetSerializedMessageContents()|. // -// |message| must be non-null unless |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| is set -// in |flags|. +// |message| must be non-null. // -// Return values correspond to the return values for |MojoReadMessage()| above. -// On success (MOJO_RESULT_OK), |*message| will contain a handle to a message -// object which may be passed to |MojoGetSerializedMessageContents()| or -// |MojoReleaseMessageContext()|. The caller owns the message object and is -// responsible for freeing it via |MojoFreeMessage()| or -// |MojoReleaseMessageContext()|. -MOJO_SYSTEM_EXPORT MojoResult MojoReadMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle* message, - MojoReadMessageFlags flags); +// Returns: +// |MOJO_RESULT_OK| on success (i.e., a message was actually read). +// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid. +// |MOJO_RESULT_FAILED_PRECONDITION| if the other endpoint has been closed +// and there are no more messages to read. +// |MOJO_RESULT_SHOULD_WAIT| if no message was available to be read. +MOJO_SYSTEM_EXPORT MojoResult MojoReadMessage(MojoHandle message_pipe_handle, + MojoMessageHandle* message, + MojoReadMessageFlags flags); // Fuses two message pipe endpoints together. Given two pipes: // @@ -323,60 +227,26 @@ MOJO_SYSTEM_EXPORT MojoResult MojoFuseMessagePipes(MojoHandle handle0, MojoHandle handle1); -// Allocates a new message whose ownership may be passed to -// |MojoWriteMessageNew()|. Use |MojoGetSerializedMessageContents()| to retrieve -// the address of the mutable message payload. -// -// |num_bytes|: The size of the message payload in bytes. -// |handles|: An array of handles to transfer in the message. This takes -// ownership of and invalidates all contained handles. Must be null if and -// only if |num_handles| is 0. -// |num_handles|: The number of handles contained in |handles|. -// |flags|: Must be |MOJO_CREATE_MESSAGE_FLAG_NONE|. -// |message|: The address of a handle to be filled with the allocated message's -// handle. Must be non-null. -// -// Returns: -// |MOJO_RESULT_OK| if the message was successfully allocated. In this case -// |*message| will be populated with a handle to an allocated message -// with a buffer large enough to hold |num_bytes| contiguous bytes. -// |MOJO_RESULT_INVALID_ARGUMENT| if one or more handles in |handles| was -// invalid, or |handles| was null with a non-zero |num_handles|. -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if allocation failed because either -// |num_bytes| or |num_handles| exceeds an implementation-defined maximum. -// |MOJO_RESULT_BUSY| if one or more handles in |handles| cannot be sent at -// the time of this call. -// -// Only upon successful message allocation will all handles in |handles| be -// transferred into the message and invalidated. -// -// DEPRECATED: Use |MojoCreateMessage()|. -MOJO_SYSTEM_EXPORT MojoResult -MojoAllocMessage(uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoAllocMessageFlags flags, - MojoMessageHandle* message); // Out - // Creates a new message object which may be sent over a message pipe via -// |MojoWriteMessageNew()|. Returns a handle to the new message object in +// |MojoWriteMessage()|. Returns a handle to the new message object in // |*message|. // // |context| is an arbitrary context value to associate with this message, and // |thunks| is a set of functions which may be called on |context| to perform // various operations. See |MojoMessageOperationThunks| for details. // -// Unlike |MojoAllocMessage()| above, this does not assume that the message -// object will require serialization. Typically a caller will use |context| as -// an opaque pointer to some arbitrary heap object which is effectively owned by -// the newly created message once this returns. In this way, messages can be -// sent over a message pipe to a peer endpoint in the same process as the sender -// without ever performing a serialization step. +// Typically a caller will use |context| as an opaque pointer to some heap +// object which is effectively owned by the newly created message once this +// returns. In this way, messages can be sent over a message pipe to a peer +// endpoint in the same process as the sender without ever performing a +// serialization step. // -// If the message does need to cross a process boundary to reach its -// destination, it will be serialized lazily when necessary. To accomplish this, -// the system will invoke the serialization helper functions from |thunks| on -// |context| to obtain a serialized representation of the message. +// If the message does need to cross a process boundary or is otherwise +// forced to serialize (see |MojoSerializeMessage()| below), it will be +// serialized by invoking the serialization helper functions from |thunks| on +// |context| to obtain a serialized representation of the message. Note that +// because the need to serialize may occur at any time and on any thread, +// functions in |thunks| must be safe to invoke accordingly. // // If |thunks| is null, the created message cannot be serialized. Subsequent // calls to |MojoSerializeMessage()| on the created message, or any attempt to @@ -393,12 +263,12 @@ const struct MojoMessageOperationThunks* thunks, MojoMessageHandle* message); -// Frees a message allocated by |MojoAllocMessage()| or |MojoReadMessageNew()|. +// Destroys a message object created by |MojoCreateMessage()| or +// |MojoReadMessage()|. // -// |message|: The message to free. This must correspond to a message previously -// allocated by |MojoAllocMessage()| or |MojoReadMessageNew()|. Note that if -// the message has already been passed to |MojoWriteMessageNew()| it should -// NOT also be freed with this API. +// |message|: The message to destroy. Note that if a message has been written +// to a message pipe using |MojoWriteMessage()|, it is neither necessary nor +// valid to attempt to destroy it. // // Returns: // |MOJO_RESULT_OK| if |message| was valid and has been freed. @@ -445,10 +315,6 @@ // null if |num_handles| is null or |*num_handles| is 0. // |flags|: Flags to affect the behavior of this API. // -// If |MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_IGNORE_HANDLES| is set in -// |flags|, |num_handles| and |handles| arguments are ignored and only payload- -// related outputs are updated. -// // Returns: // |MOJO_RESULT_OK| if |message| is a serialized message and the provided // handle storage is sufficient to contain all handles attached to the @@ -505,8 +371,7 @@ // terminate, a process, etc.) The embedder may not be notified if the calling // process has lost its connection to the source process. // -// |message|: The message to report as bad. This must have come from a call to -// |MojoReadMessageNew()|. +// |message|: The message to report as bad. // |error|: An error string which may provide the embedder with context when // notified of this error. // |error_num_bytes|: The length of |error| in bytes.
diff --git a/mojo/public/c/system/tests/core_perftest.cc b/mojo/public/c/system/tests/core_perftest.cc index 54b9d81..80508bc0 100644 --- a/mojo/public/c/system/tests/core_perftest.cc +++ b/mojo/public/c/system/tests/core_perftest.cc
@@ -147,7 +147,7 @@ CorePerftest* self = static_cast<CorePerftest*>(closure); MojoMessageHandle message; MojoResult result = - MojoReadMessageNew(self->h0_, &message, MOJO_READ_MESSAGE_FLAG_NONE); + MojoReadMessage(self->h0_, &message, MOJO_READ_MESSAGE_FLAG_NONE); ALLOW_UNUSED_LOCAL(result); assert(result == MOJO_RESULT_SHOULD_WAIT); }
diff --git a/mojo/public/c/system/tests/core_unittest.cc b/mojo/public/c/system/tests/core_unittest.cc index 7f99097..bd8e989 100644 --- a/mojo/public/c/system/tests/core_unittest.cc +++ b/mojo/public/c/system/tests/core_unittest.cc
@@ -44,10 +44,10 @@ // Message pipe: h0 = MOJO_HANDLE_INVALID; EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoWriteMessageNew(h0, MOJO_MESSAGE_HANDLE_INVALID, - MOJO_WRITE_MESSAGE_FLAG_NONE)); + MojoWriteMessage(h0, MOJO_MESSAGE_HANDLE_INVALID, + MOJO_WRITE_MESSAGE_FLAG_NONE)); EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoReadMessageNew(h0, nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); + MojoReadMessage(h0, nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); // Data pipe: buffer_size = static_cast<uint32_t>(sizeof(buffer)); @@ -94,14 +94,14 @@ // Try to read. MojoMessageHandle message; EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - MojoReadMessageNew(h0, &message, MOJO_READ_MESSAGE_FLAG_NONE)); + MojoReadMessage(h0, &message, MOJO_READ_MESSAGE_FLAG_NONE)); // Write to |h1|. const uintptr_t kTestMessageContext = 1234; EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(kTestMessageContext, nullptr, &message)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessageNew(h1, message, MOJO_WRITE_MESSAGE_FLAG_NONE)); + MojoWriteMessage(h1, message, MOJO_WRITE_MESSAGE_FLAG_NONE)); // |h0| should be readable. size_t result_index = 1; @@ -117,7 +117,7 @@ // Read from |h0|. EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessageNew(h0, &message, MOJO_READ_MESSAGE_FLAG_NONE)); + MojoReadMessage(h0, &message, MOJO_READ_MESSAGE_FLAG_NONE)); uintptr_t context; EXPECT_EQ(MOJO_RESULT_OK, MojoReleaseMessageContext(message, &context)); EXPECT_EQ(MOJO_RESULT_OK, MojoFreeMessage(message));
diff --git a/mojo/public/c/system/tests/core_unittest_pure_c.c b/mojo/public/c/system/tests/core_unittest_pure_c.c index de16790..c5b4c5d 100644 --- a/mojo/public/c/system/tests/core_unittest_pure_c.c +++ b/mojo/public/c/system/tests/core_unittest_pure_c.c
@@ -58,10 +58,10 @@ MojoMessageHandle message; EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(42, NULL, &message)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessageNew(handle0, message, MOJO_WRITE_DATA_FLAG_NONE)); + MojoWriteMessage(handle0, message, MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessageNew(handle1, &message, - MOJO_READ_MESSAGE_FLAG_NONE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(handle1, &message, + MOJO_READ_MESSAGE_FLAG_NONE)); uintptr_t context; EXPECT_EQ(MOJO_RESULT_OK, MojoReleaseMessageContext(message, &context)); EXPECT_EQ(42, context);
diff --git a/mojo/public/c/system/thunks.cc b/mojo/public/c/system/thunks.cc index 64344928..11713cc 100644 --- a/mojo/public/c/system/thunks.cc +++ b/mojo/public/c/system/thunks.cc
@@ -38,25 +38,17 @@ } MojoResult MojoWriteMessage(MojoHandle message_pipe_handle, - const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, + MojoMessageHandle message_handle, MojoWriteMessageFlags flags) { assert(g_thunks.WriteMessage); - return g_thunks.WriteMessage(message_pipe_handle, bytes, num_bytes, handles, - num_handles, flags); + return g_thunks.WriteMessage(message_pipe_handle, message_handle, flags); } MojoResult MojoReadMessage(MojoHandle message_pipe_handle, - void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, + MojoMessageHandle* message_handle, MojoReadMessageFlags flags) { assert(g_thunks.ReadMessage); - return g_thunks.ReadMessage(message_pipe_handle, bytes, num_bytes, handles, - num_handles, flags); + return g_thunks.ReadMessage(message_pipe_handle, message_handle, flags); } MojoResult MojoCreateDataPipe(const MojoCreateDataPipeOptions* options, @@ -180,30 +172,6 @@ return g_thunks.FuseMessagePipes(handle0, handle1); } -MojoResult MojoWriteMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle message, - MojoWriteMessageFlags flags) { - assert(g_thunks.WriteMessageNew); - return g_thunks.WriteMessageNew(message_pipe_handle, message, flags); -} - -MojoResult MojoReadMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle* message, - MojoReadMessageFlags flags) { - assert(g_thunks.ReadMessageNew); - return g_thunks.ReadMessageNew(message_pipe_handle, message, flags); -} - -MojoResult MojoAllocMessage(uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoAllocMessageFlags flags, - MojoMessageHandle* message) { - assert(g_thunks.AllocMessage); - return g_thunks.AllocMessage( - num_bytes, handles, num_handles, flags, message); -} - MojoResult MojoCreateMessage(uintptr_t context, const MojoMessageOperationThunks* thunks, MojoMessageHandle* message) {
diff --git a/mojo/public/c/system/thunks.h b/mojo/public/c/system/thunks.h index ba921cf..d17b09ec 100644 --- a/mojo/public/c/system/thunks.h +++ b/mojo/public/c/system/thunks.h
@@ -30,16 +30,10 @@ MojoHandle* message_pipe_handle0, MojoHandle* message_pipe_handle1); MojoResult (*WriteMessage)(MojoHandle message_pipe_handle, - const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, + MojoMessageHandle message_handle, MojoWriteMessageFlags flags); MojoResult (*ReadMessage)(MojoHandle message_pipe_handle, - void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, + MojoMessageHandle* message_handle, MojoReadMessageFlags flags); MojoResult (*CreateDataPipe)(const struct MojoCreateDataPipeOptions* options, MojoHandle* data_pipe_producer_handle, @@ -91,17 +85,6 @@ MojoResult* ready_results, MojoHandleSignalsState* ready_signals_states); MojoResult (*FuseMessagePipes)(MojoHandle handle0, MojoHandle handle1); - MojoResult (*WriteMessageNew)(MojoHandle message_pipe_handle, - MojoMessageHandle message, - MojoWriteMessageFlags flags); - MojoResult (*ReadMessageNew)(MojoHandle message_pipe_handle, - MojoMessageHandle* message, - MojoReadMessageFlags flags); - MojoResult (*AllocMessage)(uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoAllocMessageFlags flags, - MojoMessageHandle* message); MojoResult (*CreateMessage)(uintptr_t context, const struct MojoMessageOperationThunks* thunks, MojoMessageHandle* message);
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn index 43bf15b..2f3727e 100644 --- a/mojo/public/cpp/bindings/BUILD.gn +++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -60,6 +60,7 @@ "lib/binding_state.cc", "lib/binding_state.h", "lib/bindings_internal.h", + "lib/buffer.cc", "lib/buffer.h", "lib/connector.cc", "lib/control_message_handler.cc", @@ -78,10 +79,6 @@ "lib/map_serialization.h", "lib/may_auto_lock.h", "lib/message.cc", - "lib/message_buffer.cc", - "lib/message_buffer.h", - "lib/message_builder.cc", - "lib/message_builder.h", "lib/message_header_validator.cc", "lib/message_internal.h", "lib/multiplex_router.cc",
diff --git a/mojo/public/cpp/bindings/lib/buffer.cc b/mojo/public/cpp/bindings/lib/buffer.cc new file mode 100644 index 0000000..308156ad --- /dev/null +++ b/mojo/public/cpp/bindings/lib/buffer.cc
@@ -0,0 +1,52 @@ +// 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 "mojo/public/cpp/bindings/lib/buffer.h" + +#include "base/logging.h" +#include "mojo/public/cpp/bindings/lib/bindings_internal.h" + +namespace mojo { +namespace internal { + +Buffer::Buffer() = default; + +Buffer::Buffer(void* data, size_t size) : data_(data), size_(size), cursor_(0) { + DCHECK(IsAligned(data_)); +} + +Buffer::Buffer(Buffer&& other) { + *this = std::move(other); +} + +Buffer::~Buffer() = default; + +Buffer& Buffer::operator=(Buffer&& other) { + data_ = other.data_; + size_ = other.size_; + cursor_ = other.cursor_; + other.Reset(); + return *this; +} + +void* Buffer::Allocate(size_t num_bytes) { + const size_t block_start = cursor_; + cursor_ += Align(num_bytes); + if (cursor_ > size_ || cursor_ < block_start) { + NOTREACHED(); + cursor_ = block_start; + return nullptr; + } + DCHECK_LE(cursor_, size_); + return reinterpret_cast<char*>(data_) + block_start; +} + +void Buffer::Reset() { + data_ = nullptr; + size_ = 0; + cursor_ = 0; +} + +} // namespace internal +} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/buffer.h b/mojo/public/cpp/bindings/lib/buffer.h index 213a4459..2b6cbcc 100644 --- a/mojo/public/cpp/bindings/lib/buffer.h +++ b/mojo/public/cpp/bindings/lib/buffer.h
@@ -6,60 +6,51 @@ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_ #include <stddef.h> +#include <stdint.h> -#include "base/logging.h" #include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" +#include "mojo/public/cpp/bindings/bindings_export.h" namespace mojo { namespace internal { // Buffer provides an interface to allocate memory blocks which are 8-byte -// aligned and zero-initialized. It doesn't own the underlying memory. Users -// must ensure that the memory stays valid while using the allocated blocks from -// Buffer. -class Buffer { +// aligned. It doesn't own the underlying memory. Users must ensure that the +// memory stays valid while using the allocated blocks from Buffer. +// +// A Buffer may be moved around. A moved-from Buffer is reset and may no longer +// be used to Allocate memory unless re-Initialized. +class MOJO_CPP_BINDINGS_EXPORT Buffer { public: - Buffer() {} + // Constructs an invalid Buffer. May not call Allocate(). + Buffer(); - // The memory must have been zero-initialized. |data| must be 8-byte - // aligned. - void Initialize(void* data, size_t size) { - DCHECK(IsAligned(data)); + // Constructs a Buffer which can Allocate() blocks starting at |data|, up to + // a total of |size| bytes. |data| is not owned. + Buffer(void* data, size_t size); - data_ = data; - size_ = size; - cursor_ = reinterpret_cast<uintptr_t>(data); - data_end_ = cursor_ + size; - } + Buffer(Buffer&& other); + ~Buffer(); - size_t size() const { return size_; } + Buffer& operator=(Buffer&& other); void* data() const { return data_; } + size_t size() const { return size_; } + size_t cursor() const { return cursor_; } + + bool is_valid() const { return data_ != nullptr; } // Allocates |num_bytes| from the buffer and returns a pointer to the start of - // the allocated block. - // The resulting address is 8-byte aligned, and the content of the memory is - // zero-filled. - void* Allocate(size_t num_bytes) { - num_bytes = Align(num_bytes); - uintptr_t result = cursor_; - cursor_ += num_bytes; - if (cursor_ > data_end_ || cursor_ < result) { - NOTREACHED(); - cursor_ -= num_bytes; - return nullptr; - } + // the allocated block. The resulting address is 8-byte aligned. + void* Allocate(size_t num_bytes); - return reinterpret_cast<void*>(result); - } + // Resets the buffer to an invalid state. Can no longer be used to Allocate(). + void Reset(); private: void* data_ = nullptr; size_t size_ = 0; - - uintptr_t cursor_ = 0; - uintptr_t data_end_ = 0; + size_t cursor_ = 0; DISALLOW_COPY_AND_ASSIGN(Buffer); };
diff --git a/mojo/public/cpp/bindings/lib/control_message_handler.cc b/mojo/public/cpp/bindings/lib/control_message_handler.cc index 1b7bb78..2160a78 100644 --- a/mojo/public/cpp/bindings/lib/control_message_handler.cc +++ b/mojo/public/cpp/bindings/lib/control_message_handler.cc
@@ -10,9 +10,9 @@ #include "base/logging.h" #include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" #include "mojo/public/cpp/bindings/lib/serialization.h" #include "mojo/public/cpp/bindings/lib/validation_util.h" +#include "mojo/public/cpp/bindings/message.h" #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" namespace mojo { @@ -118,16 +118,15 @@ size_t size = PrepareToSerialize<interface_control::RunResponseMessageParamsDataView>( response_params_ptr, &context_); - MessageBuilder builder(interface_control::kRunMessageId, - Message::kFlagIsResponse, size, 0); - builder.message()->set_request_id(message->request_id()); - + Message response_message(interface_control::kRunMessageId, + Message::kFlagIsResponse, size, 0); + response_message.set_request_id(message->request_id()); interface_control::internal::RunResponseMessageParams_Data* response_params = nullptr; Serialize<interface_control::RunResponseMessageParamsDataView>( - response_params_ptr, builder.buffer(), &response_params, &context_); - ignore_result(responder->Accept(builder.message())); - + response_params_ptr, response_message.payload_buffer(), &response_params, + &context_); + ignore_result(responder->Accept(&response_message)); return true; }
diff --git a/mojo/public/cpp/bindings/lib/control_message_proxy.cc b/mojo/public/cpp/bindings/lib/control_message_proxy.cc index d082b49..672d620 100644 --- a/mojo/public/cpp/bindings/lib/control_message_proxy.cc +++ b/mojo/public/cpp/bindings/lib/control_message_proxy.cc
@@ -12,7 +12,6 @@ #include "base/callback_helpers.h" #include "base/macros.h" #include "base/run_loop.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" #include "mojo/public/cpp/bindings/lib/serialization.h" #include "mojo/public/cpp/bindings/lib/validation_util.h" #include "mojo/public/cpp/bindings/message.h" @@ -74,48 +73,41 @@ interface_control::RunInputPtr input_ptr, const RunCallback& callback) { SerializationContext context; - auto params_ptr = interface_control::RunMessageParams::New(); params_ptr->input = std::move(input_ptr); - size_t size = PrepareToSerialize<interface_control::RunMessageParamsDataView>( - params_ptr, &context); - MessageBuilder builder(interface_control::kRunMessageId, - Message::kFlagExpectsResponse, size, 0); - + const size_t size = + PrepareToSerialize<interface_control::RunMessageParamsDataView>( + params_ptr, &context); + Message message(interface_control::kRunMessageId, + Message::kFlagExpectsResponse, size, 0); interface_control::internal::RunMessageParams_Data* params = nullptr; Serialize<interface_control::RunMessageParamsDataView>( - params_ptr, builder.buffer(), ¶ms, &context); + params_ptr, message.payload_buffer(), ¶ms, &context); std::unique_ptr<MessageReceiver> responder = base::MakeUnique<RunResponseForwardToCallback>(callback); - ignore_result( - receiver->AcceptWithResponder(builder.message(), std::move(responder))); + ignore_result(receiver->AcceptWithResponder(&message, std::move(responder))); } Message ConstructRunOrClosePipeMessage( interface_control::RunOrClosePipeInputPtr input_ptr) { SerializationContext context; - auto params_ptr = interface_control::RunOrClosePipeMessageParams::New(); params_ptr->input = std::move(input_ptr); - - size_t size = PrepareToSerialize< + const size_t size = PrepareToSerialize< interface_control::RunOrClosePipeMessageParamsDataView>(params_ptr, &context); - MessageBuilder builder(interface_control::kRunOrClosePipeMessageId, 0, size, - 0); - + Message message(interface_control::kRunOrClosePipeMessageId, 0, size, 0); interface_control::internal::RunOrClosePipeMessageParams_Data* params = nullptr; Serialize<interface_control::RunOrClosePipeMessageParamsDataView>( - params_ptr, builder.buffer(), ¶ms, &context); - return std::move(*builder.message()); + params_ptr, message.payload_buffer(), ¶ms, &context); + return message; } void SendRunOrClosePipeMessage( MessageReceiverWithResponder* receiver, interface_control::RunOrClosePipeInputPtr input_ptr) { Message message(ConstructRunOrClosePipeMessage(std::move(input_ptr))); - ignore_result(receiver->Accept(&message)); }
diff --git a/mojo/public/cpp/bindings/lib/fixed_buffer.cc b/mojo/public/cpp/bindings/lib/fixed_buffer.cc index 725a193..3a540268 100644 --- a/mojo/public/cpp/bindings/lib/fixed_buffer.cc +++ b/mojo/public/cpp/bindings/lib/fixed_buffer.cc
@@ -6,15 +6,13 @@ #include <stdlib.h> +#include "mojo/public/cpp/bindings/lib/bindings_internal.h" + namespace mojo { namespace internal { -FixedBufferForTesting::FixedBufferForTesting(size_t size) { - size = internal::Align(size); - // Use calloc here to ensure all message memory is zero'd out. - void* ptr = calloc(size, 1); - Initialize(ptr, size); -} +FixedBufferForTesting::FixedBufferForTesting(size_t size) + : FixedBufferForTesting(nullptr, Align(size)) {} FixedBufferForTesting::~FixedBufferForTesting() { free(data()); @@ -22,9 +20,13 @@ void* FixedBufferForTesting::Leak() { void* ptr = data(); - Initialize(nullptr, 0); + Reset(); return ptr; } +FixedBufferForTesting::FixedBufferForTesting(std::nullptr_t, + size_t aligned_size) + : Buffer(calloc(aligned_size, 1), aligned_size) {} + } // namespace internal } // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/fixed_buffer.h b/mojo/public/cpp/bindings/lib/fixed_buffer.h index 070b0c8c..8fa3ff5d 100644 --- a/mojo/public/cpp/bindings/lib/fixed_buffer.h +++ b/mojo/public/cpp/bindings/lib/fixed_buffer.h
@@ -5,9 +5,8 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_ -#include <stddef.h> +#include <cstddef> -#include "base/compiler_specific.h" #include "base/macros.h" #include "mojo/public/cpp/bindings/bindings_export.h" #include "mojo/public/cpp/bindings/lib/buffer.h" @@ -17,8 +16,7 @@ // FixedBufferForTesting owns its buffer. The Leak method may be used to steal // the underlying memory. -class MOJO_CPP_BINDINGS_EXPORT FixedBufferForTesting - : NON_EXPORTED_BASE(public Buffer) { +class MOJO_CPP_BINDINGS_EXPORT FixedBufferForTesting : public Buffer { public: explicit FixedBufferForTesting(size_t size); ~FixedBufferForTesting(); @@ -30,6 +28,8 @@ void* Leak(); private: + FixedBufferForTesting(std::nullptr_t, size_t aligned_size); + DISALLOW_COPY_AND_ASSIGN(FixedBufferForTesting); };
diff --git a/mojo/public/cpp/bindings/lib/message.cc b/mojo/public/cpp/bindings/lib/message.cc index 445d0f2..36c6b86a 100644 --- a/mojo/public/cpp/bindings/lib/message.cc +++ b/mojo/public/cpp/bindings/lib/message.cc
@@ -33,44 +33,206 @@ message.NotifyBadMessage(error); } +template <typename HeaderType> +void AllocateHeaderFromBuffer(internal::Buffer* buffer, HeaderType** header) { + *header = static_cast<HeaderType*>(buffer->Allocate(sizeof(HeaderType))); + (*header)->num_bytes = sizeof(HeaderType); +} + +// An internal serialization context used to initialize new serialized messages. +struct MessageInfo { + MessageInfo(size_t total_size, std::vector<ScopedHandle> handles) + : total_size(total_size), handles(std::move(handles)) {} + const size_t total_size; + std::vector<ScopedHandle> handles; + internal::Buffer payload_buffer; +}; + +void GetSerializedSizeFromMessageInfo(uintptr_t context, + size_t* num_bytes, + size_t* num_handles) { + auto* info = reinterpret_cast<MessageInfo*>(context); + *num_bytes = info->total_size; + *num_handles = info->handles.size(); +} + +void SerializeHandlesFromMessageInfo(uintptr_t context, MojoHandle* handles) { + auto* info = reinterpret_cast<MessageInfo*>(context); + for (size_t i = 0; i < info->handles.size(); ++i) + handles[i] = info->handles[i].release().value(); +} + +void SerializePayloadFromMessageInfo(uintptr_t context, void* storage) { + auto* info = reinterpret_cast<MessageInfo*>(context); + info->payload_buffer = internal::Buffer(storage, info->total_size); +} + +void DestroyMessageInfo(uintptr_t context) { + // MessageInfo is always stack-allocated, so there's nothing to do here. +} + +const MojoMessageOperationThunks kMessageInfoThunks{ + sizeof(MojoMessageOperationThunks), + &GetSerializedSizeFromMessageInfo, + &SerializeHandlesFromMessageInfo, + &SerializePayloadFromMessageInfo, + &DestroyMessageInfo, +}; + +size_t ComputeHeaderSize(uint32_t flags, size_t payload_interface_id_count) { + if (payload_interface_id_count > 0) { + // Version 2 + return sizeof(internal::MessageHeaderV2); + } else if (flags & + (Message::kFlagExpectsResponse | Message::kFlagIsResponse)) { + // Version 1 + return sizeof(internal::MessageHeaderV1); + } else { + // Version 0 + return sizeof(internal::MessageHeader); + } +} + +size_t ComputeTotalSize(uint32_t flags, + size_t payload_size, + size_t payload_interface_id_count) { + const size_t header_size = + ComputeHeaderSize(flags, payload_interface_id_count); + if (payload_interface_id_count > 0) { + return internal::Align( + header_size + internal::Align(payload_size) + + internal::ArrayDataTraits<uint32_t>::GetStorageSize( + static_cast<uint32_t>(payload_interface_id_count))); + } + return internal::Align(header_size + payload_size); +} + +void WriteMessageHeader(uint32_t name, + uint32_t flags, + size_t payload_interface_id_count, + internal::Buffer* payload_buffer) { + if (payload_interface_id_count > 0) { + // Version 2 + internal::MessageHeaderV2* header; + AllocateHeaderFromBuffer(payload_buffer, &header); + header->version = 2; + header->name = name; + header->flags = flags; + // The payload immediately follows the header. + header->payload.Set(header + 1); + } else if (flags & + (Message::kFlagExpectsResponse | Message::kFlagIsResponse)) { + // Version 1 + internal::MessageHeaderV1* header; + AllocateHeaderFromBuffer(payload_buffer, &header); + header->version = 1; + header->name = name; + header->flags = flags; + } else { + internal::MessageHeader* header; + AllocateHeaderFromBuffer(payload_buffer, &header); + header->version = 0; + header->name = name; + header->flags = flags; + } +} + +void CreateSerializedMessageObject(uint32_t name, + uint32_t flags, + size_t payload_size, + size_t payload_interface_id_count, + std::vector<ScopedHandle> handles, + ScopedMessageHandle* out_handle, + internal::Buffer* out_buffer) { + internal::Buffer buffer; + MessageInfo info( + ComputeTotalSize(flags, payload_size, payload_interface_id_count), + std::move(handles)); + ScopedMessageHandle handle; + MojoResult rv = mojo::CreateMessage(reinterpret_cast<uintptr_t>(&info), + &kMessageInfoThunks, &handle); + DCHECK_EQ(MOJO_RESULT_OK, rv); + DCHECK(handle.is_valid()); + + // Force the message object to be serialized immediately. MessageInfo thunks + // are invoked here to serialize the handles and allocate enough space for + // header and user payload. |info.payload_buffer| is initialized with a Buffer + // that can be used to write the header and payload data. + rv = MojoSerializeMessage(handle->value()); + DCHECK_EQ(MOJO_RESULT_OK, rv); + DCHECK(info.payload_buffer.is_valid()); + + // Make sure we zero the memory first! + memset(info.payload_buffer.data(), 0, info.total_size); + WriteMessageHeader(name, flags, payload_interface_id_count, + &info.payload_buffer); + + *out_handle = std::move(handle); + *out_buffer = std::move(info.payload_buffer); +} + } // namespace -Message::Message() { +Message::Message() = default; + +Message::Message(Message&& other) = default; + +Message::Message(uint32_t name, + uint32_t flags, + size_t payload_size, + size_t payload_interface_id_count, + std::vector<ScopedHandle> handles) { + CreateSerializedMessageObject(name, flags, payload_size, + payload_interface_id_count, std::move(handles), + &handle_, &payload_buffer_); + data_ = payload_buffer_.data(); + data_size_ = payload_buffer_.size(); + transferable_ = true; } -Message::Message(Message&& other) - : buffer_(std::move(other.buffer_)), - handles_(std::move(other.handles_)), - associated_endpoint_handles_( - std::move(other.associated_endpoint_handles_)) {} +Message::Message(ScopedMessageHandle handle) { + DCHECK(handle.is_valid()); -Message::~Message() {} + // Extract any serialized handles if possible. + uint32_t num_bytes; + void* buffer; + uint32_t num_handles = 0; + MojoResult rv = MojoGetSerializedMessageContents( + handle->value(), &buffer, &num_bytes, nullptr, &num_handles, + MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); + if (rv == MOJO_RESULT_RESOURCE_EXHAUSTED) { + handles_.resize(num_handles); + rv = MojoGetSerializedMessageContents( + handle->value(), &buffer, &num_bytes, + reinterpret_cast<MojoHandle*>(handles_.data()), &num_handles, + MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); + } else { + // No handles, so it's safe to retransmit this message if the caller really + // wants to. + transferable_ = true; + } -Message& Message::operator=(Message&& other) { - Reset(); - std::swap(other.buffer_, buffer_); - std::swap(other.handles_, handles_); - std::swap(other.associated_endpoint_handles_, associated_endpoint_handles_); - return *this; + if (rv != MOJO_RESULT_OK) { + // Failed to deserialize handles. Leave the Message uninitialized. + return; + } + + handle_ = std::move(handle); + data_ = buffer; + data_size_ = num_bytes; } +Message::~Message() = default; + +Message& Message::operator=(Message&& other) = default; + void Message::Reset() { + handle_.reset(); handles_.clear(); associated_endpoint_handles_.clear(); - buffer_.reset(); -} - -void Message::Initialize(size_t capacity, bool zero_initialized) { - DCHECK(!buffer_); - buffer_.reset(new internal::MessageBuffer(capacity, zero_initialized)); -} - -void Message::InitializeFromMojoMessage(ScopedMessageHandle message, - uint32_t num_bytes, - std::vector<ScopedHandle>* handles) { - DCHECK(!buffer_); - buffer_.reset(new internal::MessageBuffer(std::move(message), num_bytes)); - handles_.swap(*handles); + data_ = nullptr; + data_size_ = 0; + transferable_ = false; } const uint8_t* Message::payload() const { @@ -112,48 +274,57 @@ return array_pointer ? array_pointer->storage() : nullptr; } +void Message::AttachHandles(std::vector<ScopedHandle> handles) { + if (handles.empty()) + return; + + // Sanity-check the current serialized message state. We must have a valid + // message handle and it must have no serialized handles. + DCHECK(handle_.is_valid()); + DCHECK(payload_buffer_.is_valid()); + void* buffer; + uint32_t num_bytes; + uint32_t num_handles = 0; + MojoResult rv = MojoGetSerializedMessageContents( + handle_->value(), &buffer, &num_bytes, nullptr, &num_handles, + MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); + DCHECK_EQ(MOJO_RESULT_OK, rv); + + MessageInfo new_info(data_size_, std::move(handles)); + ScopedMessageHandle new_handle; + rv = mojo::CreateMessage(reinterpret_cast<uintptr_t>(&new_info), + &kMessageInfoThunks, &new_handle); + DCHECK_EQ(MOJO_RESULT_OK, rv); + DCHECK(new_handle.is_valid()); + + rv = MojoSerializeMessage(new_handle->value()); + DCHECK_EQ(MOJO_RESULT_OK, rv); + DCHECK(new_info.payload_buffer.is_valid()); + + // Copy the existing payload into the new message. + void* storage = new_info.payload_buffer.Allocate(payload_buffer_.cursor()); + memcpy(storage, data_, data_size_); + + handle_ = std::move(new_handle); + payload_buffer_ = std::move(new_info.payload_buffer); + data_ = payload_buffer_.data(); + data_size_ = payload_buffer_.size(); + transferable_ = true; +} + ScopedMessageHandle Message::TakeMojoMessage() { // If there are associated endpoints transferred, // SerializeAssociatedEndpointHandles() must be called before this method. DCHECK(associated_endpoint_handles_.empty()); - - if (handles_.empty()) // Fast path for the common case: No handles. - return buffer_->TakeMessage(); - - // Allocate a new message with space for the handles, then copy the buffer - // contents into it. - // - // TODO(rockot): We could avoid this copy by extending GetSerializedSize() - // behavior to collect handles. It's unoptimized for now because it's much - // more common to have messages with no handles. - ScopedMessageHandle new_message; - MojoResult rv = AllocMessage( - data_num_bytes(), - handles_.empty() ? nullptr - : reinterpret_cast<const MojoHandle*>(handles_.data()), - handles_.size(), - MOJO_ALLOC_MESSAGE_FLAG_NONE, - &new_message); - CHECK_EQ(rv, MOJO_RESULT_OK); - - // The handles are now owned by the message object. - for (auto& handle : handles_) - ignore_result(handle.release()); - handles_.clear(); - - void* new_buffer = nullptr; - rv = GetMessageBuffer(new_message.get(), &new_buffer); - CHECK_EQ(rv, MOJO_RESULT_OK); - - memcpy(new_buffer, data(), data_num_bytes()); - buffer_.reset(); - - return new_message; + DCHECK(transferable_); + auto handle = std::move(handle_); + Reset(); + return handle; } void Message::NotifyBadMessage(const std::string& error) { - DCHECK(buffer_); - buffer_->NotifyBadMessage(error); + DCHECK(handle_.is_valid()); + mojo::NotifyBadMessage(handle_.get(), error); } void Message::SerializeAssociatedEndpointHandles( @@ -163,9 +334,10 @@ DCHECK_GE(version(), 2u); DCHECK(header_v2()->payload_interface_ids.is_null()); + DCHECK(payload_buffer_.is_valid()); size_t size = associated_endpoint_handles_.size(); - auto* data = internal::Array_Data<uint32_t>::New(size, buffer()); + auto* data = internal::Array_Data<uint32_t>::New(size, &payload_buffer_); header_v2()->payload_interface_ids.Set(data); for (size_t i = 0; i < size; ++i) { @@ -239,23 +411,13 @@ } MojoResult ReadMessage(MessagePipeHandle handle, Message* message) { - ScopedMessageHandle mojo_message; + ScopedMessageHandle message_handle; MojoResult rv = - ReadMessageNew(handle, &mojo_message, MOJO_READ_MESSAGE_FLAG_NONE); + ReadMessageNew(handle, &message_handle, MOJO_READ_MESSAGE_FLAG_NONE); if (rv != MOJO_RESULT_OK) return rv; - uint32_t num_bytes = 0; - void* buffer; - std::vector<ScopedHandle> handles; - rv = GetSerializedMessageContents( - mojo_message.get(), &buffer, &num_bytes, &handles, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); - if (rv != MOJO_RESULT_OK) - return rv; - - message->InitializeFromMojoMessage( - std::move(mojo_message), num_bytes, &handles); + *message = Message(std::move(message_handle)); return MOJO_RESULT_OK; }
diff --git a/mojo/public/cpp/bindings/lib/message_buffer.cc b/mojo/public/cpp/bindings/lib/message_buffer.cc deleted file mode 100644 index cc12ef6..0000000 --- a/mojo/public/cpp/bindings/lib/message_buffer.cc +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/message_buffer.h" - -#include <limits> - -#include "mojo/public/cpp/bindings/lib/serialization_util.h" - -namespace mojo { -namespace internal { - -MessageBuffer::MessageBuffer(size_t capacity, bool zero_initialized) { - DCHECK_LE(capacity, std::numeric_limits<uint32_t>::max()); - - MojoResult rv = AllocMessage(capacity, nullptr, 0, - MOJO_ALLOC_MESSAGE_FLAG_NONE, &message_); - CHECK_EQ(rv, MOJO_RESULT_OK); - - void* buffer = nullptr; - if (capacity != 0) { - rv = GetMessageBuffer(message_.get(), &buffer); - CHECK_EQ(rv, MOJO_RESULT_OK); - - if (zero_initialized) - memset(buffer, 0, capacity); - } - Initialize(buffer, capacity); -} - -MessageBuffer::MessageBuffer(ScopedMessageHandle message, uint32_t num_bytes) { - message_ = std::move(message); - - void* buffer = nullptr; - if (num_bytes != 0) { - MojoResult rv = GetMessageBuffer(message_.get(), &buffer); - CHECK_EQ(rv, MOJO_RESULT_OK); - } - Initialize(buffer, num_bytes); -} - -MessageBuffer::~MessageBuffer() {} - -void MessageBuffer::NotifyBadMessage(const std::string& error) { - DCHECK(message_.is_valid()); - MojoResult result = mojo::NotifyBadMessage(message_.get(), error); - DCHECK_EQ(result, MOJO_RESULT_OK); -} - -} // namespace internal -} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/message_buffer.h b/mojo/public/cpp/bindings/lib/message_buffer.h deleted file mode 100644 index 96d5140..0000000 --- a/mojo/public/cpp/bindings/lib/message_buffer.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_ - -#include <stdint.h> - -#include <utility> - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/buffer.h" -#include "mojo/public/cpp/system/message.h" - -namespace mojo { -namespace internal { - -// A fixed-size Buffer using a Mojo message object for storage. -class MessageBuffer : public Buffer { - public: - // Initializes this buffer to carry a fixed byte capacity and no handles. - MessageBuffer(size_t capacity, bool zero_initialized); - - // Initializes this buffer from an existing Mojo MessageHandle. - MessageBuffer(ScopedMessageHandle message, uint32_t num_bytes); - - ~MessageBuffer(); - - ScopedMessageHandle TakeMessage() { return std::move(message_); } - - void NotifyBadMessage(const std::string& error); - - private: - ScopedMessageHandle message_; - - DISALLOW_COPY_AND_ASSIGN(MessageBuffer); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_
diff --git a/mojo/public/cpp/bindings/lib/message_builder.cc b/mojo/public/cpp/bindings/lib/message_builder.cc deleted file mode 100644 index 6806a73..0000000 --- a/mojo/public/cpp/bindings/lib/message_builder.cc +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/message_builder.h" - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/buffer.h" -#include "mojo/public/cpp/bindings/lib/message_internal.h" - -namespace mojo { -namespace internal { - -template <typename Header> -void Allocate(Buffer* buf, Header** header) { - *header = static_cast<Header*>(buf->Allocate(sizeof(Header))); - (*header)->num_bytes = sizeof(Header); -} - -MessageBuilder::MessageBuilder(uint32_t name, - uint32_t flags, - size_t payload_size, - size_t payload_interface_id_count) { - if (payload_interface_id_count > 0) { - // Version 2 - InitializeMessage( - sizeof(MessageHeaderV2) + Align(payload_size) + - ArrayDataTraits<uint32_t>::GetStorageSize( - static_cast<uint32_t>(payload_interface_id_count))); - - MessageHeaderV2* header; - Allocate(message_.buffer(), &header); - header->version = 2; - header->name = name; - header->flags = flags; - // The payload immediately follows the header. - header->payload.Set(header + 1); - } else if (flags & - (Message::kFlagExpectsResponse | Message::kFlagIsResponse)) { - // Version 1 - InitializeMessage(sizeof(MessageHeaderV1) + payload_size); - - MessageHeaderV1* header; - Allocate(message_.buffer(), &header); - header->version = 1; - header->name = name; - header->flags = flags; - } else { - InitializeMessage(sizeof(MessageHeader) + payload_size); - - MessageHeader* header; - Allocate(message_.buffer(), &header); - header->version = 0; - header->name = name; - header->flags = flags; - } -} - -MessageBuilder::~MessageBuilder() { -} - -void MessageBuilder::InitializeMessage(size_t size) { - message_.Initialize(static_cast<uint32_t>(Align(size)), - true /* zero_initialized */); -} - -} // namespace internal -} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/message_builder.h b/mojo/public/cpp/bindings/lib/message_builder.h deleted file mode 100644 index 8a4d5c4..0000000 --- a/mojo/public/cpp/bindings/lib/message_builder.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_ - -#include <stddef.h> -#include <stdint.h> - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { - -class Message; - -namespace internal { - -class Buffer; - -class MOJO_CPP_BINDINGS_EXPORT MessageBuilder { - public: - MessageBuilder(uint32_t name, - uint32_t flags, - size_t payload_size, - size_t payload_interface_id_count); - ~MessageBuilder(); - - Buffer* buffer() { return message_.buffer(); } - Message* message() { return &message_; } - - private: - void InitializeMessage(size_t size); - - Message message_; - - DISALLOW_COPY_AND_ASSIGN(MessageBuilder); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_
diff --git a/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc b/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc index d451c05..d39b991 100644 --- a/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc +++ b/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc
@@ -6,7 +6,6 @@ #include "base/logging.h" #include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" #include "mojo/public/cpp/bindings/lib/serialization.h" #include "mojo/public/cpp/bindings/lib/serialization_context.h" #include "mojo/public/cpp/bindings/lib/validation_context.h"
diff --git a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc b/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc index 1029c2c4..50db139 100644 --- a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc +++ b/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
@@ -9,8 +9,8 @@ #include "base/logging.h" #include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" #include "mojo/public/cpp/bindings/lib/serialization.h" +#include "mojo/public/cpp/bindings/message.h" #include "mojo/public/interfaces/bindings/pipe_control_messages.mojom.h" namespace mojo { @@ -25,14 +25,12 @@ size_t size = internal::PrepareToSerialize< pipe_control::RunOrClosePipeMessageParamsDataView>(params_ptr, &context); - internal::MessageBuilder builder(pipe_control::kRunOrClosePipeMessageId, 0, - size, 0); - + Message message(pipe_control::kRunOrClosePipeMessageId, 0, size, 0); pipe_control::internal::RunOrClosePipeMessageParams_Data* params = nullptr; internal::Serialize<pipe_control::RunOrClosePipeMessageParamsDataView>( - params_ptr, builder.buffer(), ¶ms, &context); - builder.message()->set_interface_id(kInvalidInterfaceId); - return std::move(*builder.message()); + params_ptr, message.payload_buffer(), ¶ms, &context); + message.set_interface_id(kInvalidInterfaceId); + return message; } } // namespace
diff --git a/mojo/public/cpp/bindings/lib/serialization.h b/mojo/public/cpp/bindings/lib/serialization.h index 2a7d288d..f479e9ed 100644 --- a/mojo/public/cpp/bindings/lib/serialization.h +++ b/mojo/public/cpp/bindings/lib/serialization.h
@@ -50,8 +50,7 @@ DCHECK(IsAligned(result_buffer)); } - Buffer buffer; - buffer.Initialize(result_buffer, size); + Buffer buffer(result_buffer, size); typename MojomTypeTraits<MojomType>::Data* data = nullptr; Serialize<MojomType>(*input, &buffer, &data, &context);
diff --git a/mojo/public/cpp/bindings/message.h b/mojo/public/cpp/bindings/message.h index 1ec0119..07d0a7c 100644 --- a/mojo/public/cpp/bindings/message.h +++ b/mojo/public/cpp/bindings/message.h
@@ -17,7 +17,7 @@ #include "base/compiler_specific.h" #include "base/logging.h" #include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/message_buffer.h" +#include "mojo/public/cpp/bindings/lib/buffer.h" #include "mojo/public/cpp/bindings/lib/message_internal.h" #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" #include "mojo/public/cpp/system/message.h" @@ -38,11 +38,37 @@ static const uint32_t kFlagIsResponse = 1 << 1; static const uint32_t kFlagIsSync = 1 << 2; + // Constructs an uninitialized Message object. Message(); + + // Constructs a new serialized Message object with optional handles attached. + // This message is fully functional and may be exchanged for a + // ScopedMessageHandle for transit over a message pipe. See TakeMojoMessage(). + // + // If |handles| are not known at Message construction time, they may be + // attached later by calling |AttachHandles()|. See the note on that method + // regarding performance considerations. + Message(uint32_t name, + uint32_t flags, + size_t payload_size, + size_t payload_interface_id_count, + std::vector<ScopedHandle> handles = std::vector<ScopedHandle>()); + + // Constructs a new serialized Message object from an existing + // ScopedMessageHandle; e.g., one read from a message pipe. + // + // If the message had any handles attached, they will be extracted and + // retrievable via |handles()|. Such messages may NOT be sent back over + // another message pipe, but are otherwise safe to inspect and pass around. + Message(ScopedMessageHandle handle); + + // See the move-assignment operator below. Message(Message&& other); ~Message(); + // Moves |other| into a new Message object. The moved-from Message becomes + // invalid and is effectively in a default-constructed state after this call. Message& operator=(Message&& other); // Resets the Message to an uninitialized state. Upon reset, the Message @@ -51,51 +77,38 @@ void Reset(); // Indicates whether this Message is uninitialized. - bool IsNull() const { return !buffer_; } + bool IsNull() const { return !handle_.is_valid(); } - // Initializes a Message with enough space for |capacity| bytes. - void Initialize(size_t capacity, bool zero_initialized); - - // Initializes a Message from an existing Mojo MessageHandle. - void InitializeFromMojoMessage(ScopedMessageHandle message, - uint32_t num_bytes, - std::vector<ScopedHandle>* handles); - - uint32_t data_num_bytes() const { - return static_cast<uint32_t>(buffer_->size()); - } + uint32_t data_num_bytes() const { return static_cast<uint32_t>(data_size_); } // Access the raw bytes of the message. - const uint8_t* data() const { - return static_cast<const uint8_t*>(buffer_->data()); - } - - uint8_t* mutable_data() { return static_cast<uint8_t*>(buffer_->data()); } + const uint8_t* data() const { return static_cast<const uint8_t*>(data_); } + uint8_t* mutable_data() { return static_cast<uint8_t*>(data_); } // Access the header. const internal::MessageHeader* header() const { - return static_cast<const internal::MessageHeader*>(buffer_->data()); + return static_cast<const internal::MessageHeader*>(data_); } internal::MessageHeader* header() { - return static_cast<internal::MessageHeader*>(buffer_->data()); + return static_cast<internal::MessageHeader*>(data_); } const internal::MessageHeaderV1* header_v1() const { DCHECK_GE(version(), 1u); - return static_cast<const internal::MessageHeaderV1*>(buffer_->data()); + return static_cast<const internal::MessageHeaderV1*>(data_); } internal::MessageHeaderV1* header_v1() { DCHECK_GE(version(), 1u); - return static_cast<internal::MessageHeaderV1*>(buffer_->data()); + return static_cast<internal::MessageHeaderV1*>(data_); } const internal::MessageHeaderV2* header_v2() const { DCHECK_GE(version(), 2u); - return static_cast<const internal::MessageHeaderV2*>(buffer_->data()); + return static_cast<const internal::MessageHeaderV2*>(data_); } internal::MessageHeaderV2* header_v2() { DCHECK_GE(version(), 2u); - return static_cast<internal::MessageHeaderV2*>(buffer_->data()); + return static_cast<internal::MessageHeaderV2*>(data_); } uint32_t version() const { return header()->version; } @@ -120,7 +133,10 @@ uint32_t payload_num_interface_ids() const; const uint32_t* payload_interface_ids() const; - // Access the handles. + internal::Buffer* payload_buffer() { return &payload_buffer_; } + + // Access the handles of a received message. Note that these are unused on + // outgoing messages. const std::vector<ScopedHandle>* handles() const { return &handles_; } std::vector<ScopedHandle>* mutable_handles() { return &handles_; } @@ -133,8 +149,10 @@ return &associated_endpoint_handles_; } - // Access the underlying Buffer interface. - internal::Buffer* buffer() { return buffer_.get(); } + // Attaches handles to this Message. Note that this requires the underlying + // message object to be reallocated and the payload to be copied into a new + // buffer. + void AttachHandles(std::vector<ScopedHandle> handles); // Takes a scoped MessageHandle which may be passed to |WriteMessageNew()| for // transmission. Note that this invalidates this Message object, taking @@ -156,12 +174,26 @@ AssociatedGroupController* group_controller); private: - void CloseHandles(); + ScopedMessageHandle handle_; - std::unique_ptr<internal::MessageBuffer> buffer_; + // Pointer to raw serialized message data, including header. This is only + // valid when |handle_| is a valid handle to a serialized message object. + void* data_ = nullptr; + size_t data_size_ = 0; + std::vector<ScopedHandle> handles_; std::vector<ScopedInterfaceEndpointHandle> associated_endpoint_handles_; + // Indicates whether this Message object is transferable, i.e. can be sent + // elsewhere. In general this is true unless |handle_| is invalid or + // serialized handles have been extracted from the serialized message object + // identified by |handle_|. + bool transferable_ = false; + + // A Buffer which may be used to allocated blocks of data within the message + // payload. May be invalid if there is no capacity remaining in the payload. + internal::Buffer payload_buffer_; + DISALLOW_COPY_AND_ASSIGN(Message); };
diff --git a/mojo/public/cpp/bindings/tests/bindings_perftest.cc b/mojo/public/cpp/bindings/tests/bindings_perftest.cc index 65b3c8c1..aee51ef2 100644 --- a/mojo/public/cpp/bindings/tests/bindings_perftest.cc +++ b/mojo/public/cpp/bindings/tests/bindings_perftest.cc
@@ -12,7 +12,6 @@ #include "base/time/time.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/interface_endpoint_client.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" #include "mojo/public/cpp/bindings/lib/multiplex_router.h" #include "mojo/public/cpp/bindings/message.h" #include "mojo/public/cpp/test_support/test_support.h" @@ -154,8 +153,8 @@ } } - internal::MessageBuilder builder(count, 0, 8, 0); - bool result = sender_->Accept(builder.message()); + Message reply(count, 0, 8, 0); + bool result = sender_->Accept(&reply); DCHECK(result); return true; } @@ -174,8 +173,8 @@ quit_closure_ = run_loop.QuitClosure(); start_time_ = base::TimeTicks::Now(); - internal::MessageBuilder builder(0, 0, 8, 0); - bool result = sender_->Accept(builder.message()); + Message message(0, 0, 8, 0); + bool result = sender_->Accept(&message); DCHECK(result); run_loop.Run(); @@ -264,9 +263,8 @@ receiver.Reset(); base::TimeTicks start_time = base::TimeTicks::Now(); for (size_t j = 0; j < kIterations[i]; ++j) { - internal::MessageBuilder builder(0, 0, 8, 0); - bool result = - router->SimulateReceivingMessageForTesting(builder.message()); + Message message(0, 0, 8, 0); + bool result = router->SimulateReceivingMessageForTesting(&message); DCHECK(result); }
diff --git a/mojo/public/cpp/bindings/tests/connector_unittest.cc b/mojo/public/cpp/bindings/tests/connector_unittest.cc index 8757d72..63fc1efa 100644 --- a/mojo/public/cpp/bindings/tests/connector_unittest.cc +++ b/mojo/public/cpp/bindings/tests/connector_unittest.cc
@@ -16,7 +16,7 @@ #include "base/run_loop.h" #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" +#include "mojo/public/cpp/bindings/message.h" #include "mojo/public/cpp/bindings/tests/message_queue.h" #include "testing/gtest/include/gtest/gtest.h" @@ -97,12 +97,14 @@ void TearDown() override {} - void AllocMessage(const char* text, Message* message) { - size_t payload_size = strlen(text) + 1; // Plus null terminator. - internal::MessageBuilder builder(1, 0, payload_size, 0); - memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); - - *message = std::move(*builder.message()); + Message CreateMessage( + const char* text, + std::vector<ScopedHandle> handles = std::vector<ScopedHandle>()) { + const size_t size = strlen(text) + 1; // Plus null terminator. + Message message(1, 0, size, 0); + memcpy(message.payload_buffer()->Allocate(size), text, size); + message.AttachHandles(std::move(handles)); + return message; } protected: @@ -120,10 +122,7 @@ base::ThreadTaskRunnerHandle::Get()); const char kText[] = "hello world"; - - Message message; - AllocMessage(kText, &message); - + Message message = CreateMessage(kText); connector0.Accept(&message); base::RunLoop run_loop; @@ -149,10 +148,7 @@ base::ThreadTaskRunnerHandle::Get()); const char kText[] = "hello world"; - - Message message; - AllocMessage(kText, &message); - + Message message = CreateMessage(kText); connector0.Accept(&message); MessageAccumulator accumulator; @@ -181,10 +177,7 @@ connector1.set_incoming_receiver(&accumulator); const char kText[] = "hello world"; - - Message message; - AllocMessage(kText, &message); - + Message message = CreateMessage(kText); connector0.Accept(&message); run_loop.Run(); @@ -206,11 +199,8 @@ base::ThreadTaskRunnerHandle::Get()); const char* kText[] = {"hello", "world"}; - for (size_t i = 0; i < arraysize(kText); ++i) { - Message message; - AllocMessage(kText[i], &message); - + Message message = CreateMessage(kText[i]); connector0.Accept(&message); } @@ -241,11 +231,8 @@ base::ThreadTaskRunnerHandle::Get()); const char* kText[] = {"hello", "world"}; - for (size_t i = 0; i < arraysize(kText); ++i) { - Message message; - AllocMessage(kText[i], &message); - + Message message = CreateMessage(kText[i]); connector0.Accept(&message); } @@ -271,9 +258,7 @@ base::ThreadTaskRunnerHandle::Get()); const char kText[] = "hello world"; - - Message message; - AllocMessage(kText, &message); + Message message = CreateMessage(kText); // Close the other end of the pipe. handle1_.reset(); @@ -304,18 +289,13 @@ const char kText[] = "hello world"; - Message message1; - AllocMessage(kText, &message1); - MessagePipe pipe; - message1.mutable_handles()->emplace_back( - ScopedHandle::From(std::move(pipe.handle0))); + std::vector<ScopedHandle> handles; + handles.emplace_back(ScopedHandle::From(std::move(pipe.handle0))); + Message message1 = CreateMessage(kText, std::move(handles)); connector0.Accept(&message1); - // The message should have been transferred, releasing the handles. - EXPECT_TRUE(message1.handles()->empty()); - base::RunLoop run_loop; MessageAccumulator accumulator(run_loop.QuitClosure()); connector1.set_incoming_receiver(&accumulator); @@ -343,9 +323,7 @@ Connector::SINGLE_THREADED_SEND, base::ThreadTaskRunnerHandle::Get()); - Message message2; - AllocMessage(kText, &message2); - + Message message2 = CreateMessage(kText); connector_received.Accept(&message2); base::RunLoop run_loop2; MessageAccumulator accumulator2(run_loop2.QuitClosure()); @@ -377,10 +355,7 @@ base::ThreadTaskRunnerHandle::Get()); const char kText[] = "hello world"; - - Message message; - AllocMessage(kText, &message); - + Message message = CreateMessage(kText); connector0.Accept(&message); ConnectorDeletingMessageAccumulator accumulator(&connector1); @@ -406,11 +381,8 @@ base::ThreadTaskRunnerHandle::Get()); const char* kText[] = {"hello", "world"}; - for (size_t i = 0; i < arraysize(kText); ++i) { - Message message; - AllocMessage(kText[i], &message); - + Message message = CreateMessage(kText[i]); connector0.Accept(&message); } @@ -458,10 +430,7 @@ run_loop2.QuitClosure())); const char kText[] = "hello world"; - - Message message; - AllocMessage(kText, &message); - + Message message = CreateMessage(kText); connector0.Accept(&message); connector0.RaiseError(); @@ -512,10 +481,9 @@ const char kText[] = "hello world"; // Queue up two messages. - Message message; - AllocMessage(kText, &message); + Message message = CreateMessage(kText); connector0.Accept(&message); - AllocMessage(kText, &message); + message = CreateMessage(kText); connector0.Accept(&message); base::RunLoop run_loop; @@ -552,10 +520,9 @@ const char kText[] = "hello world"; // Queue up two messages. - Message message; - AllocMessage(kText, &message); + Message message = CreateMessage(kText); connector0.Accept(&message); - AllocMessage(kText, &message); + message = CreateMessage(kText); connector0.Accept(&message); base::RunLoop run_loop;
diff --git a/mojo/public/cpp/bindings/tests/router_test_util.cc b/mojo/public/cpp/bindings/tests/router_test_util.cc index 9bab1cb..4a0b4cd 100644 --- a/mojo/public/cpp/bindings/tests/router_test_util.cc +++ b/mojo/public/cpp/bindings/tests/router_test_util.cc
@@ -8,7 +8,7 @@ #include <stdint.h> #include <string.h> -#include "mojo/public/cpp/bindings/lib/message_builder.h" +#include "mojo/public/cpp/bindings/message.h" #include "mojo/public/cpp/bindings/tests/message_queue.h" #include "testing/gtest/include/gtest/gtest.h" @@ -17,10 +17,8 @@ void AllocRequestMessage(uint32_t name, const char* text, Message* message) { size_t payload_size = strlen(text) + 1; // Plus null terminator. - internal::MessageBuilder builder(name, Message::kFlagExpectsResponse, - payload_size, 0); - memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); - *message = std::move(*builder.message()); + *message = Message(name, Message::kFlagExpectsResponse, payload_size, 0); + memcpy(message->payload_buffer()->Allocate(payload_size), text, payload_size); } void AllocResponseMessage(uint32_t name, @@ -28,11 +26,9 @@ uint64_t request_id, Message* message) { size_t payload_size = strlen(text) + 1; // Plus null terminator. - internal::MessageBuilder builder(name, Message::kFlagIsResponse, payload_size, - 0); - builder.message()->set_request_id(request_id); - memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); - *message = std::move(*builder.message()); + *message = Message(name, Message::kFlagIsResponse, payload_size, 0); + message->set_request_id(request_id); + memcpy(message->payload_buffer()->Allocate(payload_size), text, payload_size); } MessageAccumulator::MessageAccumulator(MessageQueue* queue,
diff --git a/mojo/public/cpp/bindings/tests/validation_unittest.cc b/mojo/public/cpp/bindings/tests/validation_unittest.cc index f271341..d498f049 100644 --- a/mojo/public/cpp/bindings/tests/validation_unittest.cc +++ b/mojo/public/cpp/bindings/tests/validation_unittest.cc
@@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "base/macros.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" @@ -23,6 +24,7 @@ #include "mojo/public/cpp/bindings/message_header_validator.h" #include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h" #include "mojo/public/cpp/system/core.h" +#include "mojo/public/cpp/system/message.h" #include "mojo/public/cpp/test_support/test_support.h" #include "mojo/public/interfaces/bindings/tests/validation_test_associated_interfaces.mojom.h" #include "mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom.h" @@ -32,6 +34,36 @@ namespace test { namespace { +void GetSerializedRawMessageSize(uintptr_t context, + size_t* num_bytes, + size_t* num_handles) { + *num_bytes = *reinterpret_cast<size_t*>(context); + *num_handles = 0; +} +static void IgnoreSerializeHandles(uintptr_t, MojoHandle*) {} +static void IgnoreSerializePayload(uintptr_t, void*) {} +static void IgnoreDestroy(uintptr_t) {} + +const MojoMessageOperationThunks kRawMessageThunks{ + sizeof(MojoMessageOperationThunks), + &GetSerializedRawMessageSize, + &IgnoreSerializeHandles, + &IgnoreSerializePayload, + &IgnoreDestroy, +}; + +Message CreateRawMessage(size_t size) { + ScopedMessageHandle handle; + MojoResult rv = CreateMessage(reinterpret_cast<uintptr_t>(&size), + &kRawMessageThunks, &handle); + DCHECK_EQ(MOJO_RESULT_OK, rv); + DCHECK(handle.is_valid()); + + rv = MojoSerializeMessage(handle->value()); + DCHECK_EQ(MOJO_RESULT_OK, rv); + return Message(std::move(handle)); +} + template <typename T> void Append(std::vector<uint8_t>* data_vector, T data) { size_t pos = data_vector->size(); @@ -150,8 +182,7 @@ return false; } - message->Initialize(static_cast<uint32_t>(data.size()), - false /* zero_initialized */); + *message = CreateRawMessage(data.size()); if (!data.empty()) memcpy(message->mutable_data(), &data[0], data.size()); message->mutable_handles()->resize(num_handles);
diff --git a/mojo/public/cpp/system/message.h b/mojo/public/cpp/system/message.h index e06d6a7..ceb66cc 100644 --- a/mojo/public/cpp/system/message.h +++ b/mojo/public/cpp/system/message.h
@@ -62,24 +62,6 @@ return MOJO_RESULT_OK; } -inline MojoResult AllocMessage(size_t num_bytes, - const MojoHandle* handles, - size_t num_handles, - MojoAllocMessageFlags flags, - ScopedMessageHandle* handle) { - DCHECK_LE(num_bytes, std::numeric_limits<uint32_t>::max()); - DCHECK_LE(num_handles, std::numeric_limits<uint32_t>::max()); - MojoMessageHandle raw_handle; - MojoResult rv = MojoAllocMessage(static_cast<uint32_t>(num_bytes), handles, - static_cast<uint32_t>(num_handles), flags, - &raw_handle); - if (rv != MOJO_RESULT_OK) - return rv; - - handle->reset(MessageHandle(raw_handle)); - return MOJO_RESULT_OK; -} - inline MojoResult GetSerializedMessageContents( MessageHandle message, void** buffer, @@ -104,13 +86,6 @@ reinterpret_cast<MojoHandle*>(handles->data()), &num_handles, flags); } -inline MojoResult GetMessageBuffer(MessageHandle message, void** buffer) { - uint32_t num_bytes; - return GetSerializedMessageContents( - message, buffer, &num_bytes, nullptr, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_IGNORE_HANDLES); -} - inline MojoResult NotifyBadMessage(MessageHandle message, const base::StringPiece& error) { DCHECK(message.is_valid());
diff --git a/mojo/public/cpp/system/message_pipe.cc b/mojo/public/cpp/system/message_pipe.cc index 1254e2e..3f66b92 100644 --- a/mojo/public/cpp/system/message_pipe.cc +++ b/mojo/public/cpp/system/message_pipe.cc
@@ -81,8 +81,8 @@ return MOJO_RESULT_ABORTED; } - return MojoWriteMessageNew(message_pipe.value(), - message_handle.release().value(), flags); + return MojoWriteMessage(message_pipe.value(), + message_handle.release().value(), flags); } MojoResult ReadMessageRaw(MessagePipeHandle message_pipe, @@ -90,7 +90,7 @@ std::vector<ScopedHandle>* handles, MojoReadMessageFlags flags) { ScopedMessageHandle message_handle; - int rv = ReadMessageNew(message_pipe, &message_handle, flags); + MojoResult rv = ReadMessageNew(message_pipe, &message_handle, flags); if (rv != MOJO_RESULT_OK) return rv;
diff --git a/mojo/public/cpp/system/message_pipe.h b/mojo/public/cpp/system/message_pipe.h index 7a421746..ae0e2c7 100644 --- a/mojo/public/cpp/system/message_pipe.h +++ b/mojo/public/cpp/system/message_pipe.h
@@ -91,17 +91,17 @@ inline MojoResult WriteMessageNew(MessagePipeHandle message_pipe, ScopedMessageHandle message, MojoWriteMessageFlags flags) { - return MojoWriteMessageNew( - message_pipe.value(), message.release().value(), flags); + return MojoWriteMessage(message_pipe.value(), message.release().value(), + flags); } -// Reads from a message pipe. See |MojoReadMessageNew()| for complete +// Reads from a message pipe. See |MojoReadMessage()| for complete // documentation. inline MojoResult ReadMessageNew(MessagePipeHandle message_pipe, ScopedMessageHandle* message, MojoReadMessageFlags flags) { MojoMessageHandle raw_message; - MojoResult rv = MojoReadMessageNew(message_pipe.value(), &raw_message, flags); + MojoResult rv = MojoReadMessage(message_pipe.value(), &raw_message, flags); if (rv != MOJO_RESULT_OK) return rv;
diff --git a/mojo/public/cpp/test_support/lib/test_utils.cc b/mojo/public/cpp/test_support/lib/test_utils.cc index b59e3116..e5eca0ae 100644 --- a/mojo/public/cpp/test_support/lib/test_utils.cc +++ b/mojo/public/cpp/test_support/lib/test_utils.cc
@@ -47,7 +47,7 @@ bool DiscardMessage(const MessagePipeHandle& handle) { MojoMessageHandle message; int rv = - MojoReadMessageNew(handle.value(), &message, MOJO_READ_MESSAGE_FLAG_NONE); + MojoReadMessage(handle.value(), &message, MOJO_READ_MESSAGE_FLAG_NONE); if (rv != MOJO_RESULT_OK) return false; MojoFreeMessage(message);
diff --git a/mojo/public/js/core.js b/mojo/public/js/core.js index b2c4ee27..b973144 100644 --- a/mojo/public/js/core.js +++ b/mojo/public/js/core.js
@@ -74,7 +74,6 @@ * See core.h for more information. */ var READ_MESSAGE_FLAG_NONE; -var READ_MESSAGE_FLAG_MAY_DISCARD; /** * MojoCreateDataPipeOptions: Used to specify creation parameters for a data
diff --git a/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/mojo/public/tools/bindings/chromium_bindings_configuration.gni index 1166acc1..e605df00 100644 --- a/mojo/public/tools/bindings/chromium_bindings_configuration.gni +++ b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
@@ -20,7 +20,6 @@ "//device/bluetooth/public/interfaces/typemaps.gni", "//device/gamepad/public/interfaces/typemaps.gni", "//device/generic_sensor/public/interfaces/typemaps.gni", - "//device/usb/public/interfaces/typemaps.gni", "//extensions/common/typemaps.gni", "//gpu/ipc/common/typemaps.gni", "//media/capture/mojo/typemaps.gni",
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl index b748016..1aaba401 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -33,14 +33,15 @@ {%- endmacro %} {%- macro build_message(struct, input_pattern, struct_display_name, - serialization_context) -%} + serialization_context, message) -%} {{struct_macros.serialize(struct, struct_display_name, input_pattern, - "params", "builder.buffer()", + "params", "%s.payload_buffer()"|format(message), serialization_context)}} - ({{serialization_context}})->handles.Swap( - builder.message()->mutable_handles()); ({{serialization_context}})->associated_endpoint_handles.swap( - *builder.message()->mutable_associated_endpoint_handles()); + *{{message}}.mutable_associated_endpoint_handles()); + std::vector<mojo::ScopedHandle> handles_to_attach; + ({{serialization_context}})->handles.Swap(&handles_to_attach); + {{message}}.AttachHandles(std::move(handles_to_attach)); {%- endmacro %} {#--- Begin #} @@ -161,14 +162,12 @@ mojo::internal::SerializationContext serialization_context; {{struct_macros.get_serialized_size(params_struct, "param_%s", "&serialization_context")}} - - mojo::internal::MessageBuilder builder( + mojo::Message message( {{message_name}}, mojo::Message::kFlagIsSync | mojo::Message::kFlagExpectsResponse, size, serialization_context.associated_endpoint_count); - {{build_message(params_struct, "param_%s", params_description, - "&serialization_context")}} + "&serialization_context", "message")}} bool result = false; std::unique_ptr<mojo::MessageReceiver> responder( @@ -177,8 +176,7 @@ {%- for param in method.response_parameters -%} , param_{{param.name}} {%- endfor %})); - ignore_result(receiver_->AcceptWithResponder(builder.message(), - std::move(responder))); + ignore_result(receiver_->AcceptWithResponder(&message, std::move(responder))); return result; } {%- endif %} @@ -188,29 +186,25 @@ mojo::internal::SerializationContext serialization_context; {{struct_macros.get_serialized_size(params_struct, "in_%s", "&serialization_context")}} - {%- if method.response_parameters != None %} constexpr uint32_t kFlags = mojo::Message::kFlagExpectsResponse; {%- else %} constexpr uint32_t kFlags = 0; {%- endif %} - mojo::internal::MessageBuilder builder( - {{message_name}}, kFlags, size, - serialization_context.associated_endpoint_count); - + mojo::Message message({{message_name}}, kFlags, size, + serialization_context.associated_endpoint_count); {{build_message(params_struct, "in_%s", params_description, - "&serialization_context")}} + "&serialization_context", "message")}} {%- if method.response_parameters != None %} std::unique_ptr<mojo::MessageReceiver> responder( new {{class_name}}_{{method.name}}_ForwardToCallback( std::move(callback))); - ignore_result(receiver_->AcceptWithResponder(builder.message(), - std::move(responder))); + ignore_result(receiver_->AcceptWithResponder(&message, std::move(responder))); {%- else %} // This return value may be ignored as false implies the Connector has // encountered an error, which will be visible through other means. - ignore_result(receiver_->Accept(builder.message())); + ignore_result(receiver_->Accept(&message)); {%- endif %} } {%- endfor %} @@ -277,17 +271,14 @@ mojo::internal::SerializationContext serialization_context; {{struct_macros.get_serialized_size(response_params_struct, "in_%s", "&serialization_context")}} - uint32_t flags = (is_sync_ ? mojo::Message::kFlagIsSync : 0) | mojo::Message::kFlagIsResponse; - mojo::internal::MessageBuilder builder( - {{message_name}}, flags, size, - serialization_context.associated_endpoint_count); - builder.message()->set_request_id(request_id_); - + mojo::Message message({{message_name}}, flags, size, + serialization_context.associated_endpoint_count); {{build_message(response_params_struct, "in_%s", params_description, - "&serialization_context")}} - ignore_result(responder_->Accept(builder.message())); + "&serialization_context", "message")}} + message.set_request_id(request_id_); + ignore_result(responder_->Accept(&message)); // TODO(darin): Accept() returning false indicates a malformed message, and // that may be good reason to close the connection. However, we don't have a // way to do that from here. We should add a way.
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl index cbbe1be..2a0f849 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
@@ -25,7 +25,6 @@ #include <utility> #include "base/logging.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" #include "mojo/public/cpp/bindings/lib/serialization_util.h" #include "mojo/public/cpp/bindings/lib/validate_params.h" #include "mojo/public/cpp/bindings/lib/validation_context.h"
diff --git a/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs.cc b/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs.cc index 421e1f3..d05e6df 100644 --- a/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs.cc +++ b/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs.cc
@@ -10,6 +10,10 @@ namespace nacl_io { +// This is not further implemented. +// PNaCl is on a path to deprecation, and WebAssembly is +// the focused technology. + GoogleDriveFs::GoogleDriveFs() {} Error GoogleDriveFs::Init(const FsInitArgs& args) {
diff --git a/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs.h b/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs.h index 179cb8d2..fc38652 100644 --- a/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs.h +++ b/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs.h
@@ -12,6 +12,10 @@ namespace nacl_io { +// This is not further implemented. +// PNaCl is on a path to deprecation, and WebAssembly is +// the focused technology. + class GoogleDriveFs : public Filesystem { protected: GoogleDriveFs();
diff --git a/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs_node.cc b/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs_node.cc index 506ffd2..988f290 100644 --- a/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs_node.cc +++ b/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs_node.cc
@@ -13,6 +13,10 @@ namespace nacl_io { +// This is not further implemented. +// PNaCl is on a path to deprecation, and WebAssembly is +// the focused technology. + GoogleDriveFsNode::GoogleDriveFsNode(GoogleDriveFs* googledrivefs) : Node(googledrivefs) {}
diff --git a/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs_node.h b/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs_node.h index e212e89..57aa41ac 100644 --- a/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs_node.h +++ b/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs_node.h
@@ -14,6 +14,10 @@ namespace nacl_io { +// This is not further implemented. +// PNaCl is on a path to deprecation, and WebAssembly is +// the focused technology. + class GoogleDriveFsNode : public Node { public: GoogleDriveFsNode(GoogleDriveFs* googledrivefs);
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc index 6c81a55..8e3158a 100644 --- a/net/cookies/canonical_cookie.cc +++ b/net/cookies/canonical_cookie.cc
@@ -50,10 +50,12 @@ #include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "net/base/url_util.h" #include "net/cookies/cookie_util.h" #include "net/cookies/parsed_cookie.h" #include "url/gurl.h" #include "url/url_canon.h" +#include "url/url_util.h" using base::Time; using base::TimeDelta; @@ -228,21 +230,22 @@ creation_time, server_time); - CookiePrefix prefix = CanonicalCookie::GetCookiePrefix(parsed_cookie.Name()); - bool is_cookie_valid = - CanonicalCookie::IsCookiePrefixValid(prefix, url, parsed_cookie); - CanonicalCookie::RecordCookiePrefixMetrics(prefix, is_cookie_valid); + CookiePrefix prefix = GetCookiePrefix(parsed_cookie.Name()); + bool is_cookie_valid = IsCookiePrefixValid(prefix, url, parsed_cookie); + RecordCookiePrefixMetrics(prefix, is_cookie_valid); if (!is_cookie_valid) { VLOG(kVlogSetCookies) << "Create() failed because the cookie violated prefix rules."; return nullptr; } - return base::WrapUnique(new CanonicalCookie( + std::unique_ptr<CanonicalCookie> cc(base::MakeUnique<CanonicalCookie>( parsed_cookie.Name(), parsed_cookie.Value(), cookie_domain, cookie_path, creation_time, cookie_expires, creation_time, parsed_cookie.IsSecure(), parsed_cookie.IsHttpOnly(), parsed_cookie.SameSite(), parsed_cookie.Priority())); + DCHECK(cc->IsCanonical()); + return cc; } bool CanonicalCookie::IsEquivalentForSecureCookieMatching( @@ -399,6 +402,51 @@ return Priority() < other.Priority(); } +bool CanonicalCookie::IsCanonical() const { + // Not checking domain against ParsedCookie as it may have come purely + // from the URL. + if (ParsedCookie::ParseTokenString(name_) != name_ || + ParsedCookie::ParseValueString(value_) != value_ || + ParsedCookie::ParseValueString(path_) != path_ || + !ParsedCookie::IsValidCookieAttributeValue(name_) || + !ParsedCookie::IsValidCookieAttributeValue(value_) || + !ParsedCookie::IsValidCookieAttributeValue(path_)) { + return false; + } + + if (!last_access_date_.is_null() && creation_date_.is_null()) + return false; + + url::CanonHostInfo canon_host_info; + std::string canonical_domain(CanonicalizeHost(domain_, &canon_host_info)); + // TODO(rdsmith): This specifically allows for empty domains. The spec + // suggests this is invalid (if a domain attribute is empty, the cookie's + // domain is set to the canonicalized request host; see + // https://tools.ietf.org/html/rfc6265#section-5.3). However, it is + // needed for Chrome extension cookies. + // See http://crbug.com/730633 for more information. + if (canonical_domain != domain_) + return false; + + if (path_.empty() || path_[0] != '/') + return false; + + switch (GetCookiePrefix(name_)) { + case COOKIE_PREFIX_HOST: + if (!secure_ || path_ != "/" || domain_.empty() || domain_[0] == '.') + return false; + break; + case COOKIE_PREFIX_SECURE: + if (!secure_) + return false; + break; + default: + break; + } + + return true; +} + // static CanonicalCookie::CookiePrefix CanonicalCookie::GetCookiePrefix( const std::string& name) {
diff --git a/net/cookies/canonical_cookie.h b/net/cookies/canonical_cookie.h index a2b366d..1d3b3ed5 100644 --- a/net/cookies/canonical_cookie.h +++ b/net/cookies/canonical_cookie.h
@@ -144,6 +144,21 @@ // FullCompare() are also sorted with respect to PartialCompare(). bool FullCompare(const CanonicalCookie& other) const; + // Return whether this object is a valid CanonicalCookie(). Invalid + // cookies may be constructed by the detailed constructor. + // A cookie is considered canonical if-and-only-if: + // * It can be created by CanonicalCookie::Create, or + // * It is identical to a cookie created by CanonicalCookie::Create except + // that the creation time is null, or + // * It can be derived from a cookie created by CanonicalCookie::Create by + // entry into and retrieval from a cookie store (specifically, this means + // by the setting of an creation time in place of a null creation time, and + // the setting of a last access time). + // An additional requirement on a CanonicalCookie is that if the last + // access time is non-null, the creation time must also be non-null and + // greater than the last access time. + bool IsCanonical() const; + private: FRIEND_TEST_ALL_PREFIXES(CanonicalCookieTest, TestPrefixHistograms);
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc index 402846d..aaa9c69d 100644 --- a/net/cookies/canonical_cookie_unittest.cc +++ b/net/cookies/canonical_cookie_unittest.cc
@@ -44,6 +44,16 @@ EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie2->SameSite()); } +TEST(CanonicalCookie, SpaceInName) { + GURL url("http://www.example.com/test/foo.html"); + base::Time creation_time = base::Time::Now(); + CookieOptions options; + std::unique_ptr<CanonicalCookie> cookie( + CanonicalCookie::Create(url, "A C=2", creation_time, options)); + EXPECT_TRUE(cookie.get()); + EXPECT_EQ("A C", cookie->Name()); +} + TEST(CanonicalCookieTest, Create) { // Test creating cookies from a cookie string. GURL url("http://www.example.com/test/foo.html"); @@ -596,6 +606,264 @@ EXPECT_TRUE(https_cookie_secure.get()); } +TEST(CanonicalCookieTest, IsCanonical) { + // Base correct template. + EXPECT_TRUE(CanonicalCookie("A", "B", "x.y", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Newline in name. + EXPECT_FALSE(CanonicalCookie("A\n", "B", "x.y", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Carriage return in name. + EXPECT_FALSE(CanonicalCookie("A\r", "B", "x.y", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Null character in name. + EXPECT_FALSE(CanonicalCookie(std::string("A\0Z", 3), "B", "x.y", "/path", + base::Time(), base::Time(), base::Time(), false, + false, CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Name begins with whitespace. + EXPECT_FALSE(CanonicalCookie(" A", "B", "x.y", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Name ends with whitespace. + EXPECT_FALSE(CanonicalCookie("A ", "B", "x.y", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Empty name. (Note this is against the spec but compatible with other + // browsers.) + EXPECT_TRUE(CanonicalCookie("", "B", "x.y", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Space in name + EXPECT_TRUE(CanonicalCookie("A C", "B", "x.y", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Extra space suffixing name. + EXPECT_FALSE(CanonicalCookie("A ", "B", "x.y", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // '=' character in name. + EXPECT_FALSE(CanonicalCookie("A=", "B", "x.y", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Separator in name. + EXPECT_FALSE(CanonicalCookie("A;", "B", "x.y", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // '=' character in value. + EXPECT_TRUE(CanonicalCookie("A", "B=", "x.y", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Separator in value. + EXPECT_FALSE(CanonicalCookie("A", "B;", "x.y", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Separator in domain. + EXPECT_FALSE(CanonicalCookie("A", "B", ";x.y", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Garbage in domain. + EXPECT_FALSE(CanonicalCookie("A", "B", "@:&", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Space in domain. + EXPECT_FALSE(CanonicalCookie("A", "B", "x.y ", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Empty domain. (This is against cookie spec, but needed for Chrome's + // out-of-spec use of cookies for extensions; see http://crbug.com/730633. + EXPECT_TRUE(CanonicalCookie("A", "B", "", "/path", base::Time(), base::Time(), + base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Path does not start with a "/". + EXPECT_FALSE(CanonicalCookie("A", "B", "x.y", "path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Empty path. + EXPECT_FALSE(CanonicalCookie("A", "B", "x.y", "", base::Time(), base::Time(), + base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Path suffixed with a space. + EXPECT_FALSE(CanonicalCookie("A", "B", "x.y", "/path ", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Path suffixed with separator. + EXPECT_FALSE(CanonicalCookie("A", "B", "x.y", "/path;", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Simple IPv4 address as domain. + EXPECT_TRUE(CanonicalCookie("A", "B", "1.2.3.4", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // NOn-canonical IPv4 address as domain. + EXPECT_FALSE(CanonicalCookie("A", "B", "01.2.03.4", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Null IPv6 address as domain. + EXPECT_TRUE(CanonicalCookie("A", "B", "[::]", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Localhost IPv6 address as domain. + EXPECT_TRUE(CanonicalCookie("A", "B", "[::1]", "/path", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Fully speced IPv6 address as domain. + EXPECT_FALSE(CanonicalCookie( + "A", "B", "[2001:0DB8:AC10:FE01:0000:0000:0000:0000]", + "/path", base::Time(), base::Time(), base::Time(), false, + false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Zero abbreviated IPv6 address as domain. Not canonical because of leading + // zeros & uppercase hex letters. + EXPECT_FALSE(CanonicalCookie("A", "B", "[2001:0DB8:AC10:FE01::]", "/path", + base::Time(), base::Time(), base::Time(), false, + false, CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Zero prefixes removed IPv6 address as domain. Not canoncial because of + // uppercase hex letters. + EXPECT_FALSE(CanonicalCookie("A", "B", "[2001:DB8:AC10:FE01::]", "/path", + base::Time(), base::Time(), base::Time(), false, + false, CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Lowercased hex IPv6 address as domain. + EXPECT_TRUE(CanonicalCookie("A", "B", "[2001:db8:ac10:fe01::]", "/path", + base::Time(), base::Time(), base::Time(), false, + false, CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Properly formatted host cookie. + EXPECT_TRUE(CanonicalCookie("__Host-A", "B", "x.y", "/", base::Time(), + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Insecure host cookie. + EXPECT_FALSE(CanonicalCookie("__Host-A", "B", "x.y", "/", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Host cookie with non-null path. + EXPECT_FALSE(CanonicalCookie("__Host-A", "B", "x.y", "/path", base::Time(), + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Host cookie with empty domain. + EXPECT_FALSE(CanonicalCookie("__Host-A", "B", "", "/", base::Time(), + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Host cookie with period prefixed domain. + EXPECT_FALSE(CanonicalCookie("__Host-A", "B", ".x.y", "/", base::Time(), + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Properly formatted secure cookie. + EXPECT_TRUE(CanonicalCookie("__Secure-A", "B", "x.y", "/", base::Time(), + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); + + // Insecure secure cookie. + EXPECT_FALSE(CanonicalCookie("__Secure-A", "B", "x.y", "/", base::Time(), + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW) + .IsCanonical()); +} + TEST(CanonicalCookieTest, TestPrefixHistograms) { base::HistogramTester histograms; const char kCookiePrefixHistogram[] = "Cookie.CookiePrefix";
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc index 3cd57005..0b60812a 100644 --- a/net/cookies/cookie_monster_unittest.cc +++ b/net/cookies/cookie_monster_unittest.cc
@@ -109,6 +109,7 @@ static const bool preserves_trailing_dots = true; static const bool filters_schemes = true; static const bool has_path_prefix_bug = false; + static const bool forbids_setting_empty_name = false; static const int creation_time_granularity_in_ms = 0; };
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h index 8120bf0d..14aa3e9 100644 --- a/net/cookies/cookie_store_unittest.h +++ b/net/cookies/cookie_store_unittest.h
@@ -1279,6 +1279,38 @@ "a=val99", this->GetCookies(cs, GURL("http://chromium.org/path1"))); } +// Note that accepting an empty name is contrary to spec; see +// https://tools.ietf.org/html/rfc6265#section-4.1.1. However, we do it +// for web compatibility; see http://inikulin.github.io/cookie-compat/ +// (specifically the "foo" and "=a" tests). This test is present in Chromium +// so that a flag is raised if this behavior is changed. +// On IOS we use the system cookie store which has Safari's behavior, so +// the test is skipped. +TYPED_TEST_P(CookieStoreTest, EmptyName) { + if (TypeParam::forbids_setting_empty_name) + return; + + GURL url_foo("http://www.foo.com/"); + CookieStore* cs = this->GetCookieStore(); + + CookieOptions options; + if (!TypeParam::supports_http_only) + options.set_include_httponly(); + EXPECT_TRUE(this->SetCookieWithOptions(cs, url_foo, "a", options)); + CookieList list = this->GetAllCookiesForURL(cs, url_foo); + EXPECT_EQ(1u, list.size()); + EXPECT_EQ("", list[0].Name()); + EXPECT_EQ("a", list[0].Value()); + EXPECT_EQ(1, this->DeleteAll(cs)); + + EXPECT_TRUE(this->SetCookieWithOptions(cs, url_foo, "=b", options)); + list = this->GetAllCookiesForURL(cs, url_foo); + EXPECT_EQ(1u, list.size()); + EXPECT_EQ("", list[0].Name()); + EXPECT_EQ("b", list[0].Value()); + EXPECT_EQ(1, this->DeleteAll(cs)); +} + TYPED_TEST_P(CookieStoreTest, CookieOrdering) { // Put a random set of cookies into a store and make sure they're returned in // the right order. @@ -1476,6 +1508,7 @@ TestSecure, NetUtilCookieTest, OverwritePersistentCookie, + EmptyName, CookieOrdering, GetAllCookiesAsync, DeleteCookieAsync,
diff --git a/net/cookies/parsed_cookie.cc b/net/cookies/parsed_cookie.cc index ac3f87dd..8832afdb 100644 --- a/net/cookies/parsed_cookie.cc +++ b/net/cookies/parsed_cookie.cc
@@ -124,16 +124,6 @@ return c <= 31; } -bool IsValidCookieAttributeValue(const std::string& value) { - // The greatest common denominator of cookie attribute values is - // <any CHAR except CTLs or ";"> according to RFC 6265. - for (std::string::const_iterator i = value.begin(); i != value.end(); ++i) { - if (IsControlCharacter(*i) || *i == ';') - return false; - } - return true; -} - } // namespace namespace net { @@ -240,6 +230,7 @@ return out; } +// static std::string::const_iterator ParsedCookie::FindFirstTerminator( const std::string& s) { std::string::const_iterator end = s.end(); @@ -251,6 +242,7 @@ return end; } +// static bool ParsedCookie::ParseToken(std::string::const_iterator* it, const std::string::const_iterator& end, std::string::const_iterator* token_start, @@ -287,6 +279,7 @@ return true; } +// static void ParsedCookie::ParseValue(std::string::const_iterator* it, const std::string::const_iterator& end, std::string::const_iterator* value_start, @@ -313,6 +306,7 @@ } } +// static std::string ParsedCookie::ParseTokenString(const std::string& token) { std::string::const_iterator it = token.begin(); std::string::const_iterator end = FindFirstTerminator(token); @@ -323,6 +317,7 @@ return std::string(); } +// static std::string ParsedCookie::ParseValueString(const std::string& value) { std::string::const_iterator it = value.begin(); std::string::const_iterator end = FindFirstTerminator(value); @@ -332,6 +327,17 @@ return std::string(value_start, value_end); } +// static +bool ParsedCookie::IsValidCookieAttributeValue(const std::string& value) { + // The greatest common denominator of cookie attribute values is + // <any CHAR except CTLs or ";"> according to RFC 6265. + for (std::string::const_iterator i = value.begin(); i != value.end(); ++i) { + if (IsControlCharacter(*i) || *i == ';') + return false; + } + return true; +} + // Parse all token/value pairs and populate pairs_. void ParsedCookie::ParseTokenValuePairs(const std::string& cookie_line) { pairs_.clear();
diff --git a/net/cookies/parsed_cookie.h b/net/cookies/parsed_cookie.h index 5e6f615..8bc5e99 100644 --- a/net/cookies/parsed_cookie.h +++ b/net/cookies/parsed_cookie.h
@@ -103,6 +103,9 @@ static std::string ParseTokenString(const std::string& token); static std::string ParseValueString(const std::string& value); + // Is the string valid as the value of a cookie attribute? + static bool IsValidCookieAttributeValue(const std::string& value); + private: void ParseTokenValuePairs(const std::string& cookie_line); void SetupAttributes();
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc index dd17ae5..644000c 100644 --- a/net/http/http_cache_transaction.cc +++ b/net/http/http_cache_transaction.cc
@@ -1822,11 +1822,14 @@ // failure, restart this transaction. DCHECK(!reading_); + // Reset before invoking SetRequest() which can reset the request info sent to + // network transaction. + if (network_trans_) + network_trans_.reset(); + SetRequest(net_log_); entry_ = nullptr; - if (network_trans_) - network_trans_.reset(); TransitionToState(STATE_GET_BACKEND); return OK; @@ -2054,16 +2057,18 @@ //----------------------------------------------------------------------------- void HttpCache::Transaction::SetRequest(const NetLogWithSource& net_log) { + net_log_ = net_log; + // Reset the variables that might get set in this function. This is done // because this function can be invoked multiple times for a transaction. cache_entry_status_ = CacheEntryStatus::ENTRY_UNDEFINED; external_validation_.Reset(); range_requested_ = false; partial_.reset(); + + request_ = initial_request_; custom_request_.reset(); - net_log_ = net_log; - request_ = initial_request_; effective_load_flags_ = request_->load_flags; method_ = request_->method; @@ -2148,6 +2153,8 @@ if (method_ == "GET" && partial_->Init(request_->extra_headers)) { // We will be modifying the actual range requested to the server, so // let's remove the header here. + // Note that custom_request_ is a shallow copy so will keep the same + // pointer to upload data stream as in the original request. custom_request_.reset(new HttpRequestInfo(*request_)); custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange); request_ = custom_request_.get();
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index d2f0971..869708f 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc
@@ -858,12 +858,13 @@ cache.disk_cache()->set_soft_failures(true); + MockHttpRequest request(kSimpleGET_Transaction); + // Now fail to read from the cache. auto c = base::MakeUnique<Context>(); int rv = cache.CreateTransaction(&c->trans); ASSERT_THAT(rv, IsOk()); - MockHttpRequest request(kSimpleGET_Transaction); rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource()); EXPECT_THAT(c->callback.GetResult(rv), IsOk()); @@ -7971,10 +7972,10 @@ TestCompletionCallback callback; { + MockHttpRequest request(kSimpleGET_Transaction); std::unique_ptr<HttpTransaction> trans; ASSERT_THAT(cache.CreateTransaction(&trans), IsOk()); - MockHttpRequest request(kSimpleGET_Transaction); int rv = trans->Start(&request, callback.callback(), NetLogWithSource()); EXPECT_THAT(callback.GetResult(rv), IsOk()); @@ -8006,11 +8007,11 @@ ScopedMockTransaction transaction(kSimpleGET_Transaction); transaction.data = ""; + MockHttpRequest request(transaction); std::unique_ptr<HttpTransaction> trans; ASSERT_THAT(cache.CreateTransaction(&trans), IsOk()); - MockHttpRequest request(transaction); int rv = trans->Start(&request, callback.callback(), NetLogWithSource()); EXPECT_THAT(callback.GetResult(rv), IsOk()); @@ -8536,6 +8537,7 @@ TEST(HttpCache, SetPriority) { MockHttpCache cache; + HttpRequestInfo info; std::unique_ptr<HttpTransaction> trans; ASSERT_THAT(cache.http_cache()->CreateTransaction(IDLE, &trans), IsOk()); @@ -8546,7 +8548,6 @@ EXPECT_EQ(DEFAULT_PRIORITY, cache.network_layer()->last_create_transaction_priority()); - HttpRequestInfo info; info.url = GURL(kSimpleGET_Transaction.url); TestCompletionCallback callback; EXPECT_EQ(ERR_IO_PENDING, @@ -8572,6 +8573,7 @@ // transaction passes on its argument to the underlying network transaction. TEST(HttpCache, SetWebSocketHandshakeStreamCreateHelper) { MockHttpCache cache; + HttpRequestInfo info; FakeWebSocketHandshakeStreamCreateHelper create_helper; std::unique_ptr<HttpTransaction> trans; @@ -8579,7 +8581,6 @@ EXPECT_FALSE(cache.network_layer()->last_transaction()); - HttpRequestInfo info; info.url = GURL(kSimpleGET_Transaction.url); TestCompletionCallback callback; EXPECT_EQ(ERR_IO_PENDING,
diff --git a/net/http/http_stream_factory_impl_job_controller.cc b/net/http/http_stream_factory_impl_job_controller.cc index 660ff8f..3e46fa94 100644 --- a/net/http/http_stream_factory_impl_job_controller.cc +++ b/net/http/http_stream_factory_impl_job_controller.cc
@@ -107,9 +107,7 @@ alternative_job_.reset(); bound_job_ = nullptr; if (pac_request_) { - // TODO(mmenke): Convert this to a DCHECK once https://crbug.com/723589 is - // resolved. - CHECK_EQ(STATE_RESOLVE_PROXY_COMPLETE, next_state_); + DCHECK_EQ(STATE_RESOLVE_PROXY_COMPLETE, next_state_); session_->proxy_service()->CancelPacRequest(pac_request_); } net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER); @@ -711,9 +709,7 @@ } int HttpStreamFactoryImpl::JobController::DoResolveProxy() { - // TODO(mmenke): Convert this to a DCHECK once https://crbug.com/723589 is - // resolved. - CHECK(!pac_request_); + DCHECK(!pac_request_); DCHECK(session_); next_state_ = STATE_RESOLVE_PROXY_COMPLETE; @@ -1245,9 +1241,7 @@ int error) { // ReconsiderProxyAfterError() should only be called when the last job fails. DCHECK(!(alternative_job_ && main_job_)); - // TODO(mmenke): Convert this to a DCHECK once https://crbug.com/723589 is - // resolved. - CHECK(!pac_request_); + DCHECK(!pac_request_); DCHECK(session_); if (!job->should_reconsider_proxy())
diff --git a/net/http/http_transaction_test_util.cc b/net/http/http_transaction_test_util.cc index 2d728cf..9b683ef 100644 --- a/net/http/http_transaction_test_util.cc +++ b/net/http/http_transaction_test_util.cc
@@ -239,7 +239,12 @@ done_reading_called_(false), weak_factory_(this) {} -MockNetworkTransaction::~MockNetworkTransaction() {} +MockNetworkTransaction::~MockNetworkTransaction() { + // Use request_ as in ~HttpNetworkTransaction to make sure its valid and not + // already freed by the consumer. See crbug.com/734037. + if (request_) + DCHECK(request_->load_flags >= 0); +} int MockNetworkTransaction::Start(const HttpRequestInfo* request, const CompletionCallback& callback,
diff --git a/services/resource_coordinator/coordination_unit/coordination_unit_manager.cc b/services/resource_coordinator/coordination_unit/coordination_unit_manager.cc index 4eca58767..714313c 100644 --- a/services/resource_coordinator/coordination_unit/coordination_unit_manager.cc +++ b/services/resource_coordinator/coordination_unit/coordination_unit_manager.cc
@@ -7,7 +7,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "services/resource_coordinator/coordination_unit/coordination_unit_provider_impl.h" -#include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/service_context.h" namespace resource_coordinator {
diff --git a/services/resource_coordinator/coordination_unit/coordination_unit_manager.h b/services/resource_coordinator/coordination_unit/coordination_unit_manager.h index 7d07f8b..4b10fcd 100644 --- a/services/resource_coordinator/coordination_unit/coordination_unit_manager.h +++ b/services/resource_coordinator/coordination_unit/coordination_unit_manager.h
@@ -6,9 +6,9 @@ #define SERVICES_RESOURCE_COORDINATOR_COORDINATION_UNIT_COORDINATION_UNIT_MANAGER_H_ #include "base/macros.h" +#include "services/service_manager/public/cpp/binder_registry.h" namespace service_manager { -class BinderRegistry; class ServiceContextRefFactory; } // service_manager
diff --git a/services/service_manager/public/cpp/BUILD.gn b/services/service_manager/public/cpp/BUILD.gn index 1e6a2f6..c015921 100644 --- a/services/service_manager/public/cpp/BUILD.gn +++ b/services/service_manager/public/cpp/BUILD.gn
@@ -6,13 +6,11 @@ output_name = "service_manager_cpp" sources = [ - "binder_registry.cc", "binder_registry.h", "connect.h", "connector.cc", "connector.h", "export.h", - "interface_binder.cc", "interface_binder.h", "interface_provider.cc", "interface_provider.h",
diff --git a/services/service_manager/public/cpp/binder_registry.cc b/services/service_manager/public/cpp/binder_registry.cc deleted file mode 100644 index d50de16f..0000000 --- a/services/service_manager/public/cpp/binder_registry.cc +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/service_manager/public/cpp/binder_registry.h" - -#include "services/service_manager/public/cpp/identity.h" - -namespace service_manager { - -BinderRegistry::BinderRegistry() : weak_factory_(this) {} -BinderRegistry::~BinderRegistry() {} - -void BinderRegistry::AddInterface( - const std::string& interface_name, - const base::Callback<void(mojo::ScopedMessagePipeHandle)>& callback, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { - SetInterfaceBinder(interface_name, base::MakeUnique<GenericCallbackBinder>( - callback, task_runner)); -} - -void BinderRegistry::AddInterface( - const std::string& interface_name, - const Binder& binder_callback, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { - SetInterfaceBinder(interface_name, base::MakeUnique<GenericCallbackBinder>( - binder_callback, task_runner)); -} - -void BinderRegistry::RemoveInterface(const std::string& interface_name) { - auto it = binders_.find(interface_name); - if (it != binders_.end()) - binders_.erase(it); -} - -bool BinderRegistry::CanBindInterface(const std::string& interface_name) const { - auto it = binders_.find(interface_name); - return it != binders_.end(); -} - -void BinderRegistry::BindInterface( - const BindSourceInfo& source_info, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle interface_pipe) { - auto it = binders_.find(interface_name); - if (it != binders_.end()) { - it->second->BindInterface(source_info, interface_name, - std::move(interface_pipe)); - } else { - LOG(ERROR) << "Failed to locate a binder for interface: " << interface_name; - } -} - -base::WeakPtr<BinderRegistry> BinderRegistry::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); -} - -void BinderRegistry::SetInterfaceBinder( - const std::string& interface_name, - std::unique_ptr<InterfaceBinder> binder) { - RemoveInterface(interface_name); - binders_[interface_name] = std::move(binder); -} - -} // namespace service_manager
diff --git a/services/service_manager/public/cpp/binder_registry.h b/services/service_manager/public/cpp/binder_registry.h index 0cce9d98..e499b7a 100644 --- a/services/service_manager/public/cpp/binder_registry.h +++ b/services/service_manager/public/cpp/binder_registry.h
@@ -20,34 +20,46 @@ struct BindSourceInfo; -class SERVICE_MANAGER_PUBLIC_CPP_EXPORT BinderRegistry { +template <typename... BinderArgs> +class BinderRegistryWithParams { public: using Binder = base::Callback<void(const BindSourceInfo&, const std::string&, - mojo::ScopedMessagePipeHandle)>; + mojo::ScopedMessagePipeHandle, + BinderArgs...)>; - BinderRegistry(); - ~BinderRegistry(); + BinderRegistryWithParams() : weak_factory_(this) {} + ~BinderRegistryWithParams() = default; template <typename Interface> - void AddInterface( - const base::Callback<void(const BindSourceInfo&, - mojo::InterfaceRequest<Interface>)>& callback, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner = - nullptr) { + void AddInterface(const base::Callback<void(const BindSourceInfo&, + mojo::InterfaceRequest<Interface>, + BinderArgs...)>& callback, + const scoped_refptr<base::SingleThreadTaskRunner>& + task_runner = nullptr) { SetInterfaceBinder( Interface::Name_, - base::MakeUnique<CallbackBinder<Interface>>(callback, task_runner)); + base::MakeUnique<CallbackBinder<Interface, BinderArgs...>>( + callback, task_runner)); } void AddInterface( const std::string& interface_name, - const base::Callback<void(mojo::ScopedMessagePipeHandle)>& callback, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner = nullptr); - - void AddInterface( - const std::string& interface_name, - const Binder& binder_callback, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner = nullptr); + const base::Callback<void(mojo::ScopedMessagePipeHandle, BinderArgs...)>& + callback, + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner = + nullptr) { + SetInterfaceBinder(interface_name, + base::MakeUnique<GenericCallbackBinder<BinderArgs...>>( + callback, task_runner)); + } + void AddInterface(const std::string& interface_name, + const Binder& callback, + const scoped_refptr<base::SingleThreadTaskRunner>& + task_runner = nullptr) { + SetInterfaceBinder(interface_name, + base::MakeUnique<GenericCallbackBinder<BinderArgs...>>( + callback, task_runner)); + } // Removes the specified interface from the registry. This has no effect on // bindings already completed. @@ -55,34 +67,58 @@ void RemoveInterface() { RemoveInterface(Interface::Name_); } - void RemoveInterface(const std::string& interface_name); + void RemoveInterface(const std::string& interface_name) { + auto it = binders_.find(interface_name); + if (it != binders_.end()) + binders_.erase(it); + } // Returns true if an InterfaceBinder is registered for |interface_name|. - bool CanBindInterface(const std::string& interface_name) const; + bool CanBindInterface(const std::string& interface_name) const { + auto it = binders_.find(interface_name); + return it != binders_.end(); + } // Completes binding the request for |interface_name| on |interface_pipe|, by // invoking the corresponding InterfaceBinder. void BindInterface(const BindSourceInfo& source_info, const std::string& interface_name, - mojo::ScopedMessagePipeHandle interface_pipe); + mojo::ScopedMessagePipeHandle interface_pipe, + BinderArgs... args) { + auto it = binders_.find(interface_name); + if (it != binders_.end()) { + it->second->BindInterface(source_info, interface_name, + std::move(interface_pipe), args...); + } else { + LOG(ERROR) << "Failed to locate a binder for interface: " + << interface_name; + } + } - base::WeakPtr<BinderRegistry> GetWeakPtr(); + base::WeakPtr<BinderRegistryWithParams> GetWeakPtr() { + return weak_factory_.GetWeakPtr(); + } private: using InterfaceNameToBinderMap = - std::map<std::string, std::unique_ptr<InterfaceBinder>>; + std::map<std::string, std::unique_ptr<InterfaceBinder<BinderArgs...>>>; // Adds |binder| to the internal map. - void SetInterfaceBinder(const std::string& interface_name, - std::unique_ptr<InterfaceBinder> binder); + void SetInterfaceBinder( + const std::string& interface_name, + std::unique_ptr<InterfaceBinder<BinderArgs...>> binder) { + RemoveInterface(interface_name); + binders_[interface_name] = std::move(binder); + } InterfaceNameToBinderMap binders_; - base::WeakPtrFactory<BinderRegistry> weak_factory_; + base::WeakPtrFactory<BinderRegistryWithParams> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(BinderRegistry); + DISALLOW_COPY_AND_ASSIGN(BinderRegistryWithParams); }; +using BinderRegistry = BinderRegistryWithParams<>; } // namespace service_manager
diff --git a/services/service_manager/public/cpp/interface_binder.cc b/services/service_manager/public/cpp/interface_binder.cc deleted file mode 100644 index 3d4a032..0000000 --- a/services/service_manager/public/cpp/interface_binder.cc +++ /dev/null
@@ -1,58 +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 "services/service_manager/public/cpp/interface_binder.h" - -#include "services/service_manager/public/cpp/bind_source_info.h" - -namespace service_manager { - -namespace { - -void BindCallbackAdapter( - const base::Callback<void(mojo::ScopedMessagePipeHandle)>& callback, - const BindSourceInfo& source_info, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle handle) { - callback.Run(std::move(handle)); -} - -} // namespace - -GenericCallbackBinder::GenericCallbackBinder( - const BindCallback& callback, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) - : callback_(callback), task_runner_(task_runner) {} - -GenericCallbackBinder::GenericCallbackBinder( - const base::Callback<void(mojo::ScopedMessagePipeHandle)>& callback, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) - : callback_(base::Bind(&BindCallbackAdapter, callback)), - task_runner_(task_runner) {} - -GenericCallbackBinder::~GenericCallbackBinder() {} - -void GenericCallbackBinder::BindInterface( - const BindSourceInfo& source_info, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle handle) { - if (task_runner_) { - task_runner_->PostTask( - FROM_HERE, - base::Bind(&GenericCallbackBinder::RunCallback, callback_, source_info, - interface_name, base::Passed(&handle))); - return; - } - RunCallback(callback_, source_info, interface_name, std::move(handle)); -} - -// static -void GenericCallbackBinder::RunCallback(const BindCallback& callback, - const BindSourceInfo& source_info, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle handle) { - callback.Run(source_info, interface_name, std::move(handle)); -} - -} // namespace service_manager
diff --git a/services/service_manager/public/cpp/interface_binder.h b/services/service_manager/public/cpp/interface_binder.h index a53aa057..3daab552 100644 --- a/services/service_manager/public/cpp/interface_binder.h +++ b/services/service_manager/public/cpp/interface_binder.h
@@ -11,11 +11,22 @@ #include "base/bind.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "mojo/public/cpp/system/message_pipe.h" +#include "services/service_manager/public/cpp/bind_source_info.h" namespace service_manager { -struct BindSourceInfo; +template <typename... BinderArgs> +void BindCallbackAdapter( + const base::Callback<void(mojo::ScopedMessagePipeHandle, BinderArgs...)>& + callback, + const BindSourceInfo& source_info, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle handle, + BinderArgs... args) { + callback.Run(std::move(handle), args...); +} +template <typename... BinderArgs> class InterfaceBinder { public: virtual ~InterfaceBinder() {} @@ -25,11 +36,12 @@ // an implementation it must take ownership of the request handle. virtual void BindInterface(const BindSourceInfo& source_info, const std::string& interface_name, - mojo::ScopedMessagePipeHandle handle) = 0; + mojo::ScopedMessagePipeHandle handle, + BinderArgs... args) = 0; }; -template <typename Interface> -class CallbackBinder : public InterfaceBinder { +template <typename Interface, typename... BinderArgs> +class CallbackBinder : public InterfaceBinder<BinderArgs...> { public: using BindCallback = base::Callback<void(const BindSourceInfo&, mojo::InterfaceRequest<Interface>)>; @@ -43,21 +55,23 @@ // InterfaceBinder: void BindInterface(const BindSourceInfo& source_info, const std::string& interface_name, - mojo::ScopedMessagePipeHandle handle) override { + mojo::ScopedMessagePipeHandle handle, + BinderArgs... args) override { mojo::InterfaceRequest<Interface> request(std::move(handle)); if (task_runner_) { task_runner_->PostTask( FROM_HERE, base::BindOnce(&CallbackBinder::RunCallback, callback_, - source_info, std::move(request))); + source_info, std::move(request), args...)); } else { - RunCallback(callback_, source_info, std::move(request)); + RunCallback(callback_, source_info, std::move(request), args...); } } static void RunCallback(const BindCallback& callback, const BindSourceInfo& source_info, - mojo::InterfaceRequest<Interface> request) { - callback.Run(source_info, std::move(request)); + mojo::InterfaceRequest<Interface> request, + BinderArgs... args) { + callback.Run(source_info, std::move(request), args...); } const BindCallback callback_; @@ -65,30 +79,50 @@ DISALLOW_COPY_AND_ASSIGN(CallbackBinder); }; -class GenericCallbackBinder : public InterfaceBinder { +template <typename... BinderArgs> +class GenericCallbackBinder : public InterfaceBinder<BinderArgs...> { public: using BindCallback = base::Callback<void(const BindSourceInfo&, const std::string&, - mojo::ScopedMessagePipeHandle)>; + mojo::ScopedMessagePipeHandle, + BinderArgs...)>; GenericCallbackBinder( const BindCallback& callback, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner); + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) + : callback_(callback), task_runner_(task_runner) {} GenericCallbackBinder( - const base::Callback<void(mojo::ScopedMessagePipeHandle)>& callback, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner); - ~GenericCallbackBinder() override; + const base::Callback<void(mojo::ScopedMessagePipeHandle, BinderArgs...)>& + callback, + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) + : callback_(base::Bind(&BindCallbackAdapter<BinderArgs...>, callback)), + task_runner_(task_runner) {} + ~GenericCallbackBinder() override {} private: // InterfaceBinder: void BindInterface(const BindSourceInfo& source_info, const std::string& interface_name, - mojo::ScopedMessagePipeHandle handle) override; + mojo::ScopedMessagePipeHandle handle, + BinderArgs... args) override { + if (task_runner_) { + task_runner_->PostTask( + FROM_HERE, base::Bind(&GenericCallbackBinder::RunCallback, callback_, + source_info, interface_name, + base::Passed(&handle), args...)); + return; + } + RunCallback(callback_, source_info, interface_name, std::move(handle), + args...); + } static void RunCallback(const BindCallback& callback, const BindSourceInfo& source_info, const std::string& interface_name, - mojo::ScopedMessagePipeHandle client_handle); + mojo::ScopedMessagePipeHandle handle, + BinderArgs... args) { + callback.Run(source_info, interface_name, std::move(handle), args...); + } const BindCallback callback_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/services/ui/display/screen_manager.h b/services/ui/display/screen_manager.h index 017b40db..4cec5ee 100644 --- a/services/ui/display/screen_manager.h +++ b/services/ui/display/screen_manager.h
@@ -8,12 +8,9 @@ #include <memory> #include "base/macros.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "services/ui/display/screen_manager_delegate.h" -namespace service_manager { -class BinderRegistry; -} - namespace display { class ScreenBase;
diff --git a/services/ui/input_devices/input_device_server.cc b/services/ui/input_devices/input_device_server.cc index 5f5a5da..d1275f3 100644 --- a/services/ui/input_devices/input_device_server.cc +++ b/services/ui/input_devices/input_device_server.cc
@@ -8,7 +8,6 @@ #include <vector> #include "services/service_manager/public/cpp/bind_source_info.h" -#include "services/service_manager/public/cpp/binder_registry.h" #include "ui/events/devices/input_device.h" #include "ui/events/devices/touchscreen_device.h"
diff --git a/services/ui/input_devices/input_device_server.h b/services/ui/input_devices/input_device_server.h index c64bda2..2ce10100 100644 --- a/services/ui/input_devices/input_device_server.h +++ b/services/ui/input_devices/input_device_server.h
@@ -8,12 +8,12 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/interface_ptr_set.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "services/ui/public/interfaces/input_devices/input_device_server.mojom.h" #include "ui/events/devices/device_data_manager.h" #include "ui/events/devices/input_device_event_observer.h" namespace service_manager { -class BinderRegistry; struct BindSourceInfo; }
diff --git a/services/ui/input_devices/touch_device_server.cc b/services/ui/input_devices/touch_device_server.cc index efd88ba..bf74e76 100644 --- a/services/ui/input_devices/touch_device_server.cc +++ b/services/ui/input_devices/touch_device_server.cc
@@ -8,7 +8,6 @@ #include <vector> #include "services/service_manager/public/cpp/bind_source_info.h" -#include "services/service_manager/public/cpp/binder_registry.h" #include "ui/display/manager/chromeos/default_touch_transform_setter.h" #include "ui/events/devices/input_device.h" #include "ui/events/devices/touchscreen_device.h"
diff --git a/services/ui/input_devices/touch_device_server.h b/services/ui/input_devices/touch_device_server.h index 6def2b0..a06f6120 100644 --- a/services/ui/input_devices/touch_device_server.h +++ b/services/ui/input_devices/touch_device_server.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/interface_ptr_set.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "services/ui/public/interfaces/input_devices/touch_device_server.mojom.h" namespace display { @@ -15,7 +16,6 @@ } namespace service_manager { -class BinderRegistry; struct BindSourceInfo; }
diff --git a/services/ui/public/cpp/input_devices/input_device_controller.cc b/services/ui/public/cpp/input_devices/input_device_controller.cc index 084236ac..0dea582 100644 --- a/services/ui/public/cpp/input_devices/input_device_controller.cc +++ b/services/ui/public/cpp/input_devices/input_device_controller.cc
@@ -8,7 +8,6 @@ #include "base/bind.h" #include "services/service_manager/public/cpp/bind_source_info.h" -#include "services/service_manager/public/cpp/binder_registry.h" #include "ui/events/devices/input_device.h" #include "ui/events/devices/touchscreen_device.h" #include "ui/events/keycodes/dom/dom_code.h"
diff --git a/services/ui/public/cpp/input_devices/input_device_controller.h b/services/ui/public/cpp/input_devices/input_device_controller.h index 9164a1e..7fea004 100644 --- a/services/ui/public/cpp/input_devices/input_device_controller.h +++ b/services/ui/public/cpp/input_devices/input_device_controller.h
@@ -8,10 +8,10 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/interface_ptr_set.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "services/ui/public/interfaces/input_devices/input_device_controller.mojom.h" namespace service_manager { -class BinderRegistry; struct BindSourceInfo; }
diff --git a/services/video_capture/BUILD.gn b/services/video_capture/BUILD.gn index be8833cb..789fef2c0 100644 --- a/services/video_capture/BUILD.gn +++ b/services/video_capture/BUILD.gn
@@ -37,6 +37,8 @@ "receiver_mojo_to_media_adapter.h", "service_impl.cc", "service_impl.h", + "testing_controls_impl.cc", + "testing_controls_impl.h", ] public_deps = [
diff --git a/services/video_capture/public/interfaces/BUILD.gn b/services/video_capture/public/interfaces/BUILD.gn index 58034c9..36fc949 100644 --- a/services/video_capture/public/interfaces/BUILD.gn +++ b/services/video_capture/public/interfaces/BUILD.gn
@@ -10,6 +10,7 @@ "device_factory.mojom", "device_factory_provider.mojom", "receiver.mojom", + "testing_controls.mojom", ] deps = [
diff --git a/services/video_capture/public/interfaces/testing_controls.mojom b/services/video_capture/public/interfaces/testing_controls.mojom new file mode 100644 index 0000000..fd5ac97 --- /dev/null +++ b/services/video_capture/public/interfaces/testing_controls.mojom
@@ -0,0 +1,11 @@ +// 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. + +module video_capture.mojom; + +// APIs for allowing tests to control service behavior for the purpose of +// integration testing. +interface TestingControls { + Crash(); +};
diff --git a/services/video_capture/service_impl.cc b/services/video_capture/service_impl.cc index 16bfa06..5c4aa54 100644 --- a/services/video_capture/service_impl.cc +++ b/services/video_capture/service_impl.cc
@@ -8,6 +8,7 @@ #include "services/service_manager/public/cpp/service_context.h" #include "services/video_capture/device_factory_provider_impl.h" #include "services/video_capture/public/interfaces/constants.mojom.h" +#include "services/video_capture/testing_controls_impl.h" namespace video_capture { @@ -28,6 +29,10 @@ // Unretained |this| is safe because |registry_| is owned by |this|. base::Bind(&ServiceImpl::OnDeviceFactoryProviderRequest, base::Unretained(this))); + registry_.AddInterface<mojom::TestingControls>( + // Unretained |this| is safe because |registry_| is owned by |this|. + base::Bind(&ServiceImpl::OnTestingControlsRequest, + base::Unretained(this))); } void ServiceImpl::OnBindInterface( @@ -60,6 +65,15 @@ std::move(request)); } +void ServiceImpl::OnTestingControlsRequest( + const service_manager::BindSourceInfo& source_info, + mojom::TestingControlsRequest request) { + DCHECK(thread_checker_.CalledOnValidThread()); + mojo::MakeStrongBinding( + base::MakeUnique<TestingControlsImpl>(ref_factory_->CreateRef()), + std::move(request)); +} + void ServiceImpl::SetShutdownDelayInSeconds(float seconds) { DCHECK(thread_checker_.CalledOnValidThread()); shutdown_delay_in_seconds_ = seconds;
diff --git a/services/video_capture/service_impl.h b/services/video_capture/service_impl.h index fc40952..34d7079 100644 --- a/services/video_capture/service_impl.h +++ b/services/video_capture/service_impl.h
@@ -12,6 +12,7 @@ #include "services/service_manager/public/cpp/service.h" #include "services/service_manager/public/cpp/service_context_ref.h" #include "services/video_capture/public/interfaces/device_factory_provider.mojom.h" +#include "services/video_capture/public/interfaces/testing_controls.mojom.h" #if defined(OS_WIN) #include "base/win/scoped_com_initializer.h" @@ -35,6 +36,9 @@ void OnDeviceFactoryProviderRequest( const service_manager::BindSourceInfo& source_info, mojom::DeviceFactoryProviderRequest request); + void OnTestingControlsRequest( + const service_manager::BindSourceInfo& source_info, + mojom::TestingControlsRequest request); void SetShutdownDelayInSeconds(float seconds); void MaybeRequestQuitDelayed(); void MaybeRequestQuit();
diff --git a/services/video_capture/service_manifest.json b/services/video_capture/service_manifest.json index 62d76da..dcd36230 100644 --- a/services/video_capture/service_manifest.json +++ b/services/video_capture/service_manifest.json
@@ -3,11 +3,14 @@ "display_name": "Video Capture", "interface_provider_specs": { "service_manager:connector": { - "provides": { - "capture": [ "video_capture::mojom::DeviceFactoryProvider" ], - "tests": [ "*" ] + "provides" : { + "capture" : ["video_capture::mojom::DeviceFactoryProvider"], + "tests" : [ + "video_capture::mojom::DeviceFactoryProvider", + "video_capture::mojom::TestingControls" + ] }, - "requires": { + "requires" : { "service_manager": [ "service_manager:all_users" ] } }
diff --git a/services/video_capture/testing_controls_impl.cc b/services/video_capture/testing_controls_impl.cc new file mode 100644 index 0000000..e89eb86 --- /dev/null +++ b/services/video_capture/testing_controls_impl.cc
@@ -0,0 +1,19 @@ +// 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 "services/video_capture/testing_controls_impl.h" + +namespace video_capture { + +TestingControlsImpl::TestingControlsImpl( + std::unique_ptr<service_manager::ServiceContextRef> service_ref) + : service_ref_(std::move(service_ref)) {} + +TestingControlsImpl::~TestingControlsImpl() = default; + +void TestingControlsImpl::Crash() { + CHECK(false) << "This is an intentional crash for the purpose of testing"; +} + +} // namespace video_capture
diff --git a/services/video_capture/testing_controls_impl.h b/services/video_capture/testing_controls_impl.h new file mode 100644 index 0000000..f0a17fe --- /dev/null +++ b/services/video_capture/testing_controls_impl.h
@@ -0,0 +1,30 @@ +// 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 SERVICES_VIDEO_CAPTURE_TESTING_CONTROLS_IMPL_H_ +#define SERVICES_VIDEO_CAPTURE_TESTING_CONTROLS_IMPL_H_ + +#include "services/service_manager/public/cpp/service_context_ref.h" +#include "services/video_capture/public/interfaces/testing_controls.mojom.h" + +namespace video_capture { + +class TestingControlsImpl : public mojom::TestingControls { + public: + TestingControlsImpl( + std::unique_ptr<service_manager::ServiceContextRef> service_ref); + ~TestingControlsImpl() override; + + // mojom::TestingControls implementation. + void Crash() override; + + private: + const std::unique_ptr<service_manager::ServiceContextRef> service_ref_; + + DISALLOW_COPY_AND_ASSIGN(TestingControlsImpl); +}; + +} // namespace video_capture + +#endif // SERVICES_VIDEO_CAPTURE_TESTING_CONTROLS_IMPL_H_
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 6f3f0b43..bd223c9 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -3539,23 +3539,11 @@ "Linux Builder": { "additional_compile_targets": [ "all" - ], - "scripts": [ - { - "name": "check_gn_headers", - "script": "check_gn_headers.py" - } ] }, "Linux Builder (dbg)": { "additional_compile_targets": [ "all" - ], - "scripts": [ - { - "name": "check_gn_headers", - "script": "check_gn_headers.py" - } ] }, "Linux Tests": { @@ -3967,6 +3955,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "mojo_js_integration_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_js_unittests" }, { @@ -4642,6 +4636,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "mojo_js_integration_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_js_unittests" }, {
diff --git a/testing/buildbot/client.v8.chromium.json b/testing/buildbot/client.v8.chromium.json index 09e30211..bb493a0 100644 --- a/testing/buildbot/client.v8.chromium.json +++ b/testing/buildbot/client.v8.chromium.json
@@ -236,6 +236,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "mojo_js_integration_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "mojo_js_unittests" }, {
diff --git a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter index d1275115..60b106c 100644 --- a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
@@ -143,6 +143,7 @@ -WebContentsViewAuraTest.ScreenshotForSwappedOutRenderViews -WebRtcGetUserMediaOldConstraintsBrowserTest.TwoGetUserMediaWithFirstHdSecondVga -WebRtcGetUserMediaOldConstraintsBrowserTest.TwoGetUserMediaWithSecondVideoCropped +-WebRtcVideoCaptureBrowserTest.RecoverFromCrashInVideoCaptureProcess -WebUIMojoTest.EndToEndPing -WheelScrollLatchingBrowserTest.WheelEventTarget -WorkerFetchTest.*
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 34e2f4c6..f305fcf 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -712,6 +712,10 @@ "label": "//mojo/common:mojo_common_unittests", "type": "console_test_launcher", }, + "mojo_js_integration_tests": { + "label": "//mojo/edk/js/tests:mojo_js_integration_tests", + "type": "console_test_launcher", + }, "mojo_js_unittests": { "label": "//mojo/edk/js/tests:mojo_js_unittests", "type": "console_test_launcher", @@ -918,10 +922,12 @@ "script": "//third_party/catapult/devil/devil/android/tools/system_app.py", "args": [ "remove", - "--package com.android.webview com.google.android.webview", + "--package", + "com.android.webview", + "com.google.android.webview", "-v", "--", - "//testing/scripts/run_telemetry_benchmark_as_googletest.py", + "../../testing/scripts/run_telemetry_benchmark_as_googletest.py", "../../tools/perf/run_benchmark", ], },
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index d5372222..b48b43c6 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -18269,10 +18269,8 @@ crbug.com/591099 media/network-no-source-const-shadow.html [ Failure ] crbug.com/591099 media/no-autoplay-with-user-gesture-requirement.html [ Crash ] crbug.com/591099 media/remoteplayback/availability-callback-gc.html [ Crash ] -crbug.com/591099 media/remoteplayback/prompt-throws-when-backend-disabled.html [ Crash Timeout ] crbug.com/591099 media/remoteplayback/prompt-twice-throws.html [ Crash ] crbug.com/591099 media/remoteplayback/watch-availability-throws-low-end-device.html [ Crash ] -crbug.com/591099 media/remoteplayback/watch-availability-works-when-backend-disabled.html [ Crash ] crbug.com/591099 media/remove-from-document-before-load.html [ Crash ] crbug.com/591099 media/remove-from-document-config-controls-no-crash.html [ Crash Failure ] crbug.com/591099 media/remove-from-document.html [ Crash ] @@ -23057,10 +23055,8 @@ crbug.com/591099 virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-light-rendering.html [ Failure ] crbug.com/591099 virtual/new-remote-playback-pipeline/media/controls/video-overlay-play-button.html [ Crash ] crbug.com/591099 virtual/new-remote-playback-pipeline/media/remoteplayback/availability-callback-gc.html [ Crash ] -crbug.com/591099 virtual/new-remote-playback-pipeline/media/remoteplayback/prompt-throws-when-backend-disabled.html [ Crash ] crbug.com/591099 virtual/new-remote-playback-pipeline/media/remoteplayback/prompt-twice-throws.html [ Crash ] crbug.com/591099 virtual/new-remote-playback-pipeline/media/remoteplayback/watch-availability-throws-low-end-device.html [ Crash ] -crbug.com/591099 virtual/new-remote-playback-pipeline/media/remoteplayback/watch-availability-works-when-backend-disabled.html [ Crash ] crbug.com/591099 virtual/off-main-thread-fetch/external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/extendable-message-event.https.html [ Crash Timeout ] crbug.com/591099 virtual/off-main-thread-fetch/external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/registration-attribute.https.html [ Failure Pass ] crbug.com/591099 virtual/off-main-thread-fetch/external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/unregister.https.html [ Crash ]
diff --git a/third_party/WebKit/LayoutTests/SmokeTests b/third_party/WebKit/LayoutTests/SmokeTests index 05f133bc..2ddbae26 100644 --- a/third_party/WebKit/LayoutTests/SmokeTests +++ b/third_party/WebKit/LayoutTests/SmokeTests
@@ -974,6 +974,7 @@ transforms/3d/hit-testing/composited-hit-test.html transforms/3d/hit-testing/rotated-hit-test-with-child.html transforms/container-transform-crash.html +transforms/cssmatrix-crash.html transforms/focus-on-transformed-node.html transforms/no_transform_hit_testing.html transforms/topmost-becomes-bottomost-for-scrolling.html
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.html index 1aef3568..738e0f0 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.html +++ b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.html
@@ -8,7 +8,7 @@ 'use strict'; promise_test(() => { return getHealthThermometerDevice({acceptAllDevices: true}) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.getPrimaryServices(), new DOMException( 'Origin is not allowed to access any service. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/blocklisted-service-in-optionalServices.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/blocklisted-service-in-optionalServices.html index 2b9fef68..1a69b79 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/blocklisted-service-in-optionalServices.html +++ b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/blocklisted-service-in-optionalServices.html
@@ -16,7 +16,7 @@ filters: [{services: ['health_thermometer']}], optionalServices: ['human_interface_device'] }) - .then(({device, fake_peripheral}) => { + .then(([device, fake_peripheral]) => { return fake_peripheral .setNextGATTConnectionResponse({code: HCI_SUCCESS}) .then(() => device.gatt.connect())
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-before.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-before.js index 1c93f99..3945d6f 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-before.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-before.js
@@ -3,7 +3,7 @@ return getHealthThermometerDevice({ filters: [{services: ['health_thermometer']}], optionalServices: ['generic_access']}) - .then(({device}) => { + .then(([device]) => { device.gatt.disconnect(); return assert_promise_rejects_with_message( device.gatt.CALLS([
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-error.js index 4dafb7b0..f79f856 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-error.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-error.js
@@ -1,7 +1,7 @@ 'use strict'; promise_test(() => { return getEmptyHealthThermometerDevice() - .then(({device}) => { + .then(([device]) => { let promise = assert_promise_rejects_with_message( device.gatt.CALLS([ getPrimaryService('health_thermometer')|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-success.js index 722a04b..73d266a 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-success.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-success.js
@@ -1,20 +1,22 @@ 'use strict'; promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => { + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => device.gatt.connect()) + .then(gatt => { let promise = assert_promise_rejects_with_message( - device.gatt.CALLS([ - getPrimaryService('health_thermometer')| + gatt.CALLS([ + getPrimaryService('heart_rate')| getPrimaryServices()| - getPrimaryServices('health_thermometer')[UUID] + getPrimaryServices('heart_rate')[UUID] ]), new DOMException('GATT Server is disconnected. ' + 'Cannot retrieve services. ' + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); - device.gatt.disconnect(); + gatt.disconnect(); return promise; }); }, 'disconnect() called during a FUNCTION_NAME call that succeeds. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-invalidates-objects.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-invalidates-objects.js index 3367d92..db410ed 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-invalidates-objects.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-invalidates-objects.js
@@ -1,18 +1,21 @@ 'use strict'; promise_test(() => { let promise; - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => { - return device.gatt.CALLS([ - getPrimaryService('health_thermometer')| - getPrimaryServices()| - getPrimaryServices('health_thermometer')[UUID]]) + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer + .CALLS([ + getPrimaryService('heart_rate')| + getPrimaryServices()| + getPrimaryServices('heart_rate')[UUID]]) // Convert to array if necessary. .then(s => { let services = [].concat(s); - device.gatt.disconnect(); - return device.gatt.connect() + gattServer.disconnect(); + return gattServer.connect() .then(() => services); }); }) @@ -26,7 +29,7 @@ 'InvalidStateError'); promises = promises.then(() => assert_promise_rejects_with_message( - service.getCharacteristic('measurement_interval'), + service.getCharacteristic('body_sensor_location'), error)); promises = promises.then(() => assert_promise_rejects_with_message( @@ -34,7 +37,7 @@ error)); promises = promises.then(() => assert_promise_rejects_with_message( - service.getCharacteristics('measurement_interval'), + service.getCharacteristics('body_sensor_location'), error)); } return promises;
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnected-device.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnected-device.js index e1d66cb..2ae7af2 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnected-device.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnected-device.js
@@ -4,7 +4,7 @@ filters: [{services: ['health_thermometer']}], optionalServices: ['generic_access'] }) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.CALLS([ getPrimaryService('health_thermometer')| getPrimaryServices()|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-no-permission-absent-service.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-no-permission-absent-service.js index cba08269..27f8bba 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-no-permission-absent-service.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-no-permission-absent-service.js
@@ -7,7 +7,7 @@ 'SecurityError'); return getHealthThermometerDeviceWithServicesDiscovered({ filters: [{services: ['health_thermometer']}]}) - .then(({device}) => Promise.all([ + .then(([device]) => Promise.all([ assert_promise_rejects_with_message( device.gatt.CALLS([ getPrimaryService(glucose.alias)|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-service-not-found.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-service-not-found.js index 39f8376..879b6cd 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-service-not-found.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-service-not-found.js
@@ -3,7 +3,7 @@ return getHealthThermometerDeviceWithServicesDiscovered({ filters: [{services: ['health_thermometer']}], optionalServices: ['glucose']}) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.CALLS([ getPrimaryService('glucose')| getPrimaryServices('glucose')[UUID]
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-error.js index 7ae3837..360ee82 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-error.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-error.js
@@ -2,7 +2,7 @@ promise_test(() => { let promise; return getEmptyHealthThermometerDevice() - .then(({device}) => { + .then(([device]) => { promise = assert_promise_rejects_with_message( device.gatt.CALLS([ getPrimaryService('health_thermometer')|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-success.js index f03a204..f2bab5df 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-success.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-success.js
@@ -1,21 +1,25 @@ 'use strict'; promise_test(() => { let promise; - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => { - promise = assert_promise_rejects_with_message( - device.gatt.CALLS([ - getPrimaryService('health_thermometer') | - getPrimaryServices() | - getPrimaryServices('health_thermometer')[UUID]]), - new DOMException( - 'GATT Server is disconnected. Cannot retrieve services. ' + - '(Re)connect first with `device.gatt.connect`.', - 'NetworkError')); - device.gatt.disconnect(); - }) - .then(runGarbageCollection) - .then(() => promise); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + promise = assert_promise_rejects_with_message( + gattServer.CALLS( + [getPrimaryService('health_thermometer') | + getPrimaryServices() | + getPrimaryServices('health_thermometer')[UUID]]), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError')); + gattServer.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); }, 'Garbage Collection ran during a FUNCTION_NAME call that succeeds. ' + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-different-service-after-reconnection.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-different-service-after-reconnection.js index e18bc2aa..26ca8da 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-different-service-after-reconnection.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-different-service-after-reconnection.js
@@ -1,38 +1,37 @@ 'use strict'; promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => { - let services_first_connection; - return device.gatt.CALLS([ - getPrimaryService('health_thermometer')| + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => device.gatt.connect()) + .then(gattServer => { + let services1; + return gattServer + .CALLS([ + getPrimaryService('heart_rate')| getPrimaryServices()| - getPrimaryServices('health_thermometer')[UUID]]) - .then(services => services_first_connection = services) - .then(() => device.gatt.disconnect()) - .then(() => device.gatt.connect()) - .then(() => device.gatt.PREVIOUS_CALL) - .then(services_second_connection => [ - services_first_connection, - services_second_connection - ]); + getPrimaryServices('heart_rate')[UUID]]) + .then(services => services1 = services) + .then(() => gattServer.disconnect()) + .then(() => gattServer.connect()) + .then(() => gattServer.PREVIOUS_CALL) + .then(services2 => [services1, services2]) }) - .then(([services_first_connection, services_second_connection]) => { + .then(services_arrays => { // Convert to arrays if necessary. - services_first_connection = [].concat(services_first_connection); - services_second_connection = [].concat(services_second_connection); + for (let i = 0; i < services_arrays.length; i++) { + services_arrays[i] = [].concat(services_arrays[i]); + } - assert_equals(services_first_connection.length, services_second_connection.length); + for (let i = 1; i < services_arrays.length; i++) { + assert_equals(services_arrays[0].length, services_arrays[i].length); + } - let first_connection_set = new Set(services_first_connection); - let second_connection_set = new Set(services_second_connection); - - // The two sets should be disjoint. - let common_services = services_first_connection.filter( - val => second_connection_set.has(val)); - assert_equals(common_services.length, 0); - + let base_set = new Set(services_arrays.shift()); + for (let services of services_arrays) { + services.forEach(service => assert_false(base_set.has(service))); + } }); }, 'Calls to FUNCTION_NAME after a disconnection should return a ' + 'different object.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-same-object.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-same-object.js index 10d440f..529bffb87 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-same-object.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-same-object.js
@@ -1,32 +1,29 @@ 'use strict'; promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => Promise.all([ - device.gatt.CALLS([ - getPrimaryService('health_thermometer')| + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => device.gatt.connect()) + .then(gattServer => Promise.all([ + gattServer.CALLS([ + getPrimaryService('heart_rate')| getPrimaryServices()| - getPrimaryServices('health_thermometer')[UUID]]), - device.gatt.PREVIOUS_CALL])) - .then(([services_first_call, services_second_call]) => { + getPrimaryServices('heart_rate')[UUID]]), + gattServer.PREVIOUS_CALL])) + .then(services_arrays => { // Convert to arrays if necessary. - services_first_call = [].concat(services_first_call); - services_second_call = [].concat(services_second_call); + for (let i = 0; i < services_arrays.length; i++) { + services_arrays[i] = [].concat(services_arrays[i]); + } - assert_equals(services_first_call.length, services_second_call.length); + for (let i = 1; i < services_arrays.length; i++) { + assert_equals(services_arrays[0].length, services_arrays[i].length); + } - let first_call_set = new Set(services_first_call); - assert_equals(services_first_call.length, first_call_set.size); - let second_call_set = new Set(services_second_call); - assert_equals(services_second_call.length, second_call_set.size); - - services_first_call.forEach(service => { - assert_true(second_call_set.has(service)) - }); - - services_second_call.forEach(service => { - assert_true(first_call_set.has(service)); - }); + let base_set = new Set(services_arrays[0]); + for (let services of services_arrays) { + services.forEach(service => assert_true(base_set.has(service))); + } }); }, 'Calls to FUNCTION_NAME should return the same object.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/invalid-service-name.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/invalid-service-name.js index 5205b5c..32544f0 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/invalid-service-name.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/invalid-service-name.js
@@ -1,7 +1,7 @@ 'use strict'; promise_test(() => { return getHealthThermometerDevice() - .then(({device}) => { + .then(([device]) => { return assert_promise_rejects_with_message( device.gatt.CALLS([ getPrimaryService('wrong_name')|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-absent-service.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-absent-service.js index 061ff09..5be6047 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-absent-service.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-absent-service.js
@@ -7,7 +7,7 @@ 'SecurityError'); return getHealthThermometerDevice({ filters: [{services: ['health_thermometer']}]}) - .then(({device}) => Promise.all([ + .then(([device]) => Promise.all([ assert_promise_rejects_with_message( device.gatt.CALLS([ getPrimaryService(glucose.alias)|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-for-any-service.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-for-any-service.js index 41286232..e2e95c2e 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-for-any-service.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-for-any-service.js
@@ -1,7 +1,7 @@ 'use strict'; promise_test(() => { return getHealthThermometerDevice({acceptAllDevices: true}) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.CALLS([ getPrimaryService('heart_rate')| getPrimaryServices()|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-present-service.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-present-service.js index eb9dc48c..37bccfc3 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-present-service.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-present-service.js
@@ -5,16 +5,18 @@ '\'optionalServices\' in requestDevice() ' + 'options. https://goo.gl/HxfxSQ', 'SecurityError'); - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => Promise.all([ + return setBluetoothFakeAdapter('HeartRateAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gatt => Promise.all([ assert_promise_rejects_with_message( - device.gatt.CALLS([ + gatt.CALLS([ getPrimaryService(generic_access.alias)| getPrimaryServices(generic_access.alias)[UUID] ]), expected), assert_promise_rejects_with_message( - device.gatt.FUNCTION_NAME(generic_access.name), expected), + gatt.FUNCTION_NAME(generic_access.name), expected), assert_promise_rejects_with_message( - device.gatt.FUNCTION_NAME(generic_access.uuid), expected)])); + gatt.FUNCTION_NAME(generic_access.uuid), expected)])); }, 'Request for present service without permission. Reject with SecurityError.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/service-not-found.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/service-not-found.js index 888aee2..09c7d916 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/service-not-found.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/service-not-found.js
@@ -3,7 +3,7 @@ return getHealthThermometerDevice({ filters: [{services: ['health_thermometer']}], optionalServices: ['glucose']}) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.CALLS([ getPrimaryService('glucose')| getPrimaryServices('glucose')[UUID]
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/connect/connection-succeeds.html b/third_party/WebKit/LayoutTests/bluetooth/server/connect/connection-succeeds.html index 78067cb6..a5fb002 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/connect/connection-succeeds.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/connect/connection-succeeds.html
@@ -8,7 +8,7 @@ 'use strict'; promise_test(() => { return getDiscoveredHealthThermometerDevice() - .then(({device, fake_peripheral}) => { + .then(([device, fake_peripheral]) => { return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}) .then(() => device.gatt.connect()) .then(gatt => assert_true(gatt.connected));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-success.html index 7b735914..60156c1 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-success.html
@@ -8,7 +8,7 @@ 'use strict'; promise_test(() => { return getDiscoveredHealthThermometerDevice() - .then(({device, fake_peripheral}) => { + .then(([device, fake_peripheral]) => { return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}) .then(() => { // Don't return the promise and let |device| go out of scope
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/connect/get-same-gatt-server.html b/third_party/WebKit/LayoutTests/bluetooth/server/connect/get-same-gatt-server.html index 62f9d0b..d6d1a42 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/connect/get-same-gatt-server.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/connect/get-same-gatt-server.html
@@ -8,7 +8,7 @@ 'use strict'; promise_test(() => { return getDiscoveredHealthThermometerDevice() - .then(({device, fake_peripheral}) => { + .then(([device, fake_peripheral]) => { return fake_peripheral .setNextGATTConnectionResponse({code: HCI_SUCCESS}) .then(() => device.gatt.connect())
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/device-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/server/device-same-object.html index f1aa39cc..c6f391c 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/device-same-object.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/device-same-object.html
@@ -8,7 +8,7 @@ 'use strict'; promise_test(() => { return getDiscoveredHealthThermometerDevice() - .then(({device, fake_peripheral}) => { + .then(([device, fake_peripheral]) => { return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}) .then(() => device.gatt.connect()); })
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-before.html index 86e704f..36e2de71 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-before.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-before.html
@@ -11,7 +11,7 @@ return getHealthThermometerDevice({ filters: [{services: ['health_thermometer']}], optionalServices: ['generic_access']}) - .then(({device}) => { + .then(([device]) => { device.gatt.disconnect(); return assert_promise_rejects_with_message( device.gatt.getPrimaryService('health_thermometer'),
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-error.html index b4fbe18..4eb61ea1 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-error.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-error.html
@@ -9,7 +9,7 @@ 'use strict'; promise_test(() => { return getEmptyHealthThermometerDevice() - .then(({device}) => { + .then(([device]) => { let promise = assert_promise_rejects_with_message( device.gatt.getPrimaryService('health_thermometer'), new DOMException('GATT Server is disconnected. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-success.html index 9adb4ca6..802a7d6 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-success.html
@@ -8,17 +8,19 @@ <script> 'use strict'; promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => { + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => device.gatt.connect()) + .then(gatt => { let promise = assert_promise_rejects_with_message( - device.gatt.getPrimaryService('health_thermometer'), + gatt.getPrimaryService('heart_rate'), new DOMException('GATT Server is disconnected. ' + 'Cannot retrieve services. ' + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); - device.gatt.disconnect(); + gatt.disconnect(); return promise; }); }, 'disconnect() called during a getPrimaryService call that succeeds. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.html index eb20948..0acff90 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.html
@@ -9,15 +9,18 @@ 'use strict'; promise_test(() => { let promise; - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => { - return device.gatt.getPrimaryService('health_thermometer') + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer + .getPrimaryService('heart_rate') // Convert to array if necessary. .then(s => { let services = [].concat(s); - device.gatt.disconnect(); - return device.gatt.connect() + gattServer.disconnect(); + return gattServer.connect() .then(() => services); }); }) @@ -31,7 +34,7 @@ 'InvalidStateError'); promises = promises.then(() => assert_promise_rejects_with_message( - service.getCharacteristic('measurement_interval'), + service.getCharacteristic('body_sensor_location'), error)); promises = promises.then(() => assert_promise_rejects_with_message( @@ -39,7 +42,7 @@ error)); promises = promises.then(() => assert_promise_rejects_with_message( - service.getCharacteristics('measurement_interval'), + service.getCharacteristics('body_sensor_location'), error)); } return promises;
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnected-device.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnected-device.html index 938b159b..a7061fa 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnected-device.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnected-device.html
@@ -12,7 +12,7 @@ filters: [{services: ['health_thermometer']}], optionalServices: ['generic_access'] }) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.getPrimaryService('health_thermometer'), new DOMException('GATT Server is disconnected. ' + 'Cannot retrieve services. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.html index 1659be5..cb05a7a 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.html
@@ -15,7 +15,7 @@ 'SecurityError'); return getHealthThermometerDeviceWithServicesDiscovered({ filters: [{services: ['health_thermometer']}]}) - .then(({device}) => Promise.all([ + .then(([device]) => Promise.all([ assert_promise_rejects_with_message( device.gatt.getPrimaryService(glucose.alias), expected), assert_promise_rejects_with_message(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.html index 962c713..f6978485 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.html
@@ -11,7 +11,7 @@ return getHealthThermometerDeviceWithServicesDiscovered({ filters: [{services: ['health_thermometer']}], optionalServices: ['glucose']}) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.getPrimaryService('glucose'), new DOMException( 'No Services matching UUID ' + glucose.uuid + ' found in Device.',
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html index ae48249..a0c3a56 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html
@@ -10,7 +10,7 @@ promise_test(() => { let promise; return getEmptyHealthThermometerDevice() - .then(({device}) => { + .then(([device]) => { promise = assert_promise_rejects_with_message( device.gatt.getPrimaryService('health_thermometer'), new DOMException(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html index d275cea..f03e923 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html
@@ -9,19 +9,23 @@ 'use strict'; promise_test(() => { let promise; - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => { - promise = assert_promise_rejects_with_message( - device.gatt.getPrimaryService('health_thermometer'), - new DOMException( - 'GATT Server is disconnected. Cannot retrieve services. ' + - '(Re)connect first with `device.gatt.connect`.', - 'NetworkError')); - device.gatt.disconnect(); - }) - .then(runGarbageCollection) - .then(() => promise); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + promise = assert_promise_rejects_with_message( + gattServer.getPrimaryService('health_thermometer'), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError')); + gattServer.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); }, 'Garbage Collection ran during a getPrimaryService call that succeeds. ' + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.html index 69411a5b..37c33542 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.html
@@ -8,36 +8,35 @@ <script> 'use strict'; promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => { - let services_first_connection; - return device.gatt.getPrimaryService('health_thermometer') - .then(services => services_first_connection = services) - .then(() => device.gatt.disconnect()) - .then(() => device.gatt.connect()) - .then(() => device.gatt.getPrimaryService('health_thermometer')) - .then(services_second_connection => [ - services_first_connection, - services_second_connection - ]); + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => device.gatt.connect()) + .then(gattServer => { + let services1; + return gattServer + .getPrimaryService('heart_rate') + .then(services => services1 = services) + .then(() => gattServer.disconnect()) + .then(() => gattServer.connect()) + .then(() => gattServer.getPrimaryService('heart_rate')) + .then(services2 => [services1, services2]) }) - .then(([services_first_connection, services_second_connection]) => { + .then(services_arrays => { // Convert to arrays if necessary. - services_first_connection = [].concat(services_first_connection); - services_second_connection = [].concat(services_second_connection); + for (let i = 0; i < services_arrays.length; i++) { + services_arrays[i] = [].concat(services_arrays[i]); + } - assert_equals(services_first_connection.length, services_second_connection.length); + for (let i = 1; i < services_arrays.length; i++) { + assert_equals(services_arrays[0].length, services_arrays[i].length); + } - let first_connection_set = new Set(services_first_connection); - let second_connection_set = new Set(services_second_connection); - - // The two sets should be disjoint. - let common_services = services_first_connection.filter( - val => second_connection_set.has(val)); - assert_equals(common_services.length, 0); - + let base_set = new Set(services_arrays.shift()); + for (let services of services_arrays) { + services.forEach(service => assert_false(base_set.has(service))); + } }); }, 'Calls to getPrimaryService after a disconnection should return a ' + 'different object.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-same-object.html index 3783693f2..f046b52 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-same-object.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-same-object.html
@@ -8,31 +8,28 @@ <script> 'use strict'; promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => Promise.all([ - device.gatt.getPrimaryService('health_thermometer'), - device.gatt.getPrimaryService('health_thermometer')])) - .then(([services_first_call, services_second_call]) => { + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => device.gatt.connect()) + .then(gattServer => Promise.all([ + gattServer.getPrimaryService('heart_rate'), + gattServer.getPrimaryService('heart_rate')])) + .then(services_arrays => { // Convert to arrays if necessary. - services_first_call = [].concat(services_first_call); - services_second_call = [].concat(services_second_call); + for (let i = 0; i < services_arrays.length; i++) { + services_arrays[i] = [].concat(services_arrays[i]); + } - assert_equals(services_first_call.length, services_second_call.length); + for (let i = 1; i < services_arrays.length; i++) { + assert_equals(services_arrays[0].length, services_arrays[i].length); + } - let first_call_set = new Set(services_first_call); - assert_equals(services_first_call.length, first_call_set.size); - let second_call_set = new Set(services_second_call); - assert_equals(services_second_call.length, second_call_set.size); - - services_first_call.forEach(service => { - assert_true(second_call_set.has(service)) - }); - - services_second_call.forEach(service => { - assert_true(first_call_set.has(service)); - }); + let base_set = new Set(services_arrays[0]); + for (let services of services_arrays) { + services.forEach(service => assert_true(base_set.has(service))); + } }); }, 'Calls to getPrimaryService should return the same object.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-invalid-service-name.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-invalid-service-name.html index 722be1a..591757d1 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-invalid-service-name.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-invalid-service-name.html
@@ -9,7 +9,7 @@ 'use strict'; promise_test(() => { return getHealthThermometerDevice() - .then(({device}) => { + .then(([device]) => { return assert_promise_rejects_with_message( device.gatt.getPrimaryService('wrong_name'), new DOMException(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-absent-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-absent-service.html index 88362fe..04fa5a1 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-absent-service.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-absent-service.html
@@ -15,7 +15,7 @@ 'SecurityError'); return getHealthThermometerDevice({ filters: [{services: ['health_thermometer']}]}) - .then(({device}) => Promise.all([ + .then(([device]) => Promise.all([ assert_promise_rejects_with_message( device.gatt.getPrimaryService(glucose.alias), expected), assert_promise_rejects_with_message(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html index 7301f20..d02d25d 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html
@@ -9,7 +9,7 @@ 'use strict'; promise_test(() => { return getHealthThermometerDevice({acceptAllDevices: true}) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.getPrimaryService('heart_rate'), new DOMException('Origin is not allowed to access any service. Tip: ' + 'Add the service UUID to \'optionalServices\' in ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-present-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-present-service.html index d5e841c..94fad05 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-present-service.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-present-service.html
@@ -13,15 +13,17 @@ '\'optionalServices\' in requestDevice() ' + 'options. https://goo.gl/HxfxSQ', 'SecurityError'); - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => Promise.all([ + return setBluetoothFakeAdapter('HeartRateAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gatt => Promise.all([ assert_promise_rejects_with_message( - device.gatt.getPrimaryService(generic_access.alias), expected), + gatt.getPrimaryService(generic_access.alias), expected), assert_promise_rejects_with_message( - device.gatt.getPrimaryService(generic_access.name), expected), + gatt.getPrimaryService(generic_access.name), expected), assert_promise_rejects_with_message( - device.gatt.getPrimaryService(generic_access.uuid), expected)])); + gatt.getPrimaryService(generic_access.uuid), expected)])); }, 'Request for present service without permission. Reject with SecurityError.'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-service-not-found.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-service-not-found.html index d7290ba..ed44846d 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-service-not-found.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-service-not-found.html
@@ -11,7 +11,7 @@ return getHealthThermometerDevice({ filters: [{services: ['health_thermometer']}], optionalServices: ['glucose']}) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.getPrimaryService('glucose'), new DOMException( 'No Services matching UUID ' + glucose.uuid + ' found in Device.',
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/service-found.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/service-found.html index a544178..e23fc14 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/service-found.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/service-found.html
@@ -2,19 +2,19 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> -<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script> -<script src="../../../resources/mojo-helpers.js"></script> <script> 'use strict'; -promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => { - return Promise.all([ - device.gatt.getPrimaryService(generic_access.alias), - device.gatt.getPrimaryService(generic_access.name), - device.gatt.getPrimaryService(generic_access.uuid)]) +promise_test(function() { + return setBluetoothFakeAdapter('HeartRateAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => { + return device.gatt.connect() + .then(gattServer => Promise.all([ + gattServer.getPrimaryService(generic_access.alias), + gattServer.getPrimaryService(generic_access.name), + gattServer.getPrimaryService(generic_access.uuid)])) .then(services => { services.forEach(service => { assert_equals(service.uuid, generic_access.uuid,
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/two-iframes-from-same-origin.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/two-iframes-from-same-origin.html index 6989bf26..898cd7c 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/two-iframes-from-same-origin.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/two-iframes-from-same-origin.html
@@ -2,62 +2,49 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> -<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script> -<script src="../../../resources/mojo-helpers.js"></script> <script> -"use strict"; -var firstIframe = true; -var iframe1 = document.createElement('iframe'); -iframe1.src ='../../../resources/bluetooth/health-thermometer-two-iframes.html'; -iframe1.id = 'iframe1'; -var iframe2 = document.createElement('iframe'); -iframe2.src = '../../../resources/bluetooth/health-thermometer-two-iframes.html'; -iframe2.id = 'iframe2'; -async_test(test => { - window.onmessage = messageEvent => test.step(() => { - if (messageEvent.data === 'Ready') { - if (firstIframe) { + "use strict"; + var firstIframe = true; + var iframe1 = document.createElement('iframe'); + iframe1.src = '../../../resources/bluetooth/heart-rate-two-iframes.html'; + iframe1.id = 'iframe1'; + var iframe2 = document.createElement('iframe'); + iframe2.src = '../../../resources/bluetooth/heart-rate-two-iframes.html'; + iframe2.id = 'iframe2'; + async_test(test => { + window.onmessage = messageEvent => test.step(() => { + if (messageEvent.data === 'Ready') { + if (firstIframe) { + callWithKeyDown(() => { + iframe1.contentWindow.postMessage('Iframe1RequestAndConnect', '*'); + }); + } else { + callWithKeyDown(() => { + iframe2.contentWindow.postMessage('Iframe2RequestAndConnect', '*'); + }); + } + firstIframe = false; + } else if (messageEvent.data === 'Iframe1Connected') { callWithKeyDown(() => { - iframe1.contentWindow.postMessage('Iframe1RequestAndConnect', '*'); + iframe1.contentWindow.postMessage('Iframe1TryAccessGenericAccessService', '*'); }); - } else { + } else if (messageEvent.data === 'Iframe1AccessGenericAccessServiceFailed') { + document.body.appendChild(iframe2); + } else if (messageEvent.data === 'Iframe2Connected') { callWithKeyDown(() => { - iframe2.contentWindow.postMessage('Iframe2RequestAndConnect', '*'); + iframe1.contentWindow.postMessage('TestIframe1HasGenericAccessService', '*'); }); } - firstIframe = false; - } else if (messageEvent.data === 'Iframe1Connected') { - callWithKeyDown(() => { - iframe1.contentWindow.postMessage('Iframe1TryAccessGenericAccessService', '*'); - }); - } else if (messageEvent.data === 'Iframe1AccessGenericAccessServiceFailed') { - document.body.appendChild(iframe2); - } else if (messageEvent.data === 'Iframe2Connected') { - callWithKeyDown(() => { - iframe1.contentWindow.postMessage('TestIframe1HasGenericAccessService', '*'); - }); - } - else if (messageEvent.data === 'DoneTest') { - test.done(); - } else { - assert_unreached('iframe sent invalid data: ' + messageEvent.data); - } - }); - - return setUpPreconnectedDevice({ - address: '09:09:09:09:09:09', - name: 'Health Thermometer', - knownServiceUUIDs: ['generic_access', 'health_thermometer'], - }) - .then(fake_peripheral => { - return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}) - .then(() => fake_peripheral.addFakeService({uuid: 'generic_access'})) - .then(() => fake_peripheral.addFakeService({uuid: 'health_thermometer'})) - .then(() => fake_peripheral.setNextGATTDiscoveryResponse({ - code: HCI_SUCCESS})) - }) - .then(() => { - document.body.appendChild(iframe1); + else if (messageEvent.data === 'DoneTest') { + test.done(); + } else { + assert_unreached('iframe sent invalid data: ' + messageEvent.data); + } }); -}, 'Two iframes in the same origin should be able to access each other\'s services'); + + setBluetoothFakeAdapter('HeartRateAdapter') + .then(() => { + document.body.appendChild(iframe1); + }); + }, 'Two iframes in the same origin should be able to access each other\'s services'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services-with-uuid.html index 39d834d..65c8b2f 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services-with-uuid.html
@@ -2,16 +2,17 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> -<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script> -<script src="../../../resources/mojo-helpers.js"></script> <script> 'use strict'; promise_test(() => { - return getHIDDevice({ - filters: [{services: ['battery_service']}], - optionalServices: ['human_interface_device']}) - .then(({device}) => assert_promise_rejects_with_message( - device.gatt.getPrimaryServices('human_interface_device'), + return setBluetoothFakeAdapter('BlocklistTestAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['device_information']}], + optionalServices: ['human_interface_device']})) + .then(device => device.gatt.connect()) + .then(gattServer => assert_promise_rejects_with_message( + gattServer.getPrimaryServices('human_interface_device'), + new DOMException('Origin is not allowed to access the service. ' + 'Tip: Add the service UUID to \'optionalServices\' ' + 'in requestDevice() options. https://goo.gl/HxfxSQ',
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services.html index f7d2592a..e894ab5 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services.html
@@ -2,27 +2,27 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> -<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script> -<script src="../../../resources/mojo-helpers.js"></script> <script> 'use strict'; promise_test(() => { - return getHIDDevice({ - filters: [{services: ['battery_service']}], + return setBluetoothFakeAdapter('BlocklistTestAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['device_information']}], optionalServices: [ - 'generic_access', - 'human_interface_device' - ]}) - .then(({device}) => device.gatt.getPrimaryServices()) + blocklist_test_service_uuid, 'device_information', 'generic_access', + 'heart_rate', 'human_interface_device']})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryServices()) .then(services => { - assert_equals(services.length, 2); - let uuid_set = new Set(services.map(s => s.uuid)); - - assert_equals(uuid_set.size, 2); - assert_true(uuid_set.has(BluetoothUUID.getService('generic_access'))); - assert_true(uuid_set.has(BluetoothUUID.getService('battery_service'))); - assert_false( - uuid_set.has(BluetoothUUID.getService('human_interface_device'))); + assert_equals(services.length, 4); + assert_equals(services[0].uuid, + BluetoothUUID.getService(blocklist_test_service_uuid)); + assert_equals(services[1].uuid, + BluetoothUUID.getService('device_information')); + assert_equals(services[2].uuid, + BluetoothUUID.getService('generic_access')); + assert_equals(services[3].uuid, + BluetoothUUID.getService('heart_rate')); }); }, 'Request for services. Does not return blocklisted service.'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before-with-uuid.html index f5354b89..fa7df561 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before-with-uuid.html
@@ -11,7 +11,7 @@ return getHealthThermometerDevice({ filters: [{services: ['health_thermometer']}], optionalServices: ['generic_access']}) - .then(({device}) => { + .then(([device]) => { device.gatt.disconnect(); return assert_promise_rejects_with_message( device.gatt.getPrimaryServices('health_thermometer'),
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before.html index 2c19bda2..2b6213db 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before.html
@@ -11,7 +11,7 @@ return getHealthThermometerDevice({ filters: [{services: ['health_thermometer']}], optionalServices: ['generic_access']}) - .then(({device}) => { + .then(([device]) => { device.gatt.disconnect(); return assert_promise_rejects_with_message( device.gatt.getPrimaryServices(),
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error-with-uuid.html index 01017a2..a29f4a6f 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error-with-uuid.html
@@ -9,7 +9,7 @@ 'use strict'; promise_test(() => { return getEmptyHealthThermometerDevice() - .then(({device}) => { + .then(([device]) => { let promise = assert_promise_rejects_with_message( device.gatt.getPrimaryServices('health_thermometer'), new DOMException('GATT Server is disconnected. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error.html index 1e11f89..aeecb4c 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error.html
@@ -9,7 +9,7 @@ 'use strict'; promise_test(() => { return getEmptyHealthThermometerDevice() - .then(({device}) => { + .then(([device]) => { let promise = assert_promise_rejects_with_message( device.gatt.getPrimaryServices(), new DOMException('GATT Server is disconnected. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success-with-uuid.html index a6c7211..e05bbe0 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success-with-uuid.html
@@ -8,17 +8,19 @@ <script> 'use strict'; promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => { + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => device.gatt.connect()) + .then(gatt => { let promise = assert_promise_rejects_with_message( - device.gatt.getPrimaryServices('health_thermometer'), + gatt.getPrimaryServices('heart_rate'), new DOMException('GATT Server is disconnected. ' + 'Cannot retrieve services. ' + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); - device.gatt.disconnect(); + gatt.disconnect(); return promise; }); }, 'disconnect() called during a getPrimaryServices call that succeeds. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success.html index 523c668..fd9a868 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success.html
@@ -8,17 +8,19 @@ <script> 'use strict'; promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => { + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => device.gatt.connect()) + .then(gatt => { let promise = assert_promise_rejects_with_message( - device.gatt.getPrimaryServices(), + gatt.getPrimaryServices(), new DOMException('GATT Server is disconnected. ' + 'Cannot retrieve services. ' + '(Re)connect first with `device.gatt.connect`.', 'NetworkError')); - device.gatt.disconnect(); + gatt.disconnect(); return promise; }); }, 'disconnect() called during a getPrimaryServices call that succeeds. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.html index 26b6589f..19ccb5a 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.html
@@ -9,15 +9,18 @@ 'use strict'; promise_test(() => { let promise; - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => { - return device.gatt.getPrimaryServices('health_thermometer') + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer + .getPrimaryServices('heart_rate') // Convert to array if necessary. .then(s => { let services = [].concat(s); - device.gatt.disconnect(); - return device.gatt.connect() + gattServer.disconnect(); + return gattServer.connect() .then(() => services); }); }) @@ -31,7 +34,7 @@ 'InvalidStateError'); promises = promises.then(() => assert_promise_rejects_with_message( - service.getCharacteristic('measurement_interval'), + service.getCharacteristic('body_sensor_location'), error)); promises = promises.then(() => assert_promise_rejects_with_message( @@ -39,7 +42,7 @@ error)); promises = promises.then(() => assert_promise_rejects_with_message( - service.getCharacteristics('measurement_interval'), + service.getCharacteristics('body_sensor_location'), error)); } return promises;
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.html index 62a1165..1506c3d 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.html
@@ -9,15 +9,18 @@ 'use strict'; promise_test(() => { let promise; - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => { - return device.gatt.getPrimaryServices() + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer + .getPrimaryServices() // Convert to array if necessary. .then(s => { let services = [].concat(s); - device.gatt.disconnect(); - return device.gatt.connect() + gattServer.disconnect(); + return gattServer.connect() .then(() => services); }); }) @@ -31,7 +34,7 @@ 'InvalidStateError'); promises = promises.then(() => assert_promise_rejects_with_message( - service.getCharacteristic('measurement_interval'), + service.getCharacteristic('body_sensor_location'), error)); promises = promises.then(() => assert_promise_rejects_with_message( @@ -39,7 +42,7 @@ error)); promises = promises.then(() => assert_promise_rejects_with_message( - service.getCharacteristics('measurement_interval'), + service.getCharacteristics('body_sensor_location'), error)); } return promises;
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device-with-uuid.html index 202df7ec..48474bb5 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device-with-uuid.html
@@ -12,7 +12,7 @@ filters: [{services: ['health_thermometer']}], optionalServices: ['generic_access'] }) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.getPrimaryServices('health_thermometer'), new DOMException('GATT Server is disconnected. ' + 'Cannot retrieve services. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device.html index e327868..9f7a190c 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device.html
@@ -12,7 +12,7 @@ filters: [{services: ['health_thermometer']}], optionalServices: ['generic_access'] }) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.getPrimaryServices(), new DOMException('GATT Server is disconnected. ' + 'Cannot retrieve services. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.html index 2d341428..85737f76 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.html
@@ -15,7 +15,7 @@ 'SecurityError'); return getHealthThermometerDeviceWithServicesDiscovered({ filters: [{services: ['health_thermometer']}]}) - .then(({device}) => Promise.all([ + .then(([device]) => Promise.all([ assert_promise_rejects_with_message( device.gatt.getPrimaryServices(glucose.alias), expected), assert_promise_rejects_with_message(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.html index 84e5bcef..0682b61a 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.html
@@ -11,7 +11,7 @@ return getHealthThermometerDeviceWithServicesDiscovered({ filters: [{services: ['health_thermometer']}], optionalServices: ['glucose']}) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.getPrimaryServices('glucose'), new DOMException( 'No Services matching UUID ' + glucose.uuid + ' found in Device.',
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html index ae626b2..d78d076 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html
@@ -10,7 +10,7 @@ promise_test(() => { let promise; return getEmptyHealthThermometerDevice() - .then(({device}) => { + .then(([device]) => { promise = assert_promise_rejects_with_message( device.gatt.getPrimaryServices('health_thermometer'), new DOMException(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html index 4d50a5c..1beb3147 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html
@@ -10,7 +10,7 @@ promise_test(() => { let promise; return getEmptyHealthThermometerDevice() - .then(({device}) => { + .then(([device]) => { promise = assert_promise_rejects_with_message( device.gatt.getPrimaryServices(), new DOMException(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html index 58f9f534..ff3978c 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html
@@ -9,19 +9,23 @@ 'use strict'; promise_test(() => { let promise; - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => { - promise = assert_promise_rejects_with_message( - device.gatt.getPrimaryServices('health_thermometer'), - new DOMException( - 'GATT Server is disconnected. Cannot retrieve services. ' + - '(Re)connect first with `device.gatt.connect`.', - 'NetworkError')); - device.gatt.disconnect(); - }) - .then(runGarbageCollection) - .then(() => promise); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + promise = assert_promise_rejects_with_message( + gattServer.getPrimaryServices('health_thermometer'), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError')); + gattServer.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); }, 'Garbage Collection ran during a getPrimaryServices call that succeeds. ' + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html index 05983aa..66813e4 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html
@@ -9,19 +9,23 @@ 'use strict'; promise_test(() => { let promise; - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => { - promise = assert_promise_rejects_with_message( - device.gatt.getPrimaryServices(), - new DOMException( - 'GATT Server is disconnected. Cannot retrieve services. ' + - '(Re)connect first with `device.gatt.connect`.', - 'NetworkError')); - device.gatt.disconnect(); - }) - .then(runGarbageCollection) - .then(() => promise); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + promise = assert_promise_rejects_with_message( + gattServer.getPrimaryServices(), + new DOMException( + 'GATT Server is disconnected. ' + + 'Cannot retrieve services. ' + + '(Re)connect first with `device.gatt.connect`.', + 'NetworkError')); + gattServer.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); }, 'Garbage Collection ran during a getPrimaryServices call that succeeds. ' + 'Should not crash.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.html index 6bb3339..e903a517 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.html
@@ -8,36 +8,35 @@ <script> 'use strict'; promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => { - let services_first_connection; - return device.gatt.getPrimaryServices('health_thermometer') - .then(services => services_first_connection = services) - .then(() => device.gatt.disconnect()) - .then(() => device.gatt.connect()) - .then(() => device.gatt.getPrimaryServices('health_thermometer')) - .then(services_second_connection => [ - services_first_connection, - services_second_connection - ]); + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => device.gatt.connect()) + .then(gattServer => { + let services1; + return gattServer + .getPrimaryServices('heart_rate') + .then(services => services1 = services) + .then(() => gattServer.disconnect()) + .then(() => gattServer.connect()) + .then(() => gattServer.getPrimaryServices('heart_rate')) + .then(services2 => [services1, services2]) }) - .then(([services_first_connection, services_second_connection]) => { + .then(services_arrays => { // Convert to arrays if necessary. - services_first_connection = [].concat(services_first_connection); - services_second_connection = [].concat(services_second_connection); + for (let i = 0; i < services_arrays.length; i++) { + services_arrays[i] = [].concat(services_arrays[i]); + } - assert_equals(services_first_connection.length, services_second_connection.length); + for (let i = 1; i < services_arrays.length; i++) { + assert_equals(services_arrays[0].length, services_arrays[i].length); + } - let first_connection_set = new Set(services_first_connection); - let second_connection_set = new Set(services_second_connection); - - // The two sets should be disjoint. - let common_services = services_first_connection.filter( - val => second_connection_set.has(val)); - assert_equals(common_services.length, 0); - + let base_set = new Set(services_arrays.shift()); + for (let services of services_arrays) { + services.forEach(service => assert_false(base_set.has(service))); + } }); }, 'Calls to getPrimaryServices after a disconnection should return a ' + 'different object.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.html index 230c7485..1afe652 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.html
@@ -8,36 +8,35 @@ <script> 'use strict'; promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => { - let services_first_connection; - return device.gatt.getPrimaryServices() - .then(services => services_first_connection = services) - .then(() => device.gatt.disconnect()) - .then(() => device.gatt.connect()) - .then(() => device.gatt.getPrimaryServices()) - .then(services_second_connection => [ - services_first_connection, - services_second_connection - ]); + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => device.gatt.connect()) + .then(gattServer => { + let services1; + return gattServer + .getPrimaryServices() + .then(services => services1 = services) + .then(() => gattServer.disconnect()) + .then(() => gattServer.connect()) + .then(() => gattServer.getPrimaryServices()) + .then(services2 => [services1, services2]) }) - .then(([services_first_connection, services_second_connection]) => { + .then(services_arrays => { // Convert to arrays if necessary. - services_first_connection = [].concat(services_first_connection); - services_second_connection = [].concat(services_second_connection); + for (let i = 0; i < services_arrays.length; i++) { + services_arrays[i] = [].concat(services_arrays[i]); + } - assert_equals(services_first_connection.length, services_second_connection.length); + for (let i = 1; i < services_arrays.length; i++) { + assert_equals(services_arrays[0].length, services_arrays[i].length); + } - let first_connection_set = new Set(services_first_connection); - let second_connection_set = new Set(services_second_connection); - - // The two sets should be disjoint. - let common_services = services_first_connection.filter( - val => second_connection_set.has(val)); - assert_equals(common_services.length, 0); - + let base_set = new Set(services_arrays.shift()); + for (let services of services_arrays) { + services.forEach(service => assert_false(base_set.has(service))); + } }); }, 'Calls to getPrimaryServices after a disconnection should return a ' + 'different object.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.html index 5f56fe0..e6231c3 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.html
@@ -8,31 +8,28 @@ <script> 'use strict'; promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => Promise.all([ - device.gatt.getPrimaryServices('health_thermometer'), - device.gatt.getPrimaryServices('health_thermometer')])) - .then(([services_first_call, services_second_call]) => { + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => device.gatt.connect()) + .then(gattServer => Promise.all([ + gattServer.getPrimaryServices('heart_rate'), + gattServer.getPrimaryServices('heart_rate')])) + .then(services_arrays => { // Convert to arrays if necessary. - services_first_call = [].concat(services_first_call); - services_second_call = [].concat(services_second_call); + for (let i = 0; i < services_arrays.length; i++) { + services_arrays[i] = [].concat(services_arrays[i]); + } - assert_equals(services_first_call.length, services_second_call.length); + for (let i = 1; i < services_arrays.length; i++) { + assert_equals(services_arrays[0].length, services_arrays[i].length); + } - let first_call_set = new Set(services_first_call); - assert_equals(services_first_call.length, first_call_set.size); - let second_call_set = new Set(services_second_call); - assert_equals(services_second_call.length, second_call_set.size); - - services_first_call.forEach(service => { - assert_true(second_call_set.has(service)) - }); - - services_second_call.forEach(service => { - assert_true(first_call_set.has(service)); - }); + let base_set = new Set(services_arrays[0]); + for (let services of services_arrays) { + services.forEach(service => assert_true(base_set.has(service))); + } }); }, 'Calls to getPrimaryServices should return the same object.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object.html index 1685f6f..00f859b 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object.html
@@ -8,31 +8,28 @@ <script> 'use strict'; promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => Promise.all([ - device.gatt.getPrimaryServices(), - device.gatt.getPrimaryServices()])) - .then(([services_first_call, services_second_call]) => { + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => device.gatt.connect()) + .then(gattServer => Promise.all([ + gattServer.getPrimaryServices(), + gattServer.getPrimaryServices()])) + .then(services_arrays => { // Convert to arrays if necessary. - services_first_call = [].concat(services_first_call); - services_second_call = [].concat(services_second_call); + for (let i = 0; i < services_arrays.length; i++) { + services_arrays[i] = [].concat(services_arrays[i]); + } - assert_equals(services_first_call.length, services_second_call.length); + for (let i = 1; i < services_arrays.length; i++) { + assert_equals(services_arrays[0].length, services_arrays[i].length); + } - let first_call_set = new Set(services_first_call); - assert_equals(services_first_call.length, first_call_set.size); - let second_call_set = new Set(services_second_call); - assert_equals(services_second_call.length, second_call_set.size); - - services_first_call.forEach(service => { - assert_true(second_call_set.has(service)) - }); - - services_second_call.forEach(service => { - assert_true(first_call_set.has(service)); - }); + let base_set = new Set(services_arrays[0]); + for (let services of services_arrays) { + services.forEach(service => assert_true(base_set.has(service))); + } }); }, 'Calls to getPrimaryServices should return the same object.');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.html index ce17288..f8d010b 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.html
@@ -9,7 +9,7 @@ 'use strict'; promise_test(() => { return getHealthThermometerDevice() - .then(({device}) => { + .then(([device]) => { return assert_promise_rejects_with_message( device.gatt.getPrimaryServices('wrong_name'), new DOMException(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-absent-service-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-absent-service-with-uuid.html index ce19ff45..bbebc7a 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-absent-service-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-absent-service-with-uuid.html
@@ -15,7 +15,7 @@ 'SecurityError'); return getHealthThermometerDevice({ filters: [{services: ['health_thermometer']}]}) - .then(({device}) => Promise.all([ + .then(([device]) => Promise.all([ assert_promise_rejects_with_message( device.gatt.getPrimaryServices(glucose.alias), expected), assert_promise_rejects_with_message(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html index e6e5be02..c80c983 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html
@@ -9,7 +9,7 @@ 'use strict'; promise_test(() => { return getHealthThermometerDevice({acceptAllDevices: true}) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.getPrimaryServices('heart_rate'), new DOMException('Origin is not allowed to access any service. Tip: ' + 'Add the service UUID to \'optionalServices\' in ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html index 45306589..c771e477 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html
@@ -9,7 +9,7 @@ 'use strict'; promise_test(() => { return getHealthThermometerDevice({acceptAllDevices: true}) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.getPrimaryServices(), new DOMException('Origin is not allowed to access any service. Tip: ' + 'Add the service UUID to \'optionalServices\' in ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-present-service-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-present-service-with-uuid.html index 622bdaf..dd42f46 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-present-service-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-present-service-with-uuid.html
@@ -13,15 +13,17 @@ '\'optionalServices\' in requestDevice() ' + 'options. https://goo.gl/HxfxSQ', 'SecurityError'); - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => Promise.all([ + return setBluetoothFakeAdapter('HeartRateAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gatt => Promise.all([ assert_promise_rejects_with_message( - device.gatt.getPrimaryServices(generic_access.alias), expected), + gatt.getPrimaryServices(generic_access.alias), expected), assert_promise_rejects_with_message( - device.gatt.getPrimaryServices(generic_access.name), expected), + gatt.getPrimaryServices(generic_access.name), expected), assert_promise_rejects_with_message( - device.gatt.getPrimaryServices(generic_access.uuid), expected)])); + gatt.getPrimaryServices(generic_access.uuid), expected)])); }, 'Request for present service without permission. Reject with SecurityError.'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-service-not-found-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-service-not-found-with-uuid.html index 79c7d89..cd9dce1 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-service-not-found-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-service-not-found-with-uuid.html
@@ -11,7 +11,7 @@ return getHealthThermometerDevice({ filters: [{services: ['health_thermometer']}], optionalServices: ['glucose']}) - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.getPrimaryServices('glucose'), new DOMException( 'No Services matching UUID ' + glucose.uuid + ' found in Device.',
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found-with-uuid.html index 63ac04e..4b27bbb 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found-with-uuid.html
@@ -2,26 +2,27 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> -<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script> -<script src="../../../resources/mojo-helpers.js"></script> <script> 'use strict'; -promise_test(() => { - return getTwoHealthThermometerServicesDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => Promise.all([ - device.gatt.getPrimaryServices(health_thermometer.alias), - device.gatt.getPrimaryServices(health_thermometer.name), - device.gatt.getPrimaryServices(health_thermometer.uuid)])) +promise_test(function() { + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => Promise.all([ + gattServer.getPrimaryServices(heart_rate.alias), + gattServer.getPrimaryServices(heart_rate.name), + gattServer.getPrimaryServices(heart_rate.uuid)])) .then(services_arrays => { services_arrays.forEach(services => { assert_equals(services.length, 2); - services.forEach(service => { - assert_equals(service.uuid, - BluetoothUUID.getService('health_thermometer')); - assert_true(service.isPrimary); - }); + assert_equals(services[0].uuid, + BluetoothUUID.getService('heart_rate')); + assert_equals(services[1].uuid, + BluetoothUUID.getService('heart_rate')); + assert_true(services[0].isPrimary); + assert_true(services[1].isPrimary); }); }); -}, 'Request for services. Should return right number of services.'); +}, 'Request for services. Should return right services'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found.html index 880108c..64c06041 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found.html
@@ -2,27 +2,26 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> -<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script> -<script src="../../../resources/mojo-helpers.js"></script> <script> 'use strict'; promise_test(function() { - return getTwoHealthThermometerServicesDevice({ - filters: [{services: ['health_thermometer']}], - optionalServices: ['generic_access']}) - .then(({device}) => device.gatt.getPrimaryServices()) + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}], + optionalServices: ['generic_access']})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryServices()) .then(services => { - // Expect three service instances. assert_equals(services.length, 3); - services.forEach(s => assert_true(s.isPrimary)); - - let uuid_set = new Set(services.map(s => s.uuid)); - // Two of the expected services are 'health_thermometer', so - // only 2 unique UUIDs. - assert_equals(uuid_set.size, 2); - - assert_true(uuid_set.has(BluetoothUUID.getService('generic_access'))); - assert_true(uuid_set.has(BluetoothUUID.getService('health_thermometer'))); + assert_equals(services[0].uuid, + BluetoothUUID.getService('generic_access')); + assert_equals(services[1].uuid, + BluetoothUUID.getService('heart_rate')); + assert_equals(services[2].uuid, + BluetoothUUID.getService('heart_rate')); + assert_true(services[0].isPrimary); + assert_true(services[1].isPrimary); + assert_true(services[2].isPrimary); }); }, 'Find all services in a device.'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-not-found.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-not-found.html index f621118..744fda8 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-not-found.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-not-found.html
@@ -8,7 +8,7 @@ 'use strict'; promise_test(() => { return getEmptyHealthThermometerDevice() - .then(({device}) => assert_promise_rejects_with_message( + .then(([device]) => assert_promise_rejects_with_message( device.gatt.getPrimaryServices(), new DOMException('No Services found in device.', 'NotFoundError'))); }, 'Request for services in a device with no services. Reject with ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/device-same-from-2-services.html b/third_party/WebKit/LayoutTests/bluetooth/service/device-same-from-2-services.html index d1ef99d6..4056825 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/service/device-same-from-2-services.html +++ b/third_party/WebKit/LayoutTests/bluetooth/service/device-same-from-2-services.html
@@ -2,16 +2,16 @@ <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../resources/bluetooth/bluetooth-helpers.js"></script> -<script src="../../resources/bluetooth/web-bluetooth-test.js"></script> -<script src="../../resources/mojo-helpers.js"></script> <script> 'use strict'; promise_test(() => { - return getTwoHealthThermometerServicesDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => device.gatt.getPrimaryServices('health_thermometer')) - .then(([service1, service2]) => { - assert_equals(service1.device, service2.device); + return setBluetoothFakeAdapter('TwoHeartRateServicesAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryServices('heart_rate')) + .then(services => { + assert_equals(services[0].device, services[1].device); }); }, "Same parent device returned from multiple services."); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/device-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/service/device-same-object.html index d3f4808..91388573 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/service/device-same-object.html +++ b/third_party/WebKit/LayoutTests/bluetooth/service/device-same-object.html
@@ -2,14 +2,14 @@ <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../resources/bluetooth/bluetooth-helpers.js"></script> -<script src="../../resources/bluetooth/web-bluetooth-test.js"></script> -<script src="../../resources/mojo-helpers.js"></script> <script> 'use strict'; promise_test(() => { - return getHealthThermometerDevice({ - filters: [{services: ['health_thermometer']}]}) - .then(({device}) => device.gatt.getPrimaryService('health_thermometer')) + return setBluetoothFakeAdapter('HeartRateAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['heart_rate']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('heart_rate')) .then(service => { assert_equals(service.device, service.device); });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/geometry-1/DOMMatrix-stringifier-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/geometry-1/DOMMatrix-stringifier-expected.txt new file mode 100644 index 0000000..22ad39c5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/geometry-1/DOMMatrix-stringifier-expected.txt
@@ -0,0 +1,82 @@ +This is a testharness.js-based test. +Found 78 tests; 54 PASS, 24 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS DOMMatrix stringifier: identity (2d) +PASS DOMMatrix stringifier: identity (3d) +PASS DOMMatrix stringifier: NaN (2d) +PASS DOMMatrix stringifier: NaN (3d) +PASS DOMMatrix stringifier: Infinity (2d) +PASS DOMMatrix stringifier: Infinity (3d) +PASS DOMMatrix stringifier: -Infinity (2d) +PASS DOMMatrix stringifier: -Infinity (3d) +PASS DOMMatrix stringifier: 1/3 (2d) +PASS DOMMatrix stringifier: 1/3 (3d) +PASS DOMMatrix stringifier: 1/300000 (2d) +PASS DOMMatrix stringifier: 1/300000 (3d) +PASS DOMMatrix stringifier: 1/300000000 (2d) +PASS DOMMatrix stringifier: 1/300000000 (3d) +PASS DOMMatrix stringifier: 100000 + (1/3) (2d) +PASS DOMMatrix stringifier: 100000 + (1/3) (3d) +PASS DOMMatrix stringifier: Math.pow(2, 53) + 1 (2d) +PASS DOMMatrix stringifier: Math.pow(2, 53) + 1 (3d) +PASS DOMMatrix stringifier: Math.pow(2, 53) + 2 (2d) +PASS DOMMatrix stringifier: Math.pow(2, 53) + 2 (3d) +PASS DOMMatrix stringifier: Number.MAX_VALUE (2d) +PASS DOMMatrix stringifier: Number.MAX_VALUE (3d) +PASS DOMMatrix stringifier: Number.MIN_VALUE (2d) +PASS DOMMatrix stringifier: Number.MIN_VALUE (3d) +PASS DOMMatrix stringifier: throwing getters (2d) +PASS DOMMatrix stringifier: throwing getters (3d) +PASS DOMMatrixReadOnly stringifier: identity (2d) +PASS DOMMatrixReadOnly stringifier: identity (3d) +PASS DOMMatrixReadOnly stringifier: NaN (2d) +PASS DOMMatrixReadOnly stringifier: NaN (3d) +PASS DOMMatrixReadOnly stringifier: Infinity (2d) +PASS DOMMatrixReadOnly stringifier: Infinity (3d) +PASS DOMMatrixReadOnly stringifier: -Infinity (2d) +PASS DOMMatrixReadOnly stringifier: -Infinity (3d) +PASS DOMMatrixReadOnly stringifier: 1/3 (2d) +PASS DOMMatrixReadOnly stringifier: 1/3 (3d) +PASS DOMMatrixReadOnly stringifier: 1/300000 (2d) +PASS DOMMatrixReadOnly stringifier: 1/300000 (3d) +PASS DOMMatrixReadOnly stringifier: 1/300000000 (2d) +PASS DOMMatrixReadOnly stringifier: 1/300000000 (3d) +PASS DOMMatrixReadOnly stringifier: 100000 + (1/3) (2d) +PASS DOMMatrixReadOnly stringifier: 100000 + (1/3) (3d) +PASS DOMMatrixReadOnly stringifier: Math.pow(2, 53) + 1 (2d) +PASS DOMMatrixReadOnly stringifier: Math.pow(2, 53) + 1 (3d) +PASS DOMMatrixReadOnly stringifier: Math.pow(2, 53) + 2 (2d) +PASS DOMMatrixReadOnly stringifier: Math.pow(2, 53) + 2 (3d) +PASS DOMMatrixReadOnly stringifier: Number.MAX_VALUE (2d) +PASS DOMMatrixReadOnly stringifier: Number.MAX_VALUE (3d) +PASS DOMMatrixReadOnly stringifier: Number.MIN_VALUE (2d) +PASS DOMMatrixReadOnly stringifier: Number.MIN_VALUE (3d) +PASS DOMMatrixReadOnly stringifier: throwing getters (2d) +PASS DOMMatrixReadOnly stringifier: throwing getters (3d) +PASS WebKitCSSMatrix stringifier: identity (2d) +FAIL WebKitCSSMatrix stringifier: identity (3d) self[constr].fromMatrix is not a function +FAIL WebKitCSSMatrix stringifier: NaN (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,NaN'. +FAIL WebKitCSSMatrix stringifier: NaN (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,NaN,0,1'. +FAIL WebKitCSSMatrix stringifier: Infinity (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,Infinity'. +FAIL WebKitCSSMatrix stringifier: Infinity (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,Infinity,0,1'. +FAIL WebKitCSSMatrix stringifier: -Infinity (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,-Infinity'. +FAIL WebKitCSSMatrix stringifier: -Infinity (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,-Infinity,0,1'. +FAIL WebKitCSSMatrix stringifier: 1/3 (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,0.3333333333333333'. +FAIL WebKitCSSMatrix stringifier: 1/3 (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,0.3333333333333333,0,1'. +FAIL WebKitCSSMatrix stringifier: 1/300000 (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,0.0000033333333333333333'. +FAIL WebKitCSSMatrix stringifier: 1/300000 (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,0.0000033333333333333333,0,1'. +FAIL WebKitCSSMatrix stringifier: 1/300000000 (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,3.3333333333333334e-9'. +FAIL WebKitCSSMatrix stringifier: 1/300000000 (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,3.3333333333333334e-9,0,1'. +FAIL WebKitCSSMatrix stringifier: 100000 + (1/3) (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,100000.33333333333'. +FAIL WebKitCSSMatrix stringifier: 100000 + (1/3) (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,100000.33333333333,0,1'. +FAIL WebKitCSSMatrix stringifier: Math.pow(2, 53) + 1 (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,9007199254740992'. +FAIL WebKitCSSMatrix stringifier: Math.pow(2, 53) + 1 (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,9007199254740992,0,1'. +FAIL WebKitCSSMatrix stringifier: Math.pow(2, 53) + 2 (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,9007199254740994'. +FAIL WebKitCSSMatrix stringifier: Math.pow(2, 53) + 2 (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,9007199254740994,0,1'. +FAIL WebKitCSSMatrix stringifier: Number.MAX_VALUE (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,1.7976931348623157e+308'. +FAIL WebKitCSSMatrix stringifier: Number.MAX_VALUE (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,1.7976931348623157e+308,0,1'. +FAIL WebKitCSSMatrix stringifier: Number.MIN_VALUE (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,5e-324'. +FAIL WebKitCSSMatrix stringifier: Number.MIN_VALUE (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,5e-324,0,1'. +PASS WebKitCSSMatrix stringifier: throwing getters (2d) +FAIL WebKitCSSMatrix stringifier: throwing getters (3d) self[constr].fromMatrix is not a function +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/geometry-1/WebKitCSSMatrix-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/geometry-1/WebKitCSSMatrix-expected.txt new file mode 100644 index 0000000..dd0272a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/geometry-1/WebKitCSSMatrix-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +FAIL Equivalence test assert_equals: interface object expected function "function DOMMatrix() { [native code] }" but got function "function WebKitCSSMatrix() { [native code] }" +PASS Property descriptor for WebKitCSSMatrix +PASS Property descriptor for DOMMatrix +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/custom-constructors-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Window/custom-constructors-expected.txt index 294eef2..7d0014c 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/Window/custom-constructors-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/Window/custom-constructors-expected.txt
@@ -7,7 +7,7 @@ PASS Option.prototype.toString.call(new Option) is '[object HTMLOptionElement]' PASS WebKitCSSMatrix.prototype.toString.call(new WebKitCSSMatrix) is 'matrix(1, 0, 0, 1, 0, 0)' PASS WebKitCSSMatrix.prototype.toString.call(new WebKitCSSMatrix()) is 'matrix(1, 0, 0, 1, 0, 0)' -PASS new WebKitCSSMatrix(null) threw exception SyntaxError: Failed to construct 'DOMMatrix': Failed to parse 'null'.. +PASS new WebKitCSSMatrix(null) threw exception SyntaxError: Failed to construct 'WebKitCSSMatrix': Failed to parse 'null'.. FAIL new WebKitCSSMatrix(undefined) should throw an exception. Was matrix(1, 0, 0, 1, 0, 0). PASS XMLHttpRequest.prototype.toString.call(new XMLHttpRequest) is '[object XMLHttpRequest]' PASS XSLTProcessor.prototype.toString.call(new XSLTProcessor) is '[object XSLTProcessor]'
diff --git a/third_party/WebKit/LayoutTests/fast/dom/call-a-constructor-as-a-function-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/call-a-constructor-as-a-function-expected.txt index d91c597..bcd6af3 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/call-a-constructor-as-a-function-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/call-a-constructor-as-a-function-expected.txt
@@ -22,7 +22,7 @@ PASS Uint16Array() threw exception TypeError: Constructor Uint16Array requires 'new'. PASS Uint32Array() threw exception TypeError: Constructor Uint32Array requires 'new'. PASS Uint8Array() threw exception TypeError: Constructor Uint8Array requires 'new'. -PASS WebKitCSSMatrix() threw exception TypeError: Failed to construct 'DOMMatrix': Please use the 'new' operator, this DOM object constructor cannot be called as a function.. +PASS WebKitCSSMatrix() threw exception TypeError: Failed to construct 'WebKitCSSMatrix': Please use the 'new' operator, this DOM object constructor cannot be called as a function.. PASS WebSocket() threw exception TypeError: Failed to construct 'WebSocket': Please use the 'new' operator, this DOM object constructor cannot be called as a function.. PASS Worker() threw exception TypeError: Failed to construct 'Worker': Please use the 'new' operator, this DOM object constructor cannot be called as a function.. PASS XMLHttpRequest() threw exception TypeError: Failed to construct 'XMLHttpRequest': Please use the 'new' operator, this DOM object constructor cannot be called as a function..
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/application-panel/storage-view-reports-quota-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/application-panel/storage-view-reports-quota-expected.txt new file mode 100644 index 0000000..b2222f9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/application-panel/storage-view-reports-quota-expected.txt
@@ -0,0 +1,12 @@ +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback1 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback2 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback3 +Tests quota reporting. + +Tree element found: true +Clear storage view is visible: true +0 B storage quota used out of - + +Running: Now with data +9.5 MB storage quota used out of - +
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/application-panel/storage-view-reports-quota.html b/third_party/WebKit/LayoutTests/http/tests/inspector/application-panel/storage-view-reports-quota.html new file mode 100644 index 0000000..20fdf24 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/application-panel/storage-view-reports-quota.html
@@ -0,0 +1,62 @@ +<html> +<head> +<script src="../inspector-test.js"></script> +<script src="../resources-test.js"></script> +<script src="../console-test.js"></script> +<script src="../indexeddb/indexeddb-test.js"></script> +<script> +async function test() { + var updateListener = null; + + async function writeArray() { + var array = []; + for (var i = 0; i < 5000000; i++) + array.push(i % 10); + var mainFrameId = InspectorTest.resourceTreeModel.mainFrame.id; + await new Promise(resolve => InspectorTest.createDatabase(mainFrameId, 'Database1', resolve)); + await new Promise(resolve => InspectorTest.createObjectStore(mainFrameId, 'Database1', 'Store1', 'id', true, resolve)); + await new Promise(resolve => InspectorTest.addIDBValue(mainFrameId, 'Database1', 'Store1', {key: 1, value: array}, '', resolve)); + } + + async function dumpWhenMatches(view, predicate) { + await new Promise(resolve => { + function sniffer(usage, quota) { + if (usage !== null && (!predicate || predicate(usage, quota))) + resolve(); + else + InspectorTest.addSniffer(clearStorageView, '_usageUpdatedForTest', sniffer); + } + sniffer(null); + }); + // Quota will vary between setups, rather strip it altogether + var clean = view._quotaRow.innerHTML.replace(/\ /g, ' '); + var quotaStripped = clean.replace(/(.*) \d+ .?B([^\d]*)/, '$1 -$2'); + InspectorTest.addResult(quotaStripped); + } + UI.viewManager.showView('resources'); + + var parent = UI.panels.resources._sidebar._applicationTreeElement; + var clearStorageElement = parent.children().find(child => child.title === 'Clear storage'); + + InspectorTest.addResult('Tree element found: ' + !!clearStorageElement); + clearStorageElement.select(); + + var clearStorageView = UI.panels.resources.visibleView; + InspectorTest.addResult("Clear storage view is visible: " + (clearStorageView instanceof Resources.ClearStorageView)); + + clearStorageView._clearButton.click(); + await dumpWhenMatches(clearStorageView, usage => usage === 0); + + InspectorTest.markStep('Now with data'); + + await writeArray(); + await dumpWhenMatches(clearStorageView, usage => usage > 5000000); + + InspectorTest.completeTest(); +} +</script> +</head> +<body onload="runTest()"> + <p>Tests quota reporting.</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/help/release-note-expected.txt b/third_party/WebKit/LayoutTests/inspector/help/release-note-expected.txt index fd12a4d..83b5e68 100644 --- a/third_party/WebKit/LayoutTests/inspector/help/release-note-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/help/release-note-expected.txt
@@ -1,7 +1,7 @@ Test release note Last release note version seen: -0 +1 Dumping release note text: Highlights from Chrome 100 update
diff --git a/third_party/WebKit/LayoutTests/inspector/help/release-note-unit-expected.txt b/third_party/WebKit/LayoutTests/inspector/help/release-note-unit-expected.txt index 149ad071..5f3e950 100644 --- a/third_party/WebKit/LayoutTests/inspector/help/release-note-unit-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/help/release-note-unit-expected.txt
@@ -13,3 +13,8 @@ Last seen version: 5 Did not show release note drawer +Running: doNotShowReleaseNoteOnFreshProfile +Last seen version: 0 +Did not show release note drawer +Release note version in setting: 5 +
diff --git a/third_party/WebKit/LayoutTests/inspector/help/release-note-unit.html b/third_party/WebKit/LayoutTests/inspector/help/release-note-unit.html index 2de5f28..9aef56a 100644 --- a/third_party/WebKit/LayoutTests/inspector/help/release-note-unit.html +++ b/third_party/WebKit/LayoutTests/inspector/help/release-note-unit.html
@@ -42,6 +42,12 @@ testMaybeShowInDrawer(lastSeenVersion); next(); }, + function doNotShowReleaseNoteOnFreshProfile(next) { + var lastSeenVersion = 0; + testMaybeShowInDrawer(lastSeenVersion); + InspectorTest.addResult(`Release note version in setting: ${Help.releaseNoteVersionSetting().get()}`); + next(); + }, ]); } </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/help/release-note.html b/third_party/WebKit/LayoutTests/inspector/help/release-note.html index f61ad816..235b48e 100644 --- a/third_party/WebKit/LayoutTests/inspector/help/release-note.html +++ b/third_party/WebKit/LayoutTests/inspector/help/release-note.html
@@ -26,6 +26,7 @@ InspectorTest.addSniffer(UI.viewManager, "showView", onShowView); InspectorTest.addResult("Last release note version seen:"); + Help.releaseNoteVersionSetting().set(1); InspectorTest.addResult(Help.releaseNoteVersionSetting().get() + "\n"); Help.showReleaseNoteIfNeeded();
diff --git a/third_party/WebKit/LayoutTests/media/remoteplayback/prompt-throws-when-backend-disabled.html b/third_party/WebKit/LayoutTests/media/remoteplayback/prompt-throws-when-backend-disabled.html deleted file mode 100644 index 33948b9..0000000 --- a/third_party/WebKit/LayoutTests/media/remoteplayback/prompt-throws-when-backend-disabled.html +++ /dev/null
@@ -1,52 +0,0 @@ -<!DOCTYPE html> -<html> -<title>Test that calling prompt() when backend is disabled, throws an exception</title> -<script src="../../resources/testharness.js"></script> -<script src="../../resources/testharnessreport.js"></script> -<script src="../media-file.js"></script> -<script src="util.js"></script> -<button id="button">Click me</button> -<script> - // WPT: this test can't be moved to WPT because of its usage of: - // - user gesture; - // - internals.mediaPlayerRemoteRouteAvailabilityChanged - // - internals.runtimeFlags - - function clickOnElem(e) { - var x = e.offsetLeft + e.offsetWidth / 2; - var y = e.offsetTop + e.offsetHeight / 2; - chrome.gpuBenchmarking.pointerActionSequence( - [ - { - "source": "mouse", - "actions": - [ - { "name": "pointerDown", "x": x, "y": y }, - { "name": "pointerUp" } - ] - } - ]); - } - - async_test(function(t) - { - disableRemotePlaybackBackendForTest(t); - - var v = document.createElement('video'); - v.src = findMediaFile('video', 'content/test'); - document.body.appendChild(v); - - internals.mediaPlayerRemoteRouteAvailabilityChanged(v, true); - - var btn = document.getElementById('button'); - btn.onclick = function() { - v.remote.prompt().then(t.unreached_func(), - t.step_func_done(function(e) { - assert_equals(e.name, 'NotSupportedError'); - assert_equals(e.message, 'The RemotePlayback API is disabled on this platform.'); - })); - } - - clickOnElem(btn); - }, 'Test that calling prompt() when backend is disabled, throws an exception.'); -</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/media/remoteplayback/prompt-twice-throws.html b/third_party/WebKit/LayoutTests/media/remoteplayback/prompt-twice-throws.html index 51776f9..5712a66 100644 --- a/third_party/WebKit/LayoutTests/media/remoteplayback/prompt-twice-throws.html +++ b/third_party/WebKit/LayoutTests/media/remoteplayback/prompt-twice-throws.html
@@ -5,6 +5,7 @@ <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../media-file.js"></script> + <script src="util.js"></script> </head> <body> <button id="button">Click me</button> @@ -12,6 +13,7 @@ // WPT: this test can't be moved to WPT because of its usage of: // - user gesture; // - internals.mediaPlayerRemoteRouteAvailabilityChanged + // - internals.runtimeFlags function clickOnElem(e) { eventSender.mouseMoveTo( @@ -23,14 +25,17 @@ async_test(function(test) { - var v = document.createElement('video'); - v.src = findMediaFile('video', 'content/test'); - document.body.appendChild(v); + // So that prompt() doesn't throw NotSupportedError. + enableRemotePlaybackBackendForTest(test); - internals.mediaPlayerRemoteRouteAvailabilityChanged(v, true); + var v = document.createElement('video'); + v.src = findMediaFile('video', '../content/test'); + document.body.appendChild(v); var btn = document.getElementById('button'); btn.onclick = function() { + internals.mediaPlayerRemoteRouteAvailabilityChanged(v, true); + v.remote.prompt(); btn.onclick = function() {
diff --git a/third_party/WebKit/LayoutTests/media/remoteplayback/util.js b/third_party/WebKit/LayoutTests/media/remoteplayback/util.js index 10f1eb0..3502d1312 100644 --- a/third_party/WebKit/LayoutTests/media/remoteplayback/util.js +++ b/third_party/WebKit/LayoutTests/media/remoteplayback/util.js
@@ -1,10 +1,10 @@ -function disableRemotePlaybackBackendForTest(t) { +function enableRemotePlaybackBackendForTest(t) { var remotePlaybackBackendEnabledOldValue = internals.runtimeFlags.remotePlaybackBackendEnabled; - internals.runtimeFlags.remotePlaybackBackendEnabled = false; + internals.runtimeFlags.remotePlaybackBackendEnabled = true; t.add_cleanup(() => { internals.runtimeFlags.remotePlaybackBackendEnabled = remotePlaybackBackendEnabledOldValue; }); -} \ No newline at end of file +}
diff --git a/third_party/WebKit/LayoutTests/media/remoteplayback/watch-availability-works-when-backend-disabled.html b/third_party/WebKit/LayoutTests/media/remoteplayback/watch-availability-works-when-backend-disabled.html deleted file mode 100644 index 853ebfc..0000000 --- a/third_party/WebKit/LayoutTests/media/remoteplayback/watch-availability-works-when-backend-disabled.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!DOCTYPE html> -<title>Test that watchAvailability does not throw when backend is disabled.</title> -<script src="../../resources/testharness.js"></script> -<script src="../../resources/testharnessreport.js"></script> -<script src="../../resources/gc.js"></script> -<script src="../media-file.js"></script> -<script src="util.js"></script> -<video></video> -<script> - // WPT: this test can't be moved to WPT because of its usage of: - // - internals.runtimeFlags - - async_test(function(t) { - disableRemotePlaybackBackendForTest(t); - - var availability_callback_id = -1; - var v = document.querySelector('video'); - v.src = findMediaFile('video', 'content/test'); - - function callback(available) { - assert_false(available); - v.remote.cancelWatchAvailability(availability_callback_id).then( - t.step_func_done(), t.unreached_func()); - } - - v.remote.watchAvailability(callback).then(t.step_func( - function(id) { assert_true(id >= 0); availability_callback_id = id; }), - t.unreached_func()); - }, 'Test that watchAvailability doesn not throw when backend is disabled.'); -</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/paint/printing/print-box-shadow-expected.png b/third_party/WebKit/LayoutTests/paint/printing/print-box-shadow-expected.png index 5325356..cae9229 100644 --- a/third_party/WebKit/LayoutTests/paint/printing/print-box-shadow-expected.png +++ b/third_party/WebKit/LayoutTests/paint/printing/print-box-shadow-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/controls-cast-overlay-slow-fade-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/controls-cast-overlay-slow-fade-expected.txt deleted file mode 100644 index 8b4c5f2..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/controls-cast-overlay-slow-fade-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL Test that the overlay cast button fades at the right time (neither too soon nor too late). assert_true: button should exist expected true got false -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt index 4289e61..b743349 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -7369,9 +7369,63 @@ getter animationName getter elapsedTime method constructor -interface WebKitCSSMatrix : DOMMatrixReadOnly +interface WebKitCSSMatrix attribute @@toStringTag + getter a + getter b + getter c + getter d + getter e + getter f + getter m11 + getter m12 + getter m13 + getter m14 + getter m21 + getter m22 + getter m23 + getter m24 + getter m31 + getter m32 + getter m33 + getter m34 + getter m41 + getter m42 + getter m43 + getter m44 method constructor + method inverse + method multiply + method rotate + method rotateAxisAngle + method scale + method setMatrixValue + method skewX + method skewY + method toString + method translate + setter a + setter b + setter c + setter d + setter e + setter f + setter m11 + setter m12 + setter m13 + setter m14 + setter m21 + setter m22 + setter m23 + setter m24 + setter m31 + setter m32 + setter m33 + setter m34 + setter m41 + setter m42 + setter m43 + setter m44 interface WebKitMutationObserver attribute @@toStringTag method constructor
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt index f88813a..ff81a8a 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -7298,9 +7298,63 @@ getter animationName getter elapsedTime method constructor -interface WebKitCSSMatrix : DOMMatrixReadOnly +interface WebKitCSSMatrix attribute @@toStringTag + getter a + getter b + getter c + getter d + getter e + getter f + getter m11 + getter m12 + getter m13 + getter m14 + getter m21 + getter m22 + getter m23 + getter m24 + getter m31 + getter m32 + getter m33 + getter m34 + getter m41 + getter m42 + getter m43 + getter m44 method constructor + method inverse + method multiply + method rotate + method rotateAxisAngle + method scale + method setMatrixValue + method skewX + method skewY + method toString + method translate + setter a + setter b + setter c + setter d + setter e + setter f + setter m11 + setter m12 + setter m13 + setter m14 + setter m21 + setter m22 + setter m23 + setter m24 + setter m31 + setter m32 + setter m33 + setter m34 + setter m41 + setter m42 + setter m43 + setter m44 interface WebKitMutationObserver attribute @@toStringTag method constructor
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js index fbff635..c8dea3d6 100644 --- a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js +++ b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
@@ -40,11 +40,6 @@ name: 'heart_rate', uuid: '0000180d-0000-1000-8000-00805f9b34fb' }; -var health_thermometer = { - alias: 0x1809, - name: 'health_thermometer', - uuid: '00001809-0000-1000-8000-00805f9b34fb' -}; var body_sensor_location = { alias: 0x2a38, name: 'body_sensor_location', @@ -456,94 +451,22 @@ })])); } -// Returns an object containing a BluetoothDevice discovered using |options|, -// its corresponding FakePeripheral and FakeRemoteGATTServices. +// Returns a BluetoothDevice discovered using |options| and its +// corresponding FakePeripheral. // The simulated device is called 'Health Thermometer' it has two known service -// UUIDs: 'generic_access' and 'health_thermometer' which correspond to two -// services with the same UUIDs. The device has been connected to and its -// services are ready to be discovered. -// TODO(crbug.com/719816): Add characteristics and descriptors. +// UUIDs: 'generic_access' and 'health_thermometer'. The device has been +// connected to and its services have been discovered. +// TODO(crbug.com/719816): Add services, characteristics and descriptors, +// and discover all the attributes. function getHealthThermometerDevice(options) { - let device; - let fake_peripheral; - let fake_generic_access; - let fake_health_thermometer; - - return getConnectedHealthThermometerDevice(options) - .then(result => { - ({ - device, - fake_peripheral, - fake_generic_access, - fake_health_thermometer, - } = result); - }) - .then(() => fake_peripheral.setNextGATTDiscoveryResponse({ - code: HCI_SUCCESS})) - .then(() => ({ - device: device, - fake_peripheral: fake_peripheral, - fake_generic_access: fake_generic_access, - fake_health_thermometer1: fake_health_thermometer, - })); -} - -// Similar to getHealthThermometerDevice except that the peripheral has -// two 'health_thermometer' services. -function getTwoHealthThermometerServicesDevice(options) { - let device; - let fake_peripheral; - let fake_generic_access; - let fake_health_thermometer1; - let fake_health_thermometer2; - - return getConnectedHealthThermometerDevice(options) - .then(result => { - ({ - device, - fake_peripheral, - fake_generic_access, - fake_health_thermometer: fake_health_thermometer1, - } = result); - }) - .then(() => fake_peripheral.addFakeService({uuid: 'health_thermometer'})) - .then(s => fake_health_thermometer2 = s) - .then(() => fake_peripheral.setNextGATTDiscoveryResponse({ - code: HCI_SUCCESS})) - .then(() => ({ - device: device, - fake_peripheral: fake_peripheral, - fake_generic_access: fake_generic_access, - fake_health_thermometer1: fake_health_thermometer1, - fake_health_thermometer2: fake_health_thermometer2 - })); -} - -// Similar to getHealthThermometerDevice except the GATT discovery -// response has not been set yet so more attributes can still be added. -function getConnectedHealthThermometerDevice(options) { - let device; - let fake_peripheral; - let fake_generic_access; - let fake_health_thermometer; return getDiscoveredHealthThermometerDevice(options) - .then(result => { - ({device, fake_peripheral} = result); - }) - .then(() => fake_peripheral.setNextGATTConnectionResponse({ - code: HCI_SUCCESS})) - .then(() => device.gatt.connect()) - .then(() => fake_peripheral.addFakeService({uuid: 'generic_access'})) - .then(s => fake_generic_access = s) - .then(() => fake_peripheral.addFakeService({ - uuid: 'health_thermometer'})) - .then(s => fake_health_thermometer = s) - .then(() => ({ - device: device, - fake_peripheral: fake_peripheral, - fake_generic_access: fake_generic_access, - fake_health_thermometer: fake_health_thermometer, - })); + .then(([device, fake_peripheral]) => { + return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}) + .then(() => device.gatt.connect()) + .then(() => fake_peripheral.setNextGATTDiscoveryResponse({ + code: HCI_SUCCESS})) + .then(() => [device, fake_peripheral]); + }); } // Returns the same device and fake peripheral as getHealthThermometerDevice() @@ -581,10 +504,7 @@ })) .then(() => requestDeviceWithKeyDown(options)) .then(device => device.gatt.connect()) - .then(gatt => ({ - device: gatt.device, - fake_peripheral: fake_peripheral - })); + .then(gatt => [gatt.device, fake_peripheral]); }); } @@ -592,56 +512,15 @@ // characteristics, or descriptors. function getEmptyHealthThermometerDevice(options) { return getDiscoveredHealthThermometerDevice(options) - .then(({device, fake_peripheral}) => { + .then(([device, fake_peripheral]) => { return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}) .then(() => device.gatt.connect()) .then(() => fake_peripheral.setNextGATTDiscoveryResponse({ code: HCI_SUCCESS})) - .then(() => ({ - device: device, - fake_peripheral: fake_peripheral - })); + .then(() => [device, fake_peripheral]); }); } -// Returns a BluetoothDevice discovered using |options| and its -// corresponding FakePeripheral. -// The simulated device is called 'HID Device' it has three known service -// UUIDs: 'generic_access', 'battery_service', 'human_interface_device'. The -// device has been connected to and its services are ready to be discovered. -// TODO(crbug.com/719816): Add characteristics and descriptors. -function getHIDDevice(options) { - return setUpPreconnectedDevice({ - address: '10:10:10:10:10:10', - name: 'HID Device', - knownServiceUUIDs: [ - 'generic_access', - 'battery_service', - 'human_interface_device' - ], - }) - .then(fake_peripheral => { - return requestDeviceWithKeyDown(options) - .then(device => { - return fake_peripheral.setNextGATTConnectionResponse({ - code: HCI_SUCCESS}) - .then(() => device.gatt.connect()) - .then(() => fake_peripheral.addFakeService({ - uuid: 'generic_access'})) - .then(() => fake_peripheral.addFakeService({ - uuid: 'battery_service'})) - .then(() => fake_peripheral.addFakeService({ - uuid: 'human_interface_device'})) - .then(() => fake_peripheral.setNextGATTDiscoveryResponse({ - code: HCI_SUCCESS})) - .then(() => ({ - device: device, - fake_peripheral: fake_peripheral - })); - }); - }); -}; - // Similar to getHealthThermometerDevice() except the device // is not connected and thus its services have not been // discovered. @@ -654,9 +533,6 @@ }) .then(fake_peripheral => { return requestDeviceWithKeyDown(options) - .then(device => ({ - device: device, - fake_peripheral: fake_peripheral - })); + .then(device => [device, fake_peripheral]); }); }
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/health-thermometer-two-iframes.html b/third_party/WebKit/LayoutTests/resources/bluetooth/heart-rate-two-iframes.html similarity index 61% rename from third_party/WebKit/LayoutTests/resources/bluetooth/health-thermometer-two-iframes.html rename to third_party/WebKit/LayoutTests/resources/bluetooth/heart-rate-two-iframes.html index d5d38fd..91f7a98 100644 --- a/third_party/WebKit/LayoutTests/resources/bluetooth/health-thermometer-two-iframes.html +++ b/third_party/WebKit/LayoutTests/resources/bluetooth/heart-rate-two-iframes.html
@@ -1,25 +1,25 @@ <!DOCTYPE html> <script> -'use strict'; -let device; -window.onmessage = messageEvent => { - if (messageEvent.data === 'Iframe1RequestAndConnect') { - navigator.bluetooth.requestDevice({ - filters: [{services: ['health_thermometer']}] +'use restrict'; + let device; + window.onmessage = messageEvent => { + if (messageEvent.data === 'Iframe1RequestAndConnect') { + navigator.bluetooth.requestDevice({ + filters: [{services: ['heart_rate']}] }) .then(device => device.gatt.connect()) .then(gattServer => { - // iframe1 can access health_thermometer service. - return gattServer.getPrimaryService('health_thermometer'); + // iframe1 can access heart_rate service. + return gattServer.getPrimaryService('heart_rate'); }).then(() => { parent.postMessage('Iframe1Connected', '*'); }).catch(err => { console.error(err); parent.postMessage('FAIL: ' + err, '*'); }); - } else if (messageEvent.data === 'Iframe1TryAccessGenericAccessService') { - navigator.bluetooth.requestDevice({ - filters: [{services: ['health_thermometer']}] + } else if (messageEvent.data === 'Iframe1TryAccessGenericAccessService') { + navigator.bluetooth.requestDevice({ + filters: [{services: ['heart_rate']}] }) .then(device => device.gatt.connect()) .then(gattServer => { @@ -28,26 +28,26 @@ }).catch(err => { parent.postMessage('Iframe1AccessGenericAccessServiceFailed', '*'); }); - } else if (messageEvent.data === 'Iframe2RequestAndConnect') { - navigator.bluetooth.requestDevice({ + } else if (messageEvent.data === 'Iframe2RequestAndConnect') { + navigator.bluetooth.requestDevice({ filters: [{services: ['generic_access']}] }) .then(device => device.gatt.connect()) .then(gattServer => { - // Since iframe1 can access health_thermometer service, and iframe2 has the + // Since iframe1 can access heart_rate service, and iframe2 has the // same origin as iframe1, iframe2 should also be able to access - // health_thermometer service. + // heart_rate service. return Promise.all([gattServer.getPrimaryService('generic_access'), - gattServer.getPrimaryService('health_thermometer')]); + gattServer.getPrimaryService('heart_rate')]); }).then(() => { parent.postMessage('Iframe2Connected', '*'); }).catch(err => { console.error(err); parent.postMessage('FAIL: ' + err, '*'); }); - } else if (messageEvent.data === 'TestIframe1HasGenericAccessService') { - navigator.bluetooth.requestDevice({ - filters: [{services: ['health_thermometer']}] + } else if (messageEvent.data === 'TestIframe1HasGenericAccessService') { + navigator.bluetooth.requestDevice({ + filters: [{services: ['heart_rate']}] }) .then(device => device.gatt.connect()) .then(gattServer => { @@ -61,7 +61,7 @@ console.error(err); parent.postMessage('FAIL: ' + err, '*'); }); - } -}; -parent.postMessage("Ready", "*"); + } + }; + parent.postMessage("Ready", "*"); </script>
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js b/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js index 648ea2b..7b6cd79 100644 --- a/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js +++ b/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js
@@ -150,7 +150,6 @@ class FakePeripheral { constructor(address, fake_central_ptr) { this.address = address; - this.services_ = []; this.fake_central_ptr_ = fake_central_ptr; } @@ -167,24 +166,6 @@ if (success !== true) throw 'setNextGATTConnectionResponse failed.'; } - // Adds a fake GATT Service with |uuid| to be discovered when discovering - // the peripheral's GATT Attributes. Returns a FakeRemoteGATTService - // corresponding to this service. |uuid| should be a BluetoothServiceUUIDs - // https://webbluetoothcg.github.io/web-bluetooth/#typedefdef-bluetoothserviceuuid - async addFakeService({uuid}) { - let {service_id} = await this.fake_central_ptr_.addFakeService( - this.address, {uuid: BluetoothUUID.getService(uuid)}); - - if (service_id === null) throw 'addFakeService failed'; - - let fake_service = new FakeRemoteGATTService( - service_id, this.address, this.fake_central_ptr_); - - this.services_.push(fake_service); - - return fake_service; - } - // Sets the next GATT Discovery request response for peripheral with // |address| to |code|. |code| could be an HCI Error Code from // BT 4.2 Vol 2 Part D 1.3 List Of Error Codes or a number outside that @@ -210,13 +191,5 @@ } } - class FakeRemoteGATTService { - constructor(service_id, peripheral_address, fake_central_ptr) { - this.service_id_ = service_id; - this.peripheral_address_ = peripheral_address; - this.fake_central_ptr_ = fake_central_ptr; - } - } - navigator.bluetooth.test = new FakeBluetooth(); })();
diff --git a/third_party/WebKit/LayoutTests/transforms/3d/general/cssmatrix-3d-zoom-expected.png b/third_party/WebKit/LayoutTests/transforms/3d/general/cssmatrix-3d-zoom-expected.png index ba6d122..cdd5578c 100644 --- a/third_party/WebKit/LayoutTests/transforms/3d/general/cssmatrix-3d-zoom-expected.png +++ b/third_party/WebKit/LayoutTests/transforms/3d/general/cssmatrix-3d-zoom-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface-expected.txt b/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface-expected.txt index 66b3e49c..fb5cb01 100644 --- a/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface-expected.txt +++ b/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface-expected.txt
@@ -23,7 +23,7 @@ PASS a3[1] is "" Test bad input to string constructor -PASS new WebKitCSSMatrix("banana") threw exception SyntaxError: Failed to construct 'DOMMatrix': Failed to parse 'banana'.. +PASS new WebKitCSSMatrix("banana") threw exception SyntaxError: Failed to construct 'WebKitCSSMatrix': Failed to parse 'banana'.. Test attributes on default matrix PASS m.a is 1 @@ -58,9 +58,9 @@ PASS m.f is 20 Test throwing exception from setMatrixValue -PASS m.setMatrixValue("banana") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'banana'.. -PASS m.setMatrixValue("translate(10em, 20%)") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Lengths must be absolute, not relative. -PASS m.setMatrixValue("translate(10px, 20px) scale()") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'translate(10px, 20px) scale()'.. +PASS m.setMatrixValue("banana") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'WebKitCSSMatrix': Failed to parse 'banana'.. +PASS m.setMatrixValue("translate(10em, 20%)") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'WebKitCSSMatrix': The transformation depends on the box size, which is not supported.. +PASS m.setMatrixValue("translate(10px, 20px) scale()") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'WebKitCSSMatrix': Failed to parse 'translate(10px, 20px) scale()'.. Test attributes on translate() and accumulation PASS m2.a is 1 @@ -189,12 +189,7 @@ PASS sx.f is 0 Test multiply with missing argument -PASS m2.a is 1 -PASS m2.b is 2 -PASS m2.c is 3 -PASS m2.d is 4 -PASS m2.e is 5 -PASS m2.f is 6 +PASS m2 is null Test inverse PASS parseFloat(m2.a) is 0.5 @@ -212,21 +207,8 @@ PASS parseFloat(m.e) is 10 PASS parseFloat(m.f) is 20 -Test not invertible matrix -PASS m2.a is NaN -PASS m2.b is NaN -PASS m2.c is NaN -PASS m2.d is NaN -PASS m2.e is NaN -PASS m2.f is NaN - -Test immutability of inverse -PASS m.a is 0 -PASS m.b is 0 -PASS m.c is 0 -PASS m.d is 0 -PASS m.e is 0 -PASS m.f is 0 +Test throwing exception from inverse +PASS m.inverse() threw exception NotSupportedError: Failed to execute 'inverse' on 'WebKitCSSMatrix': The matrix is not invertable.. PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface.xhtml b/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface.xhtml index ed7b00c..cc85536 100644 --- a/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface.xhtml +++ b/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface.xhtml
@@ -255,12 +255,7 @@ debug("Test multiply with missing argument"); m = new WebKitCSSMatrix("matrix(1, 2, 3, 4, 5, 6)"); m2 = m.multiply(); -shouldBe('m2.a', '1'); -shouldBe('m2.b', '2'); -shouldBe('m2.c', '3'); -shouldBe('m2.d', '4'); -shouldBe('m2.e', '5'); -shouldBe('m2.f', '6'); +shouldBe('m2', 'null'); debug(""); debug("Test inverse"); @@ -284,25 +279,9 @@ shouldBe('parseFloat(m.f)', '20'); debug(""); -debug("Test not invertible matrix"); +debug("Test throwing exception from inverse"); m = new WebKitCSSMatrix("matrix(0, 0, 0, 0, 0, 0)"); // not invertible -m2 = m.inverse(); - -shouldBeNaN('m2.a'); -shouldBeNaN('m2.b'); -shouldBeNaN('m2.c'); -shouldBeNaN('m2.d'); -shouldBeNaN('m2.e'); -shouldBeNaN('m2.f'); - -debug(""); -debug("Test immutability of inverse"); -shouldBe('m.a', '0'); -shouldBe('m.b', '0'); -shouldBe('m.c', '0'); -shouldBe('m.d', '0'); -shouldBe('m.e', '0'); -shouldBe('m.f', '0'); +shouldThrow('m.inverse()'); debug("");
diff --git a/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface-expected.txt b/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface-expected.txt index 3563c33..247a66d 100644 --- a/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface-expected.txt +++ b/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface-expected.txt
@@ -29,7 +29,7 @@ PASS a3[1] is "" Test bad input to string constructor -PASS new WebKitCSSMatrix("banana") threw exception SyntaxError: Failed to construct 'DOMMatrix': Failed to parse 'banana'.. +PASS new WebKitCSSMatrix("banana") threw exception SyntaxError: Failed to construct 'WebKitCSSMatrix': Failed to parse 'banana'.. Test attributes on default matrix PASS m.m11 is 1 @@ -104,9 +104,9 @@ PASS m.m44 is 1 Test throwing exception from setMatrixValue -PASS m.setMatrixValue("banana") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'banana'.. -PASS m.setMatrixValue("translate3d(10em, 20%, 40)") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'translate3d(10em, 20%, 40)'.. -PASS m.setMatrixValue("translate3d(10px, 20px, 30px) scale3d()") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'translate3d(10px, 20px, 30px) scale3d()'.. +PASS m.setMatrixValue("banana") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'WebKitCSSMatrix': Failed to parse 'banana'.. +PASS m.setMatrixValue("translate3d(10em, 20%, 40)") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'WebKitCSSMatrix': Failed to parse 'translate3d(10em, 20%, 40)'.. +PASS m.setMatrixValue("translate3d(10px, 20px, 30px) scale3d()") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'WebKitCSSMatrix': Failed to parse 'translate3d(10px, 20px, 30px) scale3d()'.. Test multiply PASS parseFloat(m3.m11) is 538 @@ -216,41 +216,8 @@ PASS parseFloat(m.m43) is 30 PASS parseFloat(m.m44) is 1 -Test not invertible 3d matrix -PASS m2.m11 is NaN -PASS m2.m12 is NaN -PASS m2.m13 is NaN -PASS m2.m14 is NaN -PASS m2.m21 is NaN -PASS m2.m22 is NaN -PASS m2.m23 is NaN -PASS m2.m24 is NaN -PASS m2.m31 is NaN -PASS m2.m32 is NaN -PASS m2.m33 is NaN -PASS m2.m34 is NaN -PASS m2.m41 is NaN -PASS m2.m42 is NaN -PASS m2.m43 is NaN -PASS m2.m44 is NaN - -Test immutability of inverse -PASS m.m11 is 0 -PASS m.m12 is 0 -PASS m.m13 is 0 -PASS m.m14 is 0 -PASS m.m21 is 0 -PASS m.m22 is 0 -PASS m.m23 is 0 -PASS m.m24 is 0 -PASS m.m31 is 0 -PASS m.m32 is 0 -PASS m.m33 is 0 -PASS m.m34 is 0 -PASS m.m41 is 0 -PASS m.m42 is 0 -PASS m.m43 is 0 -PASS m.m44 is 0 +Test throwing exception from inverse +PASS m.inverse() threw exception NotSupportedError: Failed to execute 'inverse' on 'WebKitCSSMatrix': The matrix is not invertable.. Test translate PASS m2.m11 is 1
diff --git a/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface.xhtml b/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface.xhtml index 2ea85b43..392949f 100644 --- a/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface.xhtml +++ b/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface.xhtml
@@ -277,45 +277,9 @@ shouldBe('parseFloat(m.m44)', '1'); debug(""); -debug("Test not invertible 3d matrix"); +debug("Test throwing exception from inverse"); m = new WebKitCSSMatrix("matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)"); // not invertible -m2 = m.inverse(); - -shouldBeNaN('m2.m11'); -shouldBeNaN('m2.m12'); -shouldBeNaN('m2.m13'); -shouldBeNaN('m2.m14'); -shouldBeNaN('m2.m21'); -shouldBeNaN('m2.m22'); -shouldBeNaN('m2.m23'); -shouldBeNaN('m2.m24'); -shouldBeNaN('m2.m31'); -shouldBeNaN('m2.m32'); -shouldBeNaN('m2.m33'); -shouldBeNaN('m2.m34'); -shouldBeNaN('m2.m41'); -shouldBeNaN('m2.m42'); -shouldBeNaN('m2.m43'); -shouldBeNaN('m2.m44'); - -debug(""); -debug("Test immutability of inverse"); -shouldBe('m.m11', '0'); -shouldBe('m.m12', '0'); -shouldBe('m.m13', '0'); -shouldBe('m.m14', '0'); -shouldBe('m.m21', '0'); -shouldBe('m.m22', '0'); -shouldBe('m.m23', '0'); -shouldBe('m.m24', '0'); -shouldBe('m.m31', '0'); -shouldBe('m.m32', '0'); -shouldBe('m.m33', '0'); -shouldBe('m.m34', '0'); -shouldBe('m.m41', '0'); -shouldBe('m.m42', '0'); -shouldBe('m.m43', '0'); -shouldBe('m.m44', '0'); +shouldThrow('m.inverse()'); debug(""); debug("Test translate");
diff --git a/third_party/WebKit/LayoutTests/transforms/cssmatrix-crash-expected.txt b/third_party/WebKit/LayoutTests/transforms/cssmatrix-crash-expected.txt new file mode 100644 index 0000000..ddad5eaf --- /dev/null +++ b/third_party/WebKit/LayoutTests/transforms/cssmatrix-crash-expected.txt
@@ -0,0 +1 @@ +PASS if no crash
diff --git a/third_party/WebKit/LayoutTests/transforms/cssmatrix-crash.html b/third_party/WebKit/LayoutTests/transforms/cssmatrix-crash.html new file mode 100644 index 0000000..ad928d2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/transforms/cssmatrix-crash.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<script> +if (window.testRunner) + testRunner.dumpAsText(); + +new WebKitCSSMatrix("translateX(1ex)"); +new WebKitCSSMatrix("translateX(1ch)"); +</script> +<p>PASS if no crash</p>
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt index c9903255..22f8ae8 100644 --- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
@@ -8495,7 +8495,7 @@ getter animationName getter elapsedTime method constructor -interface WebKitCSSMatrix : DOMMatrixReadOnly +interface WebKitCSSMatrix attribute @@toStringTag getter a getter b @@ -8520,18 +8520,16 @@ getter m43 getter m44 method constructor - method invertSelf - method multiplySelf - method preMultiplySelf - method rotateAxisAngleSelf - method rotateFromVectorSelf - method rotateSelf - method scale3dSelf - method scaleSelf + method inverse + method multiply + method rotate + method rotateAxisAngle + method scale method setMatrixValue - method skewXSelf - method skewYSelf - method translateSelf + method skewX + method skewY + method toString + method translate setter a setter b setter c
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index eca5b15..a0f6f0de 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -8503,7 +8503,7 @@ getter animationName getter elapsedTime method constructor -interface WebKitCSSMatrix : DOMMatrixReadOnly +interface WebKitCSSMatrix attribute @@toStringTag getter a getter b @@ -8528,18 +8528,16 @@ getter m43 getter m44 method constructor - method invertSelf - method multiplySelf - method preMultiplySelf - method rotateAxisAngleSelf - method rotateFromVectorSelf - method rotateSelf - method scale3dSelf - method scaleSelf + method inverse + method multiply + method rotate + method rotateAxisAngle + method scale method setMatrixValue - method skewXSelf - method skewYSelf - method translateSelf + method skewX + method skewY + method toString + method translate setter a setter b setter c
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp index 75b38fe..14538dc 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
@@ -427,7 +427,7 @@ } std::unique_ptr<TextResourceDecoder> decoder(TextResourceDecoder::Create( - "application/javascript", resource->Encoding())); + "application/javascript", WTF::TextEncoding(resource->Encoding()))); decoder->CheckForBOM(maybe_bom, kMaximumLengthOfBOM); // The encoding may change when we see the BOM. Check for BOM now
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp index 9499582..dad2cb3 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp
@@ -347,7 +347,7 @@ // It's possible that the encoding of the Resource changes after we start // loading it. V8TestingScope scope; - resource_->SetEncoding("windows-1252"); + resource_->SetEncodingForTest("windows-1252"); ScriptStreamer::StartStreaming( GetPendingScript(), ScriptStreamer::kParsingBlocking, settings_.get(), @@ -355,7 +355,7 @@ TestPendingScriptClient* client = new TestPendingScriptClient; GetPendingScript()->WatchForLoad(client); - resource_->SetEncoding("UTF-8"); + resource_->SetEncodingForTest("UTF-8"); // \xec\x92\x81 are the raw bytes for \uc481. AppendData( "function foo() { var foob\xec\x92\x81r = 13; return foob\xec\x92\x81r; " @@ -384,7 +384,9 @@ // Byte order marks should be removed before giving the data to V8. They // will also affect encoding detection. V8TestingScope scope; - resource_->SetEncoding("windows-1252"); // This encoding is wrong on purpose. + + // This encoding is wrong on purpose. + resource_->SetEncodingForTest("windows-1252"); ScriptStreamer::StartStreaming( GetPendingScript(), ScriptStreamer::kParsingBlocking, settings_.get(),
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index 9d036af..b2d8eab67 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1476,7 +1476,6 @@ "//testing/gmock", "//testing/gtest", "//third_party/WebKit/Source/core/editing:unit_tests", - "//third_party/WebKit/Source/core/mojo:unit_tests", ] }
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni index 70448a2..992bddb 100644 --- a/third_party/WebKit/Source/core/core_idl_files.gni +++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -62,6 +62,7 @@ "css/StyleMedia.idl", "css/StyleSheet.idl", "css/StyleSheetList.idl", + "css/WebKitCSSMatrix.idl", "css/cssom/CSSImageValue.idl", "css/cssom/CSSKeywordValue.idl", "css/cssom/CSSMatrixComponent.idl",
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn index fa4163d..255cc52 100644 --- a/third_party/WebKit/Source/core/css/BUILD.gn +++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -94,6 +94,8 @@ "CSSKeyframesRule.h", "CSSMarkup.cpp", "CSSMarkup.h", + "CSSMatrix.cpp", + "CSSMatrix.h", "CSSMediaRule.cpp", "CSSMediaRule.h", "CSSNamespaceRule.cpp",
diff --git a/third_party/WebKit/Source/core/css/CSSMatrix.cpp b/third_party/WebKit/Source/core/css/CSSMatrix.cpp new file mode 100644 index 0000000..92af0333 --- /dev/null +++ b/third_party/WebKit/Source/core/css/CSSMatrix.cpp
@@ -0,0 +1,205 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core/css/CSSMatrix.h" + +#include "bindings/core/v8/ExceptionState.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/css/CSSIdentifierValue.h" +#include "core/css/CSSToLengthConversionData.h" +#include "core/css/StylePropertySet.h" +#include "core/css/parser/CSSParser.h" +#include "core/css/resolver/TransformBuilder.h" +#include "core/dom/ExceptionCode.h" +#include "core/frame/UseCounter.h" +#include "core/layout/api/LayoutViewItem.h" +#include "core/style/ComputedStyle.h" +#include "platform/wtf/MathExtras.h" + +namespace blink { + +CSSMatrix* CSSMatrix::Create(ExecutionContext* execution_context, + const String& s, + ExceptionState& exception_state) { + return new CSSMatrix(s, exception_state); +} + +CSSMatrix::CSSMatrix(const TransformationMatrix& m) + : matrix_(TransformationMatrix::Create(m)) {} + +CSSMatrix::CSSMatrix(const String& s, ExceptionState& exception_state) + : matrix_(TransformationMatrix::Create()) { + setMatrixValue(s, exception_state); +} + +static inline PassRefPtr<ComputedStyle> CreateInitialStyle() { + RefPtr<ComputedStyle> initial_style = ComputedStyle::Create(); + initial_style->GetFont().Update(nullptr); + return initial_style; +} + +void CSSMatrix::setMatrixValue(const String& string, + ExceptionState& exception_state) { + if (string.IsEmpty()) + return; + + if (const CSSValue* value = + CSSParser::ParseSingleValue(CSSPropertyTransform, string)) { + // Check for a "none" transform. In these cases we can use the default + // identity matrix. + if (value->IsIdentifierValue() && + (ToCSSIdentifierValue(value))->GetValueID() == CSSValueNone) + return; + + DEFINE_STATIC_REF(ComputedStyle, initial_style, CreateInitialStyle()); + TransformOperations operations = + TransformBuilder::CreateTransformOperations( + *value, CSSToLengthConversionData(initial_style, initial_style, + LayoutViewItem(nullptr), 1.0f)); + + // Convert transform operations to a TransformationMatrix. This can fail + // if a param has a percentage ('%') + if (operations.DependsOnBoxSize()) { + exception_state.ThrowDOMException(kSyntaxError, + "The transformation depends on the box " + "size, which is not supported."); + } + matrix_ = TransformationMatrix::Create(); + operations.Apply(FloatSize(0, 0), *matrix_); + } else { // There is something there but parsing failed. + exception_state.ThrowDOMException(kSyntaxError, + "Failed to parse '" + string + "'."); + } +} + +// Perform a concatenation of the matrices (this * secondMatrix) +CSSMatrix* CSSMatrix::multiply(CSSMatrix* second_matrix) const { + if (!second_matrix) + return nullptr; + + return CSSMatrix::Create( + TransformationMatrix(*matrix_).Multiply(*second_matrix->matrix_)); +} + +CSSMatrix* CSSMatrix::inverse(ExceptionState& exception_state) const { + if (!matrix_->IsInvertible()) { + exception_state.ThrowDOMException(kNotSupportedError, + "The matrix is not invertable."); + return nullptr; + } + + return CSSMatrix::Create(matrix_->Inverse()); +} + +CSSMatrix* CSSMatrix::translate(double x, double y, double z) const { + if (std::isnan(x)) + x = 0; + if (std::isnan(y)) + y = 0; + if (std::isnan(z)) + z = 0; + return CSSMatrix::Create(TransformationMatrix(*matrix_).Translate3d(x, y, z)); +} + +CSSMatrix* CSSMatrix::scale(double scale_x, + double scale_y, + double scale_z) const { + if (std::isnan(scale_x)) + scale_x = 1; + if (std::isnan(scale_y)) + scale_y = scale_x; + if (std::isnan(scale_z)) + scale_z = 1; + return CSSMatrix::Create( + TransformationMatrix(*matrix_).Scale3d(scale_x, scale_y, scale_z)); +} + +CSSMatrix* CSSMatrix::rotate(double rot_x, double rot_y, double rot_z) const { + if (std::isnan(rot_x)) + rot_x = 0; + + if (std::isnan(rot_y) && std::isnan(rot_z)) { + rot_z = rot_x; + rot_x = 0; + rot_y = 0; + } + + if (std::isnan(rot_y)) + rot_y = 0; + if (std::isnan(rot_z)) + rot_z = 0; + return CSSMatrix::Create( + TransformationMatrix(*matrix_).Rotate3d(rot_x, rot_y, rot_z)); +} + +CSSMatrix* CSSMatrix::rotateAxisAngle(double x, + double y, + double z, + double angle) const { + if (std::isnan(x)) + x = 0; + if (std::isnan(y)) + y = 0; + if (std::isnan(z)) + z = 0; + if (std::isnan(angle)) + angle = 0; + if (!x && !y && !z) + z = 1; + return CSSMatrix::Create( + TransformationMatrix(*matrix_).Rotate3d(x, y, z, angle)); +} + +CSSMatrix* CSSMatrix::skewX(double angle) const { + if (std::isnan(angle)) + angle = 0; + return CSSMatrix::Create(TransformationMatrix(*matrix_).SkewX(angle)); +} + +CSSMatrix* CSSMatrix::skewY(double angle) const { + if (std::isnan(angle)) + angle = 0; + return CSSMatrix::Create(TransformationMatrix(*matrix_).SkewY(angle)); +} + +String CSSMatrix::toString() const { + // FIXME - Need to ensure valid CSS floating point values + // (https://bugs.webkit.org/show_bug.cgi?id=20674) + if (matrix_->IsAffine()) { + return String::Format("matrix(%g, %g, %g, %g, %g, %g)", matrix_->A(), + matrix_->B(), matrix_->C(), matrix_->D(), + matrix_->E(), matrix_->F()); + } + return String::Format( + "matrix3d(%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, " + "%g)", + matrix_->M11(), matrix_->M12(), matrix_->M13(), matrix_->M14(), + matrix_->M21(), matrix_->M22(), matrix_->M23(), matrix_->M24(), + matrix_->M31(), matrix_->M32(), matrix_->M33(), matrix_->M34(), + matrix_->M41(), matrix_->M42(), matrix_->M43(), matrix_->M44()); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/CSSMatrix.h b/third_party/WebKit/Source/core/css/CSSMatrix.h new file mode 100644 index 0000000..1c25efb2 --- /dev/null +++ b/third_party/WebKit/Source/core/css/CSSMatrix.h
@@ -0,0 +1,171 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CSSMatrix_h +#define CSSMatrix_h + +#include <memory> +#include "platform/bindings/ScriptWrappable.h" +#include "platform/transforms/TransformationMatrix.h" +#include "platform/wtf/text/WTFString.h" + +namespace blink { + +class ExceptionState; +class ExecutionContext; + +class CSSMatrix final : public GarbageCollectedFinalized<CSSMatrix>, + public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); + + public: + static CSSMatrix* Create(const TransformationMatrix& m) { + return new CSSMatrix(m); + } + static CSSMatrix* Create(ExecutionContext*, const String&, ExceptionState&); + + double a() const { return matrix_->A(); } + double b() const { return matrix_->B(); } + double c() const { return matrix_->C(); } + double d() const { return matrix_->D(); } + double e() const { return matrix_->E(); } + double f() const { return matrix_->F(); } + + void setA(double f) { matrix_->SetA(f); } + void setB(double f) { matrix_->SetB(f); } + void setC(double f) { matrix_->SetC(f); } + void setD(double f) { matrix_->SetD(f); } + void setE(double f) { matrix_->SetE(f); } + void setF(double f) { matrix_->SetF(f); } + + double m11() const { return matrix_->M11(); } + double m12() const { return matrix_->M12(); } + double m13() const { return matrix_->M13(); } + double m14() const { return matrix_->M14(); } + double m21() const { return matrix_->M21(); } + double m22() const { return matrix_->M22(); } + double m23() const { return matrix_->M23(); } + double m24() const { return matrix_->M24(); } + double m31() const { return matrix_->M31(); } + double m32() const { return matrix_->M32(); } + double m33() const { return matrix_->M33(); } + double m34() const { return matrix_->M34(); } + double m41() const { return matrix_->M41(); } + double m42() const { return matrix_->M42(); } + double m43() const { return matrix_->M43(); } + double m44() const { return matrix_->M44(); } + + void setM11(double f) { matrix_->SetM11(f); } + void setM12(double f) { matrix_->SetM12(f); } + void setM13(double f) { matrix_->SetM13(f); } + void setM14(double f) { matrix_->SetM14(f); } + void setM21(double f) { matrix_->SetM21(f); } + void setM22(double f) { matrix_->SetM22(f); } + void setM23(double f) { matrix_->SetM23(f); } + void setM24(double f) { matrix_->SetM24(f); } + void setM31(double f) { matrix_->SetM31(f); } + void setM32(double f) { matrix_->SetM32(f); } + void setM33(double f) { matrix_->SetM33(f); } + void setM34(double f) { matrix_->SetM34(f); } + void setM41(double f) { matrix_->SetM41(f); } + void setM42(double f) { matrix_->SetM42(f); } + void setM43(double f) { matrix_->SetM43(f); } + void setM44(double f) { matrix_->SetM44(f); } + + void setMatrixValue(const String&, ExceptionState&); + + // The following math function return a new matrix with the + // specified operation applied. The this value is not modified. + + // Multiply this matrix by secondMatrix, on the right + // (result = this * secondMatrix) + CSSMatrix* multiply(CSSMatrix* second_matrix) const; + + // Return the inverse of this matrix. Throw an exception if the matrix is not + // invertible. + CSSMatrix* inverse(ExceptionState&) const; + + // Return this matrix translated by the passed values. + // Passing a NaN will use a value of 0. This allows the 3D form to used for 2D + // operations. + // Operation is performed as though the this matrix is multiplied by a matrix + // with the translation values on the left + // (result = translation(x,y,z) * this) + CSSMatrix* translate(double x, double y, double z) const; + + // Returns this matrix scaled by the passed values. + // Passing scaleX or scaleZ as NaN uses a value of 1, but passing scaleY of + // NaN makes it the same as scaleX. This allows the 3D form to used for 2D + // operations Operation is performed as though the this matrix is multiplied + // by a matrix with the scale values on the left + // (result = scale(x,y,z) * this) + CSSMatrix* scale(double scale_x, double scale_y, double scale_z) const; + + // Returns this matrix rotated by the passed values. + // If rotY and rotZ are NaN, rotate about Z (rotX=0, rotateY=0, rotateZ=rotX). + // Otherwise use a rotation value of 0 for any passed NaN. + // Operation is performed as though the this matrix is multiplied by a matrix + // with the rotation values on the left (result = rotation(x,y,z) * this) + CSSMatrix* rotate(double rot_x, double rot_y, double rot_z) const; + + // Returns this matrix rotated about the passed axis by the passed angle. + // Passing a NaN will use a value of 0. If the axis is (0,0,0) use a value + // Operation is performed as though the this matrix is multiplied by a matrix + // with the rotation values on the left + // (result = rotation(x,y,z,angle) * this) + CSSMatrix* rotateAxisAngle(double x, double y, double z, double angle) const; + + // Return this matrix skewed along the X axis by the passed values. + // Passing a NaN will use a value of 0. + // Operation is performed as though the this matrix is multiplied by a matrix + // with the skew values on the left (result = skewX(angle) * this) + CSSMatrix* skewX(double angle) const; + + // Return this matrix skewed along the Y axis by the passed values. + // Passing a NaN will use a value of 0. + // Operation is performed as though the this matrix is multiplied by a matrix + // with the skew values on the left (result = skewY(angle) * this) + CSSMatrix* skewY(double angle) const; + + const TransformationMatrix& Transform() const { return *matrix_; } + + String toString() const; + + DEFINE_INLINE_TRACE() {} + + protected: + CSSMatrix(const TransformationMatrix&); + CSSMatrix(const String&, ExceptionState&); + + // TransformationMatrix needs to be 16-byte aligned. PartitionAlloc + // supports 16-byte alignment but Oilpan doesn't. So we use an std::unique_ptr + // to allocate TransformationMatrix on PartitionAlloc. + // TODO(oilpan): Oilpan should support 16-byte aligned allocations. + std::unique_ptr<TransformationMatrix> matrix_; +}; + +} // namespace blink + +#endif // CSSMatrix_h
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h index 59a4c3d..0aaed58 100644 --- a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h +++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
@@ -1008,27 +1008,6 @@ } template <> -inline ETextDecorationStyle CSSIdentifierValue::ConvertTo() const { - switch (value_id_) { - case CSSValueSolid: - return ETextDecorationStyle::kSolid; - case CSSValueDouble: - return ETextDecorationStyle::kDouble; - case CSSValueDotted: - return ETextDecorationStyle::kDotted; - case CSSValueDashed: - return ETextDecorationStyle::kDashed; - case CSSValueWavy: - return ETextDecorationStyle::kWavy; - default: - break; - } - - NOTREACHED(); - return ETextDecorationStyle::kSolid; -} - -template <> inline TextDecorationSkip CSSIdentifierValue::ConvertTo() const { switch (value_id_) { case CSSValueObjects: @@ -1137,34 +1116,6 @@ } template <> -inline CSSIdentifierValue::CSSIdentifierValue(ETextOverflow overflow) - : CSSValue(kIdentifierClass) { - switch (overflow) { - case ETextOverflow::kClip: - value_id_ = CSSValueClip; - break; - case ETextOverflow::kEllipsis: - value_id_ = CSSValueEllipsis; - break; - } -} - -template <> -inline ETextOverflow CSSIdentifierValue::ConvertTo() const { - switch (value_id_) { - case CSSValueClip: - return ETextOverflow::kClip; - case CSSValueEllipsis: - return ETextOverflow::kEllipsis; - default: - break; - } - - NOTREACHED(); - return ETextOverflow::kClip; -} - -template <> inline CSSIdentifierValue::CSSIdentifierValue(TextEmphasisFill fill) : CSSValue(kIdentifierClass) { switch (fill) {
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5 index 53d72324..f6d0b9f 100644 --- a/third_party/WebKit/Source/core/css/CSSProperties.json5 +++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -2436,8 +2436,9 @@ custom_all: true, interpolable: true, runtime_flag: "CSS3TextDecorations", - field_template: "storage_only", + field_template: "external", type_name: "StyleColor", + include_paths: ["core/css/StyleColor.h"], field_group: "rare-non-inherited", default_value: "StyleColor::CurrentColor()", }, @@ -2465,10 +2466,10 @@ { name: "text-decoration-style", runtime_flag: "CSS3TextDecorations", - field_template: "storage_only", + field_template: "keyword", + keywords: ["solid", "double", "dotted", "dashed", "wavy"], field_group: "rare-non-inherited", - default_value: "ETextDecorationStyle::kSolid", - field_size: 3, + default_value: "solid", }, { name: "text-indent", @@ -2497,10 +2498,10 @@ }, { name: "text-overflow", - field_template: "storage_only", + field_template: "keyword", field_group: "rare-non-inherited", - default_value: "ETextOverflow::kClip", - field_size: 1, + default_value: "clip", + keywords: ["clip", "ellipsis"], }, { name: "text-shadow",
diff --git a/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp b/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp index 9e8458a..6ef1896 100644 --- a/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp +++ b/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp
@@ -109,7 +109,7 @@ CSSStyleSheet* CSSStyleSheet::CreateInline(Node& owner_node, const KURL& base_url, const TextPosition& start_position, - const String& encoding) { + const WTF::TextEncoding& encoding) { CSSParserContext* parser_context = CSSParserContext::Create( owner_node.GetDocument(), owner_node.GetDocument().BaseURL(), owner_node.GetDocument().GetReferrerPolicy(), encoding);
diff --git a/third_party/WebKit/Source/core/css/CSSStyleSheet.h b/third_party/WebKit/Source/core/css/CSSStyleSheet.h index eb00fc5..a0b0438 100644 --- a/third_party/WebKit/Source/core/css/CSSStyleSheet.h +++ b/third_party/WebKit/Source/core/css/CSSStyleSheet.h
@@ -28,6 +28,7 @@ #include "core/css/StyleSheet.h" #include "platform/heap/Handle.h" #include "platform/wtf/Noncopyable.h" +#include "platform/wtf/text/TextEncoding.h" #include "platform/wtf/text/TextPosition.h" namespace blink { @@ -56,7 +57,7 @@ Node&, const KURL&, const TextPosition& start_position = TextPosition::MinimumPosition(), - const String& encoding = String()); + const WTF::TextEncoding& = WTF::TextEncoding()); static CSSStyleSheet* CreateInline( StyleSheetContents*, Node& owner_node,
diff --git a/third_party/WebKit/Source/core/css/CSSTestHelper.cpp b/third_party/WebKit/Source/core/css/CSSTestHelper.cpp index 4c3f02c..b0f82af 100644 --- a/third_party/WebKit/Source/core/css/CSSTestHelper.cpp +++ b/third_party/WebKit/Source/core/css/CSSTestHelper.cpp
@@ -34,7 +34,7 @@ #include "core/css/RuleSet.h" #include "core/css/StyleSheetContents.h" #include "core/dom/Document.h" -#include "platform/wtf/text/WTFString.h" +#include "platform/wtf/text/TextEncoding.h" #include "testing/gtest/include/gtest/gtest.h" namespace blink { @@ -45,7 +45,7 @@ document_ = Document::Create(); TextPosition position; style_sheet_ = - CSSStyleSheet::CreateInline(*document_, KURL(), position, "UTF-8"); + CSSStyleSheet::CreateInline(*document_, KURL(), position, UTF8Encoding()); } CSSRuleList* CSSTestHelper::CssRules() {
diff --git a/third_party/WebKit/Source/core/css/StyleRuleImport.cpp b/third_party/WebKit/Source/core/css/StyleRuleImport.cpp index 5856e93..caf0f7b2 100644 --- a/third_party/WebKit/Source/core/css/StyleRuleImport.cpp +++ b/third_party/WebKit/Source/core/css/StyleRuleImport.cpp
@@ -69,7 +69,7 @@ const String& href, const KURL& base_url, ReferrerPolicy referrer_policy, - const String& charset, + const WTF::TextEncoding& charset, const CSSStyleSheetResource* cached_style_sheet) { if (style_sheet_) style_sheet_->ClearOwnerRule(); @@ -135,7 +135,7 @@ kClientRequestedCredentials); options.initiator_info.name = FetchInitiatorTypeNames::css; FetchParameters params(ResourceRequest(abs_url), options); - params.SetCharset(parent_style_sheet_->Charset()); + params.SetCharset(String(parent_style_sheet_->Charset().GetName())); resource_ = CSSStyleSheetResource::Fetch(params, fetcher); if (resource_) { // if the import rule is issued dynamically, the sheet may be
diff --git a/third_party/WebKit/Source/core/css/StyleRuleImport.h b/third_party/WebKit/Source/core/css/StyleRuleImport.h index 0d8134c..d52b793 100644 --- a/third_party/WebKit/Source/core/css/StyleRuleImport.h +++ b/third_party/WebKit/Source/core/css/StyleRuleImport.h
@@ -74,7 +74,7 @@ void SetCSSStyleSheet(const String& href, const KURL& base_url, ReferrerPolicy referrer_policy, - const String& charset, + const WTF::TextEncoding& charset, const CSSStyleSheetResource* sheet) override { owner_rule_->SetCSSStyleSheet(href, base_url, referrer_policy, charset, sheet); @@ -93,7 +93,7 @@ void SetCSSStyleSheet(const String& href, const KURL& base_url, ReferrerPolicy, - const String& charset, + const WTF::TextEncoding&, const CSSStyleSheetResource*); StyleRuleImport(const String& href, RefPtr<MediaQuerySet>);
diff --git a/third_party/WebKit/Source/core/css/StyleSheetContents.h b/third_party/WebKit/Source/core/css/StyleSheetContents.h index cee704a4..3fb1f42 100644 --- a/third_party/WebKit/Source/core/css/StyleSheetContents.h +++ b/third_party/WebKit/Source/core/css/StyleSheetContents.h
@@ -93,7 +93,9 @@ // if there are none. Document* AnyOwnerDocument() const; - const String& Charset() const { return parser_context_->Charset(); } + const WTF::TextEncoding& Charset() const { + return parser_context_->Charset(); + } bool LoadCompleted() const; bool HasFailedOrCanceledSubresources() const;
diff --git a/third_party/WebKit/Source/core/css/WebKitCSSMatrix.idl b/third_party/WebKit/Source/core/css/WebKitCSSMatrix.idl new file mode 100644 index 0000000..d9227cf0 --- /dev/null +++ b/third_party/WebKit/Source/core/css/WebKitCSSMatrix.idl
@@ -0,0 +1,104 @@ +/* + * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Introduced in DOM Level ?: +[ + Constructor(optional DOMString cssValue = null), + ConstructorCallWith=ExecutionContext, + ImplementedAs=CSSMatrix, + RaisesException=Constructor, +] interface WebKitCSSMatrix { + + // These attributes are simple aliases for certain elements of the 4x4 matrix + attribute unrestricted double a; // alias for m11 + attribute unrestricted double b; // alias for m12 + attribute unrestricted double c; // alias for m21 + attribute unrestricted double d; // alias for m22 + attribute unrestricted double e; // alias for m41 + attribute unrestricted double f; // alias for m42 + + attribute unrestricted double m11; + attribute unrestricted double m12; + attribute unrestricted double m13; + attribute unrestricted double m14; + attribute unrestricted double m21; + attribute unrestricted double m22; + attribute unrestricted double m23; + attribute unrestricted double m24; + attribute unrestricted double m31; + attribute unrestricted double m32; + attribute unrestricted double m33; + attribute unrestricted double m34; + attribute unrestricted double m41; + attribute unrestricted double m42; + attribute unrestricted double m43; + attribute unrestricted double m44; + + [RaisesException, MeasureAs=WebkitCSSMatrixSetMatrixValue] void setMatrixValue([Default=Undefined] optional DOMString string); + + // Multiply this matrix by secondMatrix, on the right (result = this * secondMatrix) + [LegacyInterfaceTypeChecking] WebKitCSSMatrix multiply([Default=Undefined] optional WebKitCSSMatrix secondMatrix); + + // Return the inverse of this matrix. Throw an exception if the matrix is not invertible + [RaisesException] WebKitCSSMatrix inverse(); + + // Return this matrix translated by the passed values. + // Passing a NaN will use a value of 0. This allows the 3D form to used for 2D operations + WebKitCSSMatrix translate([Default=Undefined] optional unrestricted double x, + [Default=Undefined] optional unrestricted double y, + [Default=Undefined] optional unrestricted double z); + + // Returns this matrix scaled by the passed values. + // Passing scaleX or scaleZ as NaN uses a value of 1, but passing scaleY of NaN + // makes it the same as scaleX. This allows the 3D form to used for 2D operations + WebKitCSSMatrix scale([Default=Undefined] optional unrestricted double scaleX, + [Default=Undefined] optional unrestricted double scaleY, + [Default=Undefined] optional unrestricted double scaleZ); + + // Returns this matrix rotated by the passed values. + // If rotY and rotZ are NaN, rotate about Z (rotX=0, rotateY=0, rotateZ=rotX). + // Otherwise use a rotation value of 0 for any passed NaN. + WebKitCSSMatrix rotate([Default=Undefined] optional unrestricted double rotX, + [Default=Undefined] optional unrestricted double rotY, + [Default=Undefined] optional unrestricted double rotZ); + + // Returns this matrix rotated about the passed axis by the passed angle. + // Passing a NaN will use a value of 0. If the axis is (0,0,0) use a value + // of (0,0,1). + WebKitCSSMatrix rotateAxisAngle([Default=Undefined] optional unrestricted double x, + [Default=Undefined] optional unrestricted double y, + [Default=Undefined] optional unrestricted double z, + [Default=Undefined] optional unrestricted double angle); + + // Returns this matrix skewed along the X axis by the passed values. + // Passing a NaN will use a value of 0. + WebKitCSSMatrix skewX([Default=Undefined] optional unrestricted double angle); + + // Returns this matrix skewed along the Y axis by the passed values. + // Passing a NaN will use a value of 0. + WebKitCSSMatrix skewY([Default=Undefined] optional unrestricted double angle); + + [NotEnumerable] stringifier; +};
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserContext.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserContext.cpp index fe11bce..723fc31 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserContext.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserContext.cpp
@@ -46,7 +46,7 @@ const CSSParserContext* other, const KURL& base_url, ReferrerPolicy referrer_policy, - const String& charset, + const WTF::TextEncoding& charset, const Document* use_counter_document) { return new CSSParserContext( base_url, charset, other->mode_, other->match_mode_, other->profile_, @@ -62,15 +62,15 @@ SelectorProfile profile, const Document* use_counter_document) { return new CSSParserContext( - KURL(), g_empty_string, mode, mode, profile, Referrer(), false, false, - kDoNotCheckContentSecurityPolicy, use_counter_document); + KURL(), WTF::TextEncoding(), mode, mode, profile, Referrer(), false, + false, kDoNotCheckContentSecurityPolicy, use_counter_document); } // static CSSParserContext* CSSParserContext::Create(const Document& document) { return CSSParserContext::Create(document, document.BaseURL(), - document.GetReferrerPolicy(), g_empty_string, - kDynamicProfile); + document.GetReferrerPolicy(), + WTF::TextEncoding(), kDynamicProfile); } // static @@ -78,7 +78,7 @@ const Document& document, const KURL& base_url_override, ReferrerPolicy referrer_policy_override, - const String& charset, + const WTF::TextEncoding& charset, SelectorProfile profile) { CSSParserMode mode = document.InQuirksMode() ? kHTMLQuirksMode : kHTMLStandardMode; @@ -115,7 +115,7 @@ CSSParserContext::CSSParserContext( const KURL& base_url, - const String& charset, + const WTF::TextEncoding& charset, CSSParserMode mode, CSSParserMode match_mode, SelectorProfile profile, @@ -160,7 +160,7 @@ KURL CSSParserContext::CompleteURL(const String& url) const { if (url.IsNull()) return KURL(); - if (Charset().IsEmpty()) + if (!Charset().IsValid()) return KURL(BaseURL(), url); return KURL(BaseURL(), url, Charset()); }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserContext.h b/third_party/WebKit/Source/core/css/parser/CSSParserContext.h index d096d52..62cc64a 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserContext.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParserContext.h
@@ -40,7 +40,7 @@ static CSSParserContext* Create(const CSSParserContext* other, const KURL& base_url_override, ReferrerPolicy referrer_policy_override, - const String& charset_override, + const WTF::TextEncoding& charset_override, const Document* use_counter_document); static CSSParserContext* Create( @@ -48,11 +48,12 @@ SelectorProfile = kDynamicProfile, const Document* use_counter_document = nullptr); static CSSParserContext* Create(const Document&); - static CSSParserContext* Create(const Document&, - const KURL& base_url_override, - ReferrerPolicy referrer_policy_override, - const String& charset = g_empty_string, - SelectorProfile = kDynamicProfile); + static CSSParserContext* Create( + const Document&, + const KURL& base_url_override, + ReferrerPolicy referrer_policy_override, + const WTF::TextEncoding& charset = WTF::TextEncoding(), + SelectorProfile = kDynamicProfile); bool operator==(const CSSParserContext&) const; bool operator!=(const CSSParserContext& other) const { @@ -62,7 +63,7 @@ CSSParserMode Mode() const { return mode_; } CSSParserMode MatchMode() const { return match_mode_; } const KURL& BaseURL() const { return base_url_; } - const String& Charset() const { return charset_; } + const WTF::TextEncoding& Charset() const { return charset_; } const Referrer& GetReferrer() const { return referrer_; } bool IsHTMLDocument() const { return is_html_document_; } bool IsDynamicProfile() const { return profile_ == kDynamicProfile; } @@ -96,7 +97,7 @@ private: CSSParserContext(const KURL& base_url, - const String& charset, + const WTF::TextEncoding& charset, CSSParserMode, CSSParserMode match_mode, SelectorProfile, @@ -107,7 +108,7 @@ const Document* use_counter_document); KURL base_url_; - String charset_; + WTF::TextEncoding charset_; CSSParserMode mode_; CSSParserMode match_mode_; SelectorProfile profile_ = kDynamicProfile;
diff --git a/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp b/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp index 8bf54225..0cfe3fa 100644 --- a/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp +++ b/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp
@@ -194,7 +194,7 @@ const String& href, const KURL& base_url, ReferrerPolicy referrer_policy, - const String& charset, + const WTF::TextEncoding& charset, const CSSStyleSheetResource* sheet) { if (!isConnected()) { DCHECK(!sheet_);
diff --git a/third_party/WebKit/Source/core/dom/ProcessingInstruction.h b/third_party/WebKit/Source/core/dom/ProcessingInstruction.h index e00477b22..b9fe11a 100644 --- a/third_party/WebKit/Source/core/dom/ProcessingInstruction.h +++ b/third_party/WebKit/Source/core/dom/ProcessingInstruction.h
@@ -88,7 +88,7 @@ void SetCSSStyleSheet(const String& href, const KURL& base_url, ReferrerPolicy, - const String& charset, + const WTF::TextEncoding&, const CSSStyleSheetResource*) override; void SetXSLStyleSheet(const String& href, const KURL& base_url,
diff --git a/third_party/WebKit/Source/core/dom/SelectorQuery.cpp b/third_party/WebKit/Source/core/dom/SelectorQuery.cpp index dcf0a16..5720b340 100644 --- a/third_party/WebKit/Source/core/dom/SelectorQuery.cpp +++ b/third_party/WebKit/Source/core/dom/SelectorQuery.cpp
@@ -550,9 +550,9 @@ return it->value.get(); CSSSelectorList selector_list = CSSParser::ParseSelector( - CSSParserContext::Create(document, document.BaseURL(), - document.GetReferrerPolicy(), g_empty_string, - CSSParserContext::kStaticProfile), + CSSParserContext::Create( + document, document.BaseURL(), document.GetReferrerPolicy(), + WTF::TextEncoding(), CSSParserContext::kStaticProfile), nullptr, selectors); if (!selector_list.First()) {
diff --git a/third_party/WebKit/Source/core/dom/SelectorQueryTest.cpp b/third_party/WebKit/Source/core/dom/SelectorQueryTest.cpp index 91389fe4..6f4bcda 100644 --- a/third_party/WebKit/Source/core/dom/SelectorQueryTest.cpp +++ b/third_party/WebKit/Source/core/dom/SelectorQueryTest.cpp
@@ -69,7 +69,7 @@ CSSSelectorList selector_list = CSSParser::ParseSelector( CSSParserContext::Create(*document, KURL(), kReferrerPolicyDefault, - g_empty_string, + WTF::TextEncoding(), CSSParserContext::kStaticProfile), nullptr, "span::before"); std::unique_ptr<SelectorQuery> query = @@ -79,7 +79,7 @@ selector_list = CSSParser::ParseSelector( CSSParserContext::Create(*document, KURL(), kReferrerPolicyDefault, - g_empty_string, + WTF::TextEncoding(), CSSParserContext::kStaticProfile), nullptr, "span"); query = SelectorQuery::Adopt(std::move(selector_list)); @@ -98,7 +98,7 @@ CSSSelectorList selector_list = CSSParser::ParseSelector( CSSParserContext::Create(*document, KURL(), kReferrerPolicyDefault, - g_empty_string, + WTF::TextEncoding(), CSSParserContext::kStaticProfile), nullptr, "p:last-of-type"); std::unique_ptr<SelectorQuery> query =
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.cpp b/third_party/WebKit/Source/core/dom/StyleEngine.cpp index eaf9854c..0ed95df6 100644 --- a/third_party/WebKit/Source/core/dom/StyleEngine.cpp +++ b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
@@ -602,7 +602,7 @@ TextPosition start_position) { CSSStyleSheet* style_sheet = nullptr; style_sheet = CSSStyleSheet::CreateInline(element, KURL(), start_position, - GetDocument().characterSet()); + GetDocument().Encoding()); style_sheet->Contents()->ParseStringAtPosition(text, start_position); return style_sheet; }
diff --git a/third_party/WebKit/Source/core/frame/FrameSerializer.cpp b/third_party/WebKit/Source/core/frame/FrameSerializer.cpp index 272da66..df5c806a 100644 --- a/third_party/WebKit/Source/core/frame/FrameSerializer.cpp +++ b/third_party/WebKit/Source/core/frame/FrameSerializer.cpp
@@ -421,7 +421,8 @@ if (!is_inline_css) { StringBuilder css_text; css_text.Append("@charset \""); - css_text.Append(style_sheet.Contents()->Charset().DeprecatedLower()); + css_text.Append( + String(style_sheet.Contents()->Charset().GetName()).DeprecatedLower()); css_text.Append("\";\n\n"); for (unsigned i = 0; i < style_sheet.length(); ++i) {
diff --git a/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp b/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp index f409302..009cdf3 100644 --- a/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp +++ b/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp
@@ -264,10 +264,7 @@ web_frame_client->GetInterfaceProviderForTesting(), nullptr, opener); web_frame_client->Bind(frame, std::move(owned_web_frame_client)); web_view_->SetMainFrame(frame); - - // TODO(dcheng): The main frame widget currently has a special case. - // Eliminate this once WebView is no longer a WebWidget. - blink::WebFrameWidget::Create(web_widget_client, web_view_, frame); + blink::WebFrameWidget::Create(web_widget_client, frame); test_web_view_client_ = web_view_client;
diff --git a/third_party/WebKit/Source/core/frame/Window.idl b/third_party/WebKit/Source/core/frame/Window.idl index f610832..3434eb3 100644 --- a/third_party/WebKit/Source/core/frame/Window.idl +++ b/third_party/WebKit/Source/core/frame/Window.idl
@@ -204,8 +204,6 @@ // https://w3c.github.io/webappsec/specs/powerfulfeatures/#monkey-patching-global-object readonly attribute boolean isSecureContext; - - attribute DOMMatrixConstructor WebKitCSSMatrix; }; // https://html.spec.whatwg.org/#transferable-objects
diff --git a/third_party/WebKit/Source/core/html/LinkStyle.cpp b/third_party/WebKit/Source/core/html/LinkStyle.cpp index 3a49da4..98c3125 100644 --- a/third_party/WebKit/Source/core/html/LinkStyle.cpp +++ b/third_party/WebKit/Source/core/html/LinkStyle.cpp
@@ -61,7 +61,7 @@ const String& href, const KURL& base_url, ReferrerPolicy referrer_policy, - const String& charset, + const WTF::TextEncoding& charset, const CSSStyleSheetResource* cached_style_sheet) { if (!owner_->isConnected()) { // While the stylesheet is asynchronously loading, the owner can be
diff --git a/third_party/WebKit/Source/core/html/LinkStyle.h b/third_party/WebKit/Source/core/html/LinkStyle.h index 32680b6..f06e525 100644 --- a/third_party/WebKit/Source/core/html/LinkStyle.h +++ b/third_party/WebKit/Source/core/html/LinkStyle.h
@@ -63,7 +63,7 @@ void SetCSSStyleSheet(const String& href, const KURL& base_url, ReferrerPolicy, - const String& charset, + const WTF::TextEncoding&, const CSSStyleSheetResource*) override; String DebugName() const override { return "LinkStyle"; } enum LoadReturnValue { kLoaded, kNotNeeded, kBail };
diff --git a/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.cpp b/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.cpp index e533a3ab..e26f6022 100644 --- a/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.cpp +++ b/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.cpp
@@ -275,7 +275,7 @@ const String& href, const KURL& base_url, ReferrerPolicy referrer_policy, - const String& charset, + const WTF::TextEncoding&, const CSSStyleSheetResource*) { ClearResource(); }
diff --git a/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.h b/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.h index 1c08f1a..3695d71 100644 --- a/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.h +++ b/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.h
@@ -110,7 +110,7 @@ void SetCSSStyleSheet(const String& href, const KURL& base_url, ReferrerPolicy, - const String& charset, + const WTF::TextEncoding&, const CSSStyleSheetResource*) override; void DidAppendFirstData(const CSSStyleSheetResource*) override; String DebugName() const override { return "CSSPreloaderResourceClient"; }
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLParserReentryPermit.cpp b/third_party/WebKit/Source/core/html/parser/HTMLParserReentryPermit.cpp index 49a04872..c890617 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLParserReentryPermit.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLParserReentryPermit.cpp
@@ -6,7 +6,7 @@ namespace blink { -PassRefPtr<HTMLParserReentryPermit> HTMLParserReentryPermit::Create() { +RefPtr<HTMLParserReentryPermit> HTMLParserReentryPermit::Create() { return AdoptRef(new HTMLParserReentryPermit()); }
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLParserReentryPermit.h b/third_party/WebKit/Source/core/html/parser/HTMLParserReentryPermit.h index 7b5abe5..84b5b85 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLParserReentryPermit.h +++ b/third_party/WebKit/Source/core/html/parser/HTMLParserReentryPermit.h
@@ -6,8 +6,8 @@ #define HTMLParserReentryPermit_h #include "base/macros.h" -#include "platform/wtf/PassRefPtr.h" #include "platform/wtf/RefCounted.h" +#include "platform/wtf/RefPtr.h" namespace blink { @@ -38,7 +38,7 @@ class HTMLParserReentryPermit final : public RefCounted<HTMLParserReentryPermit> { public: - static PassRefPtr<HTMLParserReentryPermit> Create(); + static RefPtr<HTMLParserReentryPermit> Create(); ~HTMLParserReentryPermit() = default; unsigned ScriptNestingLevel() const { return script_nesting_level_; }
diff --git a/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.cpp b/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.cpp index 3b00250..ed0100e 100644 --- a/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.cpp +++ b/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.cpp
@@ -114,7 +114,7 @@ Vector<char, 64> buffer(length + 1); memcpy(buffer.data(), encoding_name, length); buffer[length] = '\0'; - return buffer.data(); + return WTF::TextEncoding(buffer.data()); } TextResourceDecoder::ContentType TextResourceDecoder::DetermineContentType( @@ -190,7 +190,7 @@ // XHR), treat x-user-defined as windows-1252 (bug 18270) if (source == kEncodingFromMetaTag && !strcasecmp(encoding.GetName(), "x-user-defined")) - encoding_ = "windows-1252"; + encoding_ = WTF::TextEncoding("windows-1252"); else if (source == kEncodingFromMetaTag || source == kEncodingFromXMLHeader || source == kEncodingFromCSSCharset) encoding_ = encoding.ClosestByteBasedEquivalent();
diff --git a/third_party/WebKit/Source/core/html/parser/TextResourceDecoderForFuzzing.h b/third_party/WebKit/Source/core/html/parser/TextResourceDecoderForFuzzing.h index 8b86d970c..3f6d8c0 100644 --- a/third_party/WebKit/Source/core/html/parser/TextResourceDecoderForFuzzing.h +++ b/third_party/WebKit/Source/core/html/parser/TextResourceDecoderForFuzzing.h
@@ -8,6 +8,7 @@ #include "core/html/parser/TextResourceDecoder.h" #include "platform/testing/FuzzedDataProvider.h" +#include "platform/wtf/text/TextEncoding.h" #include "platform/wtf/text/WTFString.h" namespace blink { @@ -25,7 +26,8 @@ TextResourceDecoderForFuzzing(FuzzedDataProvider& fuzzed_data) : TextResourceDecoder( String::FromUTF8(fuzzed_data.ConsumeBytesInRange(0, 32)), - String::FromUTF8(fuzzed_data.ConsumeBytesInRange(0, 32)), + WTF::TextEncoding( + String::FromUTF8(fuzzed_data.ConsumeBytesInRange(0, 32))), FuzzedOption(fuzzed_data), KURL()) {}
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp index 25c823da..6f98e31 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
@@ -142,8 +142,10 @@ static std::unique_ptr<TextResourceDecoder> CreateResourceTextDecoder( const String& mime_type, const String& text_encoding_name) { - if (!text_encoding_name.IsEmpty()) - return TextResourceDecoder::Create("text/plain", text_encoding_name); + if (!text_encoding_name.IsEmpty()) { + return TextResourceDecoder::Create("text/plain", + WTF::TextEncoding(text_encoding_name)); + } if (DOMImplementation::IsXMLMIMEType(mime_type)) { std::unique_ptr<TextResourceDecoder> decoder = TextResourceDecoder::Create("application/xml"); @@ -151,12 +153,14 @@ return decoder; } if (DeprecatedEqualIgnoringCase(mime_type, "text/html")) - return TextResourceDecoder::Create("text/html", "UTF-8"); + return TextResourceDecoder::Create("text/html", UTF8Encoding()); if (MIMETypeRegistry::IsSupportedJavaScriptMIMEType(mime_type) || DOMImplementation::IsJSONMIMEType(mime_type)) - return TextResourceDecoder::Create("text/plain", "UTF-8"); - if (DOMImplementation::IsTextMIMEType(mime_type)) - return TextResourceDecoder::Create("text/plain", "ISO-8859-1"); + return TextResourceDecoder::Create("text/plain", UTF8Encoding()); + if (DOMImplementation::IsTextMIMEType(mime_type)) { + return TextResourceDecoder::Create("text/plain", + WTF::TextEncoding("ISO-8859-1")); + } return std::unique_ptr<TextResourceDecoder>(); }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorResourceContentLoader.cpp b/third_party/WebKit/Source/core/inspector/InspectorResourceContentLoader.cpp index 4ab6f2cf..2842f43 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorResourceContentLoader.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorResourceContentLoader.cpp
@@ -55,7 +55,7 @@ void SetCSSStyleSheet(const String&, const KURL&, ReferrerPolicy, - const String&, + const WTF::TextEncoding&, const CSSStyleSheetResource*) override; void NotifyFinished(Resource*) override; String DebugName() const override { @@ -81,7 +81,7 @@ const String&, const KURL& url, ReferrerPolicy, - const String&, + const WTF::TextEncoding&, const CSSStyleSheetResource* resource) { ResourceFinished(const_cast<CSSStyleSheetResource*>(resource)); }
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index 450a9a1..2c398966 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -4606,6 +4606,17 @@ { "name": "storageTypes", "type": "string", "description": "Comma separated origin names." } ], "description": "Clears storage for origin." + }, + { + "name": "getUsageAndQuota", + "parameters": [ + { "name": "origin", "type": "string", "description": "Security origin." } + ], + "returns": [ + { "name": "usage", "type": "number", "description": "Storage usage (bytes)." }, + { "name": "quota", "type": "number", "description": "Storage quota (bytes)." } + ], + "description": "Returns usage and quota in bytes." } ] },
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc index a7769672..e00cfde 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
@@ -315,7 +315,7 @@ // Shape each item with the full context of the entire node. HarfBuzzShaper shaper(text_content.Characters16(), text_content.length()); - ShapeResultSpacing<StringView> spacing(text_content); + ShapeResultSpacing<String> spacing(text_content); for (auto& item : MutableData().items_) { if (item.Type() != NGInlineItem::kText) continue; @@ -325,7 +325,7 @@ &font, item.Direction(), item.StartOffset(), item.EndOffset()); if (UNLIKELY(spacing.SetSpacing(font.GetFontDescription()))) - shape_result->ApplySpacing(spacing, text_content, item.Direction()); + shape_result->ApplySpacing(spacing, item.Direction()); item.shape_result_ = std::move(shape_result); }
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc index 3bb0c20..57e63b8c 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
@@ -66,7 +66,8 @@ item_index_(0), offset_(0), break_iterator_(node.Text()), - shaper_(node.Text().Characters16(), node.Text().length()) { + shaper_(node.Text().Characters16(), node.Text().length()), + spacing_(node.Text()) { if (break_token) { item_index_ = break_token->ItemIndex(); offset_ = break_token->TextOffset(); @@ -93,7 +94,7 @@ item_results->clear(); const Vector<NGInlineItem>& items = node_.Items(); line_info->SetLineStyle(node_, !item_index_ && !offset_); - UpdateBreakIterator(line_info->LineStyle()); + SetCurrentStyle(line_info->LineStyle()); position_ = LayoutUnit(0); LineBreakState state = LineBreakState::kNotBreakable; @@ -257,7 +258,8 @@ DCHECK_EQ(item.TextShapeResult()->StartIndexForResult(), item.StartOffset()); DCHECK_EQ(item.TextShapeResult()->EndIndexForResult(), item.EndOffset()); ShapingLineBreaker breaker(&shaper_, &item.Style()->GetFont(), - item.TextShapeResult(), &break_iterator_); + item.TextShapeResult(), &break_iterator_, + &spacing_); available_width = std::max(LayoutUnit(0), available_width); item_result->shape_result = breaker.ShapeLine( item_result->start_offset, available_width, &item_result->end_offset); @@ -429,7 +431,7 @@ position_ += item_result->inline_size; } } - UpdateBreakIterator(style); + SetCurrentStyle(style); MoveToNextOf(item); } @@ -447,7 +449,7 @@ position_ += item_result->inline_size; } DCHECK(item.GetLayoutObject() && item.GetLayoutObject()->Parent()); - UpdateBreakIterator(item.GetLayoutObject()->Parent()->StyleRef()); + SetCurrentStyle(item.GetLayoutObject()->Parent()->StyleRef()); MoveToNextOf(item); } @@ -535,7 +537,7 @@ line_info->SetIsLastLine(false); } -void NGLineBreaker::UpdateBreakIterator(const ComputedStyle& style) { +void NGLineBreaker::SetCurrentStyle(const ComputedStyle& style) { auto_wrap_ = style.AutoWrap(); if (auto_wrap_) { @@ -552,6 +554,8 @@ // TODO(kojii): Implement word-wrap/overflow-wrap property } + + spacing_.SetSpacing(style.GetFontDescription()); } void NGLineBreaker::MoveToNextOf(const NGInlineItem& item) {
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h index 3db5221..16cb269 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h
@@ -9,6 +9,7 @@ #include "core/layout/ng/inline/ng_inline_item_result.h" #include "core/layout/ng/inline/ng_inline_node.h" #include "platform/fonts/shaping/HarfBuzzShaper.h" +#include "platform/fonts/shaping/ShapeResultSpacing.h" #include "platform/heap/Handle.h" #include "platform/text/TextBreakIterator.h" #include "platform/wtf/Allocator.h" @@ -78,7 +79,7 @@ void HandleOverflow(LayoutUnit available_width, NGLineInfo*); void Rewind(NGLineInfo*, unsigned new_end); - void UpdateBreakIterator(const ComputedStyle&); + void SetCurrentStyle(const ComputedStyle&); void MoveToNextOf(const NGInlineItem&); void MoveToNextOf(const NGInlineItemResult&); @@ -93,6 +94,7 @@ LayoutUnit position_; LazyLineBreakIterator break_iterator_; HarfBuzzShaper shaper_; + ShapeResultSpacing<String> spacing_; unsigned auto_wrap_ : 1; };
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_length_utils.cc b/third_party/WebKit/Source/core/layout/ng/ng_length_utils.cc index 95aa083..9e5d76a 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_length_utils.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_length_utils.cc
@@ -426,4 +426,21 @@ return length; } +NGBoxStrut GetScrollbarSizes(const LayoutObject* layout_object) { + NGPhysicalBoxStrut sizes; + const ComputedStyle* style = layout_object->Style(); + if (!style->IsOverflowVisible()) { + const LayoutBox* box = ToLayoutBox(layout_object); + LayoutUnit vertical = LayoutUnit(box->VerticalScrollbarWidth()); + LayoutUnit horizontal = LayoutUnit(box->HorizontalScrollbarHeight()); + sizes.bottom = horizontal; + if (style->ShouldPlaceBlockDirectionScrollbarOnLogicalLeft()) + sizes.left = vertical; + else + sizes.right = vertical; + } + return sizes.ConvertToLogical( + FromPlatformWritingMode(style->GetWritingMode()), style->Direction()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_length_utils.h b/third_party/WebKit/Source/core/layout/ng/ng_length_utils.h index 1b456e5..597e563 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_length_utils.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_length_utils.h
@@ -14,6 +14,7 @@ namespace blink { class ComputedStyle; +class LayoutObject; class LayoutUnit; class Length; struct MinMaxContentSize; @@ -124,6 +125,9 @@ Optional<LayoutUnit> min, Optional<LayoutUnit> max); +// Returns scrollbar sizes or this layout object. +NGBoxStrut GetScrollbarSizes(const LayoutObject*); + } // namespace blink #endif // NGLengthUtils_h
diff --git a/third_party/WebKit/Source/core/loader/TextResourceDecoderBuilder.cpp b/third_party/WebKit/Source/core/loader/TextResourceDecoderBuilder.cpp index 9c5bc49..a71f775 100644 --- a/third_party/WebKit/Source/core/loader/TextResourceDecoderBuilder.cpp +++ b/third_party/WebKit/Source/core/loader/TextResourceDecoderBuilder.cpp
@@ -104,7 +104,7 @@ const WTF::TextEncoding hint_encoding = encoding_from_domain.IsValid() ? encoding_from_domain - : settings->GetDefaultTextEncodingName(); + : WTF::TextEncoding(settings->GetDefaultTextEncodingName()); // Disable autodetection for XML to honor the default encoding (UTF-8) for // unlabelled documents. if (DOMImplementation::IsXMLMIMEType(mime_type_)) @@ -126,7 +126,7 @@ parent_frame = ToLocalFrame(frame->Tree().Parent()); if (!encoding_.IsEmpty()) { - decoder->SetEncoding(encoding_.GetString(), + decoder->SetEncoding(WTF::TextEncoding(encoding_.GetString()), TextResourceDecoder::kEncodingFromHTTPHeader); }
diff --git a/third_party/WebKit/Source/core/loader/resource/StyleSheetResourceClient.h b/third_party/WebKit/Source/core/loader/resource/StyleSheetResourceClient.h index eae489f67..518f5df 100644 --- a/third_party/WebKit/Source/core/loader/resource/StyleSheetResourceClient.h +++ b/third_party/WebKit/Source/core/loader/resource/StyleSheetResourceClient.h
@@ -46,7 +46,7 @@ virtual void SetCSSStyleSheet(const String& /* href */, const KURL& /* baseURL */, ReferrerPolicy, - const String& /* charset */, + const WTF::TextEncoding&, const CSSStyleSheetResource*) {} virtual void SetXSLStyleSheet(const String& /* href */, const KURL& /* baseURL */,
diff --git a/third_party/WebKit/Source/core/loader/resource/TextResource.cpp b/third_party/WebKit/Source/core/loader/resource/TextResource.cpp index 8eafa09d..04f9652 100644 --- a/third_party/WebKit/Source/core/loader/resource/TextResource.cpp +++ b/third_party/WebKit/Source/core/loader/resource/TextResource.cpp
@@ -16,16 +16,18 @@ const String& mime_type, const String& charset) : Resource(resource_request, type, options), - decoder_(TextResourceDecoder::Create(mime_type, charset)) {} + decoder_( + TextResourceDecoder::Create(mime_type, WTF::TextEncoding(charset))) {} TextResource::~TextResource() {} void TextResource::SetEncoding(const String& chs) { - decoder_->SetEncoding(chs, TextResourceDecoder::kEncodingFromHTTPHeader); + decoder_->SetEncoding(WTF::TextEncoding(chs), + TextResourceDecoder::kEncodingFromHTTPHeader); } -String TextResource::Encoding() const { - return decoder_->Encoding().GetName(); +WTF::TextEncoding TextResource::Encoding() const { + return decoder_->Encoding(); } String TextResource::DecodedText() const {
diff --git a/third_party/WebKit/Source/core/loader/resource/TextResource.h b/third_party/WebKit/Source/core/loader/resource/TextResource.h index 9d86945..dceb5c95c 100644 --- a/third_party/WebKit/Source/core/loader/resource/TextResource.h +++ b/third_party/WebKit/Source/core/loader/resource/TextResource.h
@@ -19,8 +19,9 @@ // call time. String DecodedText() const; - void SetEncoding(const String&) override; - String Encoding() const override; + WTF::TextEncoding Encoding() const override; + + void SetEncodingForTest(const String& encoding) { SetEncoding(encoding); } protected: TextResource(const ResourceRequest&, @@ -30,6 +31,8 @@ const String& charset); ~TextResource() override; + void SetEncoding(const String&) override; + private: std::unique_ptr<TextResourceDecoder> decoder_; };
diff --git a/third_party/WebKit/Source/core/mojo/BUILD.gn b/third_party/WebKit/Source/core/mojo/BUILD.gn index aaa52ac..202d78e 100644 --- a/third_party/WebKit/Source/core/mojo/BUILD.gn +++ b/third_party/WebKit/Source/core/mojo/BUILD.gn
@@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//mojo/public/tools/bindings/mojom.gni") import("//third_party/WebKit/Source/core/core.gni") blink_core_sources("mojo") { @@ -24,39 +23,3 @@ "//services/service_manager/public/cpp", ] } - -source_set("unit_tests") { - testonly = true - sources = [ - "tests/JsToCppTest.cpp", - ] - - data = [ - "tests/JsToCppTest.js", - ] - - configs += [ - "//third_party/WebKit/Source/core:blink_core_pch", - "//third_party/WebKit/Source:config", - "//third_party/WebKit/Source:inside_blink", - ] - - deps = [ - ":test_bindings_blink", - "//mojo/public/cpp/bindings", - "//testing/gtest", - "//third_party/WebKit/Source/core:core", - "//third_party/WebKit/Source/core:testing", - ] - - data_deps = [ - ":test_bindings", # For JS bindings: crbug.com/729649. - "//mojo/public/js:new_bindings", - ] -} - -mojom("test_bindings") { - sources = [ - "tests/JsToCpp.mojom", - ] -}
diff --git a/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.cpp b/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.cpp deleted file mode 100644 index 08411ee3..0000000 --- a/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.cpp +++ /dev/null
@@ -1,436 +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 "bindings/core/v8/ScriptController.h" -#include "bindings/core/v8/ScriptSourceCode.h" -#include "bindings/core/v8/V8BindingForCore.h" -#include "bindings/core/v8/V8BindingForTesting.h" -#include "bindings/core/v8/V8ScriptRunner.h" -#include "core/frame/Settings.h" -#include "core/mojo/MojoHandle.h" -#include "core/page/Page.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/system/wait.h" -#include "platform/testing/UnitTestHelpers.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/Source/core/mojo/tests/JsToCpp.mojom-blink.h" - -namespace blink { -namespace { - -// Global value updated by some checks to prevent compilers from optimizing -// reads out of existence. -uint32_t g_waste_accumulator = 0; - -// Negative numbers with different values in each byte, the last of -// which can survive promotion to double and back. -const int8_t kExpectedInt8Value = -65; -const int16_t kExpectedInt16Value = -16961; -const int32_t kExpectedInt32Value = -1145258561; -const int64_t kExpectedInt64Value = -77263311946305LL; - -// Positive numbers with different values in each byte, the last of -// which can survive promotion to double and back. -const uint8_t kExpectedUInt8Value = 65; -const uint16_t kExpectedUInt16Value = 16961; -const uint32_t kExpectedUInt32Value = 1145258561; -const uint64_t kExpectedUInt64Value = 77263311946305LL; - -// Double/float values, including special case constants. -const double kExpectedDoubleVal = 3.14159265358979323846; -const double kExpectedDoubleInf = std::numeric_limits<double>::infinity(); -const double kExpectedDoubleNan = std::numeric_limits<double>::quiet_NaN(); -const float kExpectedFloatVal = static_cast<float>(kExpectedDoubleVal); -const float kExpectedFloatInf = std::numeric_limits<float>::infinity(); -const float kExpectedFloatNan = std::numeric_limits<float>::quiet_NaN(); - -// NaN has the property that it is not equal to itself. -#define EXPECT_NAN(x) EXPECT_NE(x, x) - -String MojoBindingsScriptPath() { - String filepath = testing::ExecutableDir(); - filepath.append("/gen/mojo/public/js/mojo_bindings.js"); - return filepath; -} - -String TestBindingsScriptPath() { - String filepath = testing::ExecutableDir(); - filepath.append( - "/gen/third_party/WebKit/Source/core/mojo/tests/JsToCpp.mojom.js"); - return filepath; -} - -String TestScriptPath() { - String filepath = testing::BlinkRootDir(); - filepath.append("/Source/core/mojo/tests/JsToCppTest.js"); - return filepath; -} - -v8::Local<v8::Value> ExecuteScript(const String& script_path, - LocalFrame& frame) { - RefPtr<SharedBuffer> script_src = testing::ReadFromFile(script_path); - return frame.GetScriptController().ExecuteScriptInMainWorldAndReturnValue( - ScriptSourceCode(String(script_src->Data(), script_src->size()))); -} - -void CheckDataPipe(mojo::DataPipeConsumerHandle data_pipe_handle) { - MojoResult result = Wait(data_pipe_handle, MOJO_HANDLE_SIGNAL_READABLE); - EXPECT_EQ(MOJO_RESULT_OK, result); - - const void* buffer = nullptr; - unsigned num_bytes = 0; - result = BeginReadDataRaw(data_pipe_handle, &buffer, &num_bytes, - MOJO_READ_DATA_FLAG_NONE); - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(64u, num_bytes); - for (unsigned i = 0; i < num_bytes; ++i) { - EXPECT_EQ(i, static_cast<unsigned>(static_cast<const char*>(buffer)[i])); - } - EndReadDataRaw(data_pipe_handle, num_bytes); -} - -void CheckMessagePipe(mojo::MessagePipeHandle message_pipe_handle) { - MojoResult result = Wait(message_pipe_handle, MOJO_HANDLE_SIGNAL_READABLE); - EXPECT_EQ(MOJO_RESULT_OK, result); - - std::vector<uint8_t> bytes; - std::vector<mojo::ScopedHandle> handles; - result = ReadMessageRaw(message_pipe_handle, &bytes, &handles, 0); - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(64u, bytes.size()); - for (int i = 0; i < 64; ++i) { - EXPECT_EQ(255 - i, bytes[i]); - } -} - -js_to_cpp::blink::EchoArgsPtr BuildSampleEchoArgs() { - auto args = js_to_cpp::blink::EchoArgs::New(); - args->si64 = kExpectedInt64Value; - args->si32 = kExpectedInt32Value; - args->si16 = kExpectedInt16Value; - args->si8 = kExpectedInt8Value; - args->ui64 = kExpectedUInt64Value; - args->ui32 = kExpectedUInt32Value; - args->ui16 = kExpectedUInt16Value; - args->ui8 = kExpectedUInt8Value; - args->float_val = kExpectedFloatVal; - args->float_inf = kExpectedFloatInf; - args->float_nan = kExpectedFloatNan; - args->double_val = kExpectedDoubleVal; - args->double_inf = kExpectedDoubleInf; - args->double_nan = kExpectedDoubleNan; - args->name = "coming"; - args->string_array.emplace(3); - (*args->string_array)[0] = "one"; - (*args->string_array)[1] = "two"; - (*args->string_array)[2] = "three"; - return args; -} - -void CheckSampleEchoArgs(const js_to_cpp::blink::EchoArgsPtr& arg) { - EXPECT_EQ(kExpectedInt64Value, arg->si64); - EXPECT_EQ(kExpectedInt32Value, arg->si32); - EXPECT_EQ(kExpectedInt16Value, arg->si16); - EXPECT_EQ(kExpectedInt8Value, arg->si8); - EXPECT_EQ(kExpectedUInt64Value, arg->ui64); - EXPECT_EQ(kExpectedUInt32Value, arg->ui32); - EXPECT_EQ(kExpectedUInt16Value, arg->ui16); - EXPECT_EQ(kExpectedUInt8Value, arg->ui8); - EXPECT_EQ(kExpectedFloatVal, arg->float_val); - EXPECT_EQ(kExpectedFloatInf, arg->float_inf); - EXPECT_NAN(arg->float_nan); - EXPECT_EQ(kExpectedDoubleVal, arg->double_val); - EXPECT_EQ(kExpectedDoubleInf, arg->double_inf); - EXPECT_NAN(arg->double_nan); - EXPECT_EQ(String("coming"), arg->name); - EXPECT_EQ(String("one"), (*arg->string_array)[0]); - EXPECT_EQ(String("two"), (*arg->string_array)[1]); - EXPECT_EQ(String("three"), (*arg->string_array)[2]); - CheckDataPipe(arg->data_handle.get()); - CheckMessagePipe(arg->message_handle.get()); -} - -void CheckSampleEchoArgsList(const js_to_cpp::blink::EchoArgsListPtr& list) { - if (list.is_null()) - return; - CheckSampleEchoArgs(list->item); - CheckSampleEchoArgsList(list->next); -} - -// More forgiving checks are needed in the face of potentially corrupt -// messages. The values don't matter so long as all accesses are within -// bounds. -void CheckCorruptedString(const String& arg) { - for (size_t i = 0; i < arg.length(); ++i) - g_waste_accumulator += arg[i]; -} - -void CheckCorruptedStringArray(const Optional<Vector<String>>& string_array) { - if (!string_array) - return; - for (size_t i = 0; i < string_array->size(); ++i) - CheckCorruptedString((*string_array)[i]); -} - -void CheckCorruptedDataPipe(mojo::DataPipeConsumerHandle data_pipe_handle) { - unsigned char buffer[100]; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - MojoResult result = ReadDataRaw(data_pipe_handle, buffer, &buffer_size, - MOJO_READ_DATA_FLAG_NONE); - if (result != MOJO_RESULT_OK) - return; - for (uint32_t i = 0; i < buffer_size; ++i) - g_waste_accumulator += buffer[i]; -} - -void CheckCorruptedMessagePipe(mojo::MessagePipeHandle message_pipe_handle) { - std::vector<uint8_t> bytes; - std::vector<mojo::ScopedHandle> handles; - MojoResult result = ReadMessageRaw(message_pipe_handle, &bytes, &handles, 0); - if (result != MOJO_RESULT_OK) - return; - for (uint32_t i = 0; i < bytes.size(); ++i) - g_waste_accumulator += bytes[i]; -} - -void CheckCorruptedEchoArgs(const js_to_cpp::blink::EchoArgsPtr& arg) { - if (arg.is_null()) - return; - CheckCorruptedString(arg->name); - CheckCorruptedStringArray(arg->string_array); - if (arg->data_handle.is_valid()) - CheckCorruptedDataPipe(arg->data_handle.get()); - if (arg->message_handle.is_valid()) - CheckCorruptedMessagePipe(arg->message_handle.get()); -} - -void CheckCorruptedEchoArgsList(const js_to_cpp::blink::EchoArgsListPtr& list) { - if (list.is_null()) - return; - CheckCorruptedEchoArgs(list->item); - CheckCorruptedEchoArgsList(list->next); -} - -// Base Provider implementation class. It's expected that tests subclass and -// override the appropriate Provider functions. When test is done quit the -// run_loop(). -class CppSideConnection : public js_to_cpp::blink::CppSide { - public: - CppSideConnection() : mishandled_messages_(0), binding_(this) {} - ~CppSideConnection() override {} - - void set_js_side(js_to_cpp::blink::JsSidePtr js_side) { - js_side_ = std::move(js_side); - } - js_to_cpp::blink::JsSide* js_side() { return js_side_.get(); } - - void Bind(mojo::InterfaceRequest<js_to_cpp::blink::CppSide> request) { - binding_.Bind(std::move(request)); - // Keep the pipe open even after validation errors. - binding_.EnableTestingMode(); - } - - // js_to_cpp::CppSide: - void StartTest() override { NOTREACHED(); } - - void TestFinished() override { NOTREACHED(); } - - void PingResponse() override { mishandled_messages_ += 1; } - - void EchoResponse(js_to_cpp::blink::EchoArgsListPtr list) override { - mishandled_messages_ += 1; - } - - void BitFlipResponse( - js_to_cpp::blink::EchoArgsListPtr list, - js_to_cpp::blink::ForTestingAssociatedPtrInfo not_used) override { - mishandled_messages_ += 1; - } - - void BackPointerResponse(js_to_cpp::blink::EchoArgsListPtr list) override { - mishandled_messages_ += 1; - } - - protected: - js_to_cpp::blink::JsSidePtr js_side_; - int mishandled_messages_; - mojo::Binding<js_to_cpp::blink::CppSide> binding_; -}; - -// Trivial test to verify a message sent from JS is received. -class PingCppSideConnection : public CppSideConnection { - public: - PingCppSideConnection() : got_message_(false) {} - ~PingCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { js_side_->Ping(); } - - void PingResponse() override { - got_message_ = true; - testing::ExitRunLoop(); - } - - bool DidSucceed() { return got_message_ && !mishandled_messages_; } - - private: - bool got_message_; -}; - -// Test that parameters are passed with correct values. -class EchoCppSideConnection : public CppSideConnection { - public: - EchoCppSideConnection() : message_count_(0), termination_seen_(false) {} - ~EchoCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { - js_side_->Echo(kExpectedMessageCount, BuildSampleEchoArgs()); - } - - void EchoResponse(js_to_cpp::blink::EchoArgsListPtr list) override { - message_count_ += 1; - - const js_to_cpp::blink::EchoArgsPtr& special_arg = list->item; - EXPECT_EQ(-1, special_arg->si64); - EXPECT_EQ(-1, special_arg->si32); - EXPECT_EQ(-1, special_arg->si16); - EXPECT_EQ(-1, special_arg->si8); - EXPECT_EQ(String("going"), special_arg->name); - CheckDataPipe(special_arg->data_handle.get()); - CheckMessagePipe(special_arg->message_handle.get()); - - CheckSampleEchoArgsList(list->next); - } - - void TestFinished() override { - termination_seen_ = true; - testing::ExitRunLoop(); - } - - bool DidSucceed() { - return termination_seen_ && !mishandled_messages_ && - message_count_ == kExpectedMessageCount; - } - - private: - static const int kExpectedMessageCount = 10; - int message_count_; - bool termination_seen_; -}; - -// Test that corrupted messages don't wreak havoc. -class BitFlipCppSideConnection : public CppSideConnection { - public: - BitFlipCppSideConnection() : termination_seen_(false) {} - ~BitFlipCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { js_side_->BitFlip(BuildSampleEchoArgs()); } - - void BitFlipResponse( - js_to_cpp::blink::EchoArgsListPtr list, - js_to_cpp::blink::ForTestingAssociatedPtrInfo not_used) override { - CheckCorruptedEchoArgsList(list); - } - - void TestFinished() override { - termination_seen_ = true; - testing::ExitRunLoop(); - } - - bool DidSucceed() { return termination_seen_; } - - private: - bool termination_seen_; -}; - -// Test that severely random messages don't wreak havoc. -class BackPointerCppSideConnection : public CppSideConnection { - public: - BackPointerCppSideConnection() : termination_seen_(false) {} - ~BackPointerCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { js_side_->BackPointer(BuildSampleEchoArgs()); } - - void BackPointerResponse(js_to_cpp::blink::EchoArgsListPtr list) override { - CheckCorruptedEchoArgsList(list); - } - - void TestFinished() override { - termination_seen_ = true; - testing::ExitRunLoop(); - } - - bool DidSucceed() { return termination_seen_; } - - private: - bool termination_seen_; -}; - -class JsToCppTest : public ::testing::Test { - public: - void RunTest(CppSideConnection* cpp_side) { - js_to_cpp::blink::CppSidePtr cpp_side_ptr; - cpp_side->Bind(MakeRequest(&cpp_side_ptr)); - - js_to_cpp::blink::JsSidePtr js_side_ptr; - auto js_side_request = MakeRequest(&js_side_ptr); - js_side_ptr->SetCppSide(std::move(cpp_side_ptr)); - cpp_side->set_js_side(std::move(js_side_ptr)); - - V8TestingScope scope; - scope.GetPage().GetSettings().SetScriptEnabled(true); - ExecuteScript(MojoBindingsScriptPath(), scope.GetFrame()); - ExecuteScript(TestBindingsScriptPath(), scope.GetFrame()); - - v8::Local<v8::Value> start_fn = - ExecuteScript(TestScriptPath(), scope.GetFrame()); - ASSERT_FALSE(start_fn.IsEmpty()); - ASSERT_TRUE(start_fn->IsFunction()); - v8::Local<v8::Object> global_proxy = scope.GetContext()->Global(); - v8::Local<v8::Value> args[1] = { - ToV8(MojoHandle::Create( - mojo::ScopedHandle::From(js_side_request.PassMessagePipe())), - global_proxy, scope.GetIsolate())}; - V8ScriptRunner::CallFunction( - start_fn.As<v8::Function>(), scope.GetExecutionContext(), global_proxy, - WTF_ARRAY_LENGTH(args), args, scope.GetIsolate()); - testing::EnterRunLoop(); - } -}; - -TEST_F(JsToCppTest, Ping) { - PingCppSideConnection cpp_side_connection; - RunTest(&cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -TEST_F(JsToCppTest, Echo) { - EchoCppSideConnection cpp_side_connection; - RunTest(&cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -TEST_F(JsToCppTest, BitFlip) { - // These tests generate a lot of expected validation errors. Suppress logging. - mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression; - - BitFlipCppSideConnection cpp_side_connection; - RunTest(&cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -TEST_F(JsToCppTest, BackPointer) { - // These tests generate a lot of expected validation errors. Suppress logging. - mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression; - - BackPointerCppSideConnection cpp_side_connection; - RunTest(&cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -} // namespace -} // namespace blink
diff --git a/third_party/WebKit/Source/core/mojo/tests/OWNERS b/third_party/WebKit/Source/core/mojo/tests/OWNERS deleted file mode 100644 index 08850f4..0000000 --- a/third_party/WebKit/Source/core/mojo/tests/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp b/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp index 9b69143..b059b5a7 100644 --- a/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp +++ b/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp
@@ -26,10 +26,6 @@ return; GraphicsContext& context = info.context; - // https://bugs.chromium.org/p/skia/issues/detail?id=237 - if (context.Printing()) - return; - FloatRoundedRect border = style.GetRoundedBorderFor( paint_rect, include_logical_left_edge, include_logical_right_edge); @@ -153,10 +149,6 @@ DCHECK(style.BoxShadow()); GraphicsContext& context = info.context; - // https://bugs.chromium.org/p/skia/issues/detail?id=237 - if (context.Printing()) - return; - bool is_horizontal = style.IsHorizontalWritingMode(); GraphicsContextStateSaver state_saver(context, false);
diff --git a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp index 3cfe7ca..91c57c6 100644 --- a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp +++ b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
@@ -4,7 +4,6 @@ #include "core/paint/InlineTextBoxPainter.h" -#include "core/editing/CompositionUnderline.h" #include "core/editing/Editor.h" #include "core/editing/markers/CompositionMarker.h" #include "core/editing/markers/DocumentMarkerController.h" @@ -539,15 +538,14 @@ return true; } -unsigned InlineTextBoxPainter::UnderlinePaintStart( - const CompositionUnderline& underline) { +unsigned InlineTextBoxPainter::MarkerPaintStart(const DocumentMarker& marker) { DCHECK(inline_text_box_.Truncation() != kCFullTruncation); DCHECK(inline_text_box_.Len()); // Start painting at the beginning of the text or the specified underline // start offset, whichever is higher. unsigned paint_start = - std::max(inline_text_box_.Start(), underline.StartOffset()); + std::max(inline_text_box_.Start(), marker.StartOffset()); // Cap the maximum paint start to (if no truncation) the last character, // else the last character before the truncation ellipsis. return std::min(paint_start, (inline_text_box_.Truncation() == kCNoTruncation) @@ -556,8 +554,7 @@ inline_text_box_.Truncation() - 1); } -unsigned InlineTextBoxPainter::UnderlinePaintEnd( - const CompositionUnderline& underline) { +unsigned InlineTextBoxPainter::MarkerPaintEnd(const DocumentMarker& marker) { DCHECK(inline_text_box_.Truncation() != kCFullTruncation); DCHECK(inline_text_box_.Len()); @@ -565,7 +562,7 @@ // offset, whichever is lower. unsigned paint_end = std::min( inline_text_box_.end() + 1, - underline.EndOffset()); // end() points at the last char, not past it. + marker.EndOffset()); // end() points at the last char, not past it. // Cap the maximum paint end to (if no truncation) one past the last // character, else one past the last character before the truncation // ellipsis. @@ -575,7 +572,7 @@ inline_text_box_.Truncation()); } -void InlineTextBoxPainter::PaintSingleCompositionBackgroundRun( +void InlineTextBoxPainter::PaintSingleMarkerBackgroundRun( GraphicsContext& context, const LayoutPoint& box_origin, const ComputedStyle& style, @@ -679,17 +676,16 @@ case DocumentMarker::kComposition: case DocumentMarker::kActiveSuggestion: { const StyleableMarker& styleable_marker = ToStyleableMarker(marker); - CompositionUnderline underline( - styleable_marker.StartOffset(), styleable_marker.EndOffset(), - styleable_marker.UnderlineColor(), styleable_marker.IsThick(), - styleable_marker.BackgroundColor()); - if (marker_paint_phase == DocumentMarkerPaintPhase::kBackground) - PaintSingleCompositionBackgroundRun( - paint_info.context, box_origin, style, font, - underline.BackgroundColor(), UnderlinePaintStart(underline), - UnderlinePaintEnd(underline)); - else - PaintCompositionUnderline(paint_info.context, box_origin, underline); + if (marker_paint_phase == DocumentMarkerPaintPhase::kBackground) { + PaintSingleMarkerBackgroundRun(paint_info.context, box_origin, style, + font, + styleable_marker.BackgroundColor(), + MarkerPaintStart(styleable_marker), + MarkerPaintEnd(styleable_marker)); + } else { + PaintStyleableMarkerUnderline(paint_info.context, box_origin, + styleable_marker); + } } break; default: NOTREACHED(); @@ -1034,18 +1030,18 @@ rect.Expand(outsets); } -void InlineTextBoxPainter::PaintCompositionUnderline( +void InlineTextBoxPainter::PaintStyleableMarkerUnderline( GraphicsContext& context, const LayoutPoint& box_origin, - const CompositionUnderline& underline) { - if (underline.GetColor() == Color::kTransparent) + const StyleableMarker& marker) { + if (marker.UnderlineColor() == Color::kTransparent) return; if (inline_text_box_.Truncation() == kCFullTruncation) return; - unsigned paint_start = UnderlinePaintStart(underline); - unsigned paint_end = UnderlinePaintEnd(underline); + unsigned paint_start = MarkerPaintStart(marker); + unsigned paint_end = MarkerPaintEnd(marker); DCHECK_LT(paint_start, paint_end); // start of line to draw @@ -1098,7 +1094,7 @@ .PrimaryFont(); DCHECK(font_data); int baseline = font_data ? font_data->GetFontMetrics().Ascent() : 0; - if (underline.Thick() && inline_text_box_.LogicalHeight() - baseline >= 2) + if (marker.IsThick() && inline_text_box_.LogicalHeight() - baseline >= 2) line_thickness = 2; // We need to have some space between underlines of subsequent clauses, @@ -1108,7 +1104,7 @@ start += 1; width -= 2; - context.SetStrokeColor(underline.GetColor()); + context.SetStrokeColor(marker.UnderlineColor()); context.SetStrokeThickness(line_thickness); context.DrawLineForText( FloatPoint(
diff --git a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.h b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.h index 9b80871..814f35f4 100644 --- a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.h +++ b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.h
@@ -14,7 +14,6 @@ struct PaintInfo; class Color; -class CompositionUnderline; class ComputedStyle; class DocumentMarker; class Font; @@ -23,6 +22,7 @@ class LayoutObject; class LayoutPoint; class LayoutTextCombine; +class StyleableMarker; class TextMatchMarker; enum class DocumentMarkerPaintPhase { kForeground, kBackground }; @@ -62,13 +62,13 @@ private: enum class PaintOptions { kNormal, kCombinedText }; - void PaintSingleCompositionBackgroundRun(GraphicsContext&, - const LayoutPoint& box_origin, - const ComputedStyle&, - const Font&, - Color background_color, - int start_pos, - int end_pos); + void PaintSingleMarkerBackgroundRun(GraphicsContext&, + const LayoutPoint& box_origin, + const ComputedStyle&, + const Font&, + Color background_color, + int start_pos, + int end_pos); template <PaintOptions> void PaintSelection(GraphicsContext&, const LayoutRect& box_rect, @@ -77,11 +77,11 @@ Color text_color, LayoutTextCombine* = nullptr); - void PaintCompositionUnderline(GraphicsContext&, - const LayoutPoint& box_origin, - const CompositionUnderline&); - unsigned UnderlinePaintStart(const CompositionUnderline&); - unsigned UnderlinePaintEnd(const CompositionUnderline&); + void PaintStyleableMarkerUnderline(GraphicsContext&, + const LayoutPoint& box_origin, + const StyleableMarker&); + unsigned MarkerPaintStart(const DocumentMarker&); + unsigned MarkerPaintEnd(const DocumentMarker&); bool ShouldPaintTextBox(const PaintInfo&); void ExpandToIncludeNewlineForSelection(LayoutRect&); LayoutObject& InlineLayoutObject() const;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp index 34436a65..321a433 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -1317,6 +1317,8 @@ } PaintLayer* PaintLayer::RemoveChild(PaintLayer* old_child) { + old_child->MarkCompositingContainerChainForNeedsRepaint(); + if (old_child->PreviousSibling()) old_child->PreviousSibling()->SetNextSibling(old_child->NextSibling()); if (old_child->NextSibling()) @@ -1361,8 +1363,6 @@ if (old_child->EnclosingPaginationLayer()) old_child->ClearPaginationRecursive(); - SetNeedsRepaint(); - return old_child; }
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp index b34af85..c9be82e 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
@@ -1090,4 +1090,33 @@ GetDocument().View()->UpdateAllLifecyclePhases(); } +TEST_P(PaintLayerTest, NeedsRepaintOnRemovingStackedLayer) { + EnableCompositing(); + SetBodyInnerHTML( + "<style>body {margin-top: 200px; backface-visibility: hidden}</style>" + "<div id='target' style='position: absolute; top: 0'>Text</div>"); + + auto* body = GetDocument().body(); + auto* body_layer = body->GetLayoutBox()->Layer(); + auto* target_element = GetDocument().getElementById("target"); + auto* target_object = target_element->GetLayoutObject(); + auto* target_layer = ToLayoutBoxModelObject(target_object)->Layer(); + + // |container| is not the CompositingContainer of |target| because |target| + // is stacked but |container| is not a stacking context. + EXPECT_TRUE(target_layer->StackingNode()->IsStacked()); + EXPECT_NE(body_layer, target_layer->CompositingContainer()); + auto* old_compositing_container = target_layer->CompositingContainer(); + + body->setAttribute(HTMLNames::styleAttr, "margin-top: 0"); + target_element->setAttribute(HTMLNames::styleAttr, "top: 0"); + GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); + + EXPECT_FALSE(target_object->HasLayer()); + EXPECT_TRUE(body_layer->NeedsRepaint()); + EXPECT_TRUE(old_compositing_container->NeedsRepaint()); + + GetDocument().View()->UpdateAllLifecyclePhases(); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h index 82bac06..e45f1b5 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.h +++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -1512,24 +1512,6 @@ } void SetTextDecoration(TextDecoration v) { SetTextDecorationInternal(v); } - // text-decoration-color - void SetTextDecorationColor(const StyleColor& c) { - SET_VAR(rare_non_inherited_data_, text_decoration_color_, c); - } - - // text-decoration-style - static ETextDecorationStyle InitialTextDecorationStyle() { - return ETextDecorationStyle::kSolid; - } - ETextDecorationStyle TextDecorationStyle() const { - return static_cast<ETextDecorationStyle>( - rare_non_inherited_data_->text_decoration_style_); - } - void SetTextDecorationStyle(ETextDecorationStyle v) { - SET_VAR(rare_non_inherited_data_, text_decoration_style_, - static_cast<unsigned>(v)); - } - // text-decoration-skip static TextDecorationSkip InitialTextDecorationSkip() { return TextDecorationSkip::kObjects; @@ -1541,16 +1523,6 @@ SetTextDecorationSkipInternal(v); } - // text-overflow - static ETextOverflow InitialTextOverflow() { return ETextOverflow::kClip; } - ETextOverflow TextOverflow() const { - return static_cast<ETextOverflow>(rare_non_inherited_data_->text_overflow_); - } - void SetTextOverflow(ETextOverflow overflow) { - SET_VAR(rare_non_inherited_data_, text_overflow_, - static_cast<unsigned>(overflow)); - } - // touch-action static TouchAction InitialTouchAction() { return TouchAction::kTouchActionAuto; @@ -3455,9 +3427,6 @@ return rare_non_inherited_data_->multi_col_data_ ->visited_link_column_rule_color_; } - StyleColor TextDecorationColor() const { - return rare_non_inherited_data_->text_decoration_color_; - } StyleColor VisitedLinkTextDecorationColor() const { return rare_non_inherited_data_->visited_link_text_decoration_color_; }
diff --git a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h index c3447f4..f90fa53f 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h +++ b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
@@ -193,8 +193,6 @@ static_cast<unsigned>(b)); } -enum class ETextDecorationStyle { kSolid, kDouble, kDotted, kDashed, kWavy }; - static const size_t kTextDecorationSkipBits = 3; enum class TextDecorationSkip { kNone = 0x0, kObjects = 0x1, kInk = 0x2 }; inline TextDecorationSkip operator&(TextDecorationSkip a, @@ -232,8 +230,6 @@ kCustom }; -enum class ETextOverflow : unsigned { kClip, kEllipsis }; - static const size_t kGridAutoFlowBits = 4; enum InternalGridAutoFlowAlgorithm { kInternalAutoFlowAlgorithmSparse = 0x1,
diff --git a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp index ad26ca3..d6bee49e 100644 --- a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp
@@ -179,11 +179,12 @@ return; if (!decoder_) { - if (!response_encoding_.IsEmpty()) - decoder_ = - TextResourceDecoder::Create("text/javascript", response_encoding_); - else - decoder_ = TextResourceDecoder::Create("text/javascript", "UTF-8"); + if (!response_encoding_.IsEmpty()) { + decoder_ = TextResourceDecoder::Create( + "text/javascript", WTF::TextEncoding(response_encoding_)); + } else { + decoder_ = TextResourceDecoder::Create("text/javascript", UTF8Encoding()); + } } if (!len)
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp index 624a05b..ad9014f1 100644 --- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp +++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -1710,10 +1710,12 @@ std::unique_ptr<TextResourceDecoder> XMLHttpRequest::CreateDecoder() const { if (response_type_code_ == kResponseTypeJSON) - return TextResourceDecoder::Create("application/json", "UTF-8"); + return TextResourceDecoder::Create("application/json", UTF8Encoding()); - if (!final_response_charset_.IsEmpty()) - return TextResourceDecoder::Create("text/plain", final_response_charset_); + if (!final_response_charset_.IsEmpty()) { + return TextResourceDecoder::Create( + "text/plain", WTF::TextEncoding(final_response_charset_)); + } // allow TextResourceDecoder to look inside the m_response if it's XML or HTML if (ResponseIsXML()) { @@ -1728,9 +1730,9 @@ } if (ResponseIsHTML()) - return TextResourceDecoder::Create("text/html", "UTF-8"); + return TextResourceDecoder::Create("text/html", UTF8Encoding()); - return TextResourceDecoder::Create("text/plain", "UTF-8"); + return TextResourceDecoder::Create("text/plain", UTF8Encoding()); } void XMLHttpRequest::DidReceiveData(const char* data, unsigned len) {
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn index 16e167a20..ed73390 100644 --- a/third_party/WebKit/Source/devtools/BUILD.gn +++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -371,6 +371,7 @@ "front_end/object_ui/ObjectPropertiesSection.js", "front_end/object_ui/objectValue.css", "front_end/object_ui/RemoteObjectPreviewFormatter.js", + "front_end/perf_ui/chartViewport.css", "front_end/perf_ui/ChartViewport.js", "front_end/perf_ui/filmStripDialog.css", "front_end/perf_ui/filmStripView.css",
diff --git a/third_party/WebKit/Source/devtools/front_end/help/Help.js b/third_party/WebKit/Source/devtools/front_end/help/Help.js index fa39639..67316d5 100644 --- a/third_party/WebKit/Source/devtools/front_end/help/Help.js +++ b/third_party/WebKit/Source/devtools/front_end/help/Help.js
@@ -33,6 +33,10 @@ * @param {number} latestVersion */ Help._showReleaseNoteIfNeeded = function(lastSeenVersion, latestVersion) { + if (!lastSeenVersion) { + Help.releaseNoteVersionSetting().set(latestVersion); + return; + } if (lastSeenVersion >= latestVersion) return; Help.releaseNoteVersionSetting().set(latestVersion);
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/ChartViewport.js b/third_party/WebKit/Source/devtools/front_end/perf_ui/ChartViewport.js index 22f3335..21633d5 100644 --- a/third_party/WebKit/Source/devtools/front_end/perf_ui/ChartViewport.js +++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/ChartViewport.js
@@ -3,15 +3,48 @@ // found in the LICENSE file. /** + * @interface + */ +PerfUI.ChartViewportDelegate = function() {}; + +PerfUI.ChartViewportDelegate.prototype = { + /** + * @param {number} startTime + * @param {number} endTime + */ + requestWindowTimes(startTime, endTime) {}, + + /** + * @param {number} startTime + * @param {number} endTime + */ + updateRangeSelection(startTime, endTime) {}, + + /** + * @param {number} width + * @param {number} height + */ + setSize(width, height) {}, + + update() {} +}; + +/** * @unrestricted */ PerfUI.ChartViewport = class extends UI.VBox { - constructor() { - super(true); + /** + * @param {!PerfUI.ChartViewportDelegate} delegate + */ + constructor(delegate) { + super(); + this.registerRequiredCSS('perf_ui/chartViewport.css'); + + this._delegate = delegate; this.viewportElement = this.contentElement.createChild('div', 'fill'); this.viewportElement.addEventListener('mousemove', this._updateCursorPosition.bind(this), false); - this.viewportElement.addEventListener('mouseout', this._showCursor.bind(this, false), false); + this.viewportElement.addEventListener('mouseout', this._onMouseOut.bind(this), false); this.viewportElement.addEventListener('mousewheel', this._onMouseWheel.bind(this), false); this.viewportElement.addEventListener('keydown', this._onChartKeyDown.bind(this), false); this.viewportElement.addEventListener('keyup', this._onChartKeyUp.bind(this), false); @@ -24,11 +57,11 @@ this._endRangeSelection.bind(this), 'text', null); this._alwaysShowVerticalScroll = false; - this._vScrollElement = this.contentElement.createChild('div', 'flame-chart-v-scroll'); + this._vScrollElement = this.contentElement.createChild('div', 'chart-viewport-v-scroll'); this._vScrollContent = this._vScrollElement.createChild('div'); this._vScrollElement.addEventListener('scroll', this._onScroll.bind(this), false); - this._selectionOverlay = this.contentElement.createChild('div', 'flame-chart-selection-overlay hidden'); + this._selectionOverlay = this.contentElement.createChild('div', 'chart-viewport-selection-overlay hidden'); this._selectedTimeSpanLabel = this._selectionOverlay.createChild('div', 'time-span'); this._cursorElement = this.contentElement.createChild('div', 'chart-cursor-element hidden'); @@ -56,9 +89,6 @@ return [this._vScrollElement]; } - /** - * @private - */ _updateScrollBar() { const showScroll = this._alwaysShowVerticalScroll || this._totalHeight > this._offsetHeight; if (this._vScrollElement.classList.contains('hidden') !== showScroll) @@ -95,17 +125,18 @@ this._updateContentElementSize(); } - /** - * @private - */ _updateContentElementSize() { var offsetWidth = this._vScrollElement.offsetLeft; if (!offsetWidth) offsetWidth = this.contentElement.offsetWidth; this._offsetWidth = offsetWidth; this._offsetHeight = this.contentElement.offsetHeight; + this._delegate.setSize(this._offsetWidth, this._offsetHeight); } + /** + * @param {number} totalHeight + */ setContentHeight(totalHeight) { this._totalHeight = totalHeight; this._vScrollContent.style.height = totalHeight + 'px'; @@ -131,26 +162,31 @@ /** * @return {number} */ - getScrollOffset() { + scrollOffset() { return this._vScrollElement.scrollTop; } /** + * @param {number} zeroTime + * @param {number} totalTime + */ + setBoundaries(zeroTime, totalTime) { + this._minimumBoundary = zeroTime; + this._totalTime = totalTime; + } + + /** * @param {!Event} e - * @private */ _onMouseWheel(e) { - if (!this._enabled()) - return; var doZoomInstead = e.shiftKey ^ (Common.moduleSetting('flamechartMouseWheelAction').get() === 'zoom'); var panVertically = !doZoomInstead && (e.wheelDeltaY || Math.abs(e.wheelDeltaX) === 120); var panHorizontally = doZoomInstead && Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY); if (panVertically) { this._vScrollElement.scrollTop -= (e.wheelDeltaY || e.wheelDeltaX) / 120 * this._offsetHeight / 8; } else if (panHorizontally) { - var shift = -e.wheelDeltaX * this._pixelToTime; this._muteAnimation = true; - this._handlePanGesture(shift); + this._handlePanGesture(-e.wheelDeltaX); this._muteAnimation = false; } else { // Zoom. const mouseWheelZoomSpeed = 1 / 120; @@ -168,15 +204,11 @@ _startDragging(event) { if (event.shiftKey) return false; - if (this._windowRight === Infinity) - return false; this._isDragging = true; - this._initMaxDragOffset(event); this._dragStartPointX = event.pageX; this._dragStartPointY = event.pageY; this._dragStartScrollTop = this._vScrollElement.scrollTop; this.viewportElement.style.cursor = ''; - this.hideHighlight(); return true; } @@ -187,60 +219,24 @@ var pixelShift = this._dragStartPointX - event.pageX; this._dragStartPointX = event.pageX; this._muteAnimation = true; - this._handlePanGesture(pixelShift * this._pixelToTime); + this._handlePanGesture(pixelShift); this._muteAnimation = false; var pixelScroll = this._dragStartPointY - event.pageY; this._vScrollElement.scrollTop = this._dragStartScrollTop + pixelScroll; - this._updateMaxDragOffset(event.pageX, event.pageY); } - /** - * @private - */ _endDragging() { this._isDragging = false; - this._updateHighlight(); } /** * @param {!MouseEvent} event - * @private - */ - _initMaxDragOffset(event) { - this._maxDragOffsetSquared = 0; - this._dragStartX = event.pageX; - this._dragStartY = event.pageY; - } - - /** - * @param {number} x - * @param {number} y - * @private - */ - _updateMaxDragOffset(x, y) { - var dx = x - this._dragStartX; - var dy = y - this._dragStartY; - var dragOffsetSquared = dx * dx + dy * dy; - this._maxDragOffsetSquared = Math.max(this._maxDragOffsetSquared, dragOffsetSquared); - } - - /** - * @return {number} - */ - maxDragOffset() { - return Math.sqrt(this._maxDragOffsetSquared); - } - - /** - * @param {!MouseEvent} event - * @private * @return {boolean} */ _startRangeSelection(event) { if (!event.shiftKey) return false; this._isDragging = true; - this._initMaxDragOffset(event); this._selectionOffsetShiftX = event.offsetX - event.pageX; this._selectionOffsetShiftY = event.offsetY - event.pageY; this._selectionStartX = event.offsetX; @@ -249,16 +245,11 @@ style.width = '1px'; this._selectedTimeSpanLabel.textContent = ''; this._selectionOverlay.classList.remove('hidden'); - this.hideHighlight(); return true; } - /** - * @private - */ _endRangeSelection() { this._isDragging = false; - this._updateHighlight(); } hideRangeSelection() { @@ -267,26 +258,21 @@ /** * @param {!MouseEvent} event - * @private */ _rangeSelectionDragging(event) { - this._updateMaxDragOffset(event.pageX, event.pageY); var x = Number.constrain(event.pageX + this._selectionOffsetShiftX, 0, this._offsetWidth); - var start = this._cursorTime(this._selectionStartX); - var end = this._cursorTime(x); + var start = this.pixelToTime(this._selectionStartX); + var end = this.pixelToTime(x); this._rangeSelectionStart = Math.min(start, end); this._rangeSelectionEnd = Math.max(start, end); this._updateRangeSelectionOverlay(); - this._flameChartDelegate.updateRangeSelection(this._rangeSelectionStart, this._rangeSelectionEnd); + this._delegate.updateRangeSelection(this._rangeSelectionStart, this._rangeSelectionEnd); } - /** - * @private - */ _updateRangeSelectionOverlay() { var /** @const */ margin = 100; - var left = Number.constrain(this._timeToPosition(this._rangeSelectionStart), -margin, this._offsetWidth + margin); - var right = Number.constrain(this._timeToPosition(this._rangeSelectionEnd), -margin, this._offsetWidth + margin); + var left = Number.constrain(this.timeToPosition(this._rangeSelectionStart), -margin, this._offsetWidth + margin); + var right = Number.constrain(this.timeToPosition(this._rangeSelectionEnd), -margin, this._offsetWidth + margin); var style = this._selectionOverlay.style; style.left = left + 'px'; style.width = (right - left) + 'px'; @@ -294,20 +280,48 @@ this._selectedTimeSpanLabel.textContent = Number.preciseMillisToString(timeSpan, 2); } - /** - * @private - */ _onScroll() { this._scrollTop = this._vScrollElement.scrollTop; this.scheduleUpdate(); } + _onMouseOut() { + this._lastMouseOffsetX = -1; + this._showCursor(false); + } + /** * @param {!Event} e */ _updateCursorPosition(e) { this._showCursor(e.shiftKey); this._cursorElement.style.left = e.offsetX + 'px'; + this._lastMouseOffsetX = e.offsetX; + } + + /** + * @param {number} x + * @return {number} + */ + pixelToTime(x) { + return this.pixelToTimeOffset(x) + this._timeWindowLeft; + } + + /** + * @param {number} x + * @return {number} + */ + pixelToTimeOffset(x) { + return x * (this._timeWindowRight - this._timeWindowLeft) / this._offsetWidth; + } + + /** + * @param {number} time + * @return {number} + */ + timeToPosition(time) { + return Math.floor( + (time - this._timeWindowLeft) / (this._timeWindowRight - this._timeWindowLeft) * this._offsetWidth); } /** @@ -334,102 +348,74 @@ /** * @param {!Event} e - * @private */ _handleZoomPanKeys(e) { if (!UI.KeyboardShortcut.hasNoModifiers(e)) return; - var zoomMultiplier = e.shiftKey ? 0.8 : 0.3; - var panMultiplier = e.shiftKey ? 320 : 80; - if (e.code === 'KeyA') { - this._handlePanGesture(-panMultiplier * this._pixelToTime); - e.consume(true); - } else if (e.code === 'KeyD') { - this._handlePanGesture(panMultiplier * this._pixelToTime); - e.consume(true); - } else if (e.code === 'KeyW') { - this._handleZoomGesture(-zoomMultiplier); - e.consume(true); - } else if (e.code === 'KeyS') { - this._handleZoomGesture(zoomMultiplier); - e.consume(true); + var zoomFactor = e.shiftKey ? 0.8 : 0.3; + var panOffset = e.shiftKey ? 320 : 80; + switch (e.code) { + case 'KeyA': + this._handlePanGesture(-panOffset); + break; + case 'KeyD': + this._handlePanGesture(panOffset); + break; + case 'KeyW': + this._handleZoomGesture(-zoomFactor); + break; + case 'KeyS': + this._handleZoomGesture(zoomFactor); + break; + default: + return; } + e.consume(true); } /** * @param {number} zoom - * @private */ _handleZoomGesture(zoom) { this._cancelAnimation(); - var bounds = this._windowForGesture(); - var cursorTime = this._cursorTime(this._lastMouseOffsetX); + var bounds = {left: this._timeWindowLeft, right: this._timeWindowRight}; + var cursorTime = this.pixelToTime(this._lastMouseOffsetX); bounds.left += (bounds.left - cursorTime) * zoom; bounds.right += (bounds.right - cursorTime) * zoom; this._requestWindowTimes(bounds); } /** - * @param {number} shift - * @private + * @param {number} offset */ - _handlePanGesture(shift) { + _handlePanGesture(offset) { this._cancelAnimation(); - var bounds = this._windowForGesture(); - shift = Number.constrain( - shift, this._minimumBoundary - bounds.left, this._totalTime + this._minimumBoundary - bounds.right); - bounds.left += shift; - bounds.right += shift; + var bounds = {left: this._timeWindowLeft, right: this._timeWindowRight}; + var timeOffset = Number.constrain( + this.pixelToTimeOffset(offset), this._minimumBoundary - bounds.left, + this._totalTime + this._minimumBoundary - bounds.right); + bounds.left += timeOffset; + bounds.right += timeOffset; this._requestWindowTimes(bounds); } /** - * @private - * @return {{left: number, right: number}} - */ - _windowForGesture() { - var windowLeft = this._timeWindowLeft ? this._timeWindowLeft : this._dataProvider.minimumBoundary(); - var windowRight = this._timeWindowRight !== Infinity ? - this._timeWindowRight : - this._dataProvider.minimumBoundary() + this._dataProvider.totalTime(); - return {left: windowLeft, right: windowRight}; - } - - /** - * @param {{left: number, right: number}} bounds - * @private + * @param {!{left: number, right: number}} bounds */ _requestWindowTimes(bounds) { - bounds.left = Number.constrain(bounds.left, this._minimumBoundary, this._totalTime + this._minimumBoundary); - bounds.right = Number.constrain(bounds.right, this._minimumBoundary, this._totalTime + this._minimumBoundary); + var maxBound = this._minimumBoundary + this._totalTime; + if (bounds.left < this._minimumBoundary) { + bounds.right = Math.min(bounds.right + this._minimumBoundary - bounds.left, maxBound); + bounds.left = this._minimumBoundary; + } else if (bounds.right > maxBound) { + bounds.left = Math.max(bounds.left - bounds.right + maxBound, this._minimumBoundary); + bounds.right = maxBound; + } if (bounds.right - bounds.left < PerfUI.FlameChart.MinimalTimeWindowMs) return; - this._flameChartDelegate.requestWindowTimes(bounds.left, bounds.right); + this._delegate.requestWindowTimes(bounds.left, bounds.right); } - /** - * @param {number} startTime - * @param {number} endTime - * @private - */ - _animateWindowTimes(startTime, endTime) { - this._timeWindowLeft = startTime; - this._timeWindowRight = endTime; - this._updateHighlight(); - this.update(); - } - - /** - * @private - */ - _animationCompleted() { - delete this._cancelWindowTimesAnimation; - this._updateHighlight(); - } - - /** - * @private - */ _cancelAnimation() { if (!this._cancelWindowTimesAnimation) return; @@ -444,11 +430,12 @@ return; this._updateTimerId = this.element.window().requestAnimationFrame(() => { this._updateTimerId = 0; - this.update(); + this._update(); }); } - update() { + _update() { + this._delegate.update(); } /** @@ -467,10 +454,21 @@ } this._cancelAnimation(); this._cancelWindowTimesAnimation = UI.animateFunction( - this.element.window(), this._animateWindowTimes.bind(this), + this.element.window(), animateWindowTimes.bind(this), [{from: this._timeWindowLeft, to: startTime}, {from: this._timeWindowRight, to: endTime}], 5, - this._animationCompleted.bind(this)); + () => delete this._cancelWindowTimesAnimation); this._pendingAnimationTimeLeft = startTime; this._pendingAnimationTimeRight = endTime; + + /** + * @param {number} startTime + * @param {number} endTime + * @this {PerfUI.ChartViewport} + */ + function animateWindowTimes(startTime, endTime) { + this._timeWindowLeft = startTime; + this._timeWindowRight = endTime; + this._update(); + } } };
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/FlameChart.js b/third_party/WebKit/Source/devtools/front_end/perf_ui/FlameChart.js index 21a236d..d83dd14 100644 --- a/third_party/WebKit/Source/devtools/front_end/perf_ui/FlameChart.js +++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/FlameChart.js
@@ -49,25 +49,31 @@ /** * @unrestricted + * @implements {PerfUI.ChartViewportDelegate} */ -PerfUI.FlameChart = class extends PerfUI.ChartViewport { +PerfUI.FlameChart = class extends UI.VBox { /** * @param {!PerfUI.FlameChartDataProvider} dataProvider * @param {!PerfUI.FlameChartDelegate} flameChartDelegate * @param {!Common.Setting=} groupExpansionSetting */ constructor(dataProvider, flameChartDelegate, groupExpansionSetting) { - super(); + super(true); this.registerRequiredCSS('perf_ui/flameChart.css'); this.contentElement.classList.add('flame-chart-main-pane'); - this._flameChartDelegate = flameChartDelegate; this._groupExpansionSetting = groupExpansionSetting; this._groupExpansionState = groupExpansionSetting && groupExpansionSetting.get() || {}; + this._flameChartDelegate = flameChartDelegate; + + this._chartViewport = new PerfUI.ChartViewport(this); + this._chartViewport.show(this.contentElement); this._dataProvider = dataProvider; this._calculator = new PerfUI.FlameChart.Calculator(dataProvider); - this._canvas = /** @type {!HTMLCanvasElement} */ (this.viewportElement.createChild('canvas')); + this._viewportElement = this._chartViewport.viewportElement; + this._canvas = /** @type {!HTMLCanvasElement} */ (this._viewportElement.createChild('canvas')); + this._canvas.tabIndex = 1; this.setDefaultFocusedElement(this._canvas); this._canvas.addEventListener('mousemove', this._onMouseMove.bind(this), false); @@ -75,10 +81,14 @@ this._canvas.addEventListener('click', this._onClick.bind(this), false); this._canvas.addEventListener('keydown', this._onKeyDown.bind(this), false); - this._entryInfo = this.viewportElement.createChild('div', 'flame-chart-entry-info'); - this._markerHighlighElement = this.viewportElement.createChild('div', 'flame-chart-marker-highlight-element'); - this._highlightElement = this.viewportElement.createChild('div', 'flame-chart-highlight-element'); - this._selectedElement = this.viewportElement.createChild('div', 'flame-chart-selected-element'); + this._entryInfo = this._viewportElement.createChild('div', 'flame-chart-entry-info'); + this._markerHighlighElement = this._viewportElement.createChild('div', 'flame-chart-marker-highlight-element'); + this._highlightElement = this._viewportElement.createChild('div', 'flame-chart-highlight-element'); + this._selectedElement = this._viewportElement.createChild('div', 'flame-chart-selected-element'); + + UI.installDragHandle( + this._viewportElement, this._startDragging.bind(this), this._dragging.bind(this), this._endDragging.bind(this), + null); this._rulerEnabled = true; this._windowLeft = 0.0; @@ -90,7 +100,6 @@ this._barHeight = 17; this._textBaseline = 5; this._textPadding = 5; - this._paddingLeft = 0; this._markerRadius = 6; /** @const */ @@ -143,19 +152,16 @@ } /** - * @param {number} value - */ - setPaddingLeft(value) { - this._paddingLeft = value; - } - - /** * @param {boolean} enable */ enableRuler(enable) { this._rulerEnabled = enable; } + alwaysShowVerticalScroll() { + this._chartViewport.alwaysShowVerticalScroll(); + } + /** * @param {number} entryIndex */ @@ -183,6 +189,61 @@ } /** + * @override + * @param {number} startTime + * @param {number} endTime + */ + requestWindowTimes(startTime, endTime) { + this._flameChartDelegate.requestWindowTimes(startTime, endTime); + } + + /** + * @override + * @param {number} startTime + * @param {number} endTime + */ + updateRangeSelection(startTime, endTime) { + this._flameChartDelegate.updateRangeSelection(startTime, endTime); + } + + /** + * @override + * @param {number} width + * @param {number} height + */ + setSize(width, height) { + this._offsetWidth = width; + this._offsetHeight = height; + } + + /** + * @param {!MouseEvent} event + */ + _startDragging(event) { + this.hideHighlight(); + this._maxDragOffset = 0; + this._dragStartX = event.pageX; + this._dragStartY = event.pageY; + return true; + } + + /** + * @param {!MouseEvent} event + */ + _dragging(event) { + var dx = event.pageX - this._dragStartX; + var dy = event.pageY - this._dragStartY; + this._maxDragOffset = Math.max(this._maxDragOffset, Math.sqrt(dx * dx + dy * dy)); + } + + /** + * @param {!MouseEvent} event + */ + _endDragging(event) { + this._updateHighlight(); + } + + /** * @return {?PerfUI.FlameChart.TimelineData} */ _timelineData() { @@ -201,36 +262,36 @@ var timelineData = this._timelineData(); if (!timelineData) return; - // Think in terms of not where we are, but where we'll be after animation (if present) - var timeLeft = this._cancelWindowTimesAnimation ? this._pendingAnimationTimeLeft : this._timeWindowLeft; - var timeRight = this._cancelWindowTimesAnimation ? this._pendingAnimationTimeRight : this._timeWindowRight; + var timeLeft = this._timeWindowLeft; + var timeRight = this._timeWindowRight; var entryStartTime = timelineData.entryStartTimes[entryIndex]; var entryTotalTime = timelineData.entryTotalTimes[entryIndex]; var entryEndTime = entryStartTime + entryTotalTime; var minEntryTimeWindow = Math.min(entryTotalTime, timeRight - timeLeft); var level = timelineData.entryLevels[entryIndex]; - this.setScrollOffset(this._levelToOffset(level), this._levelHeight(level)); + this._chartViewport.setScrollOffset(this._levelToOffset(level), this._levelHeight(level)); var minVisibleWidthPx = 30; var futurePixelToTime = (timeRight - timeLeft) / this._offsetWidth; minEntryTimeWindow = Math.max(minEntryTimeWindow, futurePixelToTime * minVisibleWidthPx); if (timeLeft > entryEndTime) { var delta = timeLeft - entryEndTime + minEntryTimeWindow; - this._flameChartDelegate.requestWindowTimes(timeLeft - delta, timeRight - delta); + this.requestWindowTimes(timeLeft - delta, timeRight - delta); } else if (timeRight < entryStartTime) { var delta = entryStartTime - timeRight + minEntryTimeWindow; - this._flameChartDelegate.requestWindowTimes(timeLeft + delta, timeRight + delta); + this.requestWindowTimes(timeLeft + delta, timeRight + delta); } } /** - * @override * @param {number} startTime * @param {number} endTime */ setWindowTimes(startTime, endTime) { - super.setWindowTimes(startTime, endTime); + this._chartViewport.setWindowTimes(startTime, endTime); + this._timeWindowLeft = startTime; + this._timeWindowRight = endTime; this._updateHighlight(); } @@ -242,11 +303,11 @@ this._lastMouseOffsetY = event.offsetY; if (!this._enabled()) return; - if (this.isDragging()) + if (this._chartViewport.isDragging()) return; if (this._coordinatesToGroupIndex(event.offsetX, event.offsetY) >= 0) { this.hideHighlight(); - this.viewportElement.style.cursor = 'pointer'; + this._viewportElement.style.cursor = 'pointer'; return; } this._updateHighlight(); @@ -264,10 +325,10 @@ this.hideHighlight(); return; } - if (this.isDragging()) + if (this._chartViewport.isDragging()) return; this._updatePopover(entryIndex); - this.viewportElement.style.cursor = this._dataProvider.canJumpToEntry(entryIndex) ? 'pointer' : 'default'; + this._viewportElement.style.cursor = this._dataProvider.canJumpToEntry(entryIndex) ? 'pointer' : 'default'; this.highlightEntry(entryIndex); } @@ -325,14 +386,14 @@ // So if there was drag (mouse move) in the middle of that events // we skip the click. Otherwise we jump to the sources. var /** @const */ clickThreshold = 5; - if (this.maxDragOffset() > clickThreshold) + if (this._maxDragOffset > clickThreshold) return; var groupIndex = this._coordinatesToGroupIndex(event.offsetX, event.offsetY); if (groupIndex >= 0) { this._toggleGroupVisibility(groupIndex); return; } - this.hideRangeSelection(); + this._chartViewport.hideRangeSelection(); this.dispatchEventToListeners(PerfUI.FlameChart.Events.EntrySelected, this._highlightedEntryIndex); } @@ -438,25 +499,16 @@ /** * @param {number} x - * @return {number} - */ - _cursorTime(x) { - return (x + this._pixelWindowLeft - this._paddingLeft) * this._pixelToTime + this._minimumBoundary; - } - - /** - * @param {number} x * @param {number} y * @return {number} */ _coordinatesToEntryIndex(x, y) { if (x < 0 || y < 0) return -1; - y += this.getScrollOffset(); var timelineData = this._timelineData(); if (!timelineData) return -1; - var cursorTime = this._cursorTime(x); + y += this._chartViewport.scrollOffset(); var cursorLevel = this._visibleLevelOffsets.upperBound(y) - 1; if (cursorLevel < 0 || !this._visibleLevels[cursorLevel]) return -1; @@ -477,6 +529,7 @@ function comparator(time, entryIndex) { return time - entryStartTimes[entryIndex]; } + var cursorTime = this._chartViewport.pixelToTime(x); var indexOnLevel = Math.max(entryIndexes.upperBound(cursorTime, comparator) - 1, 0); /** @@ -488,15 +541,16 @@ if (entryIndex === undefined) return false; var startTime = entryStartTimes[entryIndex]; + var startX = this._chartViewport.timeToPosition(startTime); var duration = entryTotalTimes[entryIndex]; if (isNaN(duration)) { - var dx = (startTime - cursorTime) / this._pixelToTime; + var dx = startX - x; var dy = this._levelHeight(cursorLevel) / 2 - offsetFromLevel; return dx * dx + dy * dy < this._markerRadius * this._markerRadius; } - var endTime = startTime + duration; - var barThreshold = 3 * this._pixelToTime; - return startTime - barThreshold < cursorTime && cursorTime < endTime + barThreshold; + var endX = this._chartViewport.timeToPosition(startTime + duration); + var /** @const */ barThresholdPx = 3; + return startX - barThresholdPx < x && x < endX + barThresholdPx; } var entryIndex = entryIndexes[indexOnLevel]; @@ -516,7 +570,7 @@ _coordinatesToGroupIndex(x, y) { if (x < 0 || y < 0) return -1; - y += this.getScrollOffset(); + y += this._chartViewport.scrollOffset(); var groups = this._rawTimelineData.groups || []; var group = this._groupOffsets.upperBound(y) - 1; @@ -542,9 +596,9 @@ if (!markers) return -1; var /** @const */ accurracyOffsetPx = 4; - var time = this._cursorTime(x); - var leftTime = this._cursorTime(x - accurracyOffsetPx); - var rightTime = this._cursorTime(x + accurracyOffsetPx); + var time = this._chartViewport.pixelToTime(x); + var leftTime = this._chartViewport.pixelToTime(x - accurracyOffsetPx); + var rightTime = this._chartViewport.pixelToTime(x + accurracyOffsetPx); var left = this._markerIndexBeforeTime(leftTime); var markerIndex = -1; var distance = Infinity; @@ -579,14 +633,12 @@ var context = /** @type {!CanvasRenderingContext2D} */ (this._canvas.getContext('2d')); context.save(); var ratio = window.devicePixelRatio; - var top = this.getScrollOffset(); + var top = this._chartViewport.scrollOffset(); context.scale(ratio, ratio); context.translate(0, -top); var defaultFont = '11px ' + Host.fontFamily(); context.font = defaultFont; - var timeWindowRight = this._timeWindowRight; - var timeWindowLeft = this._timeWindowLeft - this._paddingLeft / this._timeToPixel; var entryTotalTimes = timelineData.entryTotalTimes; var entryStartTimes = timelineData.entryStartTimes; var entryLevels = timelineData.entryLevels; @@ -608,13 +660,13 @@ // Entries are ordered by start time within a level, so find the last visible entry. var levelIndexes = this._timelineLevels[level]; var rightIndexOnLevel = - levelIndexes.lowerBound(timeWindowRight, (time, entryIndex) => time - entryStartTimes[entryIndex]) - 1; + levelIndexes.lowerBound(this._timeWindowRight, (time, entryIndex) => time - entryStartTimes[entryIndex]) - 1; var lastDrawOffset = Infinity; for (var entryIndexOnLevel = rightIndexOnLevel; entryIndexOnLevel >= 0; --entryIndexOnLevel) { var entryIndex = levelIndexes[entryIndexOnLevel]; var entryStartTime = entryStartTimes[entryIndex]; var entryOffsetRight = entryStartTime + (entryTotalTimes[entryIndex] || 0); - if (entryOffsetRight <= timeWindowLeft) + if (entryOffsetRight <= this._timeWindowLeft) break; var barX = this._timeToPositionClipped(entryStartTime); @@ -690,7 +742,7 @@ context.font = this._dataProvider.entryFont(entryIndex) || defaultFont; text = UI.trimTextMiddle(context, text, barWidth - 2 * textPadding); } - var unclippedBarX = this._timeToPosition(entryStartTime); + var unclippedBarX = this._chartViewport.timeToPosition(entryStartTime); var barHeight = this._levelHeight(barLevel); if (this._dataProvider.decorateEntry( entryIndex, context, text, barX, barY, barWidth, barHeight, unclippedBarX, this._timeToPixel)) @@ -720,7 +772,7 @@ */ _drawGroupHeaders(width, height) { var context = /** @type {!CanvasRenderingContext2D} */ (this._canvas.getContext('2d')); - var top = this.getScrollOffset(); + var top = this._chartViewport.scrollOffset(); var ratio = window.devicePixelRatio; var groups = this._rawTimelineData.groups || []; if (!groups.length) @@ -878,7 +930,7 @@ _drawCollapsedOverviewForGroup(group, y, endLevel) { var range = new Common.SegmentedRange(mergeCallback); var timeWindowRight = this._timeWindowRight; - var timeWindowLeft = this._timeWindowLeft - this._paddingLeft / this._timeToPixel; + var timeWindowLeft = this._timeWindowLeft; var context = /** @type {!CanvasRenderingContext2D} */ (this._canvas.getContext('2d')); var barHeight = group.style.height; var entryStartTimes = this._rawTimelineData.entryStartTimes; @@ -903,7 +955,7 @@ var color = this._dataProvider.entryColor(entryIndex); var endBarX = this._timeToPositionClipped(entryEndTime); if (group.style.useDecoratorsForOverview && this._dataProvider.forceDecoration(entryIndex)) { - var unclippedBarX = this._timeToPosition(entryStartTime); + var unclippedBarX = this._chartViewport.timeToPosition(entryStartTime); var barWidth = endBarX - barX; context.beginPath(); context.fillStyle = color; @@ -949,7 +1001,7 @@ _drawFlowEvents(context, width, height) { context.save(); var ratio = window.devicePixelRatio; - var top = this.getScrollOffset(); + var top = this._chartViewport.scrollOffset(); var arrowWidth = 6; context.scale(ratio, ratio); context.translate(0, -top); @@ -963,8 +1015,8 @@ for (var i = 0; i < endIndex; ++i) { if (!td.flowEndTimes[i] || td.flowEndTimes[i] < this._timeWindowLeft) continue; - var startX = this._timeToPosition(td.flowStartTimes[i]); - var endX = this._timeToPosition(td.flowEndTimes[i]); + var startX = this._chartViewport.timeToPosition(td.flowStartTimes[i]); + var endX = this._chartViewport.timeToPosition(td.flowEndTimes[i]); var startLevel = td.flowStartLevels[i]; var endLevel = td.flowEndLevels[i]; var startY = this._levelToOffset(startLevel) + this._levelHeight(startLevel) / 2; @@ -1042,7 +1094,7 @@ var style = element.style; style.left = barX + 'px'; style.backgroundColor = marker.color(); - this.viewportElement.appendChild(element); + this._viewportElement.appendChild(element); } /** @@ -1168,8 +1220,8 @@ * @param {number} entryIndex */ setSelectedEntry(entryIndex) { - if (entryIndex === -1 && !this.isDragging()) - this.hideRangeSelection(); + if (entryIndex === -1 && !this._chartViewport.isDragging()) + this._chartViewport.hideRangeSelection(); if (this._selectedEntryIndex === entryIndex) return; this._selectedEntryIndex = entryIndex; @@ -1199,14 +1251,14 @@ barWidth = Math.max(barWidth, elementMinWidthPx); barX = barCenter - barWidth / 2; var entryLevel = timelineData.entryLevels[entryIndex]; - var barY = this._levelToOffset(entryLevel) - this.getScrollOffset(); + var barY = this._levelToOffset(entryLevel) - this._chartViewport.scrollOffset(); var barHeight = this._levelHeight(entryLevel); var style = element.style; style.left = barX + 'px'; style.top = barY + 'px'; style.width = barWidth + 'px'; style.height = barHeight - 1 + 'px'; - this.viewportElement.appendChild(element); + this._viewportElement.appendChild(element); } /** @@ -1214,15 +1266,7 @@ * @return {number} */ _timeToPositionClipped(time) { - return Number.constrain(this._timeToPosition(time), 0, this._offsetWidth); - } - - /** - * @param {number} time - * @return {number} - */ - _timeToPosition(time) { - return Math.floor((time - this._minimumBoundary) * this._timeToPixel) - this._pixelWindowLeft + this._paddingLeft; + return Number.constrain(this._chartViewport.timeToPosition(time), 0, this._offsetWidth); } /** @@ -1258,23 +1302,24 @@ this._windowRight = 1; } - var totalPixels = Math.floor((this._offsetWidth - this._paddingLeft) / windowWidth); + var totalPixels = Math.floor(this._offsetWidth / windowWidth); this._pixelWindowLeft = Math.floor(totalPixels * this._windowLeft); this._timeToPixel = totalPixels / this._totalTime; this._pixelToTime = this._totalTime / totalPixels; + + this._chartViewport.setBoundaries(this._minimumBoundary, this._totalTime); } _updateHeight() { var height = this._levelToOffset(this._dataProvider.maxStackDepth()); - this.setContentHeight(height); + this._chartViewport.setContentHeight(height); } /** * @override */ onResize() { - super.onResize(); this.scheduleUpdate(); } @@ -1289,15 +1334,12 @@ this._updateBoundaries(); this._calculator._updateBoundaries(this); this._draw(this._offsetWidth, this._offsetHeight); - if (!this.isDragging()) + if (!this._chartViewport.isDragging()) this._updateHighlight(); } - /** - * @override - */ reset() { - super.reset(); + this._chartViewport.reset(); this._rawTimelineData = null; this._rawTimelineDataLength = 0; this._highlightedMarkerIndex = -1; @@ -1305,7 +1347,11 @@ this._selectedEntryIndex = -1; /** @type {!Map<string,!Map<string,number>>} */ this._textWidth = new Map(); - this.scheduleUpdate(); + this._chartViewport.scheduleUpdate(); + } + + scheduleUpdate() { + this._chartViewport.scheduleUpdate(); } _enabled() { @@ -1514,8 +1560,7 @@ this._zeroTime = mainPane._dataProvider.minimumBoundary(); this._minimumBoundaries = this._zeroTime + mainPane._windowLeft * this._totalTime; this._maximumBoundaries = this._zeroTime + mainPane._windowRight * this._totalTime; - this._paddingLeft = mainPane._paddingLeft; - this._width = mainPane._offsetWidth - this._paddingLeft; + this._width = mainPane._offsetWidth; this._timeToPixel = this._width / this.boundarySpan(); } @@ -1525,7 +1570,7 @@ * @return {number} */ computePosition(time) { - return Math.round((time - this._minimumBoundaries) * this._timeToPixel + this._paddingLeft); + return Math.round((time - this._minimumBoundaries) * this._timeToPixel); } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/chartViewport.css b/third_party/WebKit/Source/devtools/front_end/perf_ui/chartViewport.css new file mode 100644 index 0000000..22e1d6d --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/chartViewport.css
@@ -0,0 +1,73 @@ +/* + * 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. + */ + +.chart-viewport-v-scroll { + position: absolute; + top: 0; + right: 0; + bottom: 0; + overflow-x: hidden; + z-index: 200; + padding-left: 1px; +} + +.chart-viewport-v-scroll.always-show-scrollbar { + overflow-y: scroll; +} + +/* force non overlay scrollbars for Mac */ +:host-context(.platform-mac) .chart-viewport-v-scroll { + right: 2px; + top: 3px; + bottom: 3px; +} + +:host-context(.platform-mac) ::-webkit-scrollbar { + width: 8px; +} + +:host-context(.platform-mac) ::-webkit-scrollbar-thumb { + background-color: hsla(0, 0%, 56%, 0.6); + border-radius: 50px; +} + +:host-context(.platform-mac) .chart-viewport-v-scroll:hover::-webkit-scrollbar-thumb { + background-color: hsla(0, 0%, 25%, 0.6); +} + +/* force non overlay scrollbars for Aura Overlay Scrollbar enabled */ +:host-context(.overlay-scrollbar-enabled) ::-webkit-scrollbar { + width: 10px; +} + +:host-context(.overlay-scrollbar-enabled) ::-webkit-scrollbar-thumb { + background-color: hsla(0, 0%, 0%, 0.5); +} + +:host-context(.overlay-scrollbar-enabled) .chart-viewport-v-scroll:hover::-webkit-scrollbar-thumb { + background-color: hsla(0, 0%, 0%, 0.7); +} + +.chart-viewport-selection-overlay { + position: absolute; + z-index: 100; + background-color: rgba(56, 121, 217, 0.3); + border-color: rgb(16, 81, 177); + border-width: 0 1px; + border-style: solid; + pointer-events: none; + top: 0; + bottom: 0; + text-align: center; +} + +.chart-viewport-selection-overlay .time-span { + white-space: nowrap; + position: absolute; + left: 0; + right: 0; + bottom: 0; +}
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/flameChart.css b/third_party/WebKit/Source/devtools/front_end/perf_ui/flameChart.css index bad7324..8e3c69e 100644 --- a/third_party/WebKit/Source/devtools/front_end/perf_ui/flameChart.css +++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/flameChart.css
@@ -31,74 +31,6 @@ background-color: rgba(56, 121, 217, 0.1); } -.flame-chart-v-scroll { - position: absolute; - top: 0; - right: 0; - bottom: 0; - overflow-x: hidden; - z-index: 200; - padding-left: 1px; -} - -.flame-chart-v-scroll.always-show-scrollbar { - overflow-y: scroll; -} - -/* force non overlay scrollbars for Mac */ -:host-context(.platform-mac) .flame-chart-v-scroll { - right: 2px; - top: 3px; - bottom: 3px; -} - -:host-context(.platform-mac) ::-webkit-scrollbar { - width: 8px; -} - -:host-context(.platform-mac) ::-webkit-scrollbar-thumb { - background-color: hsla(0, 0%, 56%, 0.6); - border-radius: 50px; -} - -:host-context(.platform-mac) .flame-chart-v-scroll:hover::-webkit-scrollbar-thumb { - background-color: hsla(0, 0%, 25%, 0.6); -} - -/* force non overlay scrollbars for Aura Overlay Scrollbar enabled */ -:host-context(.overlay-scrollbar-enabled) ::-webkit-scrollbar { - width: 10px; -} - -:host-context(.overlay-scrollbar-enabled) ::-webkit-scrollbar-thumb { - background-color: hsla(0, 0%, 0%, 0.5); -} - -:host-context(.overlay-scrollbar-enabled) .flame-chart-v-scroll:hover::-webkit-scrollbar-thumb { - background-color: hsla(0, 0%, 0%, 0.7); -} - -.flame-chart-selection-overlay { - position: absolute; - z-index: 100; - background-color: rgba(56, 121, 217, 0.3); - border-color: rgb(16, 81, 177); - border-width: 0 1px; - border-style: solid; - pointer-events: none; - top: 0; - bottom: 0; - text-align: center; -} - -.flame-chart-selection-overlay .time-span { - white-space: nowrap; - position: absolute; - left: 0; - right: 0; - bottom: 0; -} - .chart-cursor-element { position: absolute; top: 0;
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/module.json b/third_party/WebKit/Source/devtools/front_end/perf_ui/module.json index 5d966ec..a0c8a70 100644 --- a/third_party/WebKit/Source/devtools/front_end/perf_ui/module.json +++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/module.json
@@ -44,6 +44,7 @@ "TimelineOverviewPane.js" ], "resources": [ + "chartViewport.css", "filmStripView.css", "filmStripDialog.css", "flameChart.css",
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js index fa24238..ec93484 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js
@@ -49,8 +49,8 @@ this.contentElement.appendChild(this._sidebarTree.element); this._applicationTreeElement = this._addSidebarSection(Common.UIString('Application')); - this._manifestTreeElement = new Resources.AppManifestTreeElement(panel); - this._applicationTreeElement.appendChild(this._manifestTreeElement); + var manifestTreeElement = new Resources.AppManifestTreeElement(panel); + this._applicationTreeElement.appendChild(manifestTreeElement); this.serviceWorkersTreeElement = new Resources.ServiceWorkersTreeElement(panel); this._applicationTreeElement.appendChild(this.serviceWorkersTreeElement); var clearStorageTreeElement = new Resources.ClearStorageTreeElement(panel); @@ -116,7 +116,7 @@ var selection = this._panel.lastSelectedItemPath(); if (!selection.length) - this._manifestTreeElement.select(); + manifestTreeElement.select(); } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js b/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js index 32cc5ff5..4c07cfc1 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/ClearStorageView.js
@@ -3,16 +3,19 @@ // found in the LICENSE file. /** * @implements {SDK.TargetManager.Observer} - * @unrestricted */ -Resources.ClearStorageView = class extends UI.VBox { +Resources.ClearStorageView = class extends UI.ThrottledWidget { constructor() { - super(true); + super(true, 1000); this._reportView = new UI.ReportView(Common.UIString('Clear storage')); this._reportView.registerRequiredCSS('resources/clearStorageView.css'); this._reportView.element.classList.add('clear-storage-header'); this._reportView.show(this.contentElement); + /** @type {?SDK.Target} */ + this._target = null; + /** @type {?string} */ + this._securityOrigin = null; this._settings = new Map(); for (var type @@ -22,6 +25,8 @@ Protocol.Storage.StorageType.Websql]) this._settings.set(type, Common.settings.createSetting('clear-storage-' + type, true)); + var quota = this._reportView.appendSection(Common.UIString('Usage')); + this._quotaRow = quota.appendRow(); var application = this._reportView.appendSection(Common.UIString('Application')); this._appendItem(application, Common.UIString('Unregister service workers'), 'service_workers'); @@ -93,9 +98,12 @@ _updateOrigin(url) { this._securityOrigin = new Common.ParsedURL(url).securityOrigin(); this._reportView.setSubtitle(this._securityOrigin); + this.doUpdate(); } _clear() { + if (!this._securityOrigin) + return; var storageTypes = []; for (var type of this._settings.keys()) { if (this._settings.get(type).get()) @@ -155,4 +163,32 @@ this._clearButton.textContent = label; }, 500); } + + /** + * @override + * @return {!Promise<?>} + */ + async doUpdate() { + if (!this._securityOrigin) + return; + + var securityOrigin = /** @type {string} */ (this._securityOrigin); + var response = await this._target.storageAgent().invoke_getUsageAndQuota({origin: securityOrigin}); + if (response[Protocol.Error]) { + this._quotaRow.textContent = ''; + return; + } + this._quotaRow.textContent = Common.UIString( + '%s storage quota used out of %s', Number.bytesToString(response.usage), Number.bytesToString(response.quota)); + + this._usageUpdatedForTest(response.usage, response.quota); + this.update(); + } + + /** + * @param {number} usage + * @param {number} quota + */ + _usageUpdatedForTest(usage, quota) { + } };
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css index 729a8fc..eb43ba64 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css +++ b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
@@ -431,7 +431,7 @@ } .timeline-flamechart-resizer { - height: 8px; + flex: 8px 0 0; background-color: #f3f3f3; border: 1px #a3a3a3; border-style: solid none;
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ThrottledWidget.js b/third_party/WebKit/Source/devtools/front_end/ui/ThrottledWidget.js index 6caf67cc..bbb4f37 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/ThrottledWidget.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/ThrottledWidget.js
@@ -7,10 +7,11 @@ UI.ThrottledWidget = class extends UI.VBox { /** * @param {boolean=} isWebComponent + * @param {number=} timeout */ - constructor(isWebComponent) { + constructor(isWebComponent, timeout) { super(isWebComponent); - this._updateThrottler = new Common.Throttler(100); + this._updateThrottler = new Common.Throttler(timeout === undefined ? 100 : timeout); this._updateWhenVisible = false; }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js index 6f458e91..f927d21 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
@@ -36,7 +36,7 @@ * @param {?function(!MouseEvent): boolean} elementDragStart * @param {function(!MouseEvent)} elementDrag * @param {?function(!MouseEvent)} elementDragEnd - * @param {string} cursor + * @param {?string} cursor * @param {?string=} hoverCursor * @param {number=} startDelay */ @@ -66,7 +66,7 @@ if (startDelay) element.addEventListener('mouseup', onMouseUp, false); if (hoverCursor !== null) - element.style.cursor = hoverCursor || cursor; + element.style.cursor = hoverCursor || cursor || ''; }; /** @@ -74,7 +74,7 @@ * @param {?function(!MouseEvent):boolean} elementDragStart * @param {function(!MouseEvent)} elementDrag * @param {?function(!MouseEvent)} elementDragEnd - * @param {string} cursor + * @param {?string} cursor * @param {!Event} event */ UI.elementDragStart = function(targetElement, elementDragStart, elementDrag, elementDragEnd, cursor, event) { @@ -117,7 +117,7 @@ * @param {?function(!MouseEvent):boolean} elementDragStart * @param {function(!MouseEvent)} elementDrag * @param {?function(!MouseEvent)} elementDragEnd - * @param {string} cursor + * @param {?string} cursor * @param {!Event} event */ elementDragStart(targetElement, elementDragStart, elementDrag, elementDragEnd, cursor, event) {
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp index 0f25f71..f34d20f4 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp +++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp
@@ -260,8 +260,21 @@ } bool IDBRequest::ShouldEnqueueEvent() const { - if (!GetExecutionContext()) + const ExecutionContext* execution_context = GetExecutionContext(); + + // https://crbug.com/733642 - Document::Shutdown() calls + // LocalDOMWindow::ClearEventQueue(), which nulls out the context's event + // queue, before calling ExecutionContext::NotifyContextDestroyed(). The + // latter eventually calls IDBRequest::ContextDestroyed(), which aborts the + // request. As an aborted IDBRequest is removed from its' IDBTransaction + // result queue, it may unblock another request whose result is already + // available. If the unblocked request hasn't received a + // NotifyContextDestroyed() call yet, it will hang onto an ExecutionContext + // whose event queue has been nulled out. The event queue null check covers + // these specific circumstances. + if (!execution_context || !execution_context->GetEventQueue()) return false; + DCHECK(ready_state_ == PENDING || ready_state_ == DONE); if (request_aborted_) return false;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.cpp index 0c18c8b..6756714 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.cpp +++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.cpp
@@ -26,6 +26,11 @@ } void IDBRequestLoader::Start() { +#if DCHECK_IS_ON() + DCHECK(!started_) << "Start() was already called"; + started_ = true; +#endif // DCHECK_IS_ON() + // TODO(pwnall): Start() / StartNextValue() unwrap large values sequentially. // Consider parallelizing. The main issue is that the Blob reads // will have to be throttled somewhere, and the extra complexity @@ -35,6 +40,14 @@ } void IDBRequestLoader::Cancel() { +#if DCHECK_IS_ON() + DCHECK(started_) << "Cancel() called on a loader that hasn't been Start()ed"; + DCHECK(!canceled_) << "Cancel() was already called"; + canceled_ = true; + + DCHECK(file_reader_loading_); + file_reader_loading_ = false; +#endif // DCHECK_IS_ON() loader_->Cancel(); } @@ -60,6 +73,10 @@ } wrapped_data_.ReserveCapacity(unwrapper.WrapperBlobSize()); +#if DCHECK_IS_ON() + DCHECK(!file_reader_loading_); + file_reader_loading_ = true; +#endif // DCHECK_IS_ON() loader_->Start(context, unwrapper.WrapperBlobHandle()); } @@ -74,6 +91,16 @@ } void IDBRequestLoader::DidFinishLoading() { +#if DCHECK_IS_ON() + DCHECK(started_) + << "FileReaderLoader called DidFinishLoading() before it was Start()ed"; + DCHECK(!canceled_) + << "FileReaderLoader called DidFinishLoading() after it was Cancel()ed"; + + DCHECK(file_reader_loading_); + file_reader_loading_ = false; +#endif // DCHECK_IS_ON() + *current_value_ = IDBValueUnwrapper::Unwrap( current_value_->Get(), SharedBuffer::AdoptVector(wrapped_data_)); ++current_value_; @@ -82,14 +109,32 @@ } void IDBRequestLoader::DidFail(FileError::ErrorCode) { +#if DCHECK_IS_ON() + DCHECK(started_) + << "FileReaderLoader called DidFail() before it was Start()ed"; + DCHECK(!canceled_) + << "FileReaderLoader called DidFail() after it was Cancel()ed"; + + DCHECK(file_reader_loading_); + file_reader_loading_ = false; +#endif // DCHECK_IS_ON() + ReportError(); } void IDBRequestLoader::ReportSuccess() { +#if DCHECK_IS_ON() + DCHECK(started_); + DCHECK(!canceled_); +#endif // DCHECK_IS_ON() queue_item_->OnResultLoadComplete(); } void IDBRequestLoader::ReportError() { +#if DCHECK_IS_ON() + DCHECK(started_); + DCHECK(!canceled_); +#endif // DCHECK_IS_ON() queue_item_->OnResultLoadComplete( DOMException::Create(kDataError, "Failed to read large IndexedDB value")); }
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.h b/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.h index f002222d..d447dcb 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.h +++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.h
@@ -84,6 +84,18 @@ // The value being currently unwrapped. Vector<RefPtr<IDBValue>>::iterator current_value_; + +#if DCHECK_IS_ON() + // True after Start() is called. + bool started_ = false; + + // True after Cancel() is called. + bool canceled_ = false; + + // True between a call to FileReaderLoader::Start() and the FileReaderLoader's + // call to DidFinishLoading() or to DidFail(). + bool file_reader_loading_ = false; +#endif // DCHECK_IS_ON() }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequestQueueItem.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBRequestQueueItem.cpp index 48afd5c4..ade7e98 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBRequestQueueItem.cpp +++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequestQueueItem.cpp
@@ -179,6 +179,13 @@ // The backing store can get the result back to the request after it's been // aborted due to a transaction abort. In this case, we can't rely on // IDBRequest::Abort() to call CancelLoading(). + + // Setting loader_ to null here makes sure we don't call Cancel() on a + // IDBRequestLoader that hasn't been Start()ed. The current implementation + // behaves well even if Cancel() is called without Start() being called, but + // this reset makes the IDBRequestLoader lifecycle easier to reason about. + loader_.reset(); + CancelLoading(); return; } @@ -195,7 +202,11 @@ if (loader_) { loader_->Cancel(); - loader_ = nullptr; + loader_.reset(); + + // IDBRequestLoader::Cancel() should not call any of the EnqueueResponse + // variants. + DCHECK(!ready_); } // Mark this item as ready so the transaction's result queue can be drained.
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp index 99c276caf..f06ee92 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp +++ b/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp
@@ -282,6 +282,48 @@ EXPECT_EQ(0U, live_transactions.size()); } +TEST_F(IDBTransactionTest, DocumentShutdownWithQueuedAndBlockedResults) { + // This test covers the conditions of https://crbug.com/733642 + + V8TestingScope scope; + std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create(); + EXPECT_CALL(*backend, Close()).Times(1); + BuildTransaction(scope, std::move(backend)); + + PersistentHeapHashSet<WeakMember<IDBTransaction>> live_transactions; + live_transactions.insert(transaction_); + + ThreadState::Current()->CollectAllGarbage(); + EXPECT_EQ(1U, live_transactions.size()); + + Persistent<IDBRequest> request1 = + IDBRequest::Create(scope.GetScriptState(), IDBAny::CreateUndefined(), + transaction_.Get(), IDBRequest::AsyncTraceState()); + Persistent<IDBRequest> request2 = + IDBRequest::Create(scope.GetScriptState(), IDBAny::CreateUndefined(), + transaction_.Get(), IDBRequest::AsyncTraceState()); + DeactivateNewTransactions(scope.GetIsolate()); + + request1->HandleResponse(CreateIDBValue(scope.GetIsolate(), true)); + request2->HandleResponse(CreateIDBValue(scope.GetIsolate(), false)); + + request1.Clear(); // The transaction is holding onto the requests. + request2.Clear(); + ThreadState::Current()->CollectAllGarbage(); + EXPECT_EQ(1U, live_transactions.size()); + + // This will generate an Abort() call to the back end which is dropped by the + // fake proxy, so an explicit OnAbort call is made. + scope.GetDocument().Shutdown(); + transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted")); + transaction_.Clear(); + + url_loader_mock_factory_->ServeAsynchronousRequests(); + + ThreadState::Current()->CollectAllGarbage(); + EXPECT_EQ(0U, live_transactions.size()); +} + TEST_F(IDBTransactionTest, TransactionFinish) { V8TestingScope scope; std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
diff --git a/third_party/WebKit/Source/modules/indexeddb/OWNERS b/third_party/WebKit/Source/modules/indexeddb/OWNERS index bbe466e53..b48e060 100644 --- a/third_party/WebKit/Source/modules/indexeddb/OWNERS +++ b/third_party/WebKit/Source/modules/indexeddb/OWNERS
@@ -1 +1,3 @@ file://content/browser/indexed_db/OWNERS + +pwnall@chromium.org
diff --git a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp index 55d99ad..ffafadd 100644 --- a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp +++ b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
@@ -433,6 +433,9 @@ } void RemotePlayback::StopListeningForAvailability() { + if (!RuntimeEnabledFeatures::RemotePlaybackBackendEnabled()) + return; + if (!is_listening_) return; @@ -447,6 +450,9 @@ } void RemotePlayback::MaybeStartListeningForAvailability() { + if (!RuntimeEnabledFeatures::RemotePlaybackBackendEnabled()) + return; + if (is_listening_) return;
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 index 46622713..354bea4 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -857,11 +857,11 @@ status: "stable", }, // Whether or not the Remote Playback API backend is implemented. - // Not web-exposed, set per platform. For LayoutTests, always enabled. + // Not web-exposed, set per platform. For LayoutTests, disabled by + // default. { name: "RemotePlaybackBackend", settable_from_internals: true, - status: "test" }, { name: "RenderingPipelineThrottling",
diff --git a/third_party/WebKit/Source/platform/fonts/CustomFontData.h b/third_party/WebKit/Source/platform/fonts/CustomFontData.h index f940ed7a..44a3bd3 100644 --- a/third_party/WebKit/Source/platform/fonts/CustomFontData.h +++ b/third_party/WebKit/Source/platform/fonts/CustomFontData.h
@@ -22,14 +22,14 @@ #define CustomFontData_h #include "platform/PlatformExport.h" -#include "platform/wtf/PassRefPtr.h" #include "platform/wtf/RefCounted.h" +#include "platform/wtf/RefPtr.h" namespace blink { class PLATFORM_EXPORT CustomFontData : public RefCounted<CustomFontData> { public: - static PassRefPtr<CustomFontData> Create() { + static RefPtr<CustomFontData> Create() { return AdoptRef(new CustomFontData()); }
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp index c5734e0..103445d 100644 --- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp +++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp
@@ -356,10 +356,9 @@ glyph_bounding_box_.SetWidth(glyph_bounding_box_.Width() + total_space); } -void ShapeResult::ApplySpacing(ShapeResultSpacing<StringView>& spacing, - const StringView& text, +void ShapeResult::ApplySpacing(ShapeResultSpacing<String>& spacing, TextDirection direction) { - ApplySpacing(spacing, text, direction == TextDirection::kRtl); + ApplySpacing(spacing, spacing.Text(), IsRtl(direction)); } PassRefPtr<ShapeResult> ShapeResult::ApplySpacingToCopy(
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.h b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.h index 1139558e..cfc0560f 100644 --- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.h +++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.h
@@ -91,9 +91,7 @@ return LayoutUnit::FromFloatCeil(PositionForOffset(offset)); } - void ApplySpacing(ShapeResultSpacing<StringView>&, - const StringView&, - TextDirection); + void ApplySpacing(ShapeResultSpacing<String>&, TextDirection); PassRefPtr<ShapeResult> ApplySpacingToCopy(ShapeResultSpacing<TextRun>&, const TextRun&) const;
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultSpacing.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultSpacing.cpp index d475587..3a95cb5 100644 --- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultSpacing.cpp +++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultSpacing.cpp
@@ -65,7 +65,8 @@ if (expansion_) { ComputeExpansion(text_.AllowsLeadingExpansion(), - text_.AllowsTrailingExpansion(), text_.GetTextJustify()); + text_.AllowsTrailingExpansion(), text_.Direction(), + text_.GetTextJustify()); } } @@ -73,6 +74,7 @@ void ShapeResultSpacing<TextContainerType>::ComputeExpansion( bool allows_leading_expansion, bool allows_trailing_expansion, + TextDirection direction, TextJustify text_justify) { DCHECK_GT(expansion_, 0); @@ -80,8 +82,15 @@ is_after_expansion_ = !allows_leading_expansion; bool is_after_expansion = is_after_expansion_; - expansion_opportunity_count_ = - Character::ExpansionOpportunityCount(text_, is_after_expansion); + if (text_.Is8Bit()) { + expansion_opportunity_count_ = Character::ExpansionOpportunityCount( + text_.Characters8(), text_.length(), direction, is_after_expansion, + text_justify_); + } else { + expansion_opportunity_count_ = Character::ExpansionOpportunityCount( + text_.Characters16(), text_.length(), direction, is_after_expansion, + text_justify_); + } if (is_after_expansion && !allows_trailing_expansion) { DCHECK_GT(expansion_opportunity_count_, 0u); --expansion_opportunity_count_; @@ -110,12 +119,20 @@ return expansion_per_opportunity_; } +// Test if the |run| is the first sub-run of the original text container, for +// containers that can create sub-runs such as TextRun or StringView. template <typename TextContainerType> -bool ShapeResultSpacing<TextContainerType>::IsFirstRun( +inline bool ShapeResultSpacing<TextContainerType>::IsFirstRun( const TextContainerType& run) const { return &run == &text_ || run.Bytes() == text_.Bytes(); } +template <> +inline bool ShapeResultSpacing<String>::IsFirstRun(const String& run) const { + // String::Substring() should not be used because it copies to a new buffer. + return &run == &text_ || run.Impl() == text_.Impl(); +} + template <typename TextContainerType> float ShapeResultSpacing<TextContainerType>::ComputeSpacing( const TextContainerType& run, @@ -175,6 +192,6 @@ // Instantiate the template class. template class ShapeResultSpacing<TextRun>; -template class ShapeResultSpacing<StringView>; +template class ShapeResultSpacing<String>; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultSpacing.h b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultSpacing.h index 9e31f41..da429606 100644 --- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultSpacing.h +++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultSpacing.h
@@ -22,8 +22,10 @@ public: ShapeResultSpacing(const TextContainerType&); + const TextContainerType& Text() const { return text_; } float LetterSpacing() const { return letter_spacing_; } bool HasSpacing() const { return has_spacing_; } + bool HasExpansion() const { return expansion_opportunity_count_; } bool IsVerticalOffset() const { return is_vertical_offset_; } // Set letter-spacing and word-spacing. @@ -39,12 +41,12 @@ float ComputeSpacing(const TextContainerType&, size_t, float& offset); private: - bool HasExpansion() const { return expansion_opportunity_count_; } bool IsAfterExpansion() const { return is_after_expansion_; } bool IsFirstRun(const TextContainerType&) const; void ComputeExpansion(bool allows_leading_expansion, bool allows_trailing_expansion, + TextDirection, TextJustify); float NextExpansion();
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp index d306d49..351cb23 100644 --- a/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp +++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp
@@ -8,6 +8,7 @@ #include "platform/fonts/shaping/HarfBuzzShaper.h" #include "platform/fonts/shaping/ShapeResult.h" #include "platform/fonts/shaping/ShapeResultInlineHeaders.h" +#include "platform/fonts/shaping/ShapeResultSpacing.h" #include "platform/text/TextBreakIterator.h" namespace blink { @@ -16,12 +17,18 @@ const HarfBuzzShaper* shaper, const Font* font, const ShapeResult* result, - const LazyLineBreakIterator* break_iterator) + const LazyLineBreakIterator* break_iterator, + ShapeResultSpacing<String>* spacing) : shaper_(shaper), font_(font), result_(result), - break_iterator_(break_iterator) { + break_iterator_(break_iterator), + spacing_(spacing) { text_ = String(shaper->GetText(), shaper->TextLength()); + + // ShapeResultSpacing is stateful when it has expansions. We may use it in + // arbitrary order that it cannot have expansions. + DCHECK(!spacing_ || !spacing_->HasExpansion()); } namespace { @@ -53,23 +60,35 @@ // ShapingLineBreaker computes using visual positions. This function flips // logical advance to visual, or vice versa. LayoutUnit FlipRtl(LayoutUnit value, TextDirection direction) { - return direction != TextDirection::kRtl ? value : -value; + return IsLtr(direction) ? value : -value; } // Snaps a visual position to the line start direction. LayoutUnit SnapStart(float value, TextDirection direction) { - return direction != TextDirection::kRtl ? LayoutUnit::FromFloatFloor(value) - : LayoutUnit::FromFloatCeil(value); + return IsLtr(direction) ? LayoutUnit::FromFloatFloor(value) + : LayoutUnit::FromFloatCeil(value); } // Snaps a visual position to the line end direction. LayoutUnit SnapEnd(float value, TextDirection direction) { - return direction != TextDirection::kRtl ? LayoutUnit::FromFloatCeil(value) - : LayoutUnit::FromFloatFloor(value); + return IsLtr(direction) ? LayoutUnit::FromFloatCeil(value) + : LayoutUnit::FromFloatFloor(value); } } // namespace +inline PassRefPtr<ShapeResult> ShapingLineBreaker::Shape( + TextDirection direction, + unsigned start, + unsigned end) { + if (!spacing_ || !spacing_->HasSpacing()) + return shaper_->Shape(font_, direction, start, end); + + RefPtr<ShapeResult> result = shaper_->Shape(font_, direction, start, end); + result->ApplySpacing(*spacing_, direction); + return result.Release(); +} + // Shapes a line of text by finding a valid and appropriate break opportunity // based on the shaping results for the entire paragraph. Re-shapes the start // and end of the line as needed. @@ -160,7 +179,7 @@ direction) - start_position, direction); - line_start_result = shaper_->Shape(font_, direction, start, first_safe); + line_start_result = Shape(direction, start, first_safe); available_space += line_start_result->SnappedWidth() - original_width; } @@ -180,8 +199,7 @@ result_->PositionForOffset(previous_safe - range_start), direction); while (break_opportunity > previous_safe && previous_safe >= start) { DCHECK_LE(break_opportunity, range_end); - line_end_result = - shaper_->Shape(font_, direction, previous_safe, break_opportunity); + line_end_result = Shape(direction, previous_safe, break_opportunity); if (line_end_result->SnappedWidth() <= FlipRtl(end_position - safe_position, direction)) break; @@ -247,11 +265,11 @@ result_->CopyRange(start, range_end, line_result.Get()); } else if (first_safe < range_end) { // Otherwise reshape to the first safe, then copy the rest. - line_result = shaper_->Shape(font_, direction, start, first_safe); + line_result = Shape(direction, start, first_safe); result_->CopyRange(first_safe, range_end, line_result.Get()); } else { // If no safe-to-break in the ragne, reshape the whole range. - line_result = shaper_->Shape(font_, direction, start, range_end); + line_result = Shape(direction, start, range_end); } return line_result.Release(); }
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.h b/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.h index 75fecc1..f58f070 100644 --- a/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.h +++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.h
@@ -7,6 +7,7 @@ #include "platform/LayoutUnit.h" #include "platform/PlatformExport.h" +#include "platform/text/TextDirection.h" #include "platform/wtf/text/AtomicString.h" namespace blink { @@ -16,6 +17,8 @@ class HarfBuzzShaper; class LazyLineBreakIterator; enum class LineBreakType; +template <typename TextContainerType> +class ShapeResultSpacing; // Shapes a line of text by finding the ideal break position as indicated by the // available space and the shape results for the entire paragraph. Once an ideal @@ -34,7 +37,8 @@ ShapingLineBreaker(const HarfBuzzShaper*, const Font*, const ShapeResult*, - const LazyLineBreakIterator*); + const LazyLineBreakIterator*, + ShapeResultSpacing<String>* = nullptr); ~ShapingLineBreaker() {} // Shapes a line of text by finding a valid and appropriate break opportunity @@ -45,6 +49,7 @@ unsigned* break_offset); private: + PassRefPtr<ShapeResult> Shape(TextDirection, unsigned start, unsigned end); PassRefPtr<ShapeResult> ShapeToEnd(unsigned start, LayoutUnit start_position, unsigned range_end); @@ -54,6 +59,9 @@ const ShapeResult* result_; const LazyLineBreakIterator* break_iterator_; String text_; + // TODO(kojii): ShapeResultSpacing is not const because it's stateful when it + // has expansions. Split spacing and expansions to make this const. + ShapeResultSpacing<String>* spacing_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp index dd03847..97c52ce 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
@@ -768,7 +768,6 @@ // Only one content layer, and the first child layer is the dummy layer for // the transform node. const cc::Layer* transform_node_layer = RootLayer()->children()[0].get(); - EXPECT_EQ(transform_node_layer->id(), transform_node.owning_layer_id); auto transform_node_index = transform_node_layer->transform_tree_index(); EXPECT_EQ(transform_node_index, transform_node.id); @@ -1700,7 +1699,6 @@ const cc::TransformNode* cc_transform_node = GetPropertyTrees().transform_tree.Node( transform_node_layer->transform_tree_index()); - EXPECT_EQ(transform_node_layer->id(), cc_transform_node->owning_layer_id); auto transform_node_index = transform_node_layer->transform_tree_index(); EXPECT_EQ(transform_node_index, cc_transform_node->id); }
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp index 467cd6e..5ef8abd 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp +++ b/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp
@@ -74,10 +74,6 @@ transform_tree.Insert(cc::TransformNode(), kRealRootNodeId)); DCHECK_EQ(transform_node.id, kSecondaryRootNodeId); transform_node.source_node_id = transform_node.parent_id; - // Setting owning layer id on cc property tree transform nodes is temporary - // until we can remove animation subsystem dependency on layer - // references. http://crbug.com/709137 - transform_node.owning_layer_id = root_layer_->id(); // TODO(jaydasika): We shouldn't set ToScreen and FromScreen of root // transform node here. They should be set while updating transform tree in @@ -106,7 +102,6 @@ *clip_tree.Node(clip_tree.Insert(cc::ClipNode(), kRealRootNodeId)); DCHECK_EQ(clip_node.id, kSecondaryRootNodeId); - clip_node.owning_layer_id = root_layer_->id(); clip_node.clip_type = cc::ClipNode::ClipType::APPLIES_LOCAL_CLIP; clip_node.clip = gfx::RectF( gfx::SizeF(root_layer_->layer_tree_host()->device_viewport_size())); @@ -166,10 +161,6 @@ cc::TransformNode& compositor_node = *GetTransformTree().Node(id); compositor_node.source_node_id = parent_id; - // Setting owning layer id on cc property tree transform nodes is temporary - // until we can remove animation subsystem dependency on layer - // references. http://crbug.com/709137 - compositor_node.owning_layer_id = dummy_layer->id(); FloatPoint3D origin = transform_node->Origin(); compositor_node.pre_local.matrix().setTranslate(-origin.X(), -origin.Y(), @@ -222,7 +213,6 @@ int id = GetClipTree().Insert(cc::ClipNode(), parent_id); cc::ClipNode& compositor_node = *GetClipTree().Node(id); - compositor_node.owning_layer_id = dummy_layer->id(); // TODO(jbroman): Don't discard rounded corners. compositor_node.clip = clip_node->ClipRect().Rect();
diff --git a/third_party/WebKit/Source/platform/image-decoders/FastSharedBufferReaderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/FastSharedBufferReaderTest.cpp index 2485265..5eef483 100644 --- a/third_party/WebKit/Source/platform/image-decoders/FastSharedBufferReaderTest.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/FastSharedBufferReaderTest.cpp
@@ -30,6 +30,7 @@ #include "platform/image-decoders/FastSharedBufferReader.h" #include "platform/image-decoders/SegmentReader.h" +#include "third_party/skia/include/core/SkRWBuffer.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h index 2b00aa0..ff36b94 100644 --- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h +++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
@@ -28,8 +28,6 @@ #define ImageDecoder_h #include <memory> -#include "SkColorPriv.h" -#include "SkColorSpaceXform.h" #include "platform/PlatformExport.h" #include "platform/SharedBuffer.h" #include "platform/graphics/ColorBehavior.h" @@ -39,10 +37,10 @@ #include "platform/image-decoders/SegmentReader.h" #include "platform/wtf/Assertions.h" #include "platform/wtf/RefPtr.h" -#include "platform/wtf/Threading.h" #include "platform/wtf/Vector.h" #include "platform/wtf/text/WTFString.h" #include "public/platform/Platform.h" +#include "third_party/skia/include/core/SkColorSpaceXform.h" namespace blink { @@ -100,10 +98,10 @@ static std::unique_ptr<ImageDecoder> Create( PassRefPtr<SharedBuffer> data, bool data_complete, - AlphaOption alphaoption, + AlphaOption alpha_option, const ColorBehavior& color_behavior) { return Create(SegmentReader::CreateFromSharedBuffer(std::move(data)), - data_complete, alphaoption, color_behavior); + data_complete, alpha_option, color_behavior); } virtual String FilenameExtension() const = 0;
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageFrame.h b/third_party/WebKit/Source/platform/image-decoders/ImageFrame.h index 7cd665a2..7c0bbf9 100644 --- a/third_party/WebKit/Source/platform/image-decoders/ImageFrame.h +++ b/third_party/WebKit/Source/platform/image-decoders/ImageFrame.h
@@ -31,11 +31,11 @@ #include "platform/geometry/IntRect.h" #include "platform/wtf/Allocator.h" #include "platform/wtf/Assertions.h" -#include "platform/wtf/PassRefPtr.h" #include "public/platform/WebVector.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColorPriv.h" -#include "third_party/skia/include/core/SkImage.h" + +class SkImage; namespace blink {
diff --git a/third_party/WebKit/Source/platform/image-decoders/SegmentReader.cpp b/third_party/WebKit/Source/platform/image-decoders/SegmentReader.cpp index f40f5e7..fc4ffe9 100644 --- a/third_party/WebKit/Source/platform/image-decoders/SegmentReader.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/SegmentReader.cpp
@@ -11,6 +11,7 @@ #include "platform/wtf/RefPtr.h" #include "platform/wtf/ThreadingPrimitives.h" #include "third_party/skia/include/core/SkData.h" +#include "third_party/skia/include/core/SkRWBuffer.h" namespace blink {
diff --git a/third_party/WebKit/Source/platform/image-decoders/SegmentReader.h b/third_party/WebKit/Source/platform/image-decoders/SegmentReader.h index 8fc14e7..0c99cf2 100644 --- a/third_party/WebKit/Source/platform/image-decoders/SegmentReader.h +++ b/third_party/WebKit/Source/platform/image-decoders/SegmentReader.h
@@ -9,9 +9,9 @@ #include "platform/wtf/Noncopyable.h" #include "platform/wtf/PassRefPtr.h" #include "platform/wtf/ThreadSafeRefCounted.h" -#include "third_party/skia/include/core/SkData.h" -#include "third_party/skia/include/core/SkRWBuffer.h" -#include "third_party/skia/include/core/SkRefCnt.h" + +class SkData; +class SkROBuffer; namespace blink {
diff --git a/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoder.cpp index 5666ef6..b225a10 100644 --- a/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoder.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoder.cpp
@@ -31,6 +31,7 @@ #include "platform/image-decoders/bmp/BMPImageDecoder.h" #include "platform/image-decoders/FastSharedBufferReader.h" +#include "platform/image-decoders/bmp/BMPImageReader.h" #include "platform/wtf/PtrUtil.h" namespace blink { @@ -46,6 +47,8 @@ : ImageDecoder(alpha_option, color_behavior, max_decoded_bytes), decoded_offset_(0) {} +BMPImageDecoder::~BMPImageDecoder() = default; + void BMPImageDecoder::OnSetData(SegmentReader* data) { if (reader_) reader_->SetData(data);
diff --git a/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoder.h index e79a93c..0da6e091 100644 --- a/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoder.h +++ b/third_party/WebKit/Source/platform/image-decoders/bmp/BMPImageDecoder.h
@@ -31,16 +31,20 @@ #ifndef BMPImageDecoder_h #define BMPImageDecoder_h -#include "platform/image-decoders/bmp/BMPImageReader.h" #include <memory> +#include "platform/image-decoders/ImageDecoder.h" namespace blink { +class BMPImageReader; + // This class decodes the BMP image format. class PLATFORM_EXPORT BMPImageDecoder final : public ImageDecoder { public: BMPImageDecoder(AlphaOption, const ColorBehavior&, size_t max_decoded_bytes); + ~BMPImageDecoder() override; + // ImageDecoder: String FilenameExtension() const override { return "bmp"; } void OnSetData(SegmentReader*) override;
diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.cpp b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.cpp index 4759d53..8beecc83 100644 --- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.cpp
@@ -75,6 +75,7 @@ #include "platform/image-decoders/gif/GIFImageReader.h" #include <string.h> +#include "platform/image-decoders/FastSharedBufferReader.h" #include "platform/wtf/PtrUtil.h" namespace blink {
diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.h b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.h index 60d07e4..86a2296 100644 --- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.h +++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.h
@@ -41,7 +41,6 @@ // Define ourselves as the clientPtr. Mozilla just hacked their C++ callback // class into this old C decoder, so we will too. #include <memory> -#include "platform/image-decoders/FastSharedBufferReader.h" #include "platform/image-decoders/gif/GIFImageDecoder.h" #include "platform/wtf/Allocator.h" #include "platform/wtf/Noncopyable.h" @@ -49,6 +48,8 @@ namespace blink { +class FastSharedBufferReader; + const int kCLoopCountNotSeen = -2; // List of possible parsing states.
diff --git a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp index 2fdf29e..57007c3 100644 --- a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp
@@ -28,6 +28,8 @@ #include "platform/image-decoders/webp/WEBPImageDecoder.h" +#include "third_party/skia/include/core/SkData.h" + #if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN) #error Blink assumes a little-endian target. #endif
diff --git a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.h index 483f213..ba2bd3d1 100644 --- a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.h +++ b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.h
@@ -30,10 +30,11 @@ #define WEBPImageDecoder_h #include "platform/image-decoders/ImageDecoder.h" -#include "third_party/skia/include/core/SkData.h" #include "webp/decode.h" #include "webp/demux.h" +class SkData; + namespace blink { class PLATFORM_EXPORT WEBPImageDecoder final : public ImageDecoder {
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp index 6804885..1d1f861b7 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
@@ -178,7 +178,7 @@ } String Resource::CachedMetadataHandlerImpl::Encoding() const { - return resource_->Encoding(); + return String(resource_->Encoding().GetName()); } void Resource::CachedMetadataHandlerImpl::SetSerializedCachedMetadata(
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.h b/third_party/WebKit/Source/platform/loader/fetch/Resource.h index 1b300e9..e1c25fea 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/Resource.h +++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.h
@@ -44,6 +44,7 @@ #include "platform/wtf/HashCountedSet.h" #include "platform/wtf/HashSet.h" #include "platform/wtf/text/AtomicString.h" +#include "platform/wtf/text/TextEncoding.h" #include "platform/wtf/text/WTFString.h" #include "public/platform/WebDataConsumerHandle.h" @@ -105,8 +106,7 @@ DECLARE_VIRTUAL_TRACE(); - virtual void SetEncoding(const String&) {} - virtual String Encoding() const { return String(); } + virtual WTF::TextEncoding Encoding() const { return WTF::TextEncoding(); } virtual void AppendData(const char*, size_t); virtual void FinishAsError(const ResourceError&); virtual void SetCORSFailed() {} @@ -420,6 +420,8 @@ void TriggerNotificationForFinishObservers(); + virtual void SetEncoding(const String&) {} + private: class CachedMetadataHandlerImpl; class ServiceWorkerResponseCachedMetadataHandler;
diff --git a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp index 2f6d1541..d0e10b6 100644 --- a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp +++ b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp
@@ -89,12 +89,6 @@ return FilePathToWebString(BlinkRootFilePath()); } -String ExecutableDir() { - base::FilePath path; - base::PathService::Get(base::DIR_EXE, &path); - return FilePathToWebString(base::MakeAbsoluteFilePath(path)); -} - String WebTestDataPath(const String& relative_path) { return FilePathToWebString( BlinkRootFilePath()
diff --git a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.h b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.h index 6f18cad..3b94f961 100644 --- a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.h +++ b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.h
@@ -52,9 +52,6 @@ // /src/third_party/WebKit. String BlinkRootDir(); -// Returns directory containing the current executable as absolute path. -String ExecutableDir(); - // Returns test data absolute path for webkit_unit_tests, i.e. // <blinkRootDir>/Source/web/tests/data/<relativePath>. // It returns the top web test directory if |relativePath| was not specified.
diff --git a/third_party/WebKit/Source/platform/wtf/PassRefPtr.h b/third_party/WebKit/Source/platform/wtf/PassRefPtr.h index cde758f..b2d9031 100644 --- a/third_party/WebKit/Source/platform/wtf/PassRefPtr.h +++ b/third_party/WebKit/Source/platform/wtf/PassRefPtr.h
@@ -37,10 +37,6 @@ class RefPtr; template <typename T> class PassRefPtr; -template <typename T> -PassRefPtr<T> AdoptRef(T*); - -inline void Adopted(const void*) {} // requireAdoption() is not overloaded for WTF::RefCounted, which has a built-in // assumption that adoption is required. requireAdoption() is for bootstrapping @@ -94,12 +90,7 @@ bool operator!() const { return !ptr_; } explicit operator bool() const { return ptr_ != nullptr; } - friend PassRefPtr AdoptRef<T>(T*); - private: - enum AdoptRefTag { kAdoptRef }; - PassRefPtr(T* ptr, AdoptRefTag) : ptr_(ptr) {} - PassRefPtr& operator=(const PassRefPtr&) { static_assert(!sizeof(T*), "PassRefPtr should never be assigned to"); return *this; @@ -206,12 +197,6 @@ } template <typename T> -PassRefPtr<T> AdoptRef(T* p) { - Adopted(p); - return PassRefPtr<T>(p, PassRefPtr<T>::kAdoptRef); -} - -template <typename T> inline T* GetPtr(const PassRefPtr<T>& p) { return p.Get(); } @@ -219,6 +204,5 @@ } // namespace WTF using WTF::PassRefPtr; -using WTF::AdoptRef; #endif // WTF_PassRefPtr_h
diff --git a/third_party/WebKit/Source/platform/wtf/PassRefPtrTest.cpp b/third_party/WebKit/Source/platform/wtf/PassRefPtrTest.cpp index 2386156..f479330 100644 --- a/third_party/WebKit/Source/platform/wtf/PassRefPtrTest.cpp +++ b/third_party/WebKit/Source/platform/wtf/PassRefPtrTest.cpp
@@ -5,6 +5,7 @@ #include "platform/wtf/PassRefPtr.h" #include "platform/wtf/RefCounted.h" +#include "platform/wtf/RefPtr.h" #include "testing/gtest/include/gtest/gtest.h" namespace WTF {
diff --git a/third_party/WebKit/Source/platform/wtf/RefPtr.h b/third_party/WebKit/Source/platform/wtf/RefPtr.h index b4b8113..01856fc 100644 --- a/third_party/WebKit/Source/platform/wtf/RefPtr.h +++ b/third_party/WebKit/Source/platform/wtf/RefPtr.h
@@ -35,6 +35,13 @@ class PassRefPtr; template <typename T> class RefPtrValuePeeker; +template <typename T> +class RefPtr; + +template <typename T> +RefPtr<T> AdoptRef(T*); + +inline void Adopted(const void*) {} template <typename T> class RefPtr { @@ -52,6 +59,9 @@ RefIfNotNull(ptr_); } RefPtr(RefPtr&& o) : ptr_(o.ptr_) { o.ptr_ = nullptr; } + template <typename U> + RefPtr(RefPtr<U>&& o, EnsurePtrConvertibleArgDecl(U, T)) + : ptr_(o.LeakRef()) {} // See comments in PassRefPtr.h for an explanation of why this takes a const // reference. @@ -70,11 +80,7 @@ ALWAYS_INLINE T* Get() const { return ptr_; } T* LeakRef() WARN_UNUSED_RESULT; void Clear(); - PassRefPtr<T> Release() WARN_UNUSED_RESULT { - PassRefPtr<T> tmp = AdoptRef(ptr_); - ptr_ = nullptr; - return tmp; - } + PassRefPtr<T> Release() WARN_UNUSED_RESULT { return std::move(*this); } T& operator*() const { return *ptr_; } ALWAYS_INLINE T* operator->() const { return ptr_; } @@ -99,6 +105,11 @@ static T* HashTableDeletedValue() { return reinterpret_cast<T*>(-1); } private: + friend RefPtr AdoptRef<T>(T*); + + enum AdoptRefTag { kAdoptRef }; + RefPtr(T* ptr, AdoptRefTag) : ptr_(ptr) {} + T* ptr_; }; @@ -212,8 +223,15 @@ T* ptr_; }; +template <typename T> +RefPtr<T> AdoptRef(T* p) { + Adopted(p); + return RefPtr<T>(p, RefPtr<T>::kAdoptRef); +} + } // namespace WTF using WTF::RefPtr; +using WTF::AdoptRef; #endif // WTF_RefPtr_h
diff --git a/third_party/WebKit/Source/platform/wtf/text/TextCodecICU.cpp b/third_party/WebKit/Source/platform/wtf/text/TextCodecICU.cpp index cb399fe..c940be1 100644 --- a/third_party/WebKit/Source/platform/wtf/text/TextCodecICU.cpp +++ b/third_party/WebKit/Source/platform/wtf/text/TextCodecICU.cpp
@@ -278,7 +278,7 @@ if (cached_converter) { err = U_ZERO_ERROR; const char* cached_name = ucnv_getName(cached_converter, &err); - if (U_SUCCESS(err) && encoding_ == cached_name) { + if (U_SUCCESS(err) && encoding_ == TextEncoding(cached_name)) { converter_icu_ = cached_converter; cached_converter = 0; return;
diff --git a/third_party/WebKit/Source/platform/wtf/text/TextEncoding.h b/third_party/WebKit/Source/platform/wtf/text/TextEncoding.h index 1d2aa86..77db194 100644 --- a/third_party/WebKit/Source/platform/wtf/text/TextEncoding.h +++ b/third_party/WebKit/Source/platform/wtf/text/TextEncoding.h
@@ -39,8 +39,8 @@ public: TextEncoding() : name_(0) {} - TextEncoding(const char* name); - TextEncoding(const String& name); + explicit TextEncoding(const char* name); + explicit TextEncoding(const String& name); bool IsValid() const { return name_; } const char* GetName() const { return name_; }
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp index 6c62292..71d710b 100644 --- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp +++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -83,16 +83,22 @@ WebFrameWidget* WebFrameWidget::Create(WebWidgetClient* client, WebLocalFrame* local_root) { DCHECK(client) << "A valid WebWidgetClient must be supplied."; - // Pass the WebFrameWidget's self-reference to the caller. - return WebFrameWidgetImpl::Create(client, local_root); -} + if (!local_root->Parent()) { + // Note: this isn't a leak, as the object has a self-reference that the + // caller needs to release by calling Close(). + WebLocalFrameBase& main_frame = ToWebLocalFrameBase(*local_root); + DCHECK(main_frame.ViewImpl()); + // Note: this can't DCHECK that the view's main frame points to + // |main_frame|, as provisional frames violate this precondition. + // TODO(dcheng): Remove the special bridge class for main frame widgets. + return new WebViewFrameWidget(*client, *main_frame.ViewImpl(), main_frame); + } -WebFrameWidget* WebFrameWidget::Create(WebWidgetClient* client, - WebView* web_view, - WebLocalFrame* main_frame) { - DCHECK(client) << "A valid WebWidgetClient must be supplied."; - return new WebViewFrameWidget(*client, static_cast<WebViewBase&>(*web_view), - ToWebLocalFrameBase(*main_frame)); + DCHECK(local_root->Parent()->IsWebRemoteFrame()) + << "Only local roots can have web frame widgets."; + // Note: this isn't a leak, as the object has a self-reference that the + // caller needs to release by calling Close(). + return WebFrameWidgetImpl::Create(client, local_root); } WebFrameWidgetImpl* WebFrameWidgetImpl::Create(WebWidgetClient* client,
diff --git a/third_party/WebKit/Source/web/tests/WebViewTest.cpp b/third_party/WebKit/Source/web/tests/WebViewTest.cpp index accdbfd..df90500 100644 --- a/third_party/WebKit/Source/web/tests/WebViewTest.cpp +++ b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
@@ -2064,10 +2064,7 @@ WebTreeScopeType::kDocument, &web_frame_client, nullptr, nullptr); web_frame_client.Bind(local_frame); web_view->SetMainFrame(local_frame); - - // TODO(dcheng): The main frame widget currently has a special case. - // Eliminate this once WebView is no longer a WebWidget. - blink::WebFrameWidget::Create(&web_widget_client, web_view, local_frame); + blink::WebFrameWidget::Create(&web_widget_client, local_frame); WebGestureEvent event(WebInputEvent::kGestureTap, WebInputEvent::kNoModifiers, WebInputEvent::kTimeStampForTesting);
diff --git a/third_party/WebKit/public/web/WebFrameWidget.h b/third_party/WebKit/public/web/WebFrameWidget.h index da2f088..ef2a0bb 100644 --- a/third_party/WebKit/public/web/WebFrameWidget.h +++ b/third_party/WebKit/public/web/WebFrameWidget.h
@@ -41,18 +41,11 @@ class WebDragData; class WebLocalFrame; class WebInputMethodController; -class WebView; class WebWidgetClient; class WebFrameWidget : public WebWidget { public: BLINK_EXPORT static WebFrameWidget* Create(WebWidgetClient*, WebLocalFrame*); - // Creates a frame widget for a WebView. Temporary helper to help transition - // away from WebView inheriting WebWidget. - // TODO(dcheng): Remove once transition is complete. - BLINK_EXPORT static WebFrameWidget* Create(WebWidgetClient*, - WebView*, - WebLocalFrame* main_frame); // Sets the visibility of the WebFrameWidget. // We still track page-level visibility, but additionally we need to notify a
diff --git a/tools/determinism/deterministic_build_whitelist.pyl b/tools/determinism/deterministic_build_whitelist.pyl index c9c4472..5721b9d 100644 --- a/tools/determinism/deterministic_build_whitelist.pyl +++ b/tools/determinism/deterministic_build_whitelist.pyl
@@ -119,6 +119,7 @@ 'message_center_unittests', 'midi_unittests', 'mojo_common_unittests', + 'mojo_js_integration_tests', 'mojo_js_unittests', 'mojo_public_bindings_unittests', 'mojo_public_system_unittests', @@ -275,6 +276,7 @@ 'midi_unittests.exe', 'mini_installer.exe', 'mksnapshot.exe', + 'mojo_js_integration_tests.exe', 'mojo_js_unittests.exe', 'mojo_message_pipe_perftests.exe', 'mojo_public_bindings_perftests.exe',
diff --git a/tools/gn/command_gen.cc b/tools/gn/command_gen.cc index b2ced8f..a665d2c 100644 --- a/tools/gn/command_gen.cc +++ b/tools/gn/command_gen.cc
@@ -37,6 +37,7 @@ const char kSwitchIdeValueVs2013[] = "vs2013"; const char kSwitchIdeValueVs2015[] = "vs2015"; const char kSwitchIdeValueVs2017[] = "vs2017"; +const char kSwitchIdeValueWinSdk[] = "winsdk"; const char kSwitchIdeValueXcode[] = "xcode"; const char kSwitchIdeValueJson[] = "json"; const char kSwitchNinjaExtraArgs[] = "ninja-extra-args"; @@ -207,9 +208,13 @@ std::string filters; if (command_line->HasSwitch(kSwitchFilters)) filters = command_line->GetSwitchValueASCII(kSwitchFilters); + std::string win_kit; + if (command_line->HasSwitch(kSwitchIdeValueWinSdk)) + win_kit = command_line->GetSwitchValueASCII(kSwitchIdeValueWinSdk); bool no_deps = command_line->HasSwitch(kSwitchNoDeps); - bool res = VisualStudioWriter::RunAndWriteFiles( - build_settings, builder, version, sln_name, filters, no_deps, err); + bool res = VisualStudioWriter::RunAndWriteFiles(build_settings, builder, + version, sln_name, filters, + win_kit, no_deps, err); if (res && !quiet) { OutputString("Generating Visual Studio projects took " + base::Int64ToString(timer.Elapsed().InMilliseconds()) + @@ -321,6 +326,11 @@ Don't include targets dependencies to the solution. Changes the way how --filters option works. Only directly matching targets are included. + --winsdk=<sdk_version> + Use the specified Windows 10 SDK version to generate project files. + As an example, "10.0.15063.0" can be specified to use Creators Update SDK + instead of the default one. + Xcode Flags --workspace=<file_name>
diff --git a/tools/gn/visual_studio_writer.cc b/tools/gn/visual_studio_writer.cc index a498fb9..eede7f4 100644 --- a/tools/gn/visual_studio_writer.cc +++ b/tools/gn/visual_studio_writer.cc
@@ -74,12 +74,12 @@ const char kToolsetVersionVs2017[] = "v141"; // Visual Studio 2017 const char kProjectVersionVs2013[] = "12.0"; // Visual Studio 2013 const char kProjectVersionVs2015[] = "14.0"; // Visual Studio 2015 -const char kProjectVersionVs2017[] = "15.0"; // Visual Studio 2015 +const char kProjectVersionVs2017[] = "15.0"; // Visual Studio 2017 const char kVersionStringVs2013[] = "Visual Studio 2013"; // Visual Studio 2013 const char kVersionStringVs2015[] = "Visual Studio 2015"; // Visual Studio 2015 const char kVersionStringVs2017[] = "Visual Studio 2017"; // Visual Studio 2017 const char kWindowsKitsVersion[] = "10"; // Windows 10 SDK -const char kWindowsKitsIncludeVersion[] = "10.0.14393.0"; // Windows 10 SDK +const char kWindowsKitsDefaultVersion[] = "10.0.14393.0"; // Windows 10 SDK const char kGuidTypeProject[] = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"; const char kGuidTypeFolder[] = "{2150E333-8FDC-42A3-9474-1A3956D46DE8}"; @@ -89,7 +89,7 @@ const char kConfigurationName[] = "GN"; -std::string GetWindowsKitsIncludeDirs() { +std::string GetWindowsKitsIncludeDirs(const std::string& win_kit) { std::string kits_path; #if defined(OS_WIN) @@ -115,9 +115,8 @@ kWindowsKitsVersion + "\\"; } - return kits_path + "Include\\" + kWindowsKitsIncludeVersion + "\\shared;" + - kits_path + "Include\\" + kWindowsKitsIncludeVersion + "\\um;" + - kits_path + "Include\\" + kWindowsKitsIncludeVersion + "\\winrt;"; + const std::string kit_prefix = kits_path + "Include\\" + win_kit + "\\"; + return kit_prefix + "shared;" + kit_prefix + "um;" + kit_prefix + "winrt;"; } std::string GetConfigurationType(const Target* target, Err* err) { @@ -259,12 +258,16 @@ VisualStudioWriter::VisualStudioWriter(const BuildSettings* build_settings, const char* config_platform, - Version version) + Version version, + const std::string& win_kit) : build_settings_(build_settings), config_platform_(config_platform), ninja_path_output_(build_settings->build_dir(), build_settings->root_path_utf8(), - EscapingMode::ESCAPE_NINJA_COMMAND) { + EscapingMode::ESCAPE_NINJA_COMMAND), + windows_sdk_version_(win_kit) { + DCHECK(!win_kit.empty()); + switch (version) { case Version::Vs2013: project_version_ = kProjectVersionVs2013; @@ -285,7 +288,7 @@ NOTREACHED() << "Not a valid Visual Studio Version: " << version; } - windows_kits_include_dirs_ = GetWindowsKitsIncludeDirs(); + windows_kits_include_dirs_ = GetWindowsKitsIncludeDirs(win_kit); } VisualStudioWriter::~VisualStudioWriter() { @@ -297,12 +300,17 @@ Version version, const std::string& sln_name, const std::string& filters, + const std::string& win_sdk, bool no_deps, Err* err) { std::vector<const Target*> targets; if (!FilterTargets(build_settings, builder, filters, no_deps, &targets, err)) return false; + std::string win_kit = kWindowsKitsDefaultVersion; + if (!win_sdk.empty()) + win_kit = win_sdk; + const char* config_platform = "Win32"; // Assume the "target_cpu" variable does not change between different @@ -315,7 +323,7 @@ config_platform = "x64"; } - VisualStudioWriter writer(build_settings, config_platform, version); + VisualStudioWriter writer(build_settings, config_platform, version, win_kit); writer.projects_.reserve(targets.size()); writer.folders_.reserve(targets.size()); @@ -436,7 +444,7 @@ globals->SubElement("IgnoreWarnCompileDuplicatedFilename")->Text("true"); globals->SubElement("PreferredToolArchitecture")->Text("x64"); globals->SubElement("WindowsTargetPlatformVersion") - ->Text(kWindowsKitsIncludeVersion); + ->Text(windows_sdk_version_); } project.SubElement(
diff --git a/tools/gn/visual_studio_writer.h b/tools/gn/visual_studio_writer.h index 17935731..db2f3ea 100644 --- a/tools/gn/visual_studio_writer.h +++ b/tools/gn/visual_studio_writer.h
@@ -37,12 +37,14 @@ // semicolon-separated list of label patterns used to limit the set of // generated projects. Only matching targets and their dependencies (unless // |no_deps| is true) will be included to the solution. On failure will - // populate |err| and will return false. + // populate |err| and will return false. |win_sdk| is the Windows SDK version + // which will be used by Visual Studio IntelliSense. static bool RunAndWriteFiles(const BuildSettings* build_settings, const Builder& builder, Version version, const std::string& sln_name, const std::string& filters, + const std::string& win_sdk, bool no_deps, Err* err); @@ -98,7 +100,8 @@ VisualStudioWriter(const BuildSettings* build_settings, const char* config_platform, - Version version); + Version version, + const std::string& win_kit); ~VisualStudioWriter(); bool WriteProjectFiles(const Target* target, Err* err); @@ -150,6 +153,9 @@ // Path formatter for ninja targets. PathOutput ninja_path_output_; + // Windows 10 SDK version string (e.g. 10.0.14393.0) + std::string windows_sdk_version_; + DISALLOW_COPY_AND_ASSIGN(VisualStudioWriter); };
diff --git a/tools/gn/visual_studio_writer_unittest.cc b/tools/gn/visual_studio_writer_unittest.cc index f89c1c1..1ad7c61c 100644 --- a/tools/gn/visual_studio_writer_unittest.cc +++ b/tools/gn/visual_studio_writer_unittest.cc
@@ -28,7 +28,8 @@ TEST_F(VisualStudioWriterTest, ResolveSolutionFolders) { VisualStudioWriter writer(setup_.build_settings(), "Win32", - VisualStudioWriter::Version::Vs2015); + VisualStudioWriter::Version::Vs2015, + "10.0.14393.0"); std::string path = MakeTestPath("/foo/chromium/src/out/Debug/obj/base/base.vcxproj"); @@ -82,7 +83,8 @@ TEST_F(VisualStudioWriterTest, ResolveSolutionFolders_AbsPath) { VisualStudioWriter writer(setup_.build_settings(), "Win32", - VisualStudioWriter::Version::Vs2015); + VisualStudioWriter::Version::Vs2015, + "10.0.14393.0"); std::string path = MakeTestPath("/foo/chromium/src/out/Debug/obj/base/base.vcxproj");
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 00b77cd..89839114 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -3894,6 +3894,14 @@ <int value="20" label="FutureCat (>10.10), 8-bit (?)"/> </enum> +<enum name="CdmHostVerificationStatus"> + <int value="0" label="Not Called"/> + <int value="1" label="Success"/> + <int value="2" label="CDM Load Failed"/> + <int value="3" label="Get Function Failed"/> + <int value="4" label="Init Verification Failed"/> +</enum> + <enum name="CdmPromiseResult"> <int value="0" label="Success"/> <int value="1" label="NotSupportedError"/> @@ -22163,7 +22171,6 @@ <int value="-1460462432" label="disable-media-source"/> <int value="-1456004000" label="VrShell:disabled"/> <int value="-1450576851" label="OmniboxUIExperimentVerticalLayout:enabled"/> - <int value="-1444051091" label="ash-disable-night-light"/> <int value="-1443796945" label="OfflinePagesSharing:disabled"/> <int value="-1440440375" label="WebVrAutopresent:enabled"/> <int value="-1440152291" label="disable-gesture-typing"/> @@ -23023,6 +23030,7 @@ <int value="1657713458" label="disable-virtual-keyboard-overscroll"/> <int value="1658644418" label="disable-app-list-voice-search"/> <int value="1661925474" label="silent-debugger-extension-api"/> + <int value="1664401033" label="ColorCorrectRendering:enabled"/> <int value="1668611601" label="enable-encrypted-media"/> <int value="1673427566" label="ChromeHomeExpandButton:disabled"/> <int value="1689123607" label="enable-app-link"/> @@ -23035,6 +23043,7 @@ <int value="1701972870" label="NTPSnippetsIncreasedVisibility:enabled"/> <int value="1702821235" label="WebAssembly:enabled"/> <int value="1705724232" label="use-android-midi-api"/> + <int value="1713230497" label="ColorCorrectRendering:disabled"/> <int value="1723601083" label="enable-app-window-controls"/> <int value="1724800383" label="AsmJsToWebAssembly:disabled"/> <int value="1730094138" label="enable-md-storage-manager"/> @@ -37847,6 +37856,7 @@ <int value="0" label="No WebContents"/> <int value="1" label="Prerendered WebContents"/> <int value="2" label="Spare WebContents"/> + <int value="3" label="Transferred WebContents"/> </enum> <enum name="WebFontCacheHit">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index c053a7a..8a6d4ca 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -28618,6 +28618,14 @@ </summary> </histogram> +<histogram name="Media.EME.CdmHostVerificationStatus" + enum="CdmHostVerificationStatus"> + <owner>media-dev@chromium.org</owner> + <summary> + The status of CDM host verification. This is reported per CDM load. + </summary> +</histogram> + <histogram name="Media.EME.CdmInterfaceVersion"> <owner>xhwang@chromium.org</owner> <summary> @@ -74131,6 +74139,33 @@ </summary> </histogram> +<histogram name="SubresourceFilter.PageLoad.Activation.CPUDuration" + units="microseconds"> + <owner>csharrison@chromium.org</owner> + <summary> + Records how much thread CPU time it takes to decide whether subresource + filtering should be activated for a main frame. + </summary> +</histogram> + +<histogram name="SubresourceFilter.PageLoad.Activation.WallDuration" + units="microseconds"> + <owner>csharrison@chromium.org</owner> + <summary> + Records how long it takes to decide whether subresource filtering should be + activated for a main frame. + </summary> +</histogram> + +<histogram name="SubresourceFilter.PageLoad.ActivationState" + enum="SubresourceFilterActivationState"> + <owner>csharrison@chromium.org</owner> + <summary> + Whenever a document load is committed in a main frame, records whether + subresource filtering should be activated for that load. + </summary> +</histogram> + <histogram name="SubresourceFilter.PageLoad.FinalURLMatch" units="matches"> <owner>melandory@chromium.org</owner> <summary>
diff --git a/tools/perf/docs/OWNERS b/tools/perf/docs/OWNERS deleted file mode 100644 index a85fa5e6..0000000 --- a/tools/perf/docs/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -per-file apk_size_regressions.md=agrieve@chromium.org
diff --git a/ui/accessibility/ax_tree_combiner.cc b/ui/accessibility/ax_tree_combiner.cc index ae73652..68a9c8b 100644 --- a/ui/accessibility/ax_tree_combiner.cc +++ b/ui/accessibility/ax_tree_combiner.cc
@@ -40,7 +40,7 @@ ProcessTree(root); // Set the root id. - combined_.root_id = combined_.nodes[0].id; + combined_.root_id = combined_.nodes.size() > 0 ? combined_.nodes[0].id : 0; // Finally, handle the tree ID, taking into account which subtree might // have focus and mapping IDs from the tree data appropriately.
diff --git a/ui/accessibility/ax_tree_combiner_unittest.cc b/ui/accessibility/ax_tree_combiner_unittest.cc index b80771d..70f861c0 100644 --- a/ui/accessibility/ax_tree_combiner_unittest.cc +++ b/ui/accessibility/ax_tree_combiner_unittest.cc
@@ -192,4 +192,15 @@ EXPECT_EQ(6, combined.tree_data.focus_id); } +TEST(CombineAXTreesTest, EmptyTree) { + AXTreeUpdate tree; + + AXTreeCombiner combiner; + combiner.AddTree(tree, true); + combiner.Combine(); + + const AXTreeUpdate& combined = combiner.combined(); + ASSERT_EQ(0U, combined.nodes.size()); +} + } // namespace ui
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index e76925d..d8a0150 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -134,7 +134,7 @@ command_line->HasSwitch(cc::switches::kUIEnableLayerLists); settings.enable_color_correct_rasterization = - command_line->HasSwitch(switches::kEnableColorCorrectRendering); + base::FeatureList::IsEnabled(features::kColorCorrectRendering); // UI compositor always uses partial raster if not using zero-copy. Zero copy // doesn't currently support partial raster.
diff --git a/ui/compositor/compositor_util.cc b/ui/compositor/compositor_util.cc index 20231eb..0ced0a7e 100644 --- a/ui/compositor/compositor_util.cc +++ b/ui/compositor/compositor_util.cc
@@ -29,7 +29,7 @@ renderer_settings.show_overdraw_feedback = command_line->HasSwitch(cc::switches::kShowOverdrawFeedback); renderer_settings.enable_color_correct_rendering = - command_line->HasSwitch(switches::kEnableColorCorrectRendering) || + base::FeatureList::IsEnabled(features::kColorCorrectRendering) || command_line->HasSwitch(switches::kEnableHDR); // Populate buffer_to_texture_target_map for all buffer usage/formats. for (int usage_idx = 0; usage_idx <= static_cast<int>(gfx::BufferUsage::LAST);
diff --git a/ui/display/mac/screen_mac.mm b/ui/display/mac/screen_mac.mm index d74ab25c..d9d07345 100644 --- a/ui/display/mac/screen_mac.mm +++ b/ui/display/mac/screen_mac.mm
@@ -84,8 +84,7 @@ // https://crbug.com/654488 CGColorSpaceRef color_space = [[screen colorSpace] CGColorSpace]; static bool color_correct_rendering_enabled = - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableColorCorrectRendering); + base::FeatureList::IsEnabled(features::kColorCorrectRendering); if (base::mac::IsAtLeastOS10_12() && !color_correct_rendering_enabled) color_space = base::mac::GetSystemColorSpace();
diff --git a/ui/gfx/color_space_switches.cc b/ui/gfx/color_space_switches.cc index 33295ee..31e7ca8 100644 --- a/ui/gfx/color_space_switches.cc +++ b/ui/gfx/color_space_switches.cc
@@ -5,11 +5,14 @@ #include "ui/gfx/color_space_switches.h" #include "build/build_config.h" -namespace switches { +namespace features { -// Convert rasterization and compositing inputs to the output color space -// before operating on them. -const char kEnableColorCorrectRendering[] = "enable-color-correct-rendering"; +const base::Feature kColorCorrectRendering{"ColorCorrectRendering", + base::FEATURE_DISABLED_BY_DEFAULT}; + +} // namespace features + +namespace switches { // Force all monitors to be treated as though they have the specified color // profile. Accepted values are "srgb" and "generic-rgb" (currently used by Mac
diff --git a/ui/gfx/color_space_switches.h b/ui/gfx/color_space_switches.h index 904eca3..0af262b 100644 --- a/ui/gfx/color_space_switches.h +++ b/ui/gfx/color_space_switches.h
@@ -5,12 +5,17 @@ #ifndef UI_GFX_COLOR_SPACE_SWITCHES_H_ #define UI_GFX_COLOR_SPACE_SWITCHES_H_ +#include "base/feature_list.h" #include "build/build_config.h" #include "ui/gfx/switches_export.h" -namespace switches { +namespace features { -GFX_SWITCHES_EXPORT extern const char kEnableColorCorrectRendering[]; +GFX_SWITCHES_EXPORT extern const base::Feature kColorCorrectRendering; + +} // namespace features + +namespace switches { GFX_SWITCHES_EXPORT extern const char kForceColorProfile[];
diff --git a/ui/gfx/mac/io_surface.cc b/ui/gfx/mac/io_surface.cc index 8fb16032..ee10bf3 100644 --- a/ui/gfx/mac/io_surface.cc +++ b/ui/gfx/mac/io_surface.cc
@@ -210,8 +210,7 @@ // Ensure that all IOSurfaces start as sRGB when color correct rendering // is enabled. static bool color_correct_rendering_enabled = - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableColorCorrectRendering); + base::FeatureList::IsEnabled(features::kColorCorrectRendering); if (color_correct_rendering_enabled) force_color_space = true;
diff --git a/ui/gl/gl_context.cc b/ui/gl/gl_context.cc index 08a0c78b..0f3b3561 100644 --- a/ui/gl/gl_context.cc +++ b/ui/gl/gl_context.cc
@@ -136,6 +136,10 @@ InitializeDynamicBindings(); } +void GLContext::ForceReleaseVirtuallyCurrent() { + NOTREACHED(); +} + bool GLContext::HasExtension(const char* name) { std::string extensions = GetExtensions(); extensions += " ";
diff --git a/ui/gl/gl_context.h b/ui/gl/gl_context.h index 69f4c38..0d1aa6d 100644 --- a/ui/gl/gl_context.h +++ b/ui/gl/gl_context.h
@@ -176,6 +176,11 @@ // extension entry points. void ReinitializeDynamicBindings(); + // Forces this context, which must be a virtual context, to be no + // longer considered virtually current. The real context remains + // current. + virtual void ForceReleaseVirtuallyCurrent(); + protected: virtual ~GLContext();
diff --git a/ui/ozone/BUILD.gn b/ui/ozone/BUILD.gn index 9681153..36a73ff366 100644 --- a/ui/ozone/BUILD.gn +++ b/ui/ozone/BUILD.gn
@@ -138,6 +138,7 @@ ":ozone_base", "//base", "//ipc", + "//services/service_manager/public/cpp", "//skia", "//ui/display/types", "//ui/events",
diff --git a/ui/ozone/DEPS b/ui/ozone/DEPS index e76be7b..1ac3a7a 100644 --- a/ui/ozone/DEPS +++ b/ui/ozone/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+services/service_manager/public/cpp", "+skia/ext", "+third_party/khronos", "+third_party/skia",
diff --git a/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc b/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc index 4b4913b..7c3cba7 100644 --- a/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc +++ b/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
@@ -103,6 +103,9 @@ return; } + // TODO(dcastagna): remove glFlush since eglImageFlushExternalEXT called on + // the image should be enough (crbug.com/720045). + glFlush(); unsubmitted_frames_.back()->Flush(); SwapCompletionCallback surface_swap_callback = base::Bind(
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h index 8dc9fe3..a6f87c7 100644 --- a/ui/ozone/public/ozone_platform.h +++ b/ui/ozone/public/ozone_platform.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/message_loop/message_loop.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "ui/ozone/ozone_export.h" namespace display { @@ -24,7 +25,6 @@ } namespace service_manager { -class BinderRegistry; class Connector; }
diff --git a/ui/views/window/dialog_delegate.cc b/ui/views/window/dialog_delegate.cc index b02a804..0acad06b 100644 --- a/ui/views/window/dialog_delegate.cc +++ b/ui/views/window/dialog_delegate.cc
@@ -194,17 +194,15 @@ NonClientFrameView* DialogDelegate::CreateNonClientFrameView(Widget* widget) { if (ShouldUseCustomFrame()) - return CreateDialogFrameView(widget, gfx::Insets()); + return CreateDialogFrameView(widget); return WidgetDelegate::CreateNonClientFrameView(widget); } // static -NonClientFrameView* DialogDelegate::CreateDialogFrameView( - Widget* widget, - const gfx::Insets& content_margins) { +NonClientFrameView* DialogDelegate::CreateDialogFrameView(Widget* widget) { BubbleFrameView* frame = new BubbleFrameView( LayoutProvider::Get()->GetInsetsMetric(INSETS_DIALOG_TITLE), - content_margins); + gfx::Insets()); const BubbleBorder::Shadow kShadow = BubbleBorder::SMALL_SHADOW; std::unique_ptr<BubbleBorder> border( new BubbleBorder(BubbleBorder::FLOAT, kShadow, gfx::kPlaceholderColor));
diff --git a/ui/views/window/dialog_delegate.h b/ui/views/window/dialog_delegate.h index becd0692..054edfe 100644 --- a/ui/views/window/dialog_delegate.h +++ b/ui/views/window/dialog_delegate.h
@@ -104,12 +104,7 @@ ClientView* CreateClientView(Widget* widget) override; NonClientFrameView* CreateNonClientFrameView(Widget* widget) override; - // Create a frame view using the new dialog style. - // |content_margins|: margins between the content and the inside of the - // border, in pixels. - static NonClientFrameView* CreateDialogFrameView( - Widget* widget, - const gfx::Insets& content_margins); + static NonClientFrameView* CreateDialogFrameView(Widget* widget); // Returns true if this particular dialog should use a Chrome-styled frame // like the one used for bubbles. The alternative is a more platform-native