diff --git a/DEPS b/DEPS index 00884e4..21df65c2 100644 --- a/DEPS +++ b/DEPS
@@ -133,11 +133,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': '7e603db010683f5123f267cefefabc33f33024d4', + 'skia_revision': '3fd1841161d17c99a916da6fc0a2f8e5f06b962d', # 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': 'ed14aba38a9580529707e04a9b06a74f542e3f90', + 'v8_revision': '5b1fde36ed3b4790d61938274cd83cfe88217ce4', # 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. @@ -145,15 +145,15 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'e25ff9d82c06d1fba7c31a4a2c2678cc68e10fd6', + 'angle_revision': '6f0c5b8dd5f2647131e345edea353419d5f35ed2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'dcc9fd7958e79ed3eb1fcc7e7f06a5545988f64e', + 'swiftshader_revision': 'bb12b0e41a091fe6b76003e66f08196b88290a81', # 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': 'b33a01115c28d6ec31c3bbd5df0444f56a0ce824', + 'pdfium_revision': '06d1acb7eb78a56699be59ca7f1d4fdf2bf64692', # 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. @@ -806,7 +806,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'ed8036a40a27a1ec37e686b782a0066f69392935', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c467474e3a7a3d07908a2ecbc5bd81266ced9c13', 'condition': 'checkout_linux', }, @@ -831,7 +831,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '5f6b911ad015b2660547353753bcfe50ae932fe2', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'ccd2b4da9a7e6ddf126c0b4437db75201836154c', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1028,7 +1028,7 @@ }, 'src/third_party/leveldatabase/src': - Var('chromium_git') + '/external/leveldb.git' + '@' + '3dc9202f78a3eb30ee8c0267e4e4be2e3f986e45', + Var('chromium_git') + '/external/leveldb.git' + '@' + '506b1722ef1a58d87325575d9bbcd3c8869381c7', 'src/third_party/libFuzzer/src': Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git' + '@' + Var('libfuzzer_revision'), @@ -1184,7 +1184,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'caf3ef834ff80712738fc18c17c96468a8d89969', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '4d8300d86dec31f314d95271fd40ec210b0bf74a', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1396,7 +1396,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1499f5591e06f8ed8e04af29f929d10cb4c4b83b', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f3f53a5470410b6ca96542c03e04d185a984a099', 'condition': 'checkout_src_internal', },
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index af1fec2..c36336c 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc
@@ -1902,7 +1902,8 @@ bool AcceleratorController::ShouldSwapSideVolumeButtons( int source_device_id) const { - if (!Shell::Get() + if (!features::IsSwapSideVolumeButtonsForOrientationEnabled() || + !Shell::Get() ->tablet_mode_controller() ->IsTabletModeWindowManagerEnabled() || !IsSideVolumeButton(source_device_id)) {
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc index 14d710a2..9c4abf2 100644 --- a/ash/accelerators/accelerator_controller_unittest.cc +++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -20,6 +20,7 @@ #include "ash/magnifier/docked_magnifier_controller.h" #include "ash/magnifier/magnification_controller.h" #include "ash/media/media_controller.h" +#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/interfaces/ime_info.mojom.h" @@ -1114,6 +1115,8 @@ ws::InputDeviceClientTestApi().SetUncategorizedDevices({ui::InputDevice( kSideVolumeButtonId, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, "cros_ec_buttons")}); + scoped_feature_list_.InitAndEnableFeature( + features::kSwapSideVolumeButtonsForOrientation); } bool IsLeftOrRightSide() const { @@ -1127,6 +1130,7 @@ private: std::string region_, side_; + base::test::ScopedFeatureList scoped_feature_list_; DISALLOW_COPY_AND_ASSIGN(SideVolumeButtonAcceleratorTest); };
diff --git a/ash/app_list/app_list_metrics.h b/ash/app_list/app_list_metrics.h index cdb19d1..afdc671 100644 --- a/ash/app_list/app_list_metrics.h +++ b/ash/app_list/app_list_metrics.h
@@ -245,7 +245,13 @@ kEnterOverviewMode, // Exit the overview mode in tablet - kExitOverviewMode + kExitOverviewMode, + + // Enter the kFullscreenAllApps state (usually by deactivating the search box) + kEnterFullscreenAllApps, + + // Enter the kFullscreenSearch state (usually by activating the search box). + kEnterFullscreenSearch }; void RecordFolderShowHideAnimationSmoothness(int actual_frames,
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc index 0ff2632..56cd088 100644 --- a/ash/app_list/app_list_presenter_delegate_unittest.cc +++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -51,6 +51,7 @@ #include "ui/aura/client/aura_constants.h" #include "ui/aura/test/test_windows.h" #include "ui/aura/window.h" +#include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/display/display.h" #include "ui/display/manager/display_manager.h" #include "ui/display/screen.h" @@ -249,6 +250,40 @@ EXPECT_EQ(mojom::AppListViewState::kPeeking, app_list_view->app_list_state()); } +// Verifies that clicking on the search box in tablet mode with animation and +// zero state enabled should not bring Chrome crash (https://crbug.com/958267). +TEST_F(AppListPresenterDelegateZeroStateTest, ClickSearchBoxInTabletMode) { + // Necessary for AppListView::StateAnimationMetricsReporter::Report being + // called when animation ends. + ui::ScopedAnimationDurationScaleMode non_zero_duration_mode( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + app_list::AppListView::SetShortAnimationForTesting(false); + + EnableTabletMode(true); + GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId()); + GetAppListTestHelper()->CheckState( + ash::mojom::AppListViewState::kFullscreenAllApps); + ui::test::EventGenerator* generator = GetEventGenerator(); + + // Click on the search box. + generator->MoveMouseTo(GetPointInsideSearchbox()); + generator->ClickLeftButton(); + + // Wait until animation finishes. Verifies AppListView's state. + base::RunLoop().RunUntilIdle(); + GetAppListTestHelper()->CheckState( + ash::mojom::AppListViewState::kFullscreenSearch); + + // Click on the area out of search box. + generator->MoveMouseTo(GetPointOutsideSearchbox()); + generator->ClickLeftButton(); + + // Wait until animation finishes. Verifies AppListView's state. + base::RunLoop().RunUntilIdle(); + GetAppListTestHelper()->CheckState( + ash::mojom::AppListViewState::kFullscreenAllApps); +} + TEST_F(PopulatedAppListTest, TappingAppsGridClosesVirtualKeyboard) { InitializeAppsGrid(); app_list_test_model_->PopulateApps(2);
diff --git a/ash/app_list/presenter/app_list_presenter_impl.cc b/ash/app_list/presenter/app_list_presenter_impl.cc index 4d1d5b6..7218127 100644 --- a/ash/app_list/presenter/app_list_presenter_impl.cc +++ b/ash/app_list/presenter/app_list_presenter_impl.cc
@@ -332,6 +332,11 @@ views::Widget* widget = view_->GetWidget(); ui::Layer* layer = GetLayer(widget); layer->GetAnimator()->StopAnimating(); + + // Reset animation metrics reporter for AppListView when the animation is + // interrupted. + view_->ResetTransitionMetricsReporter(); + aura::Window* root_window = widget->GetNativeView()->GetRootWindow(); const gfx::Vector2d offset = delegate_->GetVisibilityAnimationOffset(root_window);
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc index 109be11d..bd77dddd 100644 --- a/ash/app_list/views/app_list_view.cc +++ b/ash/app_list/views/app_list_view.cc
@@ -294,6 +294,18 @@ "Apps.HomeLauncherTransition.AnimationSmoothness.ExitOverview", value); break; + case TabletModeAnimationTransition::kEnterFullscreenAllApps: + UMA_HISTOGRAM_PERCENTAGE( + "Apps.HomeLauncherTransition.AnimationSmoothness." + "EnterFullscreenAllApps", + value); + break; + case TabletModeAnimationTransition::kEnterFullscreenSearch: + UMA_HISTOGRAM_PERCENTAGE( + "Apps.HomeLauncherTransition.AnimationSmoothness." + "EnterFullscreenSearch", + value); + break; } } @@ -1485,14 +1497,31 @@ ui::LayerAnimator* animator = layer->GetAnimator(); animator->StopAnimating(); + + // Reset animation metrics reporter when animation is interrupted. + ResetTransitionMetricsReporter(); + ui::ScopedLayerAnimationSettings settings(animator); settings.SetTransitionDuration( base::TimeDelta::FromMilliseconds(animation_duration)); settings.SetTweenType(gfx::Tween::EASE_OUT); settings.SetPreemptionStrategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - state_animation_metrics_reporter_->SetTargetState(target_state); - settings.SetAnimationMetricsReporter(state_animation_metrics_reporter_.get()); + + if (!is_tablet_mode_) { + state_animation_metrics_reporter_->SetTargetState(target_state); + } else { + DCHECK(target_state == ash::mojom::AppListViewState::kFullscreenAllApps || + target_state == ash::mojom::AppListViewState::kFullscreenSearch); + TabletModeAnimationTransition transition_type = + target_state == ash::mojom::AppListViewState::kFullscreenAllApps + ? TabletModeAnimationTransition::kEnterFullscreenAllApps + : TabletModeAnimationTransition::kEnterFullscreenSearch; + state_animation_metrics_reporter_->SetTabletModeAnimationTransition( + transition_type); + } + + settings.SetAnimationMetricsReporter(GetStateTransitionMetricsReporter()); settings.AddObserver(transition_animation_observer_.get()); layer->SetTransform(gfx::Transform());
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc index 155e8ad..79a39a8 100644 --- a/ash/public/cpp/ash_features.cc +++ b/ash/public/cpp/ash_features.cc
@@ -78,6 +78,9 @@ const base::Feature kSystemTrayFeaturePodsPagination{ "SystemTrayFeaturePodsPagination", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kSwapSideVolumeButtonsForOrientation{ + "SwapSideVolumeButtonsForOrientation", base::FEATURE_DISABLED_BY_DEFAULT}; + bool IsHideArcMediaNotificationsEnabled() { return base::FeatureList::IsEnabled(kMediaSessionNotification) && base::FeatureList::IsEnabled(kHideArcMediaNotifications); @@ -147,5 +150,9 @@ return base::FeatureList::IsEnabled(kSystemTrayFeaturePodsPagination); } +bool IsSwapSideVolumeButtonsForOrientationEnabled() { + return base::FeatureList::IsEnabled(kSwapSideVolumeButtonsForOrientation); +} + } // namespace features } // namespace ash
diff --git a/ash/public/cpp/ash_features.h b/ash/public/cpp/ash_features.h index b40a4412..295b433 100644 --- a/ash/public/cpp/ash_features.h +++ b/ash/public/cpp/ash_features.h
@@ -95,6 +95,12 @@ // Enables pagination for feature pod buttons in the system tray ASH_PUBLIC_EXPORT extern const base::Feature kSystemTrayFeaturePodsPagination; +// Enables side volume button control based on screen orientation feature. +// TODO(https://crbug.com/937907): Remove this after the feature is fully +// launched. +ASH_PUBLIC_EXPORT extern const base::Feature + kSwapSideVolumeButtonsForOrientation; + ASH_PUBLIC_EXPORT bool IsHideArcMediaNotificationsEnabled(); ASH_PUBLIC_EXPORT bool IsKeyboardShortcutViewerAppEnabled(); @@ -127,6 +133,8 @@ ASH_PUBLIC_EXPORT bool IsSystemTrayFeaturePodsPaginationEnabled(); +ASH_PUBLIC_EXPORT bool IsSwapSideVolumeButtonsForOrientationEnabled(); + } // namespace features } // namespace ash
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc index 8ed3481f..5ae6f47d 100644 --- a/base/message_loop/message_loop.cc +++ b/base/message_loop/message_loop.cc
@@ -208,10 +208,6 @@ sequence_manager_->SetTimerSlack(timer_slack); } -std::string MessageLoop::GetThreadName() const { - return sequence_manager_->GetThreadName(); -} - scoped_refptr<SingleThreadTaskRunner> MessageLoop::task_runner() const { return sequence_manager_->GetTaskRunner(); }
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h index ddfed50..f3dde6e 100644 --- a/base/message_loop/message_loop.h +++ b/base/message_loop/message_loop.h
@@ -152,13 +152,6 @@ // Returns the type passed to the constructor. Type type() const { return type_; } - // Returns the name of the thread this message loop is bound to. This function - // is only valid when this message loop is running, BindToCurrentThread has - // already been called and has an "happens-before" relationship with this call - // (this relationship is obtained implicitly by the MessageLoop's task posting - // system unless calling this very early). - std::string GetThreadName() const; - // Sets a new TaskRunner for this message loop. If the message loop was // already bound, this must be called on the thread to which it is bound. void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner);
diff --git a/base/message_loop/message_loop_current.cc b/base/message_loop/message_loop_current.cc index 2e2adfa..71a45d0 100644 --- a/base/message_loop/message_loop_current.cc +++ b/base/message_loop/message_loop_current.cc
@@ -51,10 +51,6 @@ current_->RemoveDestructionObserver(destruction_observer); } -std::string MessageLoopCurrent::GetThreadName() const { - return current_->GetThreadName(); -} - scoped_refptr<SingleThreadTaskRunner> MessageLoopCurrent::task_runner() const { DCHECK(current_->IsBoundToCurrentThread()); return current_->GetTaskRunner();
diff --git a/base/message_loop/message_loop_current.h b/base/message_loop/message_loop_current.h index 270c6593..f259d89 100644 --- a/base/message_loop/message_loop_current.h +++ b/base/message_loop/message_loop_current.h
@@ -105,9 +105,6 @@ // DestructionObserver is receiving a notification callback. void RemoveDestructionObserver(DestructionObserver* destruction_observer); - // Returns the name for the thread associated with this object. - std::string GetThreadName() const; - // Forwards to MessageLoop::task_runner(). // DEPRECATED(https://crbug.com/616447): Use ThreadTaskRunnerHandle::Get() // instead of MessageLoopCurrent::Get()->task_runner().
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc index 69ae6f0..9c6132c3 100644 --- a/base/message_loop/message_loop_unittest.cc +++ b/base/message_loop/message_loop_unittest.cc
@@ -2238,22 +2238,6 @@ EXPECT_EQ(loop.task_runner(), ThreadTaskRunnerHandle::Get()); } -TEST_F(MessageLoopTest, ThreadName) { - { - std::string kThreadName("foo"); - MessageLoop loop; - PlatformThread::SetName(kThreadName); - EXPECT_EQ(kThreadName, loop.GetThreadName()); - } - - { - std::string kThreadName("bar"); - base::Thread thread(kThreadName); - ASSERT_TRUE(thread.StartAndWaitForTesting()); - EXPECT_EQ(kThreadName, thread.thread_name()); - } -} - // Verify that tasks posted to and code running in the scope of the same // MessageLoop access the same SequenceLocalStorage values. TEST_F(MessageLoopTest, SequenceLocalStorageSetGet) {
diff --git a/base/task/sequence_manager/sequence_manager_impl.cc b/base/task/sequence_manager/sequence_manager_impl.cc index 62d866f..20a6d97 100644 --- a/base/task/sequence_manager/sequence_manager_impl.cc +++ b/base/task/sequence_manager/sequence_manager_impl.cc
@@ -1019,14 +1019,6 @@ return controller_->GetDefaultTaskRunner(); } -std::string SequenceManagerImpl::GetThreadName() const { - Optional<PlatformThreadId> thread_id = associated_thread_->GetBoundThreadId(); - DCHECK(thread_id) - << "GetThreadName() must only be called after BindToCurrentThread()'s " - << "side-effects have been synchronized with this thread."; - return ThreadIdNameManager::GetInstance()->GetName(*thread_id); -} - bool SequenceManagerImpl::IsBoundToCurrentThread() const { return associated_thread_->IsBoundToCurrentThread(); }
diff --git a/base/task/sequence_manager/sequence_manager_impl.h b/base/task/sequence_manager/sequence_manager_impl.h index 14cc051..57c19e8 100644 --- a/base/task/sequence_manager/sequence_manager_impl.h +++ b/base/task/sequence_manager/sequence_manager_impl.h
@@ -138,7 +138,6 @@ void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner); // TODO(alexclarke): Remove this as part of https://crbug.com/825327. scoped_refptr<SingleThreadTaskRunner> GetTaskRunner(); - std::string GetThreadName() const; bool IsBoundToCurrentThread() const; MessagePump* GetMessagePump() const; bool IsType(MessageLoop::Type type) const;
diff --git a/base/task/sequence_manager/sequence_manager_impl_unittest.cc b/base/task/sequence_manager/sequence_manager_impl_unittest.cc index 4a8eb12..8f91346 100644 --- a/base/task/sequence_manager/sequence_manager_impl_unittest.cc +++ b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
@@ -4289,12 +4289,6 @@ RunLoop().RunUntilIdle(); } -TEST_P(SequenceManagerTest, ThreadName) { - std::string kThreadName1("foo"); - PlatformThread::SetName(kThreadName1); - EXPECT_EQ(kThreadName1, sequence_manager()->GetThreadName()); -} - TEST_P(SequenceManagerTest, CreateTaskQueue) { scoped_refptr<TaskQueue> task_queue = sequence_manager()->CreateTaskQueue(TaskQueue::Spec("test"));
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index d24d1e3..67b540d 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8914618441507983984 \ No newline at end of file +8914296474736728352 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index a24f789c..255f976 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8914652258186523104 \ No newline at end of file +8914296671689431792 \ No newline at end of file
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py index 15e385e6..79b39e6 100755 --- a/build/vs_toolchain.py +++ b/build/vs_toolchain.py
@@ -5,6 +5,7 @@ from __future__ import print_function +import collections import glob import json import os @@ -22,9 +23,11 @@ script_dir = os.path.dirname(os.path.realpath(__file__)) json_data_file = os.path.join(script_dir, 'win_toolchain.json') - -# Use MSVS2017 as the default toolchain. -CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2017' +# VS versions are listed in descending order of priority (highest first). +TOOLCHAIN_VERSIONS = collections.OrderedDict([ + ('2017', '15.0'), + ('2019', '16.0'), +]) def SetEnvironmentAndGetRuntimeDllDirs(): @@ -129,9 +132,40 @@ def GetVisualStudioVersion(): - """Return GYP_MSVS_VERSION of Visual Studio. + """Return best available version of Visual Studio. """ - return os.environ.get('GYP_MSVS_VERSION', CURRENT_DEFAULT_TOOLCHAIN_VERSION) + + supported_versions = TOOLCHAIN_VERSIONS.keys() + supported_versions_str = ', '.join('{} ({})'.format(v,k) + for k,v in TOOLCHAIN_VERSIONS.items()) + available_versions = [] + for version in supported_versions: + for path in ( + os.environ.get('vs%s_install' % version), + os.path.expandvars('%ProgramFiles(x86)%' + + '/Microsoft Visual Studio/%s' % version)): + if path and os.path.exists(path): + available_versions.append(version) + break + + if not available_versions: + if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))): + return TOOLCHAIN_VERSIONS.keys()[0] + raise Exception(('No supported Visual Studio can be found.' + ' Supported versions are: %s.') % supported_versions_str) + + env_version = os.environ.get('GYP_MSVS_VERSION') + if env_version: + if env_version not in supported_versions: + raise Exception(('Visual Studio version %s (from GYP_MSVS_VERSION)' + ' is not supported. Supported versions are: %s.') + % (env_version, supported_versions_str)) + if env_version not in available_versions: + raise Exception(('Visual Studio version %s (from GYP_MSVS_VERSION)' + ' is not available.') % env_version) + return env_version + + return available_versions[0] def DetectVisualStudioPath(): @@ -141,14 +175,6 @@ # Note that this code is used from # build/toolchain/win/setup_toolchain.py as well. version_as_year = GetVisualStudioVersion() - year_to_version = { - '2017': '15.0', - '2019': '16.0', - } - if version_as_year not in year_to_version: - raise Exception(('Visual Studio version %s (from GYP_MSVS_VERSION)' - ' not supported. Supported versions are: %s') % ( - version_as_year, ', '.join(year_to_version.keys()))) # The VC++ >=2017 install location needs to be located using COM instead of # the registry. For details see: @@ -267,7 +293,7 @@ version number part changes frequently so the highest version number found is used. """ - assert GetVisualStudioVersion() in ['2017', '2019'] + SetEnvironmentAndGetRuntimeDllDirs() assert ('GYP_MSVS_OVERRIDE_PATH' in os.environ) vc_component_msvc_root = os.path.join(os.environ['GYP_MSVS_OVERRIDE_PATH'],
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc index 0a9ea808..114ee63 100644 --- a/cc/layers/heads_up_display_layer_impl.cc +++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -10,6 +10,7 @@ #include <algorithm> #include <vector> +#include "base/memory/shared_memory_mapping.h" #include "base/numerics/safe_conversions.h" #include "base/optional.h" #include "base/single_thread_task_runner.h" @@ -156,12 +157,12 @@ const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, uint64_t tracing_process_id, int importance) const override { - pmd->CreateSharedMemoryOwnershipEdge( - buffer_dump_guid, shared_memory->mapped_id(), importance); + pmd->CreateSharedMemoryOwnershipEdge(buffer_dump_guid, + shared_mapping.guid(), importance); } LayerTreeFrameSink* layer_tree_frame_sink; - std::unique_ptr<base::SharedMemory> shared_memory; + base::WritableSharedMemoryMapping shared_mapping; }; bool HeadsUpDisplayLayerImpl::WillDraw( @@ -320,15 +321,14 @@ auto backing = std::make_unique<HudSoftwareBacking>(); backing->layer_tree_frame_sink = layer_tree_frame_sink; backing->shared_bitmap_id = viz::SharedBitmap::GenerateId(); - backing->shared_memory = viz::bitmap_allocation::AllocateMappedBitmap( - pool_resource.size(), pool_resource.format()); + base::MappedReadOnlyRegion mapped_region = + viz::bitmap_allocation::AllocateSharedBitmap(pool_resource.size(), + pool_resource.format()); + backing->shared_mapping = std::move(mapped_region.mapping); - mojo::ScopedSharedBufferHandle handle = - viz::bitmap_allocation::DuplicateAndCloseMappedBitmap( - backing->shared_memory.get(), pool_resource.size(), - pool_resource.format()); - layer_tree_frame_sink->DidAllocateSharedBitmap(std::move(handle), - backing->shared_bitmap_id); + layer_tree_frame_sink->DidAllocateSharedBitmap( + viz::bitmap_allocation::ToMojoHandle(std::move(mapped_region.region)), + backing->shared_bitmap_id); pool_resource.set_software_backing(std::move(backing)); } @@ -443,7 +443,7 @@ auto* backing = static_cast<HudSoftwareBacking*>(pool_resource.software_backing()); sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect( - info, backing->shared_memory->memory(), info.minRowBytes()); + info, backing->shared_mapping.memory(), info.minRowBytes()); SkiaPaintCanvas canvas(surface->getCanvas()); DrawHudContents(&canvas);
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc index 9d2e075..6944908 100644 --- a/cc/layers/texture_layer_impl.cc +++ b/cc/layers/texture_layer_impl.cc
@@ -110,15 +110,9 @@ LayerTreeFrameSink* sink = layer_tree_impl()->layer_tree_frame_sink(); for (const auto& pair : to_register_bitmaps_) { - // Because we may want to notify a display compositor about this - // base::SharedMemory more than one time, we need to be able to keep - // making handles to share with it, so we can't close the - // base::SharedMemory. - mojo::ScopedSharedBufferHandle handle = - viz::bitmap_allocation::DuplicateWithoutClosingMappedBitmap( - pair.second->shared_memory(), pair.second->size(), - pair.second->format()); - sink->DidAllocateSharedBitmap(std::move(handle), pair.first); + sink->DidAllocateSharedBitmap(viz::bitmap_allocation::ToMojoHandle( + pair.second->shared_region().Duplicate()), + pair.first); } // All |to_register_bitmaps_| have been registered above, so we can move them // all to the |registered_bitmaps_|.
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc index 33bdd003..7aec79fdf 100644 --- a/cc/layers/texture_layer_unittest.cc +++ b/cc/layers/texture_layer_unittest.cc
@@ -1533,7 +1533,7 @@ id_ = viz::SharedBitmap::GenerateId(); bitmap_ = base::MakeRefCounted<CrossThreadSharedBitmap>( - id_, viz::bitmap_allocation::AllocateMappedBitmap(size, format), size, + id_, viz::bitmap_allocation::AllocateSharedBitmap(size, format), size, format); } @@ -1637,7 +1637,7 @@ id_ = viz::SharedBitmap::GenerateId(); bitmap_ = base::MakeRefCounted<CrossThreadSharedBitmap>( - id_, viz::bitmap_allocation::AllocateMappedBitmap(size, format), size, + id_, viz::bitmap_allocation::AllocateSharedBitmap(size, format), size, format); } @@ -1717,11 +1717,11 @@ id1_ = viz::SharedBitmap::GenerateId(); bitmap1_ = base::MakeRefCounted<CrossThreadSharedBitmap>( - id1_, viz::bitmap_allocation::AllocateMappedBitmap(size, format), size, + id1_, viz::bitmap_allocation::AllocateSharedBitmap(size, format), size, format); id2_ = viz::SharedBitmap::GenerateId(); bitmap2_ = base::MakeRefCounted<CrossThreadSharedBitmap>( - id2_, viz::bitmap_allocation::AllocateMappedBitmap(size, format), size, + id2_, viz::bitmap_allocation::AllocateSharedBitmap(size, format), size, format); } @@ -1811,11 +1811,11 @@ id1_ = viz::SharedBitmap::GenerateId(); bitmap1_ = base::MakeRefCounted<CrossThreadSharedBitmap>( - id1_, viz::bitmap_allocation::AllocateMappedBitmap(size, format), size, + id1_, viz::bitmap_allocation::AllocateSharedBitmap(size, format), size, format); id2_ = viz::SharedBitmap::GenerateId(); bitmap2_ = base::MakeRefCounted<CrossThreadSharedBitmap>( - id2_, viz::bitmap_allocation::AllocateMappedBitmap(size, format), size, + id2_, viz::bitmap_allocation::AllocateSharedBitmap(size, format), size, format); } @@ -1900,7 +1900,7 @@ id_ = viz::SharedBitmap::GenerateId(); bitmap_ = base::MakeRefCounted<CrossThreadSharedBitmap>( - id_, viz::bitmap_allocation::AllocateMappedBitmap(size, format), size, + id_, viz::bitmap_allocation::AllocateSharedBitmap(size, format), size, format); } @@ -2015,7 +2015,7 @@ id_ = viz::SharedBitmap::GenerateId(); bitmap_ = base::MakeRefCounted<CrossThreadSharedBitmap>( - id_, viz::bitmap_allocation::AllocateMappedBitmap(size, format), size, + id_, viz::bitmap_allocation::AllocateSharedBitmap(size, format), size, format); }
diff --git a/cc/raster/bitmap_raster_buffer_provider.cc b/cc/raster/bitmap_raster_buffer_provider.cc index f94e220c..408fb0f 100644 --- a/cc/raster/bitmap_raster_buffer_provider.cc +++ b/cc/raster/bitmap_raster_buffer_provider.cc
@@ -9,6 +9,7 @@ #include <algorithm> +#include "base/memory/shared_memory_mapping.h" #include "base/strings/stringprintf.h" #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" @@ -32,12 +33,12 @@ const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, uint64_t tracing_process_id, int importance) const override { - pmd->CreateSharedMemoryOwnershipEdge( - buffer_dump_guid, shared_memory->mapped_id(), importance); + pmd->CreateSharedMemoryOwnershipEdge(buffer_dump_guid, mapping.guid(), + importance); } LayerTreeFrameSink* frame_sink; - std::unique_ptr<base::SharedMemory> shared_memory; + base::WritableSharedMemoryMapping mapping; }; class BitmapRasterBufferImpl : public RasterBuffer { @@ -107,14 +108,12 @@ auto backing = std::make_unique<BitmapSoftwareBacking>(); backing->frame_sink = frame_sink_; backing->shared_bitmap_id = viz::SharedBitmap::GenerateId(); - backing->shared_memory = - viz::bitmap_allocation::AllocateMappedBitmap(size, viz::RGBA_8888); - - mojo::ScopedSharedBufferHandle handle = - viz::bitmap_allocation::DuplicateAndCloseMappedBitmap( - backing->shared_memory.get(), size, viz::RGBA_8888); - frame_sink_->DidAllocateSharedBitmap(std::move(handle), - backing->shared_bitmap_id); + base::MappedReadOnlyRegion mapped_region = + viz::bitmap_allocation::AllocateSharedBitmap(size, viz::RGBA_8888); + backing->mapping = std::move(mapped_region.mapping); + frame_sink_->DidAllocateSharedBitmap( + viz::bitmap_allocation::ToMojoHandle(std::move(mapped_region.region)), + backing->shared_bitmap_id); resource.set_software_backing(std::move(backing)); } @@ -122,7 +121,7 @@ static_cast<BitmapSoftwareBacking*>(resource.software_backing()); return std::make_unique<BitmapRasterBufferImpl>( - size, color_space, backing->shared_memory->memory(), resource_content_id, + size, color_space, backing->mapping.memory(), resource_content_id, previous_content_id); }
diff --git a/cc/resources/cross_thread_shared_bitmap.cc b/cc/resources/cross_thread_shared_bitmap.cc index 642bd39..edd1e523 100644 --- a/cc/resources/cross_thread_shared_bitmap.cc +++ b/cc/resources/cross_thread_shared_bitmap.cc
@@ -6,12 +6,15 @@ namespace cc { -CrossThreadSharedBitmap::CrossThreadSharedBitmap( - const viz::SharedBitmapId& id, - std::unique_ptr<base::SharedMemory> memory, - const gfx::Size& size, - viz::ResourceFormat format) - : id_(id), memory_(std::move(memory)), size_(size), format_(format) {} +CrossThreadSharedBitmap::CrossThreadSharedBitmap(const viz::SharedBitmapId& id, + base::MappedReadOnlyRegion shm, + const gfx::Size& size, + viz::ResourceFormat format) + : id_(id), + region_(std::move(shm.region)), + mapping_(std::move(shm.mapping)), + size_(size), + format_(format) {} CrossThreadSharedBitmap::~CrossThreadSharedBitmap() = default;
diff --git a/cc/resources/cross_thread_shared_bitmap.h b/cc/resources/cross_thread_shared_bitmap.h index f594ef1..6d7017a6a 100644 --- a/cc/resources/cross_thread_shared_bitmap.h +++ b/cc/resources/cross_thread_shared_bitmap.h
@@ -7,8 +7,9 @@ #include <memory> +#include "base/memory/read_only_shared_memory_region.h" #include "base/memory/ref_counted.h" -#include "base/memory/shared_memory.h" +#include "base/memory/shared_memory_mapping.h" #include "cc/cc_export.h" #include "components/viz/common/resources/resource_format.h" #include "components/viz/common/resources/shared_bitmap.h" @@ -16,22 +17,25 @@ namespace cc { -// This class holds ownership of a base::SharedMemory segment for use as a -// composited resource, and is refcounted in order to share ownership with the -// LayerTreeHost, via TextureLayer, which needs access to the base::SharedMemory -// from the compositor thread. -// Because all the fields exposed are const, they can be used from any thread -// without conflict, as they only read existing states. +// This class holds ownership of a base::ReadOnlySharedMemoryRegion and its +// base::WritableSharedMemoryMapping for use as a composited resource, and is +// refcounted in order to share ownership with the LayerTreeHost, via +// TextureLayer, which needs access to the base::ReadOnlySharedMemory from +// the compositor thread. Because all the fields exposed are const, they can +// be used from any thread without conflict, as they only read existing states. class CC_EXPORT CrossThreadSharedBitmap : public base::RefCountedThreadSafe<CrossThreadSharedBitmap> { public: CrossThreadSharedBitmap(const viz::SharedBitmapId& id, - std::unique_ptr<base::SharedMemory> memory, + base::MappedReadOnlyRegion shm, const gfx::Size& size, viz::ResourceFormat format); const viz::SharedBitmapId& id() const { return id_; } - const base::SharedMemory* shared_memory() const { return memory_.get(); } + const base::ReadOnlySharedMemoryRegion& shared_region() const { + return region_; + } + void* memory() const { return mapping_.memory(); } const gfx::Size& size() const { return size_; } viz::ResourceFormat format() const { return format_; } @@ -41,7 +45,8 @@ ~CrossThreadSharedBitmap(); const viz::SharedBitmapId id_; - const std::unique_ptr<const base::SharedMemory> memory_; + const base::ReadOnlySharedMemoryRegion region_; + base::WritableSharedMemoryMapping mapping_; const gfx::Size size_; const viz::ResourceFormat format_; };
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc index e35f5b85..e85a700 100644 --- a/cc/test/pixel_test.cc +++ b/cc/test/pixel_test.cc
@@ -7,7 +7,8 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h" -#include "base/memory/shared_memory.h" +#include "base/memory/read_only_shared_memory_region.h" +#include "base/memory/shared_memory_mapping.h" #include "base/path_service.h" #include "base/run_loop.h" #include "base/test/scoped_feature_list.h" @@ -210,27 +211,26 @@ *result_bitmap_, test_data_dir.Append(ref_file), comparator); } -std::unique_ptr<base::SharedMemory> PixelTest::AllocateSharedBitmapMemory( +base::WritableSharedMemoryMapping PixelTest::AllocateSharedBitmapMemory( const viz::SharedBitmapId& id, const gfx::Size& size) { - std::unique_ptr<base::SharedMemory> shm = - viz::bitmap_allocation::AllocateMappedBitmap(size, viz::RGBA_8888); + base::MappedReadOnlyRegion mapped_region = + viz::bitmap_allocation::AllocateSharedBitmap(size, viz::RGBA_8888); this->shared_bitmap_manager_->ChildAllocatedSharedBitmap( - viz::bitmap_allocation::DuplicateAndCloseMappedBitmap(shm.get(), size, - viz::RGBA_8888), + viz::bitmap_allocation::ToMojoHandle(std::move(mapped_region.region)), id); - return shm; + return std::move(mapped_region.mapping); } viz::ResourceId PixelTest::AllocateAndFillSoftwareResource( const gfx::Size& size, const SkBitmap& source) { viz::SharedBitmapId shared_bitmap_id = viz::SharedBitmap::GenerateId(); - std::unique_ptr<base::SharedMemory> shm = + base::WritableSharedMemoryMapping mapping = AllocateSharedBitmapMemory(shared_bitmap_id, size); SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height()); - source.readPixels(info, shm->memory(), info.minRowBytes(), 0, 0); + source.readPixels(info, mapping.memory(), info.minRowBytes(), 0, 0); return child_resource_provider_->ImportResource( viz::TransferableResource::MakeSoftware(shared_bitmap_id, size,
diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h index 3fdb4f20..d9529c3 100644 --- a/cc/test/pixel_test.h +++ b/cc/test/pixel_test.h
@@ -6,6 +6,7 @@ #define CC_TEST_PIXEL_TEST_H_ #include "base/files/file_util.h" +#include "base/memory/shared_memory_mapping.h" #include "base/single_thread_task_runner.h" #include "cc/test/pixel_comparator.h" #include "cc/trees/layer_tree_settings.h" @@ -79,7 +80,7 @@ // Allocates a SharedMemory bitmap and registers it with the display // compositor's SharedBitmapManager. - std::unique_ptr<base::SharedMemory> AllocateSharedBitmapMemory( + base::WritableSharedMemoryMapping AllocateSharedBitmapMemory( const viz::SharedBitmapId& id, const gfx::Size& size); // Uses AllocateSharedBitmapMemory() then registers a ResourceId with the
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index e09d1b99..eea90a16 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -21,6 +21,7 @@ #include "base/containers/flat_map.h" #include "base/json/json_writer.h" #include "base/memory/ptr_util.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/metrics/histogram.h" #include "base/numerics/safe_conversions.h" #include "base/stl_util.h" @@ -5326,7 +5327,7 @@ GLenum texture_target = GL_TEXTURE_2D; // For software compositing, shared memory will be allocated and the // UIResource will be copied into it. - std::unique_ptr<base::SharedMemory> shared_memory; + base::MappedReadOnlyRegion mapped_region; viz::SharedBitmapId shared_bitmap_id; bool overlay_candidate = false; @@ -5344,8 +5345,8 @@ BufferFormat(format), caps); } } else { - shared_memory = - viz::bitmap_allocation::AllocateMappedBitmap(upload_size, format); + mapped_region = + viz::bitmap_allocation::AllocateSharedBitmap(upload_size, format); shared_bitmap_id = viz::SharedBitmap::GenerateId(); } @@ -5370,7 +5371,7 @@ SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(upload_size)); sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect( - dst_info, shared_memory->memory(), dst_info.minRowBytes()); + dst_info, mapped_region.mapping.memory(), dst_info.minRowBytes()); surface->getCanvas()->writePixels( src_info, const_cast<uint8_t*>(bitmap.GetPixels()), src_info.minRowBytes(), 0, 0); @@ -5406,7 +5407,7 @@ SkImageInfo dst_info = SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(upload_size)); scaled_surface = SkSurface::MakeRasterDirect( - dst_info, shared_memory->memory(), dst_info.minRowBytes()); + dst_info, mapped_region.mapping.memory(), dst_info.minRowBytes()); } SkCanvas* scaled_canvas = scaled_surface->getCanvas(); scaled_canvas->scale(canvas_scale_x, canvas_scale_y); @@ -5449,11 +5450,9 @@ overlay_candidate); transferable.format = format; } else { - mojo::ScopedSharedBufferHandle memory_handle = - viz::bitmap_allocation::DuplicateAndCloseMappedBitmap( - shared_memory.get(), upload_size, format); - layer_tree_frame_sink_->DidAllocateSharedBitmap(std::move(memory_handle), - shared_bitmap_id); + layer_tree_frame_sink_->DidAllocateSharedBitmap( + viz::bitmap_allocation::ToMojoHandle(std::move(mapped_region.region)), + shared_bitmap_id); transferable = viz::TransferableResource::MakeSoftware(shared_bitmap_id, upload_size, format); } @@ -5471,7 +5470,7 @@ data.opaque = bitmap.GetOpaque(); data.format = format; data.shared_bitmap_id = shared_bitmap_id; - data.shared_memory = std::move(shared_memory); + data.shared_mapping = std::move(mapped_region.mapping); data.mailbox = mailbox; data.resource_id_for_export = id; ui_resource_map_[uid] = std::move(data); @@ -5501,8 +5500,8 @@ UIResourceData data, const gpu::SyncToken& sync_token) { // Resources are either software or gpu backed, not both. - DCHECK(!(data.shared_memory && !data.mailbox.IsZero())); - if (data.shared_memory) + DCHECK(!(data.shared_mapping.IsValid() && !data.mailbox.IsZero())); + if (data.shared_mapping.IsValid()) layer_tree_frame_sink_->DidDeleteSharedBitmap(data.shared_bitmap_id); if (!data.mailbox.IsZero()) { auto* sii =
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 18ccfb6..cd4dc10 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -18,6 +18,7 @@ #include "base/containers/circular_deque.h" #include "base/containers/flat_map.h" #include "base/memory/memory_pressure_listener.h" +#include "base/memory/shared_memory_mapping.h" #include "base/sequenced_task_runner.h" #include "base/time/time.h" #include "cc/base/synced_property.h" @@ -219,7 +220,7 @@ // Backing for software compositing. viz::SharedBitmapId shared_bitmap_id; - std::unique_ptr<base::SharedMemory> shared_memory; + base::WritableSharedMemoryMapping shared_mapping; // Backing for gpu compositing. gpu::Mailbox mailbox;
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index ef1dd234..358d9e1 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -504,6 +504,9 @@ "//third_party/blink/public:blink", "//gin", "//v8", + + # Ditto for PDFium. + "//third_party/pdfium", ] } else { deps += [ @@ -1511,6 +1514,9 @@ # V8/Gin should not be used in the browser DLL on Windows. "//gin", "//v8", + + # Ditto for PDFium. + "//third_party/pdfium", ] } }
diff --git a/chrome/VERSION b/chrome/VERSION index ec07c77a..8bfed3d 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=76 MINOR=0 -BUILD=3785 +BUILD=3786 PATCH=0
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java index 48ce147..f8dc51f 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java
@@ -15,10 +15,14 @@ import org.chromium.components.signin.ChromeSigninController; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; +import java.util.Collections; + /** * Coordinator for the header of the Autofill Assistant. */ public class AssistantHeaderCoordinator { + private ProfileDataCache mProfileCache; + public AssistantHeaderCoordinator( Context context, ViewGroup bottomBarView, AssistantHeaderModel model) { // Create the poodle and insert it before the status message. We have to create a view @@ -31,7 +35,8 @@ R.dimen.autofill_assistant_poodle_size)); addPoodle(bottomBarView, poodle.getView()); - setProfileImage(bottomBarView, context); + mProfileCache = new ProfileDataCache(context, R.dimen.autofill_assistant_profile_size); + setupProfileImage(bottomBarView); // Bind view and mediator through the model. AssistantHeaderViewBinder.ViewHolder viewHolder = @@ -50,15 +55,19 @@ } // TODO(b/130415092): Use image from AGSA if chrome is not signed in. - private void setProfileImage(ViewGroup root, Context context) { + private void setupProfileImage(ViewGroup root) { String signedInAccountName = ChromeSigninController.get().getSignedInAccountName(); if (signedInAccountName != null) { - ProfileDataCache profileCache = - new ProfileDataCache(context, R.dimen.autofill_assistant_profile_size); - DisplayableProfileData profileData = - profileCache.getProfileDataOrDefault(signedInAccountName); - ImageView profileView = root.findViewById(R.id.profile_image); - profileView.setImageDrawable(profileData.getImage()); + mProfileCache.addObserver(account -> { + if (!signedInAccountName.equals(account)) { + return; + } + DisplayableProfileData profileData = + mProfileCache.getProfileDataOrDefault(signedInAccountName); + ImageView profileView = root.findViewById(R.id.profile_image); + profileView.setImageDrawable(profileData.getImage()); + }); + mProfileCache.update(Collections.singletonList(signedInAccountName)); } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index 8f3e186..c858161 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -201,6 +201,8 @@ public static final String CONTEXTUAL_SEARCH_DEFINITIONS = "ContextualSearchDefinitions"; public static final String CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION = "ContextualSearchMlTapSuppression"; + public static final String CONTEXTUAL_SEARCH_LONGPRESS_RESOLVE = + "ContextualSearchLongpressResolve"; public static final String CONTEXTUAL_SEARCH_SIMPLIFIED_SERVER = "ContextualSearchSimplifiedServer"; public static final String CONTEXTUAL_SEARCH_SECOND_TAP = "ContextualSearchSecondTap";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java index 63fa8b6..962f2566 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
@@ -164,6 +164,22 @@ } } + @Override + public void hidePanel(@StateChangeReason int reason) { + if (getPanelState() == PanelState.PEEKED) { + mPanelHidden = true; + animatePanelToState(PanelState.CLOSED, reason); + } + } + + @Override + public void showPanel(@StateChangeReason int reason) { + if (mPanelHidden) { + animatePanelToState(PanelState.PEEKED, reason); + mPanelHidden = false; + } + } + /** * Updates the Panel so it preserves its state when the size changes. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java index 656a41a..6ab4b68 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java
@@ -162,6 +162,9 @@ return mContext; } + /** Tracks whether the panel has been hidden. {@See #showPanel, #hidePanel}. */ + protected boolean mPanelHidden; + /** * Animates the Overlay Panel to its closed state. * @param reason The reason for the change of panel state. @@ -175,6 +178,12 @@ */ protected abstract void onClosed(@StateChangeReason int reason); + /** Temporarily hides a peeking panel for the given reason. Does nothing if not peeking. */ + public abstract void hidePanel(@StateChangeReason int reason); + + /** Shows a previously hidden panel again. {@See #hidePanel}. */ + public abstract void showPanel(@StateChangeReason int reason); + /** * TODO(mdjones): This method should be removed from this class. * @return The resource id that contains how large the browser controls are. @@ -587,6 +596,8 @@ * @param reason The reason for a change in the panel's state. */ protected void setPanelState(@PanelState int state, @StateChangeReason int reason) { + if (mPanelHidden) return; + if (state == PanelState.CLOSED) { mHeight = 0; onClosed(reason);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java index 969f600..807da0f3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
@@ -13,6 +13,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.compositor.LayerTitleCache; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelContent; @@ -22,6 +23,7 @@ import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost; import org.chromium.chrome.browser.compositor.scene_layer.ContextualSearchSceneLayer; import org.chromium.chrome.browser.compositor.scene_layer.SceneOverlayLayer; +import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial; import org.chromium.chrome.browser.contextualsearch.ContextualSearchManagementDelegate; import org.chromium.chrome.browser.contextualsearch.ResolvedSearchTerm.CardTag; import org.chromium.chrome.browser.profiles.Profile; @@ -35,11 +37,8 @@ * Controls the Contextual Search Panel. */ public class ContextualSearchPanel extends OverlayPanel { - /** When using the Generic UX we never show the Arrow Icon */ - private static final float ARROW_ICON_OPACITY_GENERIC_UX = 0.f; - - /** When using the Generic UX we always show the Close Icon */ - private static final float CLOSE_ICON_OPACITY_GENERIC_UX = 1.f; + /** The number of times to allow scrolling. After this limit we'll close. */ + private static final int SCROLL_COUNT_LIMIT = 3; /** Used for logging state changes. */ private final ContextualSearchPanelMetrics mPanelMetrics; @@ -74,6 +73,9 @@ */ private ScrimParams mScrimParams; + /** Number of times the panel has been scrolled already. */ + private int mScrollCount; + // ============================================================================================ // Constructor // ============================================================================================ @@ -238,6 +240,7 @@ setProgressBarCompletion(0); setProgressBarVisible(false); getImageControl().hideCustomImage(false); + mScrollCount = 0; super.onClosed(reason); @@ -445,6 +448,28 @@ } /** + * Makes the panel not visible by either hiding it or closing it completely. + * Decides which method is most appropriate, and then makes it not visible based on that + * decision. + * @param reason The reason we want the panel to not be visible. + */ + public void makePanelNotVisible(@StateChangeReason int reason) { + if (++mScrollCount >= SCROLL_COUNT_LIMIT) { + closePanel(StateChangeReason.BASE_PAGE_SCROLL, true); + } else if (isHideDuringScrollEnabled()) { + hidePanel(reason); + } + } + + /** @return whether hiding during scrolling is enabled for the Longpress-Resolve feature. */ + private boolean isHideDuringScrollEnabled() { + return ContextualSearchFieldTrial.LONGPRESS_RESOLVE_HIDE_ON_SCROLL.equals( + ChromeFeatureList.getFieldTrialParamByFeature( + ChromeFeatureList.CONTEXTUAL_SEARCH_LONGPRESS_RESOLVE, + ContextualSearchFieldTrial.LONGPRESS_RESOLVE_PARAM_NAME)); + } + + /** * Called after the panel has navigated to prefetched Search Results. * If the user has the panel open then they will see the prefetched result starting to load. * Currently this just logs the time between the start of the search until the results start to
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java index 72ab62b6..484a7bd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java
@@ -185,7 +185,10 @@ analyzeTap(startOffset); } // Notify of an initial selection if it's not empty. - if (endOffset > startOffset) onSelectionChanged(); + if (endOffset > startOffset) { + updateInitialSelectedWord(); + onSelectionChanged(); + } if (setNative) { nativeSetContent(getNativePointer(), mSurroundingText, mSelectionStartOffset, mSelectionEndOffset); @@ -273,6 +276,16 @@ } /** + * Specifies that this resolve must return a non-expanding result. + */ + void setRestrictedResolve() { + mSurroundingText = mInitialSelectedWord; + mSelectionStartOffset = 0; + mSelectionEndOffset = mSurroundingText.length(); + nativeRestrictResolve(mNativePointer); + } + + /** * Notifies of an adjustment that has been applied to the start and end of the selection. * @param startAdjust A signed value indicating the direction of the adjustment to the start of * the selection (typically a negative value when the selection expands). @@ -283,6 +296,14 @@ // Fully track the selection as it changes. mSelectionStartOffset += startAdjust; mSelectionEndOffset += endAdjust; + updateInitialSelectedWord(); + nativeAdjustSelection(getNativePointer(), startAdjust, endAdjust); + // Notify of changes. + onSelectionChanged(); + } + + /** Updates the initial selected word if it has not yet been set. */ + private void updateInitialSelectedWord() { if (TextUtils.isEmpty(mInitialSelectedWord) && !TextUtils.isEmpty(mSurroundingText)) { // TODO(donnd): investigate the root cause of crbug.com/725027 that requires this // additional validation to prevent this substring call from crashing! @@ -290,13 +311,9 @@ || mSelectionEndOffset > mSurroundingText.length()) { return; } - mInitialSelectedWord = mSurroundingText.substring(mSelectionStartOffset, mSelectionEndOffset); } - nativeAdjustSelection(getNativePointer(), startAdjust, endAdjust); - // Notify of changes. - onSelectionChanged(); } /** @return the current selection, or an empty string if data is invalid or nothing selected. */ @@ -568,4 +585,6 @@ int selectionStart, int selectionEnd); @VisibleForTesting protected native String nativeDetectLanguage(long nativeContextualSearchContext); + @VisibleForTesting + protected native void nativeRestrictResolve(long nativeContextualSearchContext); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java index 66343b1..d1c3b35a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -21,6 +21,14 @@ * Provides Field Trial support for the Contextual Search application within Chrome for Android. */ public class ContextualSearchFieldTrial { + //========================================================================================== + // Public settings synchronized with src/components/contextual_search/core/browser/public.cc + //========================================================================================== + public static final String LONGPRESS_RESOLVE_PARAM_NAME = "longpress_resolve_variation"; + public static final String LONGPRESS_RESOLVE_HIDE_ON_SCROLL = "1"; + public static final String LONGPRESS_RESOLVE_PRIVACY_AGGRESSIVE = "2"; + + //========================================================================================== private static final String FIELD_TRIAL_NAME = "ContextualSearch"; private static final String DISABLED_PARAM = "disabled"; private static final String ENABLED_VALUE = "true"; @@ -32,6 +40,7 @@ private static Boolean[] sSwitches = new Boolean[ContextualSearchSwitch.NUM_ENTRIES]; private static Integer[] sSettings = new Integer[ContextualSearchSetting.NUM_ENTRIES]; + // SWITCHES // TODO(donnd): remove all supporting code once short-lived data collection is done. @IntDef({ContextualSearchSwitch.IS_TRANSLATION_DISABLED, ContextualSearchSwitch.IS_ONLINE_DETECTION_DISABLED,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateController.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateController.java index ed94323..d22dfc4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateController.java
@@ -10,6 +10,7 @@ import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason; +import org.chromium.chrome.browser.contextualsearch.ContextualSearchSelectionController.SelectionType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -44,6 +45,9 @@ private final ContextualSearchPolicy mPolicy; private final ContextualSearchInternalStateHandler mStateHandler; + // The type of selection that triggered this state-change sequence; + private @SelectionType int mSelectionType; + /** * The current internal state of the {@code ContextualSearchManager}. * States can be "start states" which can be passed to #enter(), or "transitional states" which @@ -51,14 +55,25 @@ * "resting states" which do not transition into any next state, or a combination of the * above. */ - @IntDef({InternalState.UNDEFINED, InternalState.IDLE, InternalState.LONG_PRESS_RECOGNIZED, - InternalState.SHOWING_LONGPRESS_SEARCH, InternalState.SELECTION_CLEARED_RECOGNIZED, - InternalState.WAITING_FOR_POSSIBLE_TAP_NEAR_PREVIOUS, InternalState.TAP_RECOGNIZED, + @IntDef({ + InternalState.UNDEFINED, + InternalState.IDLE, + InternalState.LONG_PRESS_RECOGNIZED, + InternalState.SHOWING_LONGPRESS_SEARCH, + InternalState.SELECTION_CLEARED_RECOGNIZED, + InternalState.WAITING_FOR_POSSIBLE_TAP_NEAR_PREVIOUS, + InternalState.TAP_RECOGNIZED, InternalState.WAITING_FOR_POSSIBLE_TAP_ON_TAP_SELECTION, - InternalState.TAP_GESTURE_COMMIT, InternalState.GATHERING_SURROUNDINGS, - InternalState.DECIDING_SUPPRESSION, InternalState.START_SHOWING_TAP_UI, - InternalState.SHOW_FULL_TAP_UI, InternalState.RESOLVING, - InternalState.SHOWING_TAP_SEARCH}) + InternalState.TAP_GESTURE_COMMIT, + InternalState.GATHERING_SURROUNDINGS, + InternalState.DECIDING_SUPPRESSION, + InternalState.START_SHOWING_TAP_UI, + InternalState.SHOW_RESOLVING_UI, + InternalState.RESOLVING, + InternalState.SHOWING_TAP_SEARCH, + InternalState.RESOLVING_LONG_PRESS_RECOGNIZED, + InternalState.SHOWING_RESOLVED_LONG_PRESS_SEARCH, + }) @Retention(RetentionPolicy.SOURCE) public @interface InternalState { /** @@ -121,7 +136,7 @@ /** * Show the full Tap UI. Currently this means showing the Overlay Panel. */ - int SHOW_FULL_TAP_UI = 12; + int SHOW_RESOLVING_UI = 12; /** * Resolving the Search Term using the surrounding text and additional context. * Currently this makes a server request, which could take a long time. @@ -131,6 +146,15 @@ * Resting state when showing the panel in response to a Tap gesture. */ int SHOWING_TAP_SEARCH = 14; + /** + * This starts resolving transition that leads to the SHOWING_LONGPRESS_SEARCH resting + * state. + */ + int RESOLVING_LONG_PRESS_RECOGNIZED = 14; + /** + * Resting state when showing the panel in response to a longpress gesture that resolved. + */ + int SHOWING_RESOLVED_LONG_PRESS_SEARCH = 15; } // The current state of this instance. @@ -175,6 +199,7 @@ * @param reason The reason for the reset. */ void reset(@Nullable @StateChangeReason Integer reason) { + mSelectionType = SelectionType.UNDETERMINED; transitionTo(InternalState.IDLE, reason); } @@ -185,11 +210,24 @@ void enter(@InternalState int state) { assert state == InternalState.UNDEFINED || state == InternalState.IDLE || state == InternalState.LONG_PRESS_RECOGNIZED + || state == InternalState.RESOLVING_LONG_PRESS_RECOGNIZED || state == InternalState.TAP_RECOGNIZED || state == InternalState.SELECTION_CLEARED_RECOGNIZED; mPreviousState = mState; mState = state; - + switch (state) { + case InternalState.LONG_PRESS_RECOGNIZED: + mSelectionType = SelectionType.LONG_PRESS; + break; + case InternalState.RESOLVING_LONG_PRESS_RECOGNIZED: + mSelectionType = SelectionType.RESOLVING_LONG_PRESS; + break; + case InternalState.TAP_RECOGNIZED: + mSelectionType = SelectionType.TAP; + break; + default: + mSelectionType = SelectionType.UNDETERMINED; + } notifyStartingWorkOn(mState); notifyFinishedWorkOn(mState); } @@ -291,14 +329,16 @@ case InternalState.START_SHOWING_TAP_UI: mStateHandler.startShowingTapUi(); break; - case InternalState.SHOW_FULL_TAP_UI: - mStateHandler.showContextualSearchTapUi(); + case InternalState.SHOW_RESOLVING_UI: + mStateHandler.showContextualSearchResolvingUi(); break; case InternalState.RESOLVING: mStateHandler.resolveSearchTerm(); break; case InternalState.SHOWING_TAP_SEARCH: break; + case InternalState.SHOWING_RESOLVED_LONG_PRESS_SEARCH: + break; default: Log.w(TAG, "Warning: unexpected startWorkingOn " + String.valueOf(state)); break; @@ -356,22 +396,34 @@ break; case InternalState.GATHERING_SURROUNDINGS: // We gather surroundings for both Tap and Long-press in order to notify icing. - transitionTo(mPreviousState == InternalState.LONG_PRESS_RECOGNIZED - ? InternalState.SHOWING_LONGPRESS_SEARCH - : InternalState.DECIDING_SUPPRESSION); + if (mSelectionType == SelectionType.LONG_PRESS) { + transitionTo(InternalState.SHOWING_LONGPRESS_SEARCH); + } else if (mSelectionType == SelectionType.RESOLVING_LONG_PRESS) { + transitionTo(InternalState.SHOW_RESOLVING_UI); + } else { + transitionTo(InternalState.DECIDING_SUPPRESSION); + } break; case InternalState.DECIDING_SUPPRESSION: transitionTo(InternalState.START_SHOWING_TAP_UI); break; case InternalState.START_SHOWING_TAP_UI: - transitionTo(InternalState.SHOW_FULL_TAP_UI); + transitionTo(InternalState.SHOW_RESOLVING_UI); break; - case InternalState.SHOW_FULL_TAP_UI: - transitionTo(mPolicy.shouldPreviousTapResolve() ? InternalState.RESOLVING - : InternalState.SHOWING_TAP_SEARCH); + case InternalState.SHOW_RESOLVING_UI: + transitionTo(mPolicy.shouldPreviousGestureResolve() + ? InternalState.RESOLVING + : InternalState.SHOWING_TAP_SEARCH); break; case InternalState.RESOLVING: - transitionTo(InternalState.SHOWING_TAP_SEARCH); + transitionTo(mSelectionType == SelectionType.TAP + ? InternalState.SHOWING_TAP_SEARCH + : InternalState.SHOWING_RESOLVED_LONG_PRESS_SEARCH); + break; + case InternalState.RESOLVING_LONG_PRESS_RECOGNIZED: + transitionTo(InternalState.GATHERING_SURROUNDINGS); + break; + case InternalState.SHOWING_RESOLVED_LONG_PRESS_SEARCH: break; default: Log.e(TAG, "The state " + String.valueOf(state) + " is not transitional!");
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateHandler.java index 6a442cbe..c68f58d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateHandler.java
@@ -18,10 +18,10 @@ void hideContextualSearchUi(@StateChangeReason int reason); /** - * Shows the Contextual Search user interface for a Tap. - * @see ContextualSearchInternalStateController.InternalState#SHOW_FULL_TAP_UI + * Shows the Contextual Search user interface for a resolving search. + * @see ContextualSearchInternalStateController.InternalState#SHOW_RESOLVING_UI */ - void showContextualSearchTapUi(); + void showContextualSearchResolvingUi(); /** * Shows the Contextual Search user interface for a Long-press.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java index a2224bb..33266622 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -21,6 +21,7 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.compositor.bottombar.OverlayContentDelegate; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason; @@ -467,7 +468,7 @@ // If the user action was not a long-press, we should not delay before loading content. mShouldLoadDelayedSearch = false; } - if (isTap && mPolicy.shouldPreviousTapResolve()) { + if (isTap && mPolicy.shouldPreviousGestureResolve()) { // For a resolving Tap we'll figure out translation need after the Resolve. } else if (!TextUtils.isEmpty(selection)) { boolean shouldPrefetch = mPolicy.shouldPrefetchSearchResult(); @@ -521,9 +522,10 @@ } @Override - public void startSearchTermResolutionRequest(String selection) { + public void startSearchTermResolutionRequest(String selection, boolean isRestrictedResolve) { WebContents baseWebContents = getBaseWebContents(); if (baseWebContents != null && mContext != null && mContext.canResolve()) { + if (isRestrictedResolve) mContext.setRestrictedResolve(); nativeStartSearchTermResolutionRequest( mNativeContextualSearchManagerPtr, mContext, getBaseWebContents()); } else { @@ -785,7 +787,9 @@ int selectionStartAdjust = resolvedSearchTerm.selectionStartAdjust(); int selectionEndAdjust = resolvedSearchTerm.selectionEndAdjust(); if ((selectionStartAdjust != 0 || selectionEndAdjust != 0) - && mSelectionController.getSelectionType() == SelectionType.TAP) { + && (mSelectionController.getSelectionType() == SelectionType.TAP + || mSelectionController.getSelectionType() + == SelectionType.RESOLVING_LONG_PRESS)) { String originalSelection = mContext == null ? null : mContext.getInitialSelectedWord(); String currentSelection = mSelectionController.getSelectedText(); if (currentSelection != null) currentSelection = currentSelection.trim(); @@ -1032,7 +1036,7 @@ // Record metrics for when the prefetched results became viewable. if (mSearchRequest != null && mSearchRequest.wasPrefetch()) { - boolean didResolve = mPolicy.shouldPreviousTapResolve(); + boolean didResolve = mPolicy.shouldPreviousGestureResolve(); mSearchPanel.onPanelNavigatedToPrefetchedSearch(didResolve); } } @@ -1387,10 +1391,22 @@ } @Override - public void handleScroll() { + public void handleScrollStart() { if (mIsAccessibilityModeEnabled) return; - hideContextualSearch(StateChangeReason.BASE_PAGE_SCROLL); + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SEARCH_LONGPRESS_RESOLVE) + || mSelectionController.getSelectionType() == SelectionType.TAP) { + hideContextualSearch(StateChangeReason.BASE_PAGE_SCROLL); + } else if (mSelectionController.getSelectionType() == SelectionType.RESOLVING_LONG_PRESS) { + mSearchPanel.makePanelNotVisible(StateChangeReason.BASE_PAGE_SCROLL); + } + } + + @Override + public void handleScrollEnd() { + if (mSelectionController.getSelectionType() == SelectionType.RESOLVING_LONG_PRESS) { + mSearchPanel.showPanel(StateChangeReason.BASE_PAGE_SCROLL); + } } @Override @@ -1462,6 +1478,13 @@ mInternalStateController.enter(InternalState.TAP_RECOGNIZED); } + @Override + public void handleValidResolvingLongpress() { + if (mIsAccessibilityModeEnabled || !mPolicy.canResolveLongpress()) return; + + mInternalStateController.enter(InternalState.RESOLVING_LONG_PRESS_RECOGNIZED); + } + /** * Notifies this class that the selection has changed. This may be due to the user moving the * selection handles after a long-press, or after a Tap gesture has called selectWordAroundCaret @@ -1484,6 +1507,8 @@ if (type == SelectionType.LONG_PRESS) { mInternalStateController.enter(InternalState.LONG_PRESS_RECOGNIZED); + } else if (type == SelectionType.RESOLVING_LONG_PRESS) { + mInternalStateController.enter(InternalState.RESOLVING_LONG_PRESS_RECOGNIZED); } } else { hideContextualSearch(StateChangeReason.INVALID_SELECTION); @@ -1581,8 +1606,11 @@ } }; - boolean isTap = mSelectionController.getSelectionType() == SelectionType.TAP; - if (!isTap && mCouldSmartSelectionBeActive && mContext != null) { + boolean isResolvingGesture = + mSelectionController.getSelectionType() == SelectionType.TAP + || mSelectionController.getSelectionType() + == SelectionType.RESOLVING_LONG_PRESS; + if (!isResolvingGesture && mCouldSmartSelectionBeActive && mContext != null) { // If Smart Selection might be active we need to work around a race // condition gathering surrounding text. See https://crbug.com/773330. // Instead we just return the selection which is good enough for the assistant. @@ -1595,7 +1623,7 @@ return; } - if (isTap && mPolicy.shouldPreviousTapResolve()) { + if (isResolvingGesture && mPolicy.shouldPreviousGestureResolve()) { ContextualSearchInteractionPersister.PersistedInteraction interaction = mInteractionRecorder.getInteractionPersister() .getAndClearPersistedInteraction(); @@ -1706,7 +1734,10 @@ String selection = mSelectionController.getSelectedText(); assert !TextUtils.isEmpty(selection); - mNetworkCommunicator.startSearchTermResolutionRequest(selection); + boolean isRestrictedResolve = mPolicy.isPrivacyAggressiveResolveEnabled() + || mSelectionController.isAdjustedSelection(); + mNetworkCommunicator.startSearchTermResolutionRequest( + selection, isRestrictedResolve); // If the we were unable to start the resolve, we've hidden the UI and set the // context to null. if (mContext == null || mSearchPanel == null) return; @@ -1717,11 +1748,13 @@ } @Override - public void showContextualSearchTapUi() { - mInternalStateController.notifyStartingWorkOn(InternalState.SHOW_FULL_TAP_UI); - showContextualSearch(StateChangeReason.TEXT_SELECT_TAP); - ContextualSearchUma.logRankerFeaturesAvailable(true); - mInternalStateController.notifyFinishedWorkOn(InternalState.SHOW_FULL_TAP_UI); + public void showContextualSearchResolvingUi() { + mInternalStateController.notifyStartingWorkOn(InternalState.SHOW_RESOLVING_UI); + boolean isTap = mSelectionController.getSelectionType() == SelectionType.TAP; + showContextualSearch(isTap ? StateChangeReason.TEXT_SELECT_TAP + : StateChangeReason.TEXT_SELECT_LONG_PRESS); + if (isTap) ContextualSearchUma.logRankerFeaturesAvailable(true); + mInternalStateController.notifyFinishedWorkOn(InternalState.SHOW_RESOLVING_UI); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchNetworkCommunicator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchNetworkCommunicator.java index 47dc301..a4b18ba2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchNetworkCommunicator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchNetworkCommunicator.java
@@ -16,8 +16,10 @@ * Starts a Search Term Resolution request. * When the response comes back {@link #handleSearchTermResolutionResponse} will be called. * @param selection the current selected text. + * @param isRestrictedResolve Whether the resolution should be restricted to an exact match with + * the given selection. */ - void startSearchTermResolutionRequest(String selection); + void startSearchTermResolutionRequest(String selection, boolean isRestrictedResolve); /** * Handles a Search Term Resolution response.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java index 45521c2..a2dcdd94 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
@@ -13,6 +13,7 @@ import org.chromium.base.CollectionUtil; import org.chromium.base.VisibleForTesting; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel; @@ -133,21 +134,24 @@ return false; } - // We never preload on long-press so users can cut & paste without hitting the servers. - return mSelectionController.getSelectionType() == SelectionType.TAP; + // We never preload on a regular long-press so users can cut & paste without hitting the + // servers. + return mSelectionController.getSelectionType() == SelectionType.TAP + || mSelectionController.getSelectionType() == SelectionType.RESOLVING_LONG_PRESS; } /** - * Returns whether the previous tap (the tap last counted) should resolve. - * @return Whether the previous tap should resolve. + * @return Whether the previous gesture should resolve. */ - boolean shouldPreviousTapResolve() { + boolean shouldPreviousGestureResolve() { if (isMandatoryPromoAvailable() || ContextualSearchFieldTrial.getSwitch( ContextualSearchSwitch.IS_SEARCH_TERM_RESOLUTION_DISABLED)) { return false; } + if (isPrivacyAggressiveResolveEnabled()) return true; + return (isPromoAvailable() || (mContextualSearchPreferenceHelper != null && mContextualSearchPreferenceHelper.canThrottle())) @@ -155,6 +159,11 @@ : true; } + /** @return Whether a long-press gesture can resolve. */ + boolean canResolveLongpress() { + return ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SEARCH_LONGPRESS_RESOLVE); + } + /** * Returns whether surrounding context can be accessed by other systems or not. * @return Whether surroundings are available. @@ -250,11 +259,29 @@ * is no exiting request. */ boolean shouldCreateVerbatimRequest() { + if (isPrivacyAggressiveResolveEnabled()) return false; + @SelectionType int selectionType = mSelectionController.getSelectionType(); return (mSelectionController.getSelectedText() != null && (selectionType == SelectionType.LONG_PRESS - || (selectionType == SelectionType.TAP && !shouldPreviousTapResolve()))); + || (selectionType == SelectionType.TAP + && !shouldPreviousGestureResolve()))); + } + + /** + * Returns whether doing a privacy aggressive resolve is enabled (as opposed to privacy + * conservative). When this is enabled, the selection is sent to the server immediately instead + * of waiting for the panel to be opened. This allows the server to resolve the selection which + * will recognize entities, etc. and display those attributes in the Bar. + * @return Whether the privacy-aggressive behavior of immediately sending the selection to the + * server is enabled. + */ + boolean isPrivacyAggressiveResolveEnabled() { + return ContextualSearchFieldTrial.LONGPRESS_RESOLVE_PRIVACY_AGGRESSIVE.equals( + ChromeFeatureList.getFieldTrialParamByFeature( + ChromeFeatureList.CONTEXTUAL_SEARCH_LONGPRESS_RESOLVE, + ContextualSearchFieldTrial.LONGPRESS_RESOLVE_PARAM_NAME)); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java index 8674c668..c226823 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
@@ -12,6 +12,7 @@ import org.chromium.base.TimeUtils; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel; import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSetting; import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch; @@ -39,6 +40,7 @@ int UNDETERMINED = 0; int TAP = 1; int LONG_PRESS = 2; + int RESOLVING_LONG_PRESS = 3; } private static final String TAG = "ContextualSearch"; @@ -93,15 +95,29 @@ // The duration of the last tap gesture in milliseconds, or 0 if not set. private int mTapDurationMs = INVALID_DURATION; + /** Tracks whether we're currently clearing the selection to prevent recursion. */ + private boolean mClearingSelection; + + /** + * Whether the current selection has been adjusted or not. If it has been adjusted we must + * request a resolve for this exact term rather than anything that overlaps as we get with + * normal expanding resolves. + */ + private boolean mIsAdjustedSelection; + + /** Whether the selection handles are currently showing. */ + private boolean mAreSelectionHandlesShown; + private class ContextualSearchGestureStateListener implements GestureStateListener { @Override public void onScrollStarted(int scrollOffsetY, int scrollExtentY) { - mHandler.handleScroll(); + mHandler.handleScrollStart(); } @Override public void onScrollEnded(int scrollOffsetY, int scrollExtentY) { mLastScrollTimeNs = System.nanoTime(); + mHandler.handleScrollEnd(); } @Override @@ -224,12 +240,27 @@ } /** + * Returns whether the current selection has been adjusted or not. + * If it has been adjusted we must request a resolve for this exact term rather than anything + * that overlaps as is the behavior with normal expanding resolves. + * @return Whether an exact word match is required in the resolve. + */ + boolean isAdjustedSelection() { + return mIsAdjustedSelection; + } + + /** * Clears the selection. */ void clearSelection() { + if (mClearingSelection) return; + + mClearingSelection = true; SelectionPopupController controller = getSelectionPopupController(); if (controller != null) controller.clearSelection(); + mHandler.handleSelectionCleared(); resetSelectionStates(); + mClearingSelection = false; } /** @@ -285,27 +316,35 @@ boolean shouldHandleSelection = false; switch (eventType) { case SelectionEventType.SELECTION_HANDLES_SHOWN: + mAreSelectionHandlesShown = true; mWasTapGestureDetected = false; - mSelectionType = SelectionType.LONG_PRESS; + mSelectionType = ChromeFeatureList.isEnabled( + ChromeFeatureList.CONTEXTUAL_SEARCH_LONGPRESS_RESOLVE) + ? SelectionType.RESOLVING_LONG_PRESS + : SelectionType.LONG_PRESS; shouldHandleSelection = true; SelectionPopupController controller = getSelectionPopupController(); if (controller != null) mSelectedText = controller.getSelectedText(); + mIsAdjustedSelection = false; break; case SelectionEventType.SELECTION_HANDLES_CLEARED: + mAreSelectionHandlesShown = false; mHandler.handleSelectionDismissal(); + clearSelection(); resetAllStates(); break; case SelectionEventType.SELECTION_HANDLE_DRAG_STOPPED: shouldHandleSelection = mShouldHandleSelectionModification; + mIsAdjustedSelection = true; break; default: } + mX = posXPix; + mY = posYPix; if (shouldHandleSelection) { if (mSelectedText != null) { - mX = posXPix; - mY = posYPix; - handleSelection(mSelectedText, SelectionType.LONG_PRESS); + handleSelection(mSelectedText, mSelectionType); } } } @@ -344,6 +383,8 @@ mSelectedText = null; mWasTapGestureDetected = false; + mIsAdjustedSelection = false; + mAreSelectionHandlesShown = false; } /** @@ -409,7 +450,8 @@ // been suppressed if each of the heuristics were satisfied. mHandler.handleMetricsForWouldSuppressTap(tapHeuristics); - boolean shouldSuppressTapBasedOnHeuristics = tapHeuristics.shouldSuppressTap(); + boolean shouldSuppressTapBasedOnHeuristics = + tapHeuristics.shouldSuppressTap() || mAreSelectionHandlesShown; boolean shouldOverrideMlTapSuppression = tapHeuristics.shouldOverrideMlTapSuppression(); // Make sure Tap Suppression features are consistent.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionHandler.java index 5ebaab3e..e87b0a71 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionHandler.java
@@ -14,7 +14,12 @@ /** * Handle a scroll event on the base page. */ - public void handleScroll(); + public void handleScrollStart(); + + /** + * Handle a scroll-ending event on the base page. + */ + public void handleScrollEnd(); /** * Handle the selection being cleared on the base page. @@ -77,4 +82,9 @@ * features to. */ public void logNonHeuristicFeatures(ContextualSearchInteractionRecorder interactionRecorder); + + /** + * Handles a long-press gesture that may make a server Resolve request to determine the search. + */ + void handleValidResolvingLongpress(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ResolvedSearchTerm.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ResolvedSearchTerm.java index 2ac0b8fb4..aecf2a2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ResolvedSearchTerm.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ResolvedSearchTerm.java
@@ -239,7 +239,7 @@ return TextUtils.join(", ", sections); } - List<String> buildTextSections() { + private List<String> buildTextSections() { List<String> sections = new ArrayList<String>(); if (mIsNetworkUnavailable) { sections.add("Network unavailable!"); @@ -247,8 +247,9 @@ sections.add("ResponseCode:" + mResponseCode); } else { if (mDoPreventPreload) sections.add("Preventing preload!"); - if (!TextUtils.isEmpty(mSearchTerm)) sections.add("Search for '" + mSearchTerm); - if (!TextUtils.isEmpty(mDisplayText)) sections.add("displayed as '" + mDisplayText); + if (!TextUtils.isEmpty(mSearchTerm)) sections.add("Search for '" + mSearchTerm + "'"); + if (!TextUtils.isEmpty(mDisplayText)) + sections.add("displayed as '" + mDisplayText + "'"); if (!TextUtils.isEmpty(mMid)) sections.add("MID:'" + mMid); if (mSelectionStartAdjust != 0 || mSelectionEndAdjust != 0) { sections.add(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryCardView.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryCardView.java index 48f2dd8..e2ba055 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryCardView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryCardView.java
@@ -137,8 +137,13 @@ @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { - getParent().requestChildRectangleOnScreen( - ExploreSitesCategoryCardView.this, new Rect(), true); + // Ensures the whole category card is scrolled to view when a child site has focus. + // Immediate should be false so scrolling will not interfere with any existing + // scrollers running to make the view visible. + getParent().requestChildRectangleOnScreen(ExploreSitesCategoryCardView.this, + new Rect(/* left= */ 0, /* top= */ 0, /* right= */ getWidth(), + /* bottom= */ getHeight()), + /* immediate= */ false); } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java index 1161a33..bc63a9a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.history; import android.content.res.Resources; +import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.ViewHolder; import android.text.SpannableString; @@ -40,11 +41,11 @@ private static final String EMPTY_QUERY = ""; private final SelectionDelegate<HistoryItem> mSelectionDelegate; - private final HistoryProvider mHistoryProvider; private final HistoryManager mHistoryManager; private final ArrayList<HistoryItemView> mItemViews; private final DefaultFaviconHelper mFaviconHelper; private RecyclerView mRecyclerView; + private @Nullable HistoryProvider mHistoryProvider; private View mPrivacyDisclaimerBottomSpace; private Button mClearBrowsingDataButton; @@ -77,8 +78,11 @@ * Called when the activity/native page is destroyed. */ public void onDestroyed() { - mHistoryProvider.destroy(); mIsDestroyed = true; + + mHistoryProvider.destroy(); + mHistoryProvider = null; + mRecyclerView = null; mFaviconHelper.clearCache(); } @@ -243,6 +247,9 @@ @Override public void onHistoryDeleted() { + // Return early if this call comes in after the activity/native page is destroyed. + if (mIsDestroyed) return; + mSelectionDelegate.clearSelection(); // TODO(twellington): Account for items that have been paged in due to infinite scroll. // This currently removes all items and re-issues a query.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkSplashscreenMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkSplashscreenMetrics.java index 5307cb0..4ac5e82 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkSplashscreenMetrics.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkSplashscreenMetrics.java
@@ -12,29 +12,22 @@ */ public class WebApkSplashscreenMetrics implements SplashscreenObserver { private final long mShellApkLaunchTimeMs; - private long mSplashScreenShownTimeMs = -1; public WebApkSplashscreenMetrics(long shellApkLaunchTimeMs) { mShellApkLaunchTimeMs = shellApkLaunchTimeMs; } @Override - public void onSplashscreenHidden(long timestamp) { + public void onSplashscreenHidden(long startTimestamp, long endTimestamp) { if (mShellApkLaunchTimeMs == -1) return; if (UmaUtils.hasComeToForeground() && !UmaUtils.hasComeToBackground()) { // commit both shown/hidden histograms here because native may not be loaded when the // splashscreen is shown. WebApkUma.recordShellApkLaunchToSplashscreenVisible( - mSplashScreenShownTimeMs - mShellApkLaunchTimeMs); - WebApkUma.recordShellApkLaunchToSplashscreenHidden(timestamp - mShellApkLaunchTimeMs); + startTimestamp - mShellApkLaunchTimeMs); + WebApkUma.recordShellApkLaunchToSplashscreenHidden( + endTimestamp - mShellApkLaunchTimeMs); } } - - @Override - public void onSplashscreenShown(long timestamp) { - assert mSplashScreenShownTimeMs == -1; - if (mShellApkLaunchTimeMs == -1) return; - mSplashScreenShownTimeMs = timestamp; - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/TabModalPresenter.java b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/TabModalPresenter.java index aaaac3f..64ef412 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/TabModalPresenter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/TabModalPresenter.java
@@ -237,6 +237,10 @@ mDialogContainer = (ViewGroup) dialogContainerStub.inflate(); mDialogContainer.setVisibility(View.GONE); + + // Make sure clicks are not consumed by content beneath the container view. + mDialogContainer.setClickable(true); + mContainerParent = (ViewGroup) mDialogContainer.getParent(); // The default sibling view is the next view of the dialog container stub in main.xml and // should not be removed from its parent.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/ProvidedByWebApkSplashDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ProvidedByWebApkSplashDelegate.java index 073a58b..0fb59ac 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/ProvidedByWebApkSplashDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ProvidedByWebApkSplashDelegate.java
@@ -45,7 +45,8 @@ } @Override - public void onSplashHidden(Tab tab) { + public void onSplashHidden(Tab tab, @SplashController.SplashHidesReason int reason, + long startTimestamp, long endTimestamp) { // TODO(pkotwicz) implement. }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SameActivityWebappSplashDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SameActivityWebappSplashDelegate.java index 197d832..295ee12 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SameActivityWebappSplashDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SameActivityWebappSplashDelegate.java
@@ -15,6 +15,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ContextUtils; +import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.NativeInitObserver; @@ -29,6 +30,9 @@ * activity). */ public class SameActivityWebappSplashDelegate implements SplashDelegate, NativeInitObserver { + public static final String HISTOGRAM_SPLASHSCREEN_DURATION = "Webapp.Splashscreen.Duration"; + public static final String HISTOGRAM_SPLASHSCREEN_HIDES = "Webapp.Splashscreen.Hides"; + private Activity mActivity; private ActivityLifecycleDispatcher mLifecycleDispatcher; private TabObserverRegistrar mTabObserverRegistrar; @@ -98,7 +102,8 @@ } @Override - public void onSplashHidden(Tab tab) { + public void onSplashHidden(Tab tab, @SplashController.SplashHidesReason int reason, + long startTimestamp, long endTimestamp) { if (mWebApkNetworkErrorObserver != null) { mTabObserverRegistrar.unregisterTabObserver(mWebApkNetworkErrorObserver); tab.removeObserver(mWebApkNetworkErrorObserver); @@ -106,6 +111,8 @@ } mLifecycleDispatcher.unregister(SameActivityWebappSplashDelegate.this); + recordSplashHiddenUma(reason, startTimestamp, endTimestamp); + mActivity = null; } @@ -141,6 +148,16 @@ (splashImage != null)); } + /** Called once the splash screen is hidden to record UMA metrics. */ + private void recordSplashHiddenUma(@SplashController.SplashHidesReason int reason, + long startTimestamp, long endTimestamp) { + RecordHistogram.recordEnumeratedHistogram(HISTOGRAM_SPLASHSCREEN_HIDES, reason, + SplashController.SplashHidesReason.NUM_ENTRIES); + + RecordHistogram.recordMediumTimesHistogram( + HISTOGRAM_SPLASHSCREEN_DURATION, endTimestamp - startTimestamp); + } + /** * Records splash screen UMA metrics. * @param resources
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java index c6052d0e0..08ab76cb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java
@@ -13,7 +13,6 @@ import org.chromium.base.ObserverList; import org.chromium.base.TraceEvent; import org.chromium.base.VisibleForTesting; -import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.WarmupManager; import org.chromium.chrome.browser.compositor.CompositorView; import org.chromium.chrome.browser.tab.EmptyTabObserver; @@ -62,9 +61,6 @@ int NUM_ENTRIES = 4; } - public static final String HISTOGRAM_SPLASHSCREEN_DURATION = "Webapp.Splashscreen.Duration"; - public static final String HISTOGRAM_SPLASHSCREEN_HIDES = "Webapp.Splashscreen.Hides"; - private final TabObserverRegistrar mTabObserverRegistrar; private SplashDelegate mDelegate; @@ -97,8 +93,6 @@ mSplashView = mDelegate.buildSplashView(webappInfo); mParentView.addView(mSplashView); - - notifySplashscreenVisible(mSplashShownTimestamp); } /** @@ -179,24 +173,14 @@ long splashHiddenTimestamp = SystemClock.elapsedRealtime(); recordTraceEventsFinishedHidingSplash(); - mDelegate.onSplashHidden(tab); - recordSplashHiddenUma(reason, splashHiddenTimestamp); - notifySplashscreenHidden(splashHiddenTimestamp); + assert mSplashShownTimestamp != 0; + mDelegate.onSplashHidden(tab, reason, mSplashShownTimestamp, splashHiddenTimestamp); + notifySplashscreenHidden(mSplashShownTimestamp, splashHiddenTimestamp); mDelegate = null; mSplashView = null; } - /** Called once the splash screen is hidden to record UMA metrics. */ - private void recordSplashHiddenUma(@SplashHidesReason int reason, long splashHiddenTimestamp) { - RecordHistogram.recordEnumeratedHistogram( - HISTOGRAM_SPLASHSCREEN_HIDES, reason, SplashHidesReason.NUM_ENTRIES); - - assert mSplashShownTimestamp != 0; - RecordHistogram.recordMediumTimesHistogram( - HISTOGRAM_SPLASHSCREEN_DURATION, splashHiddenTimestamp - mSplashShownTimestamp); - } - /** * Register an observer for the splashscreen hidden/visible events. */ @@ -205,21 +189,15 @@ } /** - * Deegister an observer for the splashscreen hidden/visible events. + * Deregister an observer for the splashscreen hidden/visible events. */ public void removeObserver(SplashscreenObserver observer) { mObservers.removeObserver(observer); } - private void notifySplashscreenVisible(long timestamp) { + private void notifySplashscreenHidden(long startTimestamp, long endTimestmap) { for (SplashscreenObserver observer : mObservers) { - observer.onSplashscreenShown(timestamp); - } - } - - private void notifySplashscreenHidden(long timestamp) { - for (SplashscreenObserver observer : mObservers) { - observer.onSplashscreenHidden(timestamp); + observer.onSplashscreenHidden(startTimestamp, endTimestmap); } mObservers.clear(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashDelegate.java index 8e83782..47915f5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashDelegate.java
@@ -13,8 +13,15 @@ /** Builds the splash view. */ View buildSplashView(WebappInfo webappInfo); - /** Called when splash screen has been hidden. */ - void onSplashHidden(Tab tab); + /** + * Called when splash screen has been hidden. + * @param tab + * @param reason Reason that the splash screen was hidden. + * @param startTimestamp Time that the splash screen was shown. + * @param endTimestap Time that the splash screen was hidden. + */ + void onSplashHidden(Tab tab, @SplashController.SplashHidesReason int reason, + long startTimestamp, long endTimestamp); /** Returns whether to wait for a subsequent page load to hide the splash screen. */ boolean shouldWaitForSubsequentPageLoadToHideSplash();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashscreenObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashscreenObserver.java index f79e3d2..310a75028 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashscreenObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashscreenObserver.java
@@ -9,14 +9,9 @@ */ public interface SplashscreenObserver { /** - * Called when the splashscreen is shown. - * @param timestamp Time that the splash screen was shown. + * Called when the splash screen is hidden. + * @param startTimestamp Time that the splash screen was shown. + * @param endTimestap Time that the splash screen was hidden. */ - void onSplashscreenShown(long timestamp); - - /** - * Called when the splashscreen is hidden. - * @param timestamp Time that the splash screen was hidden. - */ - void onSplashscreenHidden(long timestamp); + void onSplashscreenHidden(long startTimestamp, long endTimestamp); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFakeServer.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFakeServer.java index 1e00f24..dc5a7ed 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFakeServer.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFakeServer.java
@@ -310,7 +310,7 @@ mManagerTest.clickNode(getNodeId()); mManagerTest.waitForSelectionToBe(getSearchTerm()); - if (mPolicy.shouldPreviousTapResolve()) { + if (mPolicy.shouldPreviousGestureResolve()) { // Now wait for the Search Term Resolution to start. mManagerTest.waitForSearchTermResolutionToStart(this); @@ -422,7 +422,7 @@ mManagerTest.clickNode(getNodeId()); mManagerTest.waitForSelectionToBe(getSearchTerm()); - if (mPolicy.shouldPreviousTapResolve()) { + if (mPolicy.shouldPreviousGestureResolve()) { // Now wait for the Search Term Resolution to start. mManagerTest.waitForSearchTermResolutionToStart(this); } else { @@ -619,7 +619,7 @@ //============================================================================================ @Override - public void startSearchTermResolutionRequest(String selection) { + public void startSearchTermResolutionRequest(String selection, boolean isRestrictedResolve) { mLoadedUrl = null; mSearchTermRequested = selection;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateControllerWrapper.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateControllerWrapper.java index 23981a92..95454f5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateControllerWrapper.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateControllerWrapper.java
@@ -19,7 +19,7 @@ CollectionUtil.newArrayList(InternalState.TAP_RECOGNIZED, InternalState.TAP_GESTURE_COMMIT, InternalState.GATHERING_SURROUNDINGS, InternalState.DECIDING_SUPPRESSION, InternalState.START_SHOWING_TAP_UI, - InternalState.SHOW_FULL_TAP_UI, InternalState.RESOLVING); + InternalState.SHOW_RESOLVING_UI, InternalState.RESOLVING); static final List<Integer> EXPECTED_LONGPRESS_SEQUENCE = CollectionUtil.newArrayList(InternalState.LONG_PRESS_RECOGNIZED, InternalState.GATHERING_SURROUNDINGS, InternalState.SHOWING_LONGPRESS_SEARCH);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java index 06731630..e8d2ab3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java
@@ -15,6 +15,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeActivity; @@ -97,7 +98,8 @@ } @Override - public void startSearchTermResolutionRequest(String selection) { + public void startSearchTermResolutionRequest( + String selection, boolean isRestrictedResolve) { // Skip native calls and immediately "resolve" the search term. onSearchTermResolutionResponse(true, 200, selection, selection, "", "", false, 0, 10, "", "", "", "", QuickActionCategory.NONE, 0, "", "", 0); @@ -319,7 +321,8 @@ @SmallTest @Feature({"ContextualSearch"}) @Restriction(Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE) - public void testTapProcessIsRobustWhenSelectionGetsCleared() throws InterruptedException { + @DisabledTest(message = "See https://crbug.com/959040") + public void testTapProcessIsRobustWhenSelectionGetsClearedDLD() throws InterruptedException { Assert.assertEquals(mPanelManager.getRequestPanelShowCount(), 0); // Fake a Tap event.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/TabModalPresenterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/TabModalPresenterTest.java index 34588e8..d1560230 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/TabModalPresenterTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/TabModalPresenterTest.java
@@ -16,6 +16,7 @@ import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertTrue; import static org.chromium.chrome.browser.modaldialog.ModalDialogTestUtils.checkCurrentPresenter; import static org.chromium.chrome.browser.modaldialog.ModalDialogTestUtils.checkDialogDismissalCause; @@ -50,9 +51,11 @@ import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.OmniboxTestUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modaldialog.DialogDismissalCause; import org.chromium.ui.modaldialog.ModalDialogManager; import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; +import org.chromium.ui.modaldialog.ModalDialogProperties; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.test.util.UiRestriction; @@ -90,6 +93,7 @@ private ChromeTabbedActivity mActivity; private ModalDialogManager mManager; + private TabModalPresenter mTabModalPresenter; private TestObserver mTestObserver; private Integer mExpectedDismissalCause; @@ -103,9 +107,8 @@ .getToolbarLayoutForTesting() .getLocationBar() .addUrlFocusChangeListener(mTestObserver); - TabModalPresenter presenter = - (TabModalPresenter) mManager.getPresenterForTest(ModalDialogType.TAB); - presenter.disableAnimationForTest(); + mTabModalPresenter = (TabModalPresenter) mManager.getPresenterForTest(ModalDialogType.TAB); + mTabModalPresenter.disableAnimationForTest(); } @Test @@ -123,7 +126,7 @@ final ViewGroup containerParent = presenter.getContainerParentForTest(); ThreadUtils.runOnUiThreadBlocking(() -> { - Assert.assertTrue(containerParent.indexOfChild(dialogContainer) + assertTrue(containerParent.indexOfChild(dialogContainer) > containerParent.indexOfChild(controlContainer)); }); @@ -133,7 +136,7 @@ OmniboxTestUtils.toggleUrlBarFocus(urlBar, true); mTestObserver.onUrlFocusChangedCallback.waitForCallback(callCount); ThreadUtils.runOnUiThreadBlocking(() -> { - Assert.assertTrue(containerParent.indexOfChild(dialogContainer) + assertTrue(containerParent.indexOfChild(dialogContainer) < containerParent.indexOfChild(controlContainer)); }); @@ -142,7 +145,7 @@ OmniboxTestUtils.toggleUrlBarFocus(urlBar, false); mTestObserver.onUrlFocusChangedCallback.waitForCallback(callCount); ThreadUtils.runOnUiThreadBlocking(() -> { - Assert.assertTrue(containerParent.indexOfChild(dialogContainer) + assertTrue(containerParent.indexOfChild(dialogContainer) > containerParent.indexOfChild(controlContainer)); }); @@ -397,6 +400,36 @@ @Test @SmallTest @Feature({"ModalDialog"}) + public void testDismiss_CancelOnTouchOutside() throws Exception { + PropertyModel dialog1 = createDialog(mActivity, "1", null); + + // Show a tab modal dialog and verify it shows. + showDialog(mManager, dialog1, ModalDialogType.TAB); + onView(withId(R.id.tab_modal_dialog_container)) + .check(matches(hasDescendant(withText("1")))); + checkCurrentPresenter(mManager, ModalDialogType.TAB); + + // Click dialog container and verify the dialog is not dismissed. + final View dialogContainer = mTabModalPresenter.getDialogContainerForTest(); + assertTrue(dialogContainer.isClickable()); + TestThreadUtils.runOnUiThreadBlocking(dialogContainer::performClick); + onView(withId(R.id.tab_modal_dialog_container)) + .check(matches(hasDescendant(withText("1")))); + checkCurrentPresenter(mManager, ModalDialogType.TAB); + + // Enable cancel on touch outside and verify the dialog is dismissed. + TestThreadUtils.runOnUiThreadBlocking( + () -> dialog1.set(ModalDialogProperties.CANCEL_ON_TOUCH_OUTSIDE, true)); + assertTrue(dialogContainer.isClickable()); + TestThreadUtils.runOnUiThreadBlocking(dialogContainer::performClick); + onView(withId(R.id.tab_modal_dialog_container)) + .check(matches(not(hasDescendant(withText("1"))))); + checkCurrentPresenter(mManager, null); + } + + @Test + @SmallTest + @Feature({"ModalDialog"}) public void testDismiss_DismissalCause_BackPressed() throws Exception { PropertyModel dialog1 = createDialog(mActivity, "1", mTestObserver); mExpectedDismissalCause = DialogDismissalCause.NAVIGATE_BACK_OR_TOUCH_OUTSIDE; @@ -449,7 +482,7 @@ private void checkBrowserControls(boolean restricted) { if (restricted) { - Assert.assertTrue("All tabs should be obscured", mActivity.isViewObscuringAllTabs()); + assertTrue("All tabs should be obscured", mActivity.isViewObscuringAllTabs()); onView(allOf(isDisplayed(), withId(R.id.menu_button))).check(matches(not(isEnabled()))); } else { Assert.assertFalse("Tabs shouldn't be obscured", mActivity.isViewObscuringAllTabs());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java index 8d50461..6d15f2e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java
@@ -206,10 +206,11 @@ SameActivityWebappUmaCache.HISTOGRAM_SPLASHSCREEN_ICON_SIZE, 50)); // DURATION and HIDES UMA should not have been recorded yet. - Assert.assertFalse( - hasHistogramEntry(SplashController.HISTOGRAM_SPLASHSCREEN_DURATION, 3000)); + Assert.assertFalse(hasHistogramEntry( + SameActivityWebappSplashDelegate.HISTOGRAM_SPLASHSCREEN_DURATION, 3000)); Assert.assertEquals(0, - getHistogramTotalCountFor(SplashController.HISTOGRAM_SPLASHSCREEN_HIDES, + getHistogramTotalCountFor( + SameActivityWebappSplashDelegate.HISTOGRAM_SPLASHSCREEN_HIDES, SplashController.SplashHidesReason.NUM_ENTRIES)); } @@ -225,10 +226,11 @@ mActivityTestRule.waitUntilSplashscreenHides(); // DURATION and HIDES should now have a value. - Assert.assertTrue( - hasHistogramEntry(SplashController.HISTOGRAM_SPLASHSCREEN_DURATION, 10000)); + Assert.assertTrue(hasHistogramEntry( + SameActivityWebappSplashDelegate.HISTOGRAM_SPLASHSCREEN_DURATION, 10000)); Assert.assertEquals(1, - getHistogramTotalCountFor(SplashController.HISTOGRAM_SPLASHSCREEN_HIDES, + getHistogramTotalCountFor( + SameActivityWebappSplashDelegate.HISTOGRAM_SPLASHSCREEN_HIDES, SplashController.SplashHidesReason.NUM_ENTRIES)); // The other UMA records should not have changed.
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateTest.java index 3059b90..835e69e 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateTest.java
@@ -35,9 +35,9 @@ } @Override - public void showContextualSearchTapUi() { + public void showContextualSearchResolvingUi() { mDidShow = true; - stubForWorkOnState(InternalState.SHOW_FULL_TAP_UI); + stubForWorkOnState(InternalState.SHOW_RESOLVING_UI); } @Override @@ -131,11 +131,11 @@ } private void mocksForTap() { - when(mMockedPolicy.shouldPreviousTapResolve()).thenReturn(true); + when(mMockedPolicy.shouldPreviousGestureResolve()).thenReturn(true); } private void mocksForNonResolvingTap() { - when(mMockedPolicy.shouldPreviousTapResolve()).thenReturn(false); + when(mMockedPolicy.shouldPreviousGestureResolve()).thenReturn(false); } private void mocksForLongpress() {
diff --git a/chrome/app/chrome_content_browser_overlay_manifest.cc b/chrome/app/chrome_content_browser_overlay_manifest.cc index 215115b..858bdc2 100644 --- a/chrome/app/chrome_content_browser_overlay_manifest.cc +++ b/chrome/app/chrome_content_browser_overlay_manifest.cc
@@ -79,8 +79,8 @@ #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \ defined(OS_CHROMEOS) +#include "chrome/browser/performance_manager/webui_graph_dump.mojom.h" // nogncheck #include "chrome/browser/ui/webui/discards/discards.mojom.h" -#include "services/resource_coordinator/public/mojom/webui_graph_dump.mojom.h" // nogncheck #endif #if BUILDFLAG(ENABLE_EXTENSIONS) @@ -256,7 +256,7 @@ #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \ defined(OS_CHROMEOS) mojom::DiscardsDetailsProvider, - resource_coordinator::mojom::WebUIGraphDump, + performance_manager::mojom::WebUIGraphDump, #endif mojom::BluetoothInternalsHandler, mojom::InterventionsInternalsPageHandler,
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index c142049a..5db978d 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1834,6 +1834,7 @@ "//chrome/browser/metrics/variations:chrome_ui_string_overrider_factory", "//chrome/browser/net:probe_message_proto", "//chrome/browser/notifications", + "//chrome/browser/performance_manager:mojo_bindings", "//chrome/browser/profiling_host", "//chrome/browser/push_messaging:budget_proto", "//chrome/browser/resource_coordinator:mojo_bindings", @@ -5065,6 +5066,7 @@ ":chrome_internal_resources_gen", "//chrome/browser/engagement:mojo_bindings_js", "//chrome/browser/media:mojo_bindings_js", + "//chrome/browser/performance_manager:mojo_bindings_js", "//chrome/browser/resources/ssl/ssl_error_assistant:make_ssl_error_assistant_protobuf", "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings_js", "//chrome/browser/ui/webui/downloads:mojo_bindings_js",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 9e02d30..6fda5c2 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -899,6 +899,19 @@ contextual_search::kContextualCardsSimplifiedServerWithDiagnosticChar}; const FeatureEntry::FeatureVariation kSimplifiedServerVariations[] = { {"and allow all CoCa cards", &kSimplifiedServerAllCocaCards, 1, nullptr}}; + +const FeatureEntry::FeatureParam kLongpressResolveHideOnScroll = { + contextual_search::kLongpressResolveParamName, + contextual_search::kLongpressResolveHideOnScroll}; +const FeatureEntry::FeatureParam kLongpressResolvePrivacyAggressive = { + contextual_search::kLongpressResolveParamName, + contextual_search::kLongpressResolvePrivacyAggressive}; +const FeatureEntry::FeatureVariation kLongpressResolveVariations[] = { + {"and hide on scroll", &kLongpressResolveHideOnScroll, 1, nullptr}, + {"and allow privacy-aggressive behavior", + &kLongpressResolvePrivacyAggressive, 1, nullptr}, +}; + #endif // defined(OS_ANDROID) const FeatureEntry::FeatureParam kResamplingInputEventsLSQEnabled[] = { @@ -1091,6 +1104,16 @@ flag_descriptions::kContextualSearchDefinitionsName, flag_descriptions::kContextualSearchDefinitionsDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kContextualSearchDefinitions)}, + + {"contextual-search-longpress-resolve", + flag_descriptions::kContextualSearchLongpressResolveName, + flag_descriptions::kContextualSearchLongpressResolveDescription, + kOsAndroid, + FEATURE_WITH_PARAMS_VALUE_TYPE( + chrome::android::kContextualSearchLongpressResolve, + kLongpressResolveVariations, + "ContextualSearchLongpressResolve")}, + {"contextual-search-ml-tap-suppression", flag_descriptions::kContextualSearchMlTapSuppressionName, flag_descriptions::kContextualSearchMlTapSuppressionDescription, @@ -1104,6 +1127,7 @@ flag_descriptions::kContextualSearchSecondTapName, flag_descriptions::kContextualSearchSecondTapDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kContextualSearchSecondTap)}, + {"contextual-search-simplified-server", flag_descriptions::kContextualSearchSimplifiedServerName, flag_descriptions::kContextualSearchSimplifiedServerDescription, @@ -1112,6 +1136,7 @@ chrome::android::kContextualSearchSimplifiedServer, kSimplifiedServerVariations, "ContextualSearchSimplifiedServer")}, + {"contextual-search-translation-model", flag_descriptions::kContextualSearchTranslationModelName, flag_descriptions::kContextualSearchTranslationModelDescription, @@ -3487,6 +3512,12 @@ flag_descriptions::kAshEnablePipRoundedCornersName, flag_descriptions::kAshEnablePipRoundedCornersDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kPipRoundedCorners)}, + + {"ash-swap-side-volume-buttons-for-orientation", + flag_descriptions::kAshSwapSideVolumeButtonsForOrientationName, + flag_descriptions::kAshSwapSideVolumeButtonsForOrientationDescription, + kOsCrOS, + FEATURE_VALUE_TYPE(ash::features::kSwapSideVolumeButtonsForOrientation)}, #endif // defined(OS_CHROMEOS) {"google-password-manager", flag_descriptions::kGooglePasswordManagerName, flag_descriptions::kGooglePasswordManagerDescription, kOsAll,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index 0c182e4..df2c78f 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -119,6 +119,7 @@ &kCommandLineOnNonRooted, &kContentSuggestionsScrollToLoad, &kContextualSearchDefinitions, + &kContextualSearchLongpressResolve, &kContextualSearchMlTapSuppression, &kContextualSearchSecondTap, &kContextualSearchSimplifiedServer, @@ -334,6 +335,9 @@ const base::Feature kContextualSearchDefinitions{ "ContextualSearchDefinitions", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kContextualSearchLongpressResolve{ + "ContextualSearchLongpressResolve", base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kContextualSearchMlTapSuppression{ "ContextualSearchMlTapSuppression", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h index d7bcad4..515e35c 100644 --- a/chrome/browser/android/chrome_feature_list.h +++ b/chrome/browser/android/chrome_feature_list.h
@@ -47,6 +47,7 @@ extern const base::Feature kCommandLineOnNonRooted; extern const base::Feature kContentSuggestionsScrollToLoad; extern const base::Feature kContextualSearchDefinitions; +extern const base::Feature kContextualSearchLongpressResolve; extern const base::Feature kContextualSearchMlTapSuppression; extern const base::Feature kContextualSearchSecondTap; extern const base::Feature kContextualSearchSimplifiedServer;
diff --git a/chrome/browser/android/contextualsearch/contextual_search_context.cc b/chrome/browser/android/contextualsearch/contextual_search_context.cc index 84cdebf..e84132b 100644 --- a/chrome/browser/android/contextualsearch/contextual_search_context.cc +++ b/chrome/browser/android/contextualsearch/contextual_search_context.cc
@@ -149,6 +149,17 @@ return end_offset; } +void ContextualSearchContext::RestrictResolve( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj) { + // TODO(donnd): improve on this cheap implementation by sending this bit to + // the server instead of destroying our valuable context! + int start = this->start_offset; + int end = this->end_offset; + SetSelectionSurroundings(0, end - start, + this->surrounding_text.substr(start, end - start)); +} + base::android::ScopedJavaLocalRef<jstring> ContextualSearchContext::DetectLanguage( JNIEnv* env,
diff --git a/chrome/browser/android/contextualsearch/contextual_search_context.h b/chrome/browser/android/contextualsearch/contextual_search_context.h index efdf5c5..a2080be 100644 --- a/chrome/browser/android/contextualsearch/contextual_search_context.h +++ b/chrome/browser/android/contextualsearch/contextual_search_context.h
@@ -92,6 +92,11 @@ int64_t GetPreviousEventId() const; int GetPreviousEventResults() const; + // Causes the next resolve request to be for an exact match instead of an + // expandable term. + void RestrictResolve(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj); + // Detects the language of the context using CLD from the translate utility. base::android::ScopedJavaLocalRef<jstring> DetectLanguage( JNIEnv* env,
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 232a7ee..3b4902bf 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -75,7 +75,7 @@ <include name="IDR_DISCARDS_MOJO_PUBLIC_BASE_PROCESS_ID_MOJOM_LITE_JS" file="${root_gen_dir}\mojo\public\mojom\base\process_id.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" /> <include name="IDR_DISCARDS_SORTED_TABLE_BEHAVIOR_HTML" file="resources\discards\sorted_table_behavior.html" compress="gzip" allowexternalscript="true" type="BINDATA" /> <include name="IDR_DISCARDS_SORTED_TABLE_BEHAVIOR_JS" file="resources\discards\sorted_table_behavior.js" compress="gzip" type="BINDATA" /> - <include name="IDR_DISCARDS_WEBUI_GRAPH_DUMP_MOJOM_LITE_JS" file="${root_gen_dir}\services\resource_coordinator\public\mojom\webui_graph_dump.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" /> + <include name="IDR_DISCARDS_WEBUI_GRAPH_DUMP_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\performance_manager\webui_graph_dump.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" /> </if> <if expr="is_win or is_macosx or (is_linux and not is_chromeos)"> <include name="IDR_BROWSER_SWITCHER_APP_HTML" file="resources\browser_switcher\app.html" compress="gzip" allowexternalscript="true" type="BINDATA" />
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 7d2f5a17..222428c 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -181,6 +181,11 @@ "expiry_milestone": 75 }, { + "name": "ash-swap-side-volume-buttons-for-orientation", + "owners": [ "minch" ], + "expiry_milestone": 78 + }, + { "name": "auto-fetch-on-net-error-page", "owners": [ "harringtond", "offline-dev" ], "expiry_milestone": 82 @@ -390,6 +395,11 @@ "expiry_milestone": 74 }, { + "name": "contextual-search-longpress-resolve", + "owners": [ "//chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/OWNERS" ], + "expiry_milestone": 78 + }, + { "name": "contextual-search-ml-tap-suppression", "owners": [ "//chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/OWNERS" ], "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 05cf00c..43b4c9f 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -2174,6 +2174,13 @@ "Enables tap-activated contextual definitions of words on a page to be " "presented in the caption of the Tap to Search Bar."; +const char kContextualSearchLongpressResolveName[] = + "Contextual Search long-press Resolves"; +const char kContextualSearchLongpressResolveDescription[] = + "Enables communicating with Google servers when a long-press gesture is " + "recognized under some privacy-limited conditions. The page context data " + " sent to Google is potentially privacy sensitive!"; + const char kContextualSearchMlTapSuppressionName[] = "Contextual Search ML tap suppression"; const char kContextualSearchMlTapSuppressionDescription[] = @@ -2917,6 +2924,13 @@ const char kAshEnablePipRoundedCornersDescription[] = "Enable rounded corners on the Picture-in-Picture window."; +const char kAshSwapSideVolumeButtonsForOrientationName[] = + "Swap side volume buttons to match screen orientation."; +const char kAshSwapSideVolumeButtonsForOrientationDescription[] = + "Make the side volume button that's closer to the top/right always " + "increase the volume and the button that's closer to the bottom/left " + "always decrease the volume."; + const char kAshEnableUnifiedDesktopName[] = "Unified desktop mode"; const char kAshEnableUnifiedDesktopDescription[] = "Enable unified desktop mode which allows a window to span multiple "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 33d7873..f644266 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1306,6 +1306,9 @@ extern const char kContextualSearchDefinitionsName[]; extern const char kContextualSearchDefinitionsDescription[]; +extern const char kContextualSearchLongpressResolveName[]; +extern const char kContextualSearchLongpressResolveDescription[]; + extern const char kContextualSearchMlTapSuppressionName[]; extern const char kContextualSearchMlTapSuppressionDescription[]; @@ -1753,6 +1756,9 @@ extern const char kAshEnablePipRoundedCornersName[]; extern const char kAshEnablePipRoundedCornersDescription[]; +extern const char kAshSwapSideVolumeButtonsForOrientationName[]; +extern const char kAshSwapSideVolumeButtonsForOrientationDescription[]; + extern const char kAshEnableUnifiedDesktopName[]; extern const char kAshEnableUnifiedDesktopDescription[];
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager.cc b/chrome/browser/media/router/providers/cast/cast_activity_manager.cc index f2cde5fa..051d2a1 100644 --- a/chrome/browser/media/router/providers/cast/cast_activity_manager.cc +++ b/chrome/browser/media/router/providers/cast/cast_activity_manager.cc
@@ -360,6 +360,11 @@ const MediaSinkInternal* sink = media_sink_service_->GetSinkByRoute(route); CHECK(sink); + for (auto& client : activity->connected_clients()) { + client.second->SendMessageToClient( + CreateReceiverActionStopMessage(client.first, *sink, hash_token_)); + } + activity->SendStopSessionMessageToReceiver( base::nullopt, // TODO(jrw): Get the real client ID. hash_token_, std::move(callback)); @@ -437,6 +442,7 @@ // If |activity| is null, we have discovered a non-local activity. if (activity_it == activities_.end()) { + // TODO(crbug.com/954797): Test this case. AddNonLocalActivityRecord(sink, session); NotifyAllOnRoutesUpdated(); return;
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager.h b/chrome/browser/media/router/providers/cast/cast_activity_manager.h index 87a7a60..5313be0 100644 --- a/chrome/browser/media/router/providers/cast/cast_activity_manager.h +++ b/chrome/browser/media/router/providers/cast/cast_activity_manager.h
@@ -19,6 +19,7 @@ #include "chrome/browser/media/router/providers/cast/cast_session_tracker.h" #include "chrome/common/media_router/mojo/media_router.mojom.h" #include "chrome/common/media_router/providers/cast/cast_media_source.h" +#include "mojo/public/cpp/bindings/binding.h" #include "url/origin.h" namespace cast_channel { @@ -118,6 +119,7 @@ mojom::MediaRouteProvider::TerminateRouteCallback callback) override; private: + friend class CastActivityManagerTest; using ActivityMap = base::flat_map<MediaRoute::Id, std::unique_ptr<CastActivityRecordBase>>;
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc b/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc index a9810dd..9e8308e 100644 --- a/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc +++ b/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc
@@ -5,29 +5,44 @@ #include "chrome/browser/media/router/providers/cast/cast_activity_manager.h" #include <memory> +#include <string> #include <tuple> #include <utility> +#include <vector> #include "base/bind.h" +#include "base/optional.h" #include "base/run_loop.h" #include "base/task/post_task.h" +#include "base/test/bind_test_util.h" +#include "base/test/mock_callback.h" #include "base/test/values_test_util.h" +#include "base/values.h" #include "chrome/browser/media/router/data_decoder_util.h" +#include "chrome/browser/media/router/providers/cast/cast_session_client.h" +#include "chrome/browser/media/router/providers/cast/mock_cast_activity_record.h" +#include "chrome/browser/media/router/providers/common/buffered_message_sender.h" #include "chrome/browser/media/router/test/mock_mojo_media_router.h" #include "chrome/browser/media/router/test/test_helper.h" #include "chrome/common/media_router/test/test_helper.h" #include "components/cast_channel/cast_test_util.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "services/data_decoder/data_decoder_service.h" #include "services/data_decoder/public/cpp/testing_json_parser.h" +#include "services/data_decoder/public/mojom/constants.mojom.h" #include "services/service_manager/public/cpp/test/test_connector_factory.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using base::test::IsJson; -using base::test::ParseJsonDeprecated; +using base::test::ParseJson; using testing::_; +using testing::AnyNumber; +using testing::ByRef; +using testing::ElementsAre; using testing::IsEmpty; +using testing::Not; using testing::Return; using testing::WithArg; @@ -37,79 +52,43 @@ constexpr int kChannelId = 42; constexpr char kOrigin[] = "https://google.com"; constexpr int kTabId = 1; -constexpr char kSource1[] = "cast:ABCDEFGH?clientId=theClientId"; -constexpr char kSource2[] = "cast:BBBBBBBB?clientId=theClientId"; -constexpr char kReceiverStatus[] = R"({ +constexpr char kAppId1[] = "ABCDEFGH"; +constexpr char kAppId2[] = "BBBBBBBB"; + +std::string MakeSourceId(const std::string& app_id = kAppId1) { + return "cast:" + app_id + "?clientId=theClientId"; +} + +base::Value MakeReceiverStatus(const std::string& app_id, + bool update_display_name = false) { + return ParseJson(R"({ "applications": [{ - "appId": "ABCDEFGH", - "displayName": "App display name", + "appId": ")" + + app_id + + R"(", + "displayName": "theDisplayName)" + + std::string(update_display_name ? "1" : "2") + R"(", "namespaces": [ {"name": "urn:x-cast:com.google.cast.media"}, - {"name": "urn:x-cast:com.google.foo"} + {"name": "urn:x-cast:com.google.foo"}, ], "sessionId": "theSessionId", - "statusText":"App status", - "transportId":"theTransportId" - }] - })"; -constexpr char kReceiverStatus2[] = R"({ - "applications": [{ - "appId": "ABCDEFGH", - "displayName": "Updated display name", - "namespaces": [ - {"name": "urn:x-cast:com.google.cast.media"}, - {"name": "urn:x-cast:com.google.foo"} - ], - "sessionId": "theSessionId", - "statusText":"App status", - "transportId":"theTransportId" - }] - })"; -constexpr char kReceiverStatus3[] = R"({ - "applications": [{ - "appId": "BBBBBBBB", - "displayName": "Another app", - "namespaces": [ - {"name": "urn:x-cast:com.google.cast.media"}, - {"name": "urn:x-cast:com.google.foo"} - ], - "sessionId": "theSessionId2", - "statusText":"App status", - "transportId":"theTransportId" - }] - })"; + "statusText": "theAppStatus", + "transportId": "theTransportId", + }], + })"); +} + +using MockCastActivityRecordCallback = + base::RepeatingCallback<void(MockCastActivityRecord*)>; + } // namespace -class ClientPresentationConnection - : public blink::mojom::PresentationConnection { - public: - explicit ClientPresentationConnection( - mojom::RoutePresentationConnectionPtr connections) - : binding_(this, std::move(connections->connection_request)), - connection_(std::move(connections->connection_ptr)) {} - - ~ClientPresentationConnection() override = default; - - void SendMessageToMediaRouter( - blink::mojom::PresentationConnectionMessagePtr message) { - connection_->OnMessage(std::move(message)); - } - - MOCK_METHOD1(OnMessage, void(blink::mojom::PresentationConnectionMessagePtr)); - MOCK_METHOD1(DidChangeState, - void(blink::mojom::PresentationConnectionState state)); - MOCK_METHOD1(DidClose, void(blink::mojom::PresentationConnectionCloseReason)); - - mojo::Binding<blink::mojom::PresentationConnection> binding_; - blink::mojom::PresentationConnectionPtr connection_; - DISALLOW_COPY_AND_ASSIGN(ClientPresentationConnection); -}; - // Test parameters are a boolean indicating whether the client connection should // be closed by a leave_session message, and the URL used to create the test // session. -class CastActivityManagerTest - : public testing::TestWithParam<std::pair<bool, const char*>> { +class CastActivityManagerTest : public testing::Test, + public CastActivityRecordFactory { public: CastActivityManagerTest() : socket_service_(base::CreateSingleThreadTaskRunnerWithTraits( @@ -122,6 +101,8 @@ ~CastActivityManagerTest() override = default; void SetUp() override { + CastActivityManager::SetActitivyRecordFactoryForTest(this); + router_binding_ = std::make_unique<mojo::Binding<mojom::MediaRouter>>( &mock_router_, mojo::MakeRequest(&router_ptr_)); @@ -132,12 +113,12 @@ &media_sink_service_, session_tracker_.get(), &message_handler_, router_ptr_.get(), std::make_unique<DataDecoder>(connector_factory_.GetDefaultConnector()), - "hash-token"); + "theHashToken"); RunUntilIdle(); // Make sure we get route updates. - manager_->AddRouteQuery(MediaSource::Id()); + manager_->AddRouteQuery(route_query_); } void TearDown() override { @@ -146,6 +127,27 @@ RunUntilIdle(); manager_.reset(); + CastActivityManager::SetActitivyRecordFactoryForTest(nullptr); + } + + std::unique_ptr<CastActivityRecordBase> MakeCastActivityRecord( + const MediaRoute& route, + const std::string& app_id) override { + auto activity = std::make_unique<MockCastActivityRecord>(route, app_id); + auto* activity_ptr = activity.get(); + std::string route_id = route.media_route_id(); + ON_CALL(*activity, SendStopSessionMessageToReceiver) + .WillByDefault(WithArg<2>([this, route_id](auto callback) { + result_callback_ = manager_->MakeResultCallbackForRoute( + route_id, std::move(callback)); + })); + ON_CALL(*activity, SetOrUpdateSession) + .WillByDefault(WithArg<0>([activity_ptr](const auto& session) { + activity_ptr->set_session_id(session.session_id()); + })); + activities_.push_back(activity_ptr); + activity_record_callback_.Run(activity_ptr); + return std::move(activity); } // Run any pending events and verify expectations associated with them. This @@ -164,16 +166,9 @@ media_router::RouteRequestResult::ResultCode) { ASSERT_TRUE(route); route_ = std::make_unique<MediaRoute>(*route); - client_connection_ = std::make_unique<ClientPresentationConnection>( - std::move(presentation_connections)); - // When client is connected, the receiver_action message will be sent. - EXPECT_CALL( - *client_connection_, - DidChangeState(blink::mojom::PresentationConnectionState::CONNECTED)); - EXPECT_CALL(*client_connection_, OnMessage).RetiresOnSaturation(); } - void LaunchSession(const char* sourceId = kSource1) { + void CallLaunchSession(const std::string& source_id = MakeSourceId(kAppId1)) { // MediaRouter is notified of new route. ExpectSingleRouteUpdate(); @@ -184,9 +179,17 @@ launch_session_callback_ = std::move(callback); })); - auto source = CastMediaSource::FromMediaSourceId(sourceId); + auto source = CastMediaSource::FromMediaSourceId(source_id); ASSERT_TRUE(source); + activity_record_callback_ = + base::BindLambdaForTesting([this](MockCastActivityRecord* activity) { + // TODO(jrw): Check parameters. + EXPECT_CALL(*activity, AddClient); + EXPECT_CALL(*activity, SendMessageToClient).RetiresOnSaturation(); + activity_record_callback_ = base::DoNothing(); + }); + // Callback will be invoked synchronously. manager_->LaunchSession( *source, sink_, "presentationId", origin_, kTabId, @@ -198,19 +201,24 @@ } cast_channel::LaunchSessionResponse GetSuccessLaunchResponse() { - auto receiver_status = ParseJsonDeprecated(kReceiverStatus); cast_channel::LaunchSessionResponse response; response.result = cast_channel::LaunchSessionResponse::Result::kOk; - response.receiver_status = std::move(*receiver_status); + response.receiver_status = MakeReceiverStatus(kAppId1); return response; } - // Precondition: |LaunchSession()| must be called first. - void LaunchSessionResponseSuccess() { + void LaunchSession(const std::string& source_id = MakeSourceId(kAppId1)) { + CallLaunchSession(source_id); + // 3 things will happen: // (1) SDK client receives new_session message. // (2) Virtual connection is created. // (3) Route list will be updated. + + // TODO(jrw): Check more params. + EXPECT_CALL(*activities_[0], SendMessageToClient("theClientId", _)); + EXPECT_CALL(*activities_[0], SetOrUpdateSession(_, sink_, _)); + EXPECT_CALL(message_handler_, EnsureConnection(kChannelId, "theClientId", "theTransportId")); @@ -219,170 +227,135 @@ route_->media_sink_id(), CastSession::From(sink_, *response.receiver_status)); std::move(launch_session_callback_).Run(std::move(response)); - EXPECT_CALL(*client_connection_, OnMessage).RetiresOnSaturation(); ExpectSingleRouteUpdate(); RunUntilIdle(); } - // Precondition: |LaunchSession()| must be called first. - void LaunchSessionResponseFailure() { - // 3 things will happen: - // (1) Route is removed - // (2) Issue will be sent. - // (3) The PresentationConnection associated with the route will be closed - // with error. - cast_channel::LaunchSessionResponse response; - response.result = cast_channel::LaunchSessionResponse::Result::kError; - std::move(launch_session_callback_).Run(std::move(response)); - - EXPECT_CALL(mock_router_, OnIssue); - ExpectEmptyRouteUpdate(); - EXPECT_CALL( - *client_connection_, - DidClose( - blink::mojom::PresentationConnectionCloseReason::CONNECTION_ERROR)); - RunUntilIdle(); + void TerminateSession(bool expect_success) { + EXPECT_CALL(*activities_[0], SendStopSessionMessageToReceiver); + if (expect_success) { + ExpectEmptyRouteUpdate(); + } else { + ExpectNoRouteUpdate(); + } + manager_->TerminateSession(route_->media_route_id(), + MakeTerminateRouteCallback(expect_success)); + std::move(result_callback_) + .Run(expect_success ? cast_channel::Result::kOk + : cast_channel::Result::kFailed); } - // Precondition: |LaunchSession()| must be called first. - void TerminateSession(cast_channel::Result result) { - cast_channel::ResultCallback stop_session_callback; - - EXPECT_CALL(message_handler_, StopSession(kChannelId, "theSessionId", - base::Optional<std::string>(), _)) - .WillOnce(WithArg<3>([&](auto callback) { - stop_session_callback = std::move(callback); - })); - manager_->TerminateSession( - route_->media_route_id(), - base::BindOnce( - result == cast_channel::Result::kOk - ? &CastActivityManagerTest::ExpectTerminateResultSuccess - : &CastActivityManagerTest::ExpectTerminateResultFailure, - base::Unretained(this))); - // Receiver action stop message is sent to SDK client. - EXPECT_CALL(*client_connection_, OnMessage); - RunUntilIdle(); - - std::move(stop_session_callback).Run(result); - } - - // Precondition: |LaunchSession()| called, |LaunchSessionResponseSuccess()| - // not called. void TerminateNoSession() { // Stop session message not sent because session has not launched yet. - EXPECT_CALL(message_handler_, StopSession).Times(0); - manager_->TerminateSession( - route_->media_route_id(), - base::BindOnce(&CastActivityManagerTest::ExpectTerminateResultSuccess, - base::Unretained(this))); - RunUntilIdle(); - } - - void ExpectTerminateResultSuccess( - const base::Optional<std::string>& error_text, - RouteRequestResult::ResultCode result_code) { - EXPECT_EQ(RouteRequestResult::OK, result_code); - ExpectEmptyRouteUpdate(); - EXPECT_CALL( - *client_connection_, - DidChangeState(blink::mojom::PresentationConnectionState::TERMINATED)); - RunUntilIdle(); - } - - void ExpectTerminateResultFailure( - const base::Optional<std::string>& error_text, - RouteRequestResult::ResultCode result_code) { - EXPECT_NE(RouteRequestResult::OK, result_code); + EXPECT_CALL(*activities_[0], SendStopSessionMessageToReceiver).Times(0); ExpectNoRouteUpdate(); - RunUntilIdle(); + manager_->TerminateSession(route_->media_route_id(), + MakeTerminateRouteCallback(true)); + } + + mojom::MediaRouteProvider::TerminateRouteCallback MakeTerminateRouteCallback( + bool expect_success) { + return base::BindLambdaForTesting( + [expect_success](const base::Optional<std::string>& error_text, + RouteRequestResult::ResultCode result_code) { + if (expect_success) { + EXPECT_FALSE(error_text.has_value()); + EXPECT_EQ(RouteRequestResult::OK, result_code); + } else { + EXPECT_TRUE(error_text.has_value()); + EXPECT_NE(RouteRequestResult::OK, result_code); + } + }); } // Expect a call to OnRoutesUpdated() with a single route, which will // optionally be saved in the variable pointed to by |route_ptr|. - void ExpectSingleRouteUpdate(MediaRoute* route_ptr = nullptr) { - EXPECT_CALL(mock_router_, OnRoutesUpdated(MediaRouteProviderId::CAST, - Not(IsEmpty()), _, _)) - .WillOnce(WithArg<1>([=](auto routes) { - EXPECT_EQ(1u, routes.size()); - if (route_ptr) { - *route_ptr = routes[0]; - } - })); + void ExpectSingleRouteUpdate() { + updated_route_ = base::nullopt; + EXPECT_CALL(mock_router_, + OnRoutesUpdated(MediaRouteProviderId::CAST, ElementsAre(_), + route_query_, IsEmpty())) + .WillOnce(WithArg<1>( + [this](const auto& routes) { updated_route_ = routes[0]; })); } // Expect a call to OnRoutesUpdated() with no routes. void ExpectEmptyRouteUpdate() { + updated_route_ = base::nullopt; EXPECT_CALL(mock_router_, - OnRoutesUpdated(MediaRouteProviderId::CAST, IsEmpty(), _, _)) + OnRoutesUpdated(MediaRouteProviderId::CAST, IsEmpty(), + route_query_, IsEmpty())) .Times(1); } // Expect that OnRoutesUpdated() will not be called. void ExpectNoRouteUpdate() { + updated_route_ = base::nullopt; EXPECT_CALL(mock_router_, OnRoutesUpdated).Times(0); } + std::unique_ptr<CastSession> MakeSession(const std::string& app_id, + bool update_display_name = false) { + return CastSession::From(sink_, + MakeReceiverStatus(app_id, update_display_name)); + } + protected: content::TestBrowserThreadBundle thread_bundle_; data_decoder::TestingJsonParser::ScopedFactoryOverride parser_override_; service_manager::TestConnectorFactory connector_factory_; - MockMojoMediaRouter mock_router_; mojom::MediaRouterPtr router_ptr_; std::unique_ptr<mojo::Binding<mojom::MediaRouter>> router_binding_; - cast_channel::MockCastSocketService socket_service_; cast_channel::MockCastSocket socket_; cast_channel::MockCastMessageHandler message_handler_; - MediaSinkInternal sink_ = CreateCastSink(kChannelId); - std::unique_ptr<MediaRoute> route_; - std::unique_ptr<ClientPresentationConnection> client_connection_; + std::unique_ptr<MediaRoute> route_; // TODO(jrw): Is this needed? cast_channel::LaunchSessionCallback launch_session_callback_; - TestMediaSinkService media_sink_service_; MockCastAppDiscoveryService app_discovery_service_; std::unique_ptr<CastActivityManager> manager_; - std::unique_ptr<CastSessionTracker> session_tracker_; - + std::vector<MockCastActivityRecord*> activities_; + MockCastActivityRecordCallback activity_record_callback_ = base::DoNothing(); const url::Origin origin_ = url::Origin::Create(GURL(kOrigin)); + const MediaSource::Id route_query_ = "theRouteQuery"; + base::Optional<MediaRoute> updated_route_; + cast_channel::ResultCallback result_callback_; }; TEST_F(CastActivityManagerTest, LaunchSession) { LaunchSession(); - LaunchSessionResponseSuccess(); } TEST_F(CastActivityManagerTest, LaunchSessionFails) { - LaunchSession(); - LaunchSessionResponseFailure(); + // 3 things will happen: + // (1) Route is removed + // (2) Issue will be sent. + // (3) The PresentationConnection associated with the route will be closed + // with error. + + CallLaunchSession(); + + EXPECT_CALL( + *activities_[0], + ClosePresentationConnections( + blink::mojom::PresentationConnectionCloseReason::CONNECTION_ERROR)); + + cast_channel::LaunchSessionResponse response; + response.result = cast_channel::LaunchSessionResponse::Result::kError; + std::move(launch_session_callback_).Run(std::move(response)); + + EXPECT_CALL(mock_router_, OnIssue); + ExpectEmptyRouteUpdate(); + RunUntilIdle(); } TEST_F(CastActivityManagerTest, LaunchSessionTerminatesExistingSessionOnSink) { LaunchSession(); - LaunchSessionResponseSuccess(); - // Receiver action stop message is sent to SDK client. - EXPECT_CALL(*client_connection_, OnMessage); - - // Existing session will be terminated. - cast_channel::ResultCallback stop_session_callback; - EXPECT_CALL(message_handler_, StopSession(kChannelId, "theSessionId", - base::Optional<std::string>(), _)) - .WillOnce(WithArg<3>( - [&](auto callback) { stop_session_callback = std::move(callback); })); - - // Launch a new session on the same sink. - auto source = CastMediaSource::FromMediaSourceId(kSource2); - ASSERT_TRUE(source); - manager_->LaunchSession( - *source, sink_, "presentationId2", origin_, kTabId, /*incognito*/ - false, - base::BindOnce(&CastActivityManagerTest::ExpectLaunchSessionSuccess, - base::Unretained(this))); - RunUntilIdle(); + EXPECT_CALL(*activities_[0], SendStopSessionMessageToReceiver); { testing::InSequence dummy; @@ -396,24 +369,27 @@ ExpectSingleRouteUpdate(); } - // A launch session request is sent to the sink. + // Launch a new session on the same sink. + auto source = CastMediaSource::FromMediaSourceId(MakeSourceId(kAppId2)); + manager_->LaunchSession( + // TODO(jrw): Verify that presentation ID is used correctly. + *source, sink_, "presentationId2", origin_, kTabId, /*incognito*/ + false, + base::BindOnce(&CastActivityManagerTest::ExpectLaunchSessionSuccess, + base::Unretained(this))); + EXPECT_CALL(message_handler_, LaunchSession(kChannelId, "BBBBBBBB", kDefaultLaunchTimeout, _)); - - std::move(stop_session_callback).Run(cast_channel::Result::kOk); + std::move(result_callback_).Run(cast_channel::Result::kOk); } TEST_F(CastActivityManagerTest, AddRemoveNonLocalActivity) { - auto session = - CastSession::From(sink_, *ParseJsonDeprecated(kReceiverStatus)); - ASSERT_TRUE(session); - - MediaRoute route; - ExpectSingleRouteUpdate(&route); + auto session = MakeSession(kAppId1); + ExpectSingleRouteUpdate(); manager_->OnSessionAddedOrUpdated(sink_, *session); RunUntilIdle(); - - EXPECT_FALSE(route.is_local()); + ASSERT_TRUE(updated_route_); + EXPECT_FALSE(updated_route_->is_local()); ExpectEmptyRouteUpdate(); manager_->OnSessionRemoved(sink_); @@ -421,340 +397,80 @@ TEST_F(CastActivityManagerTest, UpdateNewlyCreatedSession) { LaunchSession(); - LaunchSessionResponseSuccess(); - auto session = - CastSession::From(sink_, *ParseJsonDeprecated(kReceiverStatus)); - ASSERT_TRUE(session); - - MediaRoute route; - ExpectSingleRouteUpdate(&route); - EXPECT_CALL(*client_connection_, OnMessage); - + EXPECT_CALL(*activities_[0], SetOrUpdateSession(_, sink_, _)); + auto session = MakeSession(kAppId1); + ExpectSingleRouteUpdate(); manager_->OnSessionAddedOrUpdated(sink_, *session); RunUntilIdle(); - - EXPECT_TRUE(route.is_local()); - EXPECT_EQ(route.description(), session->GetRouteDescription()); + ASSERT_TRUE(updated_route_); + EXPECT_TRUE(updated_route_->is_local()); } -TEST_F(CastActivityManagerTest, UpdateExistingSession) { - // Create and add the session to be updated, and verify it was added. - auto session = - CastSession::From(sink_, *ParseJsonDeprecated(kReceiverStatus)); - ASSERT_TRUE(session); - MediaRoute route; - ExpectSingleRouteUpdate(&route); +TEST_F(CastActivityManagerTest, OnSessionAddedOrUpdated) { + LaunchSession(); + auto session = MakeSession(kAppId1); + ExpectSingleRouteUpdate(); + EXPECT_CALL(*activities_[0], SetOrUpdateSession(_, _, "theHashToken")); manager_->OnSessionAddedOrUpdated(sink_, *session); - RunUntilIdle(); - EXPECT_EQ(route.description(), session->GetRouteDescription()); - auto old_route_id = route.media_route_id(); - - // Description change should be reflect in route update. - auto updated_session = - CastSession::From(sink_, *ParseJsonDeprecated(kReceiverStatus2)); - ASSERT_TRUE(updated_session); - - ExpectSingleRouteUpdate(&route); - - manager_->OnSessionAddedOrUpdated(sink_, *updated_session); - RunUntilIdle(); - - EXPECT_EQ(route.description(), updated_session->GetRouteDescription()); - EXPECT_EQ(old_route_id, route.media_route_id()); -} - -TEST_F(CastActivityManagerTest, ReplaceExistingSession) { - // Create and add the session to be replaced, and verify it was added. - auto session = - CastSession::From(sink_, *ParseJsonDeprecated(kReceiverStatus)); - ASSERT_TRUE(session); - MediaRoute route; - ExpectSingleRouteUpdate(&route); - manager_->OnSessionAddedOrUpdated(sink_, *session); - RunUntilIdle(); - auto old_route_id = route.media_route_id(); - EXPECT_EQ(route.description(), session->GetRouteDescription()); - - // Different session. - auto new_session = - CastSession::From(sink_, *ParseJsonDeprecated(kReceiverStatus3)); - ASSERT_TRUE(new_session); - - ExpectSingleRouteUpdate(&route); - manager_->OnSessionAddedOrUpdated(sink_, *new_session); - RunUntilIdle(); - - EXPECT_EQ(route.description(), new_session->GetRouteDescription()); - EXPECT_NE(old_route_id, route.media_route_id()); } TEST_F(CastActivityManagerTest, TerminateSession) { LaunchSession(); - LaunchSessionResponseSuccess(); - TerminateSession(cast_channel::Result::kOk); + TerminateSession(true); } TEST_F(CastActivityManagerTest, TerminateSessionFails) { LaunchSession(); - LaunchSessionResponseSuccess(); - TerminateSession(cast_channel::Result::kFailed); + TerminateSession(false); } TEST_F(CastActivityManagerTest, TerminateSessionBeforeLaunchResponse) { - LaunchSession(); + CallLaunchSession(); TerminateNoSession(); - - // Route already terminated, so no-op when handling launch response. + ExpectEmptyRouteUpdate(); std::move(launch_session_callback_).Run(GetSuccessLaunchResponse()); - ExpectNoRouteUpdate(); } TEST_F(CastActivityManagerTest, AppMessageFromReceiver) { LaunchSession(); - LaunchSessionResponseSuccess(); + + // TODO(jrw): Check message param. + EXPECT_CALL(*activities_[0], SendMessageToClient("theClientId", _)); // Destination ID matches client ID. cast_channel::CastMessage message = cast_channel::CreateCastMessage( "urn:x-cast:com.google.foo", base::Value(base::Value::Type::DICTIONARY), "sourceId", "theClientId"); - message_handler_.OnMessage(socket_, message); - EXPECT_CALL(*client_connection_, OnMessage); + manager_->OnAppMessage(kChannelId, message); } TEST_F(CastActivityManagerTest, AppMessageFromReceiverAllDestinations) { LaunchSession(); - LaunchSessionResponseSuccess(); + + activities_[0]->AddFakeClient("fakeClient1"); + activities_[0]->AddFakeClient("fakeClient2"); + + // TODO(jrw): Check message params. + EXPECT_CALL(*activities_[0], SendMessageToClient("fakeClient1", _)); + EXPECT_CALL(*activities_[0], SendMessageToClient("fakeClient2", _)); // Matches all destinations. cast_channel::CastMessage message = cast_channel::CreateCastMessage( "urn:x-cast:com.google.foo", base::Value(base::Value::Type::DICTIONARY), "sourceId", "*"); - message_handler_.OnMessage(socket_, message); - EXPECT_CALL(*client_connection_, OnMessage); -} - -TEST_F(CastActivityManagerTest, AppMessageFromReceiverUnknownDestination) { - LaunchSession(); - LaunchSessionResponseSuccess(); - - // Destination ID does not match client ID. - cast_channel::CastMessage message = cast_channel::CreateCastMessage( - "urn:x-cast:com.google.foo", base::Value(base::Value::Type::DICTIONARY), - "sourceId", "99999"); - message_handler_.OnMessage(socket_, message); - EXPECT_CALL(*client_connection_, OnMessage).Times(0); -} - -TEST_F(CastActivityManagerTest, AppMessageFromClient) { - LaunchSession(); - LaunchSessionResponseSuccess(); - - EXPECT_CALL(message_handler_, SendAppMessage(kChannelId, _)) - .WillOnce(Return(cast_channel::Result::kOk)); - client_connection_->SendMessageToMediaRouter( - blink::mojom::PresentationConnectionMessage::NewMessage(R"({ - "type": "app_message", - "clientId": "theClientId", - "message": { - "namespaceName": "urn:x-cast:com.google.foo", - "sessionId": "theSessionId", - "message": {} - }, - "sequenceNumber": 123 - })")); - - // An ACK message is sent back to client. - EXPECT_CALL(*client_connection_, OnMessage); -} - -TEST_F(CastActivityManagerTest, AppMessageFromClientInvalidNamespace) { - LaunchSession(); - LaunchSessionResponseSuccess(); - - // Message namespace not in set of allowed namespaces. - EXPECT_CALL(message_handler_, SendAppMessage(kChannelId, _)).Times(0); - client_connection_->SendMessageToMediaRouter( - blink::mojom::PresentationConnectionMessage::NewMessage(R"({ - "type": "app_message", - "clientId": "theClientId", - "message": { - "namespaceName": "someOtherNamespace", - "sessionId": "theSessionId", - "message": {} - } - })")); + manager_->OnAppMessage(kChannelId, message); } TEST_F(CastActivityManagerTest, OnMediaStatusUpdated) { LaunchSession(); - LaunchSessionResponseSuccess(); - EXPECT_CALL(*client_connection_, OnMessage(IsCastMessage(R"({ - "clientId": "theClientId", - "message": {"foo": "bar"}, - "timeoutMillis": 0, - "type": "v2_message" - })"))); - manager_->OnMediaStatusUpdated( - sink_, *ParseJsonDeprecated(R"({"foo": "bar"})"), 345); + const char status[] = R"({"foo": "bar"})"; + base::Optional<int> request_id(345); + + EXPECT_CALL(*activities_[0], + SendMediaStatusToClients(IsJson(status), request_id)); + manager_->OnMediaStatusUpdated(sink_, ParseJson(status), request_id); } -TEST_F(CastActivityManagerTest, OnMediaStatusUpdatedWithPendingRequest) { - LaunchSession(); - LaunchSessionResponseSuccess(); - - EXPECT_CALL(message_handler_, SendMediaRequest).WillOnce(Return(345)); - client_connection_->SendMessageToMediaRouter( - blink::mojom::PresentationConnectionMessage::NewMessage(R"({ - "type": "v2_message", - "clientId": "theClientId", - "message": { - "sessionId": "theSessionId", - "type": "MEDIA_GET_STATUS" - }, - "sequenceNumber": 123 - })")); - RunUntilIdle(); - - // Same as in OnMediaStatusUpdated, except there is a sequenceNumber field. - EXPECT_CALL(*client_connection_, OnMessage(IsCastMessage(R"({ - "clientId": "theClientId", - "message": {"foo": "bar"}, - "sequenceNumber": 123, - "timeoutMillis": 0, - "type": "v2_message" - })"))); - manager_->OnMediaStatusUpdated( - sink_, *ParseJsonDeprecated(R"({"foo": "bar"})"), 345); -} - -TEST_F(CastActivityManagerTest, SendVolumeCommandToReceiver) { - LaunchSession(); - LaunchSessionResponseSuccess(); - - // Message created by CastActivityRecord::SendVolumeCommandToReceiver(). - std::string expected_message = R"({ - "sessionId": "theSessionId", - "type": "SET_VOLUME" - })"; - EXPECT_CALL(message_handler_, - SendSetVolumeRequest(kChannelId, IsJson(expected_message), - "theClientId", _)) - .WillOnce(WithArg<3>([&](auto callback) { - // Check message created by CastSessionClient::SendResultResponse(). - EXPECT_CALL(*client_connection_, OnMessage(IsCastMessage(R"({ - "clientId": "theClientId", - "message": null, - "sequenceNumber": 123, - "timeoutMillis": 0, - "type": "v2_message" - })"))); - std::move(callback).Run(cast_channel::Result::kOk); - return cast_channel::Result::kOk; - })); - client_connection_->SendMessageToMediaRouter( - blink::mojom::PresentationConnectionMessage::NewMessage(R"({ - "type": "v2_message", - "clientId": "theClientId", - "sequenceNumber": 123, - "message": { - "sessionId": "theSessionId", - "type": "SET_VOLUME" - } - })")); -} - -TEST_F(CastActivityManagerTest, SendMediaRequestToReceiver) { - LaunchSession(); - LaunchSessionResponseSuccess(); - - std::string expected_message = R"({ - "sessionId": "theSessionId", - "type": "MEDIA_GET_STATUS" - })"; - EXPECT_CALL(message_handler_, - SendMediaRequest(kChannelId, IsJson(expected_message), - "theClientId", "theTransportId")); - client_connection_->SendMessageToMediaRouter( - blink::mojom::PresentationConnectionMessage::NewMessage(R"({ - "type": "v2_message", - "clientId": "theClientId", - "message": { - "sessionId": "theSessionId", - "type": "MEDIA_GET_STATUS" - }, - "sequenceNumber": 123 - })")); -} - -TEST_F(CastActivityManagerTest, CanJoinSession) { - // TODO(crbug/943291): Write test for CastActivityManager::CanJoinSession. -} - -TEST_F(CastActivityManagerTest, FindActivityForSessionJoin) { - // TODO(crbug/943291): Write test for - // CastActivityManager::FindActivityForSessionJoin. -} - -TEST_F(CastActivityManagerTest, FindActivityForAutoJoin) { - // TODO(crbug/943291): Write test for - // CastActivityManager::FindActivityForAutoJoin. -} - -TEST_F(CastActivityManagerTest, JoinSession) { - // TODO(crbug/943291): Write test for CastActivityManager::JoinSession. -} - -TEST_P(CastActivityManagerTest, HandleLeaveSession) { - bool should_close; - const char* url; - std::tie(should_close, url) = GetParam(); - - LaunchSession(url); - LaunchSessionResponseSuccess(); - - // Called via CastSessionClient::SendMessageToClient. - EXPECT_CALL(*client_connection_, OnMessage).WillOnce([](auto msg) { - // Verify that an acknowlegement message was sent. - ASSERT_TRUE(msg->is_message()); - EXPECT_THAT(msg->get_message(), IsJson(R"({ - "clientId": "theClientId", - "message": null, - "timeoutMillis": 0, - "type": "leave_session", - })")); - }); - - if (should_close) { - // Called via CastSessionClient::CloseConnection via - // CastActivityRecord::HandleLeaveSession. - EXPECT_CALL( - *client_connection_, - DidClose(blink::mojom::PresentationConnectionCloseReason::CLOSED)); - } - - client_connection_->SendMessageToMediaRouter( - blink::mojom::PresentationConnectionMessage::NewMessage(R"({ - "type": "leave_session", - "clientId": "theClientId", - "message": {} - })")); -} - -INSTANTIATE_TEST_SUITE_P( - Urls, - CastActivityManagerTest, - testing::Values( - std::make_pair(true, - "cast:ABCDEFGH?clientId=theClientId&autoJoinPolicy=tab_" - "and_origin_scoped"), - std::make_pair( - true, - "cast:ABCDEFGH?clientId=theClientId&autoJoinPolicy=origin_scoped"), - std::make_pair( - false, - "cast:ABCDEFGH?clientId=theClientId&autoJoinPolicy=page_scoped"), - std::make_pair(false, "cast:ABCDEFGH?clientId=theClientId"))); - } // namespace media_router
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_record.cc b/chrome/browser/media/router/providers/cast/cast_activity_record.cc index 3016f316..1489b7e 100644 --- a/chrome/browser/media/router/providers/cast/cast_activity_record.cc +++ b/chrome/browser/media/router/providers/cast/cast_activity_record.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// #include "chrome/common/media_router/mojo/media_router.mojom.h" #include "chrome/browser/media/router/providers/cast/cast_activity_record.h" #include <memory>
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_record_unittest.cc b/chrome/browser/media/router/providers/cast/cast_activity_record_unittest.cc index 1875301..1184738b 100644 --- a/chrome/browser/media/router/providers/cast/cast_activity_record_unittest.cc +++ b/chrome/browser/media/router/providers/cast/cast_activity_record_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/media/router/providers/cast/cast_activity_record.h" #include <memory> +#include <sstream> #include <string> #include <tuple> #include <utility> @@ -80,6 +81,8 @@ void(blink::mojom::PresentationConnectionCloseReason reason)); }; +using NewClientCallback = base::RepeatingCallback<void(MockCastSessionClient&)>; + class MockCastActivityManager : public CastActivityManagerBase { public: MOCK_METHOD2(MakeResultCallbackForRoute, @@ -91,7 +94,7 @@ } // namespace class CastActivityRecordTest : public testing::Test, - public CastSessionClientFactoryForTest { + CastSessionClientFactoryForTest { public: CastActivityRecordTest() {}
diff --git a/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc b/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc index 189883d..4af4556 100644 --- a/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc +++ b/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc
@@ -16,11 +16,12 @@ #include "chrome/common/media_router/providers/cast/cast_media_source.h" #include "components/cast_channel/cast_socket.h" #include "components/cast_channel/enum_table.h" +#include "components/cast_channel/proto/cast_channel.pb.h" #include "net/base/escape.h" namespace cast_util { -using media_router::CastInternalMessage; +using namespace media_router; template <> const EnumTable<CastInternalMessage::Type>
diff --git a/chrome/browser/media/router/providers/cast/cast_session_client.cc b/chrome/browser/media/router/providers/cast/cast_session_client.cc index dcf7f3ce..d30d336 100644 --- a/chrome/browser/media/router/providers/cast/cast_session_client.cc +++ b/chrome/browser/media/router/providers/cast/cast_session_client.cc
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// #include "chrome/common/media_router/mojo/media_router.mojom.h" #include "chrome/browser/media/router/providers/cast/cast_session_client.h" #include "base/bind.h" -#include "base/logging.h" #include "chrome/browser/media/router/data_decoder_util.h" #include "chrome/browser/media/router/providers/cast/cast_activity_record.h" #include "chrome/browser/media/router/providers/cast/cast_internal_message_util.h" @@ -23,9 +23,9 @@ void ReportClientMessageParseError(const MediaRoute::Id& route_id, const std::string& error) { - // TODO(crbug.com/905002): Record UMA metric for parse result. - LOG(ERROR) << "Failed to parse Cast client message for " << route_id << ": " - << error; + // TODO(crbug.com/808720): Record UMA metric for parse result. + DVLOG(2) << "Failed to parse Cast client message for " << route_id << ": " + << error; } } // namespace @@ -42,7 +42,7 @@ int tab_id, AutoJoinPolicy auto_join_policy, DataDecoder* data_decoder, - CastActivityRecordBase* activity) + CastActivityRecord* activity) : CastSessionClientBase(client_id, origin, tab_id), auto_join_policy_(auto_join_policy), data_decoder_(data_decoder), @@ -142,6 +142,7 @@ if (!cast_message) { ReportClientMessageParseError(activity_->route().media_route_id(), "Not a Cast message"); + DLOG(ERROR) << "Received non-Cast message from client"; return; }
diff --git a/chrome/browser/media/router/providers/cast/cast_session_client.h b/chrome/browser/media/router/providers/cast/cast_session_client.h index 43c115f6..9b83676 100644 --- a/chrome/browser/media/router/providers/cast/cast_session_client.h +++ b/chrome/browser/media/router/providers/cast/cast_session_client.h
@@ -23,7 +23,7 @@ namespace media_router { -class CastActivityRecordBase; +class CastActivityRecord; class DataDecoder; // TODO(jrw): Rename @@ -117,7 +117,7 @@ int tab_id, AutoJoinPolicy auto_join_policy, DataDecoder* data_decoder, - CastActivityRecordBase* activity); + CastActivityRecord* activity); ~CastSessionClient() override; // CastSessionClientBase implementation @@ -161,7 +161,7 @@ const AutoJoinPolicy auto_join_policy_; DataDecoder* const data_decoder_; - CastActivityRecordBase* const activity_; + CastActivityRecord* const activity_; // The maximum number of pending media requests, used to prevent memory leaks. // Normally the number of pending requests should be fairly small, but each
diff --git a/chrome/browser/media/router/providers/cast/cast_session_client_unittest.cc b/chrome/browser/media/router/providers/cast/cast_session_client_unittest.cc deleted file mode 100644 index 73828e4..0000000 --- a/chrome/browser/media/router/providers/cast/cast_session_client_unittest.cc +++ /dev/null
@@ -1,252 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/media/router/providers/cast/cast_session_client.h" - -// #include <iostream> -#include <memory> -#include <tuple> -#include <utility> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/run_loop.h" -#include "base/task/post_task.h" -#include "base/test/mock_log.h" -#include "base/test/values_test_util.h" -#include "chrome/browser/media/router/data_decoder_util.h" -#include "chrome/browser/media/router/providers/cast/cast_activity_manager.h" -#include "chrome/browser/media/router/providers/cast/cast_internal_message_util.h" -#include "chrome/browser/media/router/providers/cast/mock_cast_activity_record.h" -#include "chrome/browser/media/router/providers/cast/test_util.h" -#include "chrome/browser/media/router/providers/common/buffered_message_sender.h" -#include "chrome/browser/media/router/test/mock_mojo_media_router.h" -#include "chrome/browser/media/router/test/test_helper.h" -#include "chrome/common/media_router/test/test_helper.h" -#include "components/cast_channel/cast_test_util.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/test/test_browser_thread_bundle.h" -// #include "services/data_decoder/data_decoder_service.h" -#include "services/data_decoder/public/cpp/testing_json_parser.h" -// #include "services/data_decoder/public/mojom/constants.mojom.h" -#include "services/service_manager/public/cpp/test/test_connector_factory.h" -// #include "testing/gmock/include/gmock/gmock.h" -// #include "testing/gtest/include/gtest/gtest.h" - -using base::test::IsJson; -using base::test::ParseJson; -using testing::_; -using testing::AllOf; -using testing::AnyNumber; -using testing::HasSubstr; -using testing::IsEmpty; -using testing::Not; -using testing::Return; -using testing::WithArg; - -namespace media_router { - -namespace { -constexpr int kTabId = 213; - -class MockPresentationConnection : public blink::mojom::PresentationConnection { - public: - explicit MockPresentationConnection( - mojom::RoutePresentationConnectionPtr connections) - : binding_(this, std::move(connections->connection_request)) {} - - ~MockPresentationConnection() override = default; - - MOCK_METHOD1(OnMessage, void(blink::mojom::PresentationConnectionMessagePtr)); - MOCK_METHOD1(DidChangeState, - void(blink::mojom::PresentationConnectionState state)); - MOCK_METHOD1(DidClose, void(blink::mojom::PresentationConnectionCloseReason)); - - // NOTE: This member doesn't look like it's used for anything, but it needs to - // exist in order for Mojo magic to work correctly. - mojo::Binding<blink::mojom::PresentationConnection> binding_; - - DISALLOW_COPY_AND_ASSIGN(MockPresentationConnection); -}; - -} // namespace - -class CastSessionClientTest : public testing::Test { - public: - CastSessionClientTest() { activity_.set_session_id("theSessionId"); } - - ~CastSessionClientTest() override { RunUntilIdle(); } - - protected: - void RunUntilIdle() { thread_bundle_.RunUntilIdle(); } - - content::TestBrowserThreadBundle thread_bundle_; - data_decoder::TestingJsonParser::ScopedFactoryOverride parser_override_; - service_manager::TestConnectorFactory connector_factory_; - cast_channel::MockCastSocketService socket_service_{ - base::CreateSingleThreadTaskRunnerWithTraits( - {content::BrowserThread::UI})}; - cast_channel::MockCastMessageHandler message_handler_{&socket_service_}; - DataDecoder decoder_{connector_factory_.GetDefaultConnector()}; - url::Origin origin_; - MediaRoute route_; - MockCastActivityRecord activity_{route_, "theAppId"}; - std::unique_ptr<CastSessionClient> client_ = - std::make_unique<CastSessionClient>("theClientId", - origin_, - kTabId, - AutoJoinPolicy::kPageScoped, - &decoder_, - &activity_); - std::unique_ptr<MockPresentationConnection> mock_connection_ = - std::make_unique<MockPresentationConnection>(client_->Init()); - base::test::MockLog log_; -}; - -TEST_F(CastSessionClientTest, OnInvalidJson) { - // TODO(crbug.com/905002): Check UMA calls instead of logging (here and - // below). - EXPECT_CALL(log_, Log(logging::LOG_ERROR, _, _, _, - HasSubstr("Failed to parse Cast client message"))) - .WillOnce(Return(true)); // suppress logging - - log_.StartCapturingLogs(); - client_->OnMessage( - blink::mojom::PresentationConnectionMessage::NewMessage("invalid js")); -} - -TEST_F(CastSessionClientTest, OnInvalidMessage) { - EXPECT_CALL(log_, Log(logging::LOG_ERROR, _, _, _, - AllOf(HasSubstr("Failed to parse Cast client message"), - HasSubstr("Not a Cast message")))) - .WillOnce(Return(true)); // suppress logging - - log_.StartCapturingLogs(); - client_->OnMessage( - blink::mojom::PresentationConnectionMessage::NewMessage("{}")); -} - -TEST_F(CastSessionClientTest, OnMessageWrongClientId) { - EXPECT_CALL( - log_, Log(logging::LOG_ERROR, _, _, _, - AllOf(HasSubstr("Client ID mismatch"), HasSubstr("theClientId"), - HasSubstr("theWrongClientId")))) - .WillOnce(Return(true)); // suppress logging - - log_.StartCapturingLogs(); - client_->OnMessage( - blink::mojom::PresentationConnectionMessage::NewMessage(R"({ - "type": "v2_message", - "clientId": "theWrongClientId", - "message": { - "sessionId": "theSessionId", - "type": "MEDIA_GET_STATUS" - } - })")); -} - -TEST_F(CastSessionClientTest, OnMessageWrongSessionId) { - EXPECT_CALL(log_, Log(logging::LOG_ERROR, _, _, _, - AllOf(HasSubstr("Session ID mismatch"), - HasSubstr("theSessionId"), - HasSubstr("theWrongSessionId")))) - .WillOnce(Return(true)); // suppress logging - - log_.StartCapturingLogs(); - client_->OnMessage( - blink::mojom::PresentationConnectionMessage::NewMessage(R"({ - "type": "v2_message", - "clientId": "theClientId", - "message": { - "sessionId": "theWrongSessionId", - "type": "MEDIA_GET_STATUS" - } - })")); -} - -TEST_F(CastSessionClientTest, AppMessageFromClient) { - EXPECT_CALL(activity_, SendAppMessageToReceiver) - .WillOnce(Return(cast_channel::Result::kOk)); - - client_->OnMessage( - blink::mojom::PresentationConnectionMessage::NewMessage(R"({ - "type": "app_message", - "clientId": "theClientId", - "message": { - "namespaceName": "urn:x-cast:com.google.foo", - "sessionId": "theSessionId", - "message": {} - }, - "sequenceNumber": 123 - })")); -} - -TEST_F(CastSessionClientTest, OnMediaStatusUpdatedWithPendingRequest) { - EXPECT_CALL(activity_, SendMediaRequestToReceiver(IsCastInternalMessage(R"({ - "type": "v2_message", - "clientId": "theClientId", - "sequenceNumber": 123, - "message": { - "sessionId": "theSessionId", - "type": "MEDIA_GET_STATUS" - } - })"))) - .WillOnce(Return(345)); - client_->OnMessage( - blink::mojom::PresentationConnectionMessage::NewMessage(R"({ - "type": "v2_message", - "clientId": "theClientId", - "message": { - "sessionId": "theSessionId", - "type": "MEDIA_GET_STATUS" - }, - "sequenceNumber": 123 - })")); - RunUntilIdle(); - - EXPECT_CALL(*mock_connection_, OnMessage(IsCastMessage(R"({ - "clientId": "theClientId", - "message": {"foo": "bar"}, - "timeoutMillis": 0, - "type": "v2_message" - })"))); - client_->SendMediaStatusToClient(ParseJson(R"({"foo": "bar"})"), 123); -} - -TEST_F(CastSessionClientTest, SendSetVolumeCommandToReceiver) { - EXPECT_CALL(activity_, - SendSetVolumeRequestToReceiver(IsCastInternalMessage(R"({ - "type": "v2_message", - "clientId": "theClientId", - "sequenceNumber": 123, - "message": { - "sessionId": "theSessionId", - "type": "SET_VOLUME" - } - })"), - _)) - .WillOnce(WithArg<1>([](auto callback) { - std::move(callback).Run(cast_channel::Result::kOk); - })); - EXPECT_CALL(*mock_connection_, OnMessage(IsCastMessage(R"({ - "clientId": "theClientId", - "message": null, - "sequenceNumber": 123, - "timeoutMillis": 0, - "type": "v2_message" - })"))); - - client_->OnMessage( - blink::mojom::PresentationConnectionMessage::NewMessage(R"({ - "type": "v2_message", - "clientId": "theClientId", - "sequenceNumber": 123, - "message": { - "sessionId": "theSessionId", - "type": "SET_VOLUME" - } - })")); -} - -} // namespace media_router
diff --git a/chrome/browser/media/router/providers/cast/mock_cast_activity_record.h b/chrome/browser/media/router/providers/cast/mock_cast_activity_record.h index a72a33f..125c0ca 100644 --- a/chrome/browser/media/router/providers/cast/mock_cast_activity_record.h +++ b/chrome/browser/media/router/providers/cast/mock_cast_activity_record.h
@@ -5,10 +5,7 @@ #ifndef CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_MOCK_CAST_ACTIVITY_RECORD_H_ #define CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_MOCK_CAST_ACTIVITY_RECORD_H_ -#include <string> - #include "chrome/browser/media/router/providers/cast/cast_activity_record.h" -#include "chrome/browser/media/router/providers/cast/cast_internal_message_util.h" #include "chrome/browser/media/router/providers/cast/cast_session_client.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/media/router/providers/cast/test_util.cc b/chrome/browser/media/router/providers/cast/test_util.cc deleted file mode 100644 index 6c75cdc..0000000 --- a/chrome/browser/media/router/providers/cast/test_util.cc +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/media/router/providers/cast/test_util.h" - -#include "components/cast_channel/enum_table.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace media_router { - -std::ostream& operator<<(std::ostream& out, CastInternalMessage::Type type) { - return out << cast_util::EnumToString(type).value_or("<invalid>"); -} - -// TODO(jrw): Why won't gtest call this operator? -std::ostream& operator<<(std::ostream& out, - const CastInternalMessage& message) { - out << "{type=" << message.type() << ", client_id=" << message.client_id(); - if (message.sequence_number()) { - out << ", sequence_number=" << *message.sequence_number(); - } - if (message.has_session_id()) { - out << ", session_id=" << message.session_id(); - } - - switch (message.type()) { - case CastInternalMessage::Type::kAppMessage: - out << ", app_message_namespace=" << message.app_message_namespace() - << ", app_message_body=" << message.app_message_body(); - break; - case CastInternalMessage::Type::kV2Message: - out << ", v2_message_type=" << message.v2_message_type() - << ", v2_message_body=" << message.v2_message_body(); - break; - default: - break; - } - return out << "}"; -} - -} // namespace media_router
diff --git a/chrome/browser/media/router/providers/cast/test_util.h b/chrome/browser/media/router/providers/cast/test_util.h deleted file mode 100644 index b50f4d15..0000000 --- a/chrome/browser/media/router/providers/cast/test_util.h +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_TEST_UTIL_H_ -#define CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_TEST_UTIL_H_ - -#include <iosfwd> - -#include "base/test/values_test_util.h" -#include "chrome/browser/media/router/providers/cast/cast_internal_message_util.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace media_router { - -std::ostream& operator<<(std::ostream&, CastInternalMessage::Type); -std::ostream& operator<<(std::ostream&, const CastInternalMessage&); - -// Matcher for CastInternalMessage arguments. -MATCHER_P(IsCastInternalMessage, json, "") { - auto message = CastInternalMessage::From(base::test::ParseJson(json)); - DCHECK(message); - if (arg.type() != message->type() || - arg.client_id() != message->client_id() || - arg.sequence_number() != message->sequence_number()) - return false; - - if (arg.has_session_id() && arg.session_id() != message->session_id()) - return false; - - switch (arg.type()) { - case CastInternalMessage::Type::kAppMessage: - return arg.app_message_namespace() == message->app_message_namespace() && - arg.app_message_body() == message->app_message_body(); - case CastInternalMessage::Type::kV2Message: - return arg.v2_message_type() == message->v2_message_type() && - testing::Matches(base::test::IsJson(arg.v2_message_body()))( - message->v2_message_body()); - default: - return true; - } -} - -} // namespace media_router - -#endif // CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_TEST_UTIL_H_
diff --git a/chrome/browser/media/router/test/test_helper.h b/chrome/browser/media/router/test/test_helper.h index 677edd0..7873af0 100644 --- a/chrome/browser/media/router/test/test_helper.h +++ b/chrome/browser/media/router/test/test_helper.h
@@ -1,4 +1,3 @@ - // 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. @@ -6,15 +5,20 @@ #ifndef CHROME_BROWSER_MEDIA_ROUTER_TEST_TEST_HELPER_H_ #define CHROME_BROWSER_MEDIA_ROUTER_TEST_TEST_HELPER_H_ +#include <stddef.h> +#include <stdint.h> + #include <string> #include <vector> #include "base/macros.h" #include "base/test/values_test_util.h" +#include "build/build_config.h" #include "chrome/browser/media/router/issue_manager.h" #include "chrome/browser/media/router/issues_observer.h" #include "chrome/browser/media/router/media_routes_observer.h" #include "chrome/browser/media/router/media_sinks_observer.h" +#include "content/public/browser/presentation_service_delegate.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/blink/public/mojom/presentation/presentation.mojom.h" @@ -226,8 +230,6 @@ #endif // !defined(OS_ANDROID) -// Matcher for blink::mojom::PresentationConnectionMessagePtr arguments. -// TODO(jrw): Rename to something like IsPresentationConnectionMessage. MATCHER_P(IsCastMessage, json, "") { return arg->is_message() && base::test::IsJsonMatcher(json).MatchAndExplain( arg->get_message(), result_listener);
diff --git a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc index b1e69873b..abcc65b9 100644 --- a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc +++ b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
@@ -467,7 +467,7 @@ EXPECT_DOUBLE_EQ(0.5, GetEngagementScore(origin)); std::string url = web_contents->GetLastCommittedURL().spec(); - ASSERT_EQ("chrome://settings/content/notifications", url); + ASSERT_EQ(content::GetWebUIURLString("settings/content/notifications"), url); } #endif
diff --git a/chrome/browser/performance_manager/BUILD.gn b/chrome/browser/performance_manager/BUILD.gn new file mode 100644 index 0000000..de17cf02 --- /dev/null +++ b/chrome/browser/performance_manager/BUILD.gn
@@ -0,0 +1,16 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//chrome/common/features.gni") +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("mojo_bindings") { + sources = [ + "webui_graph_dump.mojom", + ] + public_deps = [ + "//mojo/public/mojom/base", + "//url/mojom:url_mojom_gurl", + ] +}
diff --git a/chrome/browser/performance_manager/OWNERS b/chrome/browser/performance_manager/OWNERS index 24d881e8..969f30f 100644 --- a/chrome/browser/performance_manager/OWNERS +++ b/chrome/browser/performance_manager/OWNERS
@@ -2,5 +2,9 @@ fdoray@chromium.org siggi@chromium.org +# For IPC security review +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS + # TEAM: catan-team@chromium.org # COMPONENT: Internals>ResourceCoordinator
diff --git a/chrome/browser/performance_manager/performance_manager.cc b/chrome/browser/performance_manager/performance_manager.cc index 9445cb25..c81ca65 100644 --- a/chrome/browser/performance_manager/performance_manager.cc +++ b/chrome/browser/performance_manager/performance_manager.cc
@@ -283,7 +283,7 @@ } void PerformanceManager::BindWebUIGraphDump( - resource_coordinator::mojom::WebUIGraphDumpRequest request, + mojom::WebUIGraphDumpRequest request, const service_manager::BindSourceInfo& source_info) { std::unique_ptr<WebUIGraphDumpImpl> graph_dump = std::make_unique<WebUIGraphDumpImpl>(&graph_);
diff --git a/chrome/browser/performance_manager/performance_manager.h b/chrome/browser/performance_manager/performance_manager.h index 7121d3f..bf69af53 100644 --- a/chrome/browser/performance_manager/performance_manager.h +++ b/chrome/browser/performance_manager/performance_manager.h
@@ -130,9 +130,8 @@ void BindInterfaceImpl(const std::string& interface_name, mojo::ScopedMessagePipeHandle message_pipe); - void BindWebUIGraphDump( - resource_coordinator::mojom::WebUIGraphDumpRequest request, - const service_manager::BindSourceInfo& source_info); + void BindWebUIGraphDump(mojom::WebUIGraphDumpRequest request, + const service_manager::BindSourceInfo& source_info); void OnGraphDumpConnectionError(WebUIGraphDumpImpl* graph_dump); InterfaceRegistry interface_registry_;
diff --git a/services/resource_coordinator/public/mojom/webui_graph_dump.mojom b/chrome/browser/performance_manager/webui_graph_dump.mojom similarity index 79% rename from services/resource_coordinator/public/mojom/webui_graph_dump.mojom rename to chrome/browser/performance_manager/webui_graph_dump.mojom index 8ace578..e71acf1 100644 --- a/services/resource_coordinator/public/mojom/webui_graph_dump.mojom +++ b/chrome/browser/performance_manager/webui_graph_dump.mojom
@@ -5,10 +5,11 @@ // This file exposes an interface to the chrome://discards Web UI to allow // viewing and exploring the CU graph. -module resource_coordinator.mojom; +module performance_manager.mojom; import "mojo/public/mojom/base/process_id.mojom"; import "mojo/public/mojom/base/time.mojom"; +import "url/mojom/url.mojom"; // Represents the momentary state of a Page CU. struct WebUIPageInfo { @@ -16,7 +17,7 @@ int64 main_frame_id; - string main_frame_url; + url.mojom.Url main_frame_url; // TODO(siggi): Estimate data. }; @@ -25,11 +26,7 @@ struct WebUIFrameInfo { int64 id; - // TODO(chrisha): This should use url.mojom.Url, but that currently creates a - // cyclic dependency on blink/renderer/platform, which contains the KURL impl. - // Either break this cycle ourselves, or wait for KURL to be moved. - // crbug.com/768298 - string url; + url.mojom.Url url; int64 parent_frame_id; int64 process_id; };
diff --git a/chrome/browser/performance_manager/webui_graph_dump_impl.cc b/chrome/browser/performance_manager/webui_graph_dump_impl.cc index 419d666..5ad5deb 100644 --- a/chrome/browser/performance_manager/webui_graph_dump_impl.cc +++ b/chrome/browser/performance_manager/webui_graph_dump_impl.cc
@@ -19,23 +19,20 @@ WebUIGraphDumpImpl::~WebUIGraphDumpImpl() {} -void WebUIGraphDumpImpl::Bind( - resource_coordinator::mojom::WebUIGraphDumpRequest request, - base::OnceClosure error_handler) { +void WebUIGraphDumpImpl::Bind(mojom::WebUIGraphDumpRequest request, + base::OnceClosure error_handler) { binding_.Bind(std::move(request)); binding_.set_connection_error_handler(std::move(error_handler)); } void WebUIGraphDumpImpl::GetCurrentGraph(GetCurrentGraphCallback callback) { - resource_coordinator::mojom::WebUIGraphPtr graph = - resource_coordinator::mojom::WebUIGraph::New(); + mojom::WebUIGraphPtr graph = mojom::WebUIGraph::New(); { auto processes = graph_->GetAllProcessNodes(); graph->processes.reserve(processes.size()); for (auto* process : processes) { - resource_coordinator::mojom::WebUIProcessInfoPtr process_info = - resource_coordinator::mojom::WebUIProcessInfo::New(); + mojom::WebUIProcessInfoPtr process_info = mojom::WebUIProcessInfo::New(); process_info->id = NodeBase::GetSerializationId(process); process_info->pid = process->process_id(); @@ -50,8 +47,7 @@ auto frames = graph_->GetAllFrameNodes(); graph->frames.reserve(frames.size()); for (auto* frame : frames) { - resource_coordinator::mojom::WebUIFrameInfoPtr frame_info = - resource_coordinator::mojom::WebUIFrameInfo::New(); + mojom::WebUIFrameInfoPtr frame_info = mojom::WebUIFrameInfo::New(); frame_info->id = NodeBase::GetSerializationId(frame); @@ -61,7 +57,7 @@ auto* process = frame->process_node(); frame_info->process_id = NodeBase::GetSerializationId(process); - frame_info->url = frame->url().spec(); + frame_info->url = frame->url(); graph->frames.push_back(std::move(frame_info)); } @@ -71,11 +67,10 @@ auto pages = graph_->GetAllPageNodes(); graph->pages.reserve(pages.size()); for (auto* page : pages) { - resource_coordinator::mojom::WebUIPageInfoPtr page_info = - resource_coordinator::mojom::WebUIPageInfo::New(); + mojom::WebUIPageInfoPtr page_info = mojom::WebUIPageInfo::New(); page_info->id = NodeBase::GetSerializationId(page); - page_info->main_frame_url = page->main_frame_url().spec(); + page_info->main_frame_url = page->main_frame_url(); auto* main_frame = page->GetMainFrameNode(); page_info->main_frame_id = NodeBase::GetSerializationId(main_frame);
diff --git a/chrome/browser/performance_manager/webui_graph_dump_impl.h b/chrome/browser/performance_manager/webui_graph_dump_impl.h index 514918c..d7ffa2f 100644 --- a/chrome/browser/performance_manager/webui_graph_dump_impl.h +++ b/chrome/browser/performance_manager/webui_graph_dump_impl.h
@@ -5,14 +5,14 @@ #ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_WEBUI_GRAPH_DUMP_IMPL_H_ #define CHROME_BROWSER_PERFORMANCE_MANAGER_WEBUI_GRAPH_DUMP_IMPL_H_ +#include "chrome/browser/performance_manager/webui_graph_dump.mojom.h" #include "mojo/public/cpp/bindings/binding.h" -#include "services/resource_coordinator/public/mojom/webui_graph_dump.mojom.h" namespace performance_manager { class GraphImpl; -class WebUIGraphDumpImpl : public resource_coordinator::mojom::WebUIGraphDump { +class WebUIGraphDumpImpl : public mojom::WebUIGraphDump { public: explicit WebUIGraphDumpImpl(GraphImpl* graph); ~WebUIGraphDumpImpl() override; @@ -21,12 +21,12 @@ void GetCurrentGraph(GetCurrentGraphCallback callback) override; // Bind this instance to |request| with the |error_handler|. - void Bind(resource_coordinator::mojom::WebUIGraphDumpRequest request, + void Bind(mojom::WebUIGraphDumpRequest request, base::OnceClosure error_handler); private: GraphImpl* graph_; - mojo::Binding<resource_coordinator::mojom::WebUIGraphDump> binding_; + mojo::Binding<mojom::WebUIGraphDump> binding_; DISALLOW_COPY_AND_ASSIGN(WebUIGraphDumpImpl); };
diff --git a/chrome/browser/performance_manager/webui_graph_dump_impl_unittest.cc b/chrome/browser/performance_manager/webui_graph_dump_impl_unittest.cc index 99a8618..9c9e9138 100644 --- a/chrome/browser/performance_manager/webui_graph_dump_impl_unittest.cc +++ b/chrome/browser/performance_manager/webui_graph_dump_impl_unittest.cc
@@ -31,12 +31,11 @@ WebUIGraphDumpImpl impl(&graph); - resource_coordinator::mojom::WebUIGraphPtr returned_graph; + mojom::WebUIGraphPtr returned_graph; WebUIGraphDumpImpl::GetCurrentGraphCallback callback = - base::BindLambdaForTesting( - [&returned_graph](resource_coordinator::mojom::WebUIGraphPtr graph) { - returned_graph = std::move(graph); - }); + base::BindLambdaForTesting([&returned_graph](mojom::WebUIGraphPtr graph) { + returned_graph = std::move(graph); + }); impl.GetCurrentGraph(std::move(callback)); task_env().RunUntilIdle();
diff --git a/chrome/browser/resources/discards/BUILD.gn b/chrome/browser/resources/discards/BUILD.gn index a49c5cb9..abe3f6ba 100644 --- a/chrome/browser/resources/discards/BUILD.gn +++ b/chrome/browser/resources/discards/BUILD.gn
@@ -50,8 +50,8 @@ js_library("graph_tab") { deps = [ + "//chrome/browser/performance_manager:mojo_bindings_js_library_for_compile", "//chrome/browser/ui/webui/discards:mojo_bindings_js_library_for_compile", - "//services/resource_coordinator/public/mojom:mojom_js_library_for_compile", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:cr", ] @@ -59,7 +59,7 @@ js_library("graph_doc") { deps = [ - "//services/resource_coordinator/public/mojom:mojom_js_library_for_compile", + "//chrome/browser/performance_manager:mojo_bindings_js_library_for_compile", ] externs_list = [ "../../../../third_party/d3/src/externs.js" ]
diff --git a/chrome/browser/resources/discards/graph_doc.js b/chrome/browser/resources/discards/graph_doc.js index 1cfcfe5..b072508 100644 --- a/chrome/browser/resources/discards/graph_doc.js +++ b/chrome/browser/resources/discards/graph_doc.js
@@ -102,17 +102,18 @@ } class PageNode extends GraphNode { - /** @param {!resourceCoordinator.mojom.WebUIPageInfo} page */ + /** @param {!performanceManager.mojom.WebUIPageInfo} page */ constructor(page) { super(page.id); - /** @type {!resourceCoordinator.mojom.WebUIPageInfo} */ + /** @type {!performanceManager.mojom.WebUIPageInfo} */ this.page = page; this.y = kPageNodesTargetY; } /** override */ get title() { - return this.page.mainFrameUrl.length > 0 ? this.page.mainFrameUrl : 'Page'; + return this.page.mainFrameUrl.url.length > 0 ? this.page.mainFrameUrl.url : + 'Page'; } /** @override */ @@ -137,17 +138,17 @@ } class FrameNode extends GraphNode { - /** @param {!resourceCoordinator.mojom.WebUIFrameInfo} frame */ + /** @param {!performanceManager.mojom.WebUIFrameInfo} frame */ constructor(frame) { super(frame.id); - /** @type {!resourceCoordinator.mojom.WebUIFrameInfo} frame */ + /** @type {!performanceManager.mojom.WebUIFrameInfo} frame */ this.frame = frame; this.color = this.selectColor(frame.processId); } /** override */ get title() { - return this.frame.url.length > 0 ? this.frame.url : 'Frame'; + return this.frame.url.url.length > 0 ? this.frame.url.url : 'Frame'; } /** override */ @@ -167,10 +168,10 @@ } class ProcessNode extends GraphNode { - /** @param {!resourceCoordinator.mojom.WebUIProcessInfo} process */ + /** @param {!performanceManager.mojom.WebUIProcessInfo} process */ constructor(process) { super(process.id); - /** @type {!resourceCoordinator.mojom.WebUIProcessInfo} */ + /** @type {!performanceManager.mojom.WebUIProcessInfo} */ this.process = process; this.color = this.selectColor(process.id); @@ -391,7 +392,7 @@ /** * @param {!Map<number, !GraphNode>} oldNodes - * @param {resourceCoordinator.mojom.WebUIPageInfo} page + * @param {performanceManager.mojom.WebUIPageInfo} page * @private */ addOrUpdatePage_(oldNodes, page) { @@ -411,7 +412,7 @@ /** * @param {!Map<number, !GraphNode>} oldNodes - * @param {resourceCoordinator.mojom.WebUIFrameInfo} frame + * @param {performanceManager.mojom.WebUIFrameInfo} frame * @private */ addOrUpdateFrame_(oldNodes, frame) { @@ -431,7 +432,7 @@ /** * @param {!Map<number, !GraphNode>} oldNodes - * @param {resourceCoordinator.mojom.WebUIProcessInfo} process + * @param {performanceManager.mojom.WebUIProcessInfo} process * @private */ addOrUpdateProcess_(oldNodes, process) { @@ -462,7 +463,7 @@ } /** - * @param {resourceCoordinator.mojom.WebUIGraph} graph An updated graph from + * @param {performanceManager.mojom.WebUIGraph} graph An updated graph from * the WebUI. * @private */
diff --git a/chrome/browser/resources/discards/graph_tab.js b/chrome/browser/resources/discards/graph_tab.js index 4f4484a..8ba93727 100644 --- a/chrome/browser/resources/discards/graph_tab.js +++ b/chrome/browser/resources/discards/graph_tab.js
@@ -8,7 +8,7 @@ /** * The Mojo graph data source. * - * @private {resourceCoordinator.mojom.WebUIGraphDumpProxy} + * @private {performanceManager.mojom.WebUIGraphDumpProxy} */ graphDump_: null, @@ -17,7 +17,7 @@ /** @override */ ready: function() { - this.graphDump_ = resourceCoordinator.mojom.WebUIGraphDump.getProxy(); + this.graphDump_ = performanceManager.mojom.WebUIGraphDump.getProxy(); }, /** @override */
diff --git a/chrome/browser/resources/discards/mojo_api.html b/chrome/browser/resources/discards/mojo_api.html index 3b7bbda..2dd0baa 100644 --- a/chrome/browser/resources/discards/mojo_api.html +++ b/chrome/browser/resources/discards/mojo_api.html
@@ -5,6 +5,7 @@ --> <link rel="import" href="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.html"> <link rel="import" href="chrome://resources/mojo/mojo/public/mojom/base/time.mojom.html"> +<link rel="import" href="chrome://resources/mojo/url/mojom/url.mojom.html"> <script src="mojo/public/mojom/base/process_id.mojom-lite.js"></script> <script src="chrome/browser/resource_coordinator/lifecycle_unit_state.mojom-lite.js">
diff --git a/chrome/browser/resources/history/history_item.js b/chrome/browser/resources/history/history_item.js index ec89a426..3e48c93 100644 --- a/chrome/browser/resources/history/history_item.js +++ b/chrome/browser/resources/history/history_item.js
@@ -209,7 +209,7 @@ */ onMenuButtonTap_: function(e) { this.fire('open-menu', { - target: Polymer.dom(e).localTarget, + target: e.target, index: this.index, item: this.item, });
diff --git a/chrome/browser/resources/history/synced_device_card.js b/chrome/browser/resources/history/synced_device_card.js index 6e1c5a6..083d18f 100644 --- a/chrome/browser/resources/history/synced_device_card.js +++ b/chrome/browser/resources/history/synced_device_card.js
@@ -110,7 +110,7 @@ */ updateIcons_: function() { this.async(function() { - const icons = Polymer.dom(this.root).querySelectorAll('.website-icon'); + const icons = this.shadowRoot.querySelectorAll('.website-icon'); for (let i = 0; i < this.tabs.length; i++) { icons[i].style.backgroundImage = cr.icon.getFavicon(this.tabs[i].url);
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_section.js b/chrome/browser/resources/settings/autofill_page/autofill_section.js index 530dcf0..652a4aa 100644 --- a/chrome/browser/resources/settings/autofill_page/autofill_section.js +++ b/chrome/browser/resources/settings/autofill_page/autofill_section.js
@@ -166,7 +166,7 @@ this.activeAddress = /** @type {!chrome.autofillPrivate.AddressEntry} */ ( Object.assign({}, item)); - const dotsButton = /** @type {!HTMLElement} */ (Polymer.dom(e).localTarget); + const dotsButton = /** @type {!HTMLElement} */ (e.target); /** @type {!CrActionMenuElement} */ (this.$.addressSharedMenu) .showAt(dotsButton); this.activeDialogAnchor_ = dotsButton;
diff --git a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html index 5508a8e..b10ede5 100644 --- a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html +++ b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html
@@ -57,15 +57,15 @@ <div slot="title">$i18n{passwordDetailsTitle}</div> <div slot="body"> <cr-input id="websiteInput" label="$i18n{editPasswordWebsiteLabel}" - value="[[item.entry.urls.link]]" readonly> + value="[[item.entry.urls.link]]" on-blur="onInputBlur_" readonly> </cr-input> <cr-input id="usernameInput" label="$i18n{editPasswordUsernameLabel}" - value="[[item.entry.username]]" readonly> + value="[[item.entry.username]]" on-blur="onInputBlur_" readonly> </cr-input> - <cr-input id="passwordInput" readonly - label="$i18n{editPasswordPasswordLabel}" + <cr-input id="passwordInput" label="$i18n{editPasswordPasswordLabel}" type="[[getPasswordInputType_(item.password)]]" - value="[[getPassword_(item.password)]]"> + value="[[getPassword_(item.password)]]" on-blur="onInputBlur_" + readonly> <cr-icon-button id="showPasswordButton" class$="[[getIconClass_(item.password)]]" slot="suffix" hidden$="[[item.entry.federationText]]"
diff --git a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.js b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.js index 2b353fb..1e5923f1 100644 --- a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.js +++ b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.js
@@ -32,5 +32,10 @@ onActionButtonTap_: function() { this.close(); }, + + /** Manually de-select texts for readonly inputs. */ + onInputBlur_: function() { + this.shadowRoot.getSelection().removeAllRanges(); + }, }); })();
diff --git a/chrome/browser/resources/settings/printing_page/cups_printers_list.js b/chrome/browser/resources/settings/printing_page/cups_printers_list.js index c92591a..0e266c7f 100644 --- a/chrome/browser/resources/settings/printing_page/cups_printers_list.js +++ b/chrome/browser/resources/settings/printing_page/cups_printers_list.js
@@ -46,8 +46,7 @@ this.activePrinter = e.model.item; const menu = /** @type {!CrActionMenuElement} */ (this.$$('cr-action-menu')); - menu.showAt(/** @type {!Element} */ ( - Polymer.dom(/** @type {!Event} */ (e)).localTarget)); + menu.showAt(/** @type {!Element} */ (/** @type {!Event} */ (e).target)); }, /**
diff --git a/chrome/browser/resources/settings/site_settings/protocol_handlers.js b/chrome/browser/resources/settings/site_settings/protocol_handlers.js index 49e6a3ed..5fe1b81 100644 --- a/chrome/browser/resources/settings/site_settings/protocol_handlers.js +++ b/chrome/browser/resources/settings/site_settings/protocol_handlers.js
@@ -207,8 +207,7 @@ this.actionMenuModel_ = event.model.item; /** @type {!CrActionMenuElement} */ (this.$$('cr-action-menu')) .showAt( - /** @type {!Element} */ ( - Polymer.dom(/** @type {!Event} */ (event)).localTarget)); + /** @type {!Element} */ (/** @type {!Event} */ (event).target)); }, // <if expr="chromeos">
diff --git a/chrome/browser/resources/settings/site_settings/site_entry.js b/chrome/browser/resources/settings/site_settings/site_entry.js index 412cbb0..ad60ba23 100644 --- a/chrome/browser/resources/settings/site_settings/site_entry.js +++ b/chrome/browser/resources/settings/site_settings/site_entry.js
@@ -369,7 +369,7 @@ */ showOverflowMenu_: function(e) { this.fire('open-menu', { - target: Polymer.dom(e).localTarget, + target: e.target, index: this.listIndex, item: this.siteGroup, }); @@ -451,4 +451,4 @@ }; } }, -}); \ No newline at end of file +});
diff --git a/chrome/browser/ui/passwords/settings/password_manager_presenter_unittest.cc b/chrome/browser/ui/passwords/settings/password_manager_presenter_unittest.cc index 6a5cabb..78810943 100644 --- a/chrome/browser/ui/passwords/settings/password_manager_presenter_unittest.cc +++ b/chrome/browser/ui/passwords/settings/password_manager_presenter_unittest.cc
@@ -222,8 +222,8 @@ } TEST_F(PasswordManagerPresenterTest, ChangeSavedPassword_UpdateDuplicates) { - AddPasswordEntry(GURL(kExampleCom), "user", "pass"); - AddPasswordEntry(GURL(kExampleCom), "user", "pass"); + AddPasswordEntry(GURL(std::string(kExampleCom) + "pathA"), "user", "pass"); + AddPasswordEntry(GURL(std::string(kExampleCom) + "pathB"), "user", "pass"); EXPECT_CALL(GetUIController(), SetPasswordList(SizeIs(1))); EXPECT_CALL(GetUIController(), SetPasswordExceptionList(IsEmpty())); UpdatePasswordLists();
diff --git a/chrome/browser/ui/webui/discards/BUILD.gn b/chrome/browser/ui/webui/discards/BUILD.gn index 62abc88..83e8fb4 100644 --- a/chrome/browser/ui/webui/discards/BUILD.gn +++ b/chrome/browser/ui/webui/discards/BUILD.gn
@@ -11,6 +11,7 @@ ] public_deps = [ + "//chrome/browser/performance_manager:mojo_bindings", "//chrome/browser/resource_coordinator:mojo_bindings", ] }
diff --git a/chrome/browser/ui/webui/discards/discards_ui.cc b/chrome/browser/ui/webui/discards/discards_ui.cc index 330ca8e..1c776f1 100644 --- a/chrome/browser/ui/webui/discards/discards_ui.cc +++ b/chrome/browser/ui/webui/discards/discards_ui.cc
@@ -451,7 +451,7 @@ } void DiscardsUI::BindWebUIGraphDumpProvider( - resource_coordinator::mojom::WebUIGraphDumpRequest request) { + performance_manager::mojom::WebUIGraphDumpRequest request) { performance_manager::PerformanceManager* performance_manager = performance_manager::PerformanceManager::GetInstance(); if (performance_manager) {
diff --git a/chrome/browser/ui/webui/discards/discards_ui.h b/chrome/browser/ui/webui/discards/discards_ui.h index 4ba70c8e..1ec8c1c 100644 --- a/chrome/browser/ui/webui/discards/discards_ui.h +++ b/chrome/browser/ui/webui/discards/discards_ui.h
@@ -8,8 +8,8 @@ #include <memory> #include "base/macros.h" +#include "chrome/browser/performance_manager/webui_graph_dump.mojom.h" #include "chrome/browser/ui/webui/discards/discards.mojom.h" -#include "services/resource_coordinator/public/mojom/webui_graph_dump.mojom.h" #include "ui/webui/mojo_web_ui_controller.h" namespace resource_coordinator { @@ -27,7 +27,7 @@ void BindDiscardsDetailsProvider( mojom::DiscardsDetailsProviderRequest request); void BindWebUIGraphDumpProvider( - resource_coordinator::mojom::WebUIGraphDumpRequest request); + performance_manager::mojom::WebUIGraphDumpRequest request); std::unique_ptr<mojom::DiscardsDetailsProvider> ui_handler_; resource_coordinator::LocalSiteCharacteristicsDataStoreInspector*
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 9e890888..c7c936be 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3617,13 +3617,10 @@ "../browser/media/router/providers/cast/cast_internal_message_util_unittest.cc", "../browser/media/router/providers/cast/cast_media_route_provider_metrics_unittest.cc", "../browser/media/router/providers/cast/cast_media_route_provider_unittest.cc", - "../browser/media/router/providers/cast/cast_session_client_unittest.cc", "../browser/media/router/providers/cast/cast_session_tracker_unittest.cc", "../browser/media/router/providers/cast/dual_media_sink_service_unittest.cc", "../browser/media/router/providers/cast/mock_cast_activity_record.cc", "../browser/media/router/providers/cast/mock_cast_activity_record.h", - "../browser/media/router/providers/cast/test_util.cc", - "../browser/media/router/providers/cast/test_util.h", "../browser/media/router/providers/dial/dial_activity_manager_unittest.cc", "../browser/media/router/providers/dial/dial_internal_message_util_unittest.cc", "../browser/media/router/providers/dial/dial_media_route_provider_unittest.cc",
diff --git a/chrome/test/data/webui/cr_elements/cr_radio_group_test.js b/chrome/test/data/webui/cr_elements/cr_radio_group_test.js index d80a59f..c483355 100644 --- a/chrome/test/data/webui/cr_elements/cr_radio_group_test.js +++ b/chrome/test/data/webui/cr_elements/cr_radio_group_test.js
@@ -96,11 +96,15 @@ // Check for decrement. checkPressed(['Home', 'PageUp', 'ArrowUp', 'ArrowLeft'], 2, 1); // No change when reached first selected. - checkPressed(['Home', 'PageUp', 'ArrowUp', 'ArrowLeft'], 1, 1); + checkPressed(['Home'], 1, 1); + // Wraps when decrementing when first selected. + checkPressed(['PageUp', 'ArrowUp', 'ArrowLeft'], 1, 3); // Check for increment. checkPressed(['End', 'ArrowRight', 'PageDown', 'ArrowDown'], 2, 3); // No change when reached last selected. - checkPressed(['End', 'ArrowRight', 'PageDown', 'ArrowDown'], 3, 3); + checkPressed(['End'], 3, 3); + // Wraps when incrementing when last selected. + checkPressed(['ArrowRight', 'PageDown', 'ArrowDown'], 3, 1); }); test('mouse event', () => {
diff --git a/chrome/test/data/webui/history/history_item_test.js b/chrome/test/data/webui/history/history_item_test.js index d5c322a2..095efe19 100644 --- a/chrome/test/data/webui/history/history_item_test.js +++ b/chrome/test/data/webui/history/history_item_test.js
@@ -79,7 +79,7 @@ return PolymerTest.flushTasks().then(function() { Polymer.dom.flush(); // Check that the correct number of time gaps are inserted. - const items = Polymer.dom(element.root).querySelectorAll('history-item'); + const items = element.shadowRoot.querySelectorAll('history-item'); assertTrue(items[0].hasTimeGap); assertTrue(items[1].hasTimeGap); @@ -96,7 +96,7 @@ return PolymerTest.flushTasks().then(function() { Polymer.dom.flush(); - const items = Polymer.dom(element.root).querySelectorAll('history-item'); + const items = element.shadowRoot.querySelectorAll('history-item'); assertTrue(items[0].hasTimeGap); assertFalse(items[1].hasTimeGap); @@ -108,7 +108,7 @@ element.addNewResults(TEST_HISTORY_RESULTS); return PolymerTest.flushTasks().then(function() { Polymer.dom.flush(); - const items = Polymer.dom(element.root).querySelectorAll('history-item'); + const items = element.shadowRoot.querySelectorAll('history-item'); element.removeItemsByIndex_([3]); assertEquals(5, element.historyData_.length); @@ -132,8 +132,7 @@ return PolymerTest.flushTasks(); }) .then(function() { - - items = Polymer.dom(element.root).querySelectorAll('history-item'); + items = element.shadowRoot.querySelectorAll('history-item'); items[1].$$('#bookmark-star').focus(); MockInteractions.tap(items[1].$$('#bookmark-star'));
diff --git a/chrome/test/data/webui/history/history_supervised_user_test.js b/chrome/test/data/webui/history/history_supervised_user_test.js index d292248..2279f467 100644 --- a/chrome/test/data/webui/history/history_supervised_user_test.js +++ b/chrome/test/data/webui/history/history_supervised_user_test.js
@@ -22,8 +22,7 @@ test('checkboxes disabled for supervised user', function() { return PolymerTest.flushTasks().then(function() { - const items = - Polymer.dom(historyList.root).querySelectorAll('history-item'); + const items = historyList.shadowRoot.querySelectorAll('history-item'); MockInteractions.tap(items[0].$['checkbox']);
diff --git a/chrome/test/data/webui/history/history_synced_tabs_test.js b/chrome/test/data/webui/history/history_synced_tabs_test.js index d9c94496..3296ea4 100644 --- a/chrome/test/data/webui/history/history_synced_tabs_test.js +++ b/chrome/test/data/webui/history/history_synced_tabs_test.js
@@ -43,8 +43,7 @@ const card = element.$$('history-synced-device-card'); assertEquals( 'http://www.google.com', - Polymer.dom(card.root) - .querySelectorAll('.website-title')[0] + card.shadowRoot.querySelectorAll('.website-title')[0] .textContent.trim()); assertEquals(2, card.tabs.length); }); @@ -108,8 +107,8 @@ // Check that the actual link changes. assertEquals( 'http://crbug.com/new', - Polymer.dom(cards[0].root) - .querySelectorAll('.website-title')[1] + cards[0] + .shadowRoot.querySelectorAll('.website-title')[1] .textContent.trim()); }); }); @@ -156,8 +155,8 @@ // Ensure the title text is rendered during searches. assertEquals( 'http://www.google.com', - Polymer.dom(cards[0].root) - .querySelectorAll('.website-title')[0] + cards[0] + .shadowRoot.querySelectorAll('.website-title')[0] .textContent.trim()); element.searchTerm = 'Sans';
diff --git a/chrome/test/data/webui/settings/all_sites_tests.js b/chrome/test/data/webui/settings/all_sites_tests.js index 5abc3a6..e83ee91 100644 --- a/chrome/test/data/webui/settings/all_sites_tests.js +++ b/chrome/test/data/webui/settings/all_sites_tests.js
@@ -150,8 +150,8 @@ Polymer.dom.flush(); const siteEntries = testElement.$.listContainer.querySelectorAll('site-entry'); - const hiddenSiteEntries = Polymer.dom(testElement.root) - .querySelectorAll('site-entry[hidden]'); + const hiddenSiteEntries = + testElement.shadowRoot.querySelectorAll('site-entry[hidden]'); assertEquals(1, siteEntries.length - hiddenSiteEntries.length); for (let i = 0; i < siteEntries; ++i) {
diff --git a/chrome/test/data/webui/settings/certificate_manager_test.js b/chrome/test/data/webui/settings/certificate_manager_test.js index d61fefb..785dcba 100644 --- a/chrome/test/data/webui/settings/certificate_manager_test.js +++ b/chrome/test/data/webui/settings/certificate_manager_test.js
@@ -302,8 +302,7 @@ test('DeleteSuccess', function() { assertTrue(dialog.$.dialog.open); // Check that the dialog title includes the certificate name. - const titleEl = - Polymer.dom(dialog.$.dialog).querySelector('[slot=title]'); + const titleEl = dialog.$.dialog.querySelector('[slot=title]'); assertTrue(titleEl.textContent.includes(model.name)); // Simulate clicking 'OK'. @@ -359,7 +358,7 @@ test('EncryptSuccess', function() { const passwordInputElements = - Polymer.dom(dialog.$.dialog).querySelectorAll('cr-input'); + dialog.$.dialog.querySelectorAll('cr-input'); const passwordInputElement = passwordInputElements[0]; const confirmPasswordInputElement = passwordInputElements[1]; @@ -394,7 +393,7 @@ browserProxy.forceCertificatesError(); const passwordInputElements = - Polymer.dom(dialog.$.dialog).querySelectorAll('cr-input'); + dialog.$.dialog.querySelectorAll('cr-input'); const passwordInputElement = passwordInputElements[0]; passwordInputElement.value = 'foopassword'; const confirmPasswordInputElement = passwordInputElements[1]; @@ -434,8 +433,7 @@ }); test('DecryptSuccess', function() { - const passwordInputElement = - Polymer.dom(dialog.$.dialog).querySelector('cr-input'); + const passwordInputElement = dialog.$.dialog.querySelector('cr-input'); assertTrue(dialog.$.dialog.open); // Test that the 'OK' button is enabled even when the password field is @@ -459,8 +457,7 @@ test('DecryptError', function() { browserProxy.forceCertificatesError(); // Simulate entering some password. - const passwordInputElement = - Polymer.dom(dialog.$.dialog).querySelector('cr-input'); + const passwordInputElement = dialog.$.dialog.querySelector('cr-input'); passwordInputElement.value = 'foopassword'; triggerInputEvent(passwordInputElement);
diff --git a/chrome/test/data/webui/settings/search_engines_page_test.js b/chrome/test/data/webui/settings/search_engines_page_test.js index a610387a..70c6ec58 100644 --- a/chrome/test/data/webui/settings/search_engines_page_test.js +++ b/chrome/test/data/webui/settings/search_engines_page_test.js
@@ -340,14 +340,13 @@ // if IronList.items instead of the child nodes. Polymer.dom.flush(); const defaultsList = searchEnginesLists[0]; - const defaultsEntries = Polymer.dom(defaultsList.shadowRoot) - .querySelector('iron-list') - .items; + const defaultsEntries = + defaultsList.shadowRoot.querySelector('iron-list').items; assertEquals(searchEnginesInfo.defaults.length, defaultsEntries.length); const othersList = searchEnginesLists[1]; const othersEntries = - Polymer.dom(othersList.shadowRoot).querySelector('iron-list').items; + othersList.shadowRoot.querySelector('iron-list').items; assertEquals(searchEnginesInfo.others.length, othersEntries.length); // Ensure that the search engines have reverse alphabetical order in the @@ -360,7 +359,7 @@ assertEquals(searchEnginesInfo.others[0].name, othersEntries[1].name); const extensionEntries = - Polymer.dom(page.shadowRoot).querySelector('iron-list').items; + page.shadowRoot.querySelector('iron-list').items; assertEquals( searchEnginesInfo.extensions.length, extensionEntries.length); });
diff --git a/chrome/test/data/webui/settings/site_details_tests.js b/chrome/test/data/webui/settings/site_details_tests.js index 79ced1fe..141797f 100644 --- a/chrome/test/data/webui/settings/site_details_tests.js +++ b/chrome/test/data/webui/settings/site_details_tests.js
@@ -228,7 +228,7 @@ const api = document.createElement('mock-website-usage-private-api-storage'); testElement.$.usageApi = api; - Polymer.dom(parent).appendChild(api); + parent.appendChild(api); Polymer.dom.flush(); // Call onOriginChanged_() manually to simulate a new navigation. @@ -272,7 +272,7 @@ const api = document.createElement('mock-website-usage-private-api-cookies'); testElement.$.usageApi = api; - Polymer.dom(parent).appendChild(api); + parent.appendChild(api); Polymer.dom.flush(); // Call onOriginChanged_() manually to simulate a new navigation. @@ -394,7 +394,7 @@ }); let api = document.createElement('mock1-website-usage-private-api'); testElement.$.usageApi = api; - Polymer.dom(parent).appendChild(api); + parent.appendChild(api); Polymer.dom.flush(); // Check both cancelling and accepting the dialog closes it.
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index c655efce..6cb5328 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn
@@ -234,16 +234,6 @@ # To disable a specific test, add it the following list. tast_disabled_tests = [] } - tast_test("chrome_kevin_tast_tests") { - # Tests that fail on Kevin devices. - tast_disabled_tests = [ - # Disabled due to misleading USE flags on full boards. crbug.com/916367 - "arc.Boot", - "arc.BuildProperties", - "security.NetworkListenersARC", - "video.WebRTCPeerConnCameraVP8", # crbug.com/923061 - ] - } group("cros_chrome_deploy") { # The following run-time dependencies are needed to deploy chrome to a
diff --git a/components/contextual_search/core/browser/public.cc b/components/contextual_search/core/browser/public.cc index e5acbd8..42755adf 100644 --- a/components/contextual_search/core/browser/public.cc +++ b/components/contextual_search/core/browser/public.cc
@@ -7,8 +7,14 @@ namespace contextual_search { const char kContextualSearchFieldTrialName[] = "ContextualSearch"; -const char kContextualCardsVersionParamName[] = "contextual_cards_version"; +// Longpress Resolve variations: +const char kLongpressResolveParamName[] = "longpress_resolve_variation"; +const char kLongpressResolveHideOnScroll[] = "1"; +const char kLongpressResolvePrivacyAggressive[] = "2"; + +// Contextual Cards variations and integration Api settings. +const char kContextualCardsVersionParamName[] = "contextual_cards_version"; // The version of the Contextual Cards API that we want to invoke. const int kContextualCardsEntityIntegration = 1; const int kContextualCardsQuickActionsIntegration = 2;
diff --git a/components/contextual_search/core/browser/public.h b/components/contextual_search/core/browser/public.h index 48e619c0..08181a7 100644 --- a/components/contextual_search/core/browser/public.h +++ b/components/contextual_search/core/browser/public.h
@@ -37,6 +37,12 @@ // String form of kContextualCardsSimplifiedServerMixin + // kContextualCardsDiagnosticIntegration. extern const char kContextualCardsSimplifiedServerWithDiagnosticChar[]; + +// Longpress resolve variations: +extern const char kLongpressResolveParamName[]; +extern const char kLongpressResolveHideOnScroll[]; +extern const char kLongpressResolvePrivacyAggressive[]; + } // namespace contextual_search #endif // COMPONENTS_CONTEXTUAL_SEARCH_CORE_BROWSER_PUBLIC_H_
diff --git a/components/gwp_asan/client/sampling_malloc_shims.cc b/components/gwp_asan/client/sampling_malloc_shims.cc index 94f6590b..4e23af21 100644 --- a/components/gwp_asan/client/sampling_malloc_shims.cc +++ b/components/gwp_asan/client/sampling_malloc_shims.cc
@@ -252,7 +252,7 @@ size_t num_metadata, size_t total_pages, size_t sampling_frequency) { - static crash_reporter::CrashKeyString<24> malloc_crash_key(kGpaCrashKey); + static crash_reporter::CrashKeyString<24> malloc_crash_key(kMallocCrashKey); gpa = new GuardedPageAllocator(); gpa->Init(max_allocated_pages, num_metadata, total_pages); malloc_crash_key.Set(gpa->GetCrashKey());
diff --git a/components/gwp_asan/client/sampling_malloc_shims_unittest.cc b/components/gwp_asan/client/sampling_malloc_shims_unittest.cc index 8d5d7aa..aaaea76 100644 --- a/components/gwp_asan/client/sampling_malloc_shims_unittest.cc +++ b/components/gwp_asan/client/sampling_malloc_shims_unittest.cc
@@ -229,7 +229,7 @@ MULTIPROCESS_TEST_MAIN_WITH_SETUP( CrashKey, SamplingMallocShimsTest::multiprocessTestSetup) { - if (crash_reporter::GetCrashKeyValue(kGpaCrashKey) != + if (crash_reporter::GetCrashKeyValue(kMallocCrashKey) != GetMallocGpaForTesting().GetCrashKey()) { return kFailure; }
diff --git a/components/gwp_asan/common/crash_key_name.h b/components/gwp_asan/common/crash_key_name.h index 50cf366b..b4e8562 100644 --- a/components/gwp_asan/common/crash_key_name.h +++ b/components/gwp_asan/common/crash_key_name.h
@@ -8,9 +8,9 @@ namespace gwp_asan { namespace internal { -// The name of the crash key used to convey the address of the -// AllocatorBaseState to the crash handler. -const char kGpaCrashKey[] = "allocator-base-state-address"; +// The name of the crash key used to convey the address of the AllocatorState +// for the malloc hooks to the crash handler. +const char kMallocCrashKey[] = "gwp-asan-malloc"; } // namespace internal } // namespace gwp_asan
diff --git a/components/gwp_asan/crash_handler/crash_analyzer.cc b/components/gwp_asan/crash_handler/crash_analyzer.cc index 531efbbf..7f4652d6 100644 --- a/components/gwp_asan/crash_handler/crash_analyzer.cc +++ b/components/gwp_asan/crash_handler/crash_analyzer.cc
@@ -73,7 +73,7 @@ const crashpad::ProcessSnapshot& process_snapshot) { for (auto* module : process_snapshot.Modules()) { for (auto annotation : module->AnnotationObjects()) { - if (annotation.name != kGpaCrashKey) + if (annotation.name != kMallocCrashKey) continue; if (annotation.type !=
diff --git a/components/gwp_asan/crash_handler/crash_handler_unittest.cc b/components/gwp_asan/crash_handler/crash_handler_unittest.cc index 1aafd2e..d529a5b 100644 --- a/components/gwp_asan/crash_handler/crash_handler_unittest.cc +++ b/components/gwp_asan/crash_handler/crash_handler_unittest.cc
@@ -87,7 +87,7 @@ std::string gpa_addr = gpa->GetCrashKey(); static crashpad::Annotation gpa_annotation( - crashpad::Annotation::Type::kString, kGpaCrashKey, + crashpad::Annotation::Type::kString, kMallocCrashKey, const_cast<char*>(gpa_addr.c_str())); gpa_annotation.SetSize(gpa_addr.size());
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index ab14de2..0ecdde87 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -43,6 +43,8 @@ "android_affiliation/lookup_affiliation_response_parser.cc", "android_affiliation/lookup_affiliation_response_parser.h", "android_affiliation/test_affiliation_fetcher_factory.h", + "blacklisted_credentials_cleaner.cc", + "blacklisted_credentials_cleaner.h", "browser_save_password_progress_logger.cc", "browser_save_password_progress_logger.h", "credential_manager_impl.cc", @@ -420,6 +422,7 @@ "android_affiliation/affiliation_service_unittest.cc", "android_affiliation/affiliation_utils_unittest.cc", "android_affiliation/facet_manager_unittest.cc", + "blacklisted_credentials_cleaner_unittest.cc", "browser_save_password_progress_logger_unittest.cc", "credential_manager_impl_unittest.cc", "credential_manager_logger_unittest.cc",
diff --git a/components/password_manager/core/browser/blacklisted_credentials_cleaner.cc b/components/password_manager/core/browser/blacklisted_credentials_cleaner.cc new file mode 100644 index 0000000..ece8b21f --- /dev/null +++ b/components/password_manager/core/browser/blacklisted_credentials_cleaner.cc
@@ -0,0 +1,67 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/password_manager/core/browser/blacklisted_credentials_cleaner.h" + +#include <set> +#include <utility> + +#include "base/logging.h" +#include "base/metrics/histogram_functions.h" +#include "components/autofill/core/common/password_form.h" +#include "components/password_manager/core/browser/password_manager_util.h" +#include "components/password_manager/core/browser/password_store.h" +#include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/prefs/pref_service.h" + +namespace password_manager { + +BlacklistedCredentialsCleaner::BlacklistedCredentialsCleaner( + scoped_refptr<PasswordStore> store, + PrefService* prefs) + : store_(std::move(store)), prefs_(prefs) {} + +BlacklistedCredentialsCleaner::~BlacklistedCredentialsCleaner() = default; + +bool BlacklistedCredentialsCleaner::NeedsCleaning() { + const bool needs_cleaning = + !prefs_->GetBoolean(prefs::kBlacklistedCredentialsNormalized); + base::UmaHistogramBoolean( + "PasswordManager.BlacklistedSites.NeedNormalization", needs_cleaning); + return needs_cleaning; +} + +void BlacklistedCredentialsCleaner::StartCleaning(Observer* observer) { + observer_ = observer; + store_->GetBlacklistLogins(this); +} + +void BlacklistedCredentialsCleaner::OnGetPasswordStoreResults( + std::vector<std::unique_ptr<autofill::PasswordForm>> results) { + std::set<std::string> signon_realms; + for (const auto& result : results) { + DCHECK(result->blacklisted_by_user); + if (!signon_realms.insert(result->signon_realm).second) { + // Insertion failed due to already existing signon realm, so we remove the + // duplicated entry from the store. + store_->RemoveLogin(*result); + continue; + } + + autofill::PasswordForm blacklisted = + password_manager_util::MakeNormalizedBlacklistedForm( + PasswordStore::FormDigest(*result)); + blacklisted.date_created = result->date_created; + // In case |blacklisted| and |result| differ, update the store. + if (!ArePasswordFormUniqueKeyEqual(blacklisted, *result)) + store_->UpdateLoginWithPrimaryKey(blacklisted, *result); + else if (blacklisted != *result) + store_->UpdateLogin(blacklisted); + } + + prefs_->SetBoolean(prefs::kBlacklistedCredentialsNormalized, true); + observer_->CleaningCompleted(); +} + +} // namespace password_manager
diff --git a/components/password_manager/core/browser/blacklisted_credentials_cleaner.h b/components/password_manager/core/browser/blacklisted_credentials_cleaner.h new file mode 100644 index 0000000..f00b16e4 --- /dev/null +++ b/components/password_manager/core/browser/blacklisted_credentials_cleaner.h
@@ -0,0 +1,59 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_BLACKLISTED_CREDENTIALS_CLEANER_H_ +#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_BLACKLISTED_CREDENTIALS_CLEANER_H_ + +#include <memory> +#include <vector> + +#include "base/memory/ref_counted.h" +#include "components/password_manager/core/browser/credentials_cleaner.h" +#include "components/password_manager/core/browser/password_store_consumer.h" + +class PrefService; + +namespace autofill { +struct PasswordForm; +} + +namespace password_manager { + +class PasswordStore; + +// This class is responsible for cleaning up blacklisted credentials. In +// particular, it does the following operations: +// - De-duplicate existing blacklisted credentials by making sure there is at +// most one blacklisted credential per signon realm. +// - Normalize existing blacklisted credentials by clearing out all data except +// scheme, signon realm and origin. +class BlacklistedCredentialsCleaner : public CredentialsCleaner, + public PasswordStoreConsumer { + public: + BlacklistedCredentialsCleaner(scoped_refptr<PasswordStore> store, + PrefService* prefs); + BlacklistedCredentialsCleaner(const BlacklistedCredentialsCleaner&) = delete; + BlacklistedCredentialsCleaner& operator=( + const BlacklistedCredentialsCleaner&) = delete; + ~BlacklistedCredentialsCleaner() override; + + // CredentialsCleaner: + bool NeedsCleaning() override; + void StartCleaning(Observer* observer) override; + + private: + // PasswordStoreConsumer: + void OnGetPasswordStoreResults( + std::vector<std::unique_ptr<autofill::PasswordForm>> results) override; + + const scoped_refptr<PasswordStore> store_; + + PrefService* prefs_ = nullptr; + + Observer* observer_ = nullptr; +}; + +} // namespace password_manager + +#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_BLACKLISTED_CREDENTIALS_CLEANER_H_
diff --git a/components/password_manager/core/browser/blacklisted_credentials_cleaner_unittest.cc b/components/password_manager/core/browser/blacklisted_credentials_cleaner_unittest.cc new file mode 100644 index 0000000..96a63bf3 --- /dev/null +++ b/components/password_manager/core/browser/blacklisted_credentials_cleaner_unittest.cc
@@ -0,0 +1,174 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/password_manager/core/browser/blacklisted_credentials_cleaner.h" + +#include "base/strings/utf_string_conversions.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_task_environment.h" +#include "base/time/time.h" +#include "components/password_manager/core/browser/test_password_store.h" +#include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/testing_pref_service.h" +#include "components/sync/model/syncable_service.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace password_manager { + +namespace { + +using autofill::PasswordForm; +using ::testing::ElementsAre; + +constexpr char kTestURL[] = "https://example.com/login/"; +constexpr char kTestUsername[] = "Username"; +constexpr char kTestUsernameElement[] = "username_element"; +constexpr char kTestUsername2[] = "Username2"; +constexpr char kTestPassword[] = "12345"; +constexpr char kTestPasswordElement[] = "password_element"; +constexpr char kTestSubmitElement[] = "submit_element"; +// An arbitrary creation date different from a default constructed base::Time(). +const base::Time kTestCreationDate = + base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromDays(1)); + +PasswordForm GetTestCredential() { + PasswordForm form; + form.scheme = PasswordForm::SCHEME_HTML; + form.signon_realm = GURL(kTestURL).GetOrigin().spec(); + form.origin = GURL(kTestURL); + form.username_element = base::ASCIIToUTF16(kTestUsernameElement); + form.username_value = base::ASCIIToUTF16(kTestUsername); + form.password_element = base::ASCIIToUTF16(kTestPasswordElement); + form.password_value = base::ASCIIToUTF16(kTestPassword); + form.submit_element = base::ASCIIToUTF16(kTestSubmitElement); + form.date_created = kTestCreationDate; + return form; +} + +} // namespace + +class MockCredentialsCleanerObserver : public CredentialsCleaner::Observer { + public: + MOCK_METHOD0(CleaningCompleted, void()); +}; + +class BlacklistedCredentialsCleanerTest : public ::testing::Test { + public: + BlacklistedCredentialsCleanerTest() { + EXPECT_TRUE( + store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr)); + prefs_.registry()->RegisterBooleanPref( + prefs::kBlacklistedCredentialsNormalized, false); + } + + BlacklistedCredentialsCleanerTest(const BlacklistedCredentialsCleanerTest&) = + delete; + BlacklistedCredentialsCleanerTest& operator=( + const BlacklistedCredentialsCleanerTest&) = delete; + + ~BlacklistedCredentialsCleanerTest() override { + store_->ShutdownOnUIThread(); + scoped_task_environment_.RunUntilIdle(); + } + + protected: + base::test::ScopedTaskEnvironment scoped_task_environment_; + base::HistogramTester histogram_tester_; + const scoped_refptr<TestPasswordStore> store_ = + base::MakeRefCounted<TestPasswordStore>(); + TestingPrefServiceSimple prefs_; + BlacklistedCredentialsCleaner cleaner_{store_, &prefs_}; +}; + +TEST_F(BlacklistedCredentialsCleanerTest, NoCleaningWhenPrefIsSet) { + prefs_.SetBoolean(prefs::kBlacklistedCredentialsNormalized, true); + EXPECT_FALSE(cleaner_.NeedsCleaning()); + histogram_tester_.ExpectUniqueSample( + "PasswordManager.BlacklistedSites.NeedNormalization", false, 1); +} + +TEST_F(BlacklistedCredentialsCleanerTest, CleanerUpdatesPref) { + EXPECT_TRUE(cleaner_.NeedsCleaning()); + histogram_tester_.ExpectUniqueSample( + "PasswordManager.BlacklistedSites.NeedNormalization", true, 1); + + MockCredentialsCleanerObserver observer; + cleaner_.StartCleaning(&observer); + EXPECT_CALL(observer, CleaningCompleted); + scoped_task_environment_.RunUntilIdle(); + + EXPECT_TRUE(prefs_.GetBoolean(prefs::kBlacklistedCredentialsNormalized)); +} + +TEST_F(BlacklistedCredentialsCleanerTest, CleanerNormalizesData) { + PasswordForm test_credential = GetTestCredential(); + test_credential.blacklisted_by_user = true; + store_->AddLogin(test_credential); + + MockCredentialsCleanerObserver observer; + cleaner_.StartCleaning(&observer); + EXPECT_CALL(observer, CleaningCompleted); + scoped_task_environment_.RunUntilIdle(); + + TestPasswordStore::PasswordMap stored_passwords = store_->stored_passwords(); + ASSERT_EQ(1u, stored_passwords.size()); + + PasswordForm blacklisted_form; + blacklisted_form.blacklisted_by_user = true; + blacklisted_form.scheme = PasswordForm::SCHEME_HTML; + blacklisted_form.signon_realm = GURL(kTestURL).GetOrigin().spec(); + blacklisted_form.origin = GURL(kTestURL).GetOrigin(); + blacklisted_form.date_created = kTestCreationDate; + EXPECT_THAT(stored_passwords.begin()->second, ElementsAre(blacklisted_form)); +} + +TEST_F(BlacklistedCredentialsCleanerTest, + CleanerDoesNotModifyNonBlacklistedEntries) { + PasswordForm test_credential = GetTestCredential(); + store_->AddLogin(test_credential); + + MockCredentialsCleanerObserver observer; + cleaner_.StartCleaning(&observer); + EXPECT_CALL(observer, CleaningCompleted); + scoped_task_environment_.RunUntilIdle(); + + TestPasswordStore::PasswordMap stored_passwords = store_->stored_passwords(); + ASSERT_EQ(1u, stored_passwords.size()); + EXPECT_THAT(stored_passwords.begin()->second, ElementsAre(test_credential)); +} + +TEST_F(BlacklistedCredentialsCleanerTest, CleanerDeduplicatesForms) { + PasswordForm test_credential = GetTestCredential(); + test_credential.blacklisted_by_user = true; + store_->AddLogin(test_credential); + + // Create a duplicated entry for the same signon realm. + test_credential.username_value = base::ASCIIToUTF16(kTestUsername2); + store_->AddLogin(test_credential); + scoped_task_environment_.RunUntilIdle(); + + const TestPasswordStore::PasswordMap& stored_passwords = + store_->stored_passwords(); + ASSERT_EQ(1u, stored_passwords.size()); + ASSERT_EQ(2u, stored_passwords.begin()->second.size()); + + MockCredentialsCleanerObserver observer; + cleaner_.StartCleaning(&observer); + EXPECT_CALL(observer, CleaningCompleted); + scoped_task_environment_.RunUntilIdle(); + + ASSERT_EQ(1u, stored_passwords.size()); + // Only one credential for the signon realm is left. + PasswordForm blacklisted_form; + blacklisted_form.blacklisted_by_user = true; + blacklisted_form.scheme = PasswordForm::SCHEME_HTML; + blacklisted_form.signon_realm = GURL(kTestURL).GetOrigin().spec(); + blacklisted_form.origin = GURL(kTestURL).GetOrigin(); + blacklisted_form.date_created = kTestCreationDate; + EXPECT_THAT(stored_passwords.begin()->second, ElementsAre(blacklisted_form)); +} + +} // namespace password_manager
diff --git a/components/password_manager/core/browser/credential_manager_impl_unittest.cc b/components/password_manager/core/browser/credential_manager_impl_unittest.cc index a1ccd31e..8e9b331 100644 --- a/components/password_manager/core/browser/credential_manager_impl_unittest.cc +++ b/components/password_manager/core/browser/credential_manager_impl_unittest.cc
@@ -1548,7 +1548,6 @@ blacklisted.blacklisted_by_user = true; blacklisted.origin = form_.origin; blacklisted.signon_realm = form_.signon_realm; - blacklisted.type = autofill::PasswordForm::TYPE_API; blacklisted.date_created = passwords[form_.signon_realm][0].date_created; EXPECT_THAT(passwords[form_.signon_realm], testing::ElementsAre(blacklisted)); } @@ -1577,7 +1576,6 @@ blacklisted.blacklisted_by_user = true; blacklisted.origin = form_.origin; blacklisted.signon_realm = blacklisted.origin.spec(); - blacklisted.type = autofill::PasswordForm::TYPE_API; blacklisted.date_created = passwords[blacklisted.signon_realm][0].date_created; EXPECT_THAT(passwords[blacklisted.signon_realm],
diff --git a/components/password_manager/core/browser/form_saver_impl.cc b/components/password_manager/core/browser/form_saver_impl.cc index d00c1ea..e879aed 100644 --- a/components/password_manager/core/browser/form_saver_impl.cc +++ b/components/password_manager/core/browser/form_saver_impl.cc
@@ -10,6 +10,7 @@ #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" +#include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/browser/password_store.h" #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/gaia_urls.h" @@ -50,16 +51,9 @@ FormSaverImpl::~FormSaverImpl() = default; void FormSaverImpl::PermanentlyBlacklist(PasswordForm* observed) { - observed->preferred = false; - observed->blacklisted_by_user = true; - observed->username_value.clear(); - observed->username_element.clear(); - observed->password_value.clear(); - observed->password_element.clear(); - observed->other_possible_usernames.clear(); + *observed = password_manager_util::MakeNormalizedBlacklistedForm( + PasswordStore::FormDigest(*observed)); observed->date_created = base::Time::Now(); - observed->origin = observed->origin.GetOrigin(); - store_->AddLogin(*observed); }
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index a77b739..14c6a46 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -353,6 +353,8 @@ // static void PasswordManager::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterBooleanPref(prefs::kBlacklistedCredentialsNormalized, + false); registry->RegisterBooleanPref( prefs::kCredentialsEnableService, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
diff --git a/components/password_manager/core/browser/password_manager_util.cc b/components/password_manager/core/browser/password_manager_util.cc index db8c51d2..82907a0c 100644 --- a/components/password_manager/core/browser/password_manager_util.cc +++ b/components/password_manager/core/browser/password_manager_util.cc
@@ -17,6 +17,8 @@ #include "components/autofill/core/browser/popup_item_ids.h" #include "components/autofill/core/common/password_form.h" #include "components/autofill/core/common/password_generation_util.h" +#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h" +#include "components/password_manager/core/browser/blacklisted_credentials_cleaner.h" #include "components/password_manager/core/browser/credentials_cleaner.h" #include "components/password_manager/core/browser/credentials_cleaner_runner.h" #include "components/password_manager/core/browser/http_credentials_cleaner.h" @@ -188,6 +190,10 @@ } #endif // !defined(OS_IOS) + cleaning_tasks_runner->MaybeAddCleaningTask( + std::make_unique<password_manager::BlacklistedCredentialsCleaner>(store, + prefs)); + if (cleaning_tasks_runner->HasPendingTasks()) { // The runner will delete itself once the clearing tasks are done, thus we // are releasing ownership here. @@ -294,4 +300,26 @@ return credentials.empty() ? nullptr : credentials.begin()->second; } +autofill::PasswordForm MakeNormalizedBlacklistedForm( + password_manager::PasswordStore::FormDigest digest) { + autofill::PasswordForm result; + result.blacklisted_by_user = true; + result.scheme = std::move(digest.scheme); + result.signon_realm = std::move(digest.signon_realm); + // In case |digest| corresponds to an Android credential copy the origin as + // is, otherwise clear out the path by calling GetOrigin(). + if (password_manager::FacetURI::FromPotentiallyInvalidSpec( + digest.origin.spec()) + .IsValidAndroidFacetURI()) { + result.origin = std::move(digest.origin); + } else { + // GetOrigin() will return an empty GURL if the origin is not valid or + // standard. DCHECK that this will not happen. + DCHECK(digest.origin.is_valid()); + DCHECK(digest.origin.IsStandard()); + result.origin = digest.origin.GetOrigin(); + } + return result; +} + } // namespace password_manager_util
diff --git a/components/password_manager/core/browser/password_manager_util.h b/components/password_manager/core/browser/password_manager_util.h index 9f4331e..6e90fd05 100644 --- a/components/password_manager/core/browser/password_manager_util.h +++ b/components/password_manager/core/browser/password_manager_util.h
@@ -12,6 +12,7 @@ #include "base/callback.h" #include "base/strings/string16.h" #include "components/password_manager/core/browser/password_manager_client.h" +#include "components/password_manager/core/browser/password_store.h" #include "ui/gfx/native_widget_types.h" namespace autofill { @@ -27,7 +28,6 @@ namespace password_manager { class PasswordManagerDriver; class PasswordManagerClient; -class PasswordStore; } namespace syncer { @@ -137,6 +137,14 @@ const autofill::PasswordForm& submitted_form, const std::map<base::string16, const autofill::PasswordForm*>& credentials); +// This method creates a blacklisted form with |digests|'s scheme, signon_realm +// and origin. This is done to avoid storing PII and to have a normalized unique +// key. Furthermore it attempts to normalize the origin by stripping path +// components. In case this fails (e.g. for non-standard origins like Android +// credentials), the original origin is kept. +autofill::PasswordForm MakeNormalizedBlacklistedForm( + password_manager::PasswordStore::FormDigest digest); + } // namespace password_manager_util #endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_UTIL_H_
diff --git a/components/password_manager/core/browser/password_manager_util_unittest.cc b/components/password_manager/core/browser/password_manager_util_unittest.cc index 6280fa6..f67f80f1 100644 --- a/components/password_manager/core/browser/password_manager_util_unittest.cc +++ b/components/password_manager/core/browser/password_manager_util_unittest.cc
@@ -30,15 +30,18 @@ constexpr char kTestAndroidRealm[] = "android://hash@com.example.beta.android"; constexpr char kTestFederationURL[] = "https://google.com/"; +constexpr char kTestProxyOrigin[] = "http://proxy.com/"; +constexpr char kTestProxySignonRealm[] = "proxy.com/realm"; constexpr char kTestURL[] = "https://example.com/login/"; constexpr char kTestUsername[] = "Username"; constexpr char kTestUsername2[] = "Username2"; constexpr char kTestPassword[] = "12345"; -autofill::PasswordForm GetTestAndroidCredentials(const char* signon_realm) { +autofill::PasswordForm GetTestAndroidCredential() { autofill::PasswordForm form; form.scheme = autofill::PasswordForm::SCHEME_HTML; - form.signon_realm = signon_realm; + form.origin = GURL(kTestAndroidRealm); + form.signon_realm = kTestAndroidRealm; form.username_value = base::ASCIIToUTF16(kTestUsername); form.password_value = base::ASCIIToUTF16(kTestPassword); return form; @@ -54,6 +57,16 @@ return form; } +autofill::PasswordForm GetTestProxyCredential() { + autofill::PasswordForm form; + form.scheme = autofill::PasswordForm::SCHEME_BASIC; + form.origin = GURL(kTestProxyOrigin); + form.signon_realm = kTestProxySignonRealm; + form.username_value = base::ASCIIToUTF16(kTestUsername); + form.password_value = base::ASCIIToUTF16(kTestPassword); + return form; +} + std::map<base::string16, const autofill::PasswordForm*> MapFromCredentials( const std::vector<const autofill::PasswordForm*>& forms) { std::map<base::string16, const autofill::PasswordForm*> result; @@ -74,10 +87,10 @@ TEST(PasswordManagerUtil, TrimUsernameOnlyCredentials) { std::vector<std::unique_ptr<autofill::PasswordForm>> forms; std::vector<std::unique_ptr<autofill::PasswordForm>> expected_forms; - forms.push_back(std::make_unique<autofill::PasswordForm>( - GetTestAndroidCredentials(kTestAndroidRealm))); - expected_forms.push_back(std::make_unique<autofill::PasswordForm>( - GetTestAndroidCredentials(kTestAndroidRealm))); + forms.push_back( + std::make_unique<autofill::PasswordForm>(GetTestAndroidCredential())); + expected_forms.push_back( + std::make_unique<autofill::PasswordForm>(GetTestAndroidCredential())); autofill::PasswordForm username_only; username_only.scheme = autofill::PasswordForm::SCHEME_USERNAME_ONLY; @@ -353,4 +366,32 @@ parsed, MapFromCredentials({&stored3, &stored2, &stored1}))); } +TEST(PasswordManagerUtil, MakeNormalizedBlacklistedForm_Android) { + autofill::PasswordForm blacklisted_credential = MakeNormalizedBlacklistedForm( + password_manager::PasswordStore::FormDigest(GetTestAndroidCredential())); + EXPECT_TRUE(blacklisted_credential.blacklisted_by_user); + EXPECT_EQ(PasswordForm::SCHEME_HTML, blacklisted_credential.scheme); + EXPECT_EQ(kTestAndroidRealm, blacklisted_credential.signon_realm); + EXPECT_EQ(GURL(kTestAndroidRealm), blacklisted_credential.origin); +} + +TEST(PasswordManagerUtil, MakeNormalizedBlacklistedForm_Html) { + autofill::PasswordForm blacklisted_credential = MakeNormalizedBlacklistedForm( + password_manager::PasswordStore::FormDigest(GetTestCredential())); + EXPECT_TRUE(blacklisted_credential.blacklisted_by_user); + EXPECT_EQ(PasswordForm::SCHEME_HTML, blacklisted_credential.scheme); + EXPECT_EQ(GURL(kTestURL).GetOrigin().spec(), + blacklisted_credential.signon_realm); + EXPECT_EQ(GURL(kTestURL).GetOrigin(), blacklisted_credential.origin); +} + +TEST(PasswordManagerUtil, MakeNormalizedBlacklistedForm_Proxy) { + autofill::PasswordForm blacklisted_credential = MakeNormalizedBlacklistedForm( + password_manager::PasswordStore::FormDigest(GetTestProxyCredential())); + EXPECT_TRUE(blacklisted_credential.blacklisted_by_user); + EXPECT_EQ(PasswordForm::SCHEME_BASIC, blacklisted_credential.scheme); + EXPECT_EQ(kTestProxySignonRealm, blacklisted_credential.signon_realm); + EXPECT_EQ(GURL(kTestProxyOrigin), blacklisted_credential.origin); +} + } // namespace password_manager_util
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index 0a276b5..7f4e0a8 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -252,6 +252,11 @@ base::BindOnce(&PasswordStore::GetAutofillableLoginsImpl, this)); } +void PasswordStore::GetBlacklistLogins(PasswordStoreConsumer* consumer) { + PostLoginsTaskAndReplyToConsumerWithResult( + consumer, base::BindOnce(&PasswordStore::GetBlacklistLoginsImpl, this)); +} + void PasswordStore::GetAllLogins(PasswordStoreConsumer* consumer) { PostLoginsTaskAndReplyToConsumerWithResult( consumer, base::BindOnce(&PasswordStore::GetAllLoginsImpl, this)); @@ -794,6 +799,15 @@ return obtained_forms; } +std::vector<std::unique_ptr<PasswordForm>> +PasswordStore::GetBlacklistLoginsImpl() { + DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); + std::vector<std::unique_ptr<PasswordForm>> obtained_forms; + if (!FillBlacklistLogins(&obtained_forms)) + obtained_forms.clear(); + return obtained_forms; +} + std::vector<std::unique_ptr<PasswordForm>> PasswordStore::GetAllLoginsImpl() { DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); std::vector<std::unique_ptr<PasswordForm>> results;
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h index 92bbb85..bd1c28f 100644 --- a/components/password_manager/core/browser/password_store.h +++ b/components/password_manager/core/browser/password_store.h
@@ -189,6 +189,11 @@ // The request will be cancelled if the consumer is destroyed. virtual void GetAutofillableLogins(PasswordStoreConsumer* consumer); + // Gets the complete list of PasswordForms that are blacklist entries and + // notifies |consumer| on completion. The request will be cancelled if the + // consumer is destroyed. + virtual void GetBlacklistLogins(PasswordStoreConsumer* consumer); + // Gets the complete list of PasswordForms (regardless of their blacklist // status) and notify |consumer| on completion. The request will be cancelled // if the consumer is destroyed. @@ -554,6 +559,9 @@ std::vector<std::unique_ptr<autofill::PasswordForm>> GetAutofillableLoginsImpl(); + // Finds all blacklist PasswordForms and returns the result. + std::vector<std::unique_ptr<autofill::PasswordForm>> GetBlacklistLoginsImpl(); + // Finds all PasswordForms and returns the result. std::vector<std::unique_ptr<autofill::PasswordForm>> GetAllLoginsImpl();
diff --git a/components/password_manager/core/browser/test_password_store.cc b/components/password_manager/core/browser/test_password_store.cc index 5efa077..b73ec985 100644 --- a/components/password_manager/core/browser/test_password_store.cc +++ b/components/password_manager/core/browser/test_password_store.cc
@@ -50,8 +50,22 @@ PasswordStoreChangeList TestPasswordStore::AddLoginImpl( const autofill::PasswordForm& form) { PasswordStoreChangeList changes; - stored_passwords_[form.signon_realm].push_back(form); - changes.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form)); + auto& passwords_for_signon_realm = stored_passwords_[form.signon_realm]; + auto iter = std::find_if( + passwords_for_signon_realm.begin(), passwords_for_signon_realm.end(), + [&form](const auto& password) { + return ArePasswordFormUniqueKeyEqual(form, password); + }); + + if (iter != passwords_for_signon_realm.end()) { + changes.emplace_back(PasswordStoreChange::REMOVE, *iter); + changes.emplace_back(PasswordStoreChange::ADD, form); + *iter = form; + return changes; + } + + changes.emplace_back(PasswordStoreChange::ADD, form); + passwords_for_signon_realm.push_back(form); return changes; }
diff --git a/components/password_manager/core/common/password_manager_pref_names.cc b/components/password_manager/core/common/password_manager_pref_names.cc index 183f3d4..36fccca 100644 --- a/components/password_manager/core/common/password_manager_pref_names.cc +++ b/components/password_manager/core/common/password_manager_pref_names.cc
@@ -8,6 +8,9 @@ namespace password_manager { namespace prefs { +const char kBlacklistedCredentialsNormalized[] = + "profile.blacklisted_credentials_normalized"; + const char kCredentialsEnableAutosignin[] = "credentials_enable_autosignin"; const char kCredentialsEnableService[] = "credentials_enable_service";
diff --git a/components/password_manager/core/common/password_manager_pref_names.h b/components/password_manager/core/common/password_manager_pref_names.h index 87df51ce..0eb4a653 100644 --- a/components/password_manager/core/common/password_manager_pref_names.h +++ b/components/password_manager/core/common/password_manager_pref_names.h
@@ -13,6 +13,10 @@ // Alphabetical list of preference names specific to the PasswordManager // component. +// Boolean indicating whether blacklisted credentials in the password store +// have already been normalized. +extern const char kBlacklistedCredentialsNormalized[]; + // Boolean controlling whether the password manager allows automatic signing in // through Credential Manager API. extern const char kCredentialsEnableAutosignin[];
diff --git a/components/previews/content/previews_user_data.cc b/components/previews/content/previews_user_data.cc index 3e0951d8..98cb43b 100644 --- a/components/previews/content/previews_user_data.cc +++ b/components/previews/content/previews_user_data.cc
@@ -11,13 +11,15 @@ const void* const kPreviewsUserDataKey = &kPreviewsUserDataKey; PreviewsUserData::PreviewsUserData(uint64_t page_id) - : page_id_(page_id), server_lite_page_info_(nullptr) {} + : page_id_(page_id), + random_coin_flip_for_navigation_(base::RandInt(0, 1)), + server_lite_page_info_(nullptr) {} PreviewsUserData::~PreviewsUserData() {} PreviewsUserData::PreviewsUserData(const PreviewsUserData& other) : page_id_(other.page_id_), - random_coin_flip_for_navigation_(base::RandInt(0, 1)), + random_coin_flip_for_navigation_(other.random_coin_flip_for_navigation_), navigation_ect_(other.navigation_ect_), data_savings_inflation_percent_(other.data_savings_inflation_percent_), cache_control_no_transform_directive_(
diff --git a/components/previews/content/previews_user_data_unittest.cc b/components/previews/content/previews_user_data_unittest.cc index a4f486f..de9fe53 100644 --- a/components/previews/content/previews_user_data_unittest.cc +++ b/components/previews/content/previews_user_data_unittest.cc
@@ -43,6 +43,7 @@ PreviewsUserData data_copy(*data); EXPECT_EQ(id, data_copy.page_id()); + EXPECT_EQ(data->CoinFlipForNavigation(), data_copy.CoinFlipForNavigation()); EXPECT_EQ(123, data_copy.data_savings_inflation_percent()); EXPECT_TRUE(data_copy.cache_control_no_transform_directive()); EXPECT_EQ(previews::PreviewsType::NOSCRIPT,
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn index 032661653..ad72a3a 100644 --- a/components/viz/common/BUILD.gn +++ b/components/viz/common/BUILD.gn
@@ -249,6 +249,7 @@ "//gpu/command_buffer/client:raster", "//gpu/command_buffer/client:raster_interface", "//gpu/vulkan:buildflags", + "//mojo/public/cpp/base", "//mojo/public/cpp/system", "//third_party/libyuv", "//ui/gfx",
diff --git a/components/viz/common/DEPS b/components/viz/common/DEPS index e8cea65c..2e907073 100644 --- a/components/viz/common/DEPS +++ b/components/viz/common/DEPS
@@ -38,4 +38,8 @@ "features.cc" : [ "+gpu/config/gpu_finch_features.h", ], + "bitmap_allocation.cc" : [ + # Only used to pass Mojo handles, not to communicate with the viz service. + "+mojo/public/cpp/base/shared_memory_utils.h", + ], }
diff --git a/components/viz/common/resources/bitmap_allocation.cc b/components/viz/common/resources/bitmap_allocation.cc index d5ac586..ede0e1f3 100644 --- a/components/viz/common/resources/bitmap_allocation.cc +++ b/components/viz/common/resources/bitmap_allocation.cc
@@ -7,11 +7,12 @@ #include <stdint.h> #include "base/debug/alias.h" -#include "base/memory/shared_memory.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/process/memory.h" #include "build/build_config.h" #include "components/viz/common/resources/resource_format_utils.h" #include "components/viz/common/resources/resource_sizes.h" +#include "mojo/public/cpp/base/shared_memory_utils.h" #include "mojo/public/cpp/system/platform_handle.h" #include "ui/gfx/geometry/size.h" @@ -40,9 +41,8 @@ namespace bitmap_allocation { -std::unique_ptr<base::SharedMemory> AllocateMappedBitmap( - const gfx::Size& size, - ResourceFormat format) { +base::MappedReadOnlyRegion AllocateSharedBitmap(const gfx::Size& size, + ResourceFormat format) { DCHECK(IsBitmapFormatSupported(format)); size_t bytes = 0; if (!ResourceSizes::MaybeSizeInBytes(size, format, &bytes)) { @@ -50,62 +50,26 @@ CollectMemoryUsageAndDie(size, format, std::numeric_limits<int>::max()); } - auto mojo_buf = mojo::SharedBufferHandle::Create(bytes); - if (!mojo_buf->is_valid()) { + // NOTE: Need to use mojo::CreateReadOnlySharedMemoryRegion() instead of + // base::ReadOnlySharedMemoryRegion::Create() to ensure that this always work, + // even in sandboxed processes. + base::MappedReadOnlyRegion shm = + mojo::CreateReadOnlySharedMemoryRegion(bytes); + if (!shm.IsValid()) { DLOG(ERROR) << "Browser failed to allocate shared memory"; CollectMemoryUsageAndDie(size, format, bytes); } - - base::SharedMemoryHandle shared_buf; - if (mojo::UnwrapSharedMemoryHandle(std::move(mojo_buf), &shared_buf, nullptr, - nullptr) != MOJO_RESULT_OK) { - DLOG(ERROR) << "Browser failed to allocate shared memory"; - CollectMemoryUsageAndDie(size, format, bytes); - } - - auto memory = std::make_unique<base::SharedMemory>(shared_buf, false); - if (!memory->Map(bytes)) { - DLOG(ERROR) << "Browser failed to map shared memory"; - CollectMemoryUsageAndDie(size, format, bytes); - } - - return memory; + return shm; } -mojo::ScopedSharedBufferHandle DuplicateAndCloseMappedBitmap( - base::SharedMemory* memory, - const gfx::Size& size, - ResourceFormat format) { - DCHECK(IsBitmapFormatSupported(format)); - base::SharedMemoryHandle dupe_handle = - base::SharedMemory::DuplicateHandle(memory->handle()); - if (!base::SharedMemory::IsHandleValid(dupe_handle)) { - DLOG(ERROR) << "Failed to duplicate shared memory handle for bitmap."; - CollectMemoryUsageAndDie(size, format, memory->requested_size()); - } - - memory->Close(); - - return mojo::WrapSharedMemoryHandle( - dupe_handle, memory->mapped_size(), - mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite); +mojo::ScopedSharedBufferHandle ToMojoHandle( + base::ReadOnlySharedMemoryRegion region) { + return mojo::WrapReadOnlySharedMemoryRegion(std::move(region)); } -mojo::ScopedSharedBufferHandle DuplicateWithoutClosingMappedBitmap( - const base::SharedMemory* memory, - const gfx::Size& size, - ResourceFormat format) { - DCHECK(IsBitmapFormatSupported(format)); - base::SharedMemoryHandle dupe_handle = - base::SharedMemory::DuplicateHandle(memory->handle()); - if (!base::SharedMemory::IsHandleValid(dupe_handle)) { - DLOG(ERROR) << "Failed to duplicate shared memory handle for bitmap."; - CollectMemoryUsageAndDie(size, format, memory->requested_size()); - } - - return mojo::WrapSharedMemoryHandle( - dupe_handle, memory->mapped_size(), - mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite); +base::ReadOnlySharedMemoryRegion FromMojoHandle( + mojo::ScopedSharedBufferHandle handle) { + return mojo::UnwrapReadOnlySharedMemoryRegion(std::move(handle)); } } // namespace bitmap_allocation
diff --git a/components/viz/common/resources/bitmap_allocation.h b/components/viz/common/resources/bitmap_allocation.h index aa8c176..8900a16 100644 --- a/components/viz/common/resources/bitmap_allocation.h +++ b/components/viz/common/resources/bitmap_allocation.h
@@ -7,14 +7,11 @@ #include <memory> +#include "base/memory/read_only_shared_memory_region.h" #include "components/viz/common/resources/resource_format.h" #include "components/viz/common/viz_common_export.h" #include "mojo/public/cpp/system/buffer.h" -namespace base { -class SharedMemory; -} - namespace gfx { class Size; } // namespace gfx @@ -23,36 +20,27 @@ namespace bitmap_allocation { -// Allocates a shared memory segment to hold |size| pixels in RGBA_8888 -// format. Crashes if allocation does not succeed. The returned SharedMemory -// will be mapped. -VIZ_COMMON_EXPORT std::unique_ptr<base::SharedMemory> AllocateMappedBitmap( +// Allocates a read-only shared memory region and its writable mapping to hold +// |size| pixels in specific |format|. Crashes if allocation does not succeed. +VIZ_COMMON_EXPORT base::MappedReadOnlyRegion AllocateSharedBitmap( const gfx::Size& size, ResourceFormat format); -// For a bitmap created with AllocateMappedBitmap(), this will duplicate the -// handle to be passed to the display compositor, which can be in another -// process. The handle must be duplicated because we want to close the handle -// once it is mapped in this process. This will then close the original file -// handle in |memory| to free it up to the operating system. Some platforms -// have very limited namespaces for file handle counts and this avoids running -// out of them. Pass the same |size| as to AllocateMappedBitmap(), for -// debugging assistance. -VIZ_COMMON_EXPORT mojo::ScopedSharedBufferHandle DuplicateAndCloseMappedBitmap( - base::SharedMemory* memory, - const gfx::Size& size, - ResourceFormat format); +// Converts a base::ReadOnlySharedMemoryRegion to its corresponding +// Mojo scoped handle. This simply calls mojo::WrapReadOnlySharedMemoryRegion() +// but allows the caller to not include the corresponding header where it is +// defined. Moreover, it will be easy to grep for all uses of this method +// in the future when MojoHandles will not longer be necessary. +// TODO(crbug.com/951391): Remove once refactor is completed. +VIZ_COMMON_EXPORT mojo::ScopedSharedBufferHandle ToMojoHandle( + base::ReadOnlySharedMemoryRegion region); -// Similar to DuplicateAndCloseMappedBitmap(), but to be used in cases where the -// SharedMemory will have to be duplicated more than once. In that case the -// handle must be kept valid, so it can not be closed. Beware this will keep an -// open file handle on posix systems, which may contribute to surpassing handle -// limits. -VIZ_COMMON_EXPORT -mojo::ScopedSharedBufferHandle DuplicateWithoutClosingMappedBitmap( - const base::SharedMemory* memory, - const gfx::Size& size, - ResourceFormat format); +// Converts a scoped Mojo handle back to a base::ReadOnlySharedMemoryRegion +// This simply calls mojo::UnwrapReadOnlySharedMemoryRegion(), but has the same +// benefits as ToMojoHandle() described above. +// TODO(crbug.com/951391): Remove once refactor is completed. +VIZ_COMMON_EXPORT base::ReadOnlySharedMemoryRegion FromMojoHandle( + mojo::ScopedSharedBufferHandle handle); } // namespace bitmap_allocation
diff --git a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc index e991f18..46d1cba 100644 --- a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc +++ b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
@@ -94,8 +94,8 @@ FuzzedBitmap::FuzzedBitmap(SharedBitmapId id, gfx::Size size, - std::unique_ptr<base::SharedMemory> shared_memory) - : id(id), size(size), shared_memory(std::move(shared_memory)) {} + base::ReadOnlySharedMemoryRegion shared_region) + : id(id), size(size), shared_region(std::move(shared_region)) {} FuzzedBitmap::~FuzzedBitmap() = default; FuzzedBitmap::FuzzedBitmap(FuzzedBitmap&& other) noexcept = default; @@ -346,16 +346,16 @@ const gfx::Size& size, SkColor color) { SharedBitmapId shared_bitmap_id = SharedBitmap::GenerateId(); - std::unique_ptr<base::SharedMemory> shared_memory = - bitmap_allocation::AllocateMappedBitmap(size, RGBA_8888); + base::MappedReadOnlyRegion shm = + bitmap_allocation::AllocateSharedBitmap(size, RGBA_8888); SkBitmap bitmap; SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height()); - bitmap.installPixels(info, shared_memory->memory(), info.minRowBytes()); + bitmap.installPixels(info, shm.mapping.memory(), info.minRowBytes()); bitmap.eraseColor(color); data_.allocated_bitmaps.push_back( - {shared_bitmap_id, size, std::move(shared_memory)}); + {shared_bitmap_id, size, std::move(shm.region)}); return &data_.allocated_bitmaps.back(); }
diff --git a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h index 3d16f41..b029293 100644 --- a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h +++ b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h
@@ -8,7 +8,7 @@ #include <memory> #include <vector> -#include "base/memory/shared_memory.h" +#include "base/memory/read_only_shared_memory_region.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/resources/bitmap_allocation.h" #include "components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.pb.h" @@ -18,7 +18,7 @@ struct FuzzedBitmap { FuzzedBitmap(SharedBitmapId id, gfx::Size size, - std::unique_ptr<base::SharedMemory> shared_memory); + base::ReadOnlySharedMemoryRegion shared_region); ~FuzzedBitmap(); FuzzedBitmap(FuzzedBitmap&& other) noexcept; @@ -26,10 +26,7 @@ SharedBitmapId id; gfx::Size size; - - // TODO(kylechar): base::SharedMemory is deprecated, change to - // base::WritableSharedMemoryRegion. - std::unique_ptr<base::SharedMemory> shared_memory; + base::ReadOnlySharedMemoryRegion shared_region; DISALLOW_COPY(FuzzedBitmap); };
diff --git a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc index 8546b29..d084b0b4 100644 --- a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc +++ b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc
@@ -10,6 +10,7 @@ #include "base/run_loop.h" #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/surface_draw_quad.h" +#include "components/viz/common/resources/bitmap_allocation.h" #include "components/viz/common/surfaces/surface_range.h" namespace viz { @@ -57,11 +58,10 @@ sink_client.BindInterfacePtr()); for (auto& fuzzed_bitmap : allocated_bitmaps) { - mojo::ScopedSharedBufferHandle handle = - bitmap_allocation::DuplicateAndCloseMappedBitmap( - fuzzed_bitmap.shared_memory.get(), fuzzed_bitmap.size, - ResourceFormat::RGBA_8888); - sink_ptr->DidAllocateSharedBitmap(std::move(handle), fuzzed_bitmap.id); + sink_ptr->DidAllocateSharedBitmap( + bitmap_allocation::ToMojoHandle( + fuzzed_bitmap.shared_region.Duplicate()), + fuzzed_bitmap.id); } lsi_allocator_.GenerateId();
diff --git a/components/viz/service/display/display_resource_provider_unittest.cc b/components/viz/service/display/display_resource_provider_unittest.cc index 97c57a4ce..603d896 100644 --- a/components/viz/service/display/display_resource_provider_unittest.cc +++ b/components/viz/service/display/display_resource_provider_unittest.cc
@@ -18,8 +18,9 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/logging.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/memory/ref_counted.h" -#include "base/memory/shared_memory.h" +#include "base/memory/shared_memory_mapping.h" #include "build/build_config.h" #include "cc/test/render_pass_test_utils.h" #include "cc/test/resource_provider_test_utils.h" @@ -70,14 +71,13 @@ uint32_t value) { SharedBitmapId shared_bitmap_id = SharedBitmap::GenerateId(); - std::unique_ptr<base::SharedMemory> shm = - bitmap_allocation::AllocateMappedBitmap(size, RGBA_8888); + base::MappedReadOnlyRegion shm = + bitmap_allocation::AllocateSharedBitmap(size, RGBA_8888); manager->ChildAllocatedSharedBitmap( - bitmap_allocation::DuplicateAndCloseMappedBitmap(shm.get(), size, - RGBA_8888), - shared_bitmap_id); + bitmap_allocation::ToMojoHandle(std::move(shm.region)), shared_bitmap_id); - std::fill_n(static_cast<uint32_t*>(shm->memory()), size.GetArea(), value); + auto* memory = static_cast<uint32_t*>(shm.mapping.memory()); + std::fill_n(memory, size.GetArea(), value); return shared_bitmap_id; }
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc index 35b28738..715489e 100644 --- a/components/viz/service/display/renderer_pixeltest.cc +++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -4,12 +4,15 @@ #include <stddef.h> #include <stdint.h> +#include <algorithm> #include <memory> #include <tuple> #include "base/bind.h" #include "base/bind_helpers.h" #include "base/memory/aligned_memory.h" +#include "base/memory/read_only_shared_memory_region.h" +#include "base/memory/shared_memory_mapping.h" #include "build/build_config.h" #include "cc/base/math_util.h" #include "cc/paint/paint_flags.h" @@ -62,17 +65,15 @@ bitmap.computeByteSize()); } -std::unique_ptr<base::SharedMemory> AllocateAndRegisterSharedBitmapMemory( +base::WritableSharedMemoryMapping AllocateAndRegisterSharedBitmapMemory( const SharedBitmapId& id, const gfx::Size& size, SharedBitmapManager* shared_bitmap_manager) { - std::unique_ptr<base::SharedMemory> shm = - bitmap_allocation::AllocateMappedBitmap(size, RGBA_8888); + base::MappedReadOnlyRegion shm = + bitmap_allocation::AllocateSharedBitmap(size, RGBA_8888); shared_bitmap_manager->ChildAllocatedSharedBitmap( - bitmap_allocation::DuplicateAndCloseMappedBitmap(shm.get(), size, - RGBA_8888), - id); - return shm; + bitmap_allocation::ToMojoHandle(std::move(shm.region)), id); + return std::move(shm.mapping); } void DeleteSharedImage(scoped_refptr<ContextProvider> context_provider, @@ -247,7 +248,7 @@ RGBA_8888, gfx::ColorSpace(), MakePixelSpan(pixels)); } else { SharedBitmapId shared_bitmap_id = SharedBitmap::GenerateId(); - std::unique_ptr<base::SharedMemory> shm = + base::WritableSharedMemoryMapping mapping = AllocateAndRegisterSharedBitmapMemory(shared_bitmap_id, rect.size(), shared_bitmap_manager); resource = child_resource_provider->ImportResource( @@ -255,8 +256,8 @@ RGBA_8888), SingleReleaseCallback::Create(base::DoNothing())); - for (int i = 0; i < rect.size().GetArea(); ++i) - static_cast<uint32_t*>(shm->memory())[i] = pixels[i]; + auto span = mapping.GetMemoryAsSpan<uint32_t>(pixels.size()); + std::copy(pixels.begin(), pixels.end(), span.begin()); } // Return the mapped resource id. @@ -308,7 +309,7 @@ RGBA_8888, gfx::ColorSpace(), MakePixelSpan(pixels)); } else { SharedBitmapId shared_bitmap_id = SharedBitmap::GenerateId(); - std::unique_ptr<base::SharedMemory> shm = + base::WritableSharedMemoryMapping mapping = AllocateAndRegisterSharedBitmapMemory(shared_bitmap_id, rect.size(), shared_bitmap_manager); resource = child_resource_provider->ImportResource( @@ -316,8 +317,8 @@ RGBA_8888), SingleReleaseCallback::Create(base::DoNothing())); - for (int i = 0; i < rect.size().GetArea(); ++i) - static_cast<uint32_t*>(shm->memory())[i] = pixels[i]; + auto span = mapping.GetMemoryAsSpan<uint32_t>(pixels.size()); + std::copy(pixels.begin(), pixels.end(), span.begin()); } // Return the mapped resource id.
diff --git a/components/viz/service/display/software_renderer_unittest.cc b/components/viz/service/display/software_renderer_unittest.cc index 853ef75..ca867491 100644 --- a/components/viz/service/display/software_renderer_unittest.cc +++ b/components/viz/service/display/software_renderer_unittest.cc
@@ -8,7 +8,8 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/memory/shared_memory.h" +#include "base/memory/read_only_shared_memory_region.h" +#include "base/memory/shared_memory_mapping.h" #include "base/run_loop.h" #include "cc/test/animation_test_common.h" #include "cc/test/fake_output_surface_client.h" @@ -77,16 +78,15 @@ ResourceId AllocateAndFillSoftwareResource(const gfx::Size& size, const SkBitmap& source) { - std::unique_ptr<base::SharedMemory> shm = - bitmap_allocation::AllocateMappedBitmap(size, RGBA_8888); + base::MappedReadOnlyRegion shm = + bitmap_allocation::AllocateSharedBitmap(size, RGBA_8888); SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height()); - source.readPixels(info, shm->memory(), info.minRowBytes(), 0, 0); + source.readPixels(info, shm.mapping.memory(), info.minRowBytes(), 0, 0); // Registers the SharedBitmapId in the display compositor. SharedBitmapId shared_bitmap_id = SharedBitmap::GenerateId(); shared_bitmap_manager_->ChildAllocatedSharedBitmap( - bitmap_allocation::DuplicateAndCloseMappedBitmap(shm.get(), size, - RGBA_8888), + bitmap_allocation::ToMojoHandle(std::move(shm.region)), shared_bitmap_id); // Makes a resource id that refers to the registered SharedBitmapId.
diff --git a/components/viz/service/display_embedder/server_shared_bitmap_manager.cc b/components/viz/service/display_embedder/server_shared_bitmap_manager.cc index 66af729..f8d3070 100644 --- a/components/viz/service/display_embedder/server_shared_bitmap_manager.cc +++ b/components/viz/service/display_embedder/server_shared_bitmap_manager.cc
@@ -10,11 +10,14 @@ #include "base/lazy_instance.h" #include "base/macros.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/memory/ref_counted.h" +#include "base/memory/shared_memory_mapping.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/trace_event/process_memory_dump.h" +#include "components/viz/common/resources/bitmap_allocation.h" #include "components/viz/common/resources/resource_sizes.h" #include "mojo/public/cpp/system/platform_handle.h" #include "ui/gfx/geometry/size.h" @@ -23,13 +26,18 @@ class BitmapData : public base::RefCounted<BitmapData> { public: - explicit BitmapData(size_t buffer_size) : buffer_size(buffer_size) {} - std::unique_ptr<base::SharedMemory> memory; - size_t buffer_size; + explicit BitmapData(base::ReadOnlySharedMemoryMapping mapping) + : mapping_(std::move(mapping)) {} + + size_t size() const { return mapping_.size(); } + const base::UnguessableToken& mapped_id() const { return mapping_.guid(); } + const void* memory() const { return mapping_.memory(); } private: friend class base::RefCounted<BitmapData>; ~BitmapData() {} + + base::ReadOnlySharedMemoryMapping mapping_; DISALLOW_COPY_AND_ASSIGN(BitmapData); }; @@ -40,8 +48,12 @@ // alive. class ServerSharedBitmap : public SharedBitmap { public: + // NOTE: bitmap_data->memory() is read-only but SharedBitmap expects a + // uint8_t* pointer, even though all instances returned by a + // SharedBitmapManager will be used read-only. explicit ServerSharedBitmap(scoped_refptr<BitmapData> bitmap_data) - : SharedBitmap(static_cast<uint8_t*>(bitmap_data->memory->memory())), + : SharedBitmap( + static_cast<uint8_t*>(const_cast<void*>(bitmap_data->memory()))), bitmap_data_(std::move(bitmap_data)) {} ~ServerSharedBitmap() override { @@ -74,10 +86,10 @@ size_t bitmap_size; if (!ResourceSizes::MaybeSizeInBytes(size, format, &bitmap_size) || - bitmap_size > data->buffer_size) + bitmap_size > data->size()) return nullptr; - if (!data->memory->memory()) { + if (!data->memory()) { return nullptr; } @@ -91,7 +103,7 @@ if (it == handle_map_.end()) return {}; BitmapData* data = it->second.get(); - return data->memory->mapped_id(); + return data->mapped_id(); } bool ServerSharedBitmapManager::ChildAllocatedSharedBitmap( @@ -103,25 +115,21 @@ if (base::ContainsKey(handle_map_, id)) return false; - base::SharedMemoryHandle memory_handle; - size_t buffer_size; - MojoResult result = mojo::UnwrapSharedMemoryHandle( - std::move(buffer), &memory_handle, &buffer_size, nullptr); + base::ReadOnlySharedMemoryRegion region = + bitmap_allocation::FromMojoHandle(std::move(buffer)); // This function handles public API requests, so verify we unwrapped a shared // memory handle before trying to use the handle. - if (result != MOJO_RESULT_OK) + if (!region.IsValid()) return false; - auto data = base::MakeRefCounted<BitmapData>(buffer_size); - data->memory = std::make_unique<base::SharedMemory>(memory_handle, false); - // Map the memory to get a pointer to it, then close it to free up the fd so - // it can be reused. This doesn't unmap the memory. Some OS have a very - // limited number of fds and this avoids consuming them all. - data->memory->Map(data->buffer_size); - data->memory->Close(); + base::ReadOnlySharedMemoryMapping mapping = region.Map(); + if (!mapping.IsValid()) + return false; - handle_map_[id] = std::move(data); + handle_map_[id] = base::MakeRefCounted<BitmapData>(std::move(mapping)); + + // Note: |region| will be destroyed at scope exit, releasing the fd. return true; } @@ -149,11 +157,11 @@ dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, base::trace_event::MemoryAllocatorDump::kUnitsBytes, - data->buffer_size); + data->size()); // This GUID is the same returned by GetSharedBitmapTracingGUIDFromId() so // other components use a consistent GUID for a given SharedBitmapId. - base::UnguessableToken shared_memory_guid = data->memory->mapped_id(); + base::UnguessableToken shared_memory_guid = data->mapped_id(); DCHECK(!shared_memory_guid.is_empty()); pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid, 0 /* importance*/);
diff --git a/components/viz/service/display_embedder/server_shared_bitmap_manager.h b/components/viz/service/display_embedder/server_shared_bitmap_manager.h index 21a699ff..fc9b8733 100644 --- a/components/viz/service/display_embedder/server_shared_bitmap_manager.h +++ b/components/viz/service/display_embedder/server_shared_bitmap_manager.h
@@ -10,8 +10,8 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" -#include "base/memory/shared_memory.h" #include "base/trace_event/memory_dump_provider.h" +#include "base/unguessable_token.h" #include "components/viz/common/resources/resource_format_utils.h" #include "components/viz/service/display/shared_bitmap_manager.h" #include "components/viz/service/viz_service_export.h"
diff --git a/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc b/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc index 7afe388..f730e3f 100644 --- a/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc +++ b/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc
@@ -4,6 +4,8 @@ #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" +#include "base/containers/span.h" +#include "components/viz/common/resources/bitmap_allocation.h" #include "components/viz/common/resources/resource_sizes.h" #include "mojo/public/cpp/system/platform_handle.h" #include "testing/gtest/include/gtest/gtest.h" @@ -27,19 +29,15 @@ TEST_F(ServerSharedBitmapManagerTest, TestCreate) { gfx::Size bitmap_size(1, 1); - size_t size_in_bytes; - EXPECT_TRUE( - ResourceSizes::MaybeSizeInBytes(bitmap_size, RGBA_8888, &size_in_bytes)); - std::unique_ptr<base::SharedMemory> bitmap(new base::SharedMemory()); - bitmap->CreateAndMapAnonymous(size_in_bytes); - memset(bitmap->memory(), 0xff, size_in_bytes); - SharedBitmapId id = SharedBitmap::GenerateId(); + base::MappedReadOnlyRegion shm = + bitmap_allocation::AllocateSharedBitmap(bitmap_size, RGBA_8888); + EXPECT_TRUE(shm.IsValid()); + base::span<uint8_t> span = shm.mapping.GetMemoryAsSpan<uint8_t>(); + std::fill(span.begin(), span.end(), 0xff); - base::SharedMemoryHandle handle = bitmap->handle().Duplicate(); - mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle( - handle, size_in_bytes, - mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite); - manager()->ChildAllocatedSharedBitmap(std::move(buffer_handle), id); + SharedBitmapId id = SharedBitmap::GenerateId(); + manager()->ChildAllocatedSharedBitmap( + bitmap_allocation::ToMojoHandle(std::move(shm.region)), id); std::unique_ptr<SharedBitmap> large_bitmap; large_bitmap = @@ -65,7 +63,8 @@ std::unique_ptr<SharedBitmap> shared_bitmap; shared_bitmap = manager()->GetSharedBitmapFromId(bitmap_size, RGBA_8888, id); ASSERT_TRUE(shared_bitmap); - EXPECT_EQ(memcmp(shared_bitmap->pixels(), bitmap->memory(), 4), 0); + EXPECT_TRUE( + std::equal(span.begin(), span.begin() + 4, shared_bitmap->pixels())); std::unique_ptr<SharedBitmap> large_bitmap2; large_bitmap2 = @@ -76,70 +75,58 @@ shared_bitmap2 = manager()->GetSharedBitmapFromId(bitmap_size, RGBA_8888, id); EXPECT_TRUE(shared_bitmap2->pixels() == shared_bitmap->pixels()); shared_bitmap2.reset(); - EXPECT_EQ(memcmp(shared_bitmap->pixels(), bitmap->memory(), size_in_bytes), - 0); + EXPECT_TRUE(std::equal(span.begin(), span.end(), shared_bitmap->pixels())); manager()->ChildDeletedSharedBitmap(id); - memset(bitmap->memory(), 0, size_in_bytes); + std::fill(span.begin(), span.end(), 0); - EXPECT_EQ(memcmp(shared_bitmap->pixels(), bitmap->memory(), size_in_bytes), - 0); - bitmap.reset(); + EXPECT_TRUE(std::equal(span.begin(), span.end(), shared_bitmap->pixels())); shared_bitmap.reset(); } TEST_F(ServerSharedBitmapManagerTest, AddDuplicate) { gfx::Size bitmap_size(1, 1); - size_t size_in_bytes; - EXPECT_TRUE( - ResourceSizes::MaybeSizeInBytes(bitmap_size, RGBA_8888, &size_in_bytes)); - std::unique_ptr<base::SharedMemory> bitmap(new base::SharedMemory()); - bitmap->CreateAndMapAnonymous(size_in_bytes); - memset(bitmap->memory(), 0xff, size_in_bytes); + base::MappedReadOnlyRegion shm = + bitmap_allocation::AllocateSharedBitmap(bitmap_size, RGBA_8888); + EXPECT_TRUE(shm.IsValid()); + base::span<uint8_t> span = shm.mapping.GetMemoryAsSpan<uint8_t>(); + std::fill(span.begin(), span.end(), 0xff); SharedBitmapId id = SharedBitmap::GenerateId(); - base::SharedMemoryHandle handle = bitmap->handle().Duplicate(); - mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle( - handle, size_in_bytes, - mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite); - manager()->ChildAllocatedSharedBitmap(std::move(buffer_handle), id); + // NOTE: Duplicate the mapping to compare its content later. + manager()->ChildAllocatedSharedBitmap( + bitmap_allocation::ToMojoHandle(std::move(shm.region)), id); - std::unique_ptr<base::SharedMemory> bitmap2(new base::SharedMemory()); - bitmap2->CreateAndMapAnonymous(size_in_bytes); - memset(bitmap2->memory(), 0x00, size_in_bytes); + base::MappedReadOnlyRegion shm2 = + bitmap_allocation::AllocateSharedBitmap(bitmap_size, RGBA_8888); + EXPECT_TRUE(shm2.IsValid()); + base::span<uint8_t> span2 = shm.mapping.GetMemoryAsSpan<uint8_t>(); + std::fill(span2.begin(), span2.end(), 0x00); - base::SharedMemoryHandle handle2 = bitmap->handle().Duplicate(); - buffer_handle = mojo::WrapSharedMemoryHandle( - handle2, size_in_bytes, - mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite); - manager()->ChildAllocatedSharedBitmap(std::move(buffer_handle), id); + manager()->ChildAllocatedSharedBitmap( + bitmap_allocation::ToMojoHandle(std::move(shm2.region)), id); std::unique_ptr<SharedBitmap> shared_bitmap; shared_bitmap = manager()->GetSharedBitmapFromId(bitmap_size, RGBA_8888, id); ASSERT_TRUE(shared_bitmap); - EXPECT_EQ(memcmp(shared_bitmap->pixels(), bitmap->memory(), size_in_bytes), - 0); + EXPECT_TRUE(std::equal(span.begin(), span.end(), shared_bitmap->pixels())); manager()->ChildDeletedSharedBitmap(id); } TEST_F(ServerSharedBitmapManagerTest, SharedMemoryHandle) { gfx::Size bitmap_size(1, 1); - size_t size_in_bytes; - EXPECT_TRUE( - ResourceSizes::MaybeSizeInBytes(bitmap_size, RGBA_8888, &size_in_bytes)); - std::unique_ptr<base::SharedMemory> bitmap(new base::SharedMemory()); - bitmap->CreateAndMapAnonymous(size_in_bytes); - memset(bitmap->memory(), 0xff, size_in_bytes); - base::UnguessableToken shared_memory_guid = bitmap->handle().GetGUID(); + base::MappedReadOnlyRegion shm = + bitmap_allocation::AllocateSharedBitmap(bitmap_size, RGBA_8888); + EXPECT_TRUE(shm.IsValid()); + base::span<uint8_t> span = shm.mapping.GetMemoryAsSpan<uint8_t>(); + std::fill(span.begin(), span.end(), 0xff); + base::UnguessableToken shared_memory_guid = shm.mapping.guid(); EXPECT_FALSE(shared_memory_guid.is_empty()); SharedBitmapId id = SharedBitmap::GenerateId(); - base::SharedMemoryHandle handle = bitmap->handle().Duplicate(); - mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle( - handle, size_in_bytes, - mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite); - manager()->ChildAllocatedSharedBitmap(std::move(buffer_handle), id); + manager()->ChildAllocatedSharedBitmap( + bitmap_allocation::ToMojoHandle(std::move(shm.region)), id); base::UnguessableToken tracing_guid = manager()->GetSharedBitmapTracingGUIDFromId(id);
diff --git a/components/viz/test/test_shared_bitmap_manager.cc b/components/viz/test/test_shared_bitmap_manager.cc index a173281..7111dd9 100644 --- a/components/viz/test/test_shared_bitmap_manager.cc +++ b/components/viz/test/test_shared_bitmap_manager.cc
@@ -6,7 +6,8 @@ #include <stdint.h> -#include "base/memory/shared_memory.h" +#include "base/memory/read_only_shared_memory_region.h" +#include "components/viz/common/resources/bitmap_allocation.h" #include "components/viz/common/resources/resource_format_utils.h" #include "mojo/public/cpp/system/platform_handle.h" @@ -24,18 +25,23 @@ const SharedBitmapId& id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (bitmap_map_.find(id) == bitmap_map_.end()) + const auto it = mapping_map_.find(id); + if (it == mapping_map_.end()) return nullptr; - uint8_t* pixels = static_cast<uint8_t*>(bitmap_map_[id]->memory()); + // NOTE: pixels needs to be writable for legacy reasons, but SharedBitmap + // instances returned by a SharedBitmapManager are always read-only. + uint8_t* pixels = + static_cast<uint8_t*>(const_cast<void*>(it->second.memory())); return std::make_unique<SharedBitmap>(pixels); } base::UnguessableToken TestSharedBitmapManager::GetSharedBitmapTracingGUIDFromId( const SharedBitmapId& id) { - if (bitmap_map_.find(id) == bitmap_map_.end()) + const auto it = mapping_map_.find(id); + if (it == mapping_map_.end()) return {}; - return bitmap_map_[id]->mapped_id(); + return it->second.guid(); } bool TestSharedBitmapManager::ChildAllocatedSharedBitmap( @@ -46,19 +52,13 @@ // TestSharedBitmapManager is both the client and service side. So the // notification here should be about a bitmap that was previously allocated // with AllocateSharedBitmap(). - if (bitmap_map_.find(id) == bitmap_map_.end()) { - base::SharedMemoryHandle memory_handle; - size_t buffer_size; - MojoResult result = mojo::UnwrapSharedMemoryHandle( - std::move(buffer), &memory_handle, &buffer_size, nullptr); - DCHECK_EQ(result, MOJO_RESULT_OK); - auto memory = std::make_unique<base::SharedMemory>(memory_handle, false); - bool mapped = memory->Map(buffer_size); - DCHECK(mapped); - memory->Close(); - - bitmap_map_.emplace(id, memory.get()); - owned_map_.emplace(id, std::move(memory)); + if (mapping_map_.find(id) == mapping_map_.end()) { + base::ReadOnlySharedMemoryRegion region = + bitmap_allocation::FromMojoHandle(std::move(buffer)); + DCHECK(region.IsValid()); + base::ReadOnlySharedMemoryMapping mapping = region.Map(); + DCHECK(mapping.IsValid()); + mapping_map_.emplace(id, std::move(mapping)); } // The same bitmap id should not be notified more than once. @@ -72,8 +72,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); notified_set_.erase(id); - bitmap_map_.erase(id); - owned_map_.erase(id); + mapping_map_.erase(id); } } // namespace viz
diff --git a/components/viz/test/test_shared_bitmap_manager.h b/components/viz/test/test_shared_bitmap_manager.h index e46da32f..cacc75d 100644 --- a/components/viz/test/test_shared_bitmap_manager.h +++ b/components/viz/test/test_shared_bitmap_manager.h
@@ -8,13 +8,10 @@ #include <map> #include <set> +#include "base/memory/shared_memory_mapping.h" #include "base/sequence_checker.h" #include "components/viz/service/display/shared_bitmap_manager.h" -namespace base { -class SharedMemory; -} // namespace base - namespace viz { class TestSharedBitmapManager : public SharedBitmapManager { @@ -36,8 +33,7 @@ private: SEQUENCE_CHECKER(sequence_checker_); - std::map<SharedBitmapId, base::SharedMemory*> bitmap_map_; - std::map<SharedBitmapId, std::unique_ptr<base::SharedMemory>> owned_map_; + std::map<SharedBitmapId, base::ReadOnlySharedMemoryMapping> mapping_map_; std::set<SharedBitmapId> notified_set_; };
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc index 04e2c388..8a2ae78 100644 --- a/content/browser/download/download_browsertest.cc +++ b/content/browser/download/download_browsertest.cc
@@ -3799,7 +3799,7 @@ // Verify WebUI download will success with an associated renderer process. IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadFromWebUI) { - GURL webui_url("chrome://resources/images/apps/blue_button.png"); + GURL webui_url(GetWebUIURL("resources/images/apps/blue_button.png")); NavigateToURL(shell(), webui_url); SetupEnsureNoPendingDownloads();
diff --git a/content/browser/fileapi/file_system_manager_impl.cc b/content/browser/fileapi/file_system_manager_impl.cc index 59e6f8f..3c9125c 100644 --- a/content/browser/fileapi/file_system_manager_impl.cc +++ b/content/browser/fileapi/file_system_manager_impl.cc
@@ -124,17 +124,17 @@ FileSystemManagerImpl::FileSystemManagerImpl( int process_id, int frame_id, - storage::FileSystemContext* file_system_context, + scoped_refptr<storage::FileSystemContext> file_system_context, scoped_refptr<ChromeBlobStorageContext> blob_storage_context) : process_id_(process_id), frame_id_(frame_id), - context_(file_system_context), + context_(std::move(file_system_context)), security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()), - blob_storage_context_(blob_storage_context), + blob_storage_context_(std::move(blob_storage_context)), weak_factory_(this) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(context_); - DCHECK(blob_storage_context); + DCHECK(blob_storage_context_); bindings_.set_connection_error_handler(base::BindRepeating( &FileSystemManagerImpl::OnConnectionError, base::Unretained(this))); } @@ -566,8 +566,7 @@ context_->default_file_task_runner()->PostTask( FROM_HERE, base::BindOnce(&FileSystemManagerImpl::GetPlatformPathOnFileThread, path, - process_id_, base::Unretained(context_), GetWeakPtr(), - std::move(callback))); + process_id_, context_, GetWeakPtr(), std::move(callback))); } void FileSystemManagerImpl::CreateWriter(const GURL& file_path, @@ -831,13 +830,13 @@ void FileSystemManagerImpl::GetPlatformPathOnFileThread( const GURL& path, int process_id, - storage::FileSystemContext* context, + scoped_refptr<storage::FileSystemContext> context, base::WeakPtr<FileSystemManagerImpl> file_system_manager, GetPlatformPathCallback callback) { DCHECK(context->default_file_task_runner()->RunsTasksInCurrentSequence()); SyncGetPlatformPath( - context, process_id, path, + context.get(), process_id, path, base::BindOnce( [](base::WeakPtr<FileSystemManagerImpl> file_system_manager, GetPlatformPathCallback callback, @@ -854,7 +853,7 @@ base::Optional<base::File::Error> FileSystemManagerImpl::ValidateFileSystemURL( const storage::FileSystemURL& url) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!FileSystemURLIsValid(context_, url)) + if (!FileSystemURLIsValid(context_.get(), url)) return base::File::FILE_ERROR_INVALID_URL; // Deny access to files in PluginPrivate FileSystem from JavaScript.
diff --git a/content/browser/fileapi/file_system_manager_impl.h b/content/browser/fileapi/file_system_manager_impl.h index 12b7cf8..5055e50 100644 --- a/content/browser/fileapi/file_system_manager_impl.h +++ b/content/browser/fileapi/file_system_manager_impl.h
@@ -63,7 +63,7 @@ FileSystemManagerImpl( int process_id, int frame_id, - storage::FileSystemContext* file_system_context, + scoped_refptr<storage::FileSystemContext> file_system_context, scoped_refptr<ChromeBlobStorageContext> blob_storage_context); ~FileSystemManagerImpl() override; base::WeakPtr<FileSystemManagerImpl> GetWeakPtr(); @@ -193,7 +193,7 @@ static void GetPlatformPathOnFileThread( const GURL& path, int process_id, - storage::FileSystemContext* context, + scoped_refptr<storage::FileSystemContext> context, base::WeakPtr<FileSystemManagerImpl> file_system_manager, GetPlatformPathCallback callback); // Returns an error if |url| is invalid. @@ -213,7 +213,7 @@ const int process_id_; const int frame_id_; - storage::FileSystemContext* const context_; + const scoped_refptr<storage::FileSystemContext> context_; ChildProcessSecurityPolicyImpl* const security_policy_; const scoped_refptr<ChromeBlobStorageContext> blob_storage_context_; std::unique_ptr<storage::FileSystemOperationRunner> operation_runner_;
diff --git a/content/browser/frame_host/navigation_handle_impl_browsertest.cc b/content/browser/frame_host/navigation_handle_impl_browsertest.cc index 01971ad..26a3c591 100644 --- a/content/browser/frame_host/navigation_handle_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -1924,7 +1924,7 @@ // the privileged process. IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, BlockedRequestAfterWebUI) { - GURL web_ui_url("chrome://gpu"); + GURL web_ui_url(GetWebUIURL("gpu")); WebContents* web_contents = shell()->web_contents(); // Navigate to the initial page.
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc index 93ce013e7..abd8192 100644 --- a/content/browser/navigation_browsertest.cc +++ b/content/browser/navigation_browsertest.cc
@@ -1770,7 +1770,7 @@ notification_registrar.Add(&crash_observer, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, content::NotificationService::AllSources()); - NavigateToURLBlockUntilNavigationsComplete(web_contents, GURL("chrome:crash"), + NavigateToURLBlockUntilNavigationsComplete(web_contents, GetWebUIURL("crash"), 1); // Wait for navigation in new WebContents to finish.
diff --git a/content/browser/network_service_browsertest.cc b/content/browser/network_service_browsertest.cc index 0789ba39..190b319 100644 --- a/content/browser/network_service_browsertest.cc +++ b/content/browser/network_service_browsertest.cc
@@ -214,7 +214,7 @@ // Verifies that WebUI pages with WebUI bindings can't make network requests. IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest, WebUIBindingsNoHttp) { - GURL test_url("chrome://webui/"); + GURL test_url(GetWebUIURL("webui/")); NavigateToURL(shell(), test_url); RenderProcessKilledObserver killed_observer(shell()->web_contents()); ASSERT_FALSE(CheckCanLoadHttp()); @@ -224,7 +224,7 @@ // Verifies that WebUI pages without WebUI bindings can make network requests. IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest, NoWebUIBindingsHttp) { - GURL test_url("chrome://webui/nobinding/"); + GURL test_url(GetWebUIURL("webui/nobinding/")); NavigateToURL(shell(), test_url); ASSERT_TRUE(CheckCanLoadHttp()); } @@ -233,7 +233,7 @@ // ChildProcessSecurityPolicyImpl::CanRequestURL is properly rejected. IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest, FileSystemBindingsCorrectOrigin) { - GURL test_url("chrome://webui/nobinding/"); + GURL test_url(GetWebUIURL("webui/nobinding/")); NavigateToURL(shell(), test_url); // Note: must be filesystem scheme (obviously).
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index db59da8..9b35d7f 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -5088,7 +5088,8 @@ EXPECT_EQ(popup_url, popup->web_contents()->GetLastCommittedURL()); EXPECT_TRUE( base::MatchPattern(console_delegate.message(), - "Not allowed to load local resource: chrome:*")); + std::string("Not allowed to load local resource: ") + + kChromeUIScheme + ":*")); } // Verify that named frames are discoverable from their opener's ancestors.
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index b4b07f5..84ca6c56 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -552,7 +552,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, AppendingFrameInWebUIDoesNotCrash) { - const GURL kWebUIUrl("chrome://tracing"); + const GURL kWebUIUrl(GetWebUIURL("tracing")); const char kJSCodeForAppendingFrame[] = "document.body.appendChild(document.createElement('iframe'));"; @@ -873,7 +873,7 @@ // Kill the renderer process so when the navigate again, it will be a fresh // renderer with an empty in-memory cache. - NavigateToURL(shell(), GURL("chrome:crash")); + NavigateToURL(shell(), GetWebUIURL("crash")); // Reload that URL, the subresource should be served from the network cache. before = base::TimeTicks::Now(); @@ -999,7 +999,7 @@ // valid and return if the script was cached or not. bool TestResourceLoad(const GURL& url, const GURL& sub_frame) { // Kill the renderer to clear the in-memory cache. - NavigateToURL(shell(), GURL("chrome:crash")); + NavigateToURL(shell(), GetWebUIURL("crash")); // Observe network requests. ResourceLoadObserver observer(shell()); @@ -1200,7 +1200,7 @@ observer.resource_load_infos()[1]->network_info->network_accessed); observer.Reset(); - NavigateToURL(shell(), GURL("chrome://gpu")); + NavigateToURL(shell(), GetWebUIURL("gpu")); ASSERT_LE(1U, observer.resource_load_infos().size()); for (const mojom::ResourceLoadInfoPtr& resource_load_info : observer.resource_load_infos()) { @@ -1679,8 +1679,7 @@ // Test that view source mode for a webui page can be opened. IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ViewSourceWebUI) { - const std::string kUrl = - "view-source:chrome://" + std::string(kChromeUIGpuHost); + const std::string kUrl = "view-source:" + GetWebUIURLString(kChromeUIGpuHost); const GURL kGURL(kUrl); NavigateToURL(shell(), kGURL); EXPECT_EQ(base::ASCIIToUTF16(kUrl), shell()->web_contents()->GetTitle());
diff --git a/content/browser/webui/web_ui_mojo_browsertest.cc b/content/browser/webui/web_ui_mojo_browsertest.cc index f94314b8..a900571 100644 --- a/content/browser/webui/web_ui_mojo_browsertest.cc +++ b/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -34,6 +34,7 @@ #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" +#include "content/public/test/test_utils.h" #include "content/shell/browser/shell.h" #include "content/test/data/web_ui_test_mojo_bindings.mojom.h" #include "mojo/public/cpp/bindings/binding.h" @@ -264,10 +265,8 @@ void NavigateWithNewWebUI(const std::string& path) { // Load a dummy WebUI URL first so that a new WebUI is set up when we load // the URL we're actually interested in. - EXPECT_TRUE(NavigateToURL(shell(), GURL("chrome://dummy-web-ui"))); - - constexpr char kChromeUIMojoWebUIOrigin[] = "chrome://mojo-web-ui/"; - EXPECT_TRUE(NavigateToURL(shell(), GURL(kChromeUIMojoWebUIOrigin + path))); + EXPECT_TRUE(NavigateToURL(shell(), GetWebUIURL("dummy-web-ui"))); + EXPECT_TRUE(NavigateToURL(shell(), GetWebUIURL("mojo-web-ui/" + path))); } // Run |script| and return a boolean result. @@ -308,7 +307,7 @@ g_got_message = false; base::RunLoop run_loop; factory()->set_run_loop(&run_loop); - GURL test_url("chrome://mojo-web-ui/web_ui_mojo.html?ping"); + GURL test_url(GetWebUIURL("mojo-web-ui/web_ui_mojo.html?ping")); NavigateToURL(shell(), test_url); // RunLoop is quit when message received from page. run_loop.Run();
diff --git a/content/renderer/pepper/pepper_graphics_2d_host.cc b/content/renderer/pepper/pepper_graphics_2d_host.cc index f75a138..c793140 100644 --- a/content/renderer/pepper/pepper_graphics_2d_host.cc +++ b/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/location.h" #include "base/logging.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/numerics/checked_math.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" @@ -741,15 +742,15 @@ } if (!shared_bitmap) { viz::SharedBitmapId id = viz::SharedBitmap::GenerateId(); - std::unique_ptr<base::SharedMemory> shm = - viz::bitmap_allocation::AllocateMappedBitmap(pixel_image_size, + base::MappedReadOnlyRegion shm = + viz::bitmap_allocation::AllocateSharedBitmap(pixel_image_size, viz::RGBA_8888); shared_bitmap = base::MakeRefCounted<cc::CrossThreadSharedBitmap>( id, std::move(shm), pixel_image_size, viz::RGBA_8888); registration = bitmap_registrar->RegisterSharedBitmapId(id, shared_bitmap); } void* src = image_data_->Map(); - memcpy(shared_bitmap->shared_memory()->memory(), src, + memcpy(shared_bitmap->memory(), src, viz::ResourceSizes::CheckedSizeInBytes<size_t>(pixel_image_size, viz::RGBA_8888)); image_data_->Unmap();
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 7b9c89c..19bcace 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -722,8 +722,7 @@ // Verify that form posts to WebUI URLs will be sent to the browser process. auto form_navigation_info = std::make_unique<blink::WebNavigationInfo>(); - form_navigation_info->url_request = - blink::WebURLRequest(GURL("chrome://foo")); + form_navigation_info->url_request = blink::WebURLRequest(GetWebUIURL("foo")); form_navigation_info->url_request.SetHttpMethod("POST"); form_navigation_info->url_request.SetRequestorOrigin(requestor_origin); form_navigation_info->frame_type = @@ -738,10 +737,9 @@ FrameHostMsg_OpenURL::ID)); // Verify that popup links to WebUI URLs also are sent to browser. - blink::WebURLRequest popup_request(GURL("chrome://foo")); + blink::WebURLRequest popup_request(GetWebUIURL("foo")); auto popup_navigation_info = std::make_unique<blink::WebNavigationInfo>(); - popup_navigation_info->url_request = - blink::WebURLRequest(GURL("chrome://foo")); + popup_navigation_info->url_request = blink::WebURLRequest(GetWebUIURL("foo")); popup_navigation_info->url_request.SetRequestorOrigin(requestor_origin); popup_navigation_info->frame_type = network::mojom::RequestContextFrameType::kAuxiliary; @@ -808,8 +806,7 @@ // Navigations to WebUI URLs will also be sent to browser process. auto webui_navigation_info = std::make_unique<blink::WebNavigationInfo>(); - webui_navigation_info->url_request = - blink::WebURLRequest(GURL("chrome://foo")); + webui_navigation_info->url_request = blink::WebURLRequest(GetWebUIURL("foo")); webui_navigation_info->url_request.SetRequestorOrigin(requestor_origin); webui_navigation_info->frame_type = network::mojom::RequestContextFrameType::kTopLevel;
diff --git a/content/shell/test_runner/test_plugin.cc b/content/shell/test_runner/test_plugin.cc index cc1f3d5..38bee7f 100644 --- a/content/shell/test_runner/test_plugin.cc +++ b/content/shell/test_runner/test_plugin.cc
@@ -12,7 +12,7 @@ #include "base/bind.h" #include "base/logging.h" #include "base/memory/ptr_util.h" -#include "base/memory/shared_memory.h" +#include "base/memory/unsafe_shared_memory_region.h" #include "base/no_destructor.h" #include "base/strings/stringprintf.h" #include "cc/layers/texture_layer.h" @@ -277,15 +277,15 @@ shared_bitmap_ = nullptr; } else { viz::SharedBitmapId id = viz::SharedBitmap::GenerateId(); - std::unique_ptr<base::SharedMemory> shm = - viz::bitmap_allocation::AllocateMappedBitmap(gfx::Rect(rect_).size(), + base::MappedReadOnlyRegion shm = + viz::bitmap_allocation::AllocateSharedBitmap(gfx::Rect(rect_).size(), viz::RGBA_8888); shared_bitmap_ = base::MakeRefCounted<cc::CrossThreadSharedBitmap>( id, std::move(shm), gfx::Rect(rect_).size(), viz::RGBA_8888); // The |shared_bitmap_|'s id will be registered when being given to the // compositor. - DrawSceneSoftware(shared_bitmap_->shared_memory()->memory()); + DrawSceneSoftware(shared_bitmap_->memory()); } content_changed_ = true;
diff --git a/content/test/content_browser_test_test.cc b/content/test/content_browser_test_test.cc index c40a840..372cb147 100644 --- a/content/test/content_browser_test_test.cc +++ b/content/test/content_browser_test_test.cc
@@ -52,7 +52,7 @@ shell()->web_contents()->GetMainFrame()->GetProcess(), content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); - NavigateToURL(shell(), GURL("chrome:crash")); + NavigateToURL(shell(), GetWebUIURL("crash")); renderer_shutdown_observer.Wait(); EXPECT_FALSE(renderer_shutdown_observer.did_exit_normally());
diff --git a/content/test/gpu/gpu_tests/power_measurement_integration_test.py b/content/test/gpu/gpu_tests/power_measurement_integration_test.py index 06eb6d0..483706a 100644 --- a/content/test/gpu/gpu_tests/power_measurement_integration_test.py +++ b/content/test/gpu/gpu_tests/power_measurement_integration_test.py
@@ -1,7 +1,6 @@ # Copyright 2018 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. - """This script only works on Windows with Intel CPU. Intel Power Gadget needs to be installed on the machine before this script works. The software can be downloaded from: @@ -39,17 +38,17 @@ _POWER_MEASUREMENT_DELAY = 20 # Measures power for [x] seconds and calculates the average as results. -_POWER_MEASUREMENT_DURATION = 30 +_POWER_MEASUREMENT_DURATION = 15 # Measures power in resolution of [x] milli-seconds. _POWER_MEASUREMENT_RESOLUTION = 100 _GPU_RELATIVE_PATH = "content/test/data/gpu/" -_DATA_PATHS = [os.path.join( - path_util.GetChromiumSrcDir(), _GPU_RELATIVE_PATH), - os.path.join( - path_util.GetChromiumSrcDir(), 'media', 'test', 'data')] +_DATA_PATHS = [ + os.path.join(path_util.GetChromiumSrcDir(), _GPU_RELATIVE_PATH), + os.path.join(path_util.GetChromiumSrcDir(), 'media', 'test', 'data') +] _VIDEO_TEST_SCRIPT = r""" var _video_in_fullscreen = false; @@ -203,6 +202,7 @@ } """ + class PowerMeasurementIntegrationTest(gpu_integration_test.GpuIntegrationTest): _url_mode = None @@ -214,47 +214,66 @@ @classmethod def AddCommandlineArgs(cls, parser): super(PowerMeasurementIntegrationTest, cls).AddCommandlineArgs(parser) - parser.add_option("--duration", default=_POWER_MEASUREMENT_DURATION, - type="int", - help="specify how many seconds Intel Power Gadget " - "measures. By default, %d seconds is selected." % - _POWER_MEASUREMENT_DURATION) - parser.add_option("--delay", default=_POWER_MEASUREMENT_DELAY, type="int", - help="specify how many seconds we skip in the data " - "Intel Power Gadget collects. This time is for starting " - "video play, switching to fullscreen mode, etc. " - "By default, %d seconds is selected." % - _POWER_MEASUREMENT_DELAY) - parser.add_option("--resolution", default=100, type="int", - help="specify how often Intel Power Gadget samples " - "data in milliseconds. By default, 100 ms is selected.") - parser.add_option("--url", - help="specify the webpage URL the browser launches with.") - parser.add_option("--fullscreen", action="store_true", default=False, - help="specify if the browser goes to fullscreen mode " - "automatically, specifically if there is a single video " - "element in the page, switch it to fullsrceen mode.") - parser.add_option("--underlay", action="store_true", default=False, - help="add a layer on top so the video layer becomes an " - "underlay.") - parser.add_option("--logdir", - help="Speficy where the Intel Power Gadget log file " - "should be stored. If specified, the log file name will " - "include a timestamp. If not specified, the log file " - "will be PowerLog.csv at the current dir and will be " - "overwritten at next run.") - parser.add_option("--repeat", default=1, type="int", - help="specify how many times to repreat the measurement. " - "By default, measure only once. If measure more than " - "once, between each measurement, browser restarts.") - parser.add_option("--outliers", default=0, type="int", - help="if a test is repeated multiples and outliers is " - "set to N, then N smallest results and N largest results " - "are discarded before computing mean and stdev.") - parser.add_option("--bypass-ipg", action="store_true", default=False, - help="Do not launch Intel Power Gadget. This is for " - "testing convenience on machines where Intel Power " - "Gadget does not work.") + parser.add_option( + "--duration", + default=_POWER_MEASUREMENT_DURATION, + type="int", + help="specify how many seconds Intel Power Gadget measures. By " + "default, %d seconds is selected." % _POWER_MEASUREMENT_DURATION) + parser.add_option( + "--delay", + default=_POWER_MEASUREMENT_DELAY, + type="int", + help="specify how many seconds we skip in the data Intel Power Gadget " + "collects. This time is for starting video play, switching to " + "fullscreen mode, etc. By default, %d seconds is selected." % + _POWER_MEASUREMENT_DELAY) + parser.add_option( + "--resolution", + default=100, + type="int", + help="specify how often Intel Power Gadget samples data in " + "milliseconds. By default, 100 ms is selected.") + parser.add_option( + "--url", help="specify the webpage URL the browser launches with.") + parser.add_option( + "--fullscreen", + action="store_true", + default=False, + help="specify if the browser goes to fullscreen mode automatically, " + "specifically if there is a single video element in the page, switch " + "it to fullsrceen mode.") + parser.add_option( + "--underlay", + action="store_true", + default=False, + help="add a layer on top so the video layer becomes an underlay.") + parser.add_option( + "--logdir", + help="Speficy where the Intel Power Gadget log file should be stored. " + "If specified, the log file name will include a timestamp. If not " + "specified, the log file will be PowerLog.csv at the current dir and " + "will be overwritten at next run.") + parser.add_option( + "--repeat", + default=3, + type="int", + help="specify how many times to repreat the measurement. By default, " + "measure only once. If measure more than once, between each " + "measurement, browser restarts.") + parser.add_option( + "--outliers", + default=0, + type="int", + help="if a test is repeated multiples and outliers is set to N, then " + "N smallest results and N largest results are discarded before " + "computing mean and stdev.") + parser.add_option( + "--bypass-ipg", + action="store_true", + default=False, + help="Do not launch Intel Power Gadget. This is for testing " + "convenience on machines where Intel Power Gadget does not work.") @classmethod def GenerateGpuTests(cls, options): @@ -262,46 +281,57 @@ # This is for local testing convenience only and is not to be added to # any bots. cls._url_mode = True - yield ('URL', options.url, - {'test_func': 'URL', - 'repeat': options.repeat, - 'outliers': options.outliers, - 'fullscreen': options.fullscreen, - 'underlay': options.underlay, - 'logdir': options.logdir, - 'duration': options.duration, - 'delay': options.delay, - 'resolution': options.resolution, - 'bypass_ipg': options.bypass_ipg}) + yield ('URL', options.url, { + 'test_func': 'URL', + 'repeat': options.repeat, + 'outliers': options.outliers, + 'fullscreen': options.fullscreen, + 'underlay': options.underlay, + 'logdir': options.logdir, + 'duration': options.duration, + 'delay': options.delay, + 'resolution': options.resolution, + 'bypass_ipg': options.bypass_ipg + }) else: cls._url_mode = False - yield ('Basic', '-', - {'test_func': 'Basic', - 'bypass_ipg': options.bypass_ipg}) + yield ('Basic', '-', { + 'test_func': 'Basic', + 'repeat': options.repeat, + 'bypass_ipg': options.bypass_ipg + }) yield ('Video_720_MP4', - _GPU_RELATIVE_PATH + 'power_video_bear_1280x720_mp4.html', - {'test_func': 'Video', - 'bypass_ipg': options.bypass_ipg, - 'underlay': False, - 'fullscreen': False}) + _GPU_RELATIVE_PATH + 'power_video_bear_1280x720_mp4.html', { + 'test_func': 'Video', + 'repeat': options.repeat, + 'bypass_ipg': options.bypass_ipg, + 'underlay': False, + 'fullscreen': False + }) yield ('Video_720_MP4_Underlay', - _GPU_RELATIVE_PATH + 'power_video_bear_1280x720_mp4.html', - {'test_func': 'Video', - 'bypass_ipg': options.bypass_ipg, - 'underlay': True, - 'fullscreen': False}) + _GPU_RELATIVE_PATH + 'power_video_bear_1280x720_mp4.html', { + 'test_func': 'Video', + 'repeat': options.repeat, + 'bypass_ipg': options.bypass_ipg, + 'underlay': True, + 'fullscreen': False + }) yield ('Video_720_MP4_Fullscreen', - _GPU_RELATIVE_PATH + 'power_video_bear_1280x720_mp4.html', - {'test_func': 'Video', - 'bypass_ipg': options.bypass_ipg, - 'underlay': False, - 'fullscreen': True}) + _GPU_RELATIVE_PATH + 'power_video_bear_1280x720_mp4.html', { + 'test_func': 'Video', + 'repeat': options.repeat, + 'bypass_ipg': options.bypass_ipg, + 'underlay': False, + 'fullscreen': True + }) yield ('Video_720_MP4_Underlay_Fullscreen', - _GPU_RELATIVE_PATH + 'power_video_bear_1280x720_mp4.html', - {'test_func': 'Video', - 'bypass_ipg': options.bypass_ipg, - 'underlay': True, - 'fullscreen': True}) + _GPU_RELATIVE_PATH + 'power_video_bear_1280x720_mp4.html', { + 'test_func': 'Video', + 'repeat': options.repeat, + 'bypass_ipg': options.bypass_ipg, + 'underlay': True, + 'fullscreen': True + }) @classmethod def SetUpProcess(cls): @@ -330,23 +360,41 @@ if bypass_ipg: logging.info("Bypassing Intel Power Gadget") time.sleep(total_time) - return - logfile = None # Use the default path + return {} + logfile = None # Use the default path ipg_utils.RunIPG(total_time, _POWER_MEASUREMENT_RESOLUTION, logfile) results = ipg_utils.AnalyzeIPGLogFile(logfile, _POWER_MEASUREMENT_DELAY) + return results + + @staticmethod + def _AppendResults(results_sum, results): + assert type(results_sum) is dict and type(results) is dict + assert results + first_append = not results_sum + for key, value in results.items(): + if first_append: + results_sum[key] = [value] + else: + assert key in results_sum + assert type(results_sum[key]) is list + results_sum[key].append(value) + return results_sum + + @staticmethod + def _LogResults(results): # TODO(zmo): output in a way that the results can be tracked at # chromeperf.appspot.com. logging.info("Results: %s", str(results)) def _SetupVideo(self, fullscreen, underlay): self.tab.action_runner.WaitForJavaScriptCondition( - 'waitForVideoToPlay()', timeout=30) + 'waitForVideoToPlay()', timeout=30) if fullscreen: self.tab.action_runner.ExecuteJavaScript( - 'startFullscreenMode();', user_gesture=True) + 'startFullscreenMode();', user_gesture=True) try: self.tab.action_runner.WaitForJavaScriptCondition( - 'isVideoInFullscreen()', timeout=5) + 'isVideoInFullscreen()', timeout=5) except py_utils.TimeoutException: self.fail('requestFullscreen() fails to work, possibly because ' '|user_gesture| is not set.') @@ -357,30 +405,49 @@ # Actual test functions def _RunTest_Basic(self, test_path, params): + repeat = params['repeat'] bypass_ipg = params['bypass_ipg'] - PowerMeasurementIntegrationTest._MeasurePowerWithIPG(bypass_ipg) + browser_args = PowerMeasurementIntegrationTest._AddDefaultArgs([]) + + results_sum = {} + for iteration in range(repeat): + logging.info('') + logging.info('Iteration #%d', iteration) + self.RestartBrowserWithArgs(browser_args) + + results = PowerMeasurementIntegrationTest._MeasurePowerWithIPG(bypass_ipg) + results_sum = PowerMeasurementIntegrationTest._AppendResults( + results_sum, results) + PowerMeasurementIntegrationTest._LogResults(results_sum) def _RunTest_Video(self, test_path, params): + repeat = params['repeat'] fullscreen = params['fullscreen'] underlay = params['underlay'] bypass_ipg = params['bypass_ipg'] disabled_features = [ - 'D3D11VideoDecoder', - 'DirectCompositionUseNV12DecodeSwapChain', - 'DirectCompositionUnderlays'] - self.RestartBrowserWithArgs( - PowerMeasurementIntegrationTest._AddDefaultArgs([ - '--disable-features=' + ','.join(disabled_features)])) + 'D3D11VideoDecoder', 'DirectCompositionUseNV12DecodeSwapChain', + 'DirectCompositionUnderlays' + ] + browser_args = PowerMeasurementIntegrationTest._AddDefaultArgs( + ['--disable-features=' + ','.join(disabled_features)]) - url = self.UrlOfStaticFilePath(test_path) - self.tab.Navigate( - url, script_to_evaluate_on_commit=_VIDEO_TEST_SCRIPT) - self._SetupVideo(fullscreen=fullscreen, underlay=underlay) + results_sum = {} + for iteration in range(repeat): + logging.info('') + logging.info('Iteration #%d', iteration) + self.RestartBrowserWithArgs(browser_args) - PowerMeasurementIntegrationTest._MeasurePowerWithIPG(bypass_ipg) + url = self.UrlOfStaticFilePath(test_path) + self.tab.Navigate(url, script_to_evaluate_on_commit=_VIDEO_TEST_SCRIPT) + self._SetupVideo(fullscreen=fullscreen, underlay=underlay) + results = PowerMeasurementIntegrationTest._MeasurePowerWithIPG(bypass_ipg) + results_sum = PowerMeasurementIntegrationTest._AppendResults( + results_sum, results) + PowerMeasurementIntegrationTest._LogResults(results_sum) def _RunTest_URL(self, test_path, params): repeat = params['repeat'] @@ -411,8 +478,8 @@ if ipg_logdir: if not os.path.isdir(ipg_logdir): self.fail("Folder " + ipg_logdir + " doesn't exist") - logfile = ipg_utils.GenerateIPGLogFilename(log_dir=ipg_logdir, - timestamp=True) + logfile = ipg_utils.GenerateIPGLogFilename( + log_dir=ipg_logdir, timestamp=True) ipg_utils.RunIPG(ipg_duration + ipg_delay, ipg_resolution, logfile) logfiles.append(logfile) @@ -433,7 +500,7 @@ print "Results saved in ", json_path summary = ipg_utils.ProcessResultsFromMultipleIPGRuns( - logfiles, ipg_delay, outliers, json_path) + logfiles, ipg_delay, outliers, json_path) logging.info("Summary: %s", str(summary))
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index 00b9082..c121cc8 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn
@@ -452,6 +452,7 @@ "//base/test:test_support", "//components/crx_file", "//components/version_info:version_info", + "//content/test:test_support", "//device/usb/public/cpp:test_support", "//extensions:extensions_resources",
diff --git a/extensions/common/api/declarative_net_request.idl b/extensions/common/api/declarative_net_request.idl index 04e68d0..5da6d46f 100644 --- a/extensions/common/api/declarative_net_request.idl +++ b/extensions/common/api/declarative_net_request.idl
@@ -46,8 +46,8 @@ block, // Redirect the network request. redirect, - // Allow the network request. The request won't be blocked or redirected - // even if there is a block or redirect rule which matches it. + // Allow the network request. The request won't be blocked even if there + // is a blocking rule which matches it. allow, // Remove request/response headers from the network request. removeHeaders @@ -156,11 +156,34 @@ interface Functions { - // TODO(crbug.com/930961): Enable documentation for these functions once - // they are implemented. - [nodoc] static void addDynamicRules(Rule[] rules, optional EmptyCallback callback); - [nodoc] static void removeDynamicRules(long[] rule_ids, optional EmptyCallback callback); - [nodoc] static void getDynamicRules(GetRulesCallback callback); + // Adds <code>rules</code> to the current set of dynamic rules for the + // extension. These rules are persisted across browser sessions. + // Note: <a href="#property-MAX_NUMBER_OF_DYNAMIC_RULES"> + // MAX_NUMBER_OF_DYNAMIC_RULES</a> is the maximum number of dynamic rules an + // extension can add. + // |rules|: The rules to add. + // |callback|: Called once the given <code>rules</code> are added. In case + // of an error, $(ref:runtime.lastError) will be set to denote the error + // message and no rules will be added. This can happen for multiple reasons, + // such as invalid rule format, duplicate rule ID, rule count limit + // exceeded, internal errors, and others. + static void addDynamicRules(Rule[] rules, optional EmptyCallback callback); + + // Removes rules corresponding to <code>rule_ids</code> from the current set + // of dynamic rules for the extension. Any <code>rule_ids</code> not already + // present are ignored. Note that static rules specified as part of the + // extension package can not be removed using this function. + // |rule_ids|: The IDs of dynamic rules to remove. + // |callback|: Called once the rules are removed. In case of an error, + // $(ref:runtime.lastError) will be set to denote the error message and no + // rules will be removed. This may happen due to internal errors. + static void removeDynamicRules(long[] rule_ids, + optional EmptyCallback callback); + + // Returns the current set of dynamic rules for the extension. + // |callback|: Called with the set of dynamic rules. An error might be + // raised in case of transient internal errors. + static void getDynamicRules(GetRulesCallback callback); // Adds <code>page_patterns</code> to the set of allowed pages. Requests // from these pages are not intercepted by the extension. These are @@ -173,11 +196,11 @@ // <a href="/extensions/match_patterns">match patterns</a> which are to be // allowed. // |callback|: Called after the <code>page_patterns</code> have been added. - // chrome.runtime.lastError will be set in case of an error, for example if + // $(ref:runtime.lastError) will be set in case of an error, for example if // an invalid page pattern is specified or the extension exceeded the // maximum page patterns limit. - - static void addAllowedPages(DOMString[] page_patterns, optional EmptyCallback callback); + static void addAllowedPages(DOMString[] page_patterns, + optional EmptyCallback callback); // Removes <code>page_patterns</code> from the set of allowed pages. // Note: Removing page patterns is atomic. In case of an error, no page @@ -186,8 +209,9 @@ // <a href="/extensions/match_patterns">match patterns</a> which are to be // removed. // |callback|: Called after the <code>page_patterns</code> have been - // removed. chrome.runtime.lastError will be set in case of an error. - static void removeAllowedPages(DOMString[] page_patterns, optional EmptyCallback callback); + // removed. $(ref:runtime.lastError) will be set in case of an error. + static void removeAllowedPages(DOMString[] page_patterns, + optional EmptyCallback callback); // Returns the current set of allowed pages. // |callback|: Called with the set of currently allowed pages.
diff --git a/extensions/common/component_extension_url_pattern_unittest.cc b/extensions/common/component_extension_url_pattern_unittest.cc index c26eedc..b2e5b90 100644 --- a/extensions/common/component_extension_url_pattern_unittest.cc +++ b/extensions/common/component_extension_url_pattern_unittest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "content/public/test/test_utils.h" #include "extensions/common/constants.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" @@ -25,7 +26,7 @@ .Build(); std::string error; EXPECT_FALSE(all_urls->permissions_data()->CanAccessPage( - GURL("chrome://settings"), kTabId, &error)) + content::GetWebUIURL("settings"), kTabId, &error)) << error; // Non-chrome scheme should be fine. EXPECT_TRUE(all_urls->permissions_data()->CanAccessPage( @@ -43,7 +44,7 @@ .Build(); std::string error; EXPECT_TRUE(all_urls->permissions_data()->CanAccessPage( - GURL("chrome://settings"), kTabId, &error)) + content::GetWebUIURL("settings"), kTabId, &error)) << error; } @@ -51,12 +52,12 @@ // Explicitly specifying a pattern that allows access to the chrome // scheme is OK. auto chrome_urls = ExtensionBuilder("chrome urls") - .AddPermission("chrome://*/*") + .AddPermission(content::GetWebUIURLString("*/*")) .SetLocation(Manifest::COMPONENT) .Build(); std::string error; EXPECT_TRUE(chrome_urls->permissions_data()->CanAccessPage( - GURL("chrome://settings"), kTabId, &error)) + content::GetWebUIURL("settings"), kTabId, &error)) << error; }
diff --git a/extensions/common/features/simple_feature_unittest.cc b/extensions/common/features/simple_feature_unittest.cc index eff9dbef..7bc3b00 100644 --- a/extensions/common/features/simple_feature_unittest.cc +++ b/extensions/common/features/simple_feature_unittest.cc
@@ -15,6 +15,7 @@ #include "base/strings/stringprintf.h" #include "base/test/scoped_command_line.h" #include "base/values.h" +#include "content/public/test/test_utils.h" #include "extensions/common/features/complex_feature.h" #include "extensions/common/features/feature_channel.h" #include "extensions/common/features/feature_session_type.h" @@ -890,10 +891,10 @@ // Create a webui feature available on trunk. SimpleFeature feature; feature.set_contexts({Feature::WEBUI_CONTEXT}); - feature.set_matches({"chrome://settings/*"}); + feature.set_matches({content::GetWebUIURLString("settings/*").c_str()}); feature.set_channel(version_info::Channel::UNKNOWN); - const GURL kAllowlistedUrl("chrome://settings/foo"); + const GURL kAllowlistedUrl(content::GetWebUIURL("settings/foo")); const GURL kOtherUrl("https://example.com"); {
diff --git a/extensions/common/url_pattern_unittest.cc b/extensions/common/url_pattern_unittest.cc index 3bedc432..993bd10 100644 --- a/extensions/common/url_pattern_unittest.cc +++ b/extensions/common/url_pattern_unittest.cc
@@ -10,6 +10,8 @@ #include "base/stl_util.h" #include "base/strings/stringprintf.h" +#include "content/public/common/url_constants.h" +#include "content/public/test/test_utils.h" #include "extensions/common/constants.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -63,7 +65,7 @@ TEST(ExtensionURLPatternTest, Ports) { const struct { - const char* pattern; + const std::string pattern; URLPattern::ParseResult expected_result; const char* expected_port; } kTestPatterns[] = { @@ -80,7 +82,8 @@ {"http://foo:123456/", URLPattern::ParseResult::kInvalidPort, "*"}, {"http://foo:80:80/monkey", URLPattern::ParseResult::kInvalidPort, "*"}, {"file://foo:1234/bar", URLPattern::ParseResult::kSuccess, "*"}, - {"chrome://foo:1234/bar", URLPattern::ParseResult::kInvalidPort, "*"}, + {content::GetWebUIURLString("foo:1234/bar"), + URLPattern::ParseResult::kInvalidPort, "*"}, // Port-like strings in the path should not trigger a warning. {"http://*/:1234", URLPattern::ParseResult::kSuccess, "*"}, @@ -283,16 +286,18 @@ TEST(ExtensionURLPatternTest, Match9) { URLPattern pattern(kAllSchemes); EXPECT_EQ(URLPattern::ParseResult::kSuccess, - pattern.Parse("chrome://favicon/*")); - EXPECT_EQ("chrome", pattern.scheme()); + pattern.Parse(content::GetWebUIURLString("favicon/*"))); + EXPECT_EQ(content::kChromeUIScheme, pattern.scheme()); EXPECT_EQ("favicon", pattern.host()); EXPECT_FALSE(pattern.match_subdomains()); EXPECT_TRUE(pattern.match_effective_tld()); EXPECT_FALSE(pattern.match_all_urls()); EXPECT_EQ("/*", pattern.path()); - EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://favicon/http://google.com"))); - EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://favicon/https://google.com"))); - EXPECT_FALSE(pattern.MatchesURL(GURL("chrome://history"))); + EXPECT_TRUE( + pattern.MatchesURL(content::GetWebUIURL("favicon/http://google.com"))); + EXPECT_TRUE( + pattern.MatchesURL(content::GetWebUIURL("favicon/https://google.com"))); + EXPECT_FALSE(pattern.MatchesURL(content::GetWebUIURL("history"))); } // *:// @@ -301,7 +306,7 @@ EXPECT_EQ(URLPattern::ParseResult::kSuccess, pattern.Parse("*://*/*")); EXPECT_TRUE(pattern.MatchesScheme("http")); EXPECT_TRUE(pattern.MatchesScheme("https")); - EXPECT_FALSE(pattern.MatchesScheme("chrome")); + EXPECT_FALSE(pattern.MatchesScheme(content::kChromeUIScheme)); EXPECT_FALSE(pattern.MatchesScheme("file")); EXPECT_FALSE(pattern.MatchesScheme("ftp")); EXPECT_TRUE(pattern.match_subdomains()); @@ -309,7 +314,8 @@ EXPECT_FALSE(pattern.match_all_urls()); EXPECT_EQ("/*", pattern.path()); EXPECT_TRUE(pattern.MatchesURL(GURL("http://127.0.0.1"))); - EXPECT_FALSE(pattern.MatchesURL(GURL("chrome://favicon/http://google.com"))); + EXPECT_FALSE( + pattern.MatchesURL(content::GetWebUIURL("favicon/http://google.com"))); EXPECT_FALSE(pattern.MatchesURL(GURL("file:///foo/bar"))); EXPECT_FALSE(pattern.MatchesURL(GURL("file://localhost/foo/bar"))); } @@ -318,7 +324,7 @@ TEST(ExtensionURLPatternTest, Match11) { URLPattern pattern(kAllSchemes); EXPECT_EQ(URLPattern::ParseResult::kSuccess, pattern.Parse("<all_urls>")); - EXPECT_TRUE(pattern.MatchesScheme("chrome")); + EXPECT_TRUE(pattern.MatchesScheme(content::kChromeUIScheme)); EXPECT_TRUE(pattern.MatchesScheme("http")); EXPECT_TRUE(pattern.MatchesScheme("https")); EXPECT_TRUE(pattern.MatchesScheme("file")); @@ -328,7 +334,8 @@ EXPECT_TRUE(pattern.match_effective_tld()); EXPECT_TRUE(pattern.match_all_urls()); EXPECT_EQ("/*", pattern.path()); - EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://favicon/http://google.com"))); + EXPECT_TRUE( + pattern.MatchesURL(content::GetWebUIURL("favicon/http://google.com"))); EXPECT_TRUE(pattern.MatchesURL(GURL("http://127.0.0.1"))); EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo/bar"))); EXPECT_TRUE(pattern.MatchesURL(GURL("file://localhost/foo/bar"))); @@ -351,7 +358,7 @@ TEST(ExtensionURLPatternTest, Match12) { URLPattern pattern(URLPattern::SCHEME_ALL); EXPECT_EQ(URLPattern::ParseResult::kSuccess, pattern.Parse("<all_urls>")); - EXPECT_TRUE(pattern.MatchesScheme("chrome")); + EXPECT_TRUE(pattern.MatchesScheme(content::kChromeUIScheme)); EXPECT_TRUE(pattern.MatchesScheme("http")); EXPECT_TRUE(pattern.MatchesScheme("https")); EXPECT_TRUE(pattern.MatchesScheme("file")); @@ -364,11 +371,12 @@ EXPECT_TRUE(pattern.match_effective_tld()); EXPECT_TRUE(pattern.match_all_urls()); EXPECT_EQ("/*", pattern.path()); - EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://favicon/http://google.com"))); + EXPECT_TRUE( + pattern.MatchesURL(content::GetWebUIURL("favicon/http://google.com"))); EXPECT_TRUE(pattern.MatchesURL(GURL("http://127.0.0.1"))); EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo/bar"))); EXPECT_TRUE(pattern.MatchesURL(GURL("file://localhost/foo/bar"))); - EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://newtab"))); + EXPECT_TRUE(pattern.MatchesURL(content::GetWebUIURL("newtab"))); EXPECT_TRUE(pattern.MatchesURL(GURL("about:blank"))); EXPECT_TRUE(pattern.MatchesURL(GURL("about:version"))); EXPECT_TRUE(pattern.MatchesURL( @@ -550,12 +558,12 @@ } static const struct GetAsStringPatterns { - const char* pattern; + const std::string pattern; } kGetAsStringTestCases[] = { {"http://www/"}, {"http://*/*"}, - {"chrome://*/*"}, - {"chrome://newtab/"}, + {content::GetWebUIURLString("*/*")}, + {content::GetWebUIURLString("newtab/")}, {"about:*"}, {"about:blank"}, {"chrome-extension://*/*"}, @@ -662,7 +670,7 @@ EXPECT_EQ("https://*/*", all_urls[1].GetAsString()); EXPECT_EQ("file:///*", all_urls[2].GetAsString()); EXPECT_EQ("ftp://*/*", all_urls[3].GetAsString()); - EXPECT_EQ("chrome://*/*", all_urls[4].GetAsString()); + EXPECT_EQ(content::GetWebUIURLString("*/*"), all_urls[4].GetAsString()); EXPECT_EQ("chrome-extension://*/*", all_urls[5].GetAsString()); EXPECT_EQ("filesystem://*/*", all_urls[6].GetAsString()); EXPECT_EQ("ws://*/*", all_urls[7].GetAsString());
diff --git a/extensions/renderer/feature_cache_unittest.cc b/extensions/renderer/feature_cache_unittest.cc index 4906461..b36e57ce 100644 --- a/extensions/renderer/feature_cache_unittest.cc +++ b/extensions/renderer/feature_cache_unittest.cc
@@ -6,6 +6,7 @@ #include "base/stl_util.h" #include "components/crx_file/id_util.h" +#include "content/public/test/test_utils.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" #include "extensions/common/permissions/permissions_data.h" @@ -74,10 +75,10 @@ // The chrome://extensions page is whitelisted for the management API. FakeContext webui_context = {Feature::WEBUI_CONTEXT, nullptr, - GURL("chrome://extensions")}; + content::GetWebUIURL("extensions")}; // chrome://baz is not whitelisted, and should not have access. FakeContext webui_context_without_access = {Feature::WEBUI_CONTEXT, nullptr, - GURL("chrome://baz")}; + content::GetWebUIURL("baz")}; EXPECT_TRUE(HasFeature(cache, webui_context, "management")); EXPECT_FALSE(HasFeature(cache, webui_context_without_access, "management"));
diff --git a/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java b/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java index ad2b1e0..9f9f56c7 100644 --- a/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java +++ b/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java
@@ -312,8 +312,7 @@ Log.d(TAG, "Not provisioned during openSession()"); if (!sMediaCryptoDeferrer.isProvisioning()) { - startProvisioning(); - return true; + return startProvisioning(); } // Cannot provision. Defer MediaCrypto creation and try again later. @@ -607,7 +606,10 @@ nativeOnProvisioningComplete(mNativeMediaDrmBridge, true); } catch (android.media.NotProvisionedException e) { - startProvisioning(); + if (!startProvisioning()) { + // Indicate that provisioning failed. + nativeOnProvisioningComplete(mNativeMediaDrmBridge, false); + } } } @@ -1133,22 +1135,39 @@ return mMediaDrm.getPropertyString(SECURITY_LEVEL); } - private void startProvisioning() { + /** + * Start provisioning. Returns true if a provisioning request can be + * generated and has been forwarded to C++ code for handling, false + * otherwise. + */ + private boolean startProvisioning() { Log.d(TAG, "startProvisioning"); assert !mProvisioningPending; mProvisioningPending = true; assert mMediaDrm != null; if (!isNativeMediaDrmBridgeValid()) { - return; + return false; } if (mRequiresMediaCrypto) { sMediaCryptoDeferrer.onProvisionStarted(); } - MediaDrm.ProvisionRequest request = mMediaDrm.getProvisionRequest(); + // getProvisionRequest() may fail with android.media.MediaDrm.MediaDrmStateException or + // android.media.MediaDrmResetException, both of which extend IllegalStateException. As + // these specific exceptions are only available in API 21 and 23 respectively, using the + // base exception so that this will work for all API versions. + MediaDrm.ProvisionRequest request; + try { + request = mMediaDrm.getProvisionRequest(); + } catch (java.lang.IllegalStateException e) { + Log.e(TAG, "Failed to get provisioning request", e); + return false; + } + nativeOnProvisionRequest(mNativeMediaDrmBridge, request.getDefaultUrl(), request.getData()); + return true; } /**
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index a8b11a3..68e2dbd 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -231,10 +231,6 @@ const base::Feature kUseAndroidOverlayAggressively{ "UseAndroidOverlayAggressively", base::FEATURE_ENABLED_BY_DEFAULT}; -// Let video track be unselected when video is playing in the background. -const base::Feature kBackgroundSrcVideoTrackOptimization{ - "BackgroundSrcVideoTrackOptimization", base::FEATURE_ENABLED_BY_DEFAULT}; - // Let video without audio be paused when it is playing in the background. const base::Feature kBackgroundVideoPauseOptimization{ "BackgroundVideoPauseOptimization", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index db13a78..aac465d 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -97,7 +97,6 @@ MEDIA_EXPORT extern const base::Feature kAutoplayIgnoreWebAudio; MEDIA_EXPORT extern const base::Feature kAutoplayDisableSettings; MEDIA_EXPORT extern const base::Feature kAutoplayWhitelistSettings; -MEDIA_EXPORT extern const base::Feature kBackgroundSrcVideoTrackOptimization; MEDIA_EXPORT extern const base::Feature kBackgroundVideoPauseOptimization; MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoder; MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoderIgnoreWorkarounds;
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 71d8e8a..e8e6f90 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -116,13 +116,6 @@ return base::FeatureList::IsEnabled(kResumeBackgroundVideo); } -bool IsBackgroundVideoTrackOptimizationEnabled( - WebMediaPlayer::LoadType load_type) { - // Background video track optimization is always enabled for MSE videos. - return load_type == WebMediaPlayer::LoadType::kLoadTypeMediaSource || - base::FeatureList::IsEnabled(kBackgroundSrcVideoTrackOptimization); -} - bool IsBackgroundVideoPauseOptimizationEnabled() { return base::FeatureList::IsEnabled(kBackgroundVideoPauseOptimization); } @@ -3222,8 +3215,7 @@ // video. MSE video track switching on hide has gone through a field test. // TODO(tmathmeyer): Passing load_type_ won't be needed after src= field // testing is finished. see: http://crbug.com/709302 - if (!is_background_video_track_optimization_supported_ || - !IsBackgroundVideoTrackOptimizationEnabled(load_type_)) + if (!is_background_video_track_optimization_supported_) return false; // Disable video track only for players with audio that match the criteria for
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc index f40e4d6..940e7c9 100644 --- a/media/blink/webmediaplayer_impl_unittest.cc +++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -1746,18 +1746,17 @@ class WebMediaPlayerImplBackgroundBehaviorTest : public WebMediaPlayerImplTest, public ::testing::WithParamInterface< - std::tuple<bool, bool, int, int, bool, bool, bool, bool, bool>> { + std::tuple<bool, int, int, bool, bool, bool, bool, bool>> { public: // Indices of the tuple parameters. static const int kIsMediaSuspendEnabled = 0; - static const int kIsBackgroundOptimizationEnabled = 1; - static const int kDurationSec = 2; - static const int kAverageKeyframeDistanceSec = 3; - static const int kIsResumeBackgroundVideoEnabled = 4; - static const int kIsMediaSource = 5; - static const int kIsBackgroundPauseEnabled = 6; - static const int kIsPictureInPictureEnabled = 7; - static const int kIsBackgroundVideoPlaybackEnabled = 8; + static const int kDurationSec = 1; + static const int kAverageKeyframeDistanceSec = 2; + static const int kIsResumeBackgroundVideoEnabled = 3; + static const int kIsMediaSource = 4; + static const int kIsBackgroundPauseEnabled = 5; + static const int kIsPictureInPictureEnabled = 6; + static const int kIsBackgroundVideoPlaybackEnabled = 7; void SetUp() override { WebMediaPlayerImplTest::SetUp(); @@ -1766,11 +1765,6 @@ std::string enabled_features; std::string disabled_features; - if (IsBackgroundOptimizationOn()) { - enabled_features += kBackgroundSrcVideoTrackOptimization.name; - } else { - disabled_features += kBackgroundSrcVideoTrackOptimization.name; - } if (IsBackgroundPauseOn()) { if (!enabled_features.empty()) @@ -1823,10 +1817,6 @@ return std::get<kIsMediaSuspendEnabled>(GetParam()); } - bool IsBackgroundOptimizationOn() { - return std::get<kIsBackgroundOptimizationEnabled>(GetParam()); - } - bool IsResumeBackgroundVideoEnabled() { return std::get<kIsResumeBackgroundVideoEnabled>(GetParam()); } @@ -1915,8 +1905,7 @@ (GetAverageKeyframeDistanceSec() < GetMaxKeyframeDistanceSec())); EXPECT_EQ(matches_requirements, IsBackgroundOptimizationCandidate()); - EXPECT_EQ(IsBackgroundOptimizationOn() && matches_requirements, - ShouldDisableVideoWhenHidden()); + EXPECT_EQ(matches_requirements, ShouldDisableVideoWhenHidden()); // Only pause audible videos if both media suspend and resume background // videos is on and background video playback is disabled. Background video @@ -1926,8 +1915,8 @@ (IsMediaSuspendOn() && IsResumeBackgroundVideoEnabled()), ShouldPausePlaybackWhenHidden()); - if (!IsBackgroundOptimizationOn() || !matches_requirements || - !ShouldDisableVideoWhenHidden() || IsMediaSuspendOn()) { + if (!matches_requirements || !ShouldDisableVideoWhenHidden() || + IsMediaSuspendOn()) { return; } @@ -1952,7 +1941,6 @@ WebMediaPlayerImplBackgroundBehaviorTest, ::testing::Combine( ::testing::Bool(), - ::testing::Bool(), ::testing::Values( WebMediaPlayerImpl::kMaxKeyframeDistanceToDisableBackgroundVideoMs / base::Time::kMillisecondsPerSecond +
diff --git a/media/gpu/linux/platform_video_frame_utils.cc b/media/gpu/linux/platform_video_frame_utils.cc index a4a4d4b..7d2a74c 100644 --- a/media/gpu/linux/platform_video_frame_utils.cc +++ b/media/gpu/linux/platform_video_frame_utils.cc
@@ -47,7 +47,11 @@ for (size_t i = 0; i < num_planes; ++i) { planes[i].stride = pixmap->GetDmaBufPitch(i); planes[i].offset = pixmap->GetDmaBufOffset(i); - planes[i].modifier = pixmap->GetDmaBufModifier(i); + // TODO(crbug.com/957381): Move the modifier variable to NativePixmapHandle + // from NativePixmapPlane. + // TODO(crbug.com/914700): Move the modifier vairable from + // VideoFrameLayout::Plane to VideoFrameLayout. + planes[i].modifier = pixmap->GetBufferFormatModifier(); buffer_sizes[i] = planes[i].offset + planes[i].stride * VideoFrame::Rows(i, pixel_format, coded_size.height());
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc index c3c4d03..2fd4954 100644 --- a/media/renderers/video_resource_updater.cc +++ b/media/renderers/video_resource_updater.cc
@@ -13,7 +13,8 @@ #include "base/atomic_sequence_num.h" #include "base/bind.h" #include "base/bit_cast.h" -#include "base/memory/shared_memory.h" +#include "base/memory/shared_memory_mapping.h" +#include "base/memory/unsafe_shared_memory_region.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" @@ -279,14 +280,13 @@ DCHECK(shared_bitmap_reporter_); // Allocate SharedMemory and notify display compositor of the allocation. - shared_memory_ = viz::bitmap_allocation::AllocateMappedBitmap( - resource_size(), viz::ResourceFormat::RGBA_8888); - mojo::ScopedSharedBufferHandle handle = - viz::bitmap_allocation::DuplicateAndCloseMappedBitmap( - shared_memory_.get(), resource_size(), - viz::ResourceFormat::RGBA_8888); - shared_bitmap_reporter_->DidAllocateSharedBitmap(std::move(handle), - shared_bitmap_id_); + base::MappedReadOnlyRegion shm = + viz::bitmap_allocation::AllocateSharedBitmap( + resource_size(), viz::ResourceFormat::RGBA_8888); + shared_mapping_ = std::move(shm.mapping); + shared_bitmap_reporter_->DidAllocateSharedBitmap( + viz::bitmap_allocation::ToMojoHandle(std::move(shm.region)), + shared_bitmap_id_); } ~SoftwarePlaneResource() override { shared_bitmap_reporter_->DidDeleteSharedBitmap(shared_bitmap_id_); @@ -295,17 +295,17 @@ const viz::SharedBitmapId& shared_bitmap_id() const { return shared_bitmap_id_; } - void* pixels() { return shared_memory_->memory(); } + void* pixels() { return shared_mapping_.memory(); } // Returns a memory dump GUID consistent across processes. base::UnguessableToken GetSharedMemoryGuid() const { - return shared_memory_->mapped_id(); + return shared_mapping_.guid(); } private: viz::SharedBitmapReporter* const shared_bitmap_reporter_; const viz::SharedBitmapId shared_bitmap_id_; - std::unique_ptr<base::SharedMemory> shared_memory_; + base::WritableSharedMemoryMapping shared_mapping_; DISALLOW_COPY_AND_ASSIGN(SoftwarePlaneResource); };
diff --git a/net/BUILD.gn b/net/BUILD.gn index 4d93a3f..29c14f1 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -2606,6 +2606,9 @@ "data/ssl/certificates/multi-root-crlset-unrelated.raw", "data/ssl/certificates/multi-root.keychain", "data/ssl/certificates/multivalue_rdn.pem", + "data/ssl/certificates/name-normalization-byteequal.pem", + "data/ssl/certificates/name-normalization-case-folding.pem", + "data/ssl/certificates/name-normalization-printable-utf8.pem", "data/ssl/certificates/name_constraint_bad.pem", "data/ssl/certificates/name_constraint_good.pem", "data/ssl/certificates/ndn.ca.crt",
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc index f7c8b29..b8ae1e99 100644 --- a/net/cert/cert_verify_proc.cc +++ b/net/cert/cert_verify_proc.cc
@@ -29,6 +29,7 @@ #include "net/cert/cert_verify_result.h" #include "net/cert/crl_set.h" #include "net/cert/internal/ocsp.h" +#include "net/cert/internal/parse_certificate.h" #include "net/cert/internal/signature_algorithm.h" #include "net/cert/known_roots.h" #include "net/cert/ocsp_revocation_status.h" @@ -36,6 +37,7 @@ #include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" #include "net/der/encode_values.h" +#include "third_party/boringssl/src/include/openssl/pool.h" #include "url/url_canon.h" #if defined(USE_NSS_CERTS) @@ -609,6 +611,72 @@ return rv; } +// static +void CertVerifyProc::LogNameNormalizationResult( + const std::string& histogram_suffix, + NameNormalizationResult result) { + base::UmaHistogramEnumeration( + std::string("Net.CertVerifier.NameNormalizationPrivateRoots") + + histogram_suffix, + result); +} + +// static +void CertVerifyProc::LogNameNormalizationMetrics( + const std::string& histogram_suffix, + X509Certificate* verified_cert, + bool is_issued_by_known_root) { + if (is_issued_by_known_root) + return; + + if (verified_cert->intermediate_buffers().empty()) { + LogNameNormalizationResult(histogram_suffix, + NameNormalizationResult::kChainLengthOne); + return; + } + + std::vector<CRYPTO_BUFFER*> der_certs; + der_certs.push_back(verified_cert->cert_buffer()); + for (const auto& buf : verified_cert->intermediate_buffers()) + der_certs.push_back(buf.get()); + + ParseCertificateOptions options; + options.allow_invalid_serial_numbers = true; + + std::vector<der::Input> subjects; + std::vector<der::Input> issuers; + + for (auto* buf : der_certs) { + der::Input tbs_certificate_tlv; + der::Input signature_algorithm_tlv; + der::BitString signature_value; + ParsedTbsCertificate tbs; + if (!ParseCertificate( + der::Input(CRYPTO_BUFFER_data(buf), CRYPTO_BUFFER_len(buf)), + &tbs_certificate_tlv, &signature_algorithm_tlv, &signature_value, + nullptr /* errors*/) || + !ParseTbsCertificate(tbs_certificate_tlv, options, &tbs, + nullptr /*errors*/)) { + LogNameNormalizationResult(histogram_suffix, + NameNormalizationResult::kError); + return; + } + subjects.push_back(tbs.subject_tlv); + issuers.push_back(tbs.issuer_tlv); + } + + for (size_t i = 0; i < subjects.size() - 1; ++i) { + if (issuers[i] != subjects[i + 1]) { + LogNameNormalizationResult(histogram_suffix, + NameNormalizationResult::kNormalized); + return; + } + } + + LogNameNormalizationResult(histogram_suffix, + NameNormalizationResult::kByteEqual); +} + // CheckNameConstraints verifies that every name in |dns_names| is in one of // the domains specified by |domains|. static bool CheckNameConstraints(const std::vector<std::string>& dns_names,
diff --git a/net/cert/cert_verify_proc.h b/net/cert/cert_verify_proc.h index 5d3c4b3..8ab3bf5 100644 --- a/net/cert/cert_verify_proc.h +++ b/net/cert/cert_verify_proc.h
@@ -54,6 +54,16 @@ VERIFY_DISABLE_SYMANTEC_ENFORCEMENT = 1 << 3, }; + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class NameNormalizationResult { + kError = 0, + kByteEqual = 1, + kNormalized = 2, + kChainLengthOne = 3, + kMaxValue = kChainLengthOne + }; + // Creates and returns the default CertVerifyProc. |cert_net_fetcher| may not // be used, depending on the implementation. static scoped_refptr<CertVerifyProc> CreateDefault( @@ -101,6 +111,17 @@ CertVerifyProc(); virtual ~CertVerifyProc(); + // Record a histogram of whether Name normalization was used in verifying the + // chain. This should only be called for successfully validated chains. + static void LogNameNormalizationResult(const std::string& histogram_suffix, + NameNormalizationResult result); + + // Record a histogram of whether Name normalization was used in verifying the + // chain. This should only be called for successfully validated chains. + static void LogNameNormalizationMetrics(const std::string& histogram_suffix, + X509Certificate* verified_cert, + bool is_issued_by_known_root); + private: friend class base::RefCountedThreadSafe<CertVerifyProc>; FRIEND_TEST_ALL_PREFIXES(CertVerifyProcTest, DigiNotarCerts);
diff --git a/net/cert/cert_verify_proc_android.cc b/net/cert/cert_verify_proc_android.cc index 7b334b7..7bae0d2 100644 --- a/net/cert/cert_verify_proc_android.cc +++ b/net/cert/cert_verify_proc_android.cc
@@ -369,6 +369,9 @@ if (IsCertStatusError(verify_result->cert_status)) return MapCertStatusToNetError(verify_result->cert_status); + LogNameNormalizationMetrics(".Android", verify_result->verified_cert.get(), + verify_result->is_issued_by_known_root); + return OK; }
diff --git a/net/cert/cert_verify_proc_builtin.cc b/net/cert/cert_verify_proc_builtin.cc index 0687bb2..8f2fec34 100644 --- a/net/cert/cert_verify_proc_builtin.cc +++ b/net/cert/cert_verify_proc_builtin.cc
@@ -661,9 +661,14 @@ } // Write the results to |*verify_result|. - return AssignVerifyResult(input_cert, hostname, result, verification_type, - checked_revocation_for_some_path, - ssl_trust_store.get(), verify_result); + int error = AssignVerifyResult( + input_cert, hostname, result, verification_type, + checked_revocation_for_some_path, ssl_trust_store.get(), verify_result); + if (error == OK) { + LogNameNormalizationMetrics(".Builtin", verify_result->verified_cert.get(), + verify_result->is_issued_by_known_root); + } + return error; } } // namespace
diff --git a/net/cert/cert_verify_proc_ios.cc b/net/cert/cert_verify_proc_ios.cc index 8aded2f14..88b6ca71 100644 --- a/net/cert/cert_verify_proc_ios.cc +++ b/net/cert/cert_verify_proc_ios.cc
@@ -331,6 +331,9 @@ if (IsCertStatusError(verify_result->cert_status)) return MapCertStatusToNetError(verify_result->cert_status); + LogNameNormalizationMetrics(".IOS", verify_result->verified_cert.get(), + verify_result->is_issued_by_known_root); + return OK; }
diff --git a/net/cert/cert_verify_proc_mac.cc b/net/cert/cert_verify_proc_mac.cc index 7d909138..548ce4f 100644 --- a/net/cert/cert_verify_proc_mac.cc +++ b/net/cert/cert_verify_proc_mac.cc
@@ -1048,6 +1048,9 @@ verify_result->cert_status |= CERT_STATUS_IS_EV; } + LogNameNormalizationMetrics(".Mac", verify_result->verified_cert.get(), + verify_result->is_issued_by_known_root); + return OK; }
diff --git a/net/cert/cert_verify_proc_nss.cc b/net/cert/cert_verify_proc_nss.cc index 2e4bc71..7bb58da 100644 --- a/net/cert/cert_verify_proc_nss.cc +++ b/net/cert/cert_verify_proc_nss.cc
@@ -996,6 +996,9 @@ } } + LogNameNormalizationMetrics(".NSS", verify_result->verified_cert.get(), + verify_result->is_issued_by_known_root); + return OK; }
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc index 67123cb8..463073da 100644 --- a/net/cert/cert_verify_proc_unittest.cc +++ b/net/cert/cert_verify_proc_unittest.cc
@@ -2504,6 +2504,142 @@ } } +class CertVerifyProcNameNormalizationTest : public CertVerifyProcInternalTest { + protected: + void SetUp() override { + CertVerifyProcInternalTest::SetUp(); + + scoped_refptr<X509Certificate> root_cert = + ImportCertFromFile(GetTestCertsDirectory(), "ocsp-test-root.pem"); + ASSERT_TRUE(root_cert); + test_root_.reset(new ScopedTestRoot(root_cert.get())); + } + + std::string HistogramName() const { + std::string prefix("Net.CertVerifier.NameNormalizationPrivateRoots."); + switch (verify_proc_type()) { + case CERT_VERIFY_PROC_NSS: + return prefix + "NSS"; + case CERT_VERIFY_PROC_ANDROID: + return prefix + "Android"; + case CERT_VERIFY_PROC_IOS: + return prefix + "IOS"; + case CERT_VERIFY_PROC_MAC: + return prefix + "Mac"; + case CERT_VERIFY_PROC_WIN: + return prefix + "Win"; + case CERT_VERIFY_PROC_BUILTIN: + return prefix + "Builtin"; + } + } + + void ExpectNormalizationHistogram(int verify_error) { + if (verify_error == OK) { + histograms_.ExpectUniqueSample( + HistogramName(), CertVerifyProc::NameNormalizationResult::kNormalized, + 1); + } else { + histograms_.ExpectTotalCount(HistogramName(), 0); + } + } + + void ExpectByteEqualHistogram() { + histograms_.ExpectUniqueSample( + HistogramName(), CertVerifyProc::NameNormalizationResult::kByteEqual, + 1); + } + + private: + std::unique_ptr<ScopedTestRoot> test_root_; + base::HistogramTester histograms_; +}; + +INSTANTIATE_TEST_SUITE_P(, + CertVerifyProcNameNormalizationTest, + testing::ValuesIn(kAllCertVerifiers), + VerifyProcTypeToName); + +// Tries to verify a chain where the leaf's issuer CN is PrintableString, while +// the intermediate's subject CN is UTF8String, and verifies the proper +// histogram is logged. +TEST_P(CertVerifyProcNameNormalizationTest, StringType) { + scoped_refptr<X509Certificate> chain = CreateCertificateChainFromFile( + GetTestCertsDirectory(), "name-normalization-printable-utf8.pem", + X509Certificate::FORMAT_PEM_CERT_SEQUENCE); + ASSERT_TRUE(chain); + + int flags = 0; + CertVerifyResult verify_result; + int error = + Verify(chain.get(), "example.test", flags, CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); + + switch (verify_proc_type()) { + case CERT_VERIFY_PROC_NSS: + case CERT_VERIFY_PROC_IOS: + case CERT_VERIFY_PROC_MAC: + case CERT_VERIFY_PROC_WIN: + EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID)); + break; + case CERT_VERIFY_PROC_ANDROID: + case CERT_VERIFY_PROC_BUILTIN: + EXPECT_THAT(error, IsOk()); + break; + } + + ExpectNormalizationHistogram(error); +} + +// Tries to verify a chain where the leaf's issuer CN and intermediate's +// subject CN are both PrintableString but have differing case on the first +// character, and verifies the proper histogram is logged. +TEST_P(CertVerifyProcNameNormalizationTest, CaseFolding) { + scoped_refptr<X509Certificate> chain = CreateCertificateChainFromFile( + GetTestCertsDirectory(), "name-normalization-case-folding.pem", + X509Certificate::FORMAT_PEM_CERT_SEQUENCE); + ASSERT_TRUE(chain); + + int flags = 0; + CertVerifyResult verify_result; + int error = + Verify(chain.get(), "example.test", flags, CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); + + switch (verify_proc_type()) { + case CERT_VERIFY_PROC_NSS: + case CERT_VERIFY_PROC_WIN: + EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID)); + break; + case CERT_VERIFY_PROC_ANDROID: + case CERT_VERIFY_PROC_IOS: + case CERT_VERIFY_PROC_MAC: + case CERT_VERIFY_PROC_BUILTIN: + EXPECT_THAT(error, IsOk()); + break; + } + + ExpectNormalizationHistogram(error); +} + +// Confirms that a chain generated by the generate-name-normalization-certs.py +// script which does not require normalization validates ok, and that the +// ByteEqual histogram is logged. +TEST_P(CertVerifyProcNameNormalizationTest, ByteEqual) { + scoped_refptr<X509Certificate> chain = CreateCertificateChainFromFile( + GetTestCertsDirectory(), "name-normalization-byteequal.pem", + X509Certificate::FORMAT_PEM_CERT_SEQUENCE); + ASSERT_TRUE(chain); + + int flags = 0; + CertVerifyResult verify_result; + int error = + Verify(chain.get(), "example.test", flags, CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); + + EXPECT_THAT(error, IsOk()); + ExpectByteEqualHistogram(); +} + // This is the same as CertVerifyProcInternalTest, but it additionally sets up // networking capabilities for the cert verifiers, and a test server that can be // used to serve mock responses for AIA/OCSP/CRL.
diff --git a/net/cert/cert_verify_proc_win.cc b/net/cert/cert_verify_proc_win.cc index 95cfda85..9fdb3b4 100644 --- a/net/cert/cert_verify_proc_win.cc +++ b/net/cert/cert_verify_proc_win.cc
@@ -1151,6 +1151,10 @@ CheckEV(chain_context, rev_checking_enabled, ev_policy_oid)) { verify_result->cert_status |= CERT_STATUS_IS_EV; } + + LogNameNormalizationMetrics(".Win", verify_result->verified_cert.get(), + verify_result->is_issued_by_known_root); + return OK; }
diff --git a/net/data/ssl/certificates/README b/net/data/ssl/certificates/README index ee1d35bf..a33a5bf 100644 --- a/net/data/ssl/certificates/README +++ b/net/data/ssl/certificates/README
@@ -352,3 +352,13 @@ - key_usage_p256_both.pem Self-signed P-256 certificates with various combinations of keyUsage flags. Their private key is key_usage_p256.key. + +===== From net/data/ssl/scripts/generate-name-normalization-certs.py +- name-normalization-printable-utf8.pem + Leaf's issuer CN is PrintableString, intermediate's subject CN is + UTF8String. +- name-normalization-case-folding.pem + Leaf's issuer CN and intermediate's subject CN are both PrintableString + but have differing case on the first character. +- name-normalization-byteequal.pem + Names are byte-equal.
diff --git a/net/data/ssl/certificates/name-normalization-byteequal.pem b/net/data/ssl/certificates/name-normalization-byteequal.pem new file mode 100644 index 0000000..65dd12d1 --- /dev/null +++ b/net/data/ssl/certificates/name-normalization-byteequal.pem
@@ -0,0 +1,151 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 0d:df:45:88:06:ab:77:aa:2d:95:0f:1f:46:dd:62:ac + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN = Intermediate for byte equality comparison + Validity + Not Before: Jan 1 06:00:00 2010 GMT + Not After : Dec 1 06:00:00 2032 GMT + Subject: CN = Leaf for byte equality comparison + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:cd:12:d3:17:b3:9c:fb:b1:60:fb:1d:c9:c9:f0: + dc:8f:ef:36:04:dd:a4:d8:c5:57:39:2c:e1:d6:16: + 48:37:13:f7:82:16:ca:db:ef:d1:c7:6e:a0:f3:bb: + be:41:0e:24:b2:33:b1:b7:35:83:92:2b:09:31:4e: + 24:9b:2c:fd:e1:be:09:95:e1:3f:16:0f:b6:30:c1: + 0d:44:77:50:da:20:ff:aa:48:80:00:67:17:fe:aa: + 3e:4d:b6:02:e4:f5:11:b5:cc:31:2f:77:0f:44:b0: + 37:78:4e:ff:ec:62:64:0f:94:8a:a1:89:c3:76:9f: + 03:bd:d0:e2:2a:36:ec:fa:59:51:f5:57:7d:e1:95: + a4:fb:a3:3c:87:9b:65:79:68:b7:91:38:fd:7a:b3: + 89:a9:96:85:22:f7:38:9c:60:52:be:1f:f7:8b:c1: + 68:d3:ea:96:1e:13:2a:04:4e:ba:33:ac:07:ea:d9: + 53:67:c7:b8:15:e9:1e:ca:92:4d:91:4f:d0:d8:11: + 34:9b:8b:f5:00:70:7b:a7:1a:43:a2:90:1a:54:5f: + 34:e1:79:2e:72:65:4f:66:49:fa:b9:71:6f:4b:a1: + 73:79:ee:80:42:18:6b:bb:a9:b9:ba:c4:16:a6:04: + 74:cc:60:68:6f:0e:6e:4b:01:25:9c:c3:cb:58:73: + ed:f9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:example.test, IP Address:127.0.0.1 + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.11129.2.4.1 + + Signature Algorithm: sha256WithRSAEncryption + 5e:0a:28:c8:75:88:60:20:9d:64:29:7c:25:ee:08:b4:c6:44: + cd:df:15:b8:66:88:8e:20:7c:35:63:81:a6:5c:6f:4f:4a:d1: + b9:21:3c:d5:45:a4:59:bf:39:6b:f0:06:5b:46:3b:dc:c6:8f: + 60:7e:f6:c1:ca:6a:c0:ef:3f:ac:d9:2b:32:c8:df:38:82:a1: + a7:6f:a6:eb:b5:0c:04:fe:bc:4c:56:40:84:23:e4:56:54:8b: + ed:63:5d:2e:e0:76:84:16:e8:aa:a8:2e:e6:45:a3:13:96:c4: + e2:e6:26:1c:e1:2d:40:92:6e:9c:35:62:fd:77:96:6c:9f:df: + 05:30:95:6b:e4:6c:02:65:fe:44:b0:3f:bb:c0:99:f4:8f:79: + aa:2f:64:4d:d3:c0:84:1c:4b:c6:a8:8d:ac:d3:2a:17:45:56: + 0d:31:40:3d:cb:2f:e8:74:68:18:92:10:57:08:ad:31:26:ea: + e4:bf:7f:a1:be:95:f1:84:46:27:8c:77:7a:0e:3a:dc:05:9a: + 69:8c:72:6a:ee:ca:e2:d7:e0:73:fb:00:8a:10:62:5d:3e:45: + e5:59:eb:be:91:b1:a7:5e:27:7e:49:39:31:e1:5a:ee:e1:ba: + 39:d4:8d:d7:b7:77:3a:31:f4:82:7d:a6:c5:dd:92:03:60:75: + 1c:7e:91:9d +-----BEGIN CERTIFICATE----- +MIIDJDCCAgygAwIBAgIQDd9FiAard6otlQ8fRt1irDANBgkqhkiG9w0BAQsFADA0 +MTIwMAYDVQQDEylJbnRlcm1lZGlhdGUgZm9yIGJ5dGUgZXF1YWxpdHkgY29tcGFy +aXNvbjAeFw0xMDAxMDEwNjAwMDBaFw0zMjEyMDEwNjAwMDBaMCwxKjAoBgNVBAMT +IUxlYWYgZm9yIGJ5dGUgZXF1YWxpdHkgY29tcGFyaXNvbjCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAM0S0xeznPuxYPsdycnw3I/vNgTdpNjFVzks4dYW +SDcT94IWytvv0cduoPO7vkEOJLIzsbc1g5IrCTFOJJss/eG+CZXhPxYPtjDBDUR3 +UNog/6pIgABnF/6qPk22AuT1EbXMMS93D0SwN3hO/+xiZA+UiqGJw3afA73Q4io2 +7PpZUfVXfeGVpPujPIebZXlot5E4/XqziamWhSL3OJxgUr4f94vBaNPqlh4TKgRO +ujOsB+rZU2fHuBXpHsqSTZFP0NgRNJuL9QBwe6caQ6KQGlRfNOF5LnJlT2ZJ+rlx +b0uhc3nugEIYa7upubrEFqYEdMxgaG8ObksBJZzDy1hz7fkCAwEAAaM6MDgwHQYD +VR0RBBYwFIIMZXhhbXBsZS50ZXN0hwR/AAABMBcGA1UdIAQQMA4wDAYKKwYBBAHW +eQIEATANBgkqhkiG9w0BAQsFAAOCAQEAXgooyHWIYCCdZCl8Je4ItMZEzd8VuGaI +jiB8NWOBplxvT0rRuSE81UWkWb85a/AGW0Y73MaPYH72wcpqwO8/rNkrMsjfOIKh +p2+m67UMBP68TFZAhCPkVlSL7WNdLuB2hBboqqgu5kWjE5bE4uYmHOEtQJJunDVi +/XeWbJ/fBTCVa+RsAmX+RLA/u8CZ9I95qi9kTdPAhBxLxqiNrNMqF0VWDTFAPcsv +6HRoGJIQVwitMSbq5L9/ob6V8YRGJ4x3eg463AWaaYxyau7K4tfgc/sAihBiXT5F +5VnrvpGxp14nfkk5MeFa7uG6OdSN17d3OjH0gn2mxd2SA2B1HH6RnQ== +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 72:9a:5b:30:b2:f1:2a:96:49:3d:14:29:21:81:7c:76 + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN = Testing CA + Validity + Not Before: Jan 1 06:00:00 2010 GMT + Not After : Dec 1 06:00:00 2032 GMT + Subject: CN = Intermediate for byte equality comparison + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:c6:61:af:cc:65:9f:88:85:5a:83:ad:e8:fb:79: + 2d:c1:3d:0c:f3:88:b1:7b:ec:e9:14:9c:f0:b8:55: + 6d:27:b1:91:01:d0:81:fb:2a:84:2d:13:a2:ac:95: + d8:30:8d:dd:66:78:38:43:ec:c5:80:65:13:95:9e: + b6:b3:0d:d6:9b:28:45:d9:7e:10:d0:bb:bf:65:3d: + 68:6d:c8:82:89:35:02:2c:c9:6f:9e:03:0b:56:71: + 57:25:7d:3d:65:26:73:40:80:bb:97:27:ce:e0:d3: + 0f:42:09:d5:82:0e:1d:66:2f:35:8f:c7:89:c0:e9: + 36:6d:84:f8:9a:df:1b:eb:8d:84:3f:74:e6:f3:25: + 87:6a:c3:5d:5c:11:69:1f:cb:29:69:67:c0:6e:df: + 69:45:0c:16:bb:23:14:c1:45:99:fe:90:72:5d:5e: + c9:0f:2d:b6:69:8a:fa:e7:2b:ba:0c:fb:f7:79:67: + c7:e8:b4:9f:21:72:f9:38:18:27:c2:7a:b7:f9:47: + 1c:62:bd:8d:a4:a6:c6:57:96:6e:c1:38:5c:f4:1d: + 73:94:49:83:58:88:f3:0d:64:97:16:19:dc:d3:80: + 40:8c:d7:4f:25:c3:be:19:83:3a:92:62:0c:9c:f7: + 10:da:67:e1:5a:c8:ce:f6:9b:c7:e4:e5:e7:f8:13: + c1:ed + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.11129.2.4.1 + + Signature Algorithm: sha256WithRSAEncryption + 83:05:f4:0a:38:98:70:fb:ca:39:a5:e6:e1:52:06:d9:8e:83: + 54:34:10:86:d6:47:d5:0d:42:a8:5c:ec:f7:e4:ad:d3:30:7f: + 96:38:c7:15:b7:0c:e6:05:9f:a1:b7:e6:2a:2b:c9:b2:b7:27: + 67:85:5f:b1:2c:e8:71:88:00:92:9d:2b:6f:d2:0f:8a:f1:d7: + 95:ac:f5:01:16:11:31:36:63:f6:4a:ee:50:96:3c:af:69:f0: + 63:34:dc:6e:73:b2:e2:3c:64:d6:62:98:04:98:52:4a:30:67: + 33:21:5a:c0:27:ff:3d:7b:69:a2:d2:c2:be:26:43:37:21:f6: + 50:5f:e3:cf:a2:8e:4e:1d:dc:5b:e4:42:44:14:96:8f:c6:cd: + a6:59:9d:56:f9:49:09:eb:3c:46:12:5a:73:b2:f9:9c:7f:2d: + d4:05:0d:db:ec:0f:08:1f:83:af:44:01:e3:8b:4a:45:ff:f7: + ee:f1:b1:9f:f6:14:f6:0f:82:e3:fa:c9:e9:62:28:27:18:8e: + 62:d7:ba:50:91:96:fc:2d:fa:b0:32:16:a2:eb:0f:bf:ea:a9: + 66:d7:f1:9f:7e:3d:5a:ab:89:6e:40:be:d1:0f:a8:ed:60:60: + c0:82:4e:cb:34:f7:63:6c:b4:1e:fb:78:c9:13:f0:77:5d:25: + d9:ac:f8:97 +-----BEGIN CERTIFICATE----- +MIIC/zCCAeegAwIBAgIQcppbMLLxKpZJPRQpIYF8djANBgkqhkiG9w0BAQsFADAV +MRMwEQYDVQQDEwpUZXN0aW5nIENBMB4XDTEwMDEwMTA2MDAwMFoXDTMyMTIwMTA2 +MDAwMFowNDEyMDAGA1UEAxMpSW50ZXJtZWRpYXRlIGZvciBieXRlIGVxdWFsaXR5 +IGNvbXBhcmlzb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGYa/M +ZZ+IhVqDrej7eS3BPQzziLF77OkUnPC4VW0nsZEB0IH7KoQtE6Ksldgwjd1meDhD +7MWAZROVnrazDdabKEXZfhDQu79lPWhtyIKJNQIsyW+eAwtWcVclfT1lJnNAgLuX +J87g0w9CCdWCDh1mLzWPx4nA6TZthPia3xvrjYQ/dObzJYdqw11cEWkfyylpZ8Bu +32lFDBa7IxTBRZn+kHJdXskPLbZpivrnK7oM+/d5Z8fotJ8hcvk4GCfCerf5Rxxi +vY2kpsZXlm7BOFz0HXOUSYNYiPMNZJcWGdzTgECM108lw74ZgzqSYgyc9xDaZ+Fa +yM72m8fk5ef4E8HtAgMBAAGjLDAqMA8GA1UdEwEB/wQFMAMBAf8wFwYDVR0gBBAw +DjAMBgorBgEEAdZ5AgQBMA0GCSqGSIb3DQEBCwUAA4IBAQCDBfQKOJhw+8o5pebh +UgbZjoNUNBCG1kfVDUKoXOz35K3TMH+WOMcVtwzmBZ+ht+YqK8mytydnhV+xLOhx +iACSnStv0g+K8deVrPUBFhExNmP2Su5QljyvafBjNNxuc7LiPGTWYpgEmFJKMGcz +IVrAJ/89e2mi0sK+JkM3IfZQX+PPoo5OHdxb5EJEFJaPxs2mWZ1W+UkJ6zxGElpz +svmcfy3UBQ3b7A8IH4OvRAHji0pF//fu8bGf9hT2D4Lj+snpYignGI5i17pQkZb8 +LfqwMhai6w+/6qlm1/Gffj1aq4luQL7RD6jtYGDAgk7LNPdjbLQe+3jJE/B3XSXZ +rPiX +-----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/name-normalization-case-folding.pem b/net/data/ssl/certificates/name-normalization-case-folding.pem new file mode 100644 index 0000000..68bff24c --- /dev/null +++ b/net/data/ssl/certificates/name-normalization-case-folding.pem
@@ -0,0 +1,151 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + ae:42:1e:0d:b1:00:6a:69:30:b1:86:8d:07:dc:40:79 + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN = intermediate for case folding comparison + Validity + Not Before: Jan 1 06:00:00 2010 GMT + Not After : Dec 1 06:00:00 2032 GMT + Subject: CN = Leaf for case folding comparison + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:cd:12:d3:17:b3:9c:fb:b1:60:fb:1d:c9:c9:f0: + dc:8f:ef:36:04:dd:a4:d8:c5:57:39:2c:e1:d6:16: + 48:37:13:f7:82:16:ca:db:ef:d1:c7:6e:a0:f3:bb: + be:41:0e:24:b2:33:b1:b7:35:83:92:2b:09:31:4e: + 24:9b:2c:fd:e1:be:09:95:e1:3f:16:0f:b6:30:c1: + 0d:44:77:50:da:20:ff:aa:48:80:00:67:17:fe:aa: + 3e:4d:b6:02:e4:f5:11:b5:cc:31:2f:77:0f:44:b0: + 37:78:4e:ff:ec:62:64:0f:94:8a:a1:89:c3:76:9f: + 03:bd:d0:e2:2a:36:ec:fa:59:51:f5:57:7d:e1:95: + a4:fb:a3:3c:87:9b:65:79:68:b7:91:38:fd:7a:b3: + 89:a9:96:85:22:f7:38:9c:60:52:be:1f:f7:8b:c1: + 68:d3:ea:96:1e:13:2a:04:4e:ba:33:ac:07:ea:d9: + 53:67:c7:b8:15:e9:1e:ca:92:4d:91:4f:d0:d8:11: + 34:9b:8b:f5:00:70:7b:a7:1a:43:a2:90:1a:54:5f: + 34:e1:79:2e:72:65:4f:66:49:fa:b9:71:6f:4b:a1: + 73:79:ee:80:42:18:6b:bb:a9:b9:ba:c4:16:a6:04: + 74:cc:60:68:6f:0e:6e:4b:01:25:9c:c3:cb:58:73: + ed:f9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:example.test, IP Address:127.0.0.1 + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.11129.2.4.1 + + Signature Algorithm: sha256WithRSAEncryption + 55:e5:e4:83:89:65:9f:e3:1c:dd:7a:cc:df:36:8f:b8:13:09: + f2:12:2c:1a:cc:c6:7f:4b:a0:a8:c9:5d:d2:16:d6:97:db:c6: + 99:4e:44:68:bc:7e:d0:6c:8d:56:6c:86:a3:cd:af:42:da:d3: + 0b:e5:f9:22:9d:aa:c8:e1:71:39:a3:36:68:19:d1:b5:f1:7e: + bc:23:9b:fc:ea:ee:a7:8c:0d:3d:e8:ff:4b:9f:46:b9:d9:7a: + 9a:77:40:d7:fa:63:76:52:61:64:f2:a2:8c:2a:61:83:d9:aa: + 37:6c:db:a4:a2:2d:41:03:cc:5a:3c:09:6c:2e:10:5d:82:4d: + 25:61:ad:12:21:4b:83:f2:6b:e1:4b:dd:3f:c1:e2:4f:32:f1: + 72:cd:cc:49:cb:33:c5:bf:b4:78:07:13:83:b6:9f:eb:c8:11: + b7:90:17:54:90:1b:df:0d:a5:76:8c:f8:68:ec:b9:c1:6f:7a: + 70:86:8a:10:e0:41:2c:c1:e1:c6:f8:9e:12:40:f4:87:2b:4e: + 5a:88:b1:06:f8:52:6a:54:0b:78:b1:97:b4:bf:0e:bf:45:92: + 1f:2f:b1:2e:87:11:e3:b7:02:fe:fa:cb:8e:a2:10:f1:10:5d: + 05:56:03:ba:9b:8c:39:b3:d7:29:cf:58:c7:f0:ed:87:15:29: + d3:8f:9e:92 +-----BEGIN CERTIFICATE----- +MIIDIzCCAgugAwIBAgIRAK5CHg2xAGppMLGGjQfcQHkwDQYJKoZIhvcNAQELBQAw +MzExMC8GA1UEAxMoaW50ZXJtZWRpYXRlIGZvciBjYXNlIGZvbGRpbmcgY29tcGFy +aXNvbjAeFw0xMDAxMDEwNjAwMDBaFw0zMjEyMDEwNjAwMDBaMCsxKTAnBgNVBAMT +IExlYWYgZm9yIGNhc2UgZm9sZGluZyBjb21wYXJpc29uMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAzRLTF7Oc+7Fg+x3JyfDcj+82BN2k2MVXOSzh1hZI +NxP3ghbK2+/Rx26g87u+QQ4ksjOxtzWDkisJMU4kmyz94b4JleE/Fg+2MMENRHdQ +2iD/qkiAAGcX/qo+TbYC5PURtcwxL3cPRLA3eE7/7GJkD5SKoYnDdp8DvdDiKjbs ++llR9Vd94ZWk+6M8h5tleWi3kTj9erOJqZaFIvc4nGBSvh/3i8Fo0+qWHhMqBE66 +M6wH6tlTZ8e4FekeypJNkU/Q2BE0m4v1AHB7pxpDopAaVF804XkucmVPZkn6uXFv +S6Fzee6AQhhru6m5usQWpgR0zGBobw5uSwElnMPLWHPt+QIDAQABozowODAdBgNV +HREEFjAUggxleGFtcGxlLnRlc3SHBH8AAAEwFwYDVR0gBBAwDjAMBgorBgEEAdZ5 +AgQBMA0GCSqGSIb3DQEBCwUAA4IBAQBV5eSDiWWf4xzdeszfNo+4EwnyEiwazMZ/ +S6CoyV3SFtaX28aZTkRovH7QbI1WbIajza9C2tML5fkinarI4XE5ozZoGdG18X68 +I5v86u6njA096P9Ln0a52Xqad0DX+mN2UmFk8qKMKmGD2ao3bNukoi1BA8xaPAls +LhBdgk0lYa0SIUuD8mvhS90/weJPMvFyzcxJyzPFv7R4BxODtp/ryBG3kBdUkBvf +DaV2jPho7LnBb3pwhooQ4EEsweHG+J4SQPSHK05aiLEG+FJqVAt4sZe0vw6/RZIf +L7EuhxHjtwL++suOohDxEF0FVgO6m4w5s9cpz1jH8O2HFSnTj56S +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 09:cc:53:82:46:23:f7:28:e0:96:73:86:c4:50:79:9e + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN = Testing CA + Validity + Not Before: Jan 1 06:00:00 2010 GMT + Not After : Dec 1 06:00:00 2032 GMT + Subject: CN = Intermediate for case folding comparison + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:c6:61:af:cc:65:9f:88:85:5a:83:ad:e8:fb:79: + 2d:c1:3d:0c:f3:88:b1:7b:ec:e9:14:9c:f0:b8:55: + 6d:27:b1:91:01:d0:81:fb:2a:84:2d:13:a2:ac:95: + d8:30:8d:dd:66:78:38:43:ec:c5:80:65:13:95:9e: + b6:b3:0d:d6:9b:28:45:d9:7e:10:d0:bb:bf:65:3d: + 68:6d:c8:82:89:35:02:2c:c9:6f:9e:03:0b:56:71: + 57:25:7d:3d:65:26:73:40:80:bb:97:27:ce:e0:d3: + 0f:42:09:d5:82:0e:1d:66:2f:35:8f:c7:89:c0:e9: + 36:6d:84:f8:9a:df:1b:eb:8d:84:3f:74:e6:f3:25: + 87:6a:c3:5d:5c:11:69:1f:cb:29:69:67:c0:6e:df: + 69:45:0c:16:bb:23:14:c1:45:99:fe:90:72:5d:5e: + c9:0f:2d:b6:69:8a:fa:e7:2b:ba:0c:fb:f7:79:67: + c7:e8:b4:9f:21:72:f9:38:18:27:c2:7a:b7:f9:47: + 1c:62:bd:8d:a4:a6:c6:57:96:6e:c1:38:5c:f4:1d: + 73:94:49:83:58:88:f3:0d:64:97:16:19:dc:d3:80: + 40:8c:d7:4f:25:c3:be:19:83:3a:92:62:0c:9c:f7: + 10:da:67:e1:5a:c8:ce:f6:9b:c7:e4:e5:e7:f8:13: + c1:ed + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.11129.2.4.1 + + Signature Algorithm: sha256WithRSAEncryption + b8:e0:27:8e:6f:76:22:82:5d:d6:aa:9c:f1:8d:f2:67:be:d5: + 57:e9:79:a2:1f:a0:e7:20:e8:f8:c6:d9:8e:60:4d:57:22:9a: + bb:bc:10:d2:7e:6a:73:52:7c:b8:04:50:91:db:2d:31:db:da: + ba:0b:28:93:3d:2a:3d:78:1f:23:f6:df:46:a6:25:be:22:b2: + 7d:fb:5c:97:fc:80:f1:86:69:0a:f8:29:90:5e:5f:61:bc:dc: + 03:5c:6e:6e:46:f9:61:5c:51:33:dd:04:fa:bf:20:da:fc:b9: + 0c:15:12:8d:c1:ae:57:d4:15:bc:b4:01:be:86:5e:03:e2:6e: + a9:39:7a:a9:37:44:f1:19:dd:5b:21:2c:ba:6b:d1:12:52:31: + a1:58:c8:0f:d5:8c:db:10:44:7d:73:be:97:5f:0e:6a:88:1c: + da:cc:71:d6:f0:68:34:e4:94:9a:cd:4c:a0:51:86:6d:ef:e4: + b4:29:39:2a:48:0c:5b:ad:c8:86:90:be:73:8d:3b:be:5e:a6: + 17:7a:98:6b:0a:7b:89:00:e3:7f:f7:db:0a:29:13:23:7a:bc: + 01:4d:f6:b0:59:60:1b:b7:91:d1:ec:e9:44:42:85:3d:8f:db: + 64:d0:72:45:98:11:8f:2d:5b:81:ff:00:99:67:00:e3:3d:10: + f4:fa:d0:7e +-----BEGIN CERTIFICATE----- +MIIC/jCCAeagAwIBAgIQCcxTgkYj9yjglnOGxFB5njANBgkqhkiG9w0BAQsFADAV +MRMwEQYDVQQDEwpUZXN0aW5nIENBMB4XDTEwMDEwMTA2MDAwMFoXDTMyMTIwMTA2 +MDAwMFowMzExMC8GA1UEAxMoSW50ZXJtZWRpYXRlIGZvciBjYXNlIGZvbGRpbmcg +Y29tcGFyaXNvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMZhr8xl +n4iFWoOt6Pt5LcE9DPOIsXvs6RSc8LhVbSexkQHQgfsqhC0ToqyV2DCN3WZ4OEPs +xYBlE5WetrMN1psoRdl+ENC7v2U9aG3Igok1AizJb54DC1ZxVyV9PWUmc0CAu5cn +zuDTD0IJ1YIOHWYvNY/HicDpNm2E+JrfG+uNhD905vMlh2rDXVwRaR/LKWlnwG7f +aUUMFrsjFMFFmf6Qcl1eyQ8ttmmK+ucrugz793lnx+i0nyFy+TgYJ8J6t/lHHGK9 +jaSmxleWbsE4XPQdc5RJg1iI8w1klxYZ3NOAQIzXTyXDvhmDOpJiDJz3ENpn4VrI +zvabx+Tl5/gTwe0CAwEAAaMsMCowDwYDVR0TAQH/BAUwAwEB/zAXBgNVHSAEEDAO +MAwGCisGAQQB1nkCBAEwDQYJKoZIhvcNAQELBQADggEBALjgJ45vdiKCXdaqnPGN +8me+1VfpeaIfoOcg6PjG2Y5gTVcimru8ENJ+anNSfLgEUJHbLTHb2roLKJM9Kj14 +HyP230amJb4isn37XJf8gPGGaQr4KZBeX2G83ANcbm5G+WFcUTPdBPq/INr8uQwV +Eo3BrlfUFby0Ab6GXgPibqk5eqk3RPEZ3VshLLpr0RJSMaFYyA/VjNsQRH1zvpdf +DmqIHNrMcdbwaDTklJrNTKBRhm3v5LQpOSpIDFutyIaQvnONO75ephd6mGsKe4kA +43/32wopEyN6vAFN9rBZYBu3kdHs6URChT2P22TQckWYEY8tW4H/AJlnAOM9EPT6 +0H4= +-----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/name-normalization-printable-utf8.pem b/net/data/ssl/certificates/name-normalization-printable-utf8.pem new file mode 100644 index 0000000..9025915 --- /dev/null +++ b/net/data/ssl/certificates/name-normalization-printable-utf8.pem
@@ -0,0 +1,152 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 5d:87:b7:b3:20:ca:71:41:44:3a:a4:68:71:bd:c6:ac + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN = Intermediate for PrintableString / Utf8String comparison + Validity + Not Before: Jan 1 06:00:00 2010 GMT + Not After : Dec 1 06:00:00 2032 GMT + Subject: CN = Leaf for PrintableString / Utf8String comparison + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:cd:12:d3:17:b3:9c:fb:b1:60:fb:1d:c9:c9:f0: + dc:8f:ef:36:04:dd:a4:d8:c5:57:39:2c:e1:d6:16: + 48:37:13:f7:82:16:ca:db:ef:d1:c7:6e:a0:f3:bb: + be:41:0e:24:b2:33:b1:b7:35:83:92:2b:09:31:4e: + 24:9b:2c:fd:e1:be:09:95:e1:3f:16:0f:b6:30:c1: + 0d:44:77:50:da:20:ff:aa:48:80:00:67:17:fe:aa: + 3e:4d:b6:02:e4:f5:11:b5:cc:31:2f:77:0f:44:b0: + 37:78:4e:ff:ec:62:64:0f:94:8a:a1:89:c3:76:9f: + 03:bd:d0:e2:2a:36:ec:fa:59:51:f5:57:7d:e1:95: + a4:fb:a3:3c:87:9b:65:79:68:b7:91:38:fd:7a:b3: + 89:a9:96:85:22:f7:38:9c:60:52:be:1f:f7:8b:c1: + 68:d3:ea:96:1e:13:2a:04:4e:ba:33:ac:07:ea:d9: + 53:67:c7:b8:15:e9:1e:ca:92:4d:91:4f:d0:d8:11: + 34:9b:8b:f5:00:70:7b:a7:1a:43:a2:90:1a:54:5f: + 34:e1:79:2e:72:65:4f:66:49:fa:b9:71:6f:4b:a1: + 73:79:ee:80:42:18:6b:bb:a9:b9:ba:c4:16:a6:04: + 74:cc:60:68:6f:0e:6e:4b:01:25:9c:c3:cb:58:73: + ed:f9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:example.test, IP Address:127.0.0.1 + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.11129.2.4.1 + + Signature Algorithm: sha256WithRSAEncryption + 7c:35:51:8f:20:b1:2d:30:8a:0c:6b:ed:16:22:a1:ac:eb:4d: + 6f:ff:fa:1e:1a:45:a5:84:92:fe:80:8d:fa:1f:b0:ca:5e:6e: + 0a:d9:d7:a8:e4:2b:5c:31:40:34:31:dd:0c:bd:2d:74:f2:b5: + 4f:ea:f7:5f:99:52:cc:47:b7:28:a2:f1:2f:55:66:42:05:6b: + 48:f7:83:52:37:67:04:3b:32:e3:dc:18:5a:33:fe:12:0e:1d: + b4:81:62:3e:61:06:d1:57:90:9f:17:cf:50:5e:6d:97:5d:ec: + ad:9f:85:c0:19:72:94:64:0c:2a:28:a2:26:4a:81:2e:c4:48: + 38:37:d2:1e:39:cf:b9:c0:f7:89:2f:42:22:5b:6d:66:a7:5b: + 4a:bc:59:91:80:a8:bd:88:6e:4b:58:ec:ca:28:fa:2e:e3:54: + dc:df:f3:c4:d0:cd:48:8c:ed:62:4a:f3:30:52:8b:c3:55:de: + fd:f5:50:13:4e:10:ed:31:5a:c1:7d:3a:d9:c4:a8:f2:b5:19: + 1f:8c:32:48:42:0e:2c:da:a1:16:23:84:49:a9:c3:87:fe:75: + a1:f3:61:49:70:60:66:29:10:cb:4c:48:c2:4d:1e:c0:8a:c4: + 12:dd:ee:74:1c:b7:ff:9d:0d:04:36:d0:e4:0f:98:78:7e:e7: + e7:22:8b:32 +-----BEGIN CERTIFICATE----- +MIIDQjCCAiqgAwIBAgIQXYe3syDKcUFEOqRocb3GrDANBgkqhkiG9w0BAQsFADBD +MUEwPwYDVQQDEzhJbnRlcm1lZGlhdGUgZm9yIFByaW50YWJsZVN0cmluZyAvIFV0 +ZjhTdHJpbmcgY29tcGFyaXNvbjAeFw0xMDAxMDEwNjAwMDBaFw0zMjEyMDEwNjAw +MDBaMDsxOTA3BgNVBAMTMExlYWYgZm9yIFByaW50YWJsZVN0cmluZyAvIFV0ZjhT +dHJpbmcgY29tcGFyaXNvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AM0S0xeznPuxYPsdycnw3I/vNgTdpNjFVzks4dYWSDcT94IWytvv0cduoPO7vkEO +JLIzsbc1g5IrCTFOJJss/eG+CZXhPxYPtjDBDUR3UNog/6pIgABnF/6qPk22AuT1 +EbXMMS93D0SwN3hO/+xiZA+UiqGJw3afA73Q4io27PpZUfVXfeGVpPujPIebZXlo +t5E4/XqziamWhSL3OJxgUr4f94vBaNPqlh4TKgROujOsB+rZU2fHuBXpHsqSTZFP +0NgRNJuL9QBwe6caQ6KQGlRfNOF5LnJlT2ZJ+rlxb0uhc3nugEIYa7upubrEFqYE +dMxgaG8ObksBJZzDy1hz7fkCAwEAAaM6MDgwHQYDVR0RBBYwFIIMZXhhbXBsZS50 +ZXN0hwR/AAABMBcGA1UdIAQQMA4wDAYKKwYBBAHWeQIEATANBgkqhkiG9w0BAQsF +AAOCAQEAfDVRjyCxLTCKDGvtFiKhrOtNb//6HhpFpYSS/oCN+h+wyl5uCtnXqOQr +XDFANDHdDL0tdPK1T+r3X5lSzEe3KKLxL1VmQgVrSPeDUjdnBDsy49wYWjP+Eg4d +tIFiPmEG0VeQnxfPUF5tl13srZ+FwBlylGQMKiiiJkqBLsRIODfSHjnPucD3iS9C +IlttZqdbSrxZkYCovYhuS1jsyij6LuNU3N/zxNDNSIztYkrzMFKLw1Xe/fVQE04Q +7TFawX062cSo8rUZH4wySEIOLNqhFiOESanDh/51ofNhSXBgZikQy0xIwk0ewIrE +Et3udBy3/50NBDbQ5A+YeH7n5yKLMg== +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 47:dd:b9:fa:88:2a:f7:c2:8a:00:52:f2:07:7b:73:a4 + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN = Testing CA + Validity + Not Before: Jan 1 06:00:00 2010 GMT + Not After : Dec 1 06:00:00 2032 GMT + Subject: CN = Intermediate for PrintableString / Utf8String comparison + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:c6:61:af:cc:65:9f:88:85:5a:83:ad:e8:fb:79: + 2d:c1:3d:0c:f3:88:b1:7b:ec:e9:14:9c:f0:b8:55: + 6d:27:b1:91:01:d0:81:fb:2a:84:2d:13:a2:ac:95: + d8:30:8d:dd:66:78:38:43:ec:c5:80:65:13:95:9e: + b6:b3:0d:d6:9b:28:45:d9:7e:10:d0:bb:bf:65:3d: + 68:6d:c8:82:89:35:02:2c:c9:6f:9e:03:0b:56:71: + 57:25:7d:3d:65:26:73:40:80:bb:97:27:ce:e0:d3: + 0f:42:09:d5:82:0e:1d:66:2f:35:8f:c7:89:c0:e9: + 36:6d:84:f8:9a:df:1b:eb:8d:84:3f:74:e6:f3:25: + 87:6a:c3:5d:5c:11:69:1f:cb:29:69:67:c0:6e:df: + 69:45:0c:16:bb:23:14:c1:45:99:fe:90:72:5d:5e: + c9:0f:2d:b6:69:8a:fa:e7:2b:ba:0c:fb:f7:79:67: + c7:e8:b4:9f:21:72:f9:38:18:27:c2:7a:b7:f9:47: + 1c:62:bd:8d:a4:a6:c6:57:96:6e:c1:38:5c:f4:1d: + 73:94:49:83:58:88:f3:0d:64:97:16:19:dc:d3:80: + 40:8c:d7:4f:25:c3:be:19:83:3a:92:62:0c:9c:f7: + 10:da:67:e1:5a:c8:ce:f6:9b:c7:e4:e5:e7:f8:13: + c1:ed + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.11129.2.4.1 + + Signature Algorithm: sha256WithRSAEncryption + 7d:86:2f:d6:61:32:cf:65:91:bb:45:d6:db:53:bc:2c:56:26: + 3f:7e:4b:fe:a9:b1:36:ae:68:18:7f:c9:8e:1e:c6:f6:c6:b8: + eb:17:6e:fc:86:74:39:a5:fb:f4:a8:66:ed:25:66:ed:ec:42: + 8b:5a:80:8e:bf:cf:c4:ba:a8:f1:af:45:52:05:fc:2d:e7:4d: + 0e:4c:5f:18:ff:78:09:69:a4:24:a0:66:48:1d:c7:d3:fa:29: + 97:00:58:ae:9c:d8:02:4d:57:37:e1:32:e0:27:0a:04:8f:69: + aa:5d:96:30:4d:70:0e:e4:f0:e1:58:38:cc:ab:34:ab:c3:02: + 80:75:69:d3:2c:78:5d:9c:79:6e:4c:6a:32:b1:33:59:99:54: + 9e:7f:1f:d2:02:b6:8f:79:37:ea:d3:9e:51:d7:5e:cc:e6:56: + e5:d3:93:20:10:80:a9:41:79:00:d2:59:49:4b:95:b9:fa:ef: + 85:9f:9d:49:81:07:49:31:e5:db:2b:5e:0d:1b:50:64:86:8e: + 50:4b:0a:d0:cd:82:b0:82:bb:ee:0c:ff:18:e1:a7:24:b5:cf: + 9e:0b:c4:2f:28:81:af:53:fb:66:ad:57:0f:7f:0f:07:40:5b: + 75:46:fd:08:8e:0d:8d:e9:c4:6a:ca:ec:19:d2:98:fd:a7:10: + b1:24:81:43 +-----BEGIN CERTIFICATE----- +MIIDDjCCAfagAwIBAgIQR925+ogq98KKAFLyB3tzpDANBgkqhkiG9w0BAQsFADAV +MRMwEQYDVQQDEwpUZXN0aW5nIENBMB4XDTEwMDEwMTA2MDAwMFoXDTMyMTIwMTA2 +MDAwMFowQzFBMD8GA1UEAww4SW50ZXJtZWRpYXRlIGZvciBQcmludGFibGVTdHJp +bmcgLyBVdGY4U3RyaW5nIGNvbXBhcmlzb24wggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDGYa/MZZ+IhVqDrej7eS3BPQzziLF77OkUnPC4VW0nsZEB0IH7 +KoQtE6Ksldgwjd1meDhD7MWAZROVnrazDdabKEXZfhDQu79lPWhtyIKJNQIsyW+e +AwtWcVclfT1lJnNAgLuXJ87g0w9CCdWCDh1mLzWPx4nA6TZthPia3xvrjYQ/dObz +JYdqw11cEWkfyylpZ8Bu32lFDBa7IxTBRZn+kHJdXskPLbZpivrnK7oM+/d5Z8fo +tJ8hcvk4GCfCerf5RxxivY2kpsZXlm7BOFz0HXOUSYNYiPMNZJcWGdzTgECM108l +w74ZgzqSYgyc9xDaZ+FayM72m8fk5ef4E8HtAgMBAAGjLDAqMA8GA1UdEwEB/wQF +MAMBAf8wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgQBMA0GCSqGSIb3DQEBCwUAA4IB +AQB9hi/WYTLPZZG7RdbbU7wsViY/fkv+qbE2rmgYf8mOHsb2xrjrF278hnQ5pfv0 +qGbtJWbt7EKLWoCOv8/Euqjxr0VSBfwt500OTF8Y/3gJaaQkoGZIHcfT+imXAFiu +nNgCTVc34TLgJwoEj2mqXZYwTXAO5PDhWDjMqzSrwwKAdWnTLHhdnHluTGoysTNZ +mVSefx/SAraPeTfq055R117M5lbl05MgEICpQXkA0llJS5W5+u+Fn51JgQdJMeXb +K14NG1Bkho5QSwrQzYKwgrvuDP8Y4acktc+eC8QvKIGvU/tmrVcPfw8HQFt1Rv0I +jg2N6cRqyuwZ0pj9pxCxJIFD +-----END CERTIFICATE-----
diff --git a/net/data/ssl/scripts/generate-name-normalization-certs.py b/net/data/ssl/scripts/generate-name-normalization-certs.py new file mode 100755 index 0000000..06429c1 --- /dev/null +++ b/net/data/ssl/scripts/generate-name-normalization-certs.py
@@ -0,0 +1,98 @@ +#!/usr/bin/env python2.7 +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +'''Generates certificate chains for testing name normalization.''' + +import os +import subprocess +import sys + +sys.path.append(os.path.join('..', '..', '..', 'tools', 'testserver')) +import minica + + +def pretty_print_cert(der): + command = ["openssl", "x509", "-text", "-inform", "DER"] + p = subprocess.Popen(command, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE) + result = p.communicate(der) + if p.returncode != 0: + raise RuntimeError("openssl failed: %s" % p.returncode) + return result[0] + + +def writecerts(name, der_certs): + fn = os.path.join('..', 'certificates', name) + + text_certs = [] + print 'pretty printing', fn + for der in der_certs: + text_certs.append(pretty_print_cert(der)) + + print 'writing', fn + with open(fn, 'w') as f: + f.write('\n'.join(text_certs)) + + +def GenerateCertAndIntermediate(leaf_subject, + leaf_issuer, + intermediate_subject, + ip_sans=None, + dns_sans=None, + serial=0): + if serial == 0: + serial = minica.RandomNumber(16) + + intermediate_serial = minica.RandomNumber(16) + + target_cert_der = minica.MakeCertificate( + leaf_issuer, leaf_subject, serial, minica.LEAF_KEY, + minica.INTERMEDIATE_KEY, ip_sans=ip_sans, dns_sans=dns_sans) + + intermediate_cert_der = minica.MakeCertificate( + minica.ROOT_CN, intermediate_subject, intermediate_serial, + minica.INTERMEDIATE_KEY, minica.ROOT_KEY, is_ca=True) + + return [target_cert_der, intermediate_cert_der] + + +def GeneratePrintableStringUtf8StringChain(): + namesuffix = " for PrintableString / Utf8String comparison" + issuer_name = "Intermediate" + namesuffix + certs = GenerateCertAndIntermediate(leaf_subject="Leaf" + namesuffix, + leaf_issuer=issuer_name, + intermediate_subject=unicode(issuer_name), + ip_sans=["\x7F\x00\x00\x01"], + dns_sans=["example.test"]) + writecerts('name-normalization-printable-utf8.pem', certs) + + +def GenerateCaseFoldChain(): + namesuffix = " for case folding comparison" + issuer_name = "Intermediate" + namesuffix + certs = GenerateCertAndIntermediate(leaf_subject="Leaf" + namesuffix, + leaf_issuer=issuer_name.replace('I', 'i'), + intermediate_subject=issuer_name, + ip_sans=["\x7F\x00\x00\x01"], + dns_sans=["example.test"]) + writecerts('name-normalization-case-folding.pem', certs) + + +def GenerateNormalChain(): + namesuffix = " for byte equality comparison" + issuer_name = "Intermediate" + namesuffix + certs = GenerateCertAndIntermediate(leaf_subject="Leaf" + namesuffix, + leaf_issuer=issuer_name, + intermediate_subject=issuer_name, + ip_sans=["\x7F\x00\x00\x01"], + dns_sans=["example.test"]) + writecerts('name-normalization-byteequal.pem', certs) + + +if __name__ == '__main__': + GeneratePrintableStringUtf8StringChain() + GenerateCaseFoldChain() + GenerateNormalChain()
diff --git a/net/tools/testserver/asn1.py b/net/tools/testserver/asn1.py index c0e0398..167b08d3 100644 --- a/net/tools/testserver/asn1.py +++ b/net/tools/testserver/asn1.py
@@ -15,6 +15,10 @@ if type(obj) == types.StringType: # Strings are PRINTABLESTRING return TagAndLength(19, len(obj)) + obj + if type(obj) == types.UnicodeType: + # Encode Unicode strings as UTF8String. + utf8val = obj.encode('utf-8') + return TagAndLength(12, len(utf8val)) + utf8val if type(obj) == types.BooleanType: val = "\x00" if obj:
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 04937ef..f04a67e 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -10938,7 +10938,7 @@ scoped_refptr<X509Certificate> root_cert = ImportCertFromFile(GetTestCertsDirectory(), "ocsp-test-root.pem"); - CHECK_NE(static_cast<X509Certificate*>(nullptr), root_cert.get()); + ASSERT_TRUE(root_cert); test_root_.reset(new ScopedTestRoot(root_cert.get())); #if defined(USE_NSS_CERTS)
diff --git a/services/network/cors/cors_url_loader_factory.h b/services/network/cors/cors_url_loader_factory.h index 89616115..5fe64e8 100644 --- a/services/network/cors/cors_url_loader_factory.h +++ b/services/network/cors/cors_url_loader_factory.h
@@ -54,6 +54,8 @@ // URLLoaders. void ClearBindings(); + size_t GetActiveLoaderCount() const { return loaders_.size(); } + private: // Implements mojom::URLLoaderFactory. void CreateLoaderAndStart(mojom::URLLoaderRequest request,
diff --git a/services/network/cors/preflight_controller.cc b/services/network/cors/preflight_controller.cc index c2f205d..3177ef7d 100644 --- a/services/network/cors/preflight_controller.cc +++ b/services/network/cors/preflight_controller.cc
@@ -351,6 +351,10 @@ (*emplaced_pair.first)->Request(loader_factory); } +size_t PreflightController::ReportAndGatherCacheSizeMetric() { + return cache_.ReportAndGatherSizeMetric(); +} + void PreflightController::RemoveLoader(PreflightLoader* loader) { auto it = loaders_.find(loader); DCHECK(it != loaders_.end());
diff --git a/services/network/cors/preflight_controller.h b/services/network/cors/preflight_controller.h index c58251a..f73ba215 100644 --- a/services/network/cors/preflight_controller.h +++ b/services/network/cors/preflight_controller.h
@@ -64,6 +64,9 @@ const net::NetworkTrafficAnnotationTag& traffic_annotation, mojom::URLLoaderFactory* loader_factory); + // Reports and gather CORS preflight cache size metric. + size_t ReportAndGatherCacheSizeMetric(); + private: class PreflightLoader;
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index ba7bc6c7..0134fda 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -758,6 +758,17 @@ return params_ && params_->skip_reporting_send_permission_check; } +size_t NetworkContext::ReportAndGatherCorsPreflightCacheSizeMetric() { + return cors_preflight_controller_.ReportAndGatherCacheSizeMetric(); +} + +size_t NetworkContext::GatherActiveLoaderCount() { + size_t count = 0; + for (const auto& factory : url_loader_factories_) + count += factory->GetActiveLoaderCount(); + return count; +} + void NetworkContext::ClearNetworkingHistorySince( base::Time time, base::OnceClosure completion_callback) {
diff --git a/services/network/network_context.h b/services/network/network_context.h index 10e7ac8..9e83d056 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h
@@ -392,6 +392,12 @@ // consulting NetworkContextClient.OnCanSendReportingReports() bool SkipReportingPermissionCheck() const; + // Reports and gather CORS preflight cache size metric. + size_t ReportAndGatherCorsPreflightCacheSizeMetric(); + + // Gather active URLLoader count. + size_t GatherActiveLoaderCount(); + private: class ContextNetworkDelegate;
diff --git a/services/network/network_service.cc b/services/network/network_service.cc index f42572a..cc8267d 100644 --- a/services/network/network_service.cc +++ b/services/network/network_service.cc
@@ -232,6 +232,9 @@ DCHECK(!g_network_service); g_network_service = this; + metrics_trigger_timer_.Start(FROM_HERE, base::TimeDelta::FromMinutes(5), this, + &NetworkService::ReportMetrics); + // In testing environments, |service_request| may not be provided. if (service_request.is_pending()) service_binding_.Bind(std::move(service_request)); @@ -815,6 +818,17 @@ MaybeStartUpdateLoadInfoTimer(); } +void NetworkService::ReportMetrics() { + size_t cache_size = 0; + size_t loader_count = 0; + for (auto* context : network_contexts_) { + cache_size += context->ReportAndGatherCorsPreflightCacheSizeMetric(); + loader_count += context->GatherActiveLoaderCount(); + } + UMA_HISTOGRAM_COUNTS_10000("Net.Cors.PreflightCacheTotalEntries", cache_size); + UMA_HISTOGRAM_COUNTS_1000("Net.Cors.ActiveLoaderCount", loader_count); +} + void NetworkService::Bind(mojom::NetworkServiceRequest request) { DCHECK(!binding_.is_bound()); binding_.Bind(std::move(request));
diff --git a/services/network/network_service.h b/services/network/network_service.h index 86d0ee1..1db705e 100644 --- a/services/network/network_service.h +++ b/services/network/network_service.h
@@ -275,6 +275,9 @@ // Starts timer call UpdateLoadInfo() again, if needed. void AckUpdateLoadInfo(); + // Reports metrics on a periodically triggered repeating timer. + void ReportMetrics(); + service_manager::ServiceBinding service_binding_{this}; bool initialized_ = false; @@ -354,6 +357,9 @@ // acknowledged. bool waiting_on_load_state_ack_ = false; + // A timer that periodically calls ReportMetrics every hour. + base::RepeatingTimer metrics_trigger_timer_; + DISALLOW_COPY_AND_ASSIGN(NetworkService); };
diff --git a/services/network/public/cpp/cors/preflight_cache.cc b/services/network/public/cpp/cors/preflight_cache.cc index 37065c97..40403d5 100644 --- a/services/network/public/cpp/cors/preflight_cache.cc +++ b/services/network/public/cpp/cors/preflight_cache.cc
@@ -6,7 +6,6 @@ #include <iterator> -#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/rand_util.h" #include "base/time/time.h" @@ -36,11 +35,7 @@ } // namespace -PreflightCache::PreflightCache() { - timer_.Start(FROM_HERE, base::TimeDelta::FromHours(1), this, - &PreflightCache::ReportMetrics); -} - +PreflightCache::PreflightCache() = default; PreflightCache::~PreflightCache() = default; void PreflightCache::AppendEntry( @@ -100,6 +95,12 @@ return false; } +size_t PreflightCache::ReportAndGatherSizeMetric() { + size_t entries = CountEntries(); + UMA_HISTOGRAM_COUNTS_10000("Net.Cors.PreflightCacheEntries", entries); + return entries; +} + size_t PreflightCache::CountOriginsForTesting() const { return cache_.size(); } @@ -134,11 +135,6 @@ } } -void PreflightCache::ReportMetrics() { - base::UmaHistogramCounts10000("Net.Cors.PreflightCacheEntries", - CountEntries()); -} - } // namespace cors } // namespace network
diff --git a/services/network/public/cpp/cors/preflight_cache.h b/services/network/public/cpp/cors/preflight_cache.h index b77be4f9..5fbd3f6 100644 --- a/services/network/public/cpp/cors/preflight_cache.h +++ b/services/network/public/cpp/cors/preflight_cache.h
@@ -11,7 +11,6 @@ #include "base/component_export.h" #include "base/macros.h" -#include "base/timer/timer.h" #include "net/http/http_request_headers.h" #include "services/network/public/cpp/cors/preflight_result.h" #include "services/network/public/mojom/fetch_api.mojom-shared.h" @@ -48,6 +47,9 @@ const net::HttpRequestHeaders& headers, bool is_revalidating); + // Reports and gather CORS preflight cache size metric. + size_t ReportAndGatherSizeMetric(); + // Counts cached origins for testing. size_t CountOriginsForTesting() const; @@ -61,7 +63,6 @@ private: size_t CountEntries() const; void MayPurge(size_t max_entries); - void ReportMetrics(); // A map for caching. The outer map takes an origin to find a per-origin // cache map, and the inner map takes an URL to find a cached entry. @@ -69,9 +70,6 @@ std::map<std::string /* url */, std::unique_ptr<PreflightResult>>> cache_; - // RepeatingTimer to report metrics. - base::RepeatingTimer timer_; - DISALLOW_COPY_AND_ASSIGN(PreflightCache); };
diff --git a/services/resource_coordinator/public/mojom/BUILD.gn b/services/resource_coordinator/public/mojom/BUILD.gn index 5f79114..1159b61 100644 --- a/services/resource_coordinator/public/mojom/BUILD.gn +++ b/services/resource_coordinator/public/mojom/BUILD.gn
@@ -14,7 +14,6 @@ "memory_instrumentation/constants.mojom", "memory_instrumentation/memory_instrumentation.mojom", "service_constants.mojom", - "webui_graph_dump.mojom", ] public_deps = [
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index a84a225..ef043e4e 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -821,7 +821,10 @@ sources += [ "ext/test_fonts_android.cc" ] } if (is_fuchsia) { - sources += [ "ext/test_fonts_fuchsia.cc" ] + sources += [ + "ext/test_fonts_fuchsia.cc", + "ext/test_fonts_fuchsia.h", + ] } if (is_linux) { sources += [ "ext/test_fonts_linux.cc" ] @@ -854,6 +857,7 @@ deps = [ ":skia", + ":test_fonts", "//base", "//base/test:test_support", "//mojo/core/test:run_all_unittests",
diff --git a/skia/ext/fontmgr_fuchsia_unittest.cc b/skia/ext/fontmgr_fuchsia_unittest.cc index d3fc113e..7ac1aaa0 100644 --- a/skia/ext/fontmgr_fuchsia_unittest.cc +++ b/skia/ext/fontmgr_fuchsia_unittest.cc
@@ -5,8 +5,7 @@ #include <fuchsia/fonts/cpp/fidl.h> #include <lib/fidl/cpp/binding.h> -#include "base/fuchsia/service_directory_client.h" -#include "base/path_service.h" +#include "skia/ext/test_fonts_fuchsia.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkFontMgr.h" #include "third_party/skia/include/core/SkTypeface.h" @@ -19,19 +18,17 @@ public: FuchsiaFontManagerTest() { font_manager_ = SkFontMgr_New_Fuchsia( - base::fuchsia::ServiceDirectoryClient::ForCurrentProcess() - ->ConnectToServiceSync<fuchsia::fonts::Provider>()); + RunTestProviderWithTestFonts(&font_provider_controller_)); } protected: + fidl::InterfaceHandle<fuchsia::sys::ComponentController> + font_provider_controller_; sk_sp<SkFontMgr> font_manager_; }; // Verify that SkTypeface objects are cached. -// TODO(https://crbug.com/931333): Currently font provider returns the same -// font for sans and serif when used with the default font config. Update this -// test to use the fonts //third_party/test_fonts. -TEST_F(FuchsiaFontManagerTest, DISABLED_Caching) { +TEST_F(FuchsiaFontManagerTest, Caching) { sk_sp<SkTypeface> sans( font_manager_->matchFamilyStyle("sans", SkFontStyle())); EXPECT_TRUE(sans);
diff --git a/skia/ext/test_fonts_fuchsia.cc b/skia/ext/test_fonts_fuchsia.cc index d277605..fa3667dc 100644 --- a/skia/ext/test_fonts_fuchsia.cc +++ b/skia/ext/test_fonts_fuchsia.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 "skia/ext/test_fonts.h" +#include "skia/ext/test_fonts_fuchsia.h" #include <fuchsia/fonts/cpp/fidl.h> #include <fuchsia/io/cpp/fidl.h> @@ -14,20 +14,14 @@ #include "base/no_destructor.h" #include "base/path_service.h" #include "skia/ext/fontmgr_default.h" +#include "skia/ext/test_fonts.h" #include "third_party/skia/include/core/SkFontMgr.h" #include "third_party/skia/include/ports/SkFontMgr_fuchsia.h" namespace skia { -void ConfigureTestFont() { - // ComponentController for the font provider service started below. It's a - // static field to keep the service running until the test process is - // destroyed. - static base::NoDestructor< - fidl::InterfaceHandle<fuchsia::sys::ComponentController>> - test_font_provider_controller; - DCHECK(!*test_font_provider_controller); - +fuchsia::fonts::ProviderSyncPtr RunTestProviderWithTestFonts( + fidl::InterfaceHandle<fuchsia::sys::ComponentController>* controller_out) { // Start a fuchsia.fonts.Provider instance and configure it to load the test // fonts, which must be bundled in the calling process' package. fuchsia::sys::LaunchInfo launch_info; @@ -53,14 +47,26 @@ base::fuchsia::ServiceDirectoryClient::ForCurrentProcess() ->ConnectToServiceSync<fuchsia::sys::Launcher>(); launcher->CreateComponent(std::move(launch_info), - test_font_provider_controller->NewRequest()); + controller_out->NewRequest()); base::fuchsia::ServiceDirectoryClient font_provider_services_client( std::move(font_provider_services_dir)); + return font_provider_services_client + .ConnectToServiceSync<fuchsia::fonts::Provider>(); +} + +void ConfigureTestFont() { + // ComponentController for the font provider service started below. It's a + // static field to keep the service running until the test process is + // destroyed. + static base::NoDestructor< + fidl::InterfaceHandle<fuchsia::sys::ComponentController>> + test_font_provider_controller; + DCHECK(!*test_font_provider_controller); + skia::OverrideDefaultSkFontMgr(SkFontMgr_New_Fuchsia( - font_provider_services_client - .ConnectToServiceSync<fuchsia::fonts::Provider>())); + RunTestProviderWithTestFonts(test_font_provider_controller.get()))); } } // namespace skia
diff --git a/skia/ext/test_fonts_fuchsia.h b/skia/ext/test_fonts_fuchsia.h new file mode 100644 index 0000000..f7aefac --- /dev/null +++ b/skia/ext/test_fonts_fuchsia.h
@@ -0,0 +1,18 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKIA_EXT_TEST_FONTS_FUCHSIA_H_ +#define SKIA_EXT_TEST_FONTS_FUCHSIA_H_ + +#include <fuchsia/fonts/cpp/fidl.h> +#include <fuchsia/sys/cpp/fidl.h> + +namespace skia { + +fuchsia::fonts::ProviderSyncPtr RunTestProviderWithTestFonts( + fidl::InterfaceHandle<fuchsia::sys::ComponentController>* controller_out); + +} // namespace skia + +#endif // SKIA_EXT_TEST_FONTS_FUCHSIA_H_
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 8c0f7b2..d654a87 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -567,7 +567,7 @@ ], "idempotent": false }, - "test": "chrome_kevin_tast_tests", + "test": "chrome_all_tast_tests", "trigger_script": { "script": "//testing/trigger_scripts/chromeos_device_trigger.py" }
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 88162d9..fe89411 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -568,13 +568,6 @@ "label": "//chrome/android:chrome_junit_tests", "type": "junit_test", }, - "chrome_kevin_tast_tests": { - "args": [ - "--vm-logs-dir=${ISOLATED_OUTDIR}", - ], - "label": "//chromeos:chrome_kevin_tast_tests", - "type": "raw", - }, "chrome_login_tast_tests": { "args": [ "--vm-logs-dir=${ISOLATED_OUTDIR}",
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index e77cf7d..6081fd43 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -316,7 +316,7 @@ '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.base_unittests.filter', ], }, - 'chrome_kevin_tast_tests': { + 'chrome_all_tast_tests': { 'swarming': { 'idempotent': False, # https://crbug.com/923426#c27 },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 83bdc4f5b..eda6dfb 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1136,31 +1136,6 @@ ] } ], - "BackgroundVideoOptimizations": [ - { - "platforms": [ - "chromeos", - "linux", - "mac", - "windows", - "android" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "BackgroundSrcVideoTrackOptimization" - ] - }, - { - "name": "Control", - "disable_features": [ - "BackgroundSrcVideoTrackOptimization" - ] - } - ] - } - ], "BlinkGenPropertyTrees": [ { "platforms": [
diff --git a/third_party/android_crazy_linker/BUILD.gn b/third_party/android_crazy_linker/BUILD.gn index a7c21e02..5747a16 100644 --- a/third_party/android_crazy_linker/BUILD.gn +++ b/third_party/android_crazy_linker/BUILD.gn
@@ -85,6 +85,7 @@ "src/src/crazy_linker_library_view.h", "src/src/crazy_linker_line_reader.cpp", "src/src/crazy_linker_line_reader.h", + "src/src/crazy_linker_load_params.h", "src/src/crazy_linker_memory_mapping.cpp", "src/src/crazy_linker_memory_mapping.h", "src/src/crazy_linker_pointer_set.cpp",
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_api.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_api.cpp index eeda97c..e7b7413 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_api.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_api.cpp
@@ -109,9 +109,22 @@ const char* lib_name, crazy_context_t* context) { ScopedLockedGlobals globals; - LibraryView* view = globals->libraries()->LoadLibrary( - lib_name, context->load_address, globals->search_path_list(), - &context->error); + crazy::LibraryList* libs = globals->libraries(); + crazy::LoadParams params; + params.wanted_address = context->load_address; + crazy::Expected<LibraryView*> found = + libs->FindAndCheckLoadedLibrary(lib_name, params, &context->error); + if (!found.has_value()) + return CRAZY_STATUS_FAILURE; + + LibraryView* view = found.value(); + if (!view) { + if (!libs->LocateLibraryFile(lib_name, *globals->search_path_list(), + ¶ms, &context->error)) { + return CRAZY_STATUS_FAILURE; + } + view = libs->LoadLibraryInternal(params, &context->error); + } if (!view) return CRAZY_STATUS_FAILURE;
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_elf_loader.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_elf_loader.cpp index d219b3c..80e3c92 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_elf_loader.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_elf_loader.cpp
@@ -27,10 +27,7 @@ public: ~InternalElfLoader(); - bool LoadAt(const char* lib_path, - off_t file_offset, - uintptr_t wanted_address, - Error* error); + bool LoadAt(const LoadParams& params, Error* error); // Only call the following functions after a successful LoadAt() call. @@ -56,7 +53,6 @@ ELF::Addr phdr_size_ = 0; // and its size. off_t file_offset_ = 0; - void* wanted_load_address_ = nullptr; void* load_start_ = nullptr; // First page of reserved address space. ELF::Addr load_size_ = 0; // Size in bytes of reserved address space. ELF::Addr load_bias_ = 0; // load_bias, add this value to all "vaddr" @@ -71,7 +67,7 @@ // Individual steps used by ::LoadAt() bool ReadElfHeader(Error* error); bool ReadProgramHeader(Error* error); - bool ReserveAddressSpace(Error* error); + bool ReserveAddressSpace(const LoadParams& params, Error* error); bool LoadSegments(Error* error); bool FindPhdr(Error* error); bool CheckPhdr(ELF::Addr, Error* error); @@ -84,25 +80,25 @@ } } -bool InternalElfLoader::LoadAt(const char* lib_path, - off_t file_offset, - uintptr_t wanted_address, - Error* error) { - LOG("lib_path='%s', file_offset=%p, load_address=%p", lib_path, file_offset, - wanted_address); +bool InternalElfLoader::LoadAt(const LoadParams& params, Error* error) { + const char* lib_path = params.library_path.c_str(); + LOG("lib_path='%s', file_offset=%p, load_address=%lx", lib_path, + params.library_offset, static_cast<unsigned long>(params.wanted_address)); // Check that the load address is properly page-aligned. + uintptr_t wanted_address = params.wanted_address; if (wanted_address != PAGE_START(wanted_address)) { error->Format("Load address is not page aligned (%08x)", wanted_address); return false; } - wanted_load_address_ = reinterpret_cast<void*>(wanted_address); // Check that the file offset is also properly page-aligned. // PAGE_START() can't be used here due to the compiler complaining about // comparing signed (off_t) and unsigned (size_t) values. + off_t file_offset = params.library_offset; if ((file_offset & static_cast<off_t>(PAGE_SIZE - 1)) != 0) { - error->Format("File offset is not page aligned (%08x)", file_offset); + error->Format("File offset is not page aligned (%08lx)", + static_cast<unsigned long>(file_offset)); return false; } file_offset_ = file_offset; @@ -122,7 +118,7 @@ path_ = lib_path; if (!ReadElfHeader(error) || !ReadProgramHeader(error) || - !ReserveAddressSpace(error)) { + !ReserveAddressSpace(params, error)) { return false; } @@ -220,7 +216,8 @@ // This will use the wanted_load_address_ value. Fails if the requested // address range cannot be reserved. Typically this would be because // it overlaps an existing, possibly system, mapping. -bool InternalElfLoader::ReserveAddressSpace(Error* error) { +bool InternalElfLoader::ReserveAddressSpace(const LoadParams& params, + Error* error) { ELF::Addr min_vaddr; load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr, NULL); @@ -229,20 +226,25 @@ return false; } - uint8_t* addr = NULL; + void* addr = nullptr; int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS; // Support loading at a fixed address. - if (wanted_load_address_) { - addr = static_cast<uint8_t*>(wanted_load_address_); + if (params.wanted_address) { + addr = reinterpret_cast<void*>(params.wanted_address); + mmap_flags |= MAP_FIXED; } size_t reserved_size = load_size_; - LOG("address=%p size=%p", addr, reserved_size); + LOG("Trying to reserve memory address=%p size=%lu (0x%lx)", addr, + static_cast<unsigned long>(load_size_), + static_cast<unsigned long>(load_size_)); + void* start = mmap(addr, reserved_size, PROT_NONE, mmap_flags, -1, 0); if (start == MAP_FAILED) { - error->Format("Could not reserve %d bytes of address space", reserved_size); + error->Format("Could not reserve %lu bytes of address space", + static_cast<unsigned long>(reserved_size)); return false; } if (addr && start != addr) { @@ -253,12 +255,16 @@ // Take ownership of the mapping here. reserved_map_ = MemoryMapping(start, reserved_size); - LOG("reserved start=%p", reserved_map_.address()); load_start_ = start; - load_bias_ = reinterpret_cast<ELF::Addr>(start) - min_vaddr; + load_bias_ = reinterpret_cast<ELF::Addr>(load_start_) - min_vaddr; - LOG("load start=%p, bias=%p", load_start_, load_bias_); + LOG("Reserved memory address=%p, size=%lu (0x%lx), bias=%lu (0x%lx)", + load_start_, static_cast<unsigned long>(load_size_), + static_cast<unsigned long>(load_size_), + static_cast<unsigned long>(load_bias_), + static_cast<unsigned long>(load_bias_)); + return true; } @@ -390,13 +396,10 @@ } // namespace // static -ElfLoader::Result ElfLoader::LoadAt(const char* lib_path, - off_t file_offset, - uintptr_t wanted_address, - Error* error) { +ElfLoader::Result ElfLoader::LoadAt(const LoadParams& params, Error* error) { InternalElfLoader loader; Result result; - if (loader.LoadAt(lib_path, file_offset, wanted_address, error)) { + if (loader.LoadAt(params, error)) { result.load_start = reinterpret_cast<ELF::Addr>(loader.load_start()); result.load_size = loader.load_size(); result.load_bias = loader.load_bias();
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_elf_loader.h b/third_party/android_crazy_linker/src/src/crazy_linker_elf_loader.h index bf4016c..03924e0b 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_elf_loader.h +++ b/third_party/android_crazy_linker/src/src/crazy_linker_elf_loader.h
@@ -6,6 +6,7 @@ #define CRAZY_LINKER_ELF_LOADER_H #include "crazy_linker_error.h" +#include "crazy_linker_load_params.h" #include "crazy_linker_memory_mapping.h" #include "crazy_linker_system.h" // For ScopedFileDescriptor #include "elf_traits.h" @@ -29,32 +30,13 @@ const ELF::Phdr* phdr = nullptr; size_t phdr_count = 0; MemoryMapping reserved_mapping; - Error error; // empty in case of success. constexpr bool IsValid() const { return this->load_start != 0; } }; - // Try to load a library at a given address. On failure, this will - // update the linker error message and returns false. - // - // |lib_path| is the full library path, and |wanted_address| should - // be the desired load address, or 0 to enable randomization. - // - // |file_offset| is an offset in the file where the ELF header will - // be looked for. - // - // |wanted_address| is the wanted load address (of the first loadable - // segment), or 0 to enable randomization. - // - // On success, returns a valid Result instance, where |reserved_mapping| will - // map the single range of reserved memory addresses for the ELF object - // (including the breakpad guard regions). - // - // On failure, return an invalid Result instance, and sets |*error|. - static Result LoadAt(const char* lib_path, - off_t file_offset, - uintptr_t wanted_address, - Error* error); + // Try to load a library at a given address. On failure, return an + // invalid Result instance, and sets |*error|. + static Result LoadAt(const LoadParams& params, Error* error); }; } // namespace crazy
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp index 99d0a209..c7565a9 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp
@@ -53,6 +53,29 @@ } }; +// Checks that |params| is compatible with a system library load. +// On success return true. On failure, set |*error| and return false. +// |lib_name| is either the library name, or nullptr, in which case +// |params.library_path| will be used for the error message. +bool CheckSystemLibraryLoadParams(const char* lib_name, + const LoadParams& params, + Error* error) { + if (!lib_name) + lib_name = params.library_path.c_str(); + + if (params.library_offset != 0) { + error->Format("Cannot load system library from offset 0x%08lx: %s", + static_cast<unsigned long>(params.library_offset), lib_name); + return false; + } + if (params.wanted_address != 0) { + error->Format("Cannot load system library at address 0x%08lx: %s", + static_cast<unsigned long>(params.wanted_address), lib_name); + return false; + } + return true; +} + } // namespace LibraryList::LibraryList() { @@ -295,11 +318,8 @@ Error* error) { // First check whether a library with the same base name was // already loaded. - LibraryView* view = FindKnownLibrary(lib_name); - if (view) { - view->AddRef(); - return view; - } + ASSERT(!FindKnownLibrary(lib_name), + "System library already loaded: ", lib_name); void* system_lib = SystemLinker::Open(lib_name, dlopen_mode); if (!system_lib) { @@ -309,86 +329,120 @@ } // Can't really find the DT_SONAME of this library, assume if is its basename. - view = new LibraryView(system_lib, GetBaseNamePtr(lib_name)); + LibraryView* view = new LibraryView(system_lib, GetBaseNamePtr(lib_name)); known_libraries_.PushBack(view); LOG("System library %s loaded at %p", lib_name, view); return view; } -LibraryView* LibraryList::LoadLibrary(const char* lib_name, - uintptr_t load_address, - SearchPathList* search_path_list, - Error* error) { - const char* base_name = GetBaseNamePtr(lib_name); +Expected<LibraryView*> LibraryList::FindAndCheckLoadedLibrary( + const char* lib_name, + const LoadParams& params, + Error* error) { + // First check whether a library with the same base name was already loaded. + LibraryView* view = FindKnownLibrary(lib_name); + if (!view) + return nullptr; - LOG("lib_name='%s'", lib_name); - - // First check whether a library with the same base name was - // already loaded. - LibraryView* view = FindKnownLibrary(base_name); - if (view) { - if (load_address) { + if (view->IsSystem()) { + if (!CheckSystemLibraryLoadParams(lib_name, params, error)) + return error; + } else { + const SharedLibrary* crazy_lib = view->GetCrazy(); + ASSERT(crazy_lib != nullptr, "Not a crazy library"); + if (params.wanted_address) { // Check that this is a crazy library and that is was loaded at // the correct address. - if (!view->IsCrazy()) { - error->Format("System library can't be loaded at fixed address %08x", - load_address); - return nullptr; - } - uintptr_t actual_address = view->GetCrazy()->load_address(); - if (actual_address != load_address) { - error->Format("Library already loaded at @%08x, can't load it at @%08x", - actual_address, - load_address); - return nullptr; + uintptr_t actual_address = crazy_lib->load_address(); + if (actual_address != params.wanted_address) { + error->Format( + "Library already loaded at address 0x%08lx, can't load it at " + "0x%08lx: %s", + static_cast<unsigned long>(actual_address), + static_cast<unsigned long>(params.wanted_address), lib_name); + return error; } } - view->AddRef(); - return view; } - // Find the full library path. - String full_path; + view->AddRef(); + return view; +} +// static +bool LibraryList::LocateLibraryFile(const char* lib_name, + const SearchPathList& search_path_list, + LoadParams* params, + Error* error) { LOG("Looking through the search path list"); - SearchPathList::Result probe = search_path_list->FindFile(lib_name); + SearchPathList::Result probe = search_path_list.FindFile(lib_name); if (!probe.IsValid()) { error->Format("Can't find library file %s", lib_name); - return nullptr; + return false; } LOG("Found library: path %s @ 0x%x", probe.path.c_str(), probe.offset); + params->library_path = std::move(probe.path); + params->library_offset = probe.offset; + return true; +} - if (IsSystemLibraryPath(probe.path.c_str())) { - return LoadLibraryWithSystemLinker(probe.path.c_str(), RTLD_NOW, error); +LibraryView* LibraryList::LoadLibrary(const char* lib_name, + const LoadParams& params, + Error* error) { + Expected<LibraryView*> found = + FindAndCheckLoadedLibrary(lib_name, params, error); + if (!found.has_value()) + return nullptr; + if (found.value()) + return found.value(); + return LoadLibraryInternal(params, error); +} + +LibraryView* LibraryList::LoadLibraryInternal(const LoadParams& params, + Error* error) { + // Load the library with the system linker if necessary. + const char* lib_path = params.library_path.c_str(); + if (IsSystemLibraryPath(lib_path)) { + if (!CheckSystemLibraryLoadParams(lib_path, params, error)) + return nullptr; + return LoadLibraryWithSystemLinker(lib_path, RTLD_NOW, error); } // Load the library with the crazy linker. ScopedPtr<SharedLibrary> lib(new SharedLibrary()); - if (!lib->Load(probe.path.c_str(), load_address, probe.offset, error)) + if (!lib->Load(params, error)) return nullptr; // Load all dependendent libraries. + const char* base_name = GetBaseNamePtr(lib_path); LOG("Loading dependencies of %s", base_name); SharedLibrary::DependencyIterator iter(lib.Get()); Vector<LibraryView*> dependencies; while (iter.GetNext()) { Error dep_error; - // TODO(digit): Call LoadLibrary recursively instead when properly - // detecting system vs Chromium libraries (http://crbug.com/843987). - LibraryView* dependency = - LoadLibraryWithSystemLinker(iter.GetName(), RTLD_NOW, &dep_error); + // TODO(digit): Better library dependency loading that isn't limited + // to system libraries. This would allow the linker to load anything + // without the caller having to load all dependencies before hand in + // reverse topological order. + const char* dependency_name = iter.GetName(); + LibraryView* dependency = FindKnownLibrary(dependency_name); if (!dependency) { - error->Format("When loading %s: %s", base_name, dep_error.c_str()); - return nullptr; + dependency = + LoadLibraryWithSystemLinker(dependency_name, RTLD_NOW, &dep_error); + if (!dependency) { + error->Format("When loading %s: %s", base_name, dep_error.c_str()); + // TODO(digit): Unload all dependencies that were loaded so far. + return nullptr; + } } dependencies.PushBack(dependency); } if (CRAZY_DEBUG) { LOG("Dependencies loaded for %s", base_name); for (const LibraryView* dep : dependencies) - LOG(" ... %p %s\n", dep, dep->GetName()); - LOG(" dependencies @%p\n", &dependencies); + LOG(" ... %p %s", dep, dep->GetName()); + LOG(" dependencies @%p", &dependencies); } // Relocate the library. @@ -412,7 +466,7 @@ head_ = lib.Get(); // Then create a new LibraryView for it. - view = new LibraryView(lib.Release()); + LibraryView* view = new LibraryView(lib.Release()); known_libraries_.PushBack(view); LOG("Running constructors for %s", base_name);
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_library_list.h b/third_party/android_crazy_linker/src/src/crazy_linker_library_list.h index 27e6f31..20a6ab6d7f 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_library_list.h +++ b/third_party/android_crazy_linker/src/src/crazy_linker_library_list.h
@@ -8,6 +8,8 @@ #include <link.h> #include "crazy_linker_error.h" +#include "crazy_linker_expected.h" +#include "crazy_linker_load_params.h" #include "crazy_linker_search_path_list.h" #include "elf_traits.h" @@ -62,13 +64,42 @@ int IteratePhdr(PhdrIterationCallback callback, void* data); #endif - // Try to load a library, possibly at a fixed address. - // On failure, returns NULL and sets the |error| message. - LibraryView* LoadLibrary(const char* path, - uintptr_t load_address, - SearchPathList* search_path_list, + // Find whether a library identified by |name| has already been loaded. + // Note that |name| should correspond to the library's unique soname, which + // comes from its DT_SONAME entry, and typically, but not necessarily + // matches its base name. + LibraryView* FindKnownLibrary(const char* name); + + // Check whether |lib_path| matches an already loaded library, compatible + // with the content of |load_params| (except its |library_path| field). + // On failure, i.e. if the load parameters are incompatible, set |*error| + // and return its address. On success, return either nullptr (if the library + // was not previously loaded, or a LibraryView* pointer after incrementing + // its reference count). + Expected<LibraryView*> FindAndCheckLoadedLibrary( + const char* lib_path, + const LoadParams& load_params, + Error* error); + + // Locate library |lib_name| using |search_path_list|. On success, update + // |params->library_path| and |params->library_offset| and return true. On + // failure, set |*error| and return false. + static bool LocateLibraryFile(const char* lib_name, + const SearchPathList& search_path_list, + LoadParams* params, + Error* error); + + // Try to load a library, according to |load_params|. On failure, returns + // nullptr and sets the |error| message. + LibraryView* LoadLibrary(const char* lib_name, + const LoadParams& load_params, Error* error); + // Try to load a library, according to |load_params|. + // On failure, return nullptr and sets the |error| message. + // Note: this will fail if the library is already loaded. + LibraryView* LoadLibraryInternal(const LoadParams& load_params, Error* error); + // Unload a given shared library. This really decrements the library's // internal reference count. When it reaches zero, the library's // destructors are run, its dependencies are unloaded, then the @@ -103,12 +134,6 @@ // The list of all known libraries. Vector<LibraryView*> known_libraries_; - // Find whether a library identified by |name| has already been loaded. - // Note that |name| should correspond to the library's unique soname, which - // comes from its DT_SONAME entry, and typically, but not necessarily - // matches its base name. - LibraryView* FindKnownLibrary(const char* name); - // The list of all libraries loaded by the crazy linker. // This does _not_ include system libraries present in known_libraries_. SharedLibrary* head_ = nullptr;
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_load_params.h b/third_party/android_crazy_linker/src/src/crazy_linker_load_params.h new file mode 100644 index 0000000..66cd03c --- /dev/null +++ b/third_party/android_crazy_linker/src/src/crazy_linker_load_params.h
@@ -0,0 +1,32 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRAZY_LINKER_LOAD_PARAMS_H +#define CRAZY_LINKER_LOAD_PARAMS_H + +#include <stddef.h> +#include <stdint.h> +#include <sys/types.h> + +#include "crazy_linker_util.h" + +namespace crazy { + +// A structure used to hold parameters related to loading an ELF library +// into the current process' address space. +// +// |library_path| is either the full library path. +// |library_offset| is the page-aligned offset where the library starts in +// its input file (typically > 0 when reading from Android APKs). +// |wanted_address| is either 0, or the address where the library should +// be loaded. +struct LoadParams { + String library_path; + off_t library_offset = 0; + uintptr_t wanted_address = 0; +}; + +} // namespace crazy + +#endif // CRAZY_LINKER_LOAD_PARAMS_H
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp index de136c4..1f5a711e 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp
@@ -15,6 +15,7 @@ #include "crazy_linker_globals.h" #include "crazy_linker_library_list.h" #include "crazy_linker_library_view.h" +#include "crazy_linker_load_params.h" #include "crazy_linker_memory_mapping.h" #include "crazy_linker_system_linker.h" #include "crazy_linker_thread_data.h" @@ -225,11 +226,9 @@ SharedLibrary::~SharedLibrary() = default; -bool SharedLibrary::Load(const char* full_path, - size_t load_address, - size_t file_offset, - Error* error) { +bool SharedLibrary::Load(const LoadParams& params, Error* error) { // First, record the path. + const char* full_path = params.library_path.c_str(); LOG("full path '%s'", full_path); size_t full_path_len = strlen(full_path); @@ -252,8 +251,7 @@ LOG("Loading ELF segments for %s", base_name_); { - ElfLoader::Result ret = - ElfLoader::LoadAt(full_path_, file_offset, load_address, error); + ElfLoader::Result ret = ElfLoader::LoadAt(params, error); if (!ret.IsValid() || !view_.InitUnmapped(ret.load_start, ret.phdr, ret.phdr_count, error)) { return false;
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h index b0c7b89..5a32665 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h +++ b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h
@@ -13,6 +13,7 @@ #include "crazy_linker_elf_symbols.h" #include "crazy_linker_elf_view.h" #include "crazy_linker_error.h" +#include "crazy_linker_load_params.h" #include "crazy_linker_memory_mapping.h" #include "crazy_linker_rdebug.h" #include "crazy_linker_util.h" @@ -50,17 +51,13 @@ // Load a library (without its dependents) from an ELF file. // Note: This does not apply relocations, nor runs constructors. // |full_path| if the file full path. - // |load_address| is the page-aligned load address in memory, or 0. - // |file_offset| is the page-aligned file offset. + // |params| are the load parameters for this operation. // On failure, return false and set |error| message. // // After this, the caller should load all library dependencies, // Then call Relocate() and CallConstructors() to complete the // operation. - bool Load(const char* full_path, - size_t load_address, - size_t file_offset, - Error* error); + bool Load(const LoadParams& params, Error* error); // Relocate this library, assuming all its dependencies are already // loaded in |lib_list|. On failure, return false and set |error|
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp index f25ffaea..44e54af 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp
@@ -89,17 +89,26 @@ void* WrapDlopen(const char* path, int mode) { ScopedLockedGlobals globals; + LibraryList* libs = globals->libraries(); // NOTE: If |path| is NULL, the wrapper should return a handle // corresponding to the current executable. This can't be a crazy // library, so don't try to handle it with the crazy linker. if (path) { Error error; - LibraryView* wrap = globals->libraries()->LoadLibrary( - path, 0U /* load_address */, globals->search_path_list(), &error); - if (wrap) { - globals->valid_handles()->Add(wrap); - return wrap; + LibraryView* view = libs->FindKnownLibrary(path); + if (!view) { + LoadParams params; + if (libs->LocateLibraryFile(path, *globals->search_path_list(), ¶ms, + &error)) { + view = libs->LoadLibraryInternal(params, &error); + if (!view) { + SetLinkerError("%s: %s", "dlopen", error.c_str()); + return nullptr; + } + globals->valid_handles()->Add(view); + return view; + } } } @@ -110,10 +119,10 @@ return nullptr; } - auto* wrap_lib = new LibraryView(system_lib, path ? path : "<executable>"); - globals->libraries()->AddLibrary(wrap_lib); - globals->valid_handles()->Add(wrap_lib); - return wrap_lib; + auto* view = new LibraryView(system_lib, path ? path : "<executable>"); + libs->AddLibrary(view); + globals->valid_handles()->Add(view); + return view; } void* WrapDlsym(void* lib_handle, const char* symbol_name) {
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.cc b/third_party/blink/renderer/core/html/html_plugin_element.cc index 011671b..5edf9ef7 100644 --- a/third_party/blink/renderer/core/html/html_plugin_element.cc +++ b/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -746,8 +746,7 @@ } void HTMLPlugInElement::ReattachOnPluginChangeIfNeeded() { - if (UseFallbackContent() || !NeedsPluginUpdate() || !GetLayoutObject() || - IsImageType()) + if (UseFallbackContent() || !NeedsPluginUpdate() || !GetLayoutObject()) return; SetNeedsStyleRecalc(
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc index 084317d..7783479 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc
@@ -22,6 +22,7 @@ struct SameSizeAsNGPhysicalTextFragment : NGPhysicalFragment { void* pointers[3]; unsigned offsets[2]; + PhysicalRect rect; }; static_assert(sizeof(NGPhysicalTextFragment) == @@ -75,7 +76,7 @@ DCHECK_GE(start_offset_, source.StartOffset()); DCHECK_LE(end_offset_, source.EndOffset()); DCHECK(shape_result_ || IsFlowControl()) << ToString(); - DCHECK(!source.rare_data_ || !source.rare_data_->style_); + DCHECK(!source.style_); line_orientation_ = source.line_orientation_; is_anonymous_text_ = source.is_anonymous_text_; ink_overflow_computed_ = false; @@ -92,7 +93,7 @@ static_cast<unsigned>(ToLineOrientation(builder->GetWritingMode())); if (UNLIKELY(StyleVariant() == NGStyleVariant::kEllipsis)) { - EnsureRareData()->style_ = std::move(builder->style_); + style_ = std::move(builder->style_); is_anonymous_text_ = true; } else { is_anonymous_text_ = @@ -102,21 +103,14 @@ ink_overflow_computed_ = false; } -NGPhysicalTextFragment::RareData* NGPhysicalTextFragment::EnsureRareData() - const { - if (!rare_data_) - rare_data_ = std::make_unique<RareData>(); - return rare_data_.get(); -} - const ComputedStyle& NGPhysicalTextFragment::Style() const { switch (StyleVariant()) { case NGStyleVariant::kStandard: case NGStyleVariant::kFirstLine: return NGPhysicalFragment::Style(); case NGStyleVariant::kEllipsis: - DCHECK(rare_data_ && rare_data_->style_); - return *rare_data_->style_; + DCHECK(style_); + return *style_; } NOTREACHED(); return NGPhysicalFragment::Style(); @@ -213,12 +207,11 @@ PhysicalRect NGPhysicalTextFragment::SelfInkOverflow() const { if (!ink_overflow_computed_) ComputeSelfInkOverflow(); - return UNLIKELY(rare_data_) ? rare_data_->self_ink_overflow_ : LocalRect(); + return self_ink_overflow_; } void NGPhysicalTextFragment::ClearSelfInkOverflow() const { - if (UNLIKELY(rare_data_)) - rare_data_->self_ink_overflow_ = LocalRect(); + self_ink_overflow_ = LocalRect(); } void NGPhysicalTextFragment::ComputeSelfInkOverflow() const { @@ -275,12 +268,12 @@ PhysicalRect local_ink_overflow = ConvertToLocal(ink_overflow); PhysicalRect local_rect = LocalRect(); if (local_rect.Contains(local_ink_overflow)) { - ClearSelfInkOverflow(); + self_ink_overflow_ = local_rect; return; } local_ink_overflow.Unite(local_rect); local_ink_overflow.ExpandEdgesToPixelBoundaries(); - EnsureRareData()->self_ink_overflow_ = local_ink_overflow; + self_ink_overflow_ = local_ink_overflow; } scoped_refptr<const NGPhysicalFragment> NGPhysicalTextFragment::TrimText(
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h index e7d5ddb..a4778e7 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h
@@ -142,15 +142,6 @@ unsigned end_offset, scoped_refptr<const ShapeResultView> shape_result); - struct RareData { - USING_FAST_MALLOC(RareData); - - public: - PhysicalRect self_ink_overflow_; - scoped_refptr<const ComputedStyle> style_; // Used only for ellipsis. - }; - RareData* EnsureRareData() const; - LayoutUnit InlinePositionForOffset(unsigned offset, LayoutUnit (*round)(float), AdjustMidCluster) const; @@ -172,7 +163,8 @@ // Fragments are immutable but allow certain expensive data, specifically ink // overflow, to be cached as long as it is guaranteed to always recompute to // the same value. - mutable std::unique_ptr<RareData> rare_data_; + mutable PhysicalRect self_ink_overflow_; + scoped_refptr<const ComputedStyle> style_; // Used only for ellipsis. }; template <>
diff --git a/third_party/blink/renderer/devtools/front_end/performance_monitor/PerformanceMonitor.js b/third_party/blink/renderer/devtools/front_end/performance_monitor/PerformanceMonitor.js index 393bf788..500e189 100644 --- a/third_party/blink/renderer/devtools/front_end/performance_monitor/PerformanceMonitor.js +++ b/third_party/blink/renderer/devtools/front_end/performance_monitor/PerformanceMonitor.js
@@ -157,10 +157,10 @@ if (x < -50) break; ctx.beginPath(); - ctx.moveTo(Math.round(x) + 0.5, 0); - ctx.lineTo(Math.round(x) + 0.5, this._height); + ctx.moveTo(x, 0); + ctx.lineTo(x, this._height); if (sec >= 0 && sec % labelDistanceSeconds === 0) - ctx.fillText(new Date(sec * 1000).toLocaleTimeString(), Math.round(x) + 4, 12); + ctx.fillText(new Date(sec * 1000).toLocaleTimeString(), x + 4, 12); ctx.strokeStyle = sec % labelDistanceSeconds ? lightGray : this._gridColor; ctx.stroke(); }
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js b/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js index b78bc66..f0787a717 100644 --- a/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js +++ b/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js
@@ -41,28 +41,26 @@ this._panel = profilesPanel; this.element.classList.add('profile-launcher-view'); + this._contentElement = this.element.createChild('div', 'profile-launcher-view-content vbox'); - const isolateSelector = new Profiler.IsolateSelector(); - this._contentElement = this.element.createChild('div', 'profile-launcher-view-content'); - this._innerContentElement = this._contentElement.createChild('div'); - const controlDiv = this._contentElement.createChild('div', 'vbox profile-launcher-control'); - controlDiv.createChild('h1').textContent = ls`Select JavaScript VM instance`; - controlDiv.appendChild(isolateSelector.totalMemoryElement()); - const targetDiv = controlDiv.createChild('div', 'vbox profile-launcher-target-list'); - isolateSelector.show(targetDiv); - - this._controlButton = - UI.createTextButton('', this._controlButtonClicked.bind(this), 'profile-launcher-button', true /* primary */); - this._contentElement.appendChild(this._controlButton); - this._recordButtonEnabled = true; - this._loadButton = - UI.createTextButton(Common.UIString('Load'), this._loadButtonClicked.bind(this), 'profile-launcher-button'); - this._contentElement.appendChild(this._loadButton); - + const profileTypeSelectorElement = this._contentElement.createChild('div', 'vbox'); this._selectedProfileTypeSetting = Common.settings.createSetting('selectedProfileType', 'CPU'); - this._header = this._innerContentElement.createChild('h1'); - this._profileTypeSelectorForm = this._innerContentElement.createChild('form'); - this._innerContentElement.createChild('div', 'flexible-space'); + this._profileTypeHeaderElement = profileTypeSelectorElement.createChild('h1'); + this._profileTypeSelectorForm = profileTypeSelectorElement.createChild('form'); + + const isolateSelectorElement = this._contentElement.createChild('div', 'vbox profile-isolate-selector-block'); + isolateSelectorElement.createChild('h1').textContent = ls`Select JavaScript VM instance`; + const isolateSelector = new Profiler.IsolateSelector(); + isolateSelector.show(isolateSelectorElement.createChild('div', 'vbox profile-launcher-target-list')); + isolateSelectorElement.appendChild(isolateSelector.totalMemoryElement()); + + const buttonsDiv = this._contentElement.createChild('div', 'hbox profile-launcher-buttons'); + this._controlButton = UI.createTextButton('', this._controlButtonClicked.bind(this), '', /* primary */ true); + this._loadButton = UI.createTextButton(ls`Load`, this._loadButtonClicked.bind(this), ''); + buttonsDiv.appendChild(this._controlButton); + buttonsDiv.appendChild(this._loadButton); + this._recordButtonEnabled = true; + /** @type {!Map<string, !HTMLOptionElement>} */ this._typeIdToOptionElement = new Map(); } @@ -132,9 +130,9 @@ if (customContent) this._profileTypeSelectorForm.createChild('p').appendChild(customContent); if (this._typeIdToOptionElement.size > 1) - this._header.textContent = ls`Select profiling type`; + this._profileTypeHeaderElement.textContent = ls`Select profiling type`; else - this._header.textContent = profileType.name; + this._profileTypeHeaderElement.textContent = profileType.name; } restoreSelectedProfileType() {
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/profileLauncherView.css b/third_party/blink/renderer/devtools/front_end/profiler/profileLauncherView.css index c73652a4..24824af 100644 --- a/third_party/blink/renderer/devtools/front_end/profiler/profileLauncherView.css +++ b/third_party/blink/renderer/devtools/front_end/profiler/profileLauncherView.css
@@ -4,10 +4,69 @@ * found in the LICENSE file. */ +.profile-launcher-view { + overflow: auto; +} + +.profile-launcher-view-content { + margin: 10px 16px; + flex: auto 1 0; +} + +.profile-launcher-view-content h1 { + font-size: 15px; + font-weight: normal; + margin: 6px 0 10px 0; +} + +.profile-launcher-view-content [is=dt-radio] { + font-size: 13px; +} + +.profile-launcher-view-content p { + color: grey; + margin-top: 1px; + margin-left: 22px; +} + +.profile-launcher-view-content p [is=dt-checkbox] { + display: flex; +} + +.profile-launcher-view-content button.running { + color: hsl(0, 100%, 58%); +} + +.profile-launcher-view-content button.running:hover { + color: hsl(0, 100%, 42%); +} + +body.inactive .profile-launcher-view-content button.running:not(.toolbar-item) { + color: rgb(220, 130, 130); +} + +.profile-launcher-view-content > div { + flex: auto 0 0; +} + +.profile-launcher-view-content > .profile-isolate-selector-block { + flex: auto 1 0; +} + +.profile-isolate-selector-block button { + min-width: 110px; +} + +.profile-launcher-target-list { + margin-bottom: 6px; + border: 1px solid #ddd; + flex: 150px 1 0; +} + .profile-memory-usage-item { padding: 4px; line-height: 16px; - border-left: 2px solid transparent; + border-left: 3px solid transparent; overflow-x: hidden; } @@ -39,7 +98,18 @@ color: red; } -.profile-launcher-control > .profile-memory-usage-item { +.profile-isolate-selector-block > .profile-memory-usage-item { margin-left: 1px; - margin-bottom: 6px; + margin-bottom: 4px; + font-weight: bolder; +} + +.profile-launcher-buttons { + flex-wrap: wrap; +} + +.profile-launcher-buttons button { + min-width: 120px; + height: 28px; + margin: 4px 16px 4px 0; }
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/profilesPanel.css b/third_party/blink/renderer/devtools/front_end/profiler/profilesPanel.css index 4849d7b..4fcbd334 100644 --- a/third_party/blink/renderer/devtools/front_end/profiler/profilesPanel.css +++ b/third_party/blink/renderer/devtools/front_end/profiler/profilesPanel.css
@@ -112,75 +112,6 @@ color: white; } - -.profile-launcher-view { - overflow: auto; -} - -.profile-launcher-view-content { - padding: 10px 16px; -} - -.profile-launcher-view-content h1 { - font-size: 15px; - font-weight: normal; - padding: 6px 0; - margin: 0 0 5px 0; -} - -.profile-launcher-view-content [is=dt-radio] { - font-size: 13px; -} - -.profile-launcher-control { - align-items: flex-start; - flex-wrap: wrap; - margin-top: 10px; - margin-right: 6px; -} - -.profile-launcher-control button { - min-width: 110px; -} - -.profile-launcher-target-list { - width: 100%; - height: 150px; - margin-bottom: 10px; - border: 1px solid #ddd; -} - -.profile-launcher-target { - align-items: baseline; -} - -.profile-launcher-target > * { - flex: 0 0 auto; - margin-right: 8px; -} - -.profile-launcher-view-content p { - color: grey; - margin-top: 1px; - margin-left: 22px; -} - -.profile-launcher-view-content p [is=dt-checkbox] { - display: flex; -} - -.profile-launcher-view-content button.running { - color: hsl(0, 100%, 58%); -} - -.profile-launcher-view-content button.running:hover { - color: hsl(0, 100%, 42%); -} - -body.inactive .profile-launcher-view-content button.running:not(.toolbar-item) { - color: rgb(220, 130, 130); -} - .highlighted-row { -webkit-animation: row_highlight 2s 0s; } @@ -204,12 +135,6 @@ margin: 0 0 0 10px !important; } -.profile-launcher-button { - min-width: 120px; - height: 28px; - margin: 8px 16px 8px 0; -} - .cpu-profile-flame-chart-overview-container { overflow: hidden; position: absolute;
diff --git a/third_party/blink/renderer/devtools/front_end/ui/SoftDropDown.js b/third_party/blink/renderer/devtools/front_end/ui/SoftDropDown.js index 6d21c347..799b2e2 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/SoftDropDown.js +++ b/third_party/blink/renderer/devtools/front_end/ui/SoftDropDown.js
@@ -15,6 +15,8 @@ this._selectedItem = null; this._model = model; + this._placeholderText = ls`(no item selected)`; + this.element = createElementWithClass('button', 'soft-dropdown'); UI.appendStyle(this.element, 'ui/softDropDownButton.css'); this._titleElement = this.element.createChild('span', 'title'); @@ -183,6 +185,15 @@ } /** + * @param {string} text + */ + setPlaceholderText(text) { + this._placeholderText = text; + if (!this._selectedItem) + this._titleElement.textContent = this._placeholderText; + } + + /** * @param {!Common.Event} event */ _itemsReplaced(event) { @@ -202,7 +213,7 @@ if (this._selectedItem) this._titleElement.textContent = this._delegate.titleFor(this._selectedItem); else - this._titleElement.textContent = ''; + this._titleElement.textContent = this._placeholderText; this._delegate.itemSelected(this._selectedItem); }
diff --git a/third_party/blink/renderer/modules/xr/xr_ray.idl b/third_party/blink/renderer/modules/xr/xr_ray.idl index 3bdfaa9..fa85593 100644 --- a/third_party/blink/renderer/modules/xr/xr_ray.idl +++ b/third_party/blink/renderer/modules/xr/xr_ray.idl
@@ -6,7 +6,7 @@ [ SecureContext, Exposed=Window, - RuntimeEnabled=WebXR, + RuntimeEnabled=WebXRHitTest, Constructor(), Constructor(DOMPointInit origin), Constructor(DOMPointInit origin, DOMPointInit direction),
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc index f1b75535..695207e6 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -5,6 +5,8 @@ #include "third_party/blink/renderer/platform/graphics/canvas_resource.h" #include <utility> + +#include "base/memory/read_only_shared_memory_region.h" #include "components/viz/common/resources/bitmap_allocation.h" #include "components/viz/common/resources/resource_format_utils.h" #include "components/viz/common/resources/single_release_callback.h" @@ -561,21 +563,20 @@ SkFilterQuality filter_quality) : CanvasResource(std::move(provider), filter_quality, color_params), size_(size) { - shared_memory_ = viz::bitmap_allocation::AllocateMappedBitmap( + base::MappedReadOnlyRegion shm = viz::bitmap_allocation::AllocateSharedBitmap( gfx::Size(Size()), ColorParams().TransferableResourceFormat()); - if (!IsValid()) + if (!shm.IsValid()) return; + shared_mapping_ = std::move(shm.mapping); shared_bitmap_id_ = viz::SharedBitmap::GenerateId(); CanvasResourceDispatcher* resource_dispatcher = Provider() ? Provider()->ResourceDispatcher() : nullptr; if (resource_dispatcher) { resource_dispatcher->DidAllocateSharedBitmap( - viz::bitmap_allocation::DuplicateAndCloseMappedBitmap( - shared_memory_.get(), gfx::Size(Size()), - ColorParams().TransferableResourceFormat()), + viz::bitmap_allocation::ToMojoHandle(std::move(shm.region)), SharedBitmapIdToGpuMailboxPtr(shared_bitmap_id_)); } } @@ -585,7 +586,7 @@ } bool CanvasResourceSharedBitmap::IsValid() const { - return !!shared_memory_; + return shared_mapping_.IsValid(); } IntSize CanvasResourceSharedBitmap::Size() const { @@ -602,7 +603,7 @@ SkImageInfo image_info = SkImageInfo::Make( Size().Width(), Size().Height(), ColorParams().GetSkColorType(), ColorParams().GetSkAlphaType(), ColorParams().GetSkColorSpace()); - SkPixmap pixmap(image_info, shared_memory_->memory(), + SkPixmap pixmap(image_info, shared_mapping_.memory(), image_info.minRowBytes()); this->AddRef(); sk_sp<SkImage> sk_image = SkImage::MakeFromRaster( @@ -633,11 +634,11 @@ resource_dispatcher->DidDeleteSharedBitmap( SharedBitmapIdToGpuMailboxPtr(shared_bitmap_id_)); } - shared_memory_ = nullptr; + shared_mapping_ = {}; } void CanvasResourceSharedBitmap::Abandon() { - shared_memory_ = nullptr; + shared_mapping_ = {}; } const gpu::Mailbox& CanvasResourceSharedBitmap::GetOrCreateGpuMailbox( @@ -656,7 +657,7 @@ ColorParams().GetSkColorSpaceForSkSurfaces()); bool read_pixels_successful = image->readPixels( - image_info, shared_memory_->memory(), image_info.minRowBytes(), 0, 0); + image_info, shared_mapping_.memory(), image_info.minRowBytes(), 0, 0); DCHECK(read_pixels_successful); }
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.h b/third_party/blink/renderer/platform/graphics/canvas_resource.h index 38af9f0..cc98f5c1 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.h +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/logging.h" +#include "base/memory/shared_memory_mapping.h" #include "base/memory/weak_ptr.h" #include "components/viz/common/resources/shared_bitmap.h" #include "gpu/command_buffer/client/gles2_interface.h" @@ -24,12 +25,6 @@ } // namespace gfx -namespace base { - -class SharedMemory; - -} // namespace base - namespace viz { class SingleReleaseCallback; @@ -305,7 +300,7 @@ SkFilterQuality); viz::SharedBitmapId shared_bitmap_id_; - std::unique_ptr<base::SharedMemory> shared_memory_; + base::WritableSharedMemoryMapping shared_mapping_; IntSize size_; bool is_origin_clean_ = true; };
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc index 1fdda6c5..77da370 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -1132,7 +1132,12 @@ blink_effects[effect.id] && blink_effects[effect.id]->HasActiveOpacityAnimation()) return cc::RenderSurfaceReason::kOpacityAnimation; - if (effect.is_fast_rounded_corner) + // Applying a rounded corner clip to more than one layer descendant + // with highest quality requires a render surface, due to the possibility + // of antialiasing issues on the rounded corner edges. + // is_fast_rounded_corner means to intentionally prefer faster compositing + // and less memory over highest quality. + if (!effect.rounded_corner_bounds.IsEmpty() && !effect.is_fast_rounded_corner) return cc::RenderSurfaceReason::kRoundedCorner; return cc::RenderSurfaceReason::kNone; }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc index cef9e09..c712eb03 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
@@ -2586,8 +2586,7 @@ if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) { // Expectation in effect stack diagram: - // l1 - // l0 + // l0 // [ mask_isolation_0 ] // [ e0 ] // One content layer. @@ -2615,6 +2614,7 @@ EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner); EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5), mask_isolation_0.rounded_corner_bounds); + EXPECT_FALSE(mask_isolation_0.HasRenderSurface()); return; } @@ -2644,6 +2644,7 @@ *GetPropertyTrees().effect_tree.Node(mask_isolation_0_id); ASSERT_EQ(e0_id, mask_isolation_0.parent_id); EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode); + EXPECT_TRUE(mask_isolation_0.HasRenderSurface()); EXPECT_EQ(SynthesizedClipLayerAt(0), clip_mask0); EXPECT_EQ(gfx::Size(300, 200), clip_mask0->bounds()); @@ -2659,6 +2660,111 @@ EXPECT_TRUE(clip_mask0->DrawsContent()); } +TEST_P(PaintArtifactCompositorTest, SynthesizedClipNested) { + // This tests the simplist case that a single layer needs to be clipped + // by a single composited rounded clip. + if (!RuntimeEnabledFeatures::FastBorderRadiusEnabled()) + return; + + FloatSize corner(5, 5); + FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner, + corner); + auto c1 = CreateClip(c0(), t0(), rrect); + auto c2 = CreateClip(*c1, t0(), rrect); + auto c3 = CreateClip(*c2, t0(), rrect); + auto t1 = CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(), + CompositingReason::kWillChangeTransform); + CompositorFilterOperations filter_operations; + filter_operations.AppendBlurFilter(5); + auto filter = CreateFilterEffect(e0(), t0(), c1.get(), filter_operations); + + TestPaintArtifact artifact; + artifact.Chunk(t0(), *c1, *filter) + .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack); + artifact.Chunk(*t1, *c3, *filter) + .RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack); + Update(artifact.Build()); + + // Expectation in effect stack diagram: + // l0 + // [ mask_isolation_2 ] + // l1 [ mask_isolation_1 ] + // [ filter ] + // [ mask_isolation_0 ] + // [ e0 ] + // Two content layers. + /// + // mask_isolation_1 will have a render surface. mask_isolation_2 will not + // because non-leaf synthetic rounded clips must have a render surface. + // mask_isolation_0 will not because it is a leaf synthetic rounded clip + // in the render surface created by the filter. + + ASSERT_EQ(2u, RootLayer()->children().size()); + ASSERT_EQ(2u, ContentLayerCount()); + // There is still a "synthesized layer" but it's null. + ASSERT_EQ(3u, SynthesizedClipLayerCount()); + EXPECT_FALSE(SynthesizedClipLayerAt(0)); + EXPECT_FALSE(SynthesizedClipLayerAt(1)); + EXPECT_FALSE(SynthesizedClipLayerAt(2)); + + const cc::Layer* content0 = RootLayer()->children()[0].get(); + EXPECT_EQ(ContentLayerAt(0), content0); + const cc::Layer* content1 = RootLayer()->children()[1].get(); + EXPECT_EQ(ContentLayerAt(1), content1); + + constexpr int c0_id = 1; + constexpr int c1_id = 2; + constexpr int e0_id = 1; + constexpr int e1_id = 2; + + int c3_id = content1->clip_tree_index(); + const cc::ClipNode& cc_c3 = *GetPropertyTrees().clip_tree.Node(c3_id); + EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c3.clip); + const cc::ClipNode& cc_c2 = + *GetPropertyTrees().clip_tree.Node(cc_c3.parent_id); + EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c2.clip); + ASSERT_EQ(c1_id, cc_c2.parent_id); + const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id); + EXPECT_EQ(c1_id, content0->clip_tree_index()); + EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip); + ASSERT_EQ(c0_id, cc_c1.parent_id); + + int mask_isolation_2_id = content1->effect_tree_index(); + const cc::EffectNode& mask_isolation_2 = + *GetPropertyTrees().effect_tree.Node(mask_isolation_2_id); + const cc::EffectNode& mask_isolation_1 = + *GetPropertyTrees().effect_tree.Node(mask_isolation_2.parent_id); + const cc::EffectNode& cc_filter = + *GetPropertyTrees().effect_tree.Node(mask_isolation_1.parent_id); + const cc::EffectNode& mask_isolation_0 = + *GetPropertyTrees().effect_tree.Node(cc_filter.parent_id); + + ASSERT_EQ(e0_id, mask_isolation_0.parent_id); + EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode); + EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner); + EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5), + mask_isolation_0.rounded_corner_bounds); + EXPECT_FALSE(mask_isolation_0.HasRenderSurface()); + + ASSERT_EQ(e1_id, cc_filter.parent_id); + EXPECT_EQ(cc_filter.id, content0->effect_tree_index()); + EXPECT_EQ(SkBlendMode::kSrcOver, cc_filter.blend_mode); + EXPECT_FALSE(cc_filter.is_fast_rounded_corner); + EXPECT_TRUE(cc_filter.HasRenderSurface()); + + EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_1.blend_mode); + EXPECT_TRUE(mask_isolation_1.is_fast_rounded_corner); + EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5), + mask_isolation_1.rounded_corner_bounds); + EXPECT_TRUE(mask_isolation_1.HasRenderSurface()); + + EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_2.blend_mode); + EXPECT_TRUE(mask_isolation_2.is_fast_rounded_corner); + EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5), + mask_isolation_2.rounded_corner_bounds); + EXPECT_FALSE(mask_isolation_2.HasRenderSurface()); +} + TEST_P(PaintArtifactCompositorTest, SynthesizedClipIsNotDrawable) { // This tests the simplist case that a single layer needs to be clipped // by a single composited rounded clip. @@ -2794,6 +2900,7 @@ EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner); EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 0), mask_isolation_0.rounded_corner_bounds); + EXPECT_FALSE(mask_isolation_0.HasRenderSurface()); return; } @@ -2900,6 +3007,7 @@ EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner); EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5), mask_isolation_0.rounded_corner_bounds); + EXPECT_FALSE(mask_isolation_0.HasRenderSurface()); return; } @@ -3009,6 +3117,7 @@ EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner); EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5), mask_isolation_0.rounded_corner_bounds); + EXPECT_FALSE(mask_isolation_0.HasRenderSurface()); EXPECT_EQ(ContentLayerAt(1), content1); int t1_id = content1->transform_tree_index(); @@ -3030,6 +3139,7 @@ EXPECT_TRUE(mask_isolation_1.is_fast_rounded_corner); EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5), mask_isolation_1.rounded_corner_bounds); + EXPECT_FALSE(mask_isolation_1.HasRenderSurface()); return; } @@ -3064,6 +3174,7 @@ *GetPropertyTrees().effect_tree.Node(mask_isolation_0_id); ASSERT_EQ(e0_id, mask_isolation_0.parent_id); EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode); + EXPECT_TRUE(mask_isolation_0.HasRenderSurface()); EXPECT_EQ(SynthesizedClipLayerAt(0), clip_mask0); EXPECT_EQ(gfx::Size(300, 200), clip_mask0->bounds()); @@ -3092,6 +3203,7 @@ EXPECT_NE(mask_isolation_0_id, mask_isolation_1_id); ASSERT_EQ(e0_id, mask_isolation_1.parent_id); EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_1.blend_mode); + EXPECT_TRUE(mask_isolation_1.HasRenderSurface()); EXPECT_EQ(SynthesizedClipLayerAt(1), clip_mask1); EXPECT_EQ(gfx::Size(300, 200), clip_mask1->bounds()); @@ -3153,6 +3265,7 @@ *GetPropertyTrees().effect_tree.Node(mask_isolation_0_id); ASSERT_EQ(e0_id, mask_isolation_0.parent_id); EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode); + EXPECT_FALSE(mask_isolation_0.HasRenderSurface()); EXPECT_EQ(ContentLayerAt(1), content1); EXPECT_EQ(c1_id, content1->clip_tree_index()); @@ -3169,7 +3282,6 @@ EXPECT_TRUE(cc_e2.is_fast_rounded_corner); EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5), mask_isolation_0.rounded_corner_bounds); - return; } @@ -3201,6 +3313,7 @@ *GetPropertyTrees().effect_tree.Node(mask_isolation_0_id); ASSERT_EQ(e0_id, mask_isolation_0.parent_id); EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode); + EXPECT_TRUE(mask_isolation_0.HasRenderSurface()); EXPECT_EQ(ContentLayerAt(1), content1); EXPECT_EQ(c1_id, content1->clip_tree_index()); @@ -3281,6 +3394,7 @@ EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner); EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5), mask_isolation_0.rounded_corner_bounds); + EXPECT_FALSE(mask_isolation_0.HasRenderSurface()); EXPECT_EQ(ContentLayerAt(1), content1); EXPECT_EQ(c1_id, content1->clip_tree_index()); @@ -3295,6 +3409,7 @@ EXPECT_TRUE(mask_isolation_1.is_fast_rounded_corner); EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5), mask_isolation_1.rounded_corner_bounds); + EXPECT_FALSE(mask_isolation_1.HasRenderSurface()); EXPECT_EQ(ContentLayerAt(2), content2); EXPECT_EQ(c1_id, content2->clip_tree_index()); @@ -3308,6 +3423,7 @@ EXPECT_TRUE(mask_isolation_2.is_fast_rounded_corner); EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5), mask_isolation_2.rounded_corner_bounds); + EXPECT_FALSE(mask_isolation_2.HasRenderSurface()); return; }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc index 1006dac..98c3bd1 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
@@ -313,12 +313,18 @@ current_.clip = &clip; if (cc_effect_node.HasRenderSurface()) { - current_.may_be_2d_axis_misaligned_to_render_surface = 0; - } else if (previous_transform && - !current_.may_be_2d_axis_misaligned_to_render_surface) { - current_.may_be_2d_axis_misaligned_to_render_surface |= - TransformsMayBe2dAxisMisaligned(*previous_transform, - current_.Transform()); + current_.may_be_2d_axis_misaligned_to_render_surface = + EffectState::kAligned; + current_.contained_by_non_render_surface_synthetic_rounded_clip = false; + } else { + if (current_.may_be_2d_axis_misaligned_to_render_surface == + EffectState::kAligned && + previous_transform != ¤t_.Transform()) { + current_.may_be_2d_axis_misaligned_to_render_surface = + EffectState::kUnknown; + } + current_.contained_by_non_render_surface_synthetic_rounded_clip |= + (effect_type & CcEffectType::kSyntheticForNonTrivialClip); } } @@ -750,21 +756,58 @@ return false; } +bool PropertyTreeManager::EffectStateMayBe2dAxisMisalignedToRenderSurface( + EffectState& state, + size_t index) { + if (state.may_be_2d_axis_misaligned_to_render_surface == + EffectState::kUnknown) { + // The root effect has render surface, so it's always kAligned. + DCHECK_NE(0u, index); + if (EffectStateMayBe2dAxisMisalignedToRenderSurface( + effect_stack_[index - 1], index - 1)) { + state.may_be_2d_axis_misaligned_to_render_surface = + EffectState::kMisaligned; + } else { + state.may_be_2d_axis_misaligned_to_render_surface = + TransformsMayBe2dAxisMisaligned(effect_stack_[index - 1].Transform(), + current_.Transform()) + ? EffectState::kMisaligned + : EffectState::kAligned; + } + } + return state.may_be_2d_axis_misaligned_to_render_surface == + EffectState::kMisaligned; +} + +bool PropertyTreeManager::CurrentEffectMayBe2dAxisMisalignedToRenderSurface() { + // |current_| is virtually the top of effect_stack_. + return EffectStateMayBe2dAxisMisalignedToRenderSurface(current_, + effect_stack_.size()); +} + PropertyTreeManager::CcEffectType PropertyTreeManager::SyntheticEffectType( - const ClipPaintPropertyNode& clip) const { + const ClipPaintPropertyNode& clip) { unsigned effect_type = CcEffectType::kEffect; if (clip.ClipRect().IsRounded() || clip.ClipPath()) effect_type |= CcEffectType::kSyntheticForNonTrivialClip; // Cc requires that a rectangluar clip is 2d-axis-aligned with the render // surface to correctly apply the clip. - if (current_.may_be_2d_axis_misaligned_to_render_surface | + if (CurrentEffectMayBe2dAxisMisalignedToRenderSurface() || TransformsMayBe2dAxisMisaligned(clip.LocalTransformSpace(), current_.Transform())) effect_type |= CcEffectType::kSyntheticFor2dAxisAlignment; return static_cast<CcEffectType>(effect_type); } +void PropertyTreeManager::ForceRenderSurfaceIfSyntheticRoundedCornerClip( + PropertyTreeManager::EffectState& state) { + if (state.effect_type & CcEffectType::kSyntheticForNonTrivialClip) { + auto& effect_node = *GetEffectTree().Node(state.effect_id); + effect_node.render_surface_reason = cc::RenderSurfaceReason::kRoundedCorner; + } +} + SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded( const ClipPaintPropertyNode& target_clip_arg, SkBlendMode delegated_blend) { @@ -856,6 +899,20 @@ synthetic_effect.rounded_corner_bounds = gfx::RRectF(pending_clip.clip->ClipRect()); synthetic_effect.is_fast_rounded_corner = true; + + // Nested rounded corner clips need to force render surfaces for + // clips other than the leaf ones, because the compositor doesn't + // know how to apply two rounded clips to the same draw quad. + if (current_.contained_by_non_render_surface_synthetic_rounded_clip) { + ForceRenderSurfaceIfSyntheticRoundedCornerClip(current_); + for (auto effect_it = effect_stack_.rbegin(); + effect_it != effect_stack_.rend(); ++effect_it) { + auto& effect_node = *GetEffectTree().Node(effect_it->effect_id); + if (effect_node.HasRenderSurface()) + break; + ForceRenderSurfaceIfSyntheticRoundedCornerClip(*effect_it); + } + } } else { synthetic_effect.render_surface_reason = pending_clip.clip->ClipRect().IsRounded()
diff --git a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h index ad38a2a..efe9f1c 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h +++ b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
@@ -140,7 +140,71 @@ void SetupRootEffectNode(); void SetupRootScrollNode(); + // The type of operation the current cc effect node applies. + enum CcEffectType { + // The cc effect corresponds to a Blink effect node. + kEffect = 0, + // The cc effect is synthetic for a blink clip node that has to be + // rasterized because the clip is non-trivial. + kSyntheticForNonTrivialClip = 1 << 0, + // The cc effect is synthetic to create a render surface that is + // 2d-axis-aligned with a blink clip node that is non-2d-axis-aligned + // in the the original render surface. Cc requires a rectangular clip to be + // 2d-axis-aligned with the render surface to correctly apply the clip. + // TODO(crbug.com/504464): This will be changed when we move render surface + // decision logic into the cc compositor thread. + kSyntheticFor2dAxisAlignment = 1 << 1 + }; + + struct EffectState { + // The cc effect node that has the corresponding drawing state to the + // effect and clip state from the last + // SwitchToEffectNodeWithSynthesizedClip. + int effect_id; + + CcEffectType effect_type; + + // The effect state of the cc effect node. It's never nullptr. + const EffectPaintPropertyNode* effect; + + // The clip state of the cc effect node. This value may be shallower than + // the one passed into SwitchToEffectNodeWithSynthesizedClip because not + // every clip needs to be synthesized as cc effect. Is set to output clip of + // the effect if the type is kEffect, or set to the synthesized clip node. + // It's never nullptr. + const ClipPaintPropertyNode* clip; + + // Whether the transform space of this state may be 2d axis misaligned to + // the containing render surface. As there may be new render surfaces + // created between this state and the current known ancestor render surface + // after this state is created, we must conservatively accumulate this flag + // from the known render surface instead of checking if the combined + // transform is 2d axis aligned, in case of: + // Effect1 (Current known render surface) + // Rotate(45deg) + // Effect2 (Not known now, but may become render surface later) + // Rotate(-45deg) + // Clip (Would be mistakenly treated as 2d axis aligned if we used + // + // It's lazily computed if it can't be trivially known when we create this + // EffectState. + enum { + kAligned, + kMisaligned, + kUnknown, + } may_be_2d_axis_misaligned_to_render_surface; + + // Whether this effect or an ancestor has a synthetic rounded clip between + // self and the next render surface. This is used to force a render surface + // for all ancestor synthetic rounded clips if a descendant is found. + bool contained_by_non_render_surface_synthetic_rounded_clip; + + // The transform space of the state. + const TransformPaintPropertyNode& Transform() const; + }; + void BuildEffectNodesRecursively(const EffectPaintPropertyNode& next_effect); + void ForceRenderSurfaceIfSyntheticRoundedCornerClip(EffectState& state); SkBlendMode SynthesizeCcEffectsForClipsIfNeeded( const ClipPaintPropertyNode& target_clip, SkBlendMode delegated_blend); @@ -172,23 +236,10 @@ return current_.effect_type & CcEffectType::kSyntheticForNonTrivialClip; } - // The type of operation the current cc effect node applies. - enum CcEffectType { - // The cc effect corresponds to a Blink effect node. - kEffect = 0, - // The cc effect is synthetic for a blink clip node that has to be - // rasterized because the clip is non-trivial. - kSyntheticForNonTrivialClip = 1 << 0, - // The cc effect is synthetic to create a render surface that is - // 2d-axis-aligned with a blink clip node that is non-2d-axis-aligned - // in the the original render surface. Cc requires a rectangular clip to be - // 2d-axis-aligned with the render surface to correctly apply the clip. - // TODO(crbug.com/504464): This will be changed when we move render surface - // decision logic into the cc compositor thread. - kSyntheticFor2dAxisAlignment = 1 << 1 - }; - - CcEffectType SyntheticEffectType(const ClipPaintPropertyNode&) const; + bool EffectStateMayBe2dAxisMisalignedToRenderSurface(EffectState&, + size_t index); + bool CurrentEffectMayBe2dAxisMisalignedToRenderSurface(); + CcEffectType SyntheticEffectType(const ClipPaintPropertyNode&); void SetCurrentEffectState(const cc::EffectNode&, CcEffectType, @@ -221,42 +272,6 @@ int new_sequence_number_ = -1; - struct EffectState { - // The cc effect node that has the corresponding drawing state to the - // effect and clip state from the last - // SwitchToEffectNodeWithSynthesizedClip. - int effect_id; - - CcEffectType effect_type; - - // The effect state of the cc effect node. It's never nullptr. - const EffectPaintPropertyNode* effect; - - // The clip state of the cc effect node. This value may be shallower than - // the one passed into SwitchToEffectNodeWithSynthesizedClip because not - // every clip needs to be synthesized as cc effect. Is set to output clip of - // the effect if the type is kEffect, or set to the synthesized clip node. - // It's never nullptr. - const ClipPaintPropertyNode* clip; - - // Whether the transform space of this state may be 2d axis misaligned to - // the containing render surface. As there may be new render surfaces - // created between this state and the current known ancestor render surface - // after this state is created, we must conservatively accumulate this flag - // from the known render surface instead of checking if the combined - // transform is 2d axis aligned, in case of: - // Effect1 (Current known render surface) - // Rotate(45deg) - // Effect2 (Not known now, but may become render surface later) - // Rotate(-45deg) - // Clip (Would be mistakenly treated as 2d axis aligned if we used - // accumulated transform from the clip to the known render surface.) - bool may_be_2d_axis_misaligned_to_render_surface; - - // The transform space of the state. - const TransformPaintPropertyNode& Transform() const; - }; - // The current effect state. Virtually it's the top of the effect stack if // it and effect_stack_ are treated as a whole stack. EffectState current_;
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc index 5bb0bd9..330047d7 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -34,6 +34,7 @@ #include <memory> #include <utility> +#include "base/memory/read_only_shared_memory_region.h" #include "base/numerics/checked_math.h" #include "build/build_config.h" #include "cc/layers/texture_layer.h" @@ -291,9 +292,8 @@ viz::ResourceFormat format = viz::RGBA_8888; if (use_half_float_storage_) format = viz::RGBA_F16; - std::unique_ptr<base::SharedMemory> shm = - viz::bitmap_allocation::AllocateMappedBitmap( - static_cast<gfx::Size>(size_), format); + base::MappedReadOnlyRegion shm = viz::bitmap_allocation::AllocateSharedBitmap( + static_cast<gfx::Size>(size_), format); auto bitmap = base::MakeRefCounted<cc::CrossThreadSharedBitmap>( id, std::move(shm), static_cast<gfx::Size>(size_), format); RegisteredBitmap registered = { @@ -358,8 +358,8 @@ // Read the framebuffer into |bitmap|. { - unsigned char* pixels = static_cast<unsigned char*>( - registered.bitmap->shared_memory()->memory()); + unsigned char* pixels = + static_cast<unsigned char*>(registered.bitmap->memory()); DCHECK(pixels); bool need_premultiply = want_alpha_channel_ && !premultiplied_alpha_; WebGLImageConversion::AlphaOp op =
diff --git a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc index acf73ec..48aa23b0 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h" +#include "base/memory/read_only_shared_memory_region.h" #include "cc/layers/texture_layer.h" #include "cc/resources/cross_thread_shared_bitmap.h" #include "components/viz/common/resources/bitmap_allocation.h" @@ -150,7 +151,7 @@ SkImageInfo dst_info = SkImageInfo::Make(size.width(), size.height(), sk_image->colorType(), kPremul_SkAlphaType, sk_image->refColorSpace()); - void* pixels = registered.bitmap->shared_memory()->memory(); + void* pixels = registered.bitmap->memory(); // Copy from SkImage into SharedMemory owned by |registered|. if (!sk_image->readPixels(dst_info, pixels, dst_info.minRowBytes(), 0, 0)) @@ -195,8 +196,8 @@ // There are no bitmaps to recycle so allocate a new one. viz::SharedBitmapId id = viz::SharedBitmap::GenerateId(); - std::unique_ptr<base::SharedMemory> shm = - viz::bitmap_allocation::AllocateMappedBitmap(size, format); + base::MappedReadOnlyRegion shm = + viz::bitmap_allocation::AllocateSharedBitmap(size, format); RegisteredBitmap registered; registered.bitmap = base::MakeRefCounted<cc::CrossThreadSharedBitmap>(
diff --git a/third_party/blink/renderer/platform/heap/gc_info.h b/third_party/blink/renderer/platform/heap/gc_info.h index f9934e8..2109246a 100644 --- a/third_party/blink/renderer/platform/heap/gc_info.h +++ b/third_party/blink/renderer/platform/heap/gc_info.h
@@ -30,7 +30,6 @@ const TraceCallback trace; const FinalizationCallback finalize; const NameCallback name; - const bool non_trivial_finalizer; const bool has_v_table; }; @@ -102,9 +101,10 @@ static uint32_t Index() { static_assert(sizeof(T), "T must be fully defined"); static const GCInfo kGcInfo = { - TraceTrait<T>::Trace, FinalizerTrait<T>::Finalize, - NameTrait<T>::GetName, FinalizerTrait<T>::kNonTrivialFinalizer, - std::is_polymorphic<T>::value}; + TraceTrait<T>::Trace, + FinalizerTrait<T>::kNonTrivialFinalizer ? FinalizerTrait<T>::Finalize + : nullptr, + NameTrait<T>::GetName, std::is_polymorphic<T>::value}; // This is more complicated than using threadsafe initialization, but this // is instantiated many times (once for every GC type). static std::atomic_uint32_t gc_info_index{0};
diff --git a/third_party/blink/renderer/platform/heap/gc_info_test.cc b/third_party/blink/renderer/platform/heap/gc_info_test.cc index e87246b..a263ac1 100644 --- a/third_party/blink/renderer/platform/heap/gc_info_test.cc +++ b/third_party/blink/renderer/platform/heap/gc_info_test.cc
@@ -15,7 +15,7 @@ TEST(GCInfoTest, ResizeToMaxIndex) { GCInfoTable table; - GCInfo info = {nullptr, nullptr, nullptr, false, false}; + GCInfo info = {nullptr, nullptr, nullptr, false}; std::atomic_uint32_t slot{0}; for (uint32_t i = 0; i < (GCInfoTable::kMaxIndex - 1); i++) { slot = 0;
diff --git a/third_party/blink/renderer/platform/heap/heap.h b/third_party/blink/renderer/platform/heap/heap.h index 0741595..508e2f9 100644 --- a/third_party/blink/renderer/platform/heap/heap.h +++ b/third_party/blink/renderer/platform/heap/heap.h
@@ -697,7 +697,7 @@ // TODO(haraken): We don't support reallocate() for finalizable objects. DCHECK(!GCInfoTable::Get() .GCInfoFromIndex(previous_header->GcInfoIndex()) - ->non_trivial_finalizer); + ->finalize); DCHECK_EQ(previous_header->GcInfoIndex(), gc_info_index); HeapAllocHooks::FreeHookIfEnabled(static_cast<Address>(previous)); Address address;
diff --git a/third_party/blink/renderer/platform/heap/heap_page.cc b/third_party/blink/renderer/platform/heap/heap_page.cc index d120b441..9d02a88 100644 --- a/third_party/blink/renderer/platform/heap/heap_page.cc +++ b/third_party/blink/renderer/platform/heap/heap_page.cc
@@ -99,7 +99,7 @@ void HeapObjectHeader::Finalize(Address object, size_t object_size) { HeapAllocHooks::FreeHookIfEnabled(object); const GCInfo* gc_info = GCInfoTable::Get().GCInfoFromIndex(GcInfoIndex()); - if (gc_info->non_trivial_finalizer) + if (gc_info->finalize) gc_info->finalize(object); ASAN_RETIRE_CONTAINER_ANNOTATION(object, object_size);
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 652e330..f530ed60 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -5571,7 +5571,6 @@ crbug.com/874162 [ Mac ] virtual/user-activation-v2/fast/events/selection-autoscroll-borderbelt.html [ Skip ] # Flaky -crbug.com/957916 fullscreen/rendering/backdrop-object.html [ Timeout Pass ] crbug.com/894077 virtual/android/fullscreen/video-fixed-background.html [ Pass Failure ] # Failures on 32-bit Android when using GPU instead of software rendering
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/extension/pointerevent_getCoalescedEvents_when_pointerlocked-manual.html b/third_party/blink/web_tests/external/wpt/pointerevents/extension/pointerevent_getCoalescedEvents_when_pointerlocked.html similarity index 76% rename from third_party/blink/web_tests/external/wpt/pointerevents/extension/pointerevent_getCoalescedEvents_when_pointerlocked-manual.html rename to third_party/blink/web_tests/external/wpt/pointerevents/extension/pointerevent_getCoalescedEvents_when_pointerlocked.html index 6efded8..b8443767 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/extension/pointerevent_getCoalescedEvents_when_pointerlocked-manual.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/extension/pointerevent_getCoalescedEvents_when_pointerlocked.html
@@ -6,6 +6,9 @@ <link rel="stylesheet" type="text/css" href="../pointerevent_styles.css"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> <script type="text/javascript" src="../pointerevent_support.js"></script> <style> #testContainer { @@ -18,6 +21,7 @@ var lock_change_count = 0; var mouseeventMovements = [] var pointereventMovements = [] + var has_coalesced_Events = false; function resetTestState() { } @@ -34,10 +38,18 @@ test_pointerEvent.step(function() { assert_greater_than(event.getCoalescedEvents().length, 0, "document.pointerLockElement should have coalesced events."); document.exitPointerLock(); - test_pointerEvent.done(); + has_coalesced_Events = true;; }); } }); + + // Inject mouse inputs. + pointerDragInTarget('mouse', div1, 'right').then(function() { + test_pointerEvent.step(function () { + assert_true(has_coalesced_Events, "document.pointerLockElement should have coalesced events."); + }, "document.pointerLockElement should have coalesced events."); + test_pointerEvent.done(); + }); } </script> </head> @@ -59,4 +71,4 @@ </div> <div class="spacer"></div> </body> -</html> +</html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_boundary_events_in_capturing-manual.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_boundary_events_in_capturing.html similarity index 91% rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_boundary_events_in_capturing-manual.html rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_boundary_events_in_capturing.html index 0de4d55..1ed26eb 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_boundary_events_in_capturing-manual.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_boundary_events_in_capturing.html
@@ -6,6 +6,9 @@ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> <!-- Additional helper script for common checks across event types --> <script type="text/javascript" src="pointerevent_support.js"></script> <script> @@ -67,6 +70,13 @@ } }); }); + + // Inject pointer inputs. + pointerDragInTarget('mouse', target0, 'right').then(function() { + return pointerDragInTarget('touch', target0, 'right'); + }).then(function() { + return pointerDragInTarget('pen', target0, 'right'); + }); } </script> </head>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_releasepointercapture_events_to_original_target.html similarity index 92% rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_releasepointercapture_events_to_original_target.html index 89f3d839..12e31cdb 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_releasepointercapture_events_to_original_target.html
@@ -8,6 +8,9 @@ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> <!-- Additional helper script for common checks across event types --> <script type="text/javascript" src="pointerevent_support.js"></script> <script type="text/javascript"> @@ -111,6 +114,13 @@ on_event(target0, All_Pointer_Events[i], targetEventHandler); on_event(listener, All_Pointer_Events[i], listenerEventHandler); } + + // Inject pointer inputs. + pointerDragInTarget('mouse', target0, 'right').then(function() { + return pointerDragInTarget('touch', target0, 'right'); + }).then(function() { + return pointerDragInTarget('pen', target0, 'right'); + }); } </script> </head>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_sequence_at_implicit_release_on_drag-manual.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_sequence_at_implicit_release_on_drag.html similarity index 80% rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_sequence_at_implicit_release_on_drag-manual.html rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_sequence_at_implicit_release_on_drag.html index 982167d..88d5eed 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_sequence_at_implicit_release_on_drag-manual.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_sequence_at_implicit_release_on_drag.html
@@ -8,6 +8,9 @@ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> <script type="text/javascript" src="pointerevent_support.js"></script> <script type="text/javascript"> var detected_pointertypes = {}; @@ -23,12 +26,14 @@ function run() { var test_pointer_event = setup_pointerevent_test("Event sequence at implicit release on drag", ["touch"]); + var button = document.getElementById("done"); + var clickIsReceived = false; on_event(document.getElementById("done"), "click", function() { test_pointer_event.step(function () { var expected_events = "pointercancel, lostpointercapture, pointerout, pointerleave"; assert_equals(event_log.join(", "), expected_events); }); - test_pointer_event.done(); + clickIsReceived = true; }); var target = document.getElementById("target"); @@ -48,6 +53,16 @@ } }); }); + + // Inject touch inputs. + pointerDragInTarget("touch", target, 'right').then(function() { + return touchTapInTarget(button); + }).then(function() { + test_pointer_event.step(function () { + assert_true(clickIsReceived, "click should be received before the test finishes"); + }, "click should be received before the test finishes"); + test_pointer_event.done(); + }); } </script> <style>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_movementxy_when_locked-manual.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_movementxy_when_locked.html similarity index 92% rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_movementxy_when_locked-manual.html rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_movementxy_when_locked.html index ccb8c27..bdad97df 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_movementxy_when_locked-manual.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_movementxy_when_locked.html
@@ -6,6 +6,9 @@ <link rel="stylesheet" type="text/css" href="/external/wpt/pointerevents/pointerevent_styles.css"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> <script type="text/javascript" src="../pointerevent_support.js"></script> <style> #testContainer { @@ -59,6 +62,9 @@ test_pointerEvent.done(); } }); + + // Inject mouse inputs. + pointerDragInTarget('mouse', target, 'right'); } </script> </head>
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/extension/pointerevent_getCoalescedEvents_when_pointerlocked-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/extension/pointerevent_getCoalescedEvents_when_pointerlocked-manual-automation.js deleted file mode 100644 index 6d50711..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/extension/pointerevent_getCoalescedEvents_when_pointerlocked-manual-automation.js +++ /dev/null
@@ -1,5 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return pointerDragInTarget('mouse', '#target', 'left'); -}
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_boundary_events_in_capturing-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_boundary_events_in_capturing-manual-automation.js deleted file mode 100644 index 6cd7425..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_boundary_events_in_capturing-manual-automation.js +++ /dev/null
@@ -1,9 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return pointerDragInTarget('mouse', '#target0', 'right').then(function() { - return pointerDragInTarget('touch', '#target0', 'right'); - }).then(function() { - return pointerDragInTarget('pen', '#target0', 'right'); - }); -}
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual-automation.js deleted file mode 100644 index 6cd7425..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual-automation.js +++ /dev/null
@@ -1,9 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return pointerDragInTarget('mouse', '#target0', 'right').then(function() { - return pointerDragInTarget('touch', '#target0', 'right'); - }).then(function() { - return pointerDragInTarget('pen', '#target0', 'right'); - }); -}
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_sequence_at_implicit_release_on_drag-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_sequence_at_implicit_release_on_drag-manual-automation.js deleted file mode 100644 index c0b9fbf..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_sequence_at_implicit_release_on_drag-manual-automation.js +++ /dev/null
@@ -1,7 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return pointerDragInTarget('touch', '#target', 'right').then(function() { - return touchTapInTarget('#done'); - }); -}
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerlock/pointerevent_movementxy_when_locked-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerlock/pointerevent_movementxy_when_locked-manual-automation.js deleted file mode 100644 index 684858a..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerlock/pointerevent_movementxy_when_locked-manual-automation.js +++ /dev/null
@@ -1,5 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return pointerDragInTarget('mouse', '#target', 'right'); -}
diff --git a/third_party/blink/web_tests/fullscreen/rendering/backdrop-object.html b/third_party/blink/web_tests/fullscreen/rendering/backdrop-object.html index 156cbec1..fff65b74 100644 --- a/third_party/blink/web_tests/fullscreen/rendering/backdrop-object.html +++ b/third_party/blink/web_tests/fullscreen/rendering/backdrop-object.html
@@ -8,12 +8,13 @@ </style> <object width="200" type="image/svg+xml" data="../../svg/as-image/resources/circle.svg"></object> <script> +var object = document.querySelector("object"); +Promise.all([ + new Promise((resolve, reject) => document.addEventListener("fullscreenchange", resolve)), + new Promise((resolve, reject) => object.addEventListener("load", resolve)) +]).then(() => testRunner.notifyDone()); + testRunner.waitUntilDone(); var t = { step_func: func => func() }; -trusted_request(t, document.querySelector("object")); -document.addEventListener("fullscreenchange", function() { - document.querySelector("object").addEventListener("load", () => { - testRunner.notifyDone(); - }); -}); +trusted_request(t, object); </script>
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/xr/webxr-origin-trial-interfaces.html b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/xr/webxr-origin-trial-interfaces.html index f099b8be..fe83083 100644 --- a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/xr/webxr-origin-trial-interfaces.html +++ b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/xr/webxr-origin-trial-interfaces.html
@@ -55,9 +55,8 @@ }, "Hit-test properties are not available with a WebXR token."); test(t => { let hittest_interfaces = [ - 'XRHitResult'/*, - TODO(https://crbug.com/958561): Uncomment after resolving the issue. - 'XRRay'*/ + 'XRHitResult', + 'XRRay' ]; OriginTrialsHelper.check_interfaces_missing_unless_runtime_flag( this, hittest_interfaces, 'webXRHitTestEnabled');
diff --git a/third_party/blink/web_tests/plugins/object-change-attribute-reattach.html b/third_party/blink/web_tests/plugins/object-change-attribute-reattach.html new file mode 100644 index 0000000..46c6568 --- /dev/null +++ b/third_party/blink/web_tests/plugins/object-change-attribute-reattach.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<object id="target"></object> +<script> + // Trigger layout now to create LayoutEmbeddedObject + document.body.offsetTop; + + // Changing it to an image should trigger a re-attach as LayoutImage. This is + // the bugfix. Previously this didn't happen. + target.type = "image/gif"; + + // Change some style that would trigger re-layout (also without the fix), and + // creation of a Frame object. + target.style.width = "100px"; + document.body.offsetTop; + + // Without the bugfix, the OBJECT would still be LayoutEmbeddedObject at this + // point, but changing the display type, would trigger reattachment, and + // *then* it would become a LayoutImage (and it would attempt to re-use + // the Frame, because nobody told it not to). + target.style.display = "block"; + document.body.offsetTop; + + test(()=> { }, "No crash or DCHECK failure"); +</script>
diff --git a/third_party/sqlite/amalgamation/sqlite3.c b/third_party/sqlite/amalgamation/sqlite3.c index b84901b..5aaf9ddd 100644 --- a/third_party/sqlite/amalgamation/sqlite3.c +++ b/third_party/sqlite/amalgamation/sqlite3.c
@@ -74663,13 +74663,19 @@ /* ** It is already known that pMem contains an unterminated string. ** Add the zero terminator. +** +** Three bytes of zero are added. In this way, there is guaranteed +** to be a double-zero byte at an even byte boundary in order to +** terminate a UTF16 string, even if the initial size of the buffer +** is an odd number of bytes. */ static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ - if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){ + if( sqlite3VdbeMemGrow(pMem, pMem->n+3, 1) ){ return SQLITE_NOMEM_BKPT; } pMem->z[pMem->n] = 0; pMem->z[pMem->n+1] = 0; + pMem->z[pMem->n+2] = 0; pMem->flags |= MEM_Term; return SQLITE_OK; } @@ -74743,9 +74749,9 @@ } /* -** Add MEM_Str to the set of representations for the given Mem. Numbers -** are converted using sqlite3_snprintf(). Converting a BLOB to a string -** is a no-op. +** Add MEM_Str to the set of representations for the given Mem. This +** routine is only called if pMem is a number of some kind, not a NULL +** or a BLOB. ** ** Existing representations MEM_Int and MEM_Real are invalidated if ** bForce is true but are retained if bForce is false. @@ -83734,7 +83740,7 @@ ** is clear. Otherwise, if this is an ephemeral cursor created by ** OP_OpenDup, the cursor will not be closed and will still be part ** of a BtShared.pCursor list. */ - p->apCsr[iCur]->isEphemeral = 0; + if( p->apCsr[iCur]->pBtx==0 ) p->apCsr[iCur]->isEphemeral = 0; sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); p->apCsr[iCur] = 0; } @@ -87245,7 +87251,10 @@ if( pCx ){ /* If the ephermeral table is already open, erase all existing content ** so that the table is empty again, rather than creating a new table. */ - rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0); + assert( pCx->isEphemeral ); + if( pCx->pBtx ){ + rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0); + } }else{ pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE); if( pCx==0 ) goto no_mem; @@ -222368,7 +222377,7 @@ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ -#if __LINE__!=222371 +#if __LINE__!=222380 #undef SQLITE_SOURCE_ID #define SQLITE_SOURCE_ID "2019-04-16 19:49:53 884b4b7e502b4e991677b53971277adfaf0a04a284f8e483e2553d0f8315alt2" #endif
diff --git a/third_party/sqlite/patched/src/vdbe.c b/third_party/sqlite/patched/src/vdbe.c index 2acc5873..b563627 100644 --- a/third_party/sqlite/patched/src/vdbe.c +++ b/third_party/sqlite/patched/src/vdbe.c
@@ -264,7 +264,7 @@ ** is clear. Otherwise, if this is an ephemeral cursor created by ** OP_OpenDup, the cursor will not be closed and will still be part ** of a BtShared.pCursor list. */ - p->apCsr[iCur]->isEphemeral = 0; + if( p->apCsr[iCur]->pBtx==0 ) p->apCsr[iCur]->isEphemeral = 0; sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); p->apCsr[iCur] = 0; } @@ -3686,7 +3686,10 @@ if( pCx ){ /* If the ephermeral table is already open, erase all existing content ** so that the table is empty again, rather than creating a new table. */ - rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0); + assert( pCx->isEphemeral ); + if( pCx->pBtx ){ + rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0); + } }else{ pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE); if( pCx==0 ) goto no_mem;
diff --git a/third_party/sqlite/patched/src/vdbemem.c b/third_party/sqlite/patched/src/vdbemem.c index 8914aa2..fbcec0f5 100644 --- a/third_party/sqlite/patched/src/vdbemem.c +++ b/third_party/sqlite/patched/src/vdbemem.c
@@ -255,13 +255,19 @@ /* ** It is already known that pMem contains an unterminated string. ** Add the zero terminator. +** +** Three bytes of zero are added. In this way, there is guaranteed +** to be a double-zero byte at an even byte boundary in order to +** terminate a UTF16 string, even if the initial size of the buffer +** is an odd number of bytes. */ static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ - if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){ + if( sqlite3VdbeMemGrow(pMem, pMem->n+3, 1) ){ return SQLITE_NOMEM_BKPT; } pMem->z[pMem->n] = 0; pMem->z[pMem->n+1] = 0; + pMem->z[pMem->n+2] = 0; pMem->flags |= MEM_Term; return SQLITE_OK; } @@ -335,9 +341,9 @@ } /* -** Add MEM_Str to the set of representations for the given Mem. Numbers -** are converted using sqlite3_snprintf(). Converting a BLOB to a string -** is a no-op. +** Add MEM_Str to the set of representations for the given Mem. This +** routine is only called if pMem is a number of some kind, not a NULL +** or a BLOB. ** ** Existing representations MEM_Int and MEM_Real are invalidated if ** bForce is true but are retained if bForce is false.
diff --git a/third_party/sqlite/patched/test/with3.test b/third_party/sqlite/patched/test/with3.test index 0fd21aa..f651207d2 100644 --- a/third_party/sqlite/patched/test/with3.test +++ b/third_party/sqlite/patched/test/with3.test
@@ -130,4 +130,40 @@ `--SEARCH TABLE w1 USING INTEGER PRIMARY KEY (rowid=?) } +do_execsql_test 4.0 { + WITH t5(t5col1) AS ( + SELECT ( + WITH t3(t3col1) AS ( + WITH t2 AS ( + WITH t1 AS (SELECT 1 AS c1 GROUP BY 1) + SELECT a.c1 FROM t1 AS a, t1 AS b + WHERE anoncol1 = 1 + ) + SELECT (SELECT 1 FROM t2) FROM t2 + ) + SELECT t3col1 FROM t3 WHERE t3col1 + ) FROM (SELECT 1 AS anoncol1) + ) + SELECT t5col1, t5col1 FROM t5 +} {1 1} +do_execsql_test 4.1 { + SELECT EXISTS ( + WITH RECURSIVE Table0 AS ( + WITH RECURSIVE Table0(Col0) AS (SELECT ALL 1 ) + SELECT ALL ( + WITH RECURSIVE Table0 AS ( + WITH RECURSIVE Table0 AS ( + WITH RECURSIVE Table0 AS (SELECT DISTINCT 1 GROUP BY 1 ) + SELECT DISTINCT * FROM Table0 NATURAL INNER JOIN Table0 + WHERE Col0 = 1 + ) + SELECT ALL (SELECT DISTINCT * FROM Table0) FROM Table0 WHERE Col0 = 1 + ) + SELECT ALL * FROM Table0 NATURAL INNER JOIN Table0 + ) FROM Table0 ) + SELECT DISTINCT * FROM Table0 NATURAL INNER JOIN Table0 + ); +} {1} + + finish_test
diff --git a/third_party/sqlite/patches/0001-Virtual-table-supporting-recovery-of-corrupted-datab.patch b/third_party/sqlite/patches/0001-Virtual-table-supporting-recovery-of-corrupted-datab.patch index 74daf68b..1bf4742 100644 --- a/third_party/sqlite/patches/0001-Virtual-table-supporting-recovery-of-corrupted-datab.patch +++ b/third_party/sqlite/patches/0001-Virtual-table-supporting-recovery-of-corrupted-datab.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Scott Hess <shess@chromium.org> Date: Sat, 20 Jul 2013 11:42:21 -0700 -Subject: [PATCH 1/4] Virtual table supporting recovery of corrupted databases. +Subject: [PATCH 1/6] Virtual table supporting recovery of corrupted databases. "recover" implements a virtual table which uses the SQLite pager layer to read table pages and pull out the data which is structurally sound
diff --git a/third_party/sqlite/patches/0002-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch b/third_party/sqlite/patches/0002-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch index 5ee7e840..6a2708d 100644 --- a/third_party/sqlite/patches/0002-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch +++ b/third_party/sqlite/patches/0002-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: "tc@google.com" <tc@google.com> Date: Tue, 6 Jan 2009 22:39:41 +0000 -Subject: [PATCH 2/4] Custom shell.c helpers to load Chromium's ICU data. +Subject: [PATCH 2/6] Custom shell.c helpers to load Chromium's ICU data. History uses fts3 with an icu-based segmenter. These changes allow building a sqlite3 binary for Linux or Windows which can read those files.
diff --git a/third_party/sqlite/patches/0003-Don-t-generate-VDBE-code-for-VACUUM-after-a-syntax-e.patch b/third_party/sqlite/patches/0003-Don-t-generate-VDBE-code-for-VACUUM-after-a-syntax-e.patch index dd4d18ea..03e8e7a3 100644 --- a/third_party/sqlite/patches/0003-Don-t-generate-VDBE-code-for-VACUUM-after-a-syntax-e.patch +++ b/third_party/sqlite/patches/0003-Don-t-generate-VDBE-code-for-VACUUM-after-a-syntax-e.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Darwin Huang <huangdarwin@chromium.org> Date: Wed, 1 May 2019 14:44:32 -0700 -Subject: [PATCH 3/4] Don't generate VDBE code for VACUUM after a syntax error +Subject: [PATCH 3/6] Don't generate VDBE code for VACUUM after a syntax error This backports https://www.sqlite.org/src/info/930842470da27d72
diff --git a/third_party/sqlite/patches/0004-Fix-use-after-free-xDestroy-error.patch b/third_party/sqlite/patches/0004-Fix-use-after-free-xDestroy-error.patch index 83387ed..26dd9df 100644 --- a/third_party/sqlite/patches/0004-Fix-use-after-free-xDestroy-error.patch +++ b/third_party/sqlite/patches/0004-Fix-use-after-free-xDestroy-error.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Darwin Huang <huangdarwin@chromium.org> Date: Wed, 1 May 2019 14:47:06 -0700 -Subject: [PATCH 4/4] Fix use-after-free xDestroy error +Subject: [PATCH 4/6] Fix use-after-free xDestroy error This backports https://www.sqlite.org/src/info/1dbbb0101e8213b9
diff --git a/third_party/sqlite/patches/0005-Fix-memory-leak-segfault.patch b/third_party/sqlite/patches/0005-Fix-memory-leak-segfault.patch new file mode 100644 index 0000000..0f91f26 --- /dev/null +++ b/third_party/sqlite/patches/0005-Fix-memory-leak-segfault.patch
@@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Darwin Huang <huangdarwin@chromium.org> +Date: Fri, 3 May 2019 14:46:06 -0700 +Subject: [PATCH 5/6] Fix memory-leak/segfault + +Backports https://www.sqlite.org/src/info/a9b90aa12eecdd9f + +Bug: 958351 +--- + third_party/sqlite/patched/src/vdbe.c | 7 +++-- + third_party/sqlite/patched/test/with3.test | 36 ++++++++++++++++++++++ + 2 files changed, 41 insertions(+), 2 deletions(-) + +diff --git a/third_party/sqlite/patched/src/vdbe.c b/third_party/sqlite/patched/src/vdbe.c +index 2acc5873c531..b563627af83a 100644 +--- a/third_party/sqlite/patched/src/vdbe.c ++++ b/third_party/sqlite/patched/src/vdbe.c +@@ -264,7 +264,7 @@ static VdbeCursor *allocateCursor( + ** is clear. Otherwise, if this is an ephemeral cursor created by + ** OP_OpenDup, the cursor will not be closed and will still be part + ** of a BtShared.pCursor list. */ +- p->apCsr[iCur]->isEphemeral = 0; ++ if( p->apCsr[iCur]->pBtx==0 ) p->apCsr[iCur]->isEphemeral = 0; + sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); + p->apCsr[iCur] = 0; + } +@@ -3686,7 +3686,10 @@ case OP_OpenEphemeral: { + if( pCx ){ + /* If the ephermeral table is already open, erase all existing content + ** so that the table is empty again, rather than creating a new table. */ +- rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0); ++ assert( pCx->isEphemeral ); ++ if( pCx->pBtx ){ ++ rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0); ++ } + }else{ + pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE); + if( pCx==0 ) goto no_mem; +diff --git a/third_party/sqlite/patched/test/with3.test b/third_party/sqlite/patched/test/with3.test +index 0fd21aa92e48..f651207d2901 100644 +--- a/third_party/sqlite/patched/test/with3.test ++++ b/third_party/sqlite/patched/test/with3.test +@@ -130,4 +130,40 @@ do_eqp_test 3.2.2 { + `--SEARCH TABLE w1 USING INTEGER PRIMARY KEY (rowid=?) + } + ++do_execsql_test 4.0 { ++ WITH t5(t5col1) AS ( ++ SELECT ( ++ WITH t3(t3col1) AS ( ++ WITH t2 AS ( ++ WITH t1 AS (SELECT 1 AS c1 GROUP BY 1) ++ SELECT a.c1 FROM t1 AS a, t1 AS b ++ WHERE anoncol1 = 1 ++ ) ++ SELECT (SELECT 1 FROM t2) FROM t2 ++ ) ++ SELECT t3col1 FROM t3 WHERE t3col1 ++ ) FROM (SELECT 1 AS anoncol1) ++ ) ++ SELECT t5col1, t5col1 FROM t5 ++} {1 1} ++do_execsql_test 4.1 { ++ SELECT EXISTS ( ++ WITH RECURSIVE Table0 AS ( ++ WITH RECURSIVE Table0(Col0) AS (SELECT ALL 1 ) ++ SELECT ALL ( ++ WITH RECURSIVE Table0 AS ( ++ WITH RECURSIVE Table0 AS ( ++ WITH RECURSIVE Table0 AS (SELECT DISTINCT 1 GROUP BY 1 ) ++ SELECT DISTINCT * FROM Table0 NATURAL INNER JOIN Table0 ++ WHERE Col0 = 1 ++ ) ++ SELECT ALL (SELECT DISTINCT * FROM Table0) FROM Table0 WHERE Col0 = 1 ++ ) ++ SELECT ALL * FROM Table0 NATURAL INNER JOIN Table0 ++ ) FROM Table0 ) ++ SELECT DISTINCT * FROM Table0 NATURAL INNER JOIN Table0 ++ ); ++} {1} ++ ++ + finish_test +-- +2.21.0.1020.gf2820cf01a-goog +
diff --git a/third_party/sqlite/patches/0006-Ensure-UTF16-strings-are-zero-terminated.patch b/third_party/sqlite/patches/0006-Ensure-UTF16-strings-are-zero-terminated.patch new file mode 100644 index 0000000..3368e3d --- /dev/null +++ b/third_party/sqlite/patches/0006-Ensure-UTF16-strings-are-zero-terminated.patch
@@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Darwin Huang <huangdarwin@chromium.org> +Date: Fri, 3 May 2019 14:49:17 -0700 +Subject: [PATCH 6/6] Ensure UTF16 strings are zero-terminated + +Backports https://www.sqlite.org/src/info/3a16ddf91f0c9c51 + +Bug: 959193 +--- + third_party/sqlite/patched/src/vdbemem.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/third_party/sqlite/patched/src/vdbemem.c b/third_party/sqlite/patched/src/vdbemem.c +index 8914aa269758..fbcec0f59c18 100644 +--- a/third_party/sqlite/patched/src/vdbemem.c ++++ b/third_party/sqlite/patched/src/vdbemem.c +@@ -255,13 +255,19 @@ int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ + /* + ** It is already known that pMem contains an unterminated string. + ** Add the zero terminator. ++** ++** Three bytes of zero are added. In this way, there is guaranteed ++** to be a double-zero byte at an even byte boundary in order to ++** terminate a UTF16 string, even if the initial size of the buffer ++** is an odd number of bytes. + */ + static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ +- if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){ ++ if( sqlite3VdbeMemGrow(pMem, pMem->n+3, 1) ){ + return SQLITE_NOMEM_BKPT; + } + pMem->z[pMem->n] = 0; + pMem->z[pMem->n+1] = 0; ++ pMem->z[pMem->n+2] = 0; + pMem->flags |= MEM_Term; + return SQLITE_OK; + } +@@ -335,9 +341,9 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){ + } + + /* +-** Add MEM_Str to the set of representations for the given Mem. Numbers +-** are converted using sqlite3_snprintf(). Converting a BLOB to a string +-** is a no-op. ++** Add MEM_Str to the set of representations for the given Mem. This ++** routine is only called if pMem is a number of some kind, not a NULL ++** or a BLOB. + ** + ** Existing representations MEM_Int and MEM_Real are invalidated if + ** bForce is true but are retained if bForce is false. +-- +2.21.0.1020.gf2820cf01a-goog +
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index bd2c455..93eabbe 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -5885,6 +5885,11 @@ <int value="1" label="Needs to be duplications cleared"/> </enum> +<enum name="BooleanNeedsNormalization"> + <int value="0" label="Doesn't need normalization"/> + <int value="1" label="Needs normalization"/> +</enum> + <enum name="BooleanNetworkQuietBeforeSwap"> <int value="0" label="FMP OK, network not yet quiet"/> <int value="1" label="FMP not OK, network was already quiet"/> @@ -32761,6 +32766,8 @@ <int value="-1677715989" label="UnifiedConsent:disabled"/> <int value="-1676256979" label="AutofillUpstreamUseGooglePayOnAndroidBranding:enabled"/> + <int value="-1672160462" + label="SwapSideVolumeButtonsForOrientation:disabled"/> <int value="-1670137340" label="OptimizeLoadingIPCForSmallResources:disabled"/> <int value="-1669486359" label="ImportantSitesInCBD:enabled"/> @@ -32895,6 +32902,7 @@ <int value="-1473878093" label="HideArcMediaNotifications:disabled"/> <int value="-1473668019" label="token-binding:disabled"/> <int value="-1473136627" label="enable-web-payments"/> + <int value="-1472825316" label="ContextualSearchLongpressResolve:enabled"/> <int value="-1471021059" label="OmniboxUIExperimentShowSuggestionFavicons:disabled"/> <int value="-1469536698" label="ChromeHomeDoodle:enabled"/> @@ -33588,6 +33596,7 @@ <int value="-456321929" label="ForceEnableSystemAec:disabled"/> <int value="-455203267" label="use_new_features_summary"/> <int value="-449465495" label="disable-browser-task-scheduler"/> + <int value="-438379844" label="SwapSideVolumeButtonsForOrientation:enabled"/> <int value="-436470115" label="TouchpadAndWheelScrollLatching:enabled"/> <int value="-435914745" label="ClipboardContentSetting:disabled"/> <int value="-430360431" label="disable-password-generation"/> @@ -33944,6 +33953,7 @@ <int value="92327255" label="DisplayMoveWindowAccels:disabled"/> <int value="93832899" label="NtpCustomizationMenuV2:enabled"/> <int value="98134240" label="material-design-ink-drop-animation-speed"/> + <int value="98218116" label="ContextualSearchLongpressResolve:disabled"/> <int value="99177659" label="OmniboxUICuesForSearchHistoryMatches:disabled"/> <int value="103932290" label="show-autofill-type-predictions"/> <int value="105046382" label="ParallelDownloading:disabled"/> @@ -38768,6 +38778,13 @@ <int value="3" label="NO_ENTRY"/> </enum> +<enum name="NetCertificateNameNormalization"> + <int value="0" label="Error parsing certificate chain"/> + <int value="1" label="Byte equal Names"/> + <int value="2" label="Normalized Names"/> + <int value="3" label="Chain contained only one certificate"/> +</enum> + <enum name="NetConnectivityProtocolStatus"> <int value="0" label="SUCCESS"/> <int value="1" label="IP_STRING_PARSE_FAILED"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 5d20341a..0b8cd3c 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -63931,6 +63931,16 @@ </summary> </histogram> +<histogram base="true" name="Net.CertVerifier.NameNormalizationPrivateRoots" + enum="NetCertificateNameNormalization" expires_after="2020-06-01"> + <owner>mattm@chromium.org</owner> + <summary> + Whether Name normalization was used in successfully validated certificate + chains, only recorded for chains ending in privately trusted roots. Suffixed + by the CertVerifyProc implementation. + </summary> +</histogram> + <histogram name="Net.CertVerifier_First_Job_Latency" units="ms" expires_after="M77"> <owner>davidben@chromium.org</owner> @@ -64400,6 +64410,17 @@ </summary> </histogram> +<histogram name="Net.Cors.ActiveLoaderCount" units="entries" + expires_after="M77"> + <owner>toyoshim@chromium.org</owner> + <owner>yhirano@chromium.org</owner> + <summary> + The distribution of active mojom::URLLoader instance counts including + network::URLLoader and network::CorsURLLoader in the network service. This + reports every 5 minutes. + </summary> +</histogram> + <histogram name="Net.Cors.CompletionStatus" enum="CorsCompletionStatus" expires_after="M77"> <owner>toyoshim@chromium.org</owner> @@ -64416,7 +64437,7 @@ <owner>yhirano@chromium.org</owner> <summary> The distribution of the number of cache entries in the CORS preflight cache. - This counts the cache entries every hour. + This counts the cache entries every 5 minutes. </summary> </histogram> @@ -64430,6 +64451,17 @@ </summary> </histogram> +<histogram name="Net.Cors.PreflightCacheTotalEntries" units="entries" + expires_after="M77"> + <owner>toyoshim@chromium.org</owner> + <owner>yhirano@chromium.org</owner> + <summary> + The distribution of the total number of cache entries that is sum of all + CORS preflight cache entries in the network service. This counts the cache + entries every 5 minutes. + </summary> +</histogram> + <histogram name="Net.CountOfAlternateProtocolServers" units="servers" expires_after="M77"> <owner>bnc@chromium.org</owner> @@ -87727,6 +87759,16 @@ </summary> </histogram> +<histogram name="PasswordManager.BlacklistedSites.NeedNormalization" + enum="BooleanNeedsNormalization" expires_after="M80"> + <owner>jdoerrie@chromium.org</owner> + <owner>vasilii@chromium.org</owner> + <summary> + Records once on startup whether the blacklisted sites in the password store + need to be normalized. + </summary> +</histogram> + <histogram name="PasswordManager.BlacklistedSites.NeedRemoveBlacklistDuplicates" enum="BooleanNeedsDeDuplication" expires_after="M73"> @@ -143611,6 +143653,10 @@ <histogram_suffixes name="AppListTabletModeTransition" separator="."> <suffix name="DragReleaseHide" label="Release drag to hide the app list"/> <suffix name="DragReleaseShow" label="Release drag to show the app list"/> + <suffix name="EnterFullscreenAllApps" + label="Enter kFullScreenAllApps state in tablet"/> + <suffix name="EnterFullscreenSearch" + label="Enter kFullscreenSearch state in tablet"/> <suffix name="EnterOverview" label="Enter overview mode in tablet"/> <suffix name="ExitOverview" label="Exit overview mode in tablet"/> <suffix name="HideLauncherForWindow" @@ -144688,6 +144734,16 @@ <affected-histogram name="DiskBasedCertCache.CertIo"/> </histogram_suffixes> +<histogram_suffixes name="CertVerifyProcImpl" separator="."> + <suffix name="Android" label="CertVerifyProcAndroid"/> + <suffix name="Builtin" label="CertVerifyProcBuiltin"/> + <suffix name="IOS" label="CertVerifyProcIOS"/> + <suffix name="Mac" label="CertVerifyProcMac"/> + <suffix name="NSS" label="CertVerifyProcNSS"/> + <suffix name="Win" label="CertVerifyProcWin"/> + <affected-histogram name="Net.CertVerifier.NameNormalizationPrivateRoots"/> +</histogram_suffixes> + <histogram_suffixes name="ChromeActivityName" separator="."> <suffix name="ChromeTabbedActivity" label="Activity launched in TABBED mode on Android"/>
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc index def47a6..b0cda21 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
@@ -2186,6 +2186,7 @@ text_data.id = 2; text_data.role = ax::mojom::Role::kStaticText; text_data.AddStringAttribute(ax::mojom::StringAttribute::kFontFamily, "sans"); + text_data.AddFloatAttribute(ax::mojom::FloatAttribute::kFontSize, 16); text_data.AddFloatAttribute(ax::mojom::FloatAttribute::kFontWeight, 300); text_data.AddIntAttribute(ax::mojom::IntAttribute::kTextOverlineStyle, 1); text_data.AddIntAttribute(ax::mojom::IntAttribute::kTextStrikethroughStyle, @@ -2369,6 +2370,11 @@ expected_variant); expected_variant.Reset(); + expected_variant.Set(16.0f); + EXPECT_UIA_TEXTATTRIBUTE_EQ(text_range_provider, UIA_FontSizeAttributeId, + expected_variant); + expected_variant.Reset(); + expected_variant.Set(300); EXPECT_UIA_TEXTATTRIBUTE_EQ(text_range_provider, UIA_FontWeightAttributeId, expected_variant);
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index 0007dbe..c913d099 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -4095,6 +4095,14 @@ V_VT(result) = VT_BSTR; V_BSTR(result) = GetFontNameAttributeAsBSTR(); break; + case UIA_FontSizeAttributeId: + V_VT(result) = VT_R8; + V_R8(result) = GetFloatAttribute(ax::mojom::FloatAttribute::kFontSize); + break; + case UIA_FontWeightAttributeId: + V_VT(result) = VT_I4; + V_I4(result) = GetFloatAttribute(ax::mojom::FloatAttribute::kFontWeight); + break; case UIA_ForegroundColorAttributeId: V_VT(result) = VT_I4; V_I4(result) = GetIntAttributeAsCOLORREF(ax::mojom::IntAttribute::kColor);
diff --git a/ui/gfx/linux/native_pixmap_dmabuf.cc b/ui/gfx/linux/native_pixmap_dmabuf.cc index 9442a7f..8327892 100644 --- a/ui/gfx/linux/native_pixmap_dmabuf.cc +++ b/ui/gfx/linux/native_pixmap_dmabuf.cc
@@ -43,9 +43,12 @@ return planes_[plane].offset; } -uint64_t NativePixmapDmaBuf::GetDmaBufModifier(size_t plane) const { - DCHECK_LT(plane, planes_.size()); - return planes_[plane].modifier; +uint64_t NativePixmapDmaBuf::GetBufferFormatModifier() const { + // Modifiers must be the same on all the planes. Return the modifier of the + // first plane. + // TODO(crbug.com/957381): Move modifier variable to NativePixmapHandle from + // NativePixmapPlane. + return planes_[0].modifier; } gfx::BufferFormat NativePixmapDmaBuf::GetBufferFormat() const {
diff --git a/ui/gfx/linux/native_pixmap_dmabuf.h b/ui/gfx/linux/native_pixmap_dmabuf.h index cea9d0c..eeca6cc5 100644 --- a/ui/gfx/linux/native_pixmap_dmabuf.h +++ b/ui/gfx/linux/native_pixmap_dmabuf.h
@@ -32,7 +32,7 @@ int GetDmaBufFd(size_t plane) const override; int GetDmaBufPitch(size_t plane) const override; int GetDmaBufOffset(size_t plane) const override; - uint64_t GetDmaBufModifier(size_t plane) const override; + uint64_t GetBufferFormatModifier() const override; gfx::BufferFormat GetBufferFormat() const override; gfx::Size GetBufferSize() const override; uint32_t GetUniqueId() const override;
diff --git a/ui/gfx/linux/native_pixmap_dmabuf_unittest.cc b/ui/gfx/linux/native_pixmap_dmabuf_unittest.cc index 624f7fa..c1c9c3c 100644 --- a/ui/gfx/linux/native_pixmap_dmabuf_unittest.cc +++ b/ui/gfx/linux/native_pixmap_dmabuf_unittest.cc
@@ -28,7 +28,7 @@ const int stride = (i + 1) * image_size.width(); const int offset = i * image_size.width() * image_size.height(); const uint64_t size = stride * image_size.height(); - const uint64_t modifiers = 1 << i; + const uint64_t modifiers = 1; base::ScopedFD fd(open("/dev/zero", O_RDONLY)); EXPECT_TRUE(fd.is_valid()); @@ -68,7 +68,7 @@ handle_clone.planes[i].stride); EXPECT_EQ(native_pixmap_dmabuf->GetDmaBufOffset(i), handle_clone.planes[i].offset); - EXPECT_EQ(native_pixmap_dmabuf->GetDmaBufModifier(i), + EXPECT_EQ(native_pixmap_dmabuf->GetBufferFormatModifier(), handle_clone.planes[i].modifier); } }
diff --git a/ui/gfx/native_pixmap.h b/ui/gfx/native_pixmap.h index f8ba1fd..7446359 100644 --- a/ui/gfx/native_pixmap.h +++ b/ui/gfx/native_pixmap.h
@@ -29,8 +29,11 @@ virtual int GetDmaBufFd(size_t plane) const = 0; virtual int GetDmaBufPitch(size_t plane) const = 0; virtual int GetDmaBufOffset(size_t plane) const = 0; - virtual uint64_t GetDmaBufModifier(size_t plane) const = 0; + + // The following methods return format, modifier and size of the buffer, + // respectively. virtual gfx::BufferFormat GetBufferFormat() const = 0; + virtual uint64_t GetBufferFormatModifier() const = 0; virtual gfx::Size GetBufferSize() const = 0; // Return an id that is guaranteed to be unique and equal for all instances
diff --git a/ui/gl/gl_image_native_pixmap.cc b/ui/gl/gl_image_native_pixmap.cc index d8a1543b..77dc777 100644 --- a/ui/gl/gl_image_native_pixmap.cc +++ b/ui/gl/gl_image_native_pixmap.cc
@@ -184,9 +184,9 @@ attrs.push_back(pixmap->GetDmaBufOffset(pixmap_plane)); attrs.push_back(EGL_DMA_BUF_PLANE0_PITCH_EXT + attrs_plane * 3); attrs.push_back(pixmap->GetDmaBufPitch(pixmap_plane)); + uint64_t modifier = pixmap->GetBufferFormatModifier(); if (has_dma_buf_import_modifier && - pixmap->GetDmaBufModifier(0) != gfx::NativePixmapPlane::kNoModifier) { - uint64_t modifier = pixmap->GetDmaBufModifier(pixmap_plane); + modifier != gfx::NativePixmapPlane::kNoModifier) { DCHECK(attrs_plane < base::size(kLinuxDrmModifiers)); attrs.push_back(kLinuxDrmModifiers[attrs_plane]); attrs.push_back(modifier & 0xffffffff);
diff --git a/ui/ozone/platform/cast/surface_factory_cast.cc b/ui/ozone/platform/cast/surface_factory_cast.cc index 41d4389..11ccb3c 100644 --- a/ui/ozone/platform/cast/surface_factory_cast.cc +++ b/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -53,7 +53,7 @@ int GetDmaBufFd(size_t plane) const override { return -1; } int GetDmaBufPitch(size_t plane) const override { return 0; } int GetDmaBufOffset(size_t plane) const override { return 0; } - uint64_t GetDmaBufModifier(size_t plane) const override { return 0; } + uint64_t GetBufferFormatModifier() const override { return 0; } gfx::BufferFormat GetBufferFormat() const override { return gfx::BufferFormat::BGRA_8888; }
diff --git a/ui/ozone/platform/drm/gpu/gbm_pixmap.cc b/ui/ozone/platform/drm/gpu/gbm_pixmap.cc index 2d80356..fbe77fbb4 100644 --- a/ui/ozone/platform/drm/gpu/gbm_pixmap.cc +++ b/ui/ozone/platform/drm/gpu/gbm_pixmap.cc
@@ -44,7 +44,7 @@ return buffer_->GetPlaneOffset(plane); } -uint64_t GbmPixmap::GetDmaBufModifier(size_t plane) const { +uint64_t GbmPixmap::GetBufferFormatModifier() const { return buffer_->GetFormatModifier(); }
diff --git a/ui/ozone/platform/drm/gpu/gbm_pixmap.h b/ui/ozone/platform/drm/gpu/gbm_pixmap.h index c10420b8..d6de7628 100644 --- a/ui/ozone/platform/drm/gpu/gbm_pixmap.h +++ b/ui/ozone/platform/drm/gpu/gbm_pixmap.h
@@ -29,7 +29,7 @@ int GetDmaBufFd(size_t plane) const override; int GetDmaBufPitch(size_t plane) const override; int GetDmaBufOffset(size_t plane) const override; - uint64_t GetDmaBufModifier(size_t plane) const override; + uint64_t GetBufferFormatModifier() const override; gfx::BufferFormat GetBufferFormat() const override; gfx::Size GetBufferSize() const override; uint32_t GetUniqueId() const override;
diff --git a/ui/ozone/platform/headless/headless_surface_factory.cc b/ui/ozone/platform/headless/headless_surface_factory.cc index 4a751a1a..4647a53 100644 --- a/ui/ozone/platform/headless/headless_surface_factory.cc +++ b/ui/ozone/platform/headless/headless_surface_factory.cc
@@ -85,7 +85,7 @@ int GetDmaBufFd(size_t plane) const override { return -1; } int GetDmaBufPitch(size_t plane) const override { return 0; } int GetDmaBufOffset(size_t plane) const override { return 0; } - uint64_t GetDmaBufModifier(size_t plane) const override { return 0; } + uint64_t GetBufferFormatModifier() const override { return 0; } gfx::BufferFormat GetBufferFormat() const override { return format_; } gfx::Size GetBufferSize() const override { return gfx::Size(); } uint32_t GetUniqueId() const override { return 0; }
diff --git a/ui/ozone/platform/scenic/sysmem_buffer_collection.cc b/ui/ozone/platform/scenic/sysmem_buffer_collection.cc index fedc834..5ac57bbe 100644 --- a/ui/ozone/platform/scenic/sysmem_buffer_collection.cc +++ b/ui/ozone/platform/scenic/sysmem_buffer_collection.cc
@@ -33,7 +33,7 @@ NOTREACHED(); return 0; } - uint64_t GetDmaBufModifier(size_t plane) const override { + uint64_t GetBufferFormatModifier() const override { NOTREACHED(); return 0; } @@ -385,4 +385,4 @@ vk_image_info->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; } -} // namespace ui \ No newline at end of file +} // namespace ui
diff --git a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc index 960afcd..f76f08f 100644 --- a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc +++ b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
@@ -100,7 +100,7 @@ return gbm_bo_->GetPlaneOffset(plane); } -uint64_t GbmPixmapWayland::GetDmaBufModifier(size_t plane) const { +uint64_t GbmPixmapWayland::GetBufferFormatModifier() const { return gbm_bo_->GetFormatModifier(); } @@ -149,9 +149,9 @@ } for (size_t i = 0; i < num_planes; ++i) { - handle.planes.emplace_back(GetDmaBufPitch(i), GetDmaBufOffset(i), - gbm_bo_->GetPlaneSize(i), - std::move(scoped_fds[i]), GetDmaBufModifier(i)); + handle.planes.emplace_back( + GetDmaBufPitch(i), GetDmaBufOffset(i), gbm_bo_->GetPlaneSize(i), + std::move(scoped_fds[i]), GetBufferFormatModifier()); } return handle; }
diff --git a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h index b99a36d..9cb9f8f0 100644 --- a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h +++ b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h
@@ -36,7 +36,7 @@ int GetDmaBufFd(size_t plane) const override; int GetDmaBufPitch(size_t plane) const override; int GetDmaBufOffset(size_t plane) const override; - uint64_t GetDmaBufModifier(size_t plane) const override; + uint64_t GetBufferFormatModifier() const override; gfx::BufferFormat GetBufferFormat() const override; gfx::Size GetBufferSize() const override; uint32_t GetUniqueId() const override;
diff --git a/ui/webui/resources/cr_components/certificate_manager/certificate_list.js b/ui/webui/resources/cr_components/certificate_manager/certificate_list.js index 6f9646e..7a2f1fe 100644 --- a/ui/webui/resources/cr_components/certificate_manager/certificate_list.js +++ b/ui/webui/resources/cr_components/certificate_manager/certificate_list.js
@@ -130,8 +130,7 @@ * @private */ onImportTap_: function(e) { - this.handleImport_( - false, /** @type {!HTMLElement} */ (Polymer.dom(e).localTarget)); + this.handleImport_(false, /** @type {!HTMLElement} */ (e.target)); }, // <if expr="chromeos"> @@ -140,8 +139,7 @@ * @param {!Event} e */ onImportAndBindTap_: function(e) { - this.handleImport_( - true, /** @type {!HTMLElement} */ (Polymer.dom(e).localTarget)); + this.handleImport_(true, /** @type {!HTMLElement} */ (e.target)); }, // </if>
diff --git a/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js b/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js index fb367837..4e12334 100644 --- a/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js +++ b/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js
@@ -164,7 +164,12 @@ // If nothing selected, start from the first radio then add |delta|. const lastSelection = enabledRadios.findIndex(radio => radio.checked); selectedIndex = Math.max(0, lastSelection) + delta; - selectedIndex = Math.min(max, Math.max(0, selectedIndex)); + // Wrap the selection, if needed. + if (selectedIndex > max) { + selectedIndex = 0; + } else if (selectedIndex < 0) { + selectedIndex = max; + } } else { return; }