diff --git a/BUILD.gn b/BUILD.gn index 9baf7278..eeb73b1 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -817,6 +817,7 @@ "//chrome", "//chrome/test/chromedriver", "//media:media_unittests", + "//media/gpu:jpeg_decode_accelerator_unittest", "//ppapi/examples/video_decode", "//sandbox/linux:chrome_sandbox", "//sandbox/linux:sandbox_linux_unittests",
diff --git a/DEPS b/DEPS index 4699a83..e730c080 100644 --- a/DEPS +++ b/DEPS
@@ -105,11 +105,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': '29a4a684af2525d78a1090fba2d3dea2b6a59fc7', + 'skia_revision': '0c3dc59fc1c61e6f54cf3d0100e54ee0d20ec13d', # 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': '1b573e9fca9fcd54985cb34889d7c895314b9ec3', + 'v8_revision': '1b63139d35984e457e9fce65b6240b5ea3fb8208', # 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. @@ -117,7 +117,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '750e508722a9405278dfb1809f7ce667a3681072', + 'angle_revision': '7359954301e131a2b1f326ef391669dbd7562d0d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -129,7 +129,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '424621e3129f7029283f72e953fe0c69f982d257', + 'pdfium_revision': 'ad370480282dd788afc80563cebb492c02644998', # 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. @@ -165,7 +165,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '638bda3a17c0a74db0e2cbd9a3f68a8419f9e7db', + 'catapult_revision': 'bcc3e491fb2e0c8776976913571b4c7355179c62', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -213,7 +213,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_tools_revision': '58e53ea82f259ed81a41c8165c749add49354380', + 'spv_tools_revision': 'b27d084b0112ca7e33262dabffe5b88dbad56673', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -313,7 +313,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '3c3b852f96c0e2351fa4d8512e175b35f92e757a', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'e58ee91454ff891892f2ac239a3e9875063da454', 'condition': 'checkout_ios', }, @@ -579,7 +579,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '8a49a283b96c36a16538c6e3893a5661c987501f', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'f23b4ab8b8898f205b65302279c1937bdb2b5674', 'condition': 'checkout_linux', }, @@ -604,7 +604,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e6438547360b8cb0469095dffccc53faaac24477', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '01f0c698fb898168940718c5616ed3f6bb6c1b18', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1098,7 +1098,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '7ca87fb1d3da3b3d2060886e8c58e726d74c8219', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '62228c41ea17b1f33ab85e80962a931ef74aa593', + Var('webrtc_git') + '/src.git' + '@' + 'b9bb9e3f6683a74acab9198359d17a3b68644338', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/android_webview/browser/input_stream_unittest.cc b/android_webview/browser/input_stream_unittest.cc index 02d525e..b41e6e4 100644 --- a/android_webview/browser/input_stream_unittest.cc +++ b/android_webview/browser/input_stream_unittest.cc
@@ -48,7 +48,7 @@ std::unique_ptr<InputStream> input_stream( new InputStream(counting_jstream)); - scoped_refptr<IOBuffer> buffer = new IOBuffer(bytes_requested); + auto buffer = base::MakeRefCounted<IOBuffer>(bytes_requested); EXPECT_TRUE(input_stream->Read(buffer.get(), bytes_requested, bytes_read)); return buffer; @@ -65,7 +65,7 @@ std::unique_ptr<InputStream> input_stream(new InputStream(empty_jstream)); const int bytes_requested = 10; int bytes_read = 0; - scoped_refptr<IOBuffer> buffer = new IOBuffer(bytes_requested); + auto buffer = base::MakeRefCounted<IOBuffer>(bytes_requested); EXPECT_TRUE(input_stream->Read(buffer.get(), bytes_requested, &bytes_read)); EXPECT_EQ(0, bytes_read); @@ -132,7 +132,7 @@ const int bytes_requested = 10; int bytes_read = 0; - scoped_refptr<IOBuffer> buffer = new IOBuffer(bytes_requested); + auto buffer = base::MakeRefCounted<IOBuffer>(bytes_requested); EXPECT_FALSE(input_stream->Read(buffer.get(), bytes_requested, &bytes_read)); EXPECT_EQ(0, bytes_read);
diff --git a/android_webview/browser/net/input_stream_reader_unittest.cc b/android_webview/browser/net/input_stream_reader_unittest.cc index b7aec52..3125579 100644 --- a/android_webview/browser/net/input_stream_reader_unittest.cc +++ b/android_webview/browser/net/input_stream_reader_unittest.cc
@@ -142,7 +142,7 @@ TEST_F(InputStreamReaderTest, ReadFailure) { const int bytesToRead = 128; - scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(bytesToRead); + auto buffer = base::MakeRefCounted<net::IOBuffer>(bytesToRead); EXPECT_CALL(input_stream_, Read(buffer.get(), bytesToRead, NotNull())) .WillOnce(Return(false)); @@ -152,7 +152,7 @@ TEST_F(InputStreamReaderTest, ReadNothing) { const int bytesToRead = 0; // Size of net::IOBuffer can't be 0. - scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(1); + auto buffer = base::MakeRefCounted<net::IOBuffer>(1); EXPECT_CALL(input_stream_, Read(buffer.get(), bytesToRead, NotNull())) .Times(0); @@ -161,7 +161,7 @@ TEST_F(InputStreamReaderTest, ReadSuccess) { const int bytesToRead = 128; - scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(bytesToRead); + auto buffer = base::MakeRefCounted<net::IOBuffer>(bytesToRead); EXPECT_CALL(input_stream_, Read(buffer.get(), bytesToRead, NotNull())) .WillOnce(DoAll(SetArgPointee<2>(bytesToRead),
diff --git a/ash/app_list/views/app_list_item_view.cc b/ash/app_list/views/app_list_item_view.cc index 2109b0e..5069d473 100644 --- a/ash/app_list/views/app_list_item_view.cc +++ b/ash/app_list/views/app_list_item_view.cc
@@ -27,6 +27,7 @@ #include "ui/gfx/canvas.h" #include "ui/gfx/font_list.h" #include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/image/canvas_image_source.h" #include "ui/gfx/image/image_skia_operations.h" @@ -80,35 +81,37 @@ // The shadow color of icon. constexpr SkColor kIconShadowColor = SkColorSetA(SK_ColorBLACK, 31); -// The class clips the provided folder icon image. -class ClippedFolderIconImageSource : public gfx::CanvasImageSource { +// The class clips the provided icon image. +class ClippedIconImageSource : public gfx::CanvasImageSource { public: - explicit ClippedFolderIconImageSource(const gfx::ImageSkia& image) - : gfx::CanvasImageSource(AppListConfig::instance().folder_icon_size(), - false), - image_(image) {} - ~ClippedFolderIconImageSource() override = default; + ClippedIconImageSource(const gfx::ImageSkia& image, + const gfx::Size& clipped_size) + : gfx::CanvasImageSource(clipped_size, false), + image_(image), + clipped_size_(clipped_size) {} + ~ClippedIconImageSource() override = default; void Draw(gfx::Canvas* canvas) override { // Draw the unclipped icon on the center of the canvas with a circular mask. - const gfx::Size size = AppListConfig::instance().folder_icon_size(); gfx::Path circular_mask; - circular_mask.addCircle(SkFloatToScalar(size.width() / 2), - SkFloatToScalar(size.height() / 2), - SkIntToScalar(size.width() / 2)); + circular_mask.addCircle(SkFloatToScalar(clipped_size_.width() / 2), + SkFloatToScalar(clipped_size_.height() / 2), + SkIntToScalar(clipped_size_.width() / 2)); cc::PaintFlags flags; flags.setStyle(cc::PaintFlags::kFill_Style); flags.setAntiAlias(true); - canvas->DrawImageInPath(image_, (size.width() - image_.size().width()) / 2, - (size.height() - image_.size().height()) / 2, - circular_mask, flags); + canvas->DrawImageInPath( + image_, (clipped_size_.width() - image_.size().width()) / 2, + (clipped_size_.height() - image_.size().height()) / 2, circular_mask, + flags); } private: const gfx::ImageSkia image_; + const gfx::Size clipped_size_; - DISALLOW_COPY_AND_ASSIGN(ClippedFolderIconImageSource); + DISALLOW_COPY_AND_ASSIGN(ClippedIconImageSource); }; } // namespace @@ -175,7 +178,9 @@ AddChildView(title_); AddChildView(progress_bar_); - SetIcon(item->icon()); + SetIcon( + item->icon(), is_folder_ /* clip */, + is_folder_ ? AppListConfig::instance().folder_icon_size() : gfx::Size()); SetItemName(base::UTF8ToUTF16(item->GetDisplayName()), base::UTF8ToUTF16(item->name())); SetItemIsInstalling(item->is_installing()); @@ -187,7 +192,6 @@ SetAnimationDuration(0); preview_circle_radius_ = 0; - folder_icon_insets_ = AppListConfig::instance().folder_icon_insets(); } AppListItemView::~AppListItemView() { @@ -195,7 +199,9 @@ item_weak_->RemoveObserver(this); } -void AppListItemView::SetIcon(const gfx::ImageSkia& icon) { +void AppListItemView::SetIcon(const gfx::ImageSkia& icon, + bool clip, + const gfx::Size& clipped_size) { // Clear icon and bail out if item icon is empty. if (icon.isNull()) { icon_->SetImage(nullptr); @@ -204,23 +210,28 @@ return; } - gfx::ImageSkia resized(gfx::ImageSkiaOperations::CreateResizedImage( + gfx::ImageSkia resized = gfx::ImageSkiaOperations::CreateResizedImage( icon, skia::ImageOperations::RESIZE_BEST, is_folder_ ? AppListConfig::instance().folder_unclipped_icon_size() - : AppListConfig::instance().grid_icon_size())); + : AppListConfig::instance().grid_icon_size()); + + gfx::ImageSkia clipped = + clip ? gfx::CanvasImageSource::MakeImageSkia<ClippedIconImageSource>( + resized, clipped_size) + : icon; + if (shadow_animator_) - shadow_animator_->SetOriginalImage(resized); + shadow_animator_->SetOriginalImage(clipped); else - icon_->SetImage(resized); + icon_->SetImage(clipped); if (icon_shadow_) { // Create a shadow for the shown icon. gfx::ImageSkia shadowed = gfx::ImageSkiaOperations::CreateImageWithDropShadow( - GetIconImage(), - gfx::ShadowValues(1, - gfx::ShadowValue(gfx::Vector2d(), kIconShadowBlur, - kIconShadowColor))); + clipped, gfx::ShadowValues( + 1, gfx::ShadowValue(gfx::Vector2d(), kIconShadowBlur, + kIconShadowColor))); icon_shadow_->SetImage(shadowed); } @@ -523,18 +534,6 @@ GetIconBoundsForTargetViewBounds(rect, icon_shadow_->GetImage().size()); icon_shadow_->SetBoundsRect(icon_shadow_bounds); } - if (is_new_style_launcher_enabled_ && is_folder_) { - // Add a folder icon mask to clip the folder icon. - folder_icon_mask_ = views::Painter::CreatePaintedLayer( - views::Painter::CreateSolidRoundRectPainter( - SK_ColorBLACK, - AppListConfig::instance().folder_unclipped_icon_dimension() / 2 - - folder_icon_insets_, - gfx::Insets(folder_icon_insets_, folder_icon_insets_))); - folder_icon_mask_->layer()->SetFillsBoundsOpaquely(false); - folder_icon_mask_->layer()->SetBounds(icon_bounds); - icon_->layer()->SetMaskLayer(folder_icon_mask_->layer()); - } title_->SetBoundsRect( GetTitleBoundsForTargetViewBounds(rect, title_->GetPreferredSize())); SetTitleSubpixelAA(); @@ -697,10 +696,12 @@ void AppListItemView::AnimationProgressed(const gfx::Animation* animation) { if (is_folder_) { - folder_icon_insets_ = gfx::Tween::IntValueBetween( - animation->GetCurrentValue(), - AppListConfig::instance().folder_icon_insets(), 0); - Layout(); + SetIcon(item_weak_->icon(), true /* clip */, + gfx::ToRoundedSize(gfx::Tween::SizeValueBetween( + animation->GetCurrentValue(), + gfx::SizeF(AppListConfig::instance().folder_icon_size()), + gfx::SizeF( + AppListConfig::instance().folder_unclipped_icon_size())))); return; } @@ -739,8 +740,8 @@ if (!is_folder_) return icon_->GetImage(); - return gfx::CanvasImageSource::MakeImageSkia<ClippedFolderIconImageSource>( - icon_->GetImage()); + return gfx::CanvasImageSource::MakeImageSkia<ClippedIconImageSource>( + icon_->GetImage(), AppListConfig::instance().folder_icon_size()); } void AppListItemView::SetIconVisible(bool visible) { @@ -806,7 +807,22 @@ void AppListItemView::ItemIconChanged() { DCHECK(item_weak_); - SetIcon(item_weak_->icon()); + if (!is_folder_) { + SetIcon(item_weak_->icon(), false /* clip */, gfx::Size()); + return; + } + + gfx::Size clipped_size = AppListConfig::instance().folder_icon_size(); + if (dragged_view_hover_animation_ && + dragged_view_hover_animation_->is_animating()) { + // The icon is updated before the folder icon animation ended, so clip the + // icon to the size in progress here. + clipped_size = gfx::ToRoundedSize(gfx::Tween::SizeValueBetween( + dragged_view_hover_animation_->GetCurrentValue(), + gfx::SizeF(AppListConfig::instance().folder_icon_size()), + gfx::SizeF(AppListConfig::instance().folder_unclipped_icon_size()))); + } + SetIcon(item_weak_->icon(), true /* clip */, clipped_size); } void AppListItemView::ItemNameChanged() {
diff --git a/ash/app_list/views/app_list_item_view.h b/ash/app_list/views/app_list_item_view.h index ab3d07e3..b4e08fc 100644 --- a/ash/app_list/views/app_list_item_view.h +++ b/ash/app_list/views/app_list_item_view.h
@@ -53,8 +53,11 @@ bool is_in_folder); ~AppListItemView() override; - // Set the icon of this image, adding a drop shadow if |has_shadow|. - void SetIcon(const gfx::ImageSkia& icon); + // Sets the icon of this image. Clips the icon into |clipped_size| if |clip| + // is true. + void SetIcon(const gfx::ImageSkia& icon, + bool clip, + const gfx::Size& clipped_size); void SetItemName(const base::string16& display_name, const base::string16& full_name); @@ -247,12 +250,6 @@ // The radius of preview circle for non-folder item. int preview_circle_radius_ = 0; - // The insets of folder icon mask to the unclipped folder icon. - int folder_icon_insets_ = 0; - - // The folder icon mask used to clip the folder icon. - std::unique_ptr<ui::LayerOwner> folder_icon_mask_; - bool is_installing_ = false; bool is_highlighted_ = false;
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc index a301175..cadae4e2 100644 --- a/ash/app_list/views/app_list_view.cc +++ b/ash/app_list/views/app_list_view.cc
@@ -1149,10 +1149,12 @@ contents_view->Layout(); gfx::Rect app_list_background_shield_bounds = contents_bounds; - // Inset by |kAppListBackgroundRadius| to account for the rounded corners - // on the top and bottom of the |app_list_background_shield_|, and offset by - // |kAppListBackgroundRadius| to center |app_list_background_shield_|. - app_list_background_shield_bounds.Inset(0, -kAppListBackgroundRadius); + // Inset bottom by 2 * |kAppListBackgroundRadius| to account for the rounded + // corners on the top and bottom of the |app_list_background_shield_|. + // Only add the inset to the bottom to keep padding at the top of the AppList + // the same. + app_list_background_shield_bounds.Inset(0, 0, 0, + -kAppListBackgroundRadius * 2); app_list_background_shield_->SetBoundsRect(app_list_background_shield_bounds); app_list_background_shield_->UpdateCornerRadius(kAppListBackgroundRadius); if (is_background_blur_enabled_ && !IsHomeLauncherEnabledInTabletMode() && @@ -1163,6 +1165,16 @@ app_list_background_shield_mask_->layer()->SetBounds( app_list_background_shield_bounds); } + + float app_list_transition_progress = GetAppListTransitionProgress(); + gfx::Transform transform; + if (app_list_transition_progress >= 1 && app_list_transition_progress <= 2) { + // Translate background shield so that it ends drag at y position + // -|kAppListBackgroundRadius| when dragging between peeking and fullscreen. + transform.Translate( + 0, -kAppListBackgroundRadius * (app_list_transition_progress - 1)); + } + app_list_background_shield_->SetTransform(transform); } void AppListView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
diff --git a/ash/assistant/ui/assistant_container_view.cc b/ash/assistant/ui/assistant_container_view.cc index e3e787a7..f55ef83 100644 --- a/ash/assistant/ui/assistant_container_view.cc +++ b/ash/assistant/ui/assistant_container_view.cc
@@ -161,8 +161,12 @@ views::BubbleDialogDelegateView::CreateBubble(this); - // These attributes can only be set after bubble creation: - GetBubbleFrameView()->bubble_border()->SetCornerRadius(kCornerRadiusDip); + // Corner radius can only be set after bubble creation. + GetBubbleFrameView()->bubble_border()->SetCornerRadius( + assistant_controller_->ui_controller()->model()->ui_mode() == + AssistantUiMode::kMiniUi + ? kMiniUiCornerRadiusDip + : kCornerRadiusDip); // Update the initial shadow layer with correct corner radius. UpdateShadow();
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc index 0deb4bf..b331e481 100644 --- a/ash/public/cpp/ash_features.cc +++ b/ash/public/cpp/ash_features.cc
@@ -26,7 +26,7 @@ "KeyboardShortcutViewerApp", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kLockScreenNotifications{"LockScreenNotifications", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kLockScreenInlineReply{"LockScreenInlineReply", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/base/test/scoped_task_environment.cc b/base/test/scoped_task_environment.cc index 5924c84ca0..50a46325 100644 --- a/base/test/scoped_task_environment.cc +++ b/base/test/scoped_task_environment.cc
@@ -282,6 +282,11 @@ return mock_time_task_runner_->DeprecatedGetMockTickClock(); } +base::TimeTicks ScopedTaskEnvironment::NowTicks() const { + DCHECK(mock_time_task_runner_); + return mock_time_task_runner_->NowTicks(); +} + size_t ScopedTaskEnvironment::GetPendingMainThreadTaskCount() const { DCHECK(mock_time_task_runner_); return mock_time_task_runner_->GetPendingTaskCount();
diff --git a/base/test/scoped_task_environment.h b/base/test/scoped_task_environment.h index 839b734a..2e46073 100644 --- a/base/test/scoped_task_environment.h +++ b/base/test/scoped_task_environment.h
@@ -126,6 +126,10 @@ std::unique_ptr<TickClock> DeprecatedGetMockTickClock(); // Only valid for instances with a MOCK_TIME MainThreadType. + // Returns the current virtual tick time (initially starting at 0). + base::TimeTicks NowTicks() const; + + // Only valid for instances with a MOCK_TIME MainThreadType. // Returns the number of pending tasks of the main thread's TaskRunner. size_t GetPendingMainThreadTaskCount() const;
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py index ed15584..ce61e756 100755 --- a/build/android/gyp/apkbuilder.py +++ b/build/android/gyp/apkbuilder.py
@@ -228,15 +228,17 @@ shutil.copy(resource_apk_info_path, res_info_path) -def _MergePakInfoFiles(pak_info_path, asset_list): - lines = set() - for asset_details in asset_list: - src = asset_details.split(':')[0] - if src.endswith('.pak'): - with open(src + '.info', 'r') as src_info_file: - lines.update(src_info_file.readlines()) - with open(pak_info_path, 'w') as merged_info_file: - merged_info_file.writelines(sorted(lines)) +def _FilterPakInfoPaths(assets): + return [f.split(':')[0] + '.info' for f in assets if f.endswith('.pak')] + + +def _MergePakInfoFiles(merged_path, pak_infos): + info_lines = set() + for pak_info_path in pak_infos: + with open(pak_info_path, 'r') as src_info_file: + info_lines.update(src_info_file.readlines()) + with open(merged_path, 'w') as merged_info_file: + merged_info_file.writelines(sorted(info_lines)) def main(args): @@ -273,6 +275,11 @@ assets = _ExpandPaths(options.assets) uncompressed_assets = _ExpandPaths(options.uncompressed_assets) + if options.apk_pak_info_path: + pak_infos = _FilterPakInfoPaths( + options.assets + options.uncompressed_assets) + depfile_deps.extend(pak_infos) + for src_path, dest_path in itertools.chain(assets, uncompressed_assets): # Included via .build_config, so need to write it to depfile. depfile_deps.append(src_path) @@ -392,8 +399,7 @@ data=java_resource_jar.read(apk_path)) if options.apk_pak_info_path: - _MergePakInfoFiles(options.apk_pak_info_path, - options.assets + options.uncompressed_assets) + _MergePakInfoFiles(options.apk_pak_info_path, pak_infos) if options.apk_res_info_path: _MergeResInfoFiles(options.apk_res_info_path, options.resource_apk)
diff --git a/build/chromeos/run_vm_test.py b/build/chromeos/run_vm_test.py index f392ca4..f13faa4b 100755 --- a/build/chromeos/run_vm_test.py +++ b/build/chromeos/run_vm_test.py
@@ -168,6 +168,16 @@ # Build the shell script that will be used on the VM to invoke the test. vm_test_script_contents = ['#!/bin/sh'] + # Clear out directories that persist logs and crash dumps. These can + # accumulate over a VM's lifetime and consume disk space. + # TODO(crbug.com/878526): Remove this once cros_run_vm_test handles it. + vm_test_script_contents += [ + # We run tests as chronos, but need to be root to rm the files. So pass + # in the public plaintext root password to sudo via stdin. + 'echo "test0000" | sudo -S find /var/spool/crash/ -type f -delete', + 'echo "test0000" | sudo -S find /var/log/chrome/ -type f -delete', + ] + # /home is mounted with "noexec" in the VM, but some of our tools # and tests use the home dir as a workspace (eg: vpython downloads # python binaries to ~/.vpython-root). /tmp doesn't have this
diff --git a/build/config/fuchsia/build_manifest.py b/build/config/fuchsia/build_manifest.py index db0db8c..0ef175d 100644 --- a/build/config/fuchsia/build_manifest.py +++ b/build/config/fuchsia/build_manifest.py
@@ -188,13 +188,14 @@ expanded_files = expanded_files.union(dist_libs) # Format and write out the manifest contents. + gen_dir = os.path.join(out_dir, "gen") app_found = False for current_file in expanded_files: if _IsBinary(current_file): current_file = _GetStrippedPath(current_file) in_package_path = MakePackagePath(os.path.join(out_dir, current_file), - [root_dir, out_dir]) + [gen_dir, root_dir, out_dir]) if in_package_path == app_filename: in_package_path = 'bin/app' app_found = True
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index 5defcc7..5be3a34 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -2705,8 +2705,8 @@ ExecuteCalculateDrawProperties(root); - EXPECT_EQ(gfx::Rect(50, 40, 10, 20), filter_child->visible_layer_rect()); - EXPECT_EQ(gfx::Rect(0, -10, 10, 20), + EXPECT_EQ(gfx::Rect(49, 39, 12, 21), filter_child->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(-1, -11, 12, 21), GetRenderSurface(filter)->content_rect()); } @@ -2758,8 +2758,8 @@ ExecuteCalculateDrawProperties(root); - EXPECT_EQ(gfx::Rect(50, 40, 10, 20), filter_child->visible_layer_rect()); - EXPECT_EQ(gfx::Rect(0, -30, 30, 60), + EXPECT_EQ(gfx::Rect(49, 39, 12, 21), filter_child->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(-1, -31, 32, 61), GetRenderSurface(filter)->content_rect()); }
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 4865a69fe..1eecdc8c 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -163,6 +163,9 @@ "$root_out_dir/locales/en-US.pak", "$root_out_dir/locales/fr.pak", ] + if (enable_hidpi || enable_mus) { + data += [ "$root_out_dir/chrome_200_percent.pak" ] + } } data_deps = [] @@ -360,9 +363,6 @@ # what telemetry test-runner expects. output_name = "test_chrome" sources = [] - data = [ - "$root_out_dir/chrome_200_percent.pak", - ] if (!is_win && use_aura) { sources += [ "app/chrome_exe_main_aura.cc" ] }
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index d298cbd..c6b141a 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -99,7 +99,7 @@ ] } -android_resources("chrome_java_resources") { +android_resources("chrome_app_java_resources") { resource_dirs = [ "java/res", "//chrome/android/java/res_chromium", @@ -125,6 +125,14 @@ custom_package = "org.chromium.chrome" } +android_resources("chrome_download_java_resources") { + resource_dirs = [ "//chrome/android/java/res_download" ] + deps = [ + ":chrome_app_java_resources", + ] + custom_package = "org.chromium.chrome.download" +} + java_strings_grd("chrome_strings_grd") { defines = chrome_grit_defines grd_file = "java/strings/android_chrome_strings.grd" @@ -204,7 +212,8 @@ android_library("chrome_java") { deps = [ - ":chrome_java_resources", + ":chrome_app_java_resources", + ":chrome_download_java_resources", ":chrome_public_android_manifest", ":chrome_public_apk_template_resources", ":document_tab_model_info_proto_java", @@ -472,8 +481,8 @@ deps = [ ":app_hooks_java", + ":chrome_app_java_resources", ":chrome_java", - ":chrome_java_resources", ":chrome_junit_test_support", ":partner_location_descriptor_proto_java", "$google_play_services_package:google_play_services_base_java", @@ -844,13 +853,13 @@ } } -# Overrides icon / name defined in chrome_java_resources. +# Overrides icon / name defined in chrome_app_java_resources. android_resources("chrome_public_apk_resources") { resource_dirs = [ "java/res_chromium" ] # Dep needed to ensure override works properly. deps = [ - ":chrome_java_resources", + ":chrome_app_java_resources", ] }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/action/FeedActionHandler.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/action/FeedActionHandler.java index c1568f4..bd933911 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/action/FeedActionHandler.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/action/FeedActionHandler.java
@@ -79,7 +79,6 @@ @Override public void downloadUrl(ContentMetadata contentMetadata) { - // TODO(twellington): https://bugs.chromium.org/p/chromium/issues/detail?id=879824 mDelegate.openUrl( WindowOpenDisposition.SAVE_TO_DISK, createLoadUrlParams(contentMetadata.getUrl())); mSuggestionConsumedObserver.run();
diff --git a/chrome/android/java/res/drawable-hdpi/bg_tabstrip_background_tab.9.png b/chrome/android/java/res/drawable-hdpi/bg_tabstrip_background_tab.9.png index 4b46ae5..5b2583e 100644 --- a/chrome/android/java/res/drawable-hdpi/bg_tabstrip_background_tab.9.png +++ b/chrome/android/java/res/drawable-hdpi/bg_tabstrip_background_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/bg_tabstrip_incognito_background_tab.9.png b/chrome/android/java/res/drawable-hdpi/bg_tabstrip_incognito_background_tab.9.png index ade4d4e2..afcee82a 100644 --- a/chrome/android/java/res/drawable-hdpi/bg_tabstrip_incognito_background_tab.9.png +++ b/chrome/android/java/res/drawable-hdpi/bg_tabstrip_incognito_background_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/bg_tabstrip_incognito_tab.9.png b/chrome/android/java/res/drawable-hdpi/bg_tabstrip_incognito_tab.9.png index f6adf59..30b08c4f 100644 --- a/chrome/android/java/res/drawable-hdpi/bg_tabstrip_incognito_tab.9.png +++ b/chrome/android/java/res/drawable-hdpi/bg_tabstrip_incognito_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/bg_tabstrip_tab.9.png b/chrome/android/java/res/drawable-hdpi/bg_tabstrip_tab.9.png index d539cd0e62..51eb256 100644 --- a/chrome/android/java/res/drawable-hdpi/bg_tabstrip_tab.9.png +++ b/chrome/android/java/res/drawable-hdpi/bg_tabstrip_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/btn_tabstrip_new_incognito_tab_pressed.png b/chrome/android/java/res/drawable-hdpi/btn_tabstrip_new_incognito_tab_pressed.png deleted file mode 100644 index ce189f9f..0000000 --- a/chrome/android/java/res/drawable-hdpi/btn_tabstrip_new_incognito_tab_pressed.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/btn_tabstrip_new_tab_normal.png b/chrome/android/java/res/drawable-hdpi/btn_tabstrip_new_tab_normal.png index 95ee05b..dca97b8 100644 --- a/chrome/android/java/res/drawable-hdpi/btn_tabstrip_new_tab_normal.png +++ b/chrome/android/java/res/drawable-hdpi/btn_tabstrip_new_tab_normal.png Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/btn_tabstrip_new_tab_pressed.png b/chrome/android/java/res/drawable-hdpi/btn_tabstrip_new_tab_pressed.png index cc3d7a4..be137e1 100644 --- a/chrome/android/java/res/drawable-hdpi/btn_tabstrip_new_tab_pressed.png +++ b/chrome/android/java/res/drawable-hdpi/btn_tabstrip_new_tab_pressed.png Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/btn_tabstrip_switch_incognito.png b/chrome/android/java/res/drawable-hdpi/btn_tabstrip_switch_incognito.png index 6f32e0db..76b7bfd 100644 --- a/chrome/android/java/res/drawable-hdpi/btn_tabstrip_switch_incognito.png +++ b/chrome/android/java/res/drawable-hdpi/btn_tabstrip_switch_incognito.png Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/btn_tabstrip_switch_normal.png b/chrome/android/java/res/drawable-hdpi/btn_tabstrip_switch_normal.png index 9376f09a..768f224 100644 --- a/chrome/android/java/res/drawable-hdpi/btn_tabstrip_switch_normal.png +++ b/chrome/android/java/res/drawable-hdpi/btn_tabstrip_switch_normal.png Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/ic_omnibox_magnifier.png b/chrome/android/java/res/drawable-hdpi/ic_omnibox_magnifier.png deleted file mode 100644 index c8daaa0..0000000 --- a/chrome/android/java/res/drawable-hdpi/ic_omnibox_magnifier.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-hdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png b/chrome/android/java/res/drawable-ldrtl-hdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png deleted file mode 100644 index 3b3be33..0000000 --- a/chrome/android/java/res/drawable-ldrtl-hdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-hdpi-v17/btn_tabstrip_new_tab_normal.png b/chrome/android/java/res/drawable-ldrtl-hdpi-v17/btn_tabstrip_new_tab_normal.png deleted file mode 100644 index 0ad397f60..0000000 --- a/chrome/android/java/res/drawable-ldrtl-hdpi-v17/btn_tabstrip_new_tab_normal.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-hdpi-v17/ic_omnibox_magnifier.png b/chrome/android/java/res/drawable-ldrtl-hdpi-v17/ic_omnibox_magnifier.png deleted file mode 100644 index 5cbb6c4c..0000000 --- a/chrome/android/java/res/drawable-ldrtl-hdpi-v17/ic_omnibox_magnifier.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-mdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png b/chrome/android/java/res/drawable-ldrtl-mdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png deleted file mode 100644 index b0d40af..0000000 --- a/chrome/android/java/res/drawable-ldrtl-mdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-mdpi-v17/btn_tabstrip_new_tab_normal.png b/chrome/android/java/res/drawable-ldrtl-mdpi-v17/btn_tabstrip_new_tab_normal.png deleted file mode 100644 index 582eec4..0000000 --- a/chrome/android/java/res/drawable-ldrtl-mdpi-v17/btn_tabstrip_new_tab_normal.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-mdpi-v17/ic_omnibox_magnifier.png b/chrome/android/java/res/drawable-ldrtl-mdpi-v17/ic_omnibox_magnifier.png deleted file mode 100644 index a75372fb..0000000 --- a/chrome/android/java/res/drawable-ldrtl-mdpi-v17/ic_omnibox_magnifier.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-sw600dp-tvdpi-v17/toolbar_background.9.png b/chrome/android/java/res/drawable-ldrtl-sw600dp-tvdpi-v17/toolbar_background.9.png deleted file mode 100644 index 31e9a17..0000000 --- a/chrome/android/java/res/drawable-ldrtl-sw600dp-tvdpi-v17/toolbar_background.9.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-sw600dp-xhdpi-v17/toolbar_background.9.png b/chrome/android/java/res/drawable-ldrtl-sw600dp-xhdpi-v17/toolbar_background.9.png index e40358b..d75dfc3 100644 --- a/chrome/android/java/res/drawable-ldrtl-sw600dp-xhdpi-v17/toolbar_background.9.png +++ b/chrome/android/java/res/drawable-ldrtl-sw600dp-xhdpi-v17/toolbar_background.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png b/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png deleted file mode 100644 index c336d9b..0000000 --- a/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/btn_tabstrip_new_tab_normal.png b/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/btn_tabstrip_new_tab_normal.png deleted file mode 100644 index 0e731a7..0000000 --- a/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/btn_tabstrip_new_tab_normal.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/ic_omnibox_magnifier.png b/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/ic_omnibox_magnifier.png deleted file mode 100644 index 6b0c5c2..0000000 --- a/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/ic_omnibox_magnifier.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png b/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png deleted file mode 100644 index d341a4c5..0000000 --- a/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/btn_tabstrip_new_tab_normal.png b/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/btn_tabstrip_new_tab_normal.png deleted file mode 100644 index 7171adf..0000000 --- a/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/btn_tabstrip_new_tab_normal.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/ic_omnibox_magnifier.png b/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/ic_omnibox_magnifier.png deleted file mode 100644 index 059471e..0000000 --- a/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/ic_omnibox_magnifier.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png b/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png deleted file mode 100644 index 138a95d..0000000 --- a/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/btn_tabstrip_new_incognito_tab_pressed.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/btn_tabstrip_new_tab_normal.png b/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/btn_tabstrip_new_tab_normal.png deleted file mode 100644 index d78237c3..0000000 --- a/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/btn_tabstrip_new_tab_normal.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/ic_omnibox_magnifier.png b/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/ic_omnibox_magnifier.png deleted file mode 100644 index 47f86c2..0000000 --- a/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/ic_omnibox_magnifier.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/bg_tabstrip_background_tab.9.png b/chrome/android/java/res/drawable-mdpi/bg_tabstrip_background_tab.9.png index b302a556..5226350 100644 --- a/chrome/android/java/res/drawable-mdpi/bg_tabstrip_background_tab.9.png +++ b/chrome/android/java/res/drawable-mdpi/bg_tabstrip_background_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/bg_tabstrip_incognito_background_tab.9.png b/chrome/android/java/res/drawable-mdpi/bg_tabstrip_incognito_background_tab.9.png index eb26e66..aef8c53 100644 --- a/chrome/android/java/res/drawable-mdpi/bg_tabstrip_incognito_background_tab.9.png +++ b/chrome/android/java/res/drawable-mdpi/bg_tabstrip_incognito_background_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/bg_tabstrip_incognito_tab.9.png b/chrome/android/java/res/drawable-mdpi/bg_tabstrip_incognito_tab.9.png index 38d0df6..2d187752 100644 --- a/chrome/android/java/res/drawable-mdpi/bg_tabstrip_incognito_tab.9.png +++ b/chrome/android/java/res/drawable-mdpi/bg_tabstrip_incognito_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/bg_tabstrip_tab.9.png b/chrome/android/java/res/drawable-mdpi/bg_tabstrip_tab.9.png index 520295e..7d926d5 100644 --- a/chrome/android/java/res/drawable-mdpi/bg_tabstrip_tab.9.png +++ b/chrome/android/java/res/drawable-mdpi/bg_tabstrip_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/btn_tabstrip_new_incognito_tab_pressed.png b/chrome/android/java/res/drawable-mdpi/btn_tabstrip_new_incognito_tab_pressed.png deleted file mode 100644 index 638b01d..0000000 --- a/chrome/android/java/res/drawable-mdpi/btn_tabstrip_new_incognito_tab_pressed.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/btn_tabstrip_new_tab_normal.png b/chrome/android/java/res/drawable-mdpi/btn_tabstrip_new_tab_normal.png index bc5d2e91..40f283b7 100644 --- a/chrome/android/java/res/drawable-mdpi/btn_tabstrip_new_tab_normal.png +++ b/chrome/android/java/res/drawable-mdpi/btn_tabstrip_new_tab_normal.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/btn_tabstrip_new_tab_pressed.png b/chrome/android/java/res/drawable-mdpi/btn_tabstrip_new_tab_pressed.png index e2c4e56..e0f9512 100644 --- a/chrome/android/java/res/drawable-mdpi/btn_tabstrip_new_tab_pressed.png +++ b/chrome/android/java/res/drawable-mdpi/btn_tabstrip_new_tab_pressed.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/btn_tabstrip_switch_incognito.png b/chrome/android/java/res/drawable-mdpi/btn_tabstrip_switch_incognito.png index 9129e3b1..d235556d 100644 --- a/chrome/android/java/res/drawable-mdpi/btn_tabstrip_switch_incognito.png +++ b/chrome/android/java/res/drawable-mdpi/btn_tabstrip_switch_incognito.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/btn_tabstrip_switch_normal.png b/chrome/android/java/res/drawable-mdpi/btn_tabstrip_switch_normal.png index cfecd1a..19c96ce 100644 --- a/chrome/android/java/res/drawable-mdpi/btn_tabstrip_switch_normal.png +++ b/chrome/android/java/res/drawable-mdpi/btn_tabstrip_switch_normal.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/ic_omnibox_magnifier.png b/chrome/android/java/res/drawable-mdpi/ic_omnibox_magnifier.png deleted file mode 100644 index 1080e5c..0000000 --- a/chrome/android/java/res/drawable-mdpi/ic_omnibox_magnifier.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-sw600dp-tvdpi/toolbar_background.9.png b/chrome/android/java/res/drawable-sw600dp-tvdpi/toolbar_background.9.png deleted file mode 100644 index de0a139..0000000 --- a/chrome/android/java/res/drawable-sw600dp-tvdpi/toolbar_background.9.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-sw600dp-xhdpi/toolbar_background.9.png b/chrome/android/java/res/drawable-sw600dp-xhdpi/toolbar_background.9.png index c86c1fa..a0671b1 100644 --- a/chrome/android/java/res/drawable-sw600dp-xhdpi/toolbar_background.9.png +++ b/chrome/android/java/res/drawable-sw600dp-xhdpi/toolbar_background.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_background_tab.9.png b/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_background_tab.9.png index 28e7511..d973615 100644 --- a/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_background_tab.9.png +++ b/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_background_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_incognito_background_tab.9.png b/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_incognito_background_tab.9.png index 0443934c..7a494bf6 100644 --- a/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_incognito_background_tab.9.png +++ b/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_incognito_background_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_incognito_tab.9.png b/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_incognito_tab.9.png index 4e74eca..68069b9 100644 --- a/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_incognito_tab.9.png +++ b/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_incognito_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_tab.9.png b/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_tab.9.png index d43da158..319d0b8e0 100644 --- a/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_tab.9.png +++ b/chrome/android/java/res/drawable-xhdpi/bg_tabstrip_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_new_incognito_tab_pressed.png b/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_new_incognito_tab_pressed.png deleted file mode 100644 index e6ac173..0000000 --- a/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_new_incognito_tab_pressed.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_new_tab_normal.png b/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_new_tab_normal.png index 40db38b..9021b3c 100644 --- a/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_new_tab_normal.png +++ b/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_new_tab_normal.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_new_tab_pressed.png b/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_new_tab_pressed.png index 961142e..29dfbefc 100644 --- a/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_new_tab_pressed.png +++ b/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_new_tab_pressed.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_switch_incognito.png b/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_switch_incognito.png index 1a18bba..cefb4fc 100644 --- a/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_switch_incognito.png +++ b/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_switch_incognito.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_switch_normal.png b/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_switch_normal.png index ccdc6ba..84bb2ed6 100644 --- a/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_switch_normal.png +++ b/chrome/android/java/res/drawable-xhdpi/btn_tabstrip_switch_normal.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/ic_omnibox_magnifier.png b/chrome/android/java/res/drawable-xhdpi/ic_omnibox_magnifier.png deleted file mode 100644 index 127a11c..0000000 --- a/chrome/android/java/res/drawable-xhdpi/ic_omnibox_magnifier.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_background_tab.9.png b/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_background_tab.9.png index 1ca31ff..6c65194f 100644 --- a/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_background_tab.9.png +++ b/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_background_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_incognito_background_tab.9.png b/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_incognito_background_tab.9.png index f9e40745..66b5ac9 100644 --- a/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_incognito_background_tab.9.png +++ b/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_incognito_background_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_incognito_tab.9.png b/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_incognito_tab.9.png index 59aca852..1b8eeaa 100644 --- a/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_incognito_tab.9.png +++ b/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_incognito_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_tab.9.png b/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_tab.9.png index 8b5fb67e..edaa909 100644 --- a/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_tab.9.png +++ b/chrome/android/java/res/drawable-xxhdpi/bg_tabstrip_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_new_incognito_tab_pressed.png b/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_new_incognito_tab_pressed.png deleted file mode 100644 index 473ff78..0000000 --- a/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_new_incognito_tab_pressed.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_new_tab_normal.png b/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_new_tab_normal.png index f467f79..465228b 100644 --- a/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_new_tab_normal.png +++ b/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_new_tab_normal.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_new_tab_pressed.png b/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_new_tab_pressed.png index d34451d..adf7d28 100644 --- a/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_new_tab_pressed.png +++ b/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_new_tab_pressed.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_switch_incognito.png b/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_switch_incognito.png index 967a37a9..c284cb9 100644 --- a/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_switch_incognito.png +++ b/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_switch_incognito.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_switch_normal.png b/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_switch_normal.png index 281d98b1..31973ee2 100644 --- a/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_switch_normal.png +++ b/chrome/android/java/res/drawable-xxhdpi/btn_tabstrip_switch_normal.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/ic_omnibox_magnifier.png b/chrome/android/java/res/drawable-xxhdpi/ic_omnibox_magnifier.png deleted file mode 100644 index 0ed2a3a..0000000 --- a/chrome/android/java/res/drawable-xxhdpi/ic_omnibox_magnifier.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_background_tab.9.png b/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_background_tab.9.png index 3af1e9e1..6d09a93 100644 --- a/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_background_tab.9.png +++ b/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_background_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_incognito_background_tab.9.png b/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_incognito_background_tab.9.png index 4e44459d..bbadf3f 100644 --- a/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_incognito_background_tab.9.png +++ b/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_incognito_background_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_incognito_tab.9.png b/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_incognito_tab.9.png index 0c82405e..228d388f 100644 --- a/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_incognito_tab.9.png +++ b/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_incognito_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_tab.9.png b/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_tab.9.png index 9ace0de..85517a6e 100644 --- a/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_tab.9.png +++ b/chrome/android/java/res/drawable-xxxhdpi/bg_tabstrip_tab.9.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_new_incognito_tab_pressed.png b/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_new_incognito_tab_pressed.png deleted file mode 100644 index f2144b81..0000000 --- a/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_new_incognito_tab_pressed.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_new_tab_normal.png b/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_new_tab_normal.png index 675fc91..db71b6f 100644 --- a/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_new_tab_normal.png +++ b/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_new_tab_normal.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_new_tab_pressed.png b/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_new_tab_pressed.png index e1413eb..c2e2705 100644 --- a/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_new_tab_pressed.png +++ b/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_new_tab_pressed.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_switch_incognito.png b/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_switch_incognito.png index a2ff7b2..2e7a2b8 100644 --- a/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_switch_incognito.png +++ b/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_switch_incognito.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_switch_normal.png b/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_switch_normal.png index f85a71ab..39788c68 100644 --- a/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_switch_normal.png +++ b/chrome/android/java/res/drawable-xxxhdpi/btn_tabstrip_switch_normal.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/ic_omnibox_magnifier.png b/chrome/android/java/res/drawable-xxxhdpi/ic_omnibox_magnifier.png deleted file mode 100644 index d8d10715..0000000 --- a/chrome/android/java/res/drawable-xxxhdpi/ic_omnibox_magnifier.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/layout/download_home_toolbar.xml b/chrome/android/java/res/layout/download_home_toolbar.xml deleted file mode 100644 index df8c587..0000000 --- a/chrome/android/java/res/layout/download_home_toolbar.xml +++ /dev/null
@@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. --> - -<org.chromium.chrome.browser.download.home.toolbar.DownloadHomeToolbar - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - style="@style/ModernToolbar"> - - <LinearLayout - android:id="@+id/title_bar" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="vertical"> - <TextView - android:id="@+id/title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - style="@style/BlackHeadline2" - android:text="@string/menu_downloads"/> - - </LinearLayout> - -</org.chromium.chrome.browser.download.home.toolbar.DownloadHomeToolbar> \ No newline at end of file
diff --git a/chrome/android/java/res/layout/location_bar_base.xml b/chrome/android/java/res/layout/location_bar_base.xml index e80b07a..7d9bc9f 100644 --- a/chrome/android/java/res/layout/location_bar_base.xml +++ b/chrome/android/java/res/layout/location_bar_base.xml
@@ -11,7 +11,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> <FrameLayout android:id="@+id/location_bar_icon" - android:layout_width="@dimen/location_bar_icon_width" + android:layout_width="@dimen/location_bar_start_icon_width" android:layout_height="match_parent" android:paddingEnd="4dp" android:visibility="gone" >
diff --git a/chrome/android/java/res/layout/toolbar_tablet.xml b/chrome/android/java/res/layout/toolbar_tablet.xml index ace8782..6fdda0c 100644 --- a/chrome/android/java/res/layout/toolbar_tablet.xml +++ b/chrome/android/java/res/layout/toolbar_tablet.xml
@@ -14,7 +14,7 @@ android:layout_width="match_parent" android:layout_height="@dimen/toolbar_height_no_shadow" android:layout_marginTop="@dimen/tab_strip_height" - android:background="@color/default_primary_color" + android:background="@color/modern_primary_color" android:paddingStart="@dimen/tablet_toolbar_start_padding" > <LinearLayout @@ -54,12 +54,10 @@ <org.chromium.chrome.browser.omnibox.LocationBarTablet android:id="@+id/location_bar" android:layout_width="0dp" - android:layout_height="match_parent" - android:layout_marginBottom="5dp" - android:layout_marginTop="5dp" + android:layout_height="@dimen/modern_toolbar_background_size" android:layout_weight="1" - android:layout_gravity="top|center" - android:background="@drawable/card_single" + android:layout_gravity="center_vertical" + android:background="@drawable/modern_toolbar_background" android:paddingEnd="1dp" android:paddingStart="2dp" />
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml index 113e4a22..794ca8db 100644 --- a/chrome/android/java/res/values-v17/styles.xml +++ b/chrome/android/java/res/values-v17/styles.xml
@@ -675,15 +675,6 @@ <item name="android:textColor">@color/chip_text_color</item> <item name="android:textSize">@dimen/text_size_medium</item> </style> - <style name="DownloadHomeStatusText"> - <item name="android:layout_width">wrap_content</item> - <item name="android:layout_height">wrap_content</item> - <item name="android:layout_marginTop">0dp</item> - <item name="android:minHeight">18dp</item> - <item name="android:textAppearance">@style/BlackBody</item> - <item name="android:ellipsize">start</item> - <item name="android:singleLine">true</item> - </style> <style name="DateView"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">wrap_content</item> @@ -693,63 +684,6 @@ <item name="android:layout_marginEnd">@dimen/list_item_default_margin</item> <item name="android:textAppearance">@style/BlackBody</item> </style> - <style name="DownloadTitleStyle"> - <item name="android:layout_width">wrap_content</item> - <item name="android:layout_height">wrap_content</item> - <item name="android:layout_alignParentTop">true</item> - <item name="android:layout_alignParentStart">true</item> - <item name="android:paddingEnd">16dp</item> - <item name="android:singleLine">true</item> - <item name="android:textAppearance">@style/BlackTitle1</item> - </style> - <style name="DownloadDescriptionStyle"> - <item name="android:layout_width">wrap_content</item> - <item name="android:layout_height">wrap_content</item> - <item name="android:layout_alignParentBottom">true</item> - <item name="android:layout_alignParentStart">true</item> - <item name="android:layout_marginEnd">16dp</item> - <item name="android:layout_marginTop">0dp</item> - <item name="android:textAlignment">viewStart</item> - <item name="android:ellipsize">start</item> - <item name="android:singleLine">true</item> - <item name="android:textAppearance">@style/BlackBody</item> - </style> - <style name="DownloadIconView" parent="@style/ListItemStartIcon"> - <item name="android:background">@color/light_active_color</item> - </style> - <style name="DownloadNewBadgeStyle"> - <item name="android:layout_width">wrap_content</item> - <item name="android:layout_height">wrap_content</item> - <item name="android:background">@color/light_active_color</item> - <item name="android:layout_marginStart">-8dp</item> - <item name="android:layout_marginTop">-2dp</item> - <item name="android:paddingStart">6dp</item> - <item name="android:paddingEnd">6dp</item> - <item name="android:singleLine">true</item> - <item name="android:text">@string/prefetch_badge_new</item> - <item name="android:textAppearance">@style/TextAppearance.DownloadNewBadge</item> - </style> - <style name="TextAppearance.DownloadNewBadge"> - <item name="android:textColor">@android:color/white</item> - <item name="android:textSize">@dimen/text_size_small</item> - <item name="android:textStyle">bold</item> - <item name="android:textAllCaps">true</item> - </style> - - <!-- Download Home V2 --> - <style name="DownloadItemText"> - <item name="android:layout_width">0dp</item> - <item name="android:layout_height">wrap_content</item> - <item name="android:maxLines">1</item> - <item name="android:ellipsize">end</item> - <item name="android:singleLine">true</item> - </style> - <style name="DownloadItemSelectionView"> - <item name="android:layout_width">24dp</item> - <item name="android:layout_height">24dp</item> - <item name="android:layout_marginStart">8dp</item> - <item name="android:layout_marginTop">8dp</item> - </style> <!-- Data Reduction --> <style name="TextAppearance.DataUsageBreakdownColumnLabel" parent="@style/BlackButtonText">
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml index 8f0e939..4ba3500c 100644 --- a/chrome/android/java/res/values/dimens.xml +++ b/chrome/android/java/res/values/dimens.xml
@@ -270,6 +270,7 @@ <dimen name="location_bar_vertical_margin">8dp</dimen> <dimen name="location_bar_url_text_size">16sp</dimen> <dimen name="location_bar_icon_width">28dp</dimen> + <dimen name="location_bar_start_icon_width">28dp</dimen> <dimen name="location_bar_lateral_padding">10dp</dimen> <dimen name="tablet_toolbar_start_padding">4dp</dimen>
diff --git a/chrome/android/java/res_download/OWNERS b/chrome/android/java/res_download/OWNERS new file mode 100644 index 0000000..d6efcb8b --- /dev/null +++ b/chrome/android/java/res_download/OWNERS
@@ -0,0 +1,5 @@ +dtrainor@chromium.org +shaktisahu@chromium.org + +# COMPONENT: UI>Browser>Downloads +# OS: Android
diff --git a/chrome/android/java/res/layout/confirm_oma_download.xml b/chrome/android/java/res_download/layout/confirm_oma_download.xml similarity index 64% rename from chrome/android/java/res/layout/confirm_oma_download.xml rename to chrome/android/java/res_download/layout/confirm_oma_download.xml index b6d58a44..d8275b8 100644 --- a/chrome/android/java/res/layout/confirm_oma_download.xml +++ b/chrome/android/java/res_download/layout/confirm_oma_download.xml
@@ -15,39 +15,39 @@ <TextView android:text="@string/oma_download_name_label" android:gravity="start" - android:textColor="@android:color/black" - android:padding="3dp" /> + android:padding="3dp" + android:textAppearance="@style/BlackBodyDefault" /> <TextView android:id="@+id/oma_download_name" android:gravity="start" - android:textColor="@android:color/black" - android:padding="3dp" /> + android:padding="3dp" + android:textAppearance="@style/BlackBodyDefault" /> </TableRow> <TableRow> <TextView android:text="@string/oma_download_vendor_label" android:gravity="start" - android:textColor="@android:color/black" - android:padding="3dp" /> + android:padding="3dp" + android:textAppearance="@style/BlackBodyDefault" /> <TextView android:id="@+id/oma_download_vendor" android:gravity="start" - android:textColor="@android:color/black" - android:padding="3dp" /> + android:padding="3dp" + android:textAppearance="@style/BlackBodyDefault" /> </TableRow> <TableRow> <TextView android:text="@string/oma_download_size_label" android:gravity="start" - android:textColor="@android:color/black" - android:padding="3dp" /> + android:padding="3dp" + android:textAppearance="@style/BlackBodyDefault" /> <TextView android:id="@+id/oma_download_size" android:gravity="start" - android:textColor="@android:color/black" - android:padding="3dp" /> + android:padding="3dp" + android:textAppearance="@style/BlackBodyDefault" /> </TableRow> @@ -55,25 +55,25 @@ <TextView android:text="@string/oma_download_type_label" android:gravity="start" - android:textColor="@android:color/black" - android:padding="3dp" /> + android:padding="3dp" + android:textAppearance="@style/BlackBodyDefault" /> <TextView android:id="@+id/oma_download_type" android:gravity="start" - android:textColor="@android:color/black" - android:padding="3dp" /> + android:padding="3dp" + android:textAppearance="@style/BlackBodyDefault" /> </TableRow> <TableRow> <TextView android:text="@string/oma_download_description_label" android:gravity="start" - android:textColor="@android:color/black" - android:padding="3dip" /> + android:padding="3dip" + android:textAppearance="@style/BlackBodyDefault" /> <TextView android:id="@+id/oma_download_description" android:gravity="start" - android:textColor="@android:color/black" - android:padding="3dip" /> + android:padding="3dip" + android:textAppearance="@style/BlackBodyDefault" /> </TableRow> </TableLayout> \ No newline at end of file
diff --git a/chrome/android/java/res/layout/download_home_tabs.xml b/chrome/android/java/res_download/layout/download_home_tabs.xml similarity index 100% rename from chrome/android/java/res/layout/download_home_tabs.xml rename to chrome/android/java/res_download/layout/download_home_tabs.xml
diff --git a/chrome/android/java/res_download/layout/download_home_toolbar.xml b/chrome/android/java/res_download/layout/download_home_toolbar.xml new file mode 100644 index 0000000..00f6c78c --- /dev/null +++ b/chrome/android/java/res_download/layout/download_home_toolbar.xml
@@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <org.chromium.chrome.browser.download.home.toolbar.DownloadHomeToolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="@dimen/toolbar_height_no_shadow" + style="@style/ModernToolbar"> + + <TextView + android:id="@+id/title_bar" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + style="@style/BlackHeadline2" + android:text="@string/menu_downloads"/> + + </org.chromium.chrome.browser.download.home.toolbar.DownloadHomeToolbar> + + <org.chromium.chrome.browser.widget.FadingShadowView + android:id="@+id/shadow" + android:layout_width="match_parent" + android:layout_height="@dimen/action_bar_shadow_height" + android:layout_marginTop="@dimen/toolbar_height_no_shadow" + android:visibility="gone"/> +</FrameLayout>
diff --git a/chrome/android/java/res/layout/download_item_view.xml b/chrome/android/java/res_download/layout/download_item_view.xml similarity index 100% rename from chrome/android/java/res/layout/download_item_view.xml rename to chrome/android/java/res_download/layout/download_item_view.xml
diff --git a/chrome/android/java/res/layout/download_location_dialog.xml b/chrome/android/java/res_download/layout/download_location_dialog.xml similarity index 97% rename from chrome/android/java/res/layout/download_location_dialog.xml rename to chrome/android/java/res_download/layout/download_location_dialog.xml index 62e26fb..cb75a04 100644 --- a/chrome/android/java/res/layout/download_location_dialog.xml +++ b/chrome/android/java/res_download/layout/download_location_dialog.xml
@@ -65,11 +65,11 @@ </LinearLayout> <CheckBox + style="@style/BlackDisabledText3" android:id="@+id/show_again_checkbox" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/download_location_dialog_checkbox" - android:textColor="@color/black_alpha_38" android:layout_marginTop="16dp" /> </LinearLayout>
diff --git a/chrome/android/java/res/layout/download_location_preference.xml b/chrome/android/java/res_download/layout/download_location_preference.xml similarity index 100% rename from chrome/android/java/res/layout/download_location_preference.xml rename to chrome/android/java/res_download/layout/download_location_preference.xml
diff --git a/chrome/android/java/res/layout/download_location_preference_item.xml b/chrome/android/java/res_download/layout/download_location_preference_item.xml similarity index 100% rename from chrome/android/java/res/layout/download_location_preference_item.xml rename to chrome/android/java/res_download/layout/download_location_preference_item.xml
diff --git a/chrome/android/java/res/layout/download_location_spinner_dropdown_item.xml b/chrome/android/java/res_download/layout/download_location_spinner_dropdown_item.xml similarity index 100% rename from chrome/android/java/res/layout/download_location_spinner_dropdown_item.xml rename to chrome/android/java/res_download/layout/download_location_spinner_dropdown_item.xml
diff --git a/chrome/android/java/res/layout/download_location_spinner_item.xml b/chrome/android/java/res_download/layout/download_location_spinner_item.xml similarity index 100% rename from chrome/android/java/res/layout/download_location_spinner_item.xml rename to chrome/android/java/res_download/layout/download_location_spinner_item.xml
diff --git a/chrome/android/java/res/layout/download_main.xml b/chrome/android/java/res_download/layout/download_main.xml similarity index 100% rename from chrome/android/java/res/layout/download_main.xml rename to chrome/android/java/res_download/layout/download_main.xml
diff --git a/chrome/android/java/res/layout/download_manager_date_item.xml b/chrome/android/java/res_download/layout/download_manager_date_item.xml similarity index 100% rename from chrome/android/java/res/layout/download_manager_date_item.xml rename to chrome/android/java/res_download/layout/download_manager_date_item.xml
diff --git a/chrome/android/java/res/layout/download_manager_date_separator.xml b/chrome/android/java/res_download/layout/download_manager_date_separator.xml similarity index 100% rename from chrome/android/java/res/layout/download_manager_date_separator.xml rename to chrome/android/java/res_download/layout/download_manager_date_separator.xml
diff --git a/chrome/android/java/res/layout/download_manager_generic_item.xml b/chrome/android/java/res_download/layout/download_manager_generic_item.xml similarity index 100% rename from chrome/android/java/res/layout/download_manager_generic_item.xml rename to chrome/android/java/res_download/layout/download_manager_generic_item.xml
diff --git a/chrome/android/java/res/layout/download_manager_image_item.xml b/chrome/android/java/res_download/layout/download_manager_image_item.xml similarity index 100% rename from chrome/android/java/res/layout/download_manager_image_item.xml rename to chrome/android/java/res_download/layout/download_manager_image_item.xml
diff --git a/chrome/android/java/res/layout/download_manager_in_progress_item.xml b/chrome/android/java/res_download/layout/download_manager_in_progress_item.xml similarity index 100% rename from chrome/android/java/res/layout/download_manager_in_progress_item.xml rename to chrome/android/java/res_download/layout/download_manager_in_progress_item.xml
diff --git a/chrome/android/java/res/layout/download_manager_prefetch_item.xml b/chrome/android/java/res_download/layout/download_manager_prefetch_item.xml similarity index 100% rename from chrome/android/java/res/layout/download_manager_prefetch_item.xml rename to chrome/android/java/res_download/layout/download_manager_prefetch_item.xml
diff --git a/chrome/android/java/res/layout/download_manager_section_header.xml b/chrome/android/java/res_download/layout/download_manager_section_header.xml similarity index 100% rename from chrome/android/java/res/layout/download_manager_section_header.xml rename to chrome/android/java/res_download/layout/download_manager_section_header.xml
diff --git a/chrome/android/java/res/layout/download_manager_section_separator.xml b/chrome/android/java/res_download/layout/download_manager_section_separator.xml similarity index 100% rename from chrome/android/java/res/layout/download_manager_section_separator.xml rename to chrome/android/java/res_download/layout/download_manager_section_separator.xml
diff --git a/chrome/android/java/res/layout/download_manager_spinner.xml b/chrome/android/java/res_download/layout/download_manager_spinner.xml similarity index 100% rename from chrome/android/java/res/layout/download_manager_spinner.xml rename to chrome/android/java/res_download/layout/download_manager_spinner.xml
diff --git a/chrome/android/java/res/layout/download_manager_spinner_drop_down.xml b/chrome/android/java/res_download/layout/download_manager_spinner_drop_down.xml similarity index 100% rename from chrome/android/java/res/layout/download_manager_spinner_drop_down.xml rename to chrome/android/java/res_download/layout/download_manager_spinner_drop_down.xml
diff --git a/chrome/android/java/res/layout/download_manager_toolbar.xml b/chrome/android/java/res_download/layout/download_manager_toolbar.xml similarity index 100% rename from chrome/android/java/res/layout/download_manager_toolbar.xml rename to chrome/android/java/res_download/layout/download_manager_toolbar.xml
diff --git a/chrome/android/java/res/layout/download_manager_ui_space_widget.xml b/chrome/android/java/res_download/layout/download_manager_ui_space_widget.xml similarity index 100% rename from chrome/android/java/res/layout/download_manager_ui_space_widget.xml rename to chrome/android/java/res_download/layout/download_manager_ui_space_widget.xml
diff --git a/chrome/android/java/res/layout/download_manager_video_item.xml b/chrome/android/java/res_download/layout/download_manager_video_item.xml similarity index 100% rename from chrome/android/java/res/layout/download_manager_video_item.xml rename to chrome/android/java/res_download/layout/download_manager_video_item.xml
diff --git a/chrome/android/java/res/layout/download_storage_summary.xml b/chrome/android/java/res_download/layout/download_storage_summary.xml similarity index 100% rename from chrome/android/java/res/layout/download_storage_summary.xml rename to chrome/android/java/res_download/layout/download_storage_summary.xml
diff --git a/chrome/android/java/res/layout/downloads_empty_view.xml b/chrome/android/java/res_download/layout/downloads_empty_view.xml similarity index 100% rename from chrome/android/java/res/layout/downloads_empty_view.xml rename to chrome/android/java/res_download/layout/downloads_empty_view.xml
diff --git a/chrome/android/java/res/layout/offline_download_header.xml b/chrome/android/java/res_download/layout/offline_download_header.xml similarity index 100% rename from chrome/android/java/res/layout/offline_download_header.xml rename to chrome/android/java/res_download/layout/offline_download_header.xml
diff --git a/chrome/android/java/res/menu/download_manager_menu.xml b/chrome/android/java/res_download/menu/download_manager_menu.xml similarity index 100% rename from chrome/android/java/res/menu/download_manager_menu.xml rename to chrome/android/java/res_download/menu/download_manager_menu.xml
diff --git a/chrome/android/java/res_download/values-v17/styles.xml b/chrome/android/java/res_download/values-v17/styles.xml new file mode 100644 index 0000000..b294e4b3 --- /dev/null +++ b/chrome/android/java/res_download/values-v17/styles.xml
@@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2014 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<resources xmlns:tools="http://schemas.android.com/tools"> + <!-- Download Home --> + <style name="DownloadHomeStatusText"> + <item name="android:layout_width">wrap_content</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:layout_marginTop">0dp</item> + <item name="android:minHeight">18dp</item> + <item name="android:textAppearance">@style/BlackBody</item> + <item name="android:ellipsize">start</item> + <item name="android:singleLine">true</item> + </style> + <style name="DownloadTitleStyle"> + <item name="android:layout_width">wrap_content</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:layout_alignParentTop">true</item> + <item name="android:layout_alignParentStart">true</item> + <item name="android:paddingEnd">16dp</item> + <item name="android:singleLine">true</item> + <item name="android:textAppearance">@style/BlackTitle1</item> + </style> + <style name="DownloadDescriptionStyle"> + <item name="android:layout_width">wrap_content</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:layout_alignParentBottom">true</item> + <item name="android:layout_alignParentStart">true</item> + <item name="android:layout_marginEnd">16dp</item> + <item name="android:layout_marginTop">0dp</item> + <item name="android:textAlignment">viewStart</item> + <item name="android:ellipsize">start</item> + <item name="android:singleLine">true</item> + <item name="android:textAppearance">@style/BlackBody</item> + </style> + <style name="DownloadIconView" parent="@style/ListItemStartIcon"> + <item name="android:background">@color/light_active_color</item> + </style> + <style name="DownloadNewBadgeStyle"> + <item name="android:layout_width">wrap_content</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:background">@color/light_active_color</item> + <item name="android:layout_marginStart">-8dp</item> + <item name="android:layout_marginTop">-2dp</item> + <item name="android:paddingStart">6dp</item> + <item name="android:paddingEnd">6dp</item> + <item name="android:singleLine">true</item> + <item name="android:text">@string/prefetch_badge_new</item> + <item name="android:textAppearance">@style/TextAppearance.DownloadNewBadge</item> + </style> + <style name="TextAppearance.DownloadNewBadge"> + <item name="android:textColor">@android:color/white</item> + <item name="android:textSize">@dimen/text_size_small</item> + <item name="android:textStyle">bold</item> + <item name="android:textAllCaps">true</item> + </style> + + <!-- Download Home V2 --> + <style name="DownloadItemText"> + <item name="android:layout_width">0dp</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:maxLines">1</item> + <item name="android:ellipsize">end</item> + <item name="android:singleLine">true</item> + </style> + <style name="DownloadItemSelectionView"> + <item name="android:layout_width">24dp</item> + <item name="android:layout_height">24dp</item> + <item name="android:layout_marginStart">8dp</item> + <item name="android:layout_marginTop">8dp</item> + </style> +</resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index 98f09f1..d8debe0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -299,7 +299,7 @@ private ActivityTabStartupMetricsTracker mActivityTabStartupMetricsTracker; /** A means of providing the foreground tab of the activity to different features. */ - private ActivityTabProvider mActivityTabProvider; + private ActivityTabProvider mActivityTabProvider = new ActivityTabProvider(); /** Whether or not the activity is in started state. */ private boolean mStarted; @@ -334,7 +334,6 @@ mFullscreenManager = createFullscreenManager(); mCreatedFullscreenManager = true; - mActivityTabProvider = new ActivityTabProvider(); } @SuppressLint("NewApi")
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java index f6dadbc..8ec2388 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java
@@ -67,7 +67,7 @@ @Override public void onNavigationBack() { - if (mIsSearching) { + if (isSearching()) { super.onNavigationBack(); return; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java index d306fb8..90f0c03 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java
@@ -291,6 +291,7 @@ mPromoHeaderManager = new BookmarkPromoHeader(mContext, promoHeaderChangeAction); populateTopLevelFoldersList(); + notifyDataSetChanged(); } // BookmarkUIObserver implementations.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java index 0120db0..9890bde56 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
@@ -181,9 +181,8 @@ mNewTabButton = new CompositorButton( context, NEW_TAB_BUTTON_WIDTH_DP, NEW_TAB_BUTTON_HEIGHT_DP, newTabClickHandler); mNewTabButton.setResources(R.drawable.btn_tabstrip_new_tab_normal, - R.drawable.btn_tabstrip_new_tab_pressed, - R.drawable.btn_tabstrip_new_incognito_tab_normal, - R.drawable.btn_tabstrip_new_incognito_tab_pressed); + R.drawable.btn_tabstrip_new_tab_pressed, R.drawable.btn_tabstrip_new_tab_normal, + R.drawable.btn_tabstrip_new_tab_pressed); mNewTabButton.setIncognito(incognito); mNewTabButton.setY(NEW_TAB_BUTTON_Y_OFFSET_DP); mNewTabButton.setClickSlop(NEW_TAB_BUTTON_CLICK_SLOP_DP);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java index d02b367..bc2692c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
@@ -41,10 +41,6 @@ // Caching Variables private final RectF mStripFilterArea = new RectF(); - // 1px border colors - private static final float BORDER_OPACITY = 0.2f; - private static final float BORDER_OPACITY_INCOGNITO = 0.4f; - // Model selector buttons constants. private static final float MODEL_SELECTOR_BUTTON_Y_OFFSET_DP = 10.f; private static final float MODEL_SELECTOR_BUTTON_END_PADDING_DP = 6.f; @@ -330,10 +326,6 @@ return mOrientation; } - public float getBorderOpacity() { - return mIsIncognito ? BORDER_OPACITY_INCOGNITO : BORDER_OPACITY; - } - /** * Updates all internal resources and dimensions. * @param context The current Android {@link Context}.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java index cb43c5d..4223a1a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java
@@ -137,8 +137,8 @@ layoutHelper.getWidth() * mDpToPx, st.getDrawX() * mDpToPx, st.getDrawY() * mDpToPx, st.getWidth() * mDpToPx, st.getHeight() * mDpToPx, st.getContentOffsetX() * mDpToPx, st.getCloseButton().getOpacity(), - st.isLoading(), st.getLoadingSpinnerRotation(), layoutHelper.getBorderOpacity(), - layerTitleCache, resourceManager); + st.isLoading(), st.getLoadingSpinnerRotation(), layerTitleCache, + resourceManager); } } @@ -167,7 +167,7 @@ private native void nativePutStripTabLayer(long nativeTabStripSceneLayer, int id, int closeResourceId, int handleResourceId, boolean foreground, boolean closePressed, float toolbarWidth, float x, float y, float width, float height, float contentOffsetX, - float closeButtonAlpha, boolean isLoading, float spinnerRotation, float borderOpacity, + float closeButtonAlpha, boolean isLoading, float spinnerRotation, LayerTitleCache layerTitleCache, ResourceManager resourceManager); private native void nativeSetContentTree(long nativeTabStripSceneLayer, SceneLayer contentTree); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialog.java index 3180812..40e701b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialog.java
@@ -15,11 +15,11 @@ import android.widget.Spinner; import android.widget.TextView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.modaldialog.ModalDialogView; import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.preferences.download.DownloadDirectoryAdapter; import org.chromium.chrome.browser.widget.AlertDialogEditText; +import org.chromium.chrome.download.R; import java.io.File;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java index 51cf5d8..bf3ff50d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java
@@ -36,8 +36,8 @@ import org.chromium.base.AsyncTask; import org.chromium.base.ContextUtils; import org.chromium.base.VisibleForTesting; -import org.chromium.chrome.R; import org.chromium.chrome.browser.content.ContentUtils; +import org.chromium.chrome.download.R; import java.io.DataOutputStream; import java.io.File;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java index 668b844e..a8cefe06 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
@@ -6,34 +6,27 @@ import android.app.Activity; import android.content.Intent; -import android.support.graphics.drawable.VectorDrawableCompat; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.Toolbar; -import android.view.LayoutInflater; -import android.view.MenuItem; +import android.view.Gravity; import android.view.View; import android.view.ViewGroup; +import android.widget.FrameLayout; import org.chromium.base.ObserverList; -import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; -import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.download.home.filter.Filters; import org.chromium.chrome.browser.download.home.filter.Filters.FilterType; import org.chromium.chrome.browser.download.home.list.DateOrderedListCoordinator; +import org.chromium.chrome.browser.download.home.list.DateOrderedListCoordinator.DateOrderedListObserver; import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.download.home.snackbars.DeleteUndoCoordinator; -import org.chromium.chrome.browser.download.home.toolbar.DownloadHomeToolbar; +import org.chromium.chrome.browser.download.home.toolbar.ToolbarCoordinator; import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory; -import org.chromium.chrome.browser.download.ui.DownloadManagerUi; import org.chromium.chrome.browser.preferences.PreferencesLauncher; import org.chromium.chrome.browser.preferences.download.DownloadPreferences; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.snackbar.SnackbarManager; -import org.chromium.chrome.browser.widget.selection.SelectableListLayout; -import org.chromium.chrome.browser.widget.selection.SelectableListToolbar; import org.chromium.chrome.browser.widget.selection.SelectionDelegate; +import org.chromium.chrome.download.R; import java.io.Closeable; @@ -42,38 +35,21 @@ * is not fully fleshed out yet. */ class DownloadManagerCoordinatorImpl - implements DownloadManagerCoordinator, Toolbar.OnMenuItemClickListener { + implements DownloadManagerCoordinator, ToolbarCoordinator.ToolbarActionDelegate { private final ObserverList<Observer> mObservers = new ObserverList<>(); private final DateOrderedListCoordinator mListCoordinator; private final DeleteUndoCoordinator mDeleteCoordinator; - private SelectableListLayout<ListItem> mSelectableListLayout; + private final ToolbarCoordinator mToolbarCoordinator; + private final SelectionDelegate<ListItem> mSelectionDelegate; + + private final Activity mActivity; + private ViewGroup mMainView; - private DownloadHomeToolbar mToolbar; - private Activity mActivity; private boolean mMuteFilterChanges; - private boolean mIsSeparateActivity; - private int mSearchMenuId; - - private SelectionDelegate<ListItem> mSelectionDelegate; - - private SelectableListToolbar.SearchDelegate mSearchDelegate = - new SelectableListToolbar.SearchDelegate() { - @Override - public void onSearchTextChanged(String query) { - mListCoordinator.setSearchQuery(query); - } - - @Override - public void onEndSearch() { - mSelectableListLayout.onEndSearch(); - mListCoordinator.setSearchQuery(null); - } - }; /** Builds a {@link DownloadManagerCoordinatorImpl} instance. */ - @SuppressWarnings({"unchecked"}) // mSelectableListLayout public DownloadManagerCoordinatorImpl(Profile profile, Activity activity, boolean offTheRecord, boolean isSeparateActivity, SnackbarManager snackbarManager) { mActivity = activity; @@ -81,48 +57,57 @@ mSelectionDelegate = new SelectionDelegate<ListItem>(); mListCoordinator = new DateOrderedListCoordinator(mActivity, offTheRecord, OfflineContentAggregatorFactory.forProfile(profile), - mDeleteCoordinator::showSnackbar, mSelectionDelegate, this ::notifyFilterChanged); + mDeleteCoordinator::showSnackbar, mSelectionDelegate, this ::notifyFilterChanged, + createDateOrderedListObserver()); + mToolbarCoordinator = new ToolbarCoordinator( + mActivity, this, mListCoordinator, mSelectionDelegate, isSeparateActivity); - mMainView = - (ViewGroup) LayoutInflater.from(mActivity).inflate(R.layout.download_main, null); - mSelectableListLayout = - (SelectableListLayout<ListItem>) mMainView.findViewById(R.id.selectable_list); - - // TODO(shaktisahu): Maybe refactor SelectableListLayout to work without supplying empty - // view. - mSelectableListLayout.initializeEmptyView( - VectorDrawableCompat.create( - mActivity.getResources(), R.drawable.downloads_big, mActivity.getTheme()), - R.string.download_manager_ui_empty, R.string.download_manager_no_results); - - RecyclerView recyclerView = (RecyclerView) mListCoordinator.getView(); - mSelectableListLayout.initializeRecyclerView(recyclerView.getAdapter(), recyclerView); - - boolean isLocationEnabled = - ChromeFeatureList.isEnabled(ChromeFeatureList.DOWNLOADS_LOCATION_CHANGE); - int normalGroupId = - isLocationEnabled ? R.id.with_settings_normal_menu_group : R.id.normal_menu_group; - mSearchMenuId = isLocationEnabled ? R.id.with_settings_search_menu_id : R.id.search_menu_id; - - mToolbar = (DownloadHomeToolbar) mSelectableListLayout.initializeToolbar( - R.layout.download_home_toolbar, mSelectionDelegate, 0, null, normalGroupId, - R.id.selection_mode_menu_group, R.color.modern_primary_color, this, true, - isSeparateActivity); - mToolbar.getMenu().setGroupVisible(normalGroupId, true); - mToolbar.initializeSearchView( - mSearchDelegate, R.string.download_manager_search, mSearchMenuId); - - mIsSeparateActivity = isSeparateActivity; - if (!mIsSeparateActivity) mToolbar.removeCloseButton(); - + initializeView(); RecordUserAction.record("Android.DownloadManager.Open"); } + /** + * Creates the top level layout for download home including the toolbar. + * TODO(crbug.com/880468) : Investigate if it is better to do in XML. + */ + private void initializeView() { + mMainView = new FrameLayout(mActivity); + + FrameLayout.LayoutParams listParams = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); + listParams.setMargins(0, + mActivity.getResources().getDimensionPixelOffset(R.dimen.toolbar_height_no_shadow), + 0, 0); + mMainView.addView(mListCoordinator.getView(), listParams); + + FrameLayout.LayoutParams toolbarParams = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT); + toolbarParams.gravity = Gravity.TOP; + mMainView.addView(mToolbarCoordinator.getView(), toolbarParams); + } + + private DateOrderedListObserver createDateOrderedListObserver() { + return new DateOrderedListObserver() { + @Override + public void onListScroll(boolean canScrollUp) { + if (mToolbarCoordinator == null) return; + mToolbarCoordinator.setShowToolbarShadow(canScrollUp); + } + + @Override + public void onEmptyStateChanged(boolean isEmpty) { + if (mToolbarCoordinator == null) return; + mToolbarCoordinator.setSearchEnabled(!isEmpty); + } + }; + } + // DownloadManagerCoordinator implementation. @Override public void destroy() { mDeleteCoordinator.destroy(); mListCoordinator.destroy(); + mToolbarCoordinator.destroy(); } @Override @@ -132,7 +117,8 @@ @Override public boolean onBackPressed() { - // TODO(dtrainor): Clear selection if multi-select is supported. + if (mListCoordinator.handleBackPressed()) return true; + if (mToolbarCoordinator.handleBackPressed()) return true; return false; } @@ -158,6 +144,20 @@ mObservers.removeObserver(observer); } + // ToolbarActionDelegate implementation. + @Override + public void close() { + mActivity.finish(); + } + + @Override + public void openSettings() { + RecordUserAction.record("Android.DownloadManager.Settings"); + Intent intent = PreferencesLauncher.createIntentForSettingsPage( + mActivity, DownloadPreferences.class.getName()); + mActivity.startActivity(intent); + } + private void notifyFilterChanged(@FilterType int filter) { mSelectionDelegate.clearSelection(); if (mMuteFilterChanges) return; @@ -166,54 +166,6 @@ for (Observer observer : mObservers) observer.onUrlChanged(url); } - @Override - public boolean onMenuItemClick(MenuItem item) { - if ((item.getItemId() == R.id.close_menu_id - || item.getItemId() == R.id.with_settings_close_menu_id) - && mIsSeparateActivity) { - DownloadManagerUi.recordMenuActionHistogram(DownloadManagerUi.MenuAction.CLOSE); - mActivity.finish(); - return true; - } else if (item.getItemId() == R.id.selection_mode_delete_menu_id) { - DownloadManagerUi.recordMenuActionHistogram(DownloadManagerUi.MenuAction.MULTI_DELETE); - RecordHistogram.recordCount100Histogram( - "Android.DownloadManager.Menu.Delete.SelectedCount", - mSelectionDelegate.getSelectedItems().size()); - mListCoordinator.onDeletionRequested(mSelectionDelegate.getSelectedItemsAsList()); - mSelectionDelegate.clearSelection(); - return true; - } else if (item.getItemId() == R.id.selection_mode_share_menu_id) { - // TODO(twellington): ideally the intent chooser would be started with - // startActivityForResult() and the selection would only be cleared - // after receiving an OK response. See https://crbug.com/638916. - - DownloadManagerUi.recordMenuActionHistogram(DownloadManagerUi.MenuAction.MULTI_SHARE); - RecordHistogram.recordCount100Histogram( - "Android.DownloadManager.Menu.Share.SelectedCount", - mSelectionDelegate.getSelectedItems().size()); - - // TODO(shaktisahu): Share selected items. - mSelectionDelegate.clearSelection(); - return true; - } else if (item.getItemId() == mSearchMenuId) { - // The header should be removed as soon as a search is started. Also it should be added - // back when the search is ended. - // TODO(shaktisahu): Check with UX and remove header. - mSelectableListLayout.onStartSearch(); - mToolbar.showSearchView(); - DownloadManagerUi.recordMenuActionHistogram(DownloadManagerUi.MenuAction.SEARCH); - RecordUserAction.record("Android.DownloadManager.Search"); - return true; - } else if (item.getItemId() == R.id.settings_menu_id) { - Intent intent = PreferencesLauncher.createIntentForSettingsPage( - mActivity, DownloadPreferences.class.getName()); - mActivity.startActivity(intent); - RecordUserAction.record("Android.DownloadManager.Settings"); - return true; - } - return false; - } - /** * Helper class to mute state changes when processing a state change request from an external * source.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/UmaUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/UmaUtils.java new file mode 100644 index 0000000..c5156a6 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/UmaUtils.java
@@ -0,0 +1,39 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.download.home; + +import android.support.annotation.IntDef; + +import org.chromium.base.metrics.RecordHistogram; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** Utility methods related to metrics collection on download home. */ +public class UmaUtils { + // Please treat this list as append only and keep it in sync with + // Android.DownloadManager.Menu.Actions in enums.xml. + @IntDef({MenuAction.CLOSE, MenuAction.MULTI_DELETE, MenuAction.MULTI_SHARE, + MenuAction.SHOW_INFO, MenuAction.HIDE_INFO, MenuAction.SEARCH}) + @Retention(RetentionPolicy.SOURCE) + public @interface MenuAction { + int CLOSE = 0; + int MULTI_DELETE = 1; + int MULTI_SHARE = 2; + int SHOW_INFO = 3; + int HIDE_INFO = 4; + int SEARCH = 5; + int NUM_ENTRIES = 6; + } + + /** + * Called to record metrics for the given menu action. + * @param action The given menu action. + */ + public static void recordMenuActionHistogram(@MenuAction int action) { + RecordHistogram.recordEnumeratedHistogram( + "Android.DownloadManager.Menu.Action", action, MenuAction.NUM_ENTRIES); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/empty/EmptyView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/empty/EmptyView.java index 7c5fe1e..3c51ed4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/empty/EmptyView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/empty/EmptyView.java
@@ -14,9 +14,9 @@ import android.view.ViewGroup; import android.widget.TextView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.empty.EmptyProperties.State; import org.chromium.chrome.browser.widget.LoadingView; +import org.chromium.chrome.download.R; /** A view that represents the visuals required for the empty state of the download home list. */ class EmptyView {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterView.java index df7092d..cd99d2f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterView.java
@@ -13,8 +13,8 @@ import android.view.ViewGroup.LayoutParams; import org.chromium.base.Callback; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.filter.FilterCoordinator.TabType; +import org.chromium.chrome.download.R; /** * A View class responsible for setting specific properties from a {@link FilterModel} to a
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java index cc1523687..ea06c32 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java
@@ -5,7 +5,10 @@ package org.chromium.chrome.browser.download.home.list; import android.content.Context; +import android.view.Gravity; import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; import org.chromium.base.Callback; import org.chromium.chrome.browser.download.home.PrefetchStatusProvider; @@ -14,6 +17,7 @@ import org.chromium.chrome.browser.download.home.filter.Filters.FilterType; import org.chromium.chrome.browser.download.home.list.ListItem.ViewListItem; import org.chromium.chrome.browser.download.home.storage.StorageCoordinator; +import org.chromium.chrome.browser.download.home.toolbar.ToolbarCoordinator; import org.chromium.chrome.browser.widget.selection.SelectionDelegate; import org.chromium.components.offline_items_collection.OfflineContentProvider; import org.chromium.components.offline_items_collection.OfflineItem; @@ -24,7 +28,7 @@ * The top level coordinator for the download home UI. This is currently an in progress class and * is not fully fleshed out yet. */ -public class DateOrderedListCoordinator { +public class DateOrderedListCoordinator implements ToolbarCoordinator.ToolbarListActionDelegate { /** * A helper interface for exposing the decision for whether or not to delete * {@link OfflineItem}s to an external layer. @@ -45,34 +49,56 @@ void canDelete(List<OfflineItem> items, Callback<Boolean> callback); } + /** + * An observer to be notified about certain changes about the recycler view and the underlying + * list. + */ + public interface DateOrderedListObserver { + /** + * Called after a scroll operation on the view. + * @param canScrollUp Whether the scroll position can scroll vertically further up. + */ + void onListScroll(boolean canScrollUp); + + /** + * Called when the empty state of the list has changed. + * @param isEmpty Whether the list is now empty. + */ + void onEmptyStateChanged(boolean isEmpty); + } + private final StorageCoordinator mStorageCoordinator; private final FilterCoordinator mFilterCoordinator; private final EmptyCoordinator mEmptyCoordinator; private final DateOrderedListMediator mMediator; - private final DateOrderedListView mView; + private final DateOrderedListView mListView; + private ViewGroup mMainView; - /** Creates an instance of a DateOrderedListCoordinator, which will visually represent + /** + * Creates an instance of a DateOrderedListCoordinator, which will visually represent * {@code provider} as a list of items. - * @param context The {@link Context} to use to build the views. - * @param offTheRecord Whether or not to include off the record items. - * @param provider The {@link OfflineContentProvider} to visually represent. + * @param context The {@link Context} to use to build the views. + * @param offTheRecord Whether or not to include off the record items. + * @param provider The {@link OfflineContentProvider} to visually represent. * @param deleteController A class to manage whether or not items can be deleted. - * @param filterObserver A {@link FilterCoordinator.Observer} that should be notified of - * filter changes. This is meant to be used for external components - * that need to take action based on the visual state of the list. + * @param filterObserver A {@link FilterCoordinator.Observer} that should be notified of + * filter changes. This is meant to be used for external components that + * need to take action based on the visual state of the list. + * @param dateOrderedListObserver A {@link DateOrderedListObserver}. */ public DateOrderedListCoordinator(Context context, Boolean offTheRecord, OfflineContentProvider provider, DeleteController deleteController, SelectionDelegate<ListItem> selectionDelegate, - FilterCoordinator.Observer filterObserver) { + FilterCoordinator.Observer filterObserver, + DateOrderedListObserver dateOrderedListObserver) { // TODO(shaktisahu): Use a real provider/have this provider query the real data source. PrefetchStatusProvider prefetchProvider = new PrefetchStatusProvider(); ListItemModel model = new ListItemModel(); DecoratedListItemModel decoratedModel = new DecoratedListItemModel(model); - mView = new DateOrderedListView(context, decoratedModel); + mListView = new DateOrderedListView(context, decoratedModel, dateOrderedListObserver); mMediator = new DateOrderedListMediator(offTheRecord, provider, context::startActivity, - deleteController, selectionDelegate, model); + deleteController, selectionDelegate, dateOrderedListObserver, model); mEmptyCoordinator = new EmptyCoordinator(context, prefetchProvider, mMediator.getEmptySource()); @@ -89,6 +115,25 @@ new ViewListItem(Long.MAX_VALUE - 1L, mStorageCoordinator.getView())); decoratedModel.addHeader( new ViewListItem(Long.MAX_VALUE - 2L, mFilterCoordinator.getView())); + initializeView(context); + } + + /** + * Creates a top-level view containing the {@link DateOrderedListView} and {@link EmptyView}. + * The list view is added on top of the empty view so that the empty view will show up when the + * list has no items or is loading. + * @param context The current context. + */ + private void initializeView(Context context) { + mMainView = new FrameLayout(context); + FrameLayout.LayoutParams emptyViewParams = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT); + emptyViewParams.gravity = Gravity.CENTER; + mMainView.addView(mEmptyCoordinator.getView(), emptyViewParams); + + FrameLayout.LayoutParams listParams = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); + mMainView.addView(mListView.getView(), listParams); } /** Tears down this coordinator. */ @@ -98,11 +143,29 @@ /** @return The {@link View} representing downloads home. */ public View getView() { - return mView.getView(); + return mMainView; } - /** Sets the string filter query to {@code query}. */ + // ToolbarListActionDelegate implementation. + @Override + public void deleteSelectedItems() { + mMediator.deleteSelectedItems(); + } + + @Override + public void shareSelectedItems() { + mMediator.shareSelectedItems(); + } + + /** Called to handle a back press event. */ + public boolean handleBackPressed() { + return mMediator.handleBackPressed(); + } + + @Override public void setSearchQuery(String query) { + // TODO(crbug.com/881047): Check with UX, if the text on empty view should change during + // search. mMediator.onFilterStringChanged(query); } @@ -110,14 +173,4 @@ public void setSelectedFilter(@FilterType int filter) { mFilterCoordinator.setSelectedFilter(filter); } - - /** Called to delete a list of items specified by {@code items}. */ - public void onDeletionRequested(List<ListItem> items) { - mMediator.onDeletionRequested(items); - } - - /** Called to share a list of items specified by {@code items}. */ - public void onShareRequested(List<ListItem> items) { - mMediator.onShareRequested(items); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java index 76c6f00..de948ca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
@@ -10,16 +10,20 @@ import org.chromium.base.CollectionUtil; import org.chromium.base.ContextUtils; +import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.download.home.OfflineItemSource; import org.chromium.chrome.browser.download.home.filter.DeleteUndoOfflineItemFilter; import org.chromium.chrome.browser.download.home.filter.Filters.FilterType; import org.chromium.chrome.browser.download.home.filter.OffTheRecordOfflineItemFilter; +import org.chromium.chrome.browser.download.home.filter.OfflineItemFilter; +import org.chromium.chrome.browser.download.home.filter.OfflineItemFilterObserver; import org.chromium.chrome.browser.download.home.filter.OfflineItemFilterSource; import org.chromium.chrome.browser.download.home.filter.SearchOfflineItemFilter; import org.chromium.chrome.browser.download.home.filter.TypeOfflineItemFilter; import org.chromium.chrome.browser.download.home.glue.OfflineContentProviderGlue; import org.chromium.chrome.browser.download.home.glue.ThumbnailRequestGlue; +import org.chromium.chrome.browser.download.home.list.DateOrderedListCoordinator.DateOrderedListObserver; import org.chromium.chrome.browser.download.home.list.DateOrderedListCoordinator.DeleteController; import org.chromium.chrome.browser.widget.ThumbnailProvider; import org.chromium.chrome.browser.widget.ThumbnailProvider.ThumbnailRequest; @@ -61,6 +65,7 @@ private final DateOrderedListMutator mListMutator; private final ThumbnailProvider mThumbnailProvider; private final MediatorSelectionObserver mSelectionObserver; + private final SelectionDelegate<ListItem> mSelectionDelegate; private final OffTheRecordOfflineItemFilter mOffTheRecordFilter; private final DeleteUndoOfflineItemFilter mDeleteUndoFilter; @@ -97,15 +102,19 @@ /** * Creates an instance of a DateOrderedListMediator that will push {@code provider} into * {@code model}. - * @param offTheRecord Whether or not to include off the record items. - * @param provider The {@link OfflineContentProvider} to visually represent. - * @param deleteController A class to manage whether or not items can be deleted. - * @param shareController A class responsible for sharing downloaded item {@link Intent}s. - * @param model The {@link ListItemModel} to push {@code provider} into. + * @param offTheRecord Whether or not to include off the record items. + * @param provider The {@link OfflineContentProvider} to visually represent. + * @param deleteController A class to manage whether or not items can be deleted. + * @param shareController A class responsible for sharing downloaded item {@link + * Intent}s. + * @param selectionDelegate A class responsible for handling list item selection. + * @param dateOrderedListObserver An observer of the list and recycler view. + * @param model The {@link ListItemModel} to push {@code provider} into. */ public DateOrderedListMediator(boolean offTheRecord, OfflineContentProvider provider, ShareController shareController, DeleteController deleteController, - SelectionDelegate<ListItem> selectionDelegate, ListItemModel model) { + SelectionDelegate<ListItem> selectionDelegate, + DateOrderedListObserver dateOrderedListObserver, ListItemModel model) { // Build a chain from the data source to the model. The chain will look like: // [OfflineContentProvider] -> // [OfflineItemSource] -> @@ -120,6 +129,7 @@ mShareController = shareController; mModel = model; mDeleteController = deleteController; + mSelectionDelegate = selectionDelegate; mSource = new OfflineItemSource(mProvider); mOffTheRecordFilter = new OffTheRecordOfflineItemFilter(offTheRecord, mSource); @@ -128,6 +138,7 @@ mSearchFilter = new SearchOfflineItemFilter(mTypeFilter); mListMutator = new DateOrderedListMutator(mSearchFilter, mModel); + mSearchFilter.addObserver(new EmptyStateObserver(mSearchFilter, dateOrderedListObserver)); mThumbnailProvider = new ThumbnailProviderImpl( ((ChromeApplication) ContextUtils.getApplicationContext()).getReferencePool()); mSelectionObserver = new MediatorSelectionObserver(selectionDelegate); @@ -173,14 +184,31 @@ } } - /** Called to delete a list of items specified by {@code items}. */ - public void onDeletionRequested(List<ListItem> items) { - onDeleteItems(ListUtils.toOfflineItems(items)); + /** Called to delete the list of currently selected items. */ + public void deleteSelectedItems() { + RecordHistogram.recordCount100Histogram("Android.DownloadManager.Menu.Delete.SelectedCount", + mSelectionDelegate.getSelectedItems().size()); + + onDeleteItems(ListUtils.toOfflineItems(mSelectionDelegate.getSelectedItems())); + mSelectionDelegate.clearSelection(); } - /** Called to share a list of items specified by {@code items}. */ - public void onShareRequested(List<ListItem> items) { - onShareItems(ListUtils.toOfflineItems(items)); + /** Called to share the list of currently selected items. */ + public void shareSelectedItems() { + RecordHistogram.recordCount100Histogram("Android.DownloadManager.Menu.Share.SelectedCount", + mSelectionDelegate.getSelectedItems().size()); + + onShareItems(ListUtils.toOfflineItems(mSelectionDelegate.getSelectedItems())); + mSelectionDelegate.clearSelection(); + } + + /** Called to handle a back press event. */ + public boolean handleBackPressed() { + if (mSelectionDelegate.isSelectionEnabled()) { + mSelectionDelegate.clearSelection(); + return true; + } + return false; } /** @@ -271,4 +299,49 @@ }); } } + + /** + * A helper class to observe the list content and notify the given observer when the list state + * changes between empty and non-empty. + */ + private static class EmptyStateObserver implements OfflineItemFilterObserver { + private boolean mIsEmpty; + private final DateOrderedListObserver mDateOrderedListObserver; + private final OfflineItemFilter mOfflineItemFilter; + + public EmptyStateObserver(OfflineItemFilter offlineItemFilter, + DateOrderedListObserver dateOrderedListObserver) { + mOfflineItemFilter = offlineItemFilter; + mDateOrderedListObserver = dateOrderedListObserver; + calculateEmptyState(); + } + + @Override + public void onItemsAvailable() { + calculateEmptyState(); + } + + @Override + public void onItemsAdded(Collection<OfflineItem> items) { + calculateEmptyState(); + } + + @Override + public void onItemsRemoved(Collection<OfflineItem> items) { + calculateEmptyState(); + } + + @Override + public void onItemUpdated(OfflineItem oldItem, OfflineItem item) { + calculateEmptyState(); + } + + private void calculateEmptyState() { + boolean isEmpty = mOfflineItemFilter.getItems().isEmpty(); + if (mIsEmpty == isEmpty) return; + + mIsEmpty = isEmpty; + mDateOrderedListObserver.onEmptyStateChanged(mIsEmpty); + } + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java index 26c21efb..1a95bb09 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java
@@ -15,6 +15,7 @@ import android.view.View; import org.chromium.chrome.R; +import org.chromium.chrome.browser.download.home.list.DateOrderedListCoordinator.DateOrderedListObserver; import org.chromium.chrome.browser.download.home.list.holder.ListItemViewHolder; import org.chromium.chrome.browser.modelutil.ForwardingListObservable; import org.chromium.chrome.browser.modelutil.PropertyModelChangeProcessor; @@ -61,7 +62,8 @@ } /** Creates an instance of a {@link DateOrderedListView} representing {@code model}. */ - public DateOrderedListView(Context context, DecoratedListItemModel model) { + public DateOrderedListView(Context context, DecoratedListItemModel model, + DateOrderedListObserver dateOrderedListObserver) { mModel = model; mImageWidthPx = @@ -88,6 +90,12 @@ mModel, new ModelChangeProcessor(mModel), ListItemViewHolder::create); mView.setAdapter(adapter); mView.post(adapter::notifyDataSetChanged); + mView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(RecyclerView view, int dx, int dy) { + dateOrderedListObserver.onListScroll(mView.canScrollVertically(-1)); + } + }); } /** @return The Android {@link View} representing this widget. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListUtils.java index b71f683..652ee4e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListUtils.java
@@ -18,6 +18,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Collection; import java.util.List; /** Utility methods for representing {@link ListItem}s in a {@link RecyclerView} list. */ @@ -41,7 +42,7 @@ } /** Converts a given list of {@link ListItem}s to a list of {@link OfflineItem}s. */ - public static List<OfflineItem> toOfflineItems(List<ListItem> items) { + public static List<OfflineItem> toOfflineItems(Collection<ListItem> items) { List<OfflineItem> offlineItems = new ArrayList<>(); for (ListItem item : items) { if (item instanceof ListItem.OfflineItemListItem) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/DateViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/DateViewHolder.java index a3f0a29..308c1d8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/DateViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/DateViewHolder.java
@@ -9,10 +9,10 @@ import android.view.ViewGroup; import android.widget.TextView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.download.home.list.UiUtils; import org.chromium.chrome.browser.modelutil.PropertyModel; +import org.chromium.chrome.download.R; /** A {@link RecyclerView.ViewHolder} specifically meant to display a date header. */ public class DateViewHolder extends ListItemViewHolder {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/GenericViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/GenericViewHolder.java index f4ff977..25ee4a60 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/GenericViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/GenericViewHolder.java
@@ -16,12 +16,12 @@ import android.widget.ImageView; import android.widget.TextView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.download.home.list.UiUtils; import org.chromium.chrome.browser.download.home.view.SelectionView; import org.chromium.chrome.browser.modelutil.PropertyModel; import org.chromium.chrome.browser.widget.TintedImageView; +import org.chromium.chrome.download.R; import org.chromium.components.offline_items_collection.OfflineItemVisuals; /** A {@link RecyclerView.ViewHolder} specifically meant to display a generic {@code OfflineItem}.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ImageViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ImageViewHolder.java index d5a321b..637ac7e6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ImageViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ImageViewHolder.java
@@ -9,10 +9,10 @@ import android.view.ViewGroup; import android.widget.ImageView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.download.home.view.LoadingBackground; import org.chromium.chrome.browser.modelutil.PropertyModel; +import org.chromium.chrome.download.R; import org.chromium.components.offline_items_collection.OfflineItemVisuals; /** A {@link RecyclerView.ViewHolder} specifically meant to display an image {@code OfflineItem}. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/InProgressViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/InProgressViewHolder.java index ec0ce711..c7376ac5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/InProgressViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/InProgressViewHolder.java
@@ -10,12 +10,12 @@ import android.widget.ProgressBar; import android.widget.TextView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.DownloadUtils; import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.download.home.list.ListProperties; import org.chromium.chrome.browser.modelutil.PropertyModel; import org.chromium.chrome.browser.widget.TintedImageButton; +import org.chromium.chrome.download.R; import org.chromium.components.offline_items_collection.OfflineItemState; /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/MoreButtonViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/MoreButtonViewHolder.java index d889181..434a3a4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/MoreButtonViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/MoreButtonViewHolder.java
@@ -7,11 +7,11 @@ import android.support.annotation.CallSuper; import android.view.View; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.download.home.list.ListProperties; import org.chromium.chrome.browser.modelutil.PropertyModel; import org.chromium.chrome.browser.widget.ListMenuButton; +import org.chromium.chrome.download.R; /** * Helper {@link RecyclerView.ViewHolder} that handles showing a 3-dot menu with preset actions.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/PrefetchViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/PrefetchViewHolder.java index 4eb4a58d..71e1c89 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/PrefetchViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/PrefetchViewHolder.java
@@ -10,10 +10,10 @@ import android.widget.ImageView; import android.widget.TextView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.download.home.list.UiUtils; import org.chromium.chrome.browser.modelutil.PropertyModel; +import org.chromium.chrome.download.R; import org.chromium.components.offline_items_collection.OfflineItemVisuals; /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SectionTitleViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SectionTitleViewHolder.java index eb450cbf..ab664e2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SectionTitleViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SectionTitleViewHolder.java
@@ -10,10 +10,10 @@ import android.view.ViewGroup; import android.widget.TextView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.download.home.list.ListUtils; import org.chromium.chrome.browser.modelutil.PropertyModel; +import org.chromium.chrome.download.R; import org.chromium.components.offline_items_collection.OfflineItemFilter; /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SeparatorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SeparatorViewHolder.java index eb12f41..881c85d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SeparatorViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SeparatorViewHolder.java
@@ -8,9 +8,9 @@ import android.view.View; import android.view.ViewGroup; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.modelutil.PropertyModel; +import org.chromium.chrome.download.R; /** * A {@link ViewHolder} specifically meant to display a separator.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ThumbnailAwareViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ThumbnailAwareViewHolder.java index fdb26374..edcbf02f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ThumbnailAwareViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ThumbnailAwareViewHolder.java
@@ -9,11 +9,11 @@ import android.view.View; import android.widget.ImageView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.download.home.list.ListProperties; import org.chromium.chrome.browser.download.home.view.SelectionView; import org.chromium.chrome.browser.modelutil.PropertyModel; +import org.chromium.chrome.download.R; import org.chromium.components.offline_items_collection.ContentId; import org.chromium.components.offline_items_collection.OfflineItem; import org.chromium.components.offline_items_collection.OfflineItemVisuals;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/VideoViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/VideoViewHolder.java index 03d1fd5..ef11049e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/VideoViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/VideoViewHolder.java
@@ -11,11 +11,11 @@ import android.widget.ImageView; import android.widget.TextView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.download.home.list.UiUtils; import org.chromium.chrome.browser.download.home.view.LoadingBackground; import org.chromium.chrome.browser.modelutil.PropertyModel; +import org.chromium.chrome.download.R; import org.chromium.components.offline_items_collection.OfflineItemVisuals; /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/storage/StorageCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/storage/StorageCoordinator.java index 818790e..4c41d1b1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/storage/StorageCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/storage/StorageCoordinator.java
@@ -9,12 +9,12 @@ import android.view.View; import android.widget.TextView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.filter.OfflineItemFilterSource; import org.chromium.chrome.browser.modelutil.PropertyKey; import org.chromium.chrome.browser.modelutil.PropertyModel; import org.chromium.chrome.browser.modelutil.PropertyModel.ObjectPropertyKey; import org.chromium.chrome.browser.modelutil.PropertyModelChangeProcessor; +import org.chromium.chrome.download.R; /** * The coordinator responsible for creating the storage summary view in download home.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java index 23b7c79..154c6f0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java
@@ -9,9 +9,9 @@ import android.view.View; import org.chromium.base.metrics.RecordUserAction; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.list.ListItem; import org.chromium.chrome.browser.widget.selection.SelectableListToolbar; +import org.chromium.chrome.download.R; import java.util.List; @@ -44,7 +44,7 @@ boolean wasSelectionEnabled = mIsSelectionEnabled; super.onSelectionStateChange(selectedItems); - mTitleBar.setVisibility((mIsSelectionEnabled || mIsSearching) ? GONE : VISIBLE); + mTitleBar.setVisibility((mIsSelectionEnabled || isSearching()) ? GONE : VISIBLE); if (mIsSelectionEnabled) { int numSelected = mSelectionDelegate.getSelectedItems().size();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/ToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/ToolbarCoordinator.java new file mode 100644 index 0000000..b4d305c4 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/ToolbarCoordinator.java
@@ -0,0 +1,218 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.download.home.toolbar; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; + +import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.base.metrics.RecordUserAction; +import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.download.home.UmaUtils; +import org.chromium.chrome.browser.download.home.list.ListItem; +import org.chromium.chrome.browser.widget.FadingShadow; +import org.chromium.chrome.browser.widget.FadingShadowView; +import org.chromium.chrome.browser.widget.displaystyle.UiConfig; +import org.chromium.chrome.browser.widget.selection.SelectableListToolbar; +import org.chromium.chrome.browser.widget.selection.SelectionDelegate; +import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionObserver; +import org.chromium.chrome.download.R; + +import java.util.List; + +/** + * A top level class to handle various toolbar related functionalities in download home. + */ +public class ToolbarCoordinator implements SelectionObserver<ListItem> { + /** + * A delegate to handle various actions taken by user that relate to list items. + */ + public interface ToolbarListActionDelegate { + /** + * Invoked when user taps on the delete button to delete the currently selected items. + */ + void deleteSelectedItems(); + + /** + * Invoked when user taps on the share button to share the currently selected items. + */ + void shareSelectedItems(); + + /** + * Invoked when user starts a search on download home. + * @param query The search text on which downloads will be filtered. + */ + void setSearchQuery(String query); + } + + /** + * A delegate to handle various non-list related actions taken by the user on the download home + * toolbar. + */ + public interface ToolbarActionDelegate { + /** + * Invoked when user taps on close button to close download home. + */ + void close(); + + /** + * Invoked when user taps on settings menu button to open the download home settings page. + */ + void openSettings(); + } + + private final ToolbarListActionDelegate mListActionDelegate; + private final ToolbarActionDelegate mDelegate; + + private final UiConfig mUiConfig; + private final ViewGroup mView; + private final DownloadHomeToolbar mToolbar; + private final FadingShadowView mShadow; + + private boolean mShowToolbarShadow; + + private SelectableListToolbar.SearchDelegate mSearchDelegate = + new SelectableListToolbar.SearchDelegate() { + @Override + public void onSearchTextChanged(String query) { + mListActionDelegate.setSearchQuery(query); + } + + @Override + public void onEndSearch() { + mListActionDelegate.setSearchQuery(null); + updateShadowVisibility(); + } + }; + + public ToolbarCoordinator(Context context, ToolbarActionDelegate delegate, + ToolbarListActionDelegate listActionDelegate, + SelectionDelegate<ListItem> selectionDelegate, boolean hasCloseButton) { + mDelegate = delegate; + mListActionDelegate = listActionDelegate; + + final boolean isLocationEnabled = + ChromeFeatureList.isEnabled(ChromeFeatureList.DOWNLOADS_LOCATION_CHANGE); + + final int normalMenuGroupId = + isLocationEnabled ? R.id.with_settings_normal_menu_group : R.id.normal_menu_group; + final int searchMenuId = + isLocationEnabled ? R.id.with_settings_search_menu_id : R.id.search_menu_id; + + mView = (ViewGroup) LayoutInflater.from(context).inflate( + R.layout.download_home_toolbar, null); + mToolbar = mView.findViewById(R.id.toolbar); + mShadow = mView.findViewById(R.id.shadow); + + mUiConfig = new UiConfig(mView); + + mToolbar.initialize(selectionDelegate, 0 /* titleResId */, null /* drawerLayout */, + normalMenuGroupId, R.id.selection_mode_menu_group, R.color.modern_primary_color, + hasCloseButton); + mToolbar.setOnMenuItemClickListener(this ::onMenuItemClick); + + // TODO(crbug.com/881037): Pass the visible group to the toolbar during initialization. + mToolbar.getMenu().setGroupVisible(normalMenuGroupId, true); + mToolbar.initializeSearchView( + mSearchDelegate, R.string.download_manager_search, searchMenuId); + mToolbar.configureWideDisplayStyle(mUiConfig); + + mShadow.init(ApiCompatibilityUtils.getColor( + context.getResources(), R.color.toolbar_shadow_color), + FadingShadow.POSITION_TOP); + + if (!hasCloseButton) mToolbar.removeCloseButton(); + } + + /** + * Called when the activity/native page is destroyed. + */ + public void destroy() { + mToolbar.destroy(); + } + + /** @return The Android {@link View} representing this widget. */ + public View getView() { + return mView; + } + + /** + * Called to update whether the toolbar should show a shadow. + * @param show Whether the shadow should be shown. + */ + public void setShowToolbarShadow(boolean show) { + if (mShowToolbarShadow == show) return; + + mShowToolbarShadow = show; + updateShadowVisibility(); + } + + /** + * Called to enable/disable the search menu button. + * @param searchEnabled Whether search is currently enabled + */ + public void setSearchEnabled(boolean searchEnabled) { + mToolbar.setSearchEnabled(searchEnabled); + } + + /** + * Invoked on the event back button was pressed. Gives a chance to this view to run any special + * handling. + * @return True if the event was handled, false otherwise. + */ + public boolean handleBackPressed() { + if (mToolbar.isSearching()) { + mToolbar.hideSearchView(); + return true; + } + + return false; + } + + // SelectionObserver<ListItem> implementation. + @Override + public void onSelectionStateChange(List<ListItem> selectedItems) { + updateShadowVisibility(); + } + + private boolean onMenuItemClick(MenuItem item) { + if (item.getItemId() == R.id.close_menu_id + || item.getItemId() == R.id.with_settings_close_menu_id) { + UmaUtils.recordMenuActionHistogram(UmaUtils.MenuAction.CLOSE); + mDelegate.close(); + return true; + } else if (item.getItemId() == R.id.selection_mode_delete_menu_id) { + UmaUtils.recordMenuActionHistogram(UmaUtils.MenuAction.MULTI_DELETE); + mListActionDelegate.deleteSelectedItems(); + return true; + } else if (item.getItemId() == R.id.selection_mode_share_menu_id) { + UmaUtils.recordMenuActionHistogram(UmaUtils.MenuAction.MULTI_SHARE); + mListActionDelegate.shareSelectedItems(); + return true; + } else if (item.getItemId() == R.id.with_settings_search_menu_id + || item.getItemId() == R.id.search_menu_id) { + RecordUserAction.record("Android.DownloadManager.Search"); + UmaUtils.recordMenuActionHistogram(UmaUtils.MenuAction.SEARCH); + mToolbar.showSearchView(); + updateShadowVisibility(); + return true; + } else if (item.getItemId() == R.id.settings_menu_id) { + // TODO(shaktisahu) : Add UMA for settings menu action. + mDelegate.openSettings(); + return true; + } else { + return false; + } + } + + // TODO(shaktisahu): May be merge toolbar shadow logic into the toolbar itself. + private void updateShadowVisibility() { + boolean show = mShowToolbarShadow || mToolbar.isSearching(); + mShadow.setVisibility(show ? ViewGroup.VISIBLE : View.GONE); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java index 193e1e3..ddc260e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
@@ -19,7 +19,6 @@ import org.chromium.base.ObserverList; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; -import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.download.DownloadItem; import org.chromium.chrome.browser.download.DownloadManagerService.DownloadObserver; @@ -32,6 +31,7 @@ import org.chromium.chrome.browser.widget.DateDividedAdapter; import org.chromium.chrome.browser.widget.displaystyle.UiConfig; import org.chromium.chrome.browser.widget.selection.SelectionDelegate; +import org.chromium.chrome.download.R; import org.chromium.components.download.DownloadState; import org.chromium.components.offline_items_collection.ContentId; import org.chromium.components.offline_items_collection.OfflineContentProvider;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java index 5ecece8..1fbd134d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java
@@ -23,7 +23,6 @@ import org.chromium.base.Callback; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.DownloadUtils; import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory; import org.chromium.chrome.browser.profiles.Profile; @@ -35,6 +34,7 @@ import org.chromium.chrome.browser.widget.ThumbnailProvider; import org.chromium.chrome.browser.widget.TintedImageButton; import org.chromium.chrome.browser.widget.selection.SelectableItemView; +import org.chromium.chrome.download.R; import org.chromium.components.offline_items_collection.OfflineItem; import org.chromium.components.offline_items_collection.OfflineItem.Progress; import org.chromium.components.variations.VariationsAssociatedData;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java index 3f8940ac..c1c564f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java
@@ -12,8 +12,8 @@ import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordUserAction; -import org.chromium.chrome.R; import org.chromium.chrome.browser.widget.selection.SelectableListToolbar; +import org.chromium.chrome.download.R; import java.util.List; @@ -73,7 +73,7 @@ boolean wasSelectionEnabled = mIsSelectionEnabled; super.onSelectionStateChange(selectedItems); - mSpinner.setVisibility((mIsSelectionEnabled || mIsSearching) ? GONE : VISIBLE); + mSpinner.setVisibility((mIsSelectionEnabled || isSearching()) ? GONE : VISIBLE); if (mIsSelectionEnabled) { int numSelected = mSelectionDelegate.getSelectedItems().size(); @@ -100,10 +100,10 @@ } @Override - protected void onDataChanged(int numItems) { - super.onDataChanged(numItems); + public void setSearchEnabled(boolean searchEnabled) { + super.setSearchEnabled(searchEnabled); MenuItem item = getMenu().findItem(mInfoMenuItemId); - if (item != null) item.setVisible(!mIsSearching && !mIsSelectionEnabled && numItems > 0); + if (item != null) item.setVisible(!isSearching() && !mIsSelectionEnabled && searchEnabled); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java index 7eaa9984..33c0514 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
@@ -8,7 +8,6 @@ import android.content.ComponentName; import android.content.Intent; import android.os.Handler; -import android.support.annotation.IntDef; import android.support.graphics.drawable.VectorDrawableCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -28,7 +27,6 @@ import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; -import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.download.DirectoryOption; @@ -36,6 +34,7 @@ import org.chromium.chrome.browser.download.DownloadManagerService; import org.chromium.chrome.browser.download.DownloadUtils; import org.chromium.chrome.browser.download.home.DownloadManagerCoordinator; +import org.chromium.chrome.browser.download.home.UmaUtils; import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; import org.chromium.chrome.browser.native_page.BasicNativePage; @@ -52,14 +51,13 @@ import org.chromium.chrome.browser.widget.selection.SelectableListToolbar.SearchDelegate; import org.chromium.chrome.browser.widget.selection.SelectionDelegate; import org.chromium.chrome.browser.widget.textbubble.TextBubble; +import org.chromium.chrome.download.R; import org.chromium.components.feature_engagement.FeatureConstants; import org.chromium.components.feature_engagement.Tracker; import org.chromium.components.offline_items_collection.OfflineContentProvider; import org.chromium.ui.widget.ViewRectProvider; import java.io.File; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -165,22 +163,6 @@ } } - // Please treat this list as append only and keep it in sync with - // Android.DownloadManager.Menu.Actions in enums.xml. - @IntDef({MenuAction.CLOSE, MenuAction.MULTI_DELETE, MenuAction.MULTI_SHARE, - MenuAction.SHOW_INFO, MenuAction.HIDE_INFO, MenuAction.SEARCH}) - @Retention(RetentionPolicy.SOURCE) - public @interface MenuAction { - // TODO(shaktisahu): Move these to new download home and make them private. - int CLOSE = 0; - int MULTI_DELETE = 1; - int MULTI_SHARE = 2; - int SHOW_INFO = 3; - int HIDE_INFO = 4; - int SEARCH = 5; - int NUM_ENTRIES = 6; - } - private static final int PREFETCH_BUNDLE_OPEN_DELAY_MS = 500; private static BackendProvider sProviderForTests; @@ -377,7 +359,7 @@ if ((item.getItemId() == R.id.close_menu_id || item.getItemId() == R.id.with_settings_close_menu_id) && mIsSeparateActivity) { - recordMenuActionHistogram(MenuAction.CLOSE); + UmaUtils.recordMenuActionHistogram(UmaUtils.MenuAction.CLOSE); mActivity.finish(); return true; } else if (item.getItemId() == R.id.selection_mode_delete_menu_id) { @@ -385,7 +367,7 @@ mBackendProvider.getSelectionDelegate().getSelectedItemsAsList(); mBackendProvider.getSelectionDelegate().clearSelection(); - recordMenuActionHistogram(MenuAction.MULTI_DELETE); + UmaUtils.recordMenuActionHistogram(UmaUtils.MenuAction.MULTI_DELETE); RecordHistogram.recordCount100Histogram( "Android.DownloadManager.Menu.Delete.SelectedCount", items.size()); @@ -399,7 +381,7 @@ // after receiving an OK response. See crbug.com/638916. mBackendProvider.getSelectionDelegate().clearSelection(); - recordMenuActionHistogram(MenuAction.MULTI_SHARE); + UmaUtils.recordMenuActionHistogram(UmaUtils.MenuAction.MULTI_SHARE); RecordHistogram.recordCount100Histogram( "Android.DownloadManager.Menu.Share.SelectedCount", items.size()); @@ -407,11 +389,12 @@ return true; } else if (item.getItemId() == mInfoMenuId) { boolean showInfo = !mHistoryAdapter.shouldShowStorageInfoHeader(); - recordMenuActionHistogram(showInfo ? MenuAction.SHOW_INFO : MenuAction.HIDE_INFO); + UmaUtils.recordMenuActionHistogram( + showInfo ? UmaUtils.MenuAction.SHOW_INFO : UmaUtils.MenuAction.HIDE_INFO); enableStorageInfoHeader(showInfo); return true; } else if (item.getItemId() == mSearchMenuId) { - recordMenuActionHistogram(MenuAction.SEARCH); + UmaUtils.recordMenuActionHistogram(UmaUtils.MenuAction.SEARCH); // The header should be removed as soon as a search is started. It will be added back in // DownloadHistoryAdatper#filter() when the search is ended. mHistoryAdapter.removeHeader(); @@ -623,11 +606,6 @@ sProviderForTests = provider; } - public static void recordMenuActionHistogram(@MenuAction int action) { - RecordHistogram.recordEnumeratedHistogram( - "Android.DownloadManager.Menu.Action", action, MenuAction.NUM_ENTRIES); - } - private void shareItems(final List<DownloadHistoryItemWrapper> items) { boolean done = DownloadUtils.prepareForSharing(items, (newFilePathMap) -> { startShareIntent(DownloadUtils.createShareIntent(items, newFilePathMap));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilterAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilterAdapter.java index 295971a..f0b57b2d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilterAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilterAdapter.java
@@ -16,8 +16,8 @@ import android.widget.TextView; import org.chromium.base.ApiCompatibilityUtils; -import org.chromium.chrome.R; import org.chromium.chrome.browser.util.FeatureUtilities; +import org.chromium.chrome.download.R; /** An adapter that allows selecting an item from a dropdown spinner. */ class FilterAdapter extends BaseAdapter implements AdapterView.OnItemSelectedListener { @@ -29,7 +29,8 @@ */ FilterAdapter(Resources resources) { super(); - mIconColor = ApiCompatibilityUtils.getColor(resources, R.color.default_icon_color); + mIconColor = ApiCompatibilityUtils.getColor( + resources, org.chromium.chrome.R.color.default_icon_color); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OfflineGroupHeaderView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OfflineGroupHeaderView.java index 46c245ab..ae8114c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OfflineGroupHeaderView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OfflineGroupHeaderView.java
@@ -15,7 +15,6 @@ import android.widget.TextView; import org.chromium.base.ApiCompatibilityUtils; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.DownloadUtils; import org.chromium.chrome.browser.download.ui.DownloadHistoryAdapter.SubsectionHeader; import org.chromium.chrome.browser.download.ui.DownloadItemSelectionDelegate.SubsectionHeaderSelectionObserver; @@ -23,6 +22,7 @@ import org.chromium.chrome.browser.widget.DateDividedAdapter.TimedItem; import org.chromium.chrome.browser.widget.TintedImageView; import org.chromium.chrome.browser.widget.selection.SelectableItemView; +import org.chromium.chrome.download.R; import java.util.Set;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java index 168b376ed..7b29159 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java
@@ -21,9 +21,9 @@ import org.chromium.base.ObserverList; import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.DownloadUtils; import org.chromium.chrome.browser.widget.MaterialProgressBar; +import org.chromium.chrome.download.R; import java.io.File; import java.util.concurrent.RejectedExecutionException;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerToolbar.java index cf17f2f..6a75878 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerToolbar.java
@@ -83,8 +83,8 @@ } @Override - protected void onDataChanged(int numItems) { - super.onDataChanged(numItems); + public void setSearchEnabled(boolean searchEnabled) { + super.setSearchEnabled(searchEnabled); updateInfoMenuItem( mManager.shouldShowInfoButton(), mManager.shouldShowInfoHeaderIfAvailable()); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index d033685..b1c2ff6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -1070,7 +1070,10 @@ mNavigationButton.setImageDrawable(page); break; case NavigationButtonType.MAGNIFIER: - mNavigationButton.setImageResource(R.drawable.ic_omnibox_magnifier); + Drawable search = TintedDrawable.constructTintedDrawable(getContext(), + R.drawable.omnibox_search, + mUseDarkColors ? R.color.dark_mode_tint : R.color.light_mode_tint); + mNavigationButton.setImageDrawable(search); break; case NavigationButtonType.EMPTY: mNavigationButton.setImageDrawable(null);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java index ec0b914..171aac8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
@@ -277,11 +277,6 @@ } } - @Override - public boolean useModernDesign() { - return false; - } - /** * @param button The {@link View} of the button to show. * @return An animator to run for the given view when showing buttons in the unfocused location
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadDirectoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadDirectoryAdapter.java index e029caff..2f42e70 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadDirectoryAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadDirectoryAdapter.java
@@ -15,12 +15,12 @@ import android.widget.ArrayAdapter; import android.widget.TextView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.DirectoryOption; import org.chromium.chrome.browser.download.DownloadDirectoryProvider; import org.chromium.chrome.browser.download.DownloadUtils; import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.widget.TintedImageView; +import org.chromium.chrome.download.R; import java.util.ArrayList; import java.util.List;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadLocationPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadLocationPreference.java index 9e78c8a..26fa5ab 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadLocationPreference.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadLocationPreference.java
@@ -14,8 +14,8 @@ import android.view.View; import android.widget.ListView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.DirectoryOption; +import org.chromium.chrome.download.R; /** * The preference used to save the download directory in download settings page.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadLocationPreferenceAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadLocationPreferenceAdapter.java index 4ae0130..a4e42be 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadLocationPreferenceAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadLocationPreferenceAdapter.java
@@ -15,10 +15,10 @@ import android.widget.TextView; import org.chromium.base.metrics.RecordHistogram; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.DirectoryOption; import org.chromium.chrome.browser.download.DownloadUtils; import org.chromium.chrome.browser.preferences.PrefServiceBridge; +import org.chromium.chrome.download.R; /** * Class used to provide data shown in the download location preference in download settings page.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java index 0e5d3ed..7645bdb0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java
@@ -28,7 +28,7 @@ * Default value for referrer URL. * It must be kept in sync with //components/ntp_suggestions/features.cc */ - private static final String DEFAULT_REFERRER_URL = "https://feed.google.com/"; + private static final String DEFAULT_REFERRER_URL = "https://discover.google.com/"; private SuggestionsConfig() {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 3c7cbdd..b143b63 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -63,6 +63,7 @@ import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; import org.chromium.chrome.browser.omnibox.LocationBar; +import org.chromium.chrome.browser.omnibox.QueryInOmnibox; import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener; import org.chromium.chrome.browser.partnercustomizations.HomepageManager; import org.chromium.chrome.browser.partnercustomizations.HomepageManager.HomepageStateListener; @@ -353,10 +354,10 @@ mTabObserver = new EmptyTabObserver() { @Override public void onSSLStateUpdated(Tab tab) { - setModelShouldIgnoreSecurityLevelForSearchTerms(false); if (mToolbarModel.getTab() == null) return; assert tab == mToolbarModel.getTab(); + QueryInOmnibox.setIgnoreSecurityLevelForSearchTerms(tab.getProfile(), false); mLocationBar.updateSecurityIcon(); mLocationBar.setUrlToPageUrl(); } @@ -392,12 +393,12 @@ @Override public void onPageLoadStarted(Tab tab, String url) { - mToolbarModel.setIgnoreSecurityLevelForSearchTerms(true); + QueryInOmnibox.setIgnoreSecurityLevelForSearchTerms(tab.getProfile(), true); } @Override public void onPageLoadFinished(Tab tab) { - mToolbarModel.setIgnoreSecurityLevelForSearchTerms(false); + QueryInOmnibox.setIgnoreSecurityLevelForSearchTerms(tab.getProfile(), false); if (tab.isShowingErrorPage()) { handleIPHForErrorPageShown(tab); return; @@ -409,7 +410,7 @@ @Override public void onLoadStarted(Tab tab, boolean toDifferentDocument) { if (!toDifferentDocument) return; - mToolbarModel.setIgnoreSecurityLevelForSearchTerms(true); + QueryInOmnibox.setIgnoreSecurityLevelForSearchTerms(tab.getProfile(), true); updateButtonStatus(); updateTabLoadingState(true); } @@ -417,7 +418,7 @@ @Override public void onLoadStopped(Tab tab, boolean toDifferentDocument) { if (!toDifferentDocument) return; - mToolbarModel.setIgnoreSecurityLevelForSearchTerms(false); + QueryInOmnibox.setIgnoreSecurityLevelForSearchTerms(tab.getProfile(), false); updateTabLoadingState(true); // If we made some progress, fast-forward to complete, otherwise just dismiss any @@ -1688,23 +1689,6 @@ == Configuration.KEYBOARD_QWERTY; } - /** - * Notifies the toolbar model that it should ignore the security level when determining whether - * or not to display search terms in the URL bar. This is useful for the interim period between - * loading a new page and getting proper security info, to avoid having the full URL flicker - * before displaying search terms. - * - * @param shouldIgnore Whether or not the toolbar model should ignore the security level. - */ - private void setModelShouldIgnoreSecurityLevelForSearchTerms(boolean shouldIgnore) { - assert mToolbar != null; - boolean wasShowingSearchTerms = mToolbarModel.shouldDisplaySearchTerms(); - mToolbarModel.setIgnoreSecurityLevelForSearchTerms(shouldIgnore); - if (wasShowingSearchTerms != mToolbarModel.shouldDisplaySearchTerms()) { - mLocationBar.setUrlToPageUrl(); - } - } - private static class LoadProgressSimulator { private static final int MSG_ID_UPDATE_PROGRESS = 1;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java index b4340f48..67dbe30 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java
@@ -15,6 +15,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeTabbedActivity; @@ -24,12 +25,11 @@ import org.chromium.chrome.browser.native_page.NativePageFactory; import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.offlinepages.OfflinePageUtils; -import org.chromium.chrome.browser.omnibox.AutocompleteController; import org.chromium.chrome.browser.omnibox.OmniboxUrlEmphasizer; +import org.chromium.chrome.browser.omnibox.QueryInOmnibox; import org.chromium.chrome.browser.omnibox.UrlBarData; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.search_engines.TemplateUrlService; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.chrome.browser.util.FeatureUtilities; @@ -38,6 +38,7 @@ import org.chromium.components.dom_distiller.core.DomDistillerService; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; import org.chromium.components.security_state.ConnectionSecurityLevel; +import org.chromium.content_public.browser.BrowserStartupController; import org.chromium.content_public.browser.WebContents; import java.net.URI; @@ -59,8 +60,6 @@ private boolean mIsIncognito; private int mPrimaryColor; private boolean mIsUsingBrandColor; - /** Query in Omnibox cached values to avoid unnecessary expensive calls. */ - private boolean mQueryInOmniboxEnabled; private String mPreviousUrl; @ConnectionSecurityLevel private int mPreviousSecurityLevel; @@ -91,7 +90,6 @@ */ public void initializeWithNative() { mNativeToolbarModelAndroid = nativeInit(); - mQueryInOmniboxEnabled = ChromeFeatureList.isEnabled(ChromeFeatureList.QUERY_IN_OMNIBOX); mIsNativeLibraryReady = true; } @@ -201,9 +199,10 @@ return buildUrlBarData(url, formattedUrl); } - if (shouldDisplaySearchTerms()) { + String searchTerms = getDisplaySearchTerms(); + if (searchTerms != null) { // Show the search terms in the omnibox instead of the URL if this is a DSE search URL. - return buildUrlBarData(url, getDisplaySearchTerms()); + return buildUrlBarData(url, searchTerms); } if (ChromeFeatureList.isEnabled( @@ -448,87 +447,27 @@ @Override public boolean shouldDisplaySearchTerms() { - if (!securityLevelSafeForQueryInOmnibox() && !mIgnoreSecurityLevelForSearchTerms) { - return false; - } - if (!mQueryInOmniboxEnabled) return false; - if (mTab != null && !(mTab.getActivity() instanceof ChromeTabbedActivity)) return false; - if (TextUtils.isEmpty(getDisplaySearchTerms())) return false; - return true; - } - - private boolean securityLevelSafeForQueryInOmnibox() { - int securityLevel = getSecurityLevel(); - return securityLevel == ConnectionSecurityLevel.SECURE - || securityLevel == ConnectionSecurityLevel.EV_SECURE; + return getDisplaySearchTerms() != null; } /** - * Extracts query terms from the current URL if it's a SRP URL from the default search engine, - * caching the result of the more expensive call to {@link #getDisplaySearchTermsInternal}. + * If the current tab state is eligible for displaying the search query terms instead of the + * URL, this extracts the query terms from the current URL. See {@link QueryInOmnibox}. * - * @return The search terms. Returns null if not a DSE SRP URL or there are no search terms to - * extract, if query in omnibox is disabled, or if the security level is insufficient to - * display search terms in place of SRP URL. This will also return nothing if the search - * terms look too much like a URL, since we don't want to display URL look-a-likes with - * "Query in Omnibox" to avoid confusion. + * @return The search terms. Returns null if the tab is ineligible to display the search terms + * instead of the URL. */ private String getDisplaySearchTerms() { - String url = getCurrentUrl(); - if (url == null) { - mCachedSearchTerms = null; - } else { - @ConnectionSecurityLevel - int securityLevel = getSecurityLevel(); - if (!url.equals(mPreviousUrl) || securityLevel != mPreviousSecurityLevel) { - mCachedSearchTerms = getDisplaySearchTermsInternal(url); - mPreviousUrl = url; - mPreviousSecurityLevel = securityLevel; - } + if (mTab != null && !(mTab.getActivity() instanceof ChromeTabbedActivity)) return null; + + // We can't fetch the Profile while the browser is still starting. + if (!BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER) + .isStartupSuccessfullyCompleted()) { + return null; } - return mCachedSearchTerms; - } - /** - * Extracts query terms from a URL if it's a SRP URL from the default search engine, returning - * the cached result of the previous call if this call is being performed for the same URL and - * security level as last time. - * - * @param url The URL to extract search terms from. - * @return The search terms. Returns null if not a DSE SRP URL or there are no search terms to - * extract, if query in omnibox is disabled, or if the security level is insufficient to - * display search terms in place of SRP URL. - */ - private String getDisplaySearchTermsInternal(String url) { - TemplateUrlService templateUrlService = TemplateUrlService.getInstance(); - if (!templateUrlService.isSearchResultsPageFromDefaultSearchProvider(url)) return null; - - String searchTerms = templateUrlService.extractSearchTermsFromUrl(url); - // Avoid showing search terms that would be interpreted as a URL if typed into the - // omnibox. - return looksLikeUrl(searchTerms) ? null : searchTerms; - } - - /** - * Checks if the provided {@link String} look like a URL. - * - * @param input The {@link String} to check. - * @return Whether or not the {@link String} appeared to be a URL. - */ - private boolean looksLikeUrl(String input) { - return !TextUtils.isEmpty(input) - && !TextUtils.isEmpty(AutocompleteController.nativeQualifyPartialURLQuery(input)); - } - - /** - * Sets a flag telling the model to ignore the security level in its check for whether to - * display search terms or not. This is useful for avoiding the flicker that occurs when loading - * a SRP URL before our SSL state updates. - * - * @param ignore Whether or not we should ignore the security level. - */ - protected void setIgnoreSecurityLevelForSearchTerms(boolean ignore) { - mIgnoreSecurityLevelForSearchTerms = ignore; + return QueryInOmnibox.getDisplaySearchTerms( + getProfile(), getSecurityLevel(), getCurrentUrl()); } /** @return The formatted URL suitable for editing. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java index d616e12..ddf89d9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java
@@ -17,7 +17,6 @@ import android.view.View.OnClickListener; import android.widget.ImageButton; -import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.StrictModeContext; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; @@ -31,6 +30,7 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.util.AccessibilityUtil; +import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.widget.TintedImageButton; import org.chromium.ui.base.DeviceFormFactor; @@ -42,7 +42,6 @@ * The Toolbar object for Tablet screens. */ @SuppressLint("Instantiatable") - public class ToolbarTablet extends ToolbarLayout implements OnClickListener, View.OnLongClickListener { // The number of toolbar buttons that can be hidden at small widths (reload, back, forward). @@ -378,11 +377,9 @@ super.onTabOrModelChanged(); boolean incognito = isIncognito(); if (mUseLightColorAssets == null || mUseLightColorAssets != incognito) { - int colorResource = - incognito ? R.color.incognito_primary_color : R.color.default_primary_color; - setBackgroundResource(colorResource); - getProgressBar().setThemeColor( - ApiCompatibilityUtils.getColor(getResources(), colorResource), isIncognito()); + int color = ColorUtils.getDefaultThemeColor(getResources(), true, isIncognito()); + setBackgroundColor(color); + getProgressBar().setThemeColor(color, isIncognito()); getMenuButton().setTint(incognito ? mLightModeTint : mDarkModeTint); mHomeButton.setTint(incognito ? mLightModeTint : mDarkModeTint);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java index e6c761b4..47e148e3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
@@ -83,7 +83,7 @@ // long as the adapter data changes, we show the recycler view, and hide loading view. mLoadingView.hideLoadingUI(); - mToolbar.onDataChanged(mAdapter.getItemCount()); + mToolbar.setSearchEnabled(mAdapter.getItemCount() != 0); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java index f676a6f5a..975cf9c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
@@ -92,15 +92,15 @@ protected boolean mIsSelectionEnabled; protected SelectionDelegate<E> mSelectionDelegate; - protected boolean mIsSearching; + private boolean mIsSearching; private boolean mHasSearchView; private LinearLayout mSearchView; private EditText mSearchText; private EditText mSearchEditText; private TintedImageButton mClearTextButton; private SearchDelegate mSearchDelegate; - private boolean mSelectableListHasItems; + private boolean mSearchEnabled; private boolean mIsVrEnabled; private boolean mUpdateStatusBarColor; @@ -478,12 +478,12 @@ } /** - * Called when the data in the selectable list this toolbar is associated with changes. - * @param numItems The number of items in the selectable list. + * Called to enable/disable search menu button. + * @param searchEnabled Whether the search button should be enabled. */ - protected void onDataChanged(int numItems) { + public void setSearchEnabled(boolean searchEnabled) { if (mHasSearchView) { - mSelectableListHasItems = numItems != 0; + mSearchEnabled = searchEnabled; updateSearchMenuItem(); } } @@ -646,8 +646,8 @@ if (!mHasSearchView) return; MenuItem searchMenuItem = getMenu().findItem(mSearchMenuItemId); if (searchMenuItem != null) { - searchMenuItem.setVisible(mSelectableListHasItems && !mIsSelectionEnabled - && !mIsSearching && !mIsVrEnabled); + searchMenuItem.setVisible( + mSearchEnabled && !mIsSelectionEnabled && !mIsSearching && !mIsVrEnabled); } }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 718619c..3c2e083 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -456,6 +456,7 @@ "java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java", "java/src/org/chromium/chrome/browser/download/home/OfflineItemSource.java", "java/src/org/chromium/chrome/browser/download/home/PrefetchStatusProvider.java", + "java/src/org/chromium/chrome/browser/download/home/UmaUtils.java", "java/src/org/chromium/chrome/browser/download/home/empty/EmptyCoordinator.java", "java/src/org/chromium/chrome/browser/download/home/empty/EmptyProperties.java", "java/src/org/chromium/chrome/browser/download/home/empty/EmptyView.java", @@ -515,6 +516,7 @@ "java/src/org/chromium/chrome/browser/download/home/storage/StorageCoordinator.java", "java/src/org/chromium/chrome/browser/download/home/storage/StorageSummaryProvider.java", "java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java", + "java/src/org/chromium/chrome/browser/download/home/toolbar/ToolbarCoordinator.java", "java/src/org/chromium/chrome/browser/download/home/view/LoadingBackground.java", "java/src/org/chromium/chrome/browser/download/home/view/SelectionView.java", "java/src/org/chromium/chrome/browser/download/items/DownloadBlockedOfflineContentProvider.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadActivityTest.java index d0538aaa..a7ee7aa6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadActivityTest.java
@@ -140,8 +140,8 @@ mAdapter = mUi.getDownloadHistoryAdapterForTests(); mAdapter.registerAdapterDataObserver(mAdapterObserver); - mSpaceUsedDisplay = - (TextView) mActivityTestRule.getActivity().findViewById(R.id.size_downloaded); + mSpaceUsedDisplay = (TextView) mActivityTestRule.getActivity().findViewById( + org.chromium.chrome.download.R.id.size_downloaded); mRecyclerView = ((RecyclerView) mActivityTestRule.getActivity().findViewById(R.id.recycler_view)); @@ -650,8 +650,8 @@ mActivityTestRule.getActivity() .findViewById(R.id.selection_mode_number) .getVisibility()); - Assert.assertNull( - mActivityTestRule.getActivity().findViewById(R.id.selection_mode_share_menu_id)); + Assert.assertNull(mActivityTestRule.getActivity().findViewById( + org.chromium.chrome.download.R.id.selection_mode_share_menu_id)); Assert.assertNull( mActivityTestRule.getActivity().findViewById(R.id.selection_mode_delete_menu_id)); Assert.assertFalse(mStubbedProvider.getSelectionDelegate().isSelectionEnabled()); @@ -667,7 +667,8 @@ .getVisibility()); Assert.assertEquals(View.VISIBLE, mActivityTestRule.getActivity() - .findViewById(R.id.selection_mode_share_menu_id) + .findViewById( + org.chromium.chrome.download.R.id.selection_mode_share_menu_id) .getVisibility()); Assert.assertEquals(View.VISIBLE, mActivityTestRule.getActivity() @@ -686,8 +687,8 @@ mActivityTestRule.getActivity() .findViewById(R.id.selection_mode_number) .getVisibility()); - Assert.assertNull( - mActivityTestRule.getActivity().findViewById(R.id.selection_mode_share_menu_id)); + Assert.assertNull(mActivityTestRule.getActivity().findViewById( + org.chromium.chrome.download.R.id.selection_mode_share_menu_id)); Assert.assertNull( mActivityTestRule.getActivity().findViewById(R.id.selection_mode_delete_menu_id)); Assert.assertFalse(mStubbedProvider.getSelectionDelegate().isSelectionEnabled());
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index d4b0ea5..77e7afc6 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -4358,7 +4358,7 @@ Restart computer </message> <message name="IDS_SETTINGS_RESET_CLEANUP_TITLE_DONE" desc="Message confirming that Chrome has removed harmful software. Exclamation point is nice in EN-US but is optional in your language; please use or omit as appropriate. The UI will also display a checkmark icon to indicate the operation is done. "> - Done! Harmful software removed. To turn extensions back on, visit <a href="chrome://extensions">Extensions.</a> + Done! Harmful software removed. To turn extensions back on, visit <a href="chrome://extensions">Extensions</a>. </message> <message name="IDS_SETTINGS_RESET_CLEANUP_TITLE_ERROR_CANT_REMOVE" desc="An error message, appearing on the Chrome Cleanup web page, that Chrome tried to clean up unwanted software, as requested by the user, but was unsuccessful. Omits subject, i.e. Chrome can't remove harmful software."> Cleanup failed
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index e563d062..e349a159 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -631,8 +631,6 @@ "loader/chrome_navigation_data.h", "loader/chrome_resource_dispatcher_host_delegate.cc", "loader/chrome_resource_dispatcher_host_delegate.h", - "loader/predictor_resource_throttle.cc", - "loader/predictor_resource_throttle.h", "mac/bluetooth_utility.h", "mac/bluetooth_utility.mm", "mac/dock.h", @@ -819,10 +817,6 @@ "net/nqe/ui_network_quality_estimator_service_factory.h", "net/prediction_options.cc", "net/prediction_options.h", - "net/predictor.cc", - "net/predictor.h", - "net/predictor_tab_helper.cc", - "net/predictor_tab_helper.h", "net/probe_message.cc", "net/probe_message.h", "net/profile_network_context_service.cc", @@ -849,10 +843,6 @@ "net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h", "net/system_network_context_manager.cc", "net/system_network_context_manager.h", - "net/timed_cache.cc", - "net/timed_cache.h", - "net/url_info.cc", - "net/url_info.h", "net_benchmarking.cc", "net_benchmarking.h", "notifications/alert_dispatcher_mac.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 8c89c82..3491fd8 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3469,9 +3469,6 @@ #endif // !defined(OS_ANDROID) #if defined(OS_MACOSX) - {"mac-touchbar", flag_descriptions::kMacTouchBarName, - flag_descriptions::kMacTouchBarDescription, kOsMac, - FEATURE_VALUE_TYPE(features::kBrowserTouchBar)}, {"dialog-touchbar", flag_descriptions::kDialogTouchBarName, flag_descriptions::kDialogTouchBarDescription, kOsMac, FEATURE_VALUE_TYPE(features::kDialogTouchBar)},
diff --git a/chrome/browser/android/compositor/layer/tab_handle_layer.cc b/chrome/browser/android/compositor/layer/tab_handle_layer.cc index ffa4a6c7..d4dcff1 100644 --- a/chrome/browser/android/compositor/layer/tab_handle_layer.cc +++ b/chrome/browser/android/compositor/layer/tab_handle_layer.cc
@@ -37,8 +37,7 @@ float close_button_alpha, bool is_loading, float spinner_rotation, - float brightness, - float border_opacity) { + float brightness) { if (brightness != brightness_ || foreground != foreground_) { brightness_ = brightness; foreground_ = foreground; @@ -51,19 +50,8 @@ float original_x = x; float original_y = y; if (foreground_) { - if (!border_->parent()) { - layer_->InsertChild(border_, 0); - border_->SetIsDrawable(true); - } - border_->SetBackgroundColor(SK_ColorBLACK); - border_->SetPosition(gfx::PointF(0, height - 1)); - border_->SetBounds(gfx::Size(toolbar_width, 1)); - border_->SetOpacity(border_opacity); - x = 0; y = 0; - } else if (border_->parent()) { - border_->RemoveFromParent(); } bool is_rtl = l10n_util::IsLayoutRtl(); @@ -97,8 +85,6 @@ if (title_layer) { title_layer->setOpacity(1.0f); unsigned expected_children = 3; - if (foreground_) - expected_children += 1; title_layer_ = title_layer->layer(); if (layer_->children().size() < expected_children) { layer_->AddChild(title_layer_); @@ -180,7 +166,6 @@ layer_(cc::Layer::Create()), close_button_(cc::UIResourceLayer::Create()), decoration_tab_(cc::NinePatchLayer::Create()), - border_(cc::SolidColorLayer::Create()), brightness_(1.0f), foreground_(false) { decoration_tab_->SetIsDrawable(true);
diff --git a/chrome/browser/android/compositor/layer/tab_handle_layer.h b/chrome/browser/android/compositor/layer/tab_handle_layer.h index 04f21f1..b2fd819f 100644 --- a/chrome/browser/android/compositor/layer/tab_handle_layer.h +++ b/chrome/browser/android/compositor/layer/tab_handle_layer.h
@@ -46,8 +46,7 @@ float close_button_alpha, bool is_loading, float spinner_rotation, - float brightness, - float border_opacity); + float brightness); scoped_refptr<cc::Layer> layer() override; protected: @@ -60,7 +59,6 @@ scoped_refptr<cc::Layer> layer_; scoped_refptr<cc::UIResourceLayer> close_button_; scoped_refptr<cc::NinePatchLayer> decoration_tab_; - scoped_refptr<cc::SolidColorLayer> border_; scoped_refptr<cc::Layer> title_layer_; float brightness_;
diff --git a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc index 43de354..1fc0d6a 100644 --- a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc
@@ -282,7 +282,6 @@ jfloat close_button_alpha, jboolean is_loading, jfloat spinner_rotation, - jfloat border_opacity, const JavaParamRef<jobject>& jlayer_title_cache, const JavaParamRef<jobject>& jresource_manager) { LayerTitleCache* layer_title_cache = @@ -298,8 +297,7 @@ layer->SetProperties(id, close_button_resource, tab_handle_resource, foreground, close_pressed, toolbar_width, x, y, width, height, content_offset_x, close_button_alpha, is_loading, - spinner_rotation, background_tab_brightness_, - border_opacity); + spinner_rotation, background_tab_brightness_); } scoped_refptr<TabHandleLayer> TabStripSceneLayer::GetNextLayer(
diff --git a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h index ae813ee..6562baa 100644 --- a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h +++ b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h
@@ -107,7 +107,6 @@ jfloat close_button_alpha, jboolean is_loading, jfloat spinner_rotation, - jfloat border_opacity, const base::android::JavaParamRef<jobject>& jlayer_title_cache, const base::android::JavaParamRef<jobject>& jresource_manager);
diff --git a/chrome/browser/android/feed/feed_host_service_factory.cc b/chrome/browser/android/feed/feed_host_service_factory.cc index 13c7fc4..b33b7813 100644 --- a/chrome/browser/android/feed/feed_host_service_factory.cc +++ b/chrome/browser/android/feed/feed_host_service_factory.cc
@@ -8,6 +8,7 @@ #include <string> #include <utility> +#include "base/bind.h" #include "base/files/file_path.h" #include "base/time/default_clock.h" #include "chrome/browser/browser_process.h" @@ -103,8 +104,15 @@ offline_pages::OfflinePageModelFactory::GetForBrowserContext(profile); offline_pages::PrefetchService* prefetch_service = offline_pages::PrefetchServiceFactory::GetForBrowserContext(profile); + // Using base::Unretained is safe because the FeedSchedulerHost ensures the + // |scheduler_host| will outlive the |offline_host|, and calls to + // |the scheduler_host| are never posted to a message loop. auto offline_host = std::make_unique<FeedOfflineHost>( - offline_page_model, prefetch_service, scheduler_host.get()); + offline_page_model, prefetch_service, + base::BindRepeating(&FeedSchedulerHost::OnSuggestionConsumed, + base::Unretained(scheduler_host.get())), + base::BindRepeating(&FeedSchedulerHost::OnSuggestionsShown, + base::Unretained(scheduler_host.get()))); return new FeedHostService( std::move(image_manager), std::move(networking_host),
diff --git a/chrome/browser/android/profiles/profile_manager_utils.cc b/chrome/browser/android/profiles/profile_manager_utils.cc index 64b26e7f..41d280d2 100644 --- a/chrome/browser/android/profiles/profile_manager_utils.cc +++ b/chrome/browser/android/profiles/profile_manager_utils.cc
@@ -6,7 +6,6 @@ #include "base/android/jni_android.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "components/prefs/pref_service.h" @@ -31,7 +30,6 @@ // These calls are asynchronous. They may not finish (and may not even // start!) before the Android OS kills our process. But we can't wait for them // to finish because blocking the UI thread is illegal. - profile->GetNetworkPredictor()->SaveStateForNextStartup(); profile->GetPrefs()->CommitPendingWrite(); content::BrowserContext::GetDefaultStoragePartition(profile) ->GetCookieManagerForBrowserProcess()
diff --git a/chrome/browser/android/warmup_manager.cc b/chrome/browser/android/warmup_manager.cc index a91b5885..0fc7ce7 100644 --- a/chrome/browser/android/warmup_manager.cc +++ b/chrome/browser/android/warmup_manager.cc
@@ -4,7 +4,6 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/predictors/loading_predictor.h" #include "chrome/browser/predictors/loading_predictor_factory.h" #include "chrome/browser/profiles/profile.h" @@ -41,8 +40,6 @@ if (loading_predictor) { loading_predictor->PrepareForPageLoad(url, predictors::HintOrigin::EXTERNAL); - } else if (profile->GetNetworkPredictor()) { - profile->GetNetworkPredictor()->PreconnectUrlAndSubresources(url, GURL()); } } }
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index ce275295..b8426d17 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm
@@ -409,11 +409,9 @@ // If the OSX version supports this method, the system will automatically // hide the item if there's no touch bar. However, for unsupported versions, - // we'll have to manually remove the item from the menu. The item also has - // to be removed if the feature is disabled. + // we'll have to manually remove the item from the menu. if (![NSApp - respondsToSelector:@selector(toggleTouchBarCustomizationPalette:)] || - !base::FeatureList::IsEnabled(features::kBrowserTouchBar)) { + respondsToSelector:@selector(toggleTouchBarCustomizationPalette:)]) { NSMenu* mainMenu = [NSApp mainMenu]; NSMenu* viewMenu = [[mainMenu itemWithTag:IDC_VIEW_MENU] submenu]; NSMenuItem* customizeItem = [viewMenu itemWithTag:IDC_CUSTOMIZE_TOUCH_BAR];
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc index e64f7ad..239a1831 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -42,7 +42,6 @@ #include "chrome/browser/media/webrtc/webrtc_event_log_manager.h" #include "chrome/browser/net/nqe/ui_network_quality_estimator_service.h" #include "chrome/browser/net/nqe/ui_network_quality_estimator_service_factory.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/browser/ntp_snippets/content_suggestions_service_factory.h" @@ -212,14 +211,6 @@ } #endif -void ClearNetworkPredictorOnIOThread(chrome_browser_net::Predictor* predictor) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(predictor); - - predictor->DiscardInitialNavigationHistory(); - predictor->DiscardAllResults(); -} - #if defined(OS_ANDROID) void ClearPrecacheInBackground(content::BrowserContext* browser_context) { // Precache code was removed in M61 but the sqlite database file could be @@ -457,16 +448,6 @@ ->ClearHostCache(filter_builder.BuildNetworkServiceFilter(), CreatePendingTaskCompletionClosureForMojo()); - if (profile_->GetNetworkPredictor()) { - // TODO(dmurph): Support all backends with filter (crbug.com/113621). - BrowserThread::PostTaskAndReply( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&ClearNetworkPredictorOnIOThread, - profile_->GetNetworkPredictor()), - CreatePendingTaskCompletionClosure()); - profile_->GetNetworkPredictor()->ClearPrefsOnUIThread(); - } - // As part of history deletion we also delete the auto-generated keywords. TemplateURLService* keywords_model = TemplateURLServiceFactory::GetForProfile(profile_);
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 223472f..ec30cd0d 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -58,7 +58,6 @@ #include "chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.h" #include "chrome/browser/nacl_host/nacl_browser_delegate_impl.h" #include "chrome/browser/navigation_predictor/navigation_predictor.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/net_benchmarking.h" #include "chrome/browser/notifications/platform_notification_service_impl.h" @@ -3495,12 +3494,10 @@ Profile::FromBrowserContext(render_process_host->GetBrowserContext()); auto* loading_predictor = predictors::LoadingPredictorFactory::GetForProfile(profile); - auto* predictor = profile->GetNetworkPredictor(); registry->AddInterface( base::BindRepeating( &NetBenchmarking::Create, loading_predictor ? loading_predictor->GetWeakPtr() : nullptr, - predictor ? predictor->GetUIWeakPtr() : nullptr, render_process_host->GetID()), ui_task_runner); }
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc index 8c539999..080d3cee5 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc
@@ -293,7 +293,7 @@ watcher_callbacks_.erase(iter); auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD( - arc_bridge_service_->file_system(), AddWatcher); + arc_bridge_service_->file_system(), RemoveWatcher); if (!file_system_instance) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), false));
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc index 963aced4..517d6335 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager.cc +++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -1328,19 +1328,33 @@ // Wait for the Tremplin signal if the vm isn't already marked "running". auto key = std::make_pair(owner_id, vm_name); if (running_vms_.find(key) == running_vms_.end()) { - // Record the running vm. - running_vms_[key] = std::move(response.vm_info()); - VLOG(1) << "Awaiting TremplinStartedSignal for " << owner_id << ", " << vm_name; + + // Record the container start and run the callback after the VM starts. tremplin_started_callbacks_.emplace( - key, - base::BindOnce(std::move(callback), ConciergeClientResult::SUCCESS)); + key, base::BindOnce(&CrostiniManager::OnStartTremplin, + weak_ptr_factory_.GetWeakPtr(), key, + std::move(response.vm_info()), std::move(callback), + ConciergeClientResult::SUCCESS)); return; } std::move(callback).Run(ConciergeClientResult::SUCCESS); } +void CrostiniManager::OnStartTremplin(std::pair<std::string, std::string> key, + vm_tools::concierge::VmInfo vm_info, + StartTerminaVmCallback callback, + ConciergeClientResult result) { + // Record the running vm. + VLOG(1) << "Received TremplinStartedSignal, VM: " << key.first << ", " + << key.second; + running_vms_[key] = std::move(vm_info); + + // Run the original callback. + std::move(callback).Run(result); +} + void CrostiniManager::OnStopVm( std::string owner_id, std::string vm_name,
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.h b/chrome/browser/chromeos/crostini/crostini_manager.h index c7e2242..93ac231 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager.h +++ b/chrome/browser/chromeos/crostini/crostini_manager.h
@@ -404,13 +404,22 @@ base::Optional<vm_tools::concierge::ListVmDisksResponse> reply); // Callback for ConciergeClient::StartTerminaVm. Called after the Concierge - // service method finishes. + // service method finishes. |callback| is called if the container has already + // been started, otherwise it is passed to OnStartTremplin. void OnStartTerminaVm( std::string owner_id, std::string vm_name, StartTerminaVmCallback callback, base::Optional<vm_tools::concierge::StartVmResponse> reply); + // Callback for ConciergeClient::TremplinStartedSignal. Called after the + // Tremplin service starts. Updates running containers list and then calls the + // |callback|. + void OnStartTremplin(std::pair<std::string, std::string> key, + vm_tools::concierge::VmInfo vm_info, + StartTerminaVmCallback callback, + ConciergeClientResult result); + // Callback for ConciergeClient::StopVm. Called after the Concierge // service method finishes. void OnStopVm(std::string owner_id,
diff --git a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc index 9242e7d..3b758c1 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc +++ b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/chromeos/crostini/crostini_manager.h" +#include <memory> #include "base/base64.h" #include "base/bind.h" #include "base/memory/ptr_util.h" @@ -91,6 +92,14 @@ std::move(closure).Run(); } + void OnStartTremplinRecordsRunningVmCallback(base::OnceClosure closure, + ConciergeClientResult result) { + // Check that running_vms_ contains the running vm. + EXPECT_TRUE( + CrostiniManager::GetInstance()->IsVmRunning(profile(), kVmName)); + std::move(closure).Run(); + } + void StopVmSuccessCallback(base::OnceClosure closure, ConciergeClientResult result) { EXPECT_TRUE(fake_concierge_client_->stop_vm_called()); @@ -300,6 +309,23 @@ run_loop()->Run(); } +TEST_F(CrostiniManagerTest, OnStartTremplinRecordsRunningVm) { + const base::FilePath& disk_path = base::FilePath(kVmName); + const std::string owner_id = CryptohomeIdForProfile(profile()); + + // Start the Vm. + CrostiniManager::GetInstance()->StartTerminaVm( + owner_id, kVmName, disk_path, + base::BindOnce( + &CrostiniManagerTest::OnStartTremplinRecordsRunningVmCallback, + base::Unretained(this), run_loop()->QuitClosure())); + + // Check that the Vm start is not recorded (without tremplin start). + EXPECT_FALSE(CrostiniManager::GetInstance()->IsVmRunning(profile(), kVmName)); + + run_loop()->Run(); +} + TEST_F(CrostiniManagerTest, StopVmNameError) { CrostiniManager::GetInstance()->StopVm( profile(), "",
diff --git a/chrome/browser/chromeos/external_metrics.cc b/chrome/browser/chromeos/external_metrics.cc index 7326b8b8..ea571dcd 100644 --- a/chrome/browser/chromeos/external_metrics.cc +++ b/chrome/browser/chromeos/external_metrics.cc
@@ -12,12 +12,15 @@ #include <vector> #include "base/bind.h" +#include "base/command_line.h" #include "base/metrics/histogram.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/statistics_recorder.h" #include "base/metrics/user_metrics.h" +#include "base/strings/string_number_conversions.h" #include "base/task/post_task.h" #include "chrome/browser/metrics/chromeos_metrics_provider.h" +#include "chromeos/chromeos_switches.h" #include "components/metrics/serialization/metric_sample.h" #include "components/metrics/serialization/serialization_utils.h" #include "content/public/browser/browser_thread.h" @@ -46,14 +49,30 @@ return CheckValues(name, 1, maximum, maximum + 1); } -// The interval between external metrics collections. -constexpr base::TimeDelta kExternalMetricsCollectionInterval = - base::TimeDelta::FromSeconds(30); +// The file from which externally-reported metrics are read. constexpr char kEventsFilePath[] = "/var/lib/metrics/uma-events"; +// Default interval between externally-reported metrics being collected. +constexpr base::TimeDelta kDefaultCollectionInterval = + base::TimeDelta::FromSeconds(30); + } // namespace -ExternalMetrics::ExternalMetrics() : uma_events_file_(kEventsFilePath) { +ExternalMetrics::ExternalMetrics() + : uma_events_file_(kEventsFilePath), + collection_interval_(kDefaultCollectionInterval) { + const std::string flag_value = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kExternalMetricsCollectionInterval); + if (!flag_value.empty()) { + int seconds = -1; + if (base::StringToInt(flag_value, &seconds) && seconds > 0) { + collection_interval_ = base::TimeDelta::FromSeconds(seconds); + } else { + LOG(WARNING) << "Ignoring bad value \"" << flag_value << "\" in --" + << switches::kExternalMetricsCollectionInterval; + } + } } ExternalMetrics::~ExternalMetrics() {} @@ -161,7 +180,7 @@ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, base::BindOnce(&chromeos::ExternalMetrics::CollectEventsAndReschedule, this), - kExternalMetricsCollectionInterval); + collection_interval_); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/external_metrics.h b/chrome/browser/chromeos/external_metrics.h index 61684f7..d7f0285 100644 --- a/chrome/browser/chromeos/external_metrics.h +++ b/chrome/browser/chromeos/external_metrics.h
@@ -11,6 +11,7 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/time/time.h" namespace metrics { class MetricSample; @@ -42,8 +43,9 @@ friend class base::RefCountedThreadSafe<ExternalMetrics>; friend class ExternalMetricsTest; - FRIEND_TEST_ALL_PREFIXES(ExternalMetricsTest, CanReceiveHistogram); + FRIEND_TEST_ALL_PREFIXES(ExternalMetricsTest, CustomInterval); FRIEND_TEST_ALL_PREFIXES(ExternalMetricsTest, HandleMissingFile); + FRIEND_TEST_ALL_PREFIXES(ExternalMetricsTest, CanReceiveHistogram); FRIEND_TEST_ALL_PREFIXES(ExternalMetricsTest, IncorrectHistogramsAreDiscarded); @@ -89,6 +91,9 @@ // File used by libmetrics to send metrics to Chrome. std::string uma_events_file_; + // Interval between metrics being read from |uma_events_file_|. + base::TimeDelta collection_interval_; + DISALLOW_COPY_AND_ASSIGN(ExternalMetrics); };
diff --git a/chrome/browser/chromeos/external_metrics_unittest.cc b/chrome/browser/chromeos/external_metrics_unittest.cc index 965252b..adc8b45 100644 --- a/chrome/browser/chromeos/external_metrics_unittest.cc +++ b/chrome/browser/chromeos/external_metrics_unittest.cc
@@ -6,10 +6,12 @@ #include <memory> +#include "base/command_line.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/metrics/statistics_recorder.h" #include "base/test/metrics/histogram_tester.h" +#include "chromeos/chromeos_switches.h" #include "components/metrics/serialization/metric_sample.h" #include "components/metrics/serialization/serialization_utils.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -19,7 +21,10 @@ class ExternalMetricsTest : public testing::Test { public: - void SetUp() override { + ExternalMetricsTest() = default; + ~ExternalMetricsTest() override = default; + + void Init() { ASSERT_TRUE(dir_.CreateUniqueTempDir()); external_metrics_ = ExternalMetrics::CreateForTesting( dir_.GetPath().Append("testfile").value()); @@ -30,7 +35,17 @@ content::TestBrowserThreadBundle thread_bundle_; }; +TEST_F(ExternalMetricsTest, CustomInterval) { + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kExternalMetricsCollectionInterval, "5"); + Init(); + + EXPECT_EQ(base::TimeDelta::FromSeconds(5), + external_metrics_->collection_interval_); +} + TEST_F(ExternalMetricsTest, HandleMissingFile) { + Init(); ASSERT_TRUE(base::DeleteFile( base::FilePath(external_metrics_->uma_events_file_), false)); @@ -38,6 +53,7 @@ } TEST_F(ExternalMetricsTest, CanReceiveHistogram) { + Init(); base::HistogramTester histogram_tester; std::unique_ptr<metrics::MetricSample> hist = @@ -52,6 +68,7 @@ } TEST_F(ExternalMetricsTest, IncorrectHistogramsAreDiscarded) { + Init(); base::HistogramTester histogram_tester; // Malformed histogram (min > max).
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.cc b/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.cc index 698d543..0ac01b3a 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.cc
@@ -4,21 +4,25 @@ #include "chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.h" -#include <memory> -#include <string> #include <utility> #include "base/bind.h" #include "base/files/file_util.h" #include "base/json/json_reader.h" #include "base/location.h" +#include "base/logging.h" #include "base/optional.h" #include "base/task/post_task.h" #include "base/task/task_traits.h" #include "base/values.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/extensions/external_cache_impl.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/extensions/external_provider_impl.h" +#include "extensions/browser/extension_file_task_runner.h" +#include "extensions/common/extension_urls.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" namespace chromeos { @@ -67,19 +71,57 @@ return demo_session && demo_session->started(); } -DemoExtensionsExternalLoader::DemoExtensionsExternalLoader() - : weak_ptr_factory_(this) { +DemoExtensionsExternalLoader::DemoExtensionsExternalLoader( + const base::FilePath& cache_dir) + : cache_dir_(cache_dir), weak_ptr_factory_(this) { DCHECK(DemoSession::Get() && DemoSession::Get()->started()); } DemoExtensionsExternalLoader::~DemoExtensionsExternalLoader() = default; +void DemoExtensionsExternalLoader::LoadApp(const std::string& app_id) { + base::DictionaryValue prefs; + base::DictionaryValue app_dict; + app_dict.SetKey(extensions::ExternalProviderImpl::kExternalUpdateUrl, + base::Value(extension_urls::kChromeWebstoreUpdateURL)); + prefs.SetKey(app_id, std::move(app_dict)); + + if (!external_cache_) { + external_cache_ = std::make_unique<ExternalCacheImpl>( + cache_dir_, g_browser_process->shared_url_loader_factory(), + extensions::GetExtensionFileTaskRunner(), this, + true /* always_check_updates */, + false /* wait_for_cache_initialization */); + } + external_cache_->UpdateExtensionsList(base::DictionaryValue::From( + base::Value::ToUniquePtrValue(std::move(prefs)))); +} + void DemoExtensionsExternalLoader::StartLoading() { DemoSession::Get()->EnsureOfflineResourcesLoaded(base::BindOnce( &DemoExtensionsExternalLoader::StartLoadingFromOfflineDemoResources, weak_ptr_factory_.GetWeakPtr())); } +void DemoExtensionsExternalLoader::OnExtensionListsUpdated( + const base::DictionaryValue* prefs) { + DCHECK(external_cache_); + // Notifies the provider that the extensions have either been downloaded or + // found in cache, and are ready to be installed. + LoadFinished(prefs->CreateDeepCopy()); +} + +void DemoExtensionsExternalLoader::OnExtensionLoadedInCache( + const std::string& id) {} + +void DemoExtensionsExternalLoader::OnExtensionDownloadFailed( + const std::string& id) {} + +std::string DemoExtensionsExternalLoader::GetInstalledExtensionVersion( + const std::string& id) { + return std::string(); +} + void DemoExtensionsExternalLoader::StartLoadingFromOfflineDemoResources() { DemoSession* demo_session = DemoSession::Get(); DCHECK(demo_session->offline_resources_loaded());
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.h b/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.h index 671b5cf..2fe8d53 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.h +++ b/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.h
@@ -5,9 +5,14 @@ #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_EXTENSIONS_EXTERNAL_LOADER_H_ #define CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_EXTENSIONS_EXTERNAL_LOADER_H_ +#include <memory> +#include <string> + +#include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" +#include "chrome/browser/chromeos/extensions/external_cache_delegate.h" #include "chrome/browser/extensions/external_loader.h" class Profile; @@ -18,6 +23,8 @@ namespace chromeos { +class ExternalCache; + // External loader for extensions to be loaded into demo mode sessions. The CRX // files are loaded from preinstalled demo mode resources image mounted by // image loader service (from the device's stateful partition). @@ -26,17 +33,27 @@ // mounted demo resources root to absolute paths that can be used by external // extensions provider. // NOTE: The class is expected to be used on the UI thread exclusively. -class DemoExtensionsExternalLoader : public extensions::ExternalLoader { +class DemoExtensionsExternalLoader : public extensions::ExternalLoader, + public ExternalCacheDelegate { public: // Whether demo apps should be loaded for the profile - i.e. whether the // profile is the primary profile in a demo session. static bool SupportedForProfile(Profile* profile); - DemoExtensionsExternalLoader(); + explicit DemoExtensionsExternalLoader(const base::FilePath& cache_dir); + + // Loads the app with |app_id| and installs it from the update url or cache. + void LoadApp(const std::string& app_id); // extensions::ExternalLoader: void StartLoading() override; + // ExternalCacheDelegate: + void OnExtensionListsUpdated(const base::DictionaryValue* prefs) override; + void OnExtensionLoadedInCache(const std::string& id) override; + void OnExtensionDownloadFailed(const std::string& id) override; + std::string GetInstalledExtensionVersion(const std::string& id) override; + protected: ~DemoExtensionsExternalLoader() override; @@ -50,6 +67,10 @@ // |prefs| - demo extensions prefs. void DemoExternalExtensionsPrefsLoaded(base::Optional<base::Value> prefs); + std::unique_ptr<ExternalCache> external_cache_; + + const base::FilePath cache_dir_; + base::WeakPtrFactory<DemoExtensionsExternalLoader> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(DemoExtensionsExternalLoader);
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader_unittest.cc b/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader_unittest.cc index 3d4554e0..0bbce2e6 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader_unittest.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader_unittest.cc
@@ -18,22 +18,30 @@ #include "base/json/json_writer.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/path_service.h" #include "base/run_loop.h" #include "base/values.h" #include "base/version.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" #include "chrome/browser/extensions/external_provider_impl.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_image_loader_client.h" #include "components/session_manager/core/session_manager.h" #include "components/user_manager/scoped_user_manager.h" +#include "content/public/browser/notification_service.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "content/public/test/test_utils.h" #include "extensions/browser/external_install_info.h" #include "extensions/browser/external_provider_interface.h" +#include "extensions/browser/notification_types.h" #include "extensions/common/extension.h" #include "extensions/common/manifest.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" #include "testing/gtest/include/gtest/gtest.h" namespace chromeos { @@ -43,6 +51,13 @@ // Information about found external extension file: {version, crx_path}. using TestCrxInfo = std::tuple<std::string, std::string>; +constexpr char kTestExtensionId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; + +constexpr char kTestExtensionUpdateManifest[] = + "extensions/good_v1_update_manifest.xml"; + +constexpr char kTestExtensionCRXVersion[] = "1.0.0.0"; + class TestExternalProviderVisitor : public extensions::ExternalProviderInterface::VisitorInterface { public: @@ -61,6 +76,16 @@ ready_waiter_.reset(); } + void WaitForFileFound() { + if (!loaded_crx_files_.empty()) + return; + file_waiter_ = std::make_unique<base::RunLoop>(); + file_waiter_->Run(); + file_waiter_.reset(); + } + + void ClearLoadedFiles() { loaded_crx_files_.clear(); } + // extensions::ExternalProviderInterface::VisitorInterface: bool OnExternalExtensionFileFound( const extensions::ExternalInstallInfoFile& info) override { @@ -71,14 +96,15 @@ loaded_crx_files_.emplace( info.extension_id, TestCrxInfo(info.version.GetString(), info.path.value())); + if (file_waiter_) + file_waiter_->Quit(); return true; } bool OnExternalExtensionUpdateUrlFound( const extensions::ExternalInstallInfoUpdateUrl& info, bool is_initial_load) override { - ADD_FAILURE() << "Found extensions with update URL"; - return false; + return true; } void OnExternalProviderReady( @@ -99,10 +125,13 @@ private: bool ready_ = false; + std::map<std::string, TestCrxInfo> loaded_crx_files_; std::unique_ptr<base::RunLoop> ready_waiter_; + std::unique_ptr<base::RunLoop> file_waiter_; + DISALLOW_COPY_AND_ASSIGN(TestExternalProviderVisitor); }; @@ -110,7 +139,11 @@ class DemoExtensionsExternalLoaderTest : public testing::Test { public: - DemoExtensionsExternalLoaderTest() = default; + DemoExtensionsExternalLoaderTest() + : test_shared_loader_factory_( + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + &test_url_loader_factory_)) {} + ~DemoExtensionsExternalLoaderTest() override = default; void SetUp() override { @@ -123,6 +156,9 @@ DBusThreadManager::GetSetterForTesting()->SetImageLoaderClient( std::move(image_loader_client)); session_manager_ = std::make_unique<session_manager::SessionManager>(); + + TestingBrowserProcess::GetGlobal()->SetSharedURLLoaderFactory( + test_shared_loader_factory_); } void TearDown() override { @@ -193,7 +229,9 @@ std::unique_ptr<extensions::ExternalProviderImpl> CreateExternalProvider( extensions::ExternalProviderInterface::VisitorInterface* visitor) { return std::make_unique<extensions::ExternalProviderImpl>( - visitor, base::MakeRefCounted<DemoExtensionsExternalLoader>(), + visitor, + base::MakeRefCounted<DemoExtensionsExternalLoader>( + base::FilePath() /*cache_dir*/), profile_.get(), extensions::Manifest::INTERNAL, extensions::Manifest::INTERNAL, extensions::Extension::FROM_WEBSTORE | @@ -203,11 +241,13 @@ protected: TestExternalProviderVisitor external_provider_visitor_; + std::unique_ptr<TestingProfile> profile_; + + network::TestURLLoaderFactory test_url_loader_factory_; + private: content::TestBrowserThreadBundle thread_bundle_; - std::unique_ptr<TestingProfile> profile_; - // Image loader client injected into, and owned by DBusThreadManager. FakeImageLoaderClient* image_loader_client_ = nullptr; @@ -215,6 +255,11 @@ std::unique_ptr<session_manager::SessionManager> session_manager_; + scoped_refptr<network::WeakWrapperSharedURLLoaderFactory> + test_shared_loader_factory_; + + content::InProcessUtilityThreadHelper in_process_utility_thread_helper_; + DISALLOW_COPY_AND_ASSIGN(DemoExtensionsExternalLoaderTest); }; @@ -439,6 +484,75 @@ EXPECT_TRUE(external_provider_visitor_.loaded_crx_files().empty()); } +TEST_F(DemoExtensionsExternalLoaderTest, LoadApp) { + InitializeSession(true /*mount_demo_resources*/, + true /*wait_for_offline_resources_load*/); + + // Create a temporary cache directory. + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + base::FilePath cache_dir = temp_dir.GetPath().Append("cache"); + ASSERT_TRUE(base::CreateDirectoryAndGetError(cache_dir, nullptr /*error*/)); + + scoped_refptr<chromeos::DemoExtensionsExternalLoader> loader = + base::MakeRefCounted<chromeos::DemoExtensionsExternalLoader>(cache_dir); + std::unique_ptr<extensions::ExternalProviderImpl> external_provider = + std::make_unique<extensions::ExternalProviderImpl>( + &external_provider_visitor_, loader, profile_.get(), + extensions::Manifest::INTERNAL, + extensions::Manifest::EXTERNAL_PREF_DOWNLOAD, + extensions::Extension::FROM_WEBSTORE | + extensions::Extension::WAS_INSTALLED_BY_DEFAULT); + + external_provider->VisitRegisteredExtension(); + external_provider_visitor_.WaitForReady(); + EXPECT_TRUE(external_provider->IsReady()); + + loader->LoadApp(kTestExtensionId); + // Verify that a downloader has started and is attempting to download an + // update manifest. + EXPECT_EQ(1, test_url_loader_factory_.NumPending()); + // Return a manifest to the downloader. + std::string manifest; + base::FilePath test_dir; + ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); + EXPECT_TRUE(base::ReadFileToString( + test_dir.Append(kTestExtensionUpdateManifest), &manifest)); + EXPECT_EQ(1u, test_url_loader_factory_.pending_requests()->size()); + test_url_loader_factory_.AddResponse( + test_url_loader_factory_.pending_requests()->at(0).request.url.spec(), + manifest); + + // Wait for the manifest to be parsed. + content::WindowedNotificationObserver( + extensions::NOTIFICATION_EXTENSION_UPDATE_FOUND, + content::NotificationService::AllSources()) + .Wait(); + + // Verify that the downloader is attempting to download a CRX file. + EXPECT_EQ(1u, test_url_loader_factory_.pending_requests()->size()); + // Trigger downloading of the CRX file. + test_url_loader_factory_.AddResponse( + test_url_loader_factory_.pending_requests()->at(0).request.url.spec(), + "Dummy content."); + + // Verify that the CRX file exists in the cache directory. + external_provider_visitor_.WaitForFileFound(); + const base::FilePath cached_crx_path = cache_dir.Append(base::StringPrintf( + "%s-%s.crx", kTestExtensionId, kTestExtensionCRXVersion)); + const std::map<std::string, TestCrxInfo> expected_info = { + {kTestExtensionId, + TestCrxInfo(kTestExtensionCRXVersion, cached_crx_path.value())}}; + EXPECT_EQ(expected_info, external_provider_visitor_.loaded_crx_files()); + + // Verify that loading the app again succeeds without downloading. + test_url_loader_factory_.ClearResponses(); + external_provider_visitor_.ClearLoadedFiles(); + loader->LoadApp(kTestExtensionId); + external_provider_visitor_.WaitForFileFound(); + EXPECT_EQ(expected_info, external_provider_visitor_.loaded_crx_files()); +} + class ShouldCreateDemoExtensionsExternalLoaderTest : public testing::Test { public: ShouldCreateDemoExtensionsExternalLoaderTest() {
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session.cc b/chrome/browser/chromeos/login/demo_mode/demo_session.cc index ca35aa6f..88cf9182f 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_session.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_session.cc
@@ -13,6 +13,7 @@ #include "base/files/file_util.h" #include "base/optional.h" #include "base/path_service.h" +#include "base/sys_info.h" #include "base/task/post_task.h" #include "chrome/browser/apps/platform_apps/app_load_service.h" #include "chrome/browser/browser_process.h" @@ -22,7 +23,10 @@ #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/settings/install_attributes.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/extensions/app_launch_params.h" +#include "chrome/browser/ui/extensions/application_launch.h" #include "chrome/common/chrome_paths.h" +#include "chrome/common/extensions/extension_constants.h" #include "chrome/common/pref_names.h" #include "chromeos/chromeos_paths.h" #include "chromeos/dbus/dbus_thread_manager.h" @@ -30,6 +34,7 @@ #include "components/prefs/pref_service.h" #include "components/session_manager/core/session_manager.h" #include "content/public/browser/browser_thread.h" +#include "extensions/browser/extension_registry.h" #include "extensions/common/constants.h" #include "net/base/network_change_notifier.h" @@ -62,6 +67,10 @@ // contains sample photos. constexpr char kPhotosPath[] = "media/photos"; +constexpr char kDefaultHighlightsAppId[] = "lpmakjfjcconjeehbidjclhdlpjmfjjj"; + +constexpr char kEveHighlightsAppId[] = "iggildboghmjpbjcpmobahnkmoefkike"; + bool IsDemoModeOfflineEnrolled() { DCHECK(DemoSession::IsDeviceInDemoMode()); return DemoSession::GetDemoConfig() == DemoSession::DemoModeConfig::kOffline; @@ -96,6 +105,19 @@ LOG(ERROR) << "Failed to install demo mode media."; } +std::string GetBoardName() { + const std::vector<std::string> board = + base::SplitString(base::SysInfo::GetLsbReleaseBoard(), "-", + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + return board[0]; +} + +std::string GetHighlightsAppId() { + if (GetBoardName() == "eve") + return kEveHighlightsAppId; + return kDefaultHighlightsAppId; +} + } // namespace // static @@ -303,6 +325,7 @@ : offline_enrolled_(IsDemoModeOfflineEnrolled()), ignore_pin_policy_offline_apps_(GetIgnorePinPolicyApps()), session_manager_observer_(this), + extension_registry_observer_(this), weak_ptr_factory_(this) { session_manager_observer_.Add(session_manager::SessionManager::Get()); OnSessionStateChanged(); @@ -351,6 +374,7 @@ DCHECK(offline_resources_loaded_); if (offline_resources_path_.empty()) { LOG(ERROR) << "Offline resources not loaded - no highlights app available."; + InstallHighlightsAppFromUpdateUrl(); return; } Profile* profile = ProfileManager::GetPrimaryUserProfile(); @@ -360,10 +384,20 @@ if (!apps::AppLoadService::Get(profile)->LoadAndLaunch( resources_path, base::CommandLine(base::CommandLine::NO_PROGRAM), base::FilePath() /* cur_dir */)) { - LOG(WARNING) << "Failed to launch highlights app!"; + LOG(WARNING) << "Failed to launch highlights app from offline resources."; + InstallHighlightsAppFromUpdateUrl(); } } +void DemoSession::InstallHighlightsAppFromUpdateUrl() { + if (!extensions_external_loader_) + return; + Profile* profile = ProfileManager::GetPrimaryUserProfile(); + DCHECK(profile); + extension_registry_observer_.Add(extensions::ExtensionRegistry::Get(profile)); + extensions_external_loader_->LoadApp(GetHighlightsAppId()); +} + void DemoSession::OnSessionStateChanged() { if (session_manager::SessionManager::Get()->session_state() != session_manager::SessionState::ACTIVE || @@ -374,4 +408,16 @@ &DemoSession::InstallDemoResources, weak_ptr_factory_.GetWeakPtr())); } +void DemoSession::OnExtensionInstalled(content::BrowserContext* browser_context, + const extensions::Extension* extension, + bool is_update) { + if (extension->id() != GetHighlightsAppId()) + return; + Profile* profile = ProfileManager::GetPrimaryUserProfile(); + DCHECK(profile); + OpenApplication(AppLaunchParams( + profile, extension, extensions::LAUNCH_CONTAINER_WINDOW, + WindowOpenDisposition::NEW_WINDOW, extensions::SOURCE_CHROME_INTERNAL)); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session.h b/chrome/browser/chromeos/login/demo_mode/demo_session.h index 7b8b249..894e8de 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_session.h +++ b/chrome/browser/chromeos/login/demo_mode/demo_session.h
@@ -12,11 +12,14 @@ #include "base/callback_forward.h" #include "base/files/file_path.h" #include "base/macros.h" +#include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/scoped_observer.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.h" #include "chrome/browser/component_updater/cros_component_installer_chromeos.h" #include "components/session_manager/core/session_manager_observer.h" +#include "extensions/browser/extension_registry_observer.h" namespace session_manager { class SessionManager; @@ -26,7 +29,8 @@ // Tracks global demo session state. For example, whether the demo session has // started, and whether the demo session offline resources have been loaded. -class DemoSession : public session_manager::SessionManagerObserver { +class DemoSession : public session_manager::SessionManagerObserver, + extensions::ExtensionRegistryObserver { public: // Type of demo mode configuration. // Warning: DemoModeConfig is stored in local state. Existing entries should @@ -119,6 +123,11 @@ bool offline_resources_loaded() const { return offline_resources_loaded_; } + void set_extensions_external_loader( + scoped_refptr<DemoExtensionsExternalLoader> extensions_external_loader) { + extensions_external_loader_ = extensions_external_loader; + } + private: DemoSession(); ~DemoSession() override; @@ -139,12 +148,22 @@ // as apps and media. void InstallDemoResources(); - // Loads and launches the highlights app. + // Loads the highlights app from offline resources and launches it upon + // success. void LoadAndLaunchHighlightsApp(); + // Installs the CRX file from an update URL. Observes |ExtensionRegistry| to + // launch the highlights app upon installation. + void InstallHighlightsAppFromUpdateUrl(); + // session_manager::SessionManagerObserver: void OnSessionStateChanged() override; + // extensions::ExtensionRegistryObserver: + void OnExtensionInstalled(content::BrowserContext* browser_context, + const extensions::Extension* extension, + bool is_update) override; + // Whether the device was offline-enrolled into demo mode, i.e. enrolled using // pre-built policies. Offline enrolled demo sessions do not have working // robot account associated with them. @@ -169,6 +188,12 @@ session_manager::SessionManagerObserver> session_manager_observer_; + ScopedObserver<extensions::ExtensionRegistry, + extensions::ExtensionRegistryObserver> + extension_registry_observer_; + + scoped_refptr<DemoExtensionsExternalLoader> extensions_external_loader_; + base::WeakPtrFactory<DemoSession> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(DemoSession);
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.cc index 8da23936..19efd54 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.cc
@@ -73,6 +73,17 @@ // Other error codes are treated as failures. if (return_code == cryptohome::MOUNT_ERROR_NONE || return_code == cryptohome::MOUNT_ERROR_KEY_FAILURE) { + // Prior to the introduction of the |unlock_key| field, only one + // EasyUnlockDeviceKeyData was peristed, and implicitly assumed to be the + // unlock key. Now, multiple EasyUnlockDeviceKeyData objects are + // persisted, and this deserializing logic cannot assume that a given + // object is the unlock key. To handle the case of migrating from the old + // paradigm of a single persisted EasyUnlockDeviceKeyData, the + // |unlock_key| field is defaulted to true if only a single device entry + // exists, in order to correctly mark that old entry as the unlock key. + if (devices_.size() == 1) + devices_[0].unlock_key = true; + callback_.Run(true, devices_); return; }
diff --git a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc new file mode 100644 index 0000000..0478e8f --- /dev/null +++ b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
@@ -0,0 +1,296 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "base/macros.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/login/screens/gaia_view.h" +#include "chrome/browser/chromeos/login/screens/sync_consent_screen.h" +#include "chrome/browser/chromeos/login/screens/update_screen.h" +#include "chrome/browser/chromeos/login/test/js_checker.h" +#include "chrome/browser/chromeos/login/test/oobe_base_test.h" +#include "chrome/browser/chromeos/login/ui/login_display_host.h" +#include "chrome/browser/chromeos/login/wizard_controller.h" +#include "chrome/browser/lifetime/application_lifetime.h" +#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" +#include "chromeos/dbus/update_engine_client.h" +#include "content/public/browser/notification_service.h" + +namespace chromeos { +namespace { +constexpr base::TimeDelta kJsConditionCheckFrequency = + base::TimeDelta::FromMilliseconds(2000); +} // namespace + +// Waits for js condition to be fulfilled. +class JsConditionWaiter { + public: + JsConditionWaiter(const test::JSChecker& js_checker, + const std::string& js_condition) + : js_checker_(js_checker), js_condition_(js_condition) {} + + ~JsConditionWaiter() = default; + + void Wait() { + if (IsConditionFulfilled()) + return; + + timer_.Start(FROM_HERE, kJsConditionCheckFrequency, this, + &JsConditionWaiter::CheckCondition); + run_loop_.Run(); + } + + private: + bool IsConditionFulfilled() { return js_checker_.GetBool(js_condition_); } + + void CheckCondition() { + if (IsConditionFulfilled()) { + run_loop_.Quit(); + timer_.Stop(); + } + } + + test::JSChecker js_checker_; + const std::string js_condition_; + + base::RepeatingTimer timer_; + base::RunLoop run_loop_; + + DISALLOW_COPY_AND_ASSIGN(JsConditionWaiter); +}; + +class OobeInteractiveUITest : public OobeBaseTest { + public: + OobeInteractiveUITest() = default; + ~OobeInteractiveUITest() override = default; + + void TearDownOnMainThread() override { + // If the login display is still showing, exit gracefully. + if (LoginDisplayHost::default_host()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&chrome::AttemptExit)); + RunUntilBrowserProcessQuits(); + } + + OobeBaseTest::TearDownOnMainThread(); + } + + void WaitForLoginDisplayHostShutdown() { + if (!LoginDisplayHost::default_host()) + return; + + base::RunLoop runloop; + LOG(INFO) + << "OobeInteractiveUITest: Waiting for LoginDisplayHost to shut down."; + while (LoginDisplayHost::default_host()) { + runloop.RunUntilIdle(); + } + LOG(INFO) << "OobeInteractiveUITest: LoginDisplayHost is down."; + } + + void WaitForOobeWelcomeScreen() { + content::WindowedNotificationObserver observer( + chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, + content::NotificationService::AllSources()); + observer.Wait(); + + JsConditionWaiter(js_checker_, + "Oobe.getInstance().currentScreen.id == 'connect'") + .Wait(); + } + + void RunWelcomeScreenChecks() { +#if defined(GOOGLE_CHROME_BUILD) + constexpr int kNumberOfVideosPlaying = 1; +#else + constexpr int kNumberOfVideosPlaying = 0; +#endif + + js_checker_.ExpectFalse("$('oobe-welcome-md').$.welcomeScreen.hidden"); + js_checker_.ExpectTrue("$('oobe-welcome-md').$.accessibilityScreen.hidden"); + js_checker_.ExpectTrue("$('oobe-welcome-md').$.languageScreen.hidden"); + js_checker_.ExpectTrue("$('oobe-welcome-md').$.timezoneScreen.hidden"); + + js_checker_.ExpectEQ( + "(() => {let cnt = 0; for (let v of " + "$('oobe-welcome-md').$.welcomeScreen.root.querySelectorAll('video')) " + "{ cnt += v.paused ? 0 : 1; }; return cnt; })()", + kNumberOfVideosPlaying); + } + + void TapWelcomeNext() { + js_checker_.Evaluate( + "$('oobe-welcome-md').$.welcomeScreen.$.welcomeNextButton.click()"); + } + + void WaitForNetworkSelectionScreen() { + JsConditionWaiter( + js_checker_, + "Oobe.getInstance().currentScreen.id == 'network-selection'") + .Wait(); + LOG(INFO) + << "OobeInteractiveUITest: Switched to 'network-selection' screen."; + } + + void RunNetworkSelectionScreenChecks() { + js_checker_.ExpectTrue( + "!$('oobe-network-md').$.networkDialog.querySelector('oobe-next-button'" + ").disabled"); + } + + void TapNetworkSelectionNext() { + js_checker_.Evaluate( + "$('oobe-network-md').$.networkDialog.querySelector('oobe-next-button')" + ".click()"); + } + + void WaitForEulaScreen() { + JsConditionWaiter(js_checker_, + "Oobe.getInstance().currentScreen.id == 'eula'") + .Wait(); + LOG(INFO) << "OobeInteractiveUITest: Switched to 'eula' screen."; + } + + void RunEulaScreenChecks() { + // Wait for actual EULA to appear. + JsConditionWaiter(js_checker_, "!$('oobe-eula-md').$.eulaDialog.hidden") + .Wait(); + js_checker_.ExpectTrue("!$('oobe-eula-md').$.acceptButton.disabled"); + } + + void TapEulaAccept() { + js_checker_.Evaluate("$('oobe-eula-md').$.acceptButton.click();"); + } + + void WaitForUpdateScreen() { + JsConditionWaiter(js_checker_, + "Oobe.getInstance().currentScreen.id == 'update'") + .Wait(); + + LOG(INFO) << "OobeInteractiveUITest: Switched to 'update' screen."; + } + + void ExitUpdateScreenNoUpdate() { + UpdateScreen* screen = static_cast<UpdateScreen*>( + WizardController::default_controller()->GetScreen( + OobeScreen::SCREEN_OOBE_UPDATE)); + UpdateEngineClient::Status status; + status.status = UpdateEngineClient::UPDATE_STATUS_ERROR; + screen->UpdateStatusChanged(status); + } + + void WaitForGaiaSignInScreen() { + JsConditionWaiter(js_checker_, + "Oobe.getInstance().currentScreen.id == 'gaia-signin'") + .Wait(); + LOG(INFO) << "OobeInteractiveUITest: Switched to 'gaia-signin' screen."; + } + + void LogInAsRegularUser() { + LoginDisplayHost::default_host() + ->GetOobeUI() + ->GetGaiaScreenView() + ->ShowSigninScreenForTest(OobeBaseTest::kFakeUserEmail, + OobeBaseTest::kFakeUserPassword, + OobeBaseTest::kEmptyUserServices); + } + + void WaitForSyncConsentScreen() { + JsConditionWaiter(js_checker_, + "Oobe.getInstance().currentScreen.id == 'sync-consent'") + .Wait(); + + LOG(INFO) << "OobeInteractiveUITest: Logged in. Switched to 'sync-consent' " + "screen."; + } + + void ExitScreenSyncConsent() { + SyncConsentScreen* screen = static_cast<SyncConsentScreen*>( + WizardController::default_controller()->GetScreen( + OobeScreen::SCREEN_SYNC_CONSENT)); + + screen->SetProfileSyncDisabledByPolicyForTesting(true); + screen->OnStateChanged(nullptr); + } + + void WaitForMarketingOptInScreen() { + JsConditionWaiter( + js_checker_, + "Oobe.getInstance().currentScreen.id == 'marketing-opt-in'") + .Wait(); + LOG(INFO) + << "OobeInteractiveUITest: Switched to 'marketing-opt-in' screen."; + } + + void RunMarketingOptInScreenChecks() { + js_checker_.ExpectTrue("!$('marketing-opt-in').hidden"); + js_checker_.ExpectEQ( + "$('marketing-opt-in-impl').root.querySelectorAll('oobe-text-button')." + "length", + 1); + } + + void ExitMarketingOptInScreen() { + js_checker_.Evaluate( + "$('marketing-opt-in-impl').root.querySelectorAll('oobe-text-button')[" + "0].click()"); + JsConditionWaiter(js_checker_, + "Oobe.getInstance().currentScreen.id == 'user-image'") + .Wait(); + + LOG(INFO) << "OobeInteractiveUITest: Switched to 'user-image' screen."; + } + + void RunUserImageScreenChecks() { + js_checker_.ExpectTrue("!$('user-image').hidden"); + } + + void ExitUserImageScreen() { + js_checker_.Evaluate("$('user-image').querySelector('#ok-button').click()"); + + LOG(INFO) << "OobeInteractiveUITest: Exited 'user-image' screen."; + WaitForLoginDisplayHostShutdown(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(OobeInteractiveUITest); +}; + +IN_PROC_BROWSER_TEST_F(OobeInteractiveUITest, SimpleEndToEnd) { + WaitForOobeWelcomeScreen(); + RunWelcomeScreenChecks(); + TapWelcomeNext(); + + WaitForNetworkSelectionScreen(); + RunNetworkSelectionScreenChecks(); + TapNetworkSelectionNext(); + +#if defined(GOOGLE_CHROME_BUILD) + WaitForEulaScreen(); + RunEulaScreenChecks(); + TapEulaAccept(); +#endif + + WaitForUpdateScreen(); + ExitUpdateScreenNoUpdate(); + WaitForGaiaSignInScreen(); + + LogInAsRegularUser(); + +#if defined(GOOGLE_CHROME_BUILD) + WaitForSyncConsentScreen(); + ExitScreenSyncConsent(); +#endif + + WaitForMarketingOptInScreen(); + RunMarketingOptInScreenChecks(); + ExitMarketingOptInScreen(); + + RunUserImageScreenChecks(); + ExitUserImageScreen(); + + WaitForLoginDisplayHostShutdown(); +} + +} // namespace chromeos
diff --git a/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc b/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc index 155a2bb..c862c0f 100644 --- a/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc +++ b/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
@@ -8,6 +8,10 @@ #include <utility> #include "base/lazy_instance.h" +#include "base/metrics/histogram_base.h" +#include "base/metrics/histogram_samples.h" +#include "base/metrics/statistics_recorder.h" +#include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" #include "build/build_config.h" @@ -649,6 +653,43 @@ #endif } +AutotestPrivateGetHistogramFunction::~AutotestPrivateGetHistogramFunction() = + default; + +ExtensionFunction::ResponseAction AutotestPrivateGetHistogramFunction::Run() { + DVLOG(1) << "AutotestPrivateGetHistogramFunction"; + std::unique_ptr<api::autotest_private::GetHistogram::Params> params( + api::autotest_private::GetHistogram::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params); + + const base::HistogramBase* histogram = + base::StatisticsRecorder::FindHistogram(params->name); + if (!histogram) { + return RespondNow( + Error(base::StrCat({"Histogram ", params->name, " not found"}))); + } + + std::unique_ptr<base::HistogramSamples> samples = + histogram->SnapshotSamples(); + api::autotest_private::Histogram result; + + for (std::unique_ptr<base::SampleCountIterator> it = samples->Iterator(); + !it->Done(); it->Next()) { + base::HistogramBase::Sample min = 0; + int64_t max = 0; + base::HistogramBase::Count count = 0; + it->Get(&min, &max, &count); + + api::autotest_private::HistogramBucket bucket; + bucket.min = min; + bucket.max = max; + bucket.count = count; + result.buckets.push_back(std::move(bucket)); + } + + return RespondNow(OneArgument(result.ToValue())); +} + AutotestPrivateIsAppShownFunction::~AutotestPrivateIsAppShownFunction() = default;
diff --git a/chrome/browser/extensions/api/autotest_private/autotest_private_api.h b/chrome/browser/extensions/api/autotest_private/autotest_private_api.h index f087be3..01394d8 100644 --- a/chrome/browser/extensions/api/autotest_private/autotest_private_api.h +++ b/chrome/browser/extensions/api/autotest_private/autotest_private_api.h
@@ -231,6 +231,16 @@ ResponseAction Run() override; }; +class AutotestPrivateGetHistogramFunction : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("autotestPrivate.getHistogram", + AUTOTESTPRIVATE_GETHISTOGRAM) + + private: + ~AutotestPrivateGetHistogramFunction() override; + ResponseAction Run() override; +}; + class AutotestPrivateIsAppShownFunction : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("autotestPrivate.isAppShown", @@ -339,7 +349,7 @@ static const bool kServiceIsNULLWhileTesting = true; static const bool kServiceRedirectedInIncognito = true; - bool test_mode_; // true for ExtensionApiTest.AutotestPrivate browser test. + bool test_mode_; // true for AutotestPrivateApiTest.AutotestPrivate test. }; template <>
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_api.cc b/chrome/browser/extensions/api/content_settings/content_settings_api.cc index 85bbb99..8d5ccd7 100644 --- a/chrome/browser/extensions/api/content_settings/content_settings_api.cc +++ b/chrome/browser/extensions/api/content_settings/content_settings_api.cc
@@ -249,6 +249,18 @@ readable_type_name.c_str()))); } + size_t num_values = 0; + int histogram_value = + ContentSettingTypeToHistogramValue(content_type, &num_values); + if (primary_pattern != secondary_pattern && + secondary_pattern != ContentSettingsPattern::Wildcard()) { + UMA_HISTOGRAM_EXACT_LINEAR("ContentSettings.ExtensionEmbeddedSettingSet", + histogram_value, num_values); + } else { + UMA_HISTOGRAM_EXACT_LINEAR("ContentSettings.ExtensionNonEmbeddedSettingSet", + histogram_value, num_values); + } + if (primary_pattern != secondary_pattern && secondary_pattern != ContentSettingsPattern::Wildcard() && !info->website_settings_info()->SupportsEmbeddedExceptions() && @@ -288,18 +300,6 @@ return RespondNow(Error(pref_keys::kIncognitoSessionOnlyErrorMessage)); } - size_t num_values = 0; - int histogram_value = - ContentSettingTypeToHistogramValue(content_type, &num_values); - if (primary_pattern != secondary_pattern && - secondary_pattern != ContentSettingsPattern::Wildcard()) { - UMA_HISTOGRAM_EXACT_LINEAR("ContentSettings.ExtensionEmbeddedSettingSet", - histogram_value, num_values); - } else { - UMA_HISTOGRAM_EXACT_LINEAR("ContentSettings.ExtensionNonEmbeddedSettingSet", - histogram_value, num_values); - } - scoped_refptr<ContentSettingsStore> store = ContentSettingsService::Get(browser_context())->content_settings_store(); store->SetExtensionContentSetting(extension_id(), primary_pattern,
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc b/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc index 155603e..c304565 100644 --- a/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc +++ b/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
@@ -370,7 +370,7 @@ EXPECT_TRUE(RunExtensionSubtest(kExtensionPath, "test.html")) << message_; size_t num_values = 0; - int javascript_type = ContentSettingTypeToHistogramValue( + int images_type = ContentSettingTypeToHistogramValue( CONTENT_SETTINGS_TYPE_IMAGES, &num_values); int geolocation_type = ContentSettingTypeToHistogramValue( CONTENT_SETTINGS_TYPE_GEOLOCATION, &num_values); @@ -378,14 +378,14 @@ CONTENT_SETTINGS_TYPE_COOKIES, &num_values); histogram_tester.ExpectBucketCount( - "ContentSettings.ExtensionEmbeddedSettingSet", javascript_type, 1); + "ContentSettings.ExtensionEmbeddedSettingSet", images_type, 1); histogram_tester.ExpectBucketCount( "ContentSettings.ExtensionEmbeddedSettingSet", geolocation_type, 1); histogram_tester.ExpectTotalCount( "ContentSettings.ExtensionEmbeddedSettingSet", 2); histogram_tester.ExpectBucketCount( - "ContentSettings.ExtensionNonEmbeddedSettingSet", javascript_type, 1); + "ContentSettings.ExtensionNonEmbeddedSettingSet", images_type, 1); histogram_tester.ExpectBucketCount( "ContentSettings.ExtensionNonEmbeddedSettingSet", cookies_type, 1); histogram_tester.ExpectTotalCount(
diff --git a/chrome/browser/extensions/external_provider_impl.cc b/chrome/browser/extensions/external_provider_impl.cc index 9d16ef7..2ef26c9 100644 --- a/chrome/browser/extensions/external_provider_impl.cc +++ b/chrome/browser/extensions/external_provider_impl.cc
@@ -48,14 +48,17 @@ #include "ui/base/l10n/l10n_util.h" #if defined(OS_CHROMEOS) +#include "base/path_service.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_external_loader.h" #include "chrome/browser/chromeos/customization/customization_document.h" #include "chrome/browser/chromeos/extensions/device_local_account_external_policy_loader.h" #include "chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chromeos/chromeos_paths.h" #include "components/arc/arc_util.h" #else #include "chrome/browser/extensions/default_apps.h" @@ -693,14 +696,18 @@ // For Chrome OS demo sessions, add pre-installed demo extensions and apps. if (chromeos::DemoExtensionsExternalLoader::SupportedForProfile(profile)) { + base::FilePath cache_dir; + CHECK(base::PathService::Get(chromeos::DIR_DEVICE_EXTENSION_LOCAL_CACHE, + &cache_dir)); + scoped_refptr<chromeos::DemoExtensionsExternalLoader> loader = + base::MakeRefCounted<chromeos::DemoExtensionsExternalLoader>(cache_dir); std::unique_ptr<ExternalProviderImpl> demo_apps_provider = std::make_unique<ExternalProviderImpl>( - service, - base::MakeRefCounted<chromeos::DemoExtensionsExternalLoader>(), - profile, Manifest::EXTERNAL_PREF, Manifest::INVALID_LOCATION, - Extension::NO_FLAGS); + service, loader, profile, Manifest::EXTERNAL_PREF, + Manifest::EXTERNAL_PREF_DOWNLOAD, Extension::NO_FLAGS); demo_apps_provider->set_auto_acknowledge(true); demo_apps_provider->set_install_immediately(true); + chromeos::DemoSession::Get()->set_extensions_external_loader(loader); provider_list->push_back(std::move(demo_apps_provider)); }
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc index bd14c121..c0f4d4b5 100644 --- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc +++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/download/download_request_limiter.h" #include "chrome/browser/download/download_resource_throttle.h" #include "chrome/browser/loader/chrome_navigation_data.h" -#include "chrome/browser/loader/predictor_resource_throttle.h" #include "chrome/browser/loader/safe_browsing_resource_throttle.h" #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" #include "chrome/browser/plugins/plugin_prefs.h" @@ -510,11 +509,6 @@ std::make_unique<prerender::PrerenderResourceThrottle>(request)); } } - - std::unique_ptr<PredictorResourceThrottle> predictor_throttle = - PredictorResourceThrottle::MaybeCreate(request, io_data); - if (predictor_throttle) - throttles->push_back(std::move(predictor_throttle)); } bool ChromeResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream(
diff --git a/chrome/browser/loader/predictor_resource_throttle.cc b/chrome/browser/loader/predictor_resource_throttle.cc deleted file mode 100644 index 021e238..0000000 --- a/chrome/browser/loader/predictor_resource_throttle.cc +++ /dev/null
@@ -1,138 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/loader/predictor_resource_throttle.h" - -#include "base/memory/ptr_util.h" -#include "base/sequenced_task_runner.h" -#include "base/threading/sequenced_task_runner_handle.h" -#include "base/trace_event/trace_event.h" -#include "chrome/browser/net/predictor.h" -#include "chrome/browser/profiles/profile_io_data.h" -#include "content/public/browser/resource_request_info.h" -#include "content/public/common/resource_type.h" -#include "net/url_request/redirect_info.h" -#include "net/url_request/url_request.h" -#include "url/gurl.h" - -namespace { - -bool IsNavigationRequest(net::URLRequest* request) { - content::ResourceType resource_type = - content::ResourceRequestInfo::ForRequest(request)->GetResourceType(); - return resource_type == content::RESOURCE_TYPE_MAIN_FRAME || - resource_type == content::RESOURCE_TYPE_SUB_FRAME; -} - -} // namespace - -PredictorResourceThrottle::PredictorResourceThrottle( - net::URLRequest* request, - chrome_browser_net::Predictor* predictor) - : request_(request), predictor_(predictor), weak_factory_(this) {} - -PredictorResourceThrottle::~PredictorResourceThrottle() {} - -// static -std::unique_ptr<PredictorResourceThrottle> -PredictorResourceThrottle::MaybeCreate(net::URLRequest* request, - ProfileIOData* io_data) { - if (io_data->GetPredictor()) { - return base::WrapUnique( - new PredictorResourceThrottle(request, io_data->GetPredictor())); - } - return nullptr; -} - -void PredictorResourceThrottle::WillStartRequest(bool* defer) { - GURL request_scheme_host( - chrome_browser_net::Predictor::CanonicalizeUrl(request_->url())); - if (request_scheme_host.is_empty()) - return; - - // Learn what URLs are likely to be needed during next startup. - // TODO(csharrison): Rename this method, as this code path is used for more - // than just navigation requests. - predictor_->LearnAboutInitialNavigation(request_scheme_host); - - const content::ResourceRequestInfo* info = - content::ResourceRequestInfo::ForRequest(request_); - DCHECK(info); - content::ResourceType resource_type = info->GetResourceType(); - const GURL& referring_scheme_host = - GURL(request_->referrer()).GetWithEmptyPath(); - - // Learn about our referring URL, for use in the future. Only learn - // subresource relationships. - if (!referring_scheme_host.is_empty() && - resource_type != content::RESOURCE_TYPE_MAIN_FRAME && - predictor_->timed_cache()->WasRecentlySeen(referring_scheme_host)) { - predictor_->LearnFromNavigation(referring_scheme_host, request_scheme_host); - } - - // If the referring host is equal to the request host, then the predictor has - // already made any/all predictions when navigating to the referring host. - // Don't update the RecentlySeen() time because the timed cache is already - // populated (with the correct timeout) based on the initial navigation. - if (IsNavigationRequest(request_) && - referring_scheme_host != request_scheme_host) { - predictor_->timed_cache()->SetRecentlySeen(request_scheme_host); - DispatchPredictions(request_scheme_host, request_->site_for_cookies()); - } -} - -void PredictorResourceThrottle::WillRedirectRequest( - const net::RedirectInfo& redirect_info, - bool* defer) { - GURL new_scheme_host( - chrome_browser_net::Predictor::CanonicalizeUrl(redirect_info.new_url)); - GURL original_scheme_host(request_->original_url().GetWithEmptyPath()); - // Note: This is comparing a canonicalizd URL with a non-canonicalized URL. - // This should be fixed and the idea of canonicalization revisited. - if (new_scheme_host == original_scheme_host || new_scheme_host.is_empty()) - return; - // Don't learn or predict subresource redirects. - if (!IsNavigationRequest(request_)) - return; - - // Don't learn from redirects that take path as an argument, but do - // learn from short-hand typing entries, such as "cnn.com" redirects to - // "www.cnn.com". We can't just check for has_path(), as a mere "/" - // will count as a path, so we check that the path is at most a "/" - // (1 character long) to decide the redirect is "definitive" and has no - // significant path. - // TODO(jar): It may be ok to learn from all redirects, as the adaptive - // system will not respond until several identical redirects have taken - // place. Hence a use of a path (that changes) wouldn't really be - // learned from anyway. - if (request_->original_url().path().length() <= 1 && - predictor_->timed_cache()->WasRecentlySeen(original_scheme_host)) { - // TODO(jar): These definite redirects could be learned much faster. - predictor_->LearnFromNavigation(original_scheme_host, new_scheme_host); - } - - predictor_->timed_cache()->SetRecentlySeen(new_scheme_host); - DispatchPredictions(new_scheme_host, redirect_info.new_site_for_cookies); -} - -const char* PredictorResourceThrottle::GetNameForLogging() const { - return "PredictorResourceThrottle"; -} - -void PredictorResourceThrottle::DispatchPredictions( - const GURL& url, - const GURL& site_for_cookies) { - // Dispatch predictions asynchronously to avoid blocking the actual request - // from going out to the network. - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&PredictorResourceThrottle::DoPredict, - weak_factory_.GetWeakPtr(), url, site_for_cookies)); -} - -void PredictorResourceThrottle::DoPredict(const GURL& url, - const GURL& site_for_cookies) { - TRACE_EVENT0("loading", "PredictorResourceThrottle::DoPredict"); - predictor_->PredictFrameSubresources(url, site_for_cookies); -}
diff --git a/chrome/browser/loader/predictor_resource_throttle.h b/chrome/browser/loader/predictor_resource_throttle.h deleted file mode 100644 index 083b7eed..0000000 --- a/chrome/browser/loader/predictor_resource_throttle.h +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_LOADER_PREDICTOR_RESOURCE_THROTTLE_H_ -#define CHROME_BROWSER_LOADER_PREDICTOR_RESOURCE_THROTTLE_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "content/public/browser/resource_throttle.h" - -namespace chrome_browser_net { -class Predictor; -} - -namespace net { -struct RedirectInfo; -class URLRequest; -} - -class GURL; -class ProfileIOData; - -// This resource throttle tracks requests in order to help the predictor learn -// resource relationships. It notifies the predictor of redirect and referrer -// relationships, and populates the predictor's timed cache of ongoing -// navigations. It also initiates predictive actions based on navigation -// requests and redirects. -// Note: This class does not issue predictive actions off of the initial main -// frame request (before any redirects). That is done on the UI thread in -// response to navigation callbacks in predictor_tab_helper.cc. -// TODO(csharrison): This class shouldn't depend on chrome_browser_net. The -// predictor should probably be moved here (along with its dependencies). -class PredictorResourceThrottle : public content::ResourceThrottle { - public: - PredictorResourceThrottle(net::URLRequest* request, - chrome_browser_net::Predictor* predictor); - ~PredictorResourceThrottle() override; - - static std::unique_ptr<PredictorResourceThrottle> MaybeCreate( - net::URLRequest* request, - ProfileIOData* io_data); - - // content::ResourceThrottle: - void WillStartRequest(bool* defer) override; - void WillRedirectRequest(const net::RedirectInfo& redirect_info, - bool* defer) override; - const char* GetNameForLogging() const override; - - private: - void DispatchPredictions(const GURL& url, const GURL& site_for_cookies); - void DoPredict(const GURL& url, const GURL& site_for_cookies); - - net::URLRequest* request_; - chrome_browser_net::Predictor* predictor_; - - base::WeakPtrFactory<PredictorResourceThrottle> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(PredictorResourceThrottle); -}; - -#endif // CHROME_BROWSER_LOADER_PREDICTOR_RESOURCE_THROTTLE_H_
diff --git a/chrome/browser/media/media_engagement_contents_observer.cc b/chrome/browser/media/media_engagement_contents_observer.cc index a3929df..8837753 100644 --- a/chrome/browser/media/media_engagement_contents_observer.cc +++ b/chrome/browser/media/media_engagement_contents_observer.cc
@@ -529,6 +529,9 @@ } bool MediaEngagementContentsObserver::AreAudioContextConditionsMet() const { + if (!base::FeatureList::IsEnabled(media::kRecordWebAudioEngagement)) + return false; + if (audio_context_players_.empty()) return false;
diff --git a/chrome/browser/media/media_engagement_contents_observer_unittest.cc b/chrome/browser/media/media_engagement_contents_observer_unittest.cc index cafd83923..d3dd8c9 100644 --- a/chrome/browser/media/media_engagement_contents_observer_unittest.cc +++ b/chrome/browser/media/media_engagement_contents_observer_unittest.cc
@@ -28,6 +28,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/test_service_manager_context.h" #include "content/public/test/web_contents_tester.h" +#include "media/base/media_switches.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_source.h" #include "testing/gtest/include/gtest/gtest.h" @@ -39,9 +40,6 @@ : task_runner_(new base::TestMockTimeTaskRunner()) {} void SetUp() override { - scoped_feature_list_.InitFromCommandLine("RecordMediaEngagementScores", - std::string()); - ChromeRenderViewHostTestHarness::SetUp(); test_service_manager_context_ = @@ -449,8 +447,6 @@ std::unique_ptr<MediaEngagementService> service_; - base::test::ScopedFeatureList scoped_feature_list_; - ukm::TestAutoSetUkmRecorder test_ukm_recorder_; base::HistogramTester histogram_tester_; @@ -1373,3 +1369,19 @@ EXPECT_EQ(GetSessionFor(other_observer), GetOrCreateSession(url::Origin::Create(url), opener.get())); } + +TEST_F(MediaEngagementContentsObserverTest, IgnoreAudioContextIfDisabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(media::kRecordWebAudioEngagement); + + Navigate(GURL("https://www.example.com")); + SimulateAudioContextStarted(0); + SimulateAudible(); + + EXPECT_FALSE(AreAudioContextConditionsMet()); + EXPECT_FALSE(IsAudioContextTimerRunning()); + EXPECT_FALSE(WasSignificantAudioContextPlaybackRecorded()); + + SimulateAudioContextPlaybackTimerFired(); + EXPECT_FALSE(WasSignificantAudioContextPlaybackRecorded()); +}
diff --git a/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer.cc b/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer.cc index 06b6628..4236a95e 100644 --- a/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer.cc +++ b/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer.cc
@@ -5,6 +5,9 @@ #include "chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer.h" #include "net/base/network_change_notifier.h" +#include "content/public/browser/network_service_instance.h" +#include "services/network/public/cpp/network_connection_tracker.h" + namespace media_router { namespace { @@ -12,9 +15,9 @@ // network ID of kNetworkIdDisconnected in a change event and checking that we // are actually disconnected and reporting it. // -// net::NetworkChangeNotifier, and therefore DiscoveryNetworkMonitor, reports a -// disconnected state between any other network change. In order to avoid -// reporting these spurious kNetworkIdDisconnected events as real +// network::NetworkConnectionTracker, and therefore DiscoveryNetworkMonitor, +// reports a disconnected state between any other network change. In order to +// avoid reporting these spurious kNetworkIdDisconnected events as real // disconnections, we wait for this timeout and then check the network status // again. If any other network change notification comes while we are waiting, // this state check is cancelled. @@ -23,26 +26,26 @@ DiscoveryNetworkMonitorConnectionType ConnectionTypeFromIdAndType( const std::string& network_id, - net::NetworkChangeNotifier::ConnectionType connection_type) { + network::mojom::ConnectionType connection_type) { if (network_id == DiscoveryNetworkMonitor::kNetworkIdDisconnected) { return DiscoveryNetworkMonitorConnectionType::kDisconnected; } else if (network_id == DiscoveryNetworkMonitor::kNetworkIdUnknown) { switch (connection_type) { - case net::NetworkChangeNotifier::CONNECTION_WIFI: + case network::mojom::ConnectionType::CONNECTION_WIFI: return DiscoveryNetworkMonitorConnectionType::kUnknownReportedAsWifi; - case net::NetworkChangeNotifier::CONNECTION_ETHERNET: + case network::mojom::ConnectionType::CONNECTION_ETHERNET: return DiscoveryNetworkMonitorConnectionType:: kUnknownReportedAsEthernet; - case net::NetworkChangeNotifier::CONNECTION_UNKNOWN: + case network::mojom::ConnectionType::CONNECTION_UNKNOWN: return DiscoveryNetworkMonitorConnectionType::kUnknown; default: return DiscoveryNetworkMonitorConnectionType::kUnknownReportedAsOther; } } else { switch (connection_type) { - case net::NetworkChangeNotifier::CONNECTION_WIFI: + case network::mojom::ConnectionType::CONNECTION_WIFI: return DiscoveryNetworkMonitorConnectionType::kWifi; - case net::NetworkChangeNotifier::CONNECTION_ETHERNET: + case network::mojom::ConnectionType::CONNECTION_ETHERNET: return DiscoveryNetworkMonitorConnectionType::kEthernet; default: return DiscoveryNetworkMonitorConnectionType::kUnknown; @@ -50,6 +53,13 @@ } } +network::mojom::ConnectionType GetConnectionType() { + auto connection_type = network::mojom::ConnectionType::CONNECTION_UNKNOWN; + content::GetNetworkConnectionTracker()->GetConnectionType(&connection_type, + base::DoNothing()); + return connection_type; +} + } // namespace DiscoveryNetworkMonitorMetricObserver::DiscoveryNetworkMonitorMetricObserver( @@ -80,8 +90,7 @@ last_event_time_ = now; disconnect_timer_.Stop(); DiscoveryNetworkMonitorConnectionType connection_type = - ConnectionTypeFromIdAndType( - network_id, net::NetworkChangeNotifier::GetConnectionType()); + ConnectionTypeFromIdAndType(network_id, GetConnectionType()); metrics_->RecordConnectionType(connection_type); }
diff --git a/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer_unittest.cc b/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer_unittest.cc index 7cca342..ed6086e 100644 --- a/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer_unittest.cc +++ b/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer_unittest.cc
@@ -6,11 +6,10 @@ #include <memory> -#include "base/test/simple_test_tick_clock.h" -#include "base/test/test_mock_time_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/timer/mock_timer.h" -#include "net/base/mock_network_change_notifier.h" +#include "base/test/scoped_task_environment.h" +#include "content/public/browser/network_service_instance.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "services/network/test/test_network_connection_tracker.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -59,38 +58,29 @@ void(DiscoveryNetworkMonitorConnectionType)); }; -class MockNetworkChangeNotifier : public net::NetworkChangeNotifier { - public: - ConnectionType GetCurrentConnectionType() const override { - return connection_type_; - } - - void SetConnectionType(ConnectionType connection_type) { - connection_type_ = connection_type; - } - - private: - ConnectionType connection_type_; -}; - class DiscoveryNetworkMonitorMetricObserverTest : public ::testing::Test { public: DiscoveryNetworkMonitorMetricObserverTest() - : mock_network_change_notifier_( - std::make_unique<MockNetworkChangeNotifier>()), - task_runner_(new base::TestMockTimeTaskRunner()), - task_runner_handle_(task_runner_), - start_ticks_(task_runner_->NowTicks()), + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME), + thread_bundle_(content::TestBrowserThreadBundle::PLAIN_MAINLOOP), + test_network_connection_tracker_( + true, + network::mojom::ConnectionType::CONNECTION_NONE), + start_ticks_(scoped_task_environment_.NowTicks()), metrics_(std::make_unique<MockMetrics>()), mock_metrics_(metrics_.get()), - metric_observer_(task_runner_->GetMockTickClock(), - std::move(metrics_)) {} + metric_observer_(scoped_task_environment_.GetMockTickClock(), + std::move(metrics_)) { + content::SetNetworkConnectionTrackerForTesting( + &test_network_connection_tracker_); + } protected: + base::test::ScopedTaskEnvironment scoped_task_environment_; + content::TestBrowserThreadBundle thread_bundle_; base::TimeDelta time_advance_ = base::TimeDelta::FromMilliseconds(10); - std::unique_ptr<MockNetworkChangeNotifier> mock_network_change_notifier_; - scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; - base::ThreadTaskRunnerHandle task_runner_handle_; + network::TestNetworkConnectionTracker test_network_connection_tracker_; const base::TimeTicks start_ticks_; std::unique_ptr<MockMetrics> metrics_; MockMetrics* mock_metrics_; @@ -101,8 +91,8 @@ } // namespace TEST_F(DiscoveryNetworkMonitorMetricObserverTest, RecordsFirstGoodNetworkWifi) { - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_WIFI); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_WIFI); EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents(_)).Times(0); EXPECT_CALL( *mock_metrics_, @@ -112,8 +102,8 @@ TEST_F(DiscoveryNetworkMonitorMetricObserverTest, RecordsFirstGoodNetworkEthernet) { - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_ETHERNET); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_ETHERNET); EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents(_)).Times(0); EXPECT_CALL( *mock_metrics_, @@ -123,8 +113,8 @@ TEST_F(DiscoveryNetworkMonitorMetricObserverTest, RecordsFirstGoodNetworkUnknownWifi) { - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_WIFI); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_WIFI); EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents(_)).Times(0); EXPECT_CALL( *mock_metrics_, @@ -136,8 +126,8 @@ TEST_F(DiscoveryNetworkMonitorMetricObserverTest, RecordsFirstGoodNetworkUnknownEthernet) { - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_ETHERNET); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_ETHERNET); EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents(_)).Times(0); EXPECT_CALL( *mock_metrics_, @@ -149,8 +139,8 @@ TEST_F(DiscoveryNetworkMonitorMetricObserverTest, RecordsFirstGoodNetworkUnknownOther) { - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_4G); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_4G); EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents(_)).Times(0); EXPECT_CALL( *mock_metrics_, @@ -162,8 +152,8 @@ TEST_F(DiscoveryNetworkMonitorMetricObserverTest, RecordsFirstGoodNetworkUnknown) { - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_UNKNOWN); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_UNKNOWN); EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents(_)).Times(0); EXPECT_CALL( *mock_metrics_, @@ -174,8 +164,8 @@ TEST_F(DiscoveryNetworkMonitorMetricObserverTest, RecordsFirstGoodNetworkDisconnected) { - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_NONE); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_NONE); EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents(_)).Times(0); EXPECT_CALL(*mock_metrics_, RecordConnectionType( @@ -183,8 +173,8 @@ metric_observer_.OnNetworksChanged( DiscoveryNetworkMonitor::kNetworkIdDisconnected); - task_runner_->FastForwardUntilNoTasksRemain(); - task_runner_->RunUntilIdle(); + scoped_task_environment_.FastForwardUntilNoTasksRemain(); + scoped_task_environment_.RunUntilIdle(); } TEST_F(DiscoveryNetworkMonitorMetricObserverTest, @@ -193,46 +183,46 @@ EXPECT_CALL( *mock_metrics_, RecordConnectionType(DiscoveryNetworkMonitorConnectionType::kEthernet)); - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_ETHERNET); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_ETHERNET); metric_observer_.OnNetworksChanged("network1"); EXPECT_CALL(*mock_metrics_, RecordConnectionType(_)).Times(0); - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_NONE); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_NONE); metric_observer_.OnNetworksChanged( DiscoveryNetworkMonitor::kNetworkIdDisconnected); - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_ETHERNET); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_ETHERNET); EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents(_)); EXPECT_CALL( *mock_metrics_, RecordConnectionType(DiscoveryNetworkMonitorConnectionType::kEthernet)); metric_observer_.OnNetworksChanged("network2"); - task_runner_->FastForwardUntilNoTasksRemain(); - task_runner_->RunUntilIdle(); + scoped_task_environment_.FastForwardUntilNoTasksRemain(); + scoped_task_environment_.RunUntilIdle(); } TEST_F(DiscoveryNetworkMonitorMetricObserverTest, DoesntRecordEphemeralDisconnectedStateWhenFirst) { EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents(_)).Times(0); EXPECT_CALL(*mock_metrics_, RecordConnectionType(_)).Times(0); - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_NONE); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_NONE); metric_observer_.OnNetworksChanged( DiscoveryNetworkMonitor::kNetworkIdDisconnected); - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_ETHERNET); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_ETHERNET); EXPECT_CALL( *mock_metrics_, RecordConnectionType(DiscoveryNetworkMonitorConnectionType::kEthernet)); metric_observer_.OnNetworksChanged("network2"); - task_runner_->FastForwardUntilNoTasksRemain(); - task_runner_->RunUntilIdle(); + scoped_task_environment_.FastForwardUntilNoTasksRemain(); + scoped_task_environment_.RunUntilIdle(); } TEST_F(DiscoveryNetworkMonitorMetricObserverTest, @@ -241,19 +231,19 @@ EXPECT_CALL( *mock_metrics_, RecordConnectionType(DiscoveryNetworkMonitorConnectionType::kEthernet)); - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_ETHERNET); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_ETHERNET); metric_observer_.OnNetworksChanged("network1"); - task_runner_->FastForwardBy(time_advance_); - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_NONE); + scoped_task_environment_.FastForwardBy(time_advance_); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_NONE); metric_observer_.OnNetworksChanged( DiscoveryNetworkMonitor::kNetworkIdDisconnected); - task_runner_->FastForwardBy(time_advance_); - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_ETHERNET); + scoped_task_environment_.FastForwardBy(time_advance_); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_ETHERNET); EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents( (start_ticks_ + time_advance_ * 2) - start_ticks_)); @@ -262,8 +252,8 @@ RecordConnectionType(DiscoveryNetworkMonitorConnectionType::kEthernet)); metric_observer_.OnNetworksChanged("network2"); - task_runner_->FastForwardUntilNoTasksRemain(); - task_runner_->RunUntilIdle(); + scoped_task_environment_.FastForwardUntilNoTasksRemain(); + scoped_task_environment_.RunUntilIdle(); } TEST_F(DiscoveryNetworkMonitorMetricObserverTest, @@ -272,17 +262,17 @@ EXPECT_CALL( *mock_metrics_, RecordConnectionType(DiscoveryNetworkMonitorConnectionType::kEthernet)); - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_ETHERNET); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_ETHERNET); metric_observer_.OnNetworksChanged("network1"); - task_runner_->FastForwardBy(time_advance_); - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_NONE); + scoped_task_environment_.FastForwardBy(time_advance_); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_NONE); metric_observer_.OnNetworksChanged( DiscoveryNetworkMonitor::kNetworkIdDisconnected); - task_runner_->FastForwardBy(time_advance_); + scoped_task_environment_.FastForwardBy(time_advance_); EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents( (start_ticks_ + time_advance_) - start_ticks_)); @@ -290,8 +280,8 @@ RecordConnectionType( DiscoveryNetworkMonitorConnectionType::kDisconnected)); - task_runner_->FastForwardUntilNoTasksRemain(); - task_runner_->RunUntilIdle(); + scoped_task_environment_.FastForwardUntilNoTasksRemain(); + scoped_task_environment_.RunUntilIdle(); } TEST_F(DiscoveryNetworkMonitorMetricObserverTest, @@ -300,18 +290,18 @@ EXPECT_CALL( *mock_metrics_, RecordConnectionType(DiscoveryNetworkMonitorConnectionType::kEthernet)); - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_ETHERNET); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_ETHERNET); metric_observer_.OnNetworksChanged("network1"); - task_runner_->FastForwardBy(time_advance_); - const auto disconnect_ticks = task_runner_->NowTicks(); - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_NONE); + scoped_task_environment_.FastForwardBy(time_advance_); + const auto disconnect_ticks = scoped_task_environment_.NowTicks(); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_NONE); metric_observer_.OnNetworksChanged( DiscoveryNetworkMonitor::kNetworkIdDisconnected); - task_runner_->FastForwardBy(time_advance_); + scoped_task_environment_.FastForwardBy(time_advance_); EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents( (start_ticks_ + time_advance_) - start_ticks_)); @@ -319,18 +309,18 @@ RecordConnectionType( DiscoveryNetworkMonitorConnectionType::kDisconnected)); - task_runner_->FastForwardUntilNoTasksRemain(); - task_runner_->RunUntilIdle(); + scoped_task_environment_.FastForwardUntilNoTasksRemain(); + scoped_task_environment_.RunUntilIdle(); - task_runner_->FastForwardBy(time_advance_); - const auto second_ethernet_ticks = task_runner_->NowTicks(); + scoped_task_environment_.FastForwardBy(time_advance_); + const auto second_ethernet_ticks = scoped_task_environment_.NowTicks(); EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents( second_ethernet_ticks - disconnect_ticks)); EXPECT_CALL( *mock_metrics_, RecordConnectionType(DiscoveryNetworkMonitorConnectionType::kEthernet)); - mock_network_change_notifier_->SetConnectionType( - net::NetworkChangeNotifier::CONNECTION_ETHERNET); + test_network_connection_tracker_.SetConnectionType( + network::mojom::ConnectionType::CONNECTION_ETHERNET); metric_observer_.OnNetworksChanged("network1"); }
diff --git a/chrome/browser/media/router/discovery/discovery_network_monitor_metrics.h b/chrome/browser/media/router/discovery/discovery_network_monitor_metrics.h index ceec530..57e466b 100644 --- a/chrome/browser/media/router/discovery/discovery_network_monitor_metrics.h +++ b/chrome/browser/media/router/discovery/discovery_network_monitor_metrics.h
@@ -10,36 +10,36 @@ namespace media_router { // This enum indicates the state of the host's network connectivity according to -// both net::NetworkChangeNotifier and DiscoveryNetworkMonitor. If +// both network::NetworkConnectionTracker and DiscoveryNetworkMonitor. If // DiscoveryNetworkMonitor reports the network identifier is unknown, we would -// also like to record what net::NetworkChangeNotifier says about the connection -// type. +// also like to record what network::NetworkConnectionTracker says about the +// connection type. // // It is tied to the UMA histogram MediaRouter.NetworkMonitor.ConnectionType so // new values should only be added at the end, but before kTotalCount. enum class DiscoveryNetworkMonitorConnectionType { - // net::NetworkChangeNotifier reports the connection type is Wifi and we have - // a valid network identifier from DiscoveryNetworkMonitor. + // network::NetworkConnectionTracker reports the connection type is Wifi and + // we have a valid network identifier from DiscoveryNetworkMonitor. kWifi = 0, - // net::NetworkChangeNotifier reports the connection type is ethernet and we - // have a valid network identifier from DiscoveryNetworkMonitor. + // network::NetworkConnectionTracker reports the connection type is ethernet + // and we have a valid network identifier from DiscoveryNetworkMonitor. kEthernet = 1, - // net::NetworkChangeNotifier reports the connection type is Wifi but we don't - // have a valid network identifier from DiscoveryNetworkMonitor. + // network::NetworkConnectionTracker reports the connection type is Wifi but + // we don't have a valid network identifier from DiscoveryNetworkMonitor. kUnknownReportedAsWifi = 2, - // net::NetworkChangeNotifier reports the connection type is ethernet but we - // don't have a valid network identifier from DiscoveryNetworkMonitor. + // network::NetworkConnectionTracker reports the connection type is ethernet + // but we don't have a valid network identifier from DiscoveryNetworkMonitor. kUnknownReportedAsEthernet = 3, - // net::NetworkChangeNotifier reports the connection type is something other - // than Wifi and ethernet and we don't have a valid network identifier from - // DiscoveryNetworkMonitor. + // network::NetworkConnectionTracker reports the connection type is something + // other than Wifi and ethernet and we don't have a valid network identifier + // from DiscoveryNetworkMonitor. kUnknownReportedAsOther = 4, - // net::NetworkChangeNotifier reports the connection type is unknown and we - // don't have a valid network identifier from DiscoveryNetworkMonitor. + // network::NetworkConnectionTracker reports the connection type is unknown + // and we don't have a valid network identifier from DiscoveryNetworkMonitor. kUnknown = 5, // DiscoveryNetworkMonitor reports that the host is disconnected from all - // networks. This comes directly from net::NetworkChangeNotifier so there is - // no potential inconsistency to record. + // networks. This comes directly from network::NetworkConnectionTracker so + // there is no potential inconsistency to record. kDisconnected = 6, // NOTE: Add entries only immediately above this line. @@ -55,7 +55,7 @@ virtual void RecordTimeBetweenNetworkChangeEvents(base::TimeDelta delta); // This records the connection type as reported by both - // DiscoveryNetworkMonitor and net::NetworkChangeNotifier. + // DiscoveryNetworkMonitor and network::NetworkConnectionTracker. virtual void RecordConnectionType( DiscoveryNetworkMonitorConnectionType connection_type); };
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_unittest.cc b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_unittest.cc index 4afa439..874dc19 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_unittest.cc +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_unittest.cc
@@ -16,8 +16,10 @@ #include "components/cast_channel/cast_socket.h" #include "components/cast_channel/cast_socket_service.h" #include "components/cast_channel/cast_test_util.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/test/test_browser_thread_bundle.h" #include "net/base/ip_address.h" +#include "services/network/test/test_network_connection_tracker.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -118,13 +120,18 @@ public: CastMediaSinkServiceTest() : task_runner_(new base::TestSimpleTaskRunner()), - network_change_notifier_(net::NetworkChangeNotifier::CreateMock()), + test_network_connection_tracker_( + true, + network::mojom::ConnectionType::CONNECTION_UNKNOWN), mock_cast_socket_service_( new cast_channel::MockCastSocketService(task_runner_)), media_sink_service_(new TestCastMediaSinkService( mock_cast_socket_service_.get(), DiscoveryNetworkMonitor::GetInstance())), - test_dns_sd_registry_(media_sink_service_.get()) {} + test_dns_sd_registry_(media_sink_service_.get()) { + content::SetNetworkConnectionTrackerForTesting( + &test_network_connection_tracker_); + } void SetUp() override { EXPECT_CALL(test_dns_sd_registry_, AddObserver(media_sink_service_.get())); @@ -146,12 +153,13 @@ EXPECT_CALL(test_dns_sd_registry_, UnregisterDnsSdListener(_)); media_sink_service_.reset(); task_runner_->RunUntilIdle(); + thread_bundle_.RunUntilIdle(); } protected: content::TestBrowserThreadBundle thread_bundle_; scoped_refptr<base::TestSimpleTaskRunner> task_runner_; - std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; + network::TestNetworkConnectionTracker test_network_connection_tracker_; base::MockCallback<OnSinksDiscoveredCallback> mock_sink_discovered_ui_cb_; TestMediaSinkService dial_media_sink_service_;
diff --git a/chrome/browser/net/OWNERS b/chrome/browser/net/OWNERS index 7123cf4..6e9ab05a 100644 --- a/chrome/browser/net/OWNERS +++ b/chrome/browser/net/OWNERS
@@ -1,6 +1,5 @@ file://net/OWNERS -per-file *predictor*=alexilin@chromium.org per-file disk_cache_dir_policy_handler*=atwilson@chromium.org # COMPONENT: Internals>Network
diff --git a/chrome/browser/net/chrome_network_service_browsertest.cc b/chrome/browser/net/chrome_network_service_browsertest.cc index 4958ef39..0d6d4933 100644 --- a/chrome/browser/net/chrome_network_service_browsertest.cc +++ b/chrome/browser/net/chrome_network_service_browsertest.cc
@@ -16,6 +16,10 @@ #include "net/extras/sqlite/cookie_crypto_delegate.h" #include "services/network/public/cpp/features.h" +#if defined(OS_MACOSX) +#include "base/mac/mac_util.h" +#endif + namespace content { namespace { @@ -91,7 +95,7 @@ EXPECT_EQ(kCookieValue, cookies[0].Value()); } -#if defined(OS_WIN) || defined(OS_MACOSX) +#if defined(OS_WIN) // The cookies.size() ASSERT is failing flakily on the Win7 bots. // See https://crbug.com/868667 #define MAYBE_EncryptedCookies DISABLED_EncryptedCookies @@ -101,6 +105,11 @@ IN_PROC_BROWSER_TEST_F(ChromeNetworkServiceBrowserTest, MAYBE_EncryptedCookies) { +#if defined(OS_MACOSX) + // TODO(https://crbug.com/868667): Fix and reenable test. + if (base::mac::IsOS10_11()) + return; +#endif net::CookieCryptoDelegate* crypto_delegate = cookie_config::GetCookieCryptoDelegate(); std::string ciphertext;
diff --git a/chrome/browser/net/network_context_configuration_browsertest.cc b/chrome/browser/net/network_context_configuration_browsertest.cc index 404b550..2f225bc 100644 --- a/chrome/browser/net/network_context_configuration_browsertest.cc +++ b/chrome/browser/net/network_context_configuration_browsertest.cc
@@ -79,6 +79,10 @@ #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" +#if defined(OS_MACOSX) +#include "base/mac/mac_util.h" +#endif + namespace { const char kCacheRandomPath[] = "/cacherandom"; @@ -1234,15 +1238,12 @@ EXPECT_FALSE(GetCookies(embedded_test_server()->base_url()).empty()); } +IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, CookiesEnabled) { #if defined(OS_MACOSX) -// https://crbug.com/880496 -#define MAYBE_CookiesEnabled DISABLED_CookiesEnabled -#else -#define MAYBE_CookiesEnabled CookiesEnabled + // TODO(https://crbug.com/880496): Fix and reenable test. + if (base::mac::IsOS10_11()) + return; #endif - -IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, - MAYBE_CookiesEnabled) { // Check that the cookie from the first stage of the test was / was not // preserved between browser restarts, as expected. bool has_cookies = !GetCookies(embedded_test_server()->base_url()).empty();
diff --git a/chrome/browser/net/predictor.cc b/chrome/browser/net/predictor.cc deleted file mode 100644 index 3c4ca44..0000000 --- a/chrome/browser/net/predictor.cc +++ /dev/null
@@ -1,1103 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/net/predictor.h" - -#include <algorithm> -#include <cmath> -#include <iterator> -#include <set> -#include <sstream> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/containers/mru_cache.h" -#include "base/feature_list.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/metrics/histogram_macros.h" -#include "base/single_thread_task_runner.h" -#include "base/stl_util.h" -#include "base/strings/stringprintf.h" -#include "base/threading/thread_restrictions.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "base/trace_event/trace_event.h" -#include "base/values.h" -#include "build/build_config.h" -#include "chrome/browser/io_thread.h" -#include "chrome/browser/predictors/loading_predictor_config.h" -#include "chrome/browser/prefs/session_startup_pref.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_io_data.h" -#include "chrome/common/chrome_features.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/pref_names.h" -#include "components/pref_registry/pref_registry_syncable.h" -#include "components/prefs/pref_service.h" -#include "components/prefs/scoped_user_pref_update.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/resource_hints.h" -#include "content/public/browser/storage_partition.h" -#include "net/base/address_list.h" -#include "net/base/completion_callback.h" -#include "net/base/host_port_pair.h" -#include "net/base/net_errors.h" -#include "net/http/transport_security_state.h" -#include "net/log/net_log_with_source.h" -#include "net/proxy_resolution/proxy_info.h" -#include "net/proxy_resolution/proxy_resolution_service.h" -#include "net/ssl/ssl_config_service.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_getter.h" - -using base::TimeDelta; -using content::BrowserThread; - -namespace chrome_browser_net { - -namespace { - -#if defined(OS_ANDROID) -// Disabled on Android, as there are no "pinned tabs", meaning that a startup -// is unlikely to request the same URL, and hence to resolve the same domains -// as the previous one. -constexpr bool kInitialDnsPrefetchListEnabled = false; -#else -constexpr bool kInitialDnsPrefetchListEnabled = true; -#endif // defined(OS_ANDROID) - -} // namespace - -// The InitialObserver monitors navigations made by the network stack. This -// is only used to identify startup time resolutions (for re-resolution -// during our next process startup). -// TODO(jar): Consider preconnecting at startup, which may be faster than -// waiting for render process to start and request a connection. -class InitialObserver { - public: - InitialObserver(); - ~InitialObserver(); - // Recording of when we observed each navigation. - typedef std::map<GURL, base::TimeTicks> FirstNavigations; - - // Potentially add a new URL to our startup list. - void Append(const GURL& url, Predictor* predictor); - - // Persist the current first_navigations_ for storage in a list. - void GetInitialDnsResolutionList(base::ListValue* startup_list); - - // Discards all initial loading history. - void DiscardInitialNavigationHistory() { first_navigations_.clear(); } - - private: - // List of the first N URL resolutions observed in this run. - FirstNavigations first_navigations_; - - // The number of URLs we'll save for pre-resolving at next startup. - static const size_t kStartupResolutionCount = 10; -}; - -// static -const int Predictor::kPredictorReferrerVersion = 2; -const double Predictor::kPreconnectWorthyExpectedValue = 0.8; -const double Predictor::kDNSPreresolutionWorthyExpectedValue = 0.1; -const double Predictor::kDiscardableExpectedValue = 0.05; -const size_t Predictor::kMaxSpeculativeParallelResolves = 3; -const int Predictor::kMaxUnusedSocketLifetimeSecondsWithoutAGet = 10; - -// This number was obtained by the Net.Predictor.MRUIndex histogram on Canary -// and Dev channel (M53). The database size was initialized to 1000, and the -// histogram logged the index into the MRU in PrepareFrameSubresources. The -// results showed that 99% of all accesses used the first 100 elements, and -// 99.5% of all accesses used the first 170 elements. -const int Predictor::kMaxReferrers = 100; - -// To control our congestion avoidance system, which discards a queue when -// resolutions are "taking too long," we need an expected resolution time. -// Common average is in the range of 300-500ms. -const int kExpectedResolutionTimeMs = 500; -const int Predictor::kTypicalSpeculativeGroupSize = 8; -const int Predictor::kMaxSpeculativeResolveQueueDelayMs = - (kExpectedResolutionTimeMs * Predictor::kTypicalSpeculativeGroupSize) / - Predictor::kMaxSpeculativeParallelResolves; - -// The default value of the credentials flag when preconnecting. -static constexpr bool kAllowCredentialsOnPreconnectByDefault = true; - -static int g_max_queueing_delay_ms = - Predictor::kMaxSpeculativeResolveQueueDelayMs; -static size_t g_max_parallel_resolves = - Predictor::kMaxSpeculativeParallelResolves; - -// A version number for prefs that are saved. This should be incremented when -// we change the format so that we discard old data. -static const int kPredictorStartupFormatVersion = 1; - -Predictor::Predictor(bool predictor_enabled) - : url_request_context_getter_(nullptr), - predictor_enabled_(predictor_enabled), - user_prefs_(nullptr), - profile_io_data_(nullptr), - num_pending_lookups_(0), - peak_pending_lookups_(0), - shutdown_(false), - max_concurrent_dns_lookups_(g_max_parallel_resolves), - max_dns_queue_delay_( - TimeDelta::FromMilliseconds(g_max_queueing_delay_ms)), - transport_security_state_(nullptr), - ssl_config_service_(nullptr), - proxy_resolution_service_(nullptr), - consecutive_omnibox_preconnect_count_(0), - referrers_(kMaxReferrers), - observer_(nullptr), - timed_cache_(new TimedCache(base::TimeDelta::FromSeconds( - kMaxUnusedSocketLifetimeSecondsWithoutAGet))), - ui_weak_factory_(new base::WeakPtrFactory<Predictor>(this)) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); -} - -Predictor::~Predictor() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(shutdown_); -} - -// static -Predictor* Predictor::CreatePredictor(bool simple_shutdown) { - bool predictor_enabled = - base::FeatureList::IsEnabled(features::kNetworkPrediction) && - !predictors::ShouldDisableOtherPreconnects(); - if (simple_shutdown) - return new SimplePredictor(predictor_enabled); - return new Predictor(predictor_enabled); -} - -void Predictor::RegisterProfilePrefs( - user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterListPref(prefs::kDnsPrefetchingStartupList, - PrefRegistry::LOSSY_PREF); - registry->RegisterListPref(prefs::kDnsPrefetchingHostReferralList, - PrefRegistry::LOSSY_PREF); -} - -// --------------------- Start UI methods. ------------------------------------ - -void Predictor::InitNetworkPredictor(PrefService* user_prefs, - IOThread* io_thread, - net::URLRequestContextGetter* getter, - ProfileIOData* profile_io_data, - Profile* profile) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - user_prefs_ = user_prefs; - url_request_context_getter_ = getter; - profile_ = profile; - - // Gather the list of hostnames to prefetch on startup. - std::vector<GURL> urls = GetPredictedUrlListAtStartup(user_prefs); - - std::unique_ptr<base::ListValue> referral_list = base::WrapUnique( - user_prefs->GetList(prefs::kDnsPrefetchingHostReferralList)->DeepCopy()); - - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&Predictor::FinalizeInitializationOnIOThread, - base::Unretained(this), urls, std::move(referral_list), - io_thread, profile_io_data)); -} - -void Predictor::AnticipateOmniboxUrl(const GURL& url, bool preconnectable) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (!PredictorEnabled()) - return; - if (!url.is_valid() || !url.has_host()) - return; - if (!CanPreresolveAndPreconnect()) - return; - - std::string host = url.HostNoBrackets(); - bool is_new_host_request = (host != last_omnibox_host_); - last_omnibox_host_ = host; - - UrlInfo::ResolutionMotivation motivation(UrlInfo::OMNIBOX_MOTIVATED); - base::TimeTicks now = base::TimeTicks::Now(); - - if (preconnectable && !is_new_host_request) { - ++consecutive_omnibox_preconnect_count_; - // The omnibox suggests a search URL (for which we can preconnect) after - // one or two characters are typed, even though such typing often (1 in - // 3?) becomes a real URL. This code waits till is has more evidence of a - // preconnectable URL (search URL) before forming a preconnection, so as - // to reduce the useless preconnect rate. - // Perchance this logic should be pushed back into the omnibox, where the - // actual characters typed, such as a space, can better forcast whether - // we need to search/preconnect or not. By waiting for at least 4 - // characters in a row that have lead to a search proposal, we avoid - // preconnections for a prefix like "www." and we also wait until we have - // at least a 4 letter word to search for. - // Each character typed appears to induce 2 calls to AnticipateOmniboxUrl(), - // so we double 4 characters and limit at 8 requests. - // TODO(jar): Use an A/B test to optimize this. - const int kMinConsecutiveRequests = 8; - if (consecutive_omnibox_preconnect_count_ >= kMinConsecutiveRequests) { - // TODO(jar): Perhaps we should do a GET to leave the socket open in the - // pool. Currently, we just do a connect, which MAY be reset if we - // don't use it in 10 secondes!!! As a result, we may do more - // connections, and actually cost the server more than if we did a real - // get with a fake request (/gen_204 might be the good path on Google). - const int kMaxSearchKeepaliveSeconds(10); - if ((now - last_omnibox_preconnect_).InSeconds() < - kMaxSearchKeepaliveSeconds) - return; // We've done a preconnect recently. - last_omnibox_preconnect_ = now; - const int kConnectionsNeeded = 1; - PreconnectUrl(CanonicalizeUrl(url), GURL(), motivation, - kAllowCredentialsOnPreconnectByDefault, kConnectionsNeeded); - return; // Skip pre-resolution, since we'll open a connection. - } - } else { - consecutive_omnibox_preconnect_count_ = 0; - } - - // Fall through and consider pre-resolution. - - // Omnibox tends to call in pairs (just a few milliseconds apart), and we - // really don't need to keep resolving a name that often. - // TODO(jar): A/B tests could check for perf impact of the early returns. - if (!is_new_host_request) { - const int kMinPreresolveSeconds(10); - if (kMinPreresolveSeconds > (now - last_omnibox_preresolve_).InSeconds()) - return; - } - last_omnibox_preresolve_ = now; - - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&Predictor::Resolve, base::Unretained(this), - CanonicalizeUrl(url), motivation)); -} - -void Predictor::PreconnectUrlAndSubresources(const GURL& url, - const GURL& site_for_cookies) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || - BrowserThread::CurrentlyOn(BrowserThread::IO)); - if (!PredictorEnabled()) - return; - if (!CanPreresolveAndPreconnect()) - return; - const GURL canonicalized_url = CanonicalizeUrl(url); - if (!canonicalized_url.is_valid() || !canonicalized_url.has_host()) - return; - UrlInfo::ResolutionMotivation motivation(UrlInfo::EARLY_LOAD_MOTIVATED); - const int kConnectionsNeeded = 1; - PreconnectUrl(canonicalized_url, site_for_cookies, motivation, - kAllowCredentialsOnPreconnectByDefault, kConnectionsNeeded); - PredictFrameSubresources(canonicalized_url.GetWithEmptyPath(), - site_for_cookies); -} - -std::vector<GURL> Predictor::GetPredictedUrlListAtStartup( - PrefService* user_prefs) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - std::vector<GURL> urls; - // Recall list of URLs we learned about during last session. - // This may catch secondary hostnames, pulled in by the homepages. It will - // also catch more of the "primary" home pages, since that was (presumably) - // rendered first (and will be rendered first this time too). - const base::ListValue* startup_list = - user_prefs->GetList(prefs::kDnsPrefetchingStartupList); - - if (startup_list) { - base::ListValue::const_iterator it = startup_list->begin(); - int format_version = -1; - if (it != startup_list->end() && it->GetAsInteger(&format_version) && - format_version == kPredictorStartupFormatVersion) { - ++it; - for (; it != startup_list->end(); ++it) { - std::string url_spec; - if (!it->GetAsString(&url_spec)) { - LOG(DFATAL); - break; // Format incompatibility. - } - GURL url(url_spec); - if (!url.has_host() || !url.has_scheme()) { - LOG(DFATAL); - break; // Format incompatibility. - } - - urls.push_back(url); - } - } - } - - // Prepare for any static home page(s) the user has in prefs. The user may - // have a LOT of tab's specified, so we may as well try to warm them all. - SessionStartupPref tab_start_pref = - SessionStartupPref::GetStartupPref(user_prefs); - if (SessionStartupPref::URLS == tab_start_pref.type) { - for (size_t i = 0; i < tab_start_pref.urls.size(); i++) { - GURL gurl = tab_start_pref.urls[i]; - if (!gurl.is_valid() || gurl.SchemeIsFile() || gurl.host_piece().empty()) - continue; - if (gurl.SchemeIsHTTPOrHTTPS()) - urls.push_back(gurl.GetWithEmptyPath()); - } - } - - if (urls.empty()) - urls.push_back(GURL("http://www.google.com:80")); - - return urls; -} - -void Predictor::DiscardAllResultsAndClearPrefsOnUIThread() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - // The post task here is guaranteed to execute before the post task in - // ShutdownOnUIThread, because the caller has a valid profile here. Note that - // the ChromeNetBenchmarkingMessageFilter calls unsafely (an existing bug) - // into the profile, but doing so would crash before this point anyways. - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&Predictor::DiscardAllResults, base::Unretained(this))); - ClearPrefsOnUIThread(); -} - -void Predictor::ClearPrefsOnUIThread() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - user_prefs_->ClearPref(prefs::kDnsPrefetchingStartupList); - user_prefs_->ClearPref(prefs::kDnsPrefetchingHostReferralList); -} - -void Predictor::set_max_queueing_delay(int max_queueing_delay_ms) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - g_max_queueing_delay_ms = max_queueing_delay_ms; -} - -void Predictor::set_max_parallel_resolves(size_t max_parallel_resolves) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - g_max_parallel_resolves = max_parallel_resolves; -} - -void Predictor::ShutdownOnUIThread() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - ui_weak_factory_->InvalidateWeakPtrs(); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&Predictor::Shutdown, base::Unretained(this))); -} - -// ---------------------- End UI methods. ------------------------------------- - -// --------------------- Start IO methods. ------------------------------------ - -void Predictor::Shutdown() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(!shutdown_); - shutdown_ = true; -} - -void Predictor::DiscardAllResults() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - // Delete anything listed so far in this session that shows in about:dns. - referrers_.Clear(); - - // Try to delete anything in our work queue. - while (!work_queue_.IsEmpty()) { - // Emulate processing cycle as though host was not found. - GURL url = work_queue_.Pop(); - UrlInfo* info = &results_[url]; - DCHECK(info->HasUrl(url)); - info->SetAssignedState(); - info->SetNoSuchNameState(); - } - // Now every result_ is either resolved, or is being resolved. - - // Step through result_, recording names of all hosts that can't be erased. - // We can't erase anything being worked on. - Results assignees; - for (auto& result : results_) { - const GURL& url = result.first; - UrlInfo& info = result.second; - DCHECK(info.HasUrl(url)); - if (info.is_assigned()) { - info.SetPendingDeleteState(); - assignees[url] = std::move(info); - } - } - DCHECK_LE(assignees.size(), max_concurrent_dns_lookups_); - results_.clear(); - // Put back in the names being worked on. - for (auto& assignee : assignees) { - DCHECK(assignee.second.is_marked_to_delete()); - results_[assignee.first] = std::move(assignee.second); - } -} - -// Overloaded Resolve() to take a vector of names. -void Predictor::ResolveList(const std::vector<GURL>& urls, - UrlInfo::ResolutionMotivation motivation) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - for (std::vector<GURL>::const_iterator it = urls.begin(); it < urls.end(); - ++it) { - AppendToResolutionQueue(*it, motivation); - } -} - -// Basic Resolve() takes an invidual name, and adds it -// to the queue. -void Predictor::Resolve(const GURL& url, - UrlInfo::ResolutionMotivation motivation) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!url.has_host()) - return; - AppendToResolutionQueue(url, motivation); -} - -void Predictor::LearnFromNavigation(const GURL& referring_url, - const GURL& target_url) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!PredictorEnabled() || !CanPreresolveAndPreconnect()) - return; - DCHECK_EQ(referring_url, Predictor::CanonicalizeUrl(referring_url)); - DCHECK_NE(referring_url, GURL::EmptyGURL()); - DCHECK_EQ(target_url, Predictor::CanonicalizeUrl(target_url)); - DCHECK_NE(target_url, GURL::EmptyGURL()); - - // Skip HSTS redirects to learn the true referrer. - GURL referring_url_with_hsts = GetHSTSRedirectOnIOThread(referring_url); - - if (observer_) - observer_->OnLearnFromNavigation(referring_url_with_hsts, target_url); - // Peek here, as Get() occurs on the actual navigation. Note, Put is used here - // due to the fact that on a new navigation, it is unclear whether the URL - // will be a referrer to any subresource. That could result in bloating the - // database with empty entries. - Referrers::iterator it = referrers_.Peek(referring_url_with_hsts); - if (it == referrers_.end()) - it = referrers_.Put(referring_url_with_hsts, Referrer()); - - it->second.SuggestHost(target_url); -} - -// Iterating through a MRUCache goes through most recent first. Iterate -// backwards here so that adding items in order "Just Works" when deserializing. -void Predictor::SerializeReferrers(base::ListValue* referral_list) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(referral_list->empty()); - referral_list->AppendInteger(kPredictorReferrerVersion); - for (Referrers::const_reverse_iterator it = referrers_.rbegin(); - it != referrers_.rend(); ++it) { - // Create a list for each referer. - std::unique_ptr<base::ListValue> motivator(new base::ListValue); - motivator->AppendString(it->first.spec()); - motivator->Append(it->second.Serialize()); - - referral_list->Append(std::move(motivator)); - } -} - -void Predictor::DeserializeReferrers(const base::ListValue& referral_list) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - int format_version = -1; - if (referral_list.GetSize() > 0 && - referral_list.GetInteger(0, &format_version) && - format_version == kPredictorReferrerVersion) { - for (size_t i = 1; i < referral_list.GetSize(); ++i) { - const base::ListValue* motivator; - if (!referral_list.GetList(i, &motivator)) { - NOTREACHED(); - return; - } - std::string motivating_url_spec; - if (!motivator->GetString(0, &motivating_url_spec)) { - NOTREACHED(); - return; - } - - const base::Value* subresource_list; - if (!motivator->Get(1, &subresource_list)) { - NOTREACHED(); - return; - } - - referrers_.Put(GURL(motivating_url_spec), Referrer()) - ->second.Deserialize(*subresource_list); - } - } -} - -void Predictor::DiscardInitialNavigationHistory() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (kInitialDnsPrefetchListEnabled && initial_observer_) - initial_observer_->DiscardInitialNavigationHistory(); -} - -void Predictor::FinalizeInitializationOnIOThread( - const std::vector<GURL>& startup_urls, - std::unique_ptr<base::ListValue> referral_list, - IOThread* io_thread, - ProfileIOData* profile_io_data) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - TRACE_EVENT0("net", "Predictor::FinalizeInitializationOnIOThread"); - - profile_io_data_ = profile_io_data; - if (kInitialDnsPrefetchListEnabled) - initial_observer_ = std::make_unique<InitialObserver>(); - - net::URLRequestContext* context = - url_request_context_getter_->GetURLRequestContext(); - transport_security_state_ = context->transport_security_state(); - ssl_config_service_ = context->ssl_config_service(); - proxy_resolution_service_ = context->proxy_resolution_service(); - - // base::WeakPtrFactory instances need to be created and destroyed - // on the same thread. Initialize the IO thread weak factory now. - io_weak_factory_.reset(new base::WeakPtrFactory<Predictor>(this)); - - // Prefetch these hostnames on startup. - if (kInitialDnsPrefetchListEnabled) - DnsPrefetchMotivatedList(startup_urls, UrlInfo::STARTUP_LIST_MOTIVATED); - - DeserializeReferrers(*referral_list); -} - -//----------------------------------------------------------------------------- -// This section intermingles prefetch results with actual browser HTTP -// network activity. It supports calculating of the benefit of a prefetch, as -// well as recording what prefetched hostname resolutions might be potentially -// helpful during the next chrome-startup. -//----------------------------------------------------------------------------- - -void Predictor::LearnAboutInitialNavigation(const GURL& url) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!PredictorEnabled() || !kInitialDnsPrefetchListEnabled || - !initial_observer_ || !CanPreresolveAndPreconnect()) { - return; - } - initial_observer_->Append(url, this); -} - -// This API is only used in the browser process. -// It is called from an IPC message originating in the renderer. It currently -// includes both Page-Scan, and Link-Hover prefetching. -// TODO(jar): Separate out link-hover prefetching, and page-scan results. -void Predictor::DnsPrefetchList(const std::vector<std::string>& hostnames) { - // TODO(jar): Push GURL transport further back into renderer, but this will - // require a Webkit change in the observer :-/. - std::vector<GURL> urls; - for (std::vector<std::string>::const_iterator it = hostnames.begin(); - it < hostnames.end(); ++it) { - urls.push_back(GURL("http://" + *it + ":80")); - } - - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DnsPrefetchMotivatedList(urls, UrlInfo::PAGE_SCAN_MOTIVATED); -} - -void Predictor::DnsPrefetchMotivatedList( - const std::vector<GURL>& urls, - UrlInfo::ResolutionMotivation motivation) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || - BrowserThread::CurrentlyOn(BrowserThread::IO)); - if (!PredictorEnabled()) - return; - if (!CanPreresolveAndPreconnect()) - return; - - if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { - ResolveList(urls, motivation); - } else { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&Predictor::ResolveList, base::Unretained(this), urls, - motivation)); - } -} - -//----------------------------------------------------------------------------- -// Functions to handle saving of hostnames from one session to the next, to -// expedite startup times. - -void Predictor::SaveStateForNextStartup() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (!PredictorEnabled()) - return; - if (!CanPreresolveAndPreconnect()) - return; - - auto startup_list = std::make_unique<base::ListValue>(); - auto referral_list = std::make_unique<base::ListValue>(); - - // Get raw pointers to pass to the first task. Ownership of the unique_ptrs - // will be passed to the reply task. - base::ListValue* startup_list_raw = startup_list.get(); - base::ListValue* referral_list_raw = referral_list.get(); - - // The first post task here is guaranteed to execute before the post task in - // ShutdownOnUIThread, because the caller has a valid profile. - BrowserThread::PostTaskAndReply( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&Predictor::WriteDnsPrefetchState, base::Unretained(this), - startup_list_raw, referral_list_raw), - base::BindOnce(&Predictor::UpdatePrefsOnUIThread, - ui_weak_factory_->GetWeakPtr(), std::move(startup_list), - std::move(referral_list))); -} - -void Predictor::UpdatePrefsOnUIThread( - std::unique_ptr<base::ListValue> startup_list, - std::unique_ptr<base::ListValue> referral_list) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - user_prefs_->Set(prefs::kDnsPrefetchingStartupList, *startup_list); - - // May be empty if kInitialDnsPrefetchListEnabled is false. Still update the - // prefs to clear the state. - user_prefs_->Set(prefs::kDnsPrefetchingHostReferralList, *referral_list); -} - -void Predictor::WriteDnsPrefetchState(base::ListValue* startup_list, - base::ListValue* referral_list) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (kInitialDnsPrefetchListEnabled && initial_observer_) - initial_observer_->GetInitialDnsResolutionList(startup_list); - - SerializeReferrers(referral_list); -} - -void Predictor::PreconnectUrl(const GURL& url, - const GURL& site_for_cookies, - UrlInfo::ResolutionMotivation motivation, - bool allow_credentials, - int count) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || - BrowserThread::CurrentlyOn(BrowserThread::IO)); - DCHECK(url.is_valid()); - - if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { - PreconnectUrlOnIOThread(url, site_for_cookies, motivation, - allow_credentials, count); - } else { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&Predictor::PreconnectUrlOnIOThread, - base::Unretained(this), url, site_for_cookies, - motivation, allow_credentials, count)); - } -} - -void Predictor::PredictFrameSubresources(const GURL& url, - const GURL& site_for_cookies) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || - BrowserThread::CurrentlyOn(BrowserThread::IO)); - if (!PredictorEnabled()) - return; - if (!CanPreresolveAndPreconnect()) - return; - DCHECK_EQ(url.GetWithEmptyPath(), url); - // Add one pass through the message loop to allow current navigation to - // proceed. - if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { - PrepareFrameSubresources(url, site_for_cookies); - } else { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&Predictor::PrepareFrameSubresources, - base::Unretained(this), url, site_for_cookies)); - } -} - -bool Predictor::CanPrefetchAndPrerender() const { - chrome_browser_net::NetworkPredictionStatus status; - if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { - status = chrome_browser_net::CanPrefetchAndPrerenderUI(user_prefs_); - } else { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - status = chrome_browser_net::CanPrefetchAndPrerenderIO(profile_io_data_); - } - return status == chrome_browser_net::NetworkPredictionStatus::ENABLED; -} - -bool Predictor::CanPreresolveAndPreconnect() const { - if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { - return chrome_browser_net::CanPreresolveAndPreconnectUI(user_prefs_); - } else { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - return chrome_browser_net::CanPreresolveAndPreconnectIO(profile_io_data_); - } -} - -enum SubresourceValue { - PRECONNECTION, - PRERESOLUTION, - TOO_NEW, - SUBRESOURCE_VALUE_MAX -}; - -void Predictor::PreconnectUrlOnIOThread( - const GURL& url, - const GURL& site_for_cookies, - UrlInfo::ResolutionMotivation motivation, - bool allow_credentials, - int count) { - // TODO(csharrison): The observer should only be notified after the null check - // for the URLRequestContextGetter. The predictor tests should be fixed to - // allow for this, as they currently expect a callback with no getter. - if (observer_) { - observer_->OnPreconnectUrl(url, site_for_cookies, motivation, count); - } - - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&Predictor::PreconnectUrlOnUIThread, - ui_weak_factory_->GetWeakPtr(), url, site_for_cookies, - motivation, allow_credentials, count)); -} - -void Predictor::PrepareFrameSubresources(const GURL& original_url, - const GURL& site_for_cookies) { - // Apply HSTS redirect early so it is taken into account when looking up - // subresources. - GURL url = GetHSTSRedirectOnIOThread(original_url); - - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK_EQ(url.GetWithEmptyPath(), url); - DCHECK(PredictorEnabled()); - // Peek here, and Get after logging the index into the MRU. - Referrers::iterator it = referrers_.Get(url); - if (referrers_.end() == it) { - // Only when we don't know anything about this url, make 2 connections - // available. We could do this completely via learning (by prepopulating - // the referrer_ list with this expected value), but it would swell the - // size of the list with all the "Leaf" nodes in the tree (nodes that don't - // load any subresources). If we learn about this resource, we will instead - // provide a more carefully estimated preconnection count. - PreconnectUrlOnIOThread(url, site_for_cookies, - UrlInfo::SELF_REFERAL_MOTIVATED, - kAllowCredentialsOnPreconnectByDefault, 2); - return; - } - Referrer* referrer = &(it->second); - - referrer->IncrementUseCount(); - const UrlInfo::ResolutionMotivation motivation = - UrlInfo::LEARNED_REFERAL_MOTIVATED; - for (std::map<GURL, ReferrerValue>::iterator future_url = referrer->begin(); - future_url != referrer->end();) { - double connection_expectation = future_url->second.subresource_use_rate(); - future_url->second.ReferrerWasObserved(); - if (connection_expectation > kPreconnectWorthyExpectedValue) { - future_url->second.IncrementPreconnectionCount(); - int count = static_cast<int>(std::ceil(connection_expectation)); - if (url.host_piece() == future_url->first.host_piece()) - ++count; - PreconnectUrlOnIOThread(future_url->first, site_for_cookies, motivation, - kAllowCredentialsOnPreconnectByDefault, count); - } else if (connection_expectation > kDNSPreresolutionWorthyExpectedValue) { - future_url->second.preresolution_increment(); - AppendToResolutionQueue(future_url->first, motivation); - } - // Remove future urls that are below the discardable threshold here. This is - // the only place where the future urls of a referrer are iterated through, - // so it is the most logical place for trimming. - if (connection_expectation < kDiscardableExpectedValue) { - future_url = referrer->erase(future_url); - } else { - ++future_url; - } - } - // If the Referrer has no URLs associated with it, remove it from the map. - if (referrer->empty()) - referrers_.Erase(it); -} - -void Predictor::OnLookupFinished(const GURL& url, int result) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - LookupFinished(url, result == net::OK); - if (observer_) - observer_->OnDnsLookupFinished(url, result == net::OK); - DCHECK_GT(num_pending_lookups_, 0u); - num_pending_lookups_--; - StartSomeQueuedResolutions(); -} - -void Predictor::LookupFinished(const GURL& url, bool found) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - auto info_it = results_.find(url); - UrlInfo* info = &info_it->second; - DCHECK(info->HasUrl(url)); - bool is_marked_to_delete = info->is_marked_to_delete(); - - if (found) - info->SetFoundState(); - else - info->SetNoSuchNameState(); - - if (is_marked_to_delete) - results_.erase(info_it); -} - -bool Predictor::WouldLikelyProxyURL(const GURL& url) { - if (!proxy_resolution_service_) - return false; - - net::ProxyInfo info; - bool synchronous_success = proxy_resolution_service_->TryResolveProxySynchronously( - url, std::string(), &info, nullptr, net::NetLogWithSource()); - - return synchronous_success && !info.is_direct(); -} - -void Predictor::AppendToResolutionQueue( - const GURL& url, - UrlInfo::ResolutionMotivation motivation) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(url.has_host()); - - if (shutdown_) - return; - - UrlInfo* info = &results_[url]; - info->SetUrl(url); // Initialize or DCHECK. - DCHECK(info->HasUrl(url)); - - if (!info->NeedsDnsUpdate()) { - info->DLogResultsStats("DNS PrefetchNotUpdated"); - return; - } - - if (WouldLikelyProxyURL(url)) { - info->DLogResultsStats("DNS PrefetchForProxiedRequest"); - return; - } - - info->SetQueuedState(motivation); - work_queue_.Push(url, motivation); - - StartSomeQueuedResolutions(); -} - -bool Predictor::CongestionControlPerformed(Results::iterator info_it) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - UrlInfo* info = &info_it->second; - // Note: queue_duration is ONLY valid after we go to assigned state. - if (info->queue_duration() < max_dns_queue_delay_) - return false; - // We need to discard all entries in our queue, as we're keeping them waiting - // too long. By doing this, we'll have a chance to quickly service urgent - // resolutions, and not have a bogged down system. - while (true) { - info->RemoveFromQueue(); - results_.erase(info_it); - if (work_queue_.IsEmpty()) - break; - info_it = results_.find(work_queue_.Pop()); - info = &info_it->second; - info->SetAssignedState(); - } - return true; -} - -void Predictor::StartSomeQueuedResolutions() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - while (!work_queue_.IsEmpty() && - num_pending_lookups_ < max_concurrent_dns_lookups_) { - const GURL url(work_queue_.Pop()); - auto info_it = results_.find(url); - UrlInfo* info = &info_it->second; - DCHECK(info->HasUrl(url)); - info->SetAssignedState(); - - if (CongestionControlPerformed(info_it)) { - DCHECK(work_queue_.IsEmpty()); - return; - } - - info->SetPendingDeleteState(); - std::unique_ptr<net::HostResolver::Request> request; - int status = - content::PreresolveUrl(url_request_context_getter_.get(), url, - base::Bind(&Predictor::OnLookupFinished, - io_weak_factory_->GetWeakPtr(), url), - &request); - info->set_request(std::move(request)); - if (status == net::ERR_IO_PENDING) { - // Will complete asynchronously. - num_pending_lookups_++; - peak_pending_lookups_ = - std::max(peak_pending_lookups_, num_pending_lookups_); - } else { - // Completed synchronously (was already cached by HostResolver), or else - // there was (equivalently) some network error that prevents us from - // finding the name. Status net::OK means it was "found." - LookupFinished(url, status == net::OK); - } - } -} - -GURL Predictor::GetHSTSRedirectOnIOThread(const GURL& url) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (!transport_security_state_) - return url; - if (!url.SchemeIs("http")) - return url; - if (!transport_security_state_->ShouldUpgradeToSSL(url.host())) - return url; - - url::Replacements<char> replacements; - const char kNewScheme[] = "https"; - replacements.SetScheme(kNewScheme, url::Component(0, strlen(kNewScheme))); - return url.ReplaceComponents(replacements); -} - -// ---------------------- End IO methods. ------------------------------------- - -//----------------------------------------------------------------------------- - -void Predictor::PreconnectUrlOnUIThread( - const GURL& url, - const GURL& site_for_cookies, - UrlInfo::ResolutionMotivation motivation, - bool allow_credentials, - int count) { - bool privacy_mode = false; - int load_flags = net::LOAD_NORMAL; - - if (!allow_credentials) { - privacy_mode = true; - load_flags = net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES | - net::LOAD_DO_NOT_SEND_AUTH_DATA; - } - - content::BrowserContext::GetDefaultStoragePartition(profile_) - ->GetNetworkContext() - ->PreconnectSockets(count, url, load_flags, privacy_mode); -} - -bool Predictor::PredictorEnabled() const { - base::AutoLock lock(predictor_enabled_lock_); - return predictor_enabled_; -} - -void Predictor::SetPredictorEnabledForTest(bool predictor_enabled) { - base::AutoLock lock(predictor_enabled_lock_); - predictor_enabled_ = predictor_enabled; -} - -Predictor::HostNameQueue::HostNameQueue() { -} - -Predictor::HostNameQueue::~HostNameQueue() { -} - -void Predictor::HostNameQueue::Push(const GURL& url, - UrlInfo::ResolutionMotivation motivation) { - switch (motivation) { - case UrlInfo::STATIC_REFERAL_MOTIVATED: - case UrlInfo::LEARNED_REFERAL_MOTIVATED: - case UrlInfo::MOUSE_OVER_MOTIVATED: - rush_queue_.push(url); - break; - - default: - background_queue_.push(url); - break; - } -} - -bool Predictor::HostNameQueue::IsEmpty() const { - return rush_queue_.empty() && background_queue_.empty(); -} - -GURL Predictor::HostNameQueue::Pop() { - DCHECK(!IsEmpty()); - base::queue<GURL>* queue(rush_queue_.empty() ? &background_queue_ - : &rush_queue_); - GURL url(queue->front()); - queue->pop(); - return url; -} - -//----------------------------------------------------------------------------- -// Member definitions for InitialObserver class. - -InitialObserver::InitialObserver() = default; - -InitialObserver::~InitialObserver() = default; - -void InitialObserver::Append(const GURL& url, Predictor* predictor) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (kStartupResolutionCount <= first_navigations_.size()) - return; - - DCHECK(url.SchemeIsHTTPOrHTTPS()); - DCHECK_EQ(url, Predictor::CanonicalizeUrl(url)); - if (first_navigations_.find(url) == first_navigations_.end()) - first_navigations_[url] = base::TimeTicks::Now(); -} - -void InitialObserver::GetInitialDnsResolutionList( - base::ListValue* startup_list) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(startup_list); - DCHECK(startup_list->empty()); - DCHECK_EQ(0u, startup_list->GetSize()); - startup_list->AppendInteger(kPredictorStartupFormatVersion); - for (const auto& url_time : first_navigations_) { - DCHECK(url_time.first == Predictor::CanonicalizeUrl(url_time.first)); - startup_list->AppendString(url_time.first.spec()); - } -} - -//----------------------------------------------------------------------------- -// Helper functions -//----------------------------------------------------------------------------- - -// static -GURL Predictor::CanonicalizeUrl(const GURL& url) { - if (!url.has_host()) - return GURL::EmptyGURL(); - - std::string scheme; - if (url.has_scheme()) { - scheme = url.scheme(); - if (scheme != "http" && scheme != "https") - return GURL::EmptyGURL(); - if (url.has_port()) - return url.GetWithEmptyPath(); - } else { - scheme = "http"; - } - - // If we omit a port, it will default to 80 or 443 as appropriate. - std::string colon_plus_port; - if (url.has_port()) - colon_plus_port = ":" + url.port(); - - return GURL(scheme + "://" + url.host() + colon_plus_port); -} - -void SimplePredictor::InitNetworkPredictor(PrefService* user_prefs, - IOThread* io_thread, - net::URLRequestContextGetter* getter, - ProfileIOData* profile_io_data, - Profile* profile) { - // Empty function for unittests. -} - -void SimplePredictor::ShutdownOnUIThread() { - SetShutdown(true); -} - -bool SimplePredictor::CanPrefetchAndPrerender() const { return true; } -bool SimplePredictor::CanPreresolveAndPreconnect() const { return true; } - -} // namespace chrome_browser_net
diff --git a/chrome/browser/net/predictor.h b/chrome/browser/net/predictor.h deleted file mode 100644 index 9c1058d9..0000000 --- a/chrome/browser/net/predictor.h +++ /dev/null
@@ -1,537 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// A Predictor object is instantiated once in the browser process, and manages -// both preresolution of hostnames, as well as TCP/IP preconnection to expected -// subresources. -// Most hostname lists are provided by the renderer processes, and include URLs -// that *might* be used in the near future by the browsing user. One goal of -// this class is to cause the underlying DNS structure to lookup a hostname -// before it is really needed, and hence reduce latency in the standard lookup -// paths. -// Subresource relationships are usually acquired from the referrer field in a -// navigation. A subresource URL may be associated with a referrer URL. Later -// navigations may, if the likelihood of needing the subresource is high enough, -// cause this module to speculatively create a TCP/IP connection. If there is -// only a low likelihood, then a DNS pre-resolution operation may be performed. - -#ifndef CHROME_BROWSER_NET_PREDICTOR_H_ -#define CHROME_BROWSER_NET_PREDICTOR_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <map> -#include <memory> -#include <string> -#include <vector> - -#include "base/containers/mru_cache.h" -#include "base/containers/queue.h" -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "chrome/browser/net/prediction_options.h" -#include "chrome/browser/net/referrer.h" -#include "chrome/browser/net/timed_cache.h" -#include "chrome/browser/net/url_info.h" -#include "components/network_hints/common/network_hints_common.h" -#include "net/base/host_port_pair.h" -#include "url/gurl.h" - -class IOThread; -class PrefService; -class Profile; -class ProfileIOData; - -namespace base { -class ListValue; -} - -namespace net { -class HostResolver; -class SSLConfigService; -class ProxyResolutionService; -class TransportSecurityState; -class URLRequestContextGetter; -} - -namespace user_prefs { -class PrefRegistrySyncable; -} - -namespace chrome_browser_net { - -class InitialObserver; -typedef std::map<GURL, UrlInfo> Results; - -// An observer for testing. -class PredictorObserver { - public: - virtual ~PredictorObserver() {} - - virtual void OnPreconnectUrl(const GURL& original_url, - const GURL& site_for_cookies, - UrlInfo::ResolutionMotivation motivation, - int count) {} - virtual void OnLearnFromNavigation(const GURL& referring_url, - const GURL& target_url) {} - - virtual void OnDnsLookupFinished(const GURL& url, bool found) {} -}; - -// Predictor is constructed during Profile construction (on the UI thread), -// but it is destroyed on the IO thread when ProfileIOData goes away. All of -// its core state and functionality happens on the IO thread. -// The only UI methods are initialization / shutdown related (including -// preconnect initialization), convenience methods that internally forward -// calls to the IO thread, or internal functions that interface with the Network -// Service. -class Predictor { - public: - // A version number for prefs that are saved. This should be incremented when - // we change the format so that we discard old data. - static const int kPredictorReferrerVersion; - - // Given that the underlying Chromium resolver defaults to a total maximum of - // 8 paralell resolutions, we will avoid any chance of starving navigational - // resolutions by limiting the number of paralell speculative resolutions. - // This is used in the field trials and testing. - // TODO(jar): Move this limitation into the resolver. - static const size_t kMaxSpeculativeParallelResolves; - - // To control the congestion avoidance system, we need an estimate of how - // many speculative requests may arrive at once. Since we currently only - // keep 8 subresource names for each frame, we'll use that as our basis. - // Note that when scanning search results lists, we might actually get 10 at - // a time, and wikipedia can often supply (during a page scan) upwards of 50. - // In those odd cases, we may discard some of the later speculative requests - // mistakenly assuming that the resolutions took too long. - static const int kTypicalSpeculativeGroupSize; - - // The next constant specifies an amount of queueing delay that is - // "too large," and indicative of problems with resolutions (perhaps due to - // an overloaded router, or such). When we exceed this delay, congestion - // avoidance will kick in and all speculations in the queue will be discarded. - static const int kMaxSpeculativeResolveQueueDelayMs; - - // We don't bother learning to preconnect via a GET if the original URL - // navigation was so long ago, that a preconnection would have been dropped - // anyway. We believe most servers will drop the connection in 10 seconds, so - // we currently estimate this time-till-drop at 10 seconds. - // TODO(jar): We should do a persistent field trial to validate/optimize this. - static const int kMaxUnusedSocketLifetimeSecondsWithoutAGet; - - // The maximum size of the MRU cache of referrers. - static const int kMaxReferrers; - - explicit Predictor(bool predictor_enabled); - - virtual ~Predictor(); - - // This function is used to create a predictor. For testing, we can create - // a version which does a simpler shutdown. - // TODO(636128): This method should return a unique_ptr. - static Predictor* CreatePredictor(bool simple_shutdown); - - static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); - - // ------------- Start UI thread methods. - - virtual void InitNetworkPredictor(PrefService* user_prefs, - IOThread* io_thread, - net::URLRequestContextGetter* getter, - ProfileIOData* profile_io_data, - Profile* profile); - - // The Omnibox has proposed a given url to the user, and if it is a search - // URL, then it also indicates that this is preconnectable (i.e., we could - // preconnect to the search server). - void AnticipateOmniboxUrl(const GURL& url, bool preconnectable); - - // Preconnect a URL and all of its subresource domains. - void PreconnectUrlAndSubresources(const GURL& url, - const GURL& site_for_cookies); - - static std::vector<GURL> GetPredictedUrlListAtStartup( - PrefService* user_prefs); - - // Calls ClearPrefsOnUIThread and posts a task to the IO thread to - // DiscardAllResults. - void DiscardAllResultsAndClearPrefsOnUIThread(); - - // Clears the preferences used by the predictor. Must be called on the UI - // thread. - void ClearPrefsOnUIThread(); - - static void set_max_queueing_delay(int max_queueing_delay_ms); - - static void set_max_parallel_resolves(size_t max_parallel_resolves); - - virtual void ShutdownOnUIThread(); - - void UpdatePrefsOnUIThread(std::unique_ptr<base::ListValue> startup_list, - std::unique_ptr<base::ListValue> referral_list); - - // ------------- End UI thread methods. - - // ------------- Start IO thread methods. - - void WriteDnsPrefetchState(base::ListValue* startup_list, - base::ListValue* referral_list); - - // Cancel pending requests and prevent new ones from being made. - void Shutdown(); - - // In some circumstances, for privacy reasons, all results should be - // discarded. This method gracefully handles that activity. - // Destroy all our internal state, which shows what names we've looked up, and - // how long each has taken, etc. etc. We also destroy records of suggesses - // (cache hits etc.). - void DiscardAllResults(); - - // Add hostname(s) to the queue for processing. - void ResolveList(const std::vector<GURL>& urls, - UrlInfo::ResolutionMotivation motivation); - - void Resolve(const GURL& url, UrlInfo::ResolutionMotivation motivation); - - // Record details of a navigation so that we can preresolve the host name - // ahead of time the next time the users navigates to the indicated host. - // Should only be called when urls are distinct, and they should already be - // canonicalized to not have a path. - void LearnFromNavigation(const GURL& referring_url, const GURL& target_url); - - // Construct a ListValue object that contains all the data in the referrers_ - // so that it can be persisted in a pref. - void SerializeReferrers(base::ListValue* referral_list); - - // Process a ListValue that contains all the data from a previous reference - // list, as constructed by SerializeReferrers(), and add all the identified - // values into the current referrer list. - void DeserializeReferrers(const base::ListValue& referral_list); - - void DiscardInitialNavigationHistory(); - - void FinalizeInitializationOnIOThread( - const std::vector<GURL>& urls_to_prefetch, - std::unique_ptr<base::ListValue> referral_list, - IOThread* io_thread, - ProfileIOData* profile_io_data); - - // During startup, we learn what the first N urls visited are, and then - // resolve the associated hosts ASAP during our next startup. - void LearnAboutInitialNavigation(const GURL& url); - - // Renderer bundles up list and sends to this browser API via IPC. - // TODO(csharrison): Use a GURL vector instead to include port and scheme. - void DnsPrefetchList(const std::vector<std::string>& hostnames); - - // May be called from either the IO or UI thread and will PostTask - // to the IO thread if necessary. - void DnsPrefetchMotivatedList(const std::vector<GURL>& urls, - UrlInfo::ResolutionMotivation motivation); - - // Called from the UI thread in response to the load event. - void SaveStateForNextStartup(); - - // ------------- End IO thread methods. - - // The following methods may be called on either the IO or UI threads. - - // Calls |PreconnectUrlOnIOThread()|, posting it to the IO thread if - // necessary. - void PreconnectUrl(const GURL& url, - const GURL& site_for_cookies, - UrlInfo::ResolutionMotivation motivation, - bool allow_credentials, - int count); - - // Instigate pre-connection to any URLs, or pre-resolution of related host, - // that we predict will be needed after this navigation (typically - // more-embedded resources on a page). This method will actually post a task - // to do the actual work, so as not to jump ahead of the frame navigation that - // instigated this activity. - void PredictFrameSubresources(const GURL& url, const GURL& site_for_cookies); - - // Put URL in canonical form, including a scheme, host, and port. - // Returns GURL::EmptyGURL() if the scheme is not http/https or if the url - // cannot be otherwise canonicalized. - static GURL CanonicalizeUrl(const GURL& url); - - // Used for testing. - void SetTransportSecurityState( - net::TransportSecurityState* transport_security_state) { - transport_security_state_ = transport_security_state; - } - // Used for testing. - size_t max_concurrent_dns_lookups() const { - return max_concurrent_dns_lookups_; - } - // Used for testing. - void SetShutdown(bool shutdown) { - shutdown_ = shutdown; - } - // Used for testing. - void SetObserver(PredictorObserver* observer) { - observer_ = observer; - } - - ProfileIOData* profile_io_data() const { - return profile_io_data_; - } - - bool PredictorEnabled() const; - - // Used only for testing. Overrides command line flag to disable the - // predictor, which is added in the browser test fixture. - void SetPredictorEnabledForTest(bool predictor_enabled); - - net::URLRequestContextGetter* url_request_context_getter_for_test() { - return url_request_context_getter_.get(); - } - - TimedCache* timed_cache() { return timed_cache_.get(); } - - base::WeakPtr<Predictor> GetUIWeakPtr() { - return ui_weak_factory_->GetWeakPtr(); - } - - private: - FRIEND_TEST_ALL_PREFIXES(PredictorTest, PriorityQueuePushPopTest); - FRIEND_TEST_ALL_PREFIXES(PredictorTest, PriorityQueueReorderTest); - FRIEND_TEST_ALL_PREFIXES(PredictorTest, NoProxyService); - FRIEND_TEST_ALL_PREFIXES(PredictorTest, ProxyDefinitelyEnabled); - FRIEND_TEST_ALL_PREFIXES(PredictorTest, ProxyDefinitelyNotEnabled); - FRIEND_TEST_ALL_PREFIXES(PredictorTest, ProxyMaybeEnabled); - friend class WaitForResolutionHelper; // For testing. - friend class PredictorBrowserTest; - - // A simple priority queue for handling host names. - // Some names that are queued up have |motivation| that requires very rapid - // handling. For example, a sub-resource name lookup MUST be done before the - // actual sub-resource is fetched. In contrast, a name that was speculatively - // noted in a page has to be resolved before the user "gets around to" - // clicking on a link. By tagging (with a motivation) each push we make into - // this FIFO queue, the queue can re-order the more important names to service - // them sooner (relative to some low priority background resolutions). - class HostNameQueue { - public: - HostNameQueue(); - ~HostNameQueue(); - void Push(const GURL& url, - UrlInfo::ResolutionMotivation motivation); - bool IsEmpty() const; - GURL Pop(); - - private: - // The names in the queue that should be serviced (popped) ASAP. - base::queue<GURL> rush_queue_; - // The names in the queue that should only be serviced when rush_queue is - // empty. - base::queue<GURL> background_queue_; - - DISALLOW_COPY_AND_ASSIGN(HostNameQueue); - }; - - // A map that is keyed with the host/port that we've learned were the cause - // of loading additional URLs. The list of additional targets is held - // in a Referrer instance, which is a value in this map. - typedef base::MRUCache<GURL, Referrer> Referrers; - - // Depending on the expected_subresource_use_, we may either make a TCP/IP - // preconnection, or merely pre-resolve the hostname via DNS (or even do - // nothing). The following are the threasholds for taking those actions. - static const double kPreconnectWorthyExpectedValue; - static const double kDNSPreresolutionWorthyExpectedValue; - static const double kDiscardableExpectedValue; - - // These two members call the appropriate global functions in - // prediction_options.cc depending on which thread they are called on. - virtual bool CanPrefetchAndPrerender() const; - virtual bool CanPreresolveAndPreconnect() const; - - // ------------- Start IO thread methods. - - void PreconnectUrlOnIOThread(const GURL& original_url, - const GURL& site_for_cookies, - UrlInfo::ResolutionMotivation motivation, - bool allow_credentials, - int count); - - // Perform actual resolution or preconnection to subresources now. This is - // an internal worker method that is reached via a post task from - // PredictFrameSubresources(). - void PrepareFrameSubresources(const GURL& url, const GURL& site_for_cookies); - - // Access method for use by async lookup request to pass resolution result. - void OnLookupFinished(const GURL& url, int result); - - // Underlying method for both async and synchronous lookup to update state. - void LookupFinished(const GURL& url, bool found); - - // Queues hostname for resolution. If the proxy advisor is enabled, and - // |url| is likely to be proxied, the hostname will not be queued as the - // browser is not expected to fetch it directly. - void AppendToResolutionQueue(const GURL& url, - UrlInfo::ResolutionMotivation motivation); - - // Check to see if too much queuing delay has been noted for the given info, - // which indicates that there is "congestion" or growing delay in handling the - // resolution of names. Rather than letting this congestion potentially grow - // without bounds, we abandon our queued efforts at pre-resolutions in such a - // case. - // To do this, we will recycle |info_it|, as well as all queued items. - // We can't do anything about the resolutions we've already sent off for - // processing on another thread, so we just let them complete. On a slow - // system, subject to congestion, this will greatly reduce the number of - // resolutions done, but it will assure that any resolutions that are done, - // are in a timely and hence potentially helpful manner. - bool CongestionControlPerformed(Results::iterator info_it); - - // Take lookup requests from work_queue_ and tell HostResolver to look them up - // asynchronously, provided we don't exceed concurrent resolution limit. - void StartSomeQueuedResolutions(); - - // If we can determine immediately (i.e. synchronously) that requests to this - // URL would likely go through a proxy, then return true. Otherwise, return - // false. This is used to avoid issuing DNS requests when a fixed proxy - // configuration is in place, which improves efficiency, and is also important - // if the unproxied DNS may contain incorrect entries. - bool WouldLikelyProxyURL(const GURL& url); - - // Applies the HSTS redirect for |url|, if any. - GURL GetHSTSRedirectOnIOThread(const GURL& url); - - // ------------- End IO thread methods. - - void PreconnectUrlOnUIThread(const GURL& url, - const GURL& site_for_cookies, - UrlInfo::ResolutionMotivation motivation, - bool allow_credentials, - int count); - - std::unique_ptr<InitialObserver> initial_observer_; - - // Reference to URLRequestContextGetter from the Profile which owns the - // predictor. Used by Preconnect. - scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; - - // Status of speculative DNS resolution and speculative TCP/IP connection - // feature. This is true if features::kNetworkPredicton is enabled and - // LoadingPredictor's preconnect is disabled. - // Protected by |preconnect_enabled_lock_|, which is used by tests to bypass - // the command line flags. - bool predictor_enabled_; - - // This is set by InitNetworkPredictor and used for calling - // CanPrefetchAndPrerenderUI and CanPreresolveAndPreconnectUI. - PrefService* user_prefs_; - - // This is set by InitNetworkPredictor and used for calling - // CanPrefetchAndPrerenderIO and CanPreresolveAndPreconnectIO. - ProfileIOData* profile_io_data_; - - // This is set by InitNetworkPredictor and used for calling into the Network - // Context. - Profile* profile_; - - // work_queue_ holds a list of names we need to look up. - HostNameQueue work_queue_; - - // results_ contains information for existing/prior prefetches. - Results results_; - - size_t num_pending_lookups_; - - // For testing, to verify that we don't exceed the limit. - size_t peak_pending_lookups_; - - // When true, we don't make new lookup requests. - bool shutdown_; - - // The number of concurrent speculative lookups currently allowed to be sent - // to the resolver. Any additional lookups will be queued to avoid exceeding - // this value. The queue is a priority queue that will accelerate - // sub-resource speculation, and retard resolutions suggested by page scans. - const size_t max_concurrent_dns_lookups_; - - // The maximum queueing delay that is acceptable before we enter congestion - // reduction mode, and discard all queued (but not yet assigned) resolutions. - const base::TimeDelta max_dns_queue_delay_; - - // The TransportSecurityState instance we query HSTS redirects from. - net::TransportSecurityState* transport_security_state_; - - // The SSLConfigService we query SNI support from (used in querying HSTS - // redirects). - net::SSLConfigService* ssl_config_service_; - - // The ProxyResolutionService, used to determine whether preresolve is useful. - net::ProxyResolutionService* proxy_resolution_service_; - - // Most recent suggestion from Omnibox provided via AnticipateOmniboxUrl(). - std::string last_omnibox_host_; - - // The time when the last preresolve was done for last_omnibox_host_. - base::TimeTicks last_omnibox_preresolve_; - - // The number of consecutive requests to AnticipateOmniboxUrl() that suggested - // preconnecting (because it was to a search service). - int consecutive_omnibox_preconnect_count_; - - // The time when the last preconnection was requested to a search service. - base::TimeTicks last_omnibox_preconnect_; - - // For each URL that we might navigate to (that we've "learned about") - // we have a Referrer list. Each Referrer list has all hostnames we might - // need to pre-resolve or pre-connect to when there is a navigation to the - // orginial hostname. - Referrers referrers_; - - // An observer for testing. - PredictorObserver* observer_; - - std::unique_ptr<TimedCache> timed_cache_; - - // TODO(csharrison): It is not great that two weak pointer factories are - // needed in this class. Let's split it into two classes that live on each - // thread. - // - // Weak factory for weak pointers that should be dereferenced on the IO - // thread. - std::unique_ptr<base::WeakPtrFactory<Predictor>> io_weak_factory_; - - // Weak factory for weak pointers that should be dereferenced on the UI - // thread. - std::unique_ptr<base::WeakPtrFactory<Predictor>> ui_weak_factory_; - - // Protects |predictor_enabled_|. - mutable base::Lock predictor_enabled_lock_; - - DISALLOW_COPY_AND_ASSIGN(Predictor); -}; - -// This version of the predictor is used for testing. -class SimplePredictor : public Predictor { - public: - explicit SimplePredictor(bool predictor_enabled) - : Predictor(predictor_enabled) {} - ~SimplePredictor() override {} - void InitNetworkPredictor(PrefService* user_prefs, - IOThread* io_thread, - net::URLRequestContextGetter* getter, - ProfileIOData* profile_io_data, - Profile* profile) override; - void ShutdownOnUIThread() override; - - private: - // These member functions return True for unittests. - bool CanPrefetchAndPrerender() const override; - bool CanPreresolveAndPreconnect() const override; -}; - -} // namespace chrome_browser_net - -#endif // CHROME_BROWSER_NET_PREDICTOR_H_
diff --git a/chrome/browser/net/predictor_browsertest.cc b/chrome/browser/net/predictor_browsertest.cc deleted file mode 100644 index 86168302..0000000 --- a/chrome/browser/net/predictor_browsertest.cc +++ /dev/null
@@ -1,1682 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include <algorithm> -#include <map> -#include <memory> -#include <set> - -#include "base/base64.h" -#include "base/bind.h" -#include "base/callback.h" -#include "base/command_line.h" -#include "base/json/json_string_value_serializer.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/stl_util.h" -#include "base/synchronization/lock.h" -#include "base/test/scoped_feature_list.h" -#include "base/threading/thread_task_runner_handle.h" -#include "build/build_config.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/browsing_data/browsing_data_helper.h" -#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h" -#include "chrome/browser/net/predictor.h" -#include "chrome/browser/predictors/loading_predictor_config.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/chrome_features.h" -#include "chrome/common/pref_names.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" -#include "components/prefs/pref_service.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/browsing_data_remover.h" -#include "content/public/common/content_switches.h" -#include "content/public/test/browser_test_utils.h" -#include "content/public/test/test_utils.h" -#include "net/base/host_port_pair.h" -#include "net/base/ip_endpoint.h" -#include "net/base/net_errors.h" -#include "net/dns/host_resolver_proc.h" -#include "net/dns/mock_host_resolver.h" -#include "net/http/http_transaction_factory.h" -#include "net/socket/stream_socket.h" -#include "net/test/embedded_test_server/embedded_test_server.h" -#include "net/test/embedded_test_server/embedded_test_server_connection_listener.h" -#include "net/test/embedded_test_server/http_request.h" -#include "net/test/embedded_test_server/http_response.h" -#include "net/test/url_request/url_request_failed_job.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_getter.h" -#include "net/url_request/url_request_filter.h" -#include "net/url_request/url_request_interceptor.h" -#include "net/url_request/url_request_test_job.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "url/gurl.h" -#include "url/url_constants.h" - -using content::BrowserThread; -using testing::HasSubstr; - -namespace { - -net::URLRequestJob* CreateEmptyBodyRequestJob(net::URLRequest* request, - net::NetworkDelegate* delegate) { - const char kPlainTextHeaders[] = - "HTTP/1.1 200 OK\n" - "Content-Type: text/plain\n" - "Access-Control-Allow-Origin: *\n" - "\n"; - return new net::URLRequestTestJob(request, delegate, kPlainTextHeaders, "", - true); -} - -net::URLRequestJob* CreateRedirectRequestJob(std::string location, - net::URLRequest* request, - net::NetworkDelegate* delegate) { - char kPlainTextHeaders[] = - "HTTP/1.1 302 \n" - "Location: %s\n" - "Access-Control-Allow-Origin: *\n" - "\n"; - return new net::URLRequestTestJob( - request, delegate, - base::StringPrintf(kPlainTextHeaders, location.c_str()), "", true); -} - -// Override the test server to redirect requests matching some path. This is -// used because the predictor only learns simple redirects with a path of "/" -std::unique_ptr<net::test_server::HttpResponse> RedirectForPathHandler( - const std::string& path, - const GURL& redirect_url, - const net::test_server::HttpRequest& request) { - if (request.GetURL().path() != path) - return nullptr; - std::unique_ptr<net::test_server::BasicHttpResponse> response( - new net::test_server::BasicHttpResponse); - response->set_code(net::HTTP_MOVED_PERMANENTLY); - response->AddCustomHeader("Location", redirect_url.spec()); - return std::move(response); -} - -const char kChromiumUrl[] = "http://chromium.org"; -const char kInvalidLongUrl[] = - "http://" - "illegally-long-hostname-over-255-characters-should-not-send-an-ipc-" - "message-to-the-browser-" - "00000000000000000000000000000000000000000000000000000000000000000000000000" - "00000000000000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000.org"; - -// Returns a motivation_list if we can find one for the given motivating_host -// (or nullptr if a match is not found). -static const base::ListValue* FindSerializationMotivation( - const GURL& motivation, - const base::ListValue* referral_list) { - CHECK_LT(0u, referral_list->GetSize()); // Room for version. - int format_version = -1; - CHECK(referral_list->GetInteger(0, &format_version)); - CHECK_EQ(chrome_browser_net::Predictor::kPredictorReferrerVersion, - format_version); - const base::ListValue* motivation_list = nullptr; - for (size_t i = 1; i < referral_list->GetSize(); ++i) { - referral_list->GetList(i, &motivation_list); - std::string existing_spec; - EXPECT_TRUE(motivation_list->GetString(0, &existing_spec)); - if (motivation == GURL(existing_spec)) - return motivation_list; - } - return nullptr; -} - -// Gets notified by the EmbeddedTestServer on incoming connections being -// accepted or read from, keeps track of them and exposes that info to -// the tests. -// A port being reused is currently considered an error. If a test -// needs to verify multiple connections are opened in sequence, that will need -// to be changed. -class ConnectionListener - : public net::test_server::EmbeddedTestServerConnectionListener { - public: - ConnectionListener() - : task_runner_(base::ThreadTaskRunnerHandle::Get()), - num_accepted_connections_needed_(0), - num_accepted_connections_loop_(nullptr) {} - - ~ConnectionListener() override {} - - // Get called from the EmbeddedTestServer thread to be notified that - // a connection was accepted. - void AcceptedSocket(const net::StreamSocket& connection) override { - base::AutoLock lock(lock_); - uint16_t socket = GetPort(connection); - EXPECT_TRUE(sockets_.find(socket) == sockets_.end()); - - sockets_[socket] = SOCKET_ACCEPTED; - task_runner_->PostTask(FROM_HERE, accept_loop_.QuitClosure()); - CheckAccepted(); - } - - // Get called from the EmbeddedTestServer thread to be notified that - // a connection was read from. - void ReadFromSocket(const net::StreamSocket& connection, int rv) override { - // Don't log a read if no data was transferred. This case often happens if - // the sockets of the test server are being flushed and disconnected. - if (rv <= 0) - return; - base::AutoLock lock(lock_); - uint16_t socket = GetPort(connection); - EXPECT_FALSE(sockets_.find(socket) == sockets_.end()); - - sockets_[socket] = SOCKET_READ_FROM; - task_runner_->PostTask(FROM_HERE, read_loop_.QuitClosure()); - } - - // Returns the number of sockets that were accepted by the server. - size_t GetAcceptedSocketCount() const { - base::AutoLock lock(lock_); - return sockets_.size(); - } - - // Returns the number of sockets that were read from by the server. - size_t GetReadSocketCount() const { - base::AutoLock lock(lock_); - size_t read_sockets = 0; - for (const auto& socket : sockets_) { - if (socket.second == SOCKET_READ_FROM) - ++read_sockets; - } - return read_sockets; - } - - void WaitUntilFirstConnectionAccepted() { accept_loop_.Run(); } - void WaitUntilFirstConnectionRead() { read_loop_.Run(); } - - // The UI thread will wait for exactly |n| items in |sockets_|. |n| must be - // greater than 0. - void WaitForAcceptedConnectionsOnUI(size_t num_connections) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(!num_accepted_connections_loop_); - DCHECK_GT(num_connections, 0u); - base::RunLoop run_loop; - { - base::AutoLock lock(lock_); - EXPECT_GE(num_connections, sockets_.size()); - num_accepted_connections_loop_ = &run_loop; - num_accepted_connections_needed_ = num_connections; - CheckAccepted(); - } - // Note that the previous call to CheckAccepted can quit this run loop - // before this call, which will make this call a no-op. - run_loop.Run(); - - // Grab the mutex again and make sure that the number of accepted sockets is - // indeed |num_connections|. - base::AutoLock lock(lock_); - EXPECT_EQ(num_connections, sockets_.size()); - } - - void CheckAcceptedLocked() { - base::AutoLock lock(lock_); - CheckAccepted(); - } - - // Helper function to stop the waiting for sockets to be accepted for - // WaitForAcceptedConnectionsOnUI. |num_accepted_connections_loop_| spins - // until |num_accepted_connections_needed_| sockets are accepted by the test - // server. The values will be null/0 if the loop is not running. - void CheckAccepted() { - lock_.AssertAcquired(); - // |num_accepted_connections_loop_| null implies - // |num_accepted_connections_needed_| == 0. - DCHECK(num_accepted_connections_loop_ || - num_accepted_connections_needed_ == 0); - if (!num_accepted_connections_loop_ || - num_accepted_connections_needed_ != sockets_.size()) { - return; - } - - task_runner_->PostTask(FROM_HERE, - num_accepted_connections_loop_->QuitClosure()); - num_accepted_connections_needed_ = 0; - num_accepted_connections_loop_ = nullptr; - } - - void ResetCounts() { - base::AutoLock lock(lock_); - sockets_.clear(); - } - - private: - static uint16_t GetPort(const net::StreamSocket& connection) { - // Get the remote port of the peer, since the local port will always be the - // port the test server is listening on. This isn't strictly correct - it's - // possible for multiple peers to connect with the same remote port but - // different remote IPs - but the tests here assume that connections to the - // test server (running on localhost) will always come from localhost, and - // thus the peer port is all thats needed to distinguish two connections. - // This also would be problematic if the OS reused ports, but that's not - // something to worry about for these tests. - net::IPEndPoint address; - EXPECT_EQ(net::OK, connection.GetPeerAddress(&address)); - return address.port(); - } - - enum SocketStatus { SOCKET_ACCEPTED, SOCKET_READ_FROM }; - - base::RunLoop accept_loop_; - base::RunLoop read_loop_; - - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - - // This lock protects all the members below, which each are used on both the - // IO and UI thread. Members declared after the lock are protected by it. - mutable base::Lock lock_; - typedef std::map<uint16_t, SocketStatus> SocketContainer; - SocketContainer sockets_; - - // If |num_accepted_connections_needed_| is non zero, then the object is - // waiting for |num_accepted_connections_needed_| sockets to be accepted - // before quitting the |num_accepted_connections_loop_|. - size_t num_accepted_connections_needed_; - base::RunLoop* num_accepted_connections_loop_; - - DISALLOW_COPY_AND_ASSIGN(ConnectionListener); -}; - -// This class intercepts URLRequests and responds with the URLRequestJob* -// callback provided by the constructor. Note that the port of the URL must -// match the port given in the constructor. -class MatchingPortRequestInterceptor : public net::URLRequestInterceptor { - public: - typedef base::Callback<net::URLRequestJob*(net::URLRequest*, - net::NetworkDelegate*)> - CreateJobCallback; - - MatchingPortRequestInterceptor( - int port, - base::Callback<net::URLRequestJob*(net::URLRequest*, - net::NetworkDelegate*)> - create_job_callback) - : create_job_callback_(create_job_callback), port_(port) {} - ~MatchingPortRequestInterceptor() override {} - - private: - net::URLRequestJob* MaybeInterceptRequest( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override { - if (request->url().EffectiveIntPort() != port_) - return nullptr; - return create_job_callback_.Run(request, network_delegate); - } - - const CreateJobCallback create_job_callback_; - const int port_; - - DISALLOW_COPY_AND_ASSIGN(MatchingPortRequestInterceptor); -}; - -// This class is owned by the test harness, and listens to Predictor events. It -// takes as input the source host and cross site host used by the test harness, -// and asserts that only valid preconnects and learning can occur between the -// two. -class CrossSitePredictorObserver - : public chrome_browser_net::PredictorObserver { - public: - CrossSitePredictorObserver(const GURL& source_host, - const GURL& cross_site_host) - : source_host_(source_host), - cross_site_host_(cross_site_host), - cross_site_learned_(0), - cross_site_preconnected_(0), - same_site_preconnected_(0), - dns_run_loop_(nullptr), - strict_(true) {} - - void OnPreconnectUrl( - const GURL& original_url, - const GURL& site_for_cookies, - chrome_browser_net::UrlInfo::ResolutionMotivation motivation, - int count) override { - base::AutoLock lock(lock_); - preconnect_url_attempts_.insert(original_url); - if (original_url == cross_site_host_) { - cross_site_preconnected_ = std::max(cross_site_preconnected_, count); - } else if (original_url == source_host_) { - same_site_preconnected_ = std::max(same_site_preconnected_, count); - } else if (strict_) { - ADD_FAILURE() << "Preconnected " << original_url - << " when should only be preconnecting the source host: " - << source_host_ - << " or the cross site host: " << cross_site_host_; - } - } - - void OnLearnFromNavigation(const GURL& referring_url, - const GURL& target_url) override { - base::AutoLock lock(lock_); - // There are three possibilities: - // source => target - // source => source - // target => target - if (referring_url == source_host_ && target_url == cross_site_host_) { - cross_site_learned_++; - } else if (referring_url == source_host_ && target_url == source_host_) { - // Same site learned. Branch retained for clarity. - } else if (strict_ && - !(referring_url == cross_site_host_ && - target_url == cross_site_host_)) { - ADD_FAILURE() << "Learned " << referring_url << " => " << target_url - << " when should only be learning the source host: " - << source_host_ - << " or the cross site host: " << cross_site_host_; - } - } - - void OnDnsLookupFinished(const GURL& url, bool found) override { - base::AutoLock lock(lock_); - if (found) { - successful_dns_lookups_.insert(url); - } else { - unsuccessful_dns_lookups_.insert(url); - } - CheckForWaitingLoop(); - } - - void ResetCounts() { - base::AutoLock lock(lock_); - cross_site_learned_ = 0; - cross_site_preconnected_ = 0; - same_site_preconnected_ = 0; - } - - int CrossSiteLearned() { - base::AutoLock lock(lock_); - return cross_site_learned_; - } - - int CrossSitePreconnected() { - base::AutoLock lock(lock_); - return cross_site_preconnected_; - } - - int SameSitePreconnected() { - base::AutoLock lock(lock_); - return same_site_preconnected_; - } - - // Spins a run loop until |url| is added to one of the lookup maps. - void WaitUntilHostLookedUp(const GURL& url) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - base::RunLoop run_loop; - { - base::AutoLock lock(lock_); - DCHECK(waiting_on_dns_.is_empty()); - DCHECK(!dns_run_loop_); - waiting_on_dns_ = url; - dns_run_loop_ = &run_loop; - CheckForWaitingLoop(); - } - run_loop.Run(); - } - - bool HasHostBeenLookedUpLocked(const GURL& url) { - lock_.AssertAcquired(); - return base::ContainsKey(successful_dns_lookups_, url) || - base::ContainsKey(unsuccessful_dns_lookups_, url); - } - - bool HasHostBeenLookedUp(const GURL& url) { - base::AutoLock lock(lock_); - return HasHostBeenLookedUpLocked(url); - } - - bool HasHostAttemptedToPreconnect(const GURL& url) { - base::AutoLock lock(lock_); - return base::ContainsKey(preconnect_url_attempts_, url); - } - - void CheckForWaitingLoop() { - lock_.AssertAcquired(); - if (waiting_on_dns_.is_empty()) - return; - if (!HasHostBeenLookedUpLocked(waiting_on_dns_)) - return; - DCHECK(dns_run_loop_); - DCHECK(task_runner_); - waiting_on_dns_ = GURL(); - task_runner_->PostTask(FROM_HERE, dns_run_loop_->QuitClosure()); - dns_run_loop_ = nullptr; - } - - size_t TotalHostsLookedUp() { - base::AutoLock lock(lock_); - return successful_dns_lookups_.size() + unsuccessful_dns_lookups_.size(); - } - - // Note: this method expects the URL to have been looked up. - bool HostFound(const GURL& url) { - base::AutoLock lock(lock_); - EXPECT_TRUE(HasHostBeenLookedUpLocked(url)) << "Expected to have looked up " - << url.spec(); - return base::ContainsKey(successful_dns_lookups_, url); - } - - void set_task_runner( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - task_runner_.swap(task_runner); - } - - // Optionally allows the object to observe preconnects / learning from other - // hosts. - void SetStrict(bool strict) { - base::AutoLock lock(lock_); - strict_ = strict; - } - - private: - const GURL source_host_; - const GURL cross_site_host_; - - GURL waiting_on_dns_; - - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - - // Protects all following members. They are read and updated from different - // threads. - base::Lock lock_; - - int cross_site_learned_; - int cross_site_preconnected_; - int same_site_preconnected_; - - std::set<GURL> preconnect_url_attempts_; - std::set<GURL> successful_dns_lookups_; - std::set<GURL> unsuccessful_dns_lookups_; - base::RunLoop* dns_run_loop_; - - // This member can be set to optionally allow url learning other than from - // source => source, source => target, or target => target. It will also allow - // preconnects to other hosts. - bool strict_; - - DISALLOW_COPY_AND_ASSIGN(CrossSitePredictorObserver); -}; - -} // namespace - -namespace chrome_browser_net { - -class PredictorBrowserTest : public InProcessBrowserTest { - public: - PredictorBrowserTest() - : startup_url_("http://host1/"), - referring_url_("http://host2/"), - target_url_("http://host3/"), - rule_based_resolver_proc_(new net::RuleBasedHostResolverProc(nullptr)), - cross_site_test_server_(new net::EmbeddedTestServer()) { - // The predictor should be disabled until we set everything up. - std::vector<base::Feature> enabled_features = {}; - std::vector<base::Feature> disabled_features = { - features::kNetworkPrediction, - predictors::kSpeculativePreconnectFeature}; - scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); - rule_based_resolver_proc_->AddRuleWithLatency("www.example.test", - "127.0.0.1", 50); - rule_based_resolver_proc_->AddRuleWithLatency("gmail.google.com", - "127.0.0.1", 70); - rule_based_resolver_proc_->AddRuleWithLatency("mail.google.com", - "127.0.0.1", 44); - rule_based_resolver_proc_->AddRuleWithLatency("gmail.com", "127.0.0.1", 63); - rule_based_resolver_proc_->AddSimulatedFailure("*.notfound"); - rule_based_resolver_proc_->AddRuleWithLatency( - "slow*.google.com", "127.0.0.1", - Predictor::kMaxSpeculativeResolveQueueDelayMs + 300); - rule_based_resolver_proc_->AddRuleWithLatency("delay.google.com", - "127.0.0.1", 1000 * 60); - } - - ~PredictorBrowserTest() override {} - - protected: - void SetUpInProcessBrowserTestFixture() override { - scoped_host_resolver_proc_.reset(new net::ScopedDefaultHostResolverProc( - rule_based_resolver_proc_.get())); - } - - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitch( - switches::kEnableExperimentalWebPlatformFeatures); - } - - void SetUpOnMainThread() override { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - task_runner_ = base::ThreadTaskRunnerHandle::Get(); - cross_site_test_server()->ServeFilesFromSourceDirectory( - "chrome/test/data/"); - - connection_listener_.reset(new ConnectionListener()); - cross_site_connection_listener_.reset(new ConnectionListener()); - embedded_test_server()->SetConnectionListener(connection_listener_.get()); - cross_site_test_server()->SetConnectionListener( - cross_site_connection_listener_.get()); - ASSERT_TRUE(cross_site_test_server()->Start()); - - embedded_test_server()->RegisterRequestHandler( - base::Bind(&RedirectForPathHandler, "/", - cross_site_test_server()->GetURL("/title1.html"))); - - ASSERT_TRUE(embedded_test_server()->Start()); - - predictor()->SetPredictorEnabledForTest(true); - InstallPredictorObserver(embedded_test_server()->base_url(), - cross_site_test_server()->base_url()); - observer()->set_task_runner(task_runner_); - StartInterceptingCrossSiteOnUI(); - } - - static void StartInterceptingHostWithCreateJobCallback( - const GURL& url, - const MatchingPortRequestInterceptor::CreateJobCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( - url.scheme(), url.host(), - std::make_unique<MatchingPortRequestInterceptor>(url.EffectiveIntPort(), - callback)); - } - - static void StopInterceptingHost(const GURL& url) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(url.scheme(), - url.host()); - } - - // Intercepts all requests to the specified host and returns a response with - // an empty body. Needed to prevent requests from actually going to the test - // server, to avoid any races related to socket accounting. Note, the - // interceptor also looks at the port, to differentiate between the - // two test servers. - void StartInterceptingCrossSiteOnUI() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::BindOnce( - &PredictorBrowserTest::StartInterceptingHostWithCreateJobCallback, - cross_site_test_server()->base_url(), - base::Bind(&CreateEmptyBodyRequestJob))); - } - - void StopInterceptingCrossSiteOnUI() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::BindOnce(&PredictorBrowserTest::StopInterceptingHost, - cross_site_test_server()->base_url())); - } - - void TearDownOnMainThread() override { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); - } - - // Navigates to a data URL containing the given content, with a MIME type of - // text/html. - void NavigateToDataURLWithContent(const std::string& content) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - std::string encoded_content; - base::Base64Encode(content, &encoded_content); - std::string data_uri_content = "data:text/html;base64," + encoded_content; - ui_test_utils::NavigateToURL(browser(), GURL(data_uri_content)); - } - - void TearDownInProcessBrowserTestFixture() override { - scoped_host_resolver_proc_.reset(); - } - - void LearnAboutInitialNavigation(const GURL& url) { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&Predictor::LearnAboutInitialNavigation, - base::Unretained(predictor()), url)); - content::RunAllPendingInMessageLoop(BrowserThread::IO); - } - - void LearnFromNavigation(const GURL& referring_url, const GURL& target_url) { - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::BindOnce(&Predictor::LearnFromNavigation, - base::Unretained(predictor()), - referring_url, target_url)); - content::RunAllPendingInMessageLoop(BrowserThread::IO); - } - - void PrepareFrameSubresources(const GURL& url) { - predictor()->PredictFrameSubresources(url, GURL()); - } - - void GetListFromPrefsAsString(const char* list_path, - std::string* value_as_string) const { - PrefService* prefs = browser()->profile()->GetPrefs(); - const base::ListValue* list_value = prefs->GetList(list_path); - JSONStringValueSerializer serializer(value_as_string); - serializer.Serialize(*list_value); - } - - void WaitUntilHostsLookedUp(const std::vector<GURL>& names) { - for (const GURL& url : names) - observer()->WaitUntilHostLookedUp(url); - } - - void FloodResolveRequestsOnUIThread(const std::vector<GURL>& names) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&PredictorBrowserTest::FloodResolveRequests, - base::Unretained(this), names)); - } - - void FloodResolveRequests(const std::vector<GURL>& names) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - for (int i = 0; i < 10; i++) { - predictor()->DnsPrefetchMotivatedList(names, - UrlInfo::PAGE_SCAN_MOTIVATED); - } - } - - net::EmbeddedTestServer* cross_site_test_server() { - return cross_site_test_server_.get(); - } - - Predictor* predictor() { return browser()->profile()->GetNetworkPredictor(); } - - void InstallPredictorObserver(const GURL& source_host, - const GURL& cross_site_host) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - observer_.reset( - new CrossSitePredictorObserver(source_host, cross_site_host)); - base::RunLoop run_loop; - BrowserThread::PostTaskAndReply( - BrowserThread::IO, FROM_HERE, - base::BindOnce( - &PredictorBrowserTest::InstallPredictorObserverOnIOThread, - base::Unretained(this), base::Unretained(predictor())), - run_loop.QuitClosure()); - run_loop.Run(); - } - - void InstallPredictorObserverOnIOThread( - chrome_browser_net::Predictor* predictor) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - predictor->SetObserver(observer_.get()); - } - - // Note: For many of the tests to get to a "clean slate" mid run, they must - // flush sockets on both the client and server. - void FlushClientSockets() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - predictor() - ->url_request_context_getter_for_test() - ->GetURLRequestContext() - ->http_transaction_factory() - ->GetSession() - ->CloseAllConnections(); - } - - void FlushClientSocketsOnUIThread() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - base::RunLoop run_loop; - BrowserThread::PostTaskAndReply( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&PredictorBrowserTest::FlushClientSockets, - base::Unretained(this)), - run_loop.QuitClosure()); - run_loop.Run(); - } - - void FlushServerSocketsOnUIThread(net::EmbeddedTestServer* test_server) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - EXPECT_TRUE(test_server->FlushAllSocketsAndConnectionsOnUIThread()); - } - - // Note this method also expects that all the urls (found or not) were looked - // up. - void ExpectFoundUrls(const std::vector<GURL>& found_names, - const std::vector<GURL>& not_found_names) { - for (const auto& name : found_names) { - EXPECT_TRUE(observer()->HostFound(name)) << "Expected to have found " - << name.spec(); - } - for (const auto& name : not_found_names) { - EXPECT_FALSE(observer()->HostFound(name)) << "Did not expect to find " - << name.spec(); - } - } - - // This method verifies that |url| is in the predictor's |results_| map. This - // is used for pending lookups. - void ExpectUrlLookupIsInProgressOnUIThread(const GURL& url) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&PredictorBrowserTest::ExpectUrlLookupIsInProgress, - base::Unretained(this), url)); - } - - void ExpectUrlLookupIsInProgress(const GURL& url) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - EXPECT_TRUE(base::ContainsKey(predictor()->results_, url)); - } - - // This method verifies that the predictor's |results_| map is empty, i.e. - // there are no lookups in progress. - void ExpectNoLookupsAreInProgressOnUIThread() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&PredictorBrowserTest::ExpectNoLookupsAreInProgress, - base::Unretained(this))); - } - - void ExpectNoLookupsAreInProgress() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - EXPECT_TRUE(predictor()->results_.empty()); - } - - void DiscardAllResultsOnUIThread() { - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::BindOnce(&Predictor::DiscardAllResults, - base::Unretained(predictor()))); - } - - void ExpectValidPeakPendingLookupsOnUI(size_t num_names_requested) { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&PredictorBrowserTest::ExpectValidPeakPendingLookups, - base::Unretained(this), num_names_requested)); - } - - void ExpectValidPeakPendingLookups(size_t num_names_requested) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - EXPECT_LE(predictor()->peak_pending_lookups_, num_names_requested); - EXPECT_LE(predictor()->peak_pending_lookups_, - predictor()->max_concurrent_dns_lookups()); - } - - CrossSitePredictorObserver* observer() { return observer_.get(); } - - // Navigate to an html file on embedded_test_server and tell it to request - // |num_cors| resources from the cross_site_test_server. It then waits for - // those requests to complete. Note that "cors" here means using cors-mode in - // correspondence with the fetch spec. - void NavigateToCrossSiteHtmlUrl(int num_cors, const char* file_suffix) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - const GURL& base_url = cross_site_test_server()->base_url(); - std::string path = base::StringPrintf( - "/predictor/" - "predictor_cross_site%s.html?subresourceHost=%s&" - "numCORSResources=%d", - file_suffix, base_url.spec().c_str(), num_cors); - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL(path)); - bool result = false; - EXPECT_TRUE(content::ExecuteScriptAndExtractBool( - browser()->tab_strip_model()->GetActiveWebContents(), - "startFetchesAndWaitForReply()", &result)); - EXPECT_TRUE(result); - } - - base::test::ScopedFeatureList scoped_feature_list_; - - const GURL startup_url_; - const GURL referring_url_; - const GURL target_url_; - std::unique_ptr<ConnectionListener> connection_listener_; - std::unique_ptr<ConnectionListener> cross_site_connection_listener_; - - private: - scoped_refptr<net::RuleBasedHostResolverProc> rule_based_resolver_proc_; - std::unique_ptr<net::ScopedDefaultHostResolverProc> - scoped_host_resolver_proc_; - std::unique_ptr<net::EmbeddedTestServer> cross_site_test_server_; - std::unique_ptr<CrossSitePredictorObserver> observer_; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - - DISALLOW_COPY_AND_ASSIGN(PredictorBrowserTest); -}; - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SingleLookupTest) { - DiscardAllResultsOnUIThread(); - GURL url("http://www.example.test/"); - - // Try to flood the predictor with many concurrent requests. - std::vector<GURL> names{url}; - FloodResolveRequestsOnUIThread(names); - observer()->WaitUntilHostLookedUp(url); - EXPECT_TRUE(observer()->HostFound(url)); - ExpectValidPeakPendingLookupsOnUI(1u); - ExpectNoLookupsAreInProgressOnUIThread(); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ConcurrentLookupTest) { - DiscardAllResultsOnUIThread(); - GURL url("http://www.example.test"), goog2("http://gmail.google.com"), - goog3("http://mail.google.com"), goog4("http://gmail.com"); - GURL bad1("http://bad1.notfound"), bad2("http://bad2.notfound"); - - std::vector<GURL> found_names{url, goog3, goog2, goog4}; - std::vector<GURL> not_found_names{bad1, bad2}; - FloodResolveRequestsOnUIThread(found_names); - FloodResolveRequestsOnUIThread(not_found_names); - - WaitUntilHostsLookedUp(found_names); - WaitUntilHostsLookedUp(not_found_names); - ExpectFoundUrls(found_names, not_found_names); - ExpectValidPeakPendingLookupsOnUI(found_names.size() + - not_found_names.size()); - ExpectNoLookupsAreInProgressOnUIThread(); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, MassiveConcurrentLookupTest) { - DiscardAllResultsOnUIThread(); - std::vector<GURL> not_found_names; - for (int i = 0; i < 100; i++) { - not_found_names.push_back( - GURL(base::StringPrintf("http://host%d.notfound:80", i))); - } - FloodResolveRequestsOnUIThread(not_found_names); - - WaitUntilHostsLookedUp(not_found_names); - ExpectFoundUrls(std::vector<GURL>(), not_found_names); - ExpectValidPeakPendingLookupsOnUI(not_found_names.size()); - ExpectNoLookupsAreInProgressOnUIThread(); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, - ShutdownWhenResolutionIsPendingTest) { - GURL delayed_url("http://delay.google.com:80"); - std::vector<GURL> names{delayed_url}; - - // Flood with delayed requests, then wait. - FloodResolveRequestsOnUIThread(names); - base::RunLoop run_loop; - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, run_loop.QuitClosure(), - base::TimeDelta::FromMilliseconds(500)); - run_loop.Run(); - - ExpectUrlLookupIsInProgressOnUIThread(delayed_url); - EXPECT_FALSE(observer()->HasHostBeenLookedUp(delayed_url)); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, CongestionControlTest) { - const int queue_max_size = Predictor::kMaxSpeculativeParallelResolves; - std::vector<GURL> slow_names; - std::vector<GURL> recycled_names; - for (int i = 0; i < queue_max_size; ++i) - slow_names.emplace_back(base::StringPrintf("http://slow%d.google.com", i)); - for (int i = queue_max_size; i < 5; ++i) { - recycled_names.emplace_back( - base::StringPrintf("http://host%d.notfound", i)); - } - - FloodResolveRequestsOnUIThread(slow_names); - FloodResolveRequestsOnUIThread(recycled_names); - - WaitUntilHostsLookedUp(slow_names); - ExpectFoundUrls(slow_names, {}); - for (const auto& name : recycled_names) - EXPECT_FALSE(observer()->HasHostBeenLookedUp(name)); - ExpectValidPeakPendingLookupsOnUI(slow_names.size()); - ExpectNoLookupsAreInProgressOnUIThread(); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SimplePreconnectOne) { - predictor()->PreconnectUrl( - embedded_test_server()->base_url(), GURL(), - UrlInfo::ResolutionMotivation::EARLY_LOAD_MOTIVATED, - false /* allow credentials */, 1); - connection_listener_->WaitForAcceptedConnectionsOnUI(1u); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SimplePreconnectTwo) { - predictor()->PreconnectUrl( - embedded_test_server()->base_url(), GURL(), - UrlInfo::ResolutionMotivation::EARLY_LOAD_MOTIVATED, - false /* allow credentials */, 2); - connection_listener_->WaitForAcceptedConnectionsOnUI(2u); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SimplePreconnectFour) { - predictor()->PreconnectUrl( - embedded_test_server()->base_url(), GURL(), - UrlInfo::ResolutionMotivation::EARLY_LOAD_MOTIVATED, - false /* allow credentials */, 4); - connection_listener_->WaitForAcceptedConnectionsOnUI(4u); -} - -// Regression test for crbug.com/721981. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectNonHttpScheme) { - GURL url("chrome-native://dummyurl"); - predictor()->PreconnectUrlAndSubresources(url, GURL()); - base::RunLoop().RunUntilIdle(); - // Since |url| is non-HTTP(s) scheme, Predictor will canonicalize it to an - // empty url. Make sure that there is no attempt to preconnect |url| or an - // empty url. - EXPECT_FALSE(observer()->HasHostAttemptedToPreconnect(url)); - EXPECT_FALSE(observer()->HasHostAttemptedToPreconnect(GURL())); -} - -// Test the html test harness used to initiate cross site fetches. These -// initiate cross site subresource requests to the cross site test server. -// Inspect the predictor's internal state to make sure that they are properly -// logged. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, CrossSiteUseOneSocket) { - StopInterceptingCrossSiteOnUI(); - NavigateToCrossSiteHtmlUrl(1 /* num_cors */, "" /* file_suffix */); - EXPECT_EQ(1u, cross_site_connection_listener_->GetAcceptedSocketCount()); - EXPECT_EQ(1, observer()->CrossSiteLearned()); - EXPECT_EQ(2, observer()->SameSitePreconnected()); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, CrossSiteUseThreeSockets) { - StopInterceptingCrossSiteOnUI(); - NavigateToCrossSiteHtmlUrl(3 /* num_cors */, "" /* file_suffix */); - EXPECT_EQ(3u, cross_site_connection_listener_->GetAcceptedSocketCount()); - EXPECT_EQ(3, observer()->CrossSiteLearned()); - EXPECT_EQ(2, observer()->SameSitePreconnected()); -} - -// The following tests confirm that Chrome accurately predicts preconnects after -// learning from navigations. Note that every "learned" connection adds ~.33 to -// the expected connection number, which starts at 2. Every preconnect Chrome -// performs multiplies the expected connections by .66. -// -// In order to simplify things, many of the following tests intercept requests -// to the cross site test server. This allows the test server to maintain a -// "clean slate" with no connected sockets, so that when the tests need to check -// that predictor initiated preconnects occur, there are no races and the -// connections are deterministic. -// -// One additional complexity is that if a preconnect from A to B is learned, an -// extra preconnect will be issued if the host part of A and B match (ignoring -// port). TODO(csharrison): This logic could probably be removed from the -// predictor. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, - CrossSiteSimplePredictionAfterOneNavigation) { - NavigateToCrossSiteHtmlUrl(2 /* num_cors */, "" /* file_suffix */); - EXPECT_EQ(2, observer()->CrossSiteLearned()); - - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - // Navigate again and confirm a preconnect. Note that because the two - // embedded test servers have the same host name, an extra preconnect is - // issued. This results in ceil(2.66) + 1 = 4 preconnects. - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - EXPECT_EQ(4, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(4u); -} - -// This test does not intercept initial requests / preconnects to the cross site -// test server. This is a sanity check to make sure that the interceptor doesn't -// change the logic in the predictor. Note that the test does not have the -// ability to inspect at the socket layer, but verifies that the predictor is at -// least making preconnect requests. -IN_PROC_BROWSER_TEST_F( - PredictorBrowserTest, - CrossSiteSimplePredictionAfterOneNavigationNoInterceptor) { - StopInterceptingCrossSiteOnUI(); - NavigateToCrossSiteHtmlUrl(1 /* num_cors */, "" /* file_suffix */); - EXPECT_EQ(1, observer()->CrossSiteLearned()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(1u); - - // Navigate again and confirm a preconnect. Note that because the two - // embedded test servers have the same host_piece, an extra preconnect is - // issued. This results in ceil(2.33) + 1 = 4 preconnects. - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - // Just check that predictor has initiated preconnects to the cross site test - // server. It's tricky to reset the connections to the test server, and - // sockets can be reused. - EXPECT_EQ(4, observer()->CrossSitePreconnected()); -} - -// 1. Navigate to A.com learning B.com -// 2. Navigate to B.com with subresource from C.com redirecting to A.com. -// 3. Assert that the redirect does not cause us to preconnect to B.com (via -// A.com). -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, DontPredictBasedOnSubresources) { - GURL redirector_url = GURL("http://redirector.com"); - - NavigateToCrossSiteHtmlUrl(1 /* num_cors */, "" /* file_suffix */); - EXPECT_EQ(1, observer()->CrossSiteLearned()); - EXPECT_EQ(0, observer()->CrossSitePreconnected()); - - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - // Stop intercepting so that the test can actually navigate to the cross site - // server. - StopInterceptingCrossSiteOnUI(); - - // All requests with the redirector url as base url should redirect to the - // embedded_test_server_. - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::BindOnce( - &PredictorBrowserTest::StartInterceptingHostWithCreateJobCallback, - redirector_url, - base::Bind( - &CreateRedirectRequestJob, - embedded_test_server()->GetURL("/predictor/empty.js").spec()))); - - // Reduce the strictness, because the below logic causes the predictor to - // learn cross_site_test_server_ => redirector, as well as - // cross_site_test_server_ => embedded_test_server_ (via referrer header). - observer()->SetStrict(false); - - GURL redirect_requesting_url = - cross_site_test_server()->GetURL(base::StringPrintf( - "/predictor/" - "predictor_cross_site.html?subresourceHost=%s&numCORSResources=1", - redirector_url.spec().c_str())); - ui_test_utils::NavigateToURL(browser(), redirect_requesting_url); - bool result = false; - - int navigation_preconnects = observer()->CrossSitePreconnected(); - EXPECT_EQ(2, navigation_preconnects); - - EXPECT_TRUE(content::ExecuteScriptAndExtractBool( - browser()->tab_strip_model()->GetActiveWebContents(), - "startFetchesAndWaitForReply()", &result)); - EXPECT_TRUE(result); - - // The number of preconnects should not increase. Note that the predictor - // would preconnect 4 sockets if it were doing so based on learning. - EXPECT_EQ(navigation_preconnects, observer()->CrossSitePreconnected()); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PredictBasedOnSubframeRedirect) { - // A test server is needed here because data url navigations with redirect - // interceptors don't interact well with the ResourceTiming API. - // TODO(csharrison): Possibly this is a bug in either net or Blink, and it - // might be worthwhile to investigate. - std::unique_ptr<net::EmbeddedTestServer> redirector = - std::make_unique<net::EmbeddedTestServer>(); - - NavigateToCrossSiteHtmlUrl(1 /* num_cors */, "" /* file_suffix */); - EXPECT_EQ(1, observer()->CrossSiteLearned()); - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - redirector->RegisterRequestHandler( - base::Bind(&RedirectForPathHandler, "/", - embedded_test_server()->GetURL("/title1.html"))); - ASSERT_TRUE(redirector->Start()); - - // Note that the observer will see preconnects to the redirector, and the - // predictor will learn redirector->embedded_test_server. - observer()->SetStrict(false); - - NavigateToDataURLWithContent(base::StringPrintf( - "<iframe src='%s'></iframe>", redirector->base_url().spec().c_str())); - - EXPECT_EQ(4, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(4u); -} - -// Expect that the predictor correctly predicts subframe navigations. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SubframeCrossSitePrediction) { - ui_test_utils::NavigateToURL( - browser(), embedded_test_server()->GetURL( - "/predictor/predictor_cross_site_subframe_nav.html")); - bool result = false; - EXPECT_TRUE(content::ExecuteScriptAndExtractBool( - browser()->tab_strip_model()->GetActiveWebContents(), - base::StringPrintf( - "navigateSubframe('%s')", - cross_site_test_server()->GetURL("/title1.html").spec().c_str()), - &result)); - EXPECT_TRUE(result); - EXPECT_EQ(1, observer()->CrossSiteLearned()); - - // The subframe navigation initiates two preconnects. - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(2u); - - FlushClientSocketsOnUIThread(); - FlushServerSocketsOnUIThread(cross_site_test_server()); - cross_site_connection_listener_->ResetCounts(); - - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - // Navigate again and confirm a preconnect. Note that because the two - // embedded test servers have the same host_piece, an extra preconnect is - // issued. This results in ceil(2 + .33) + 1 = 4 preconnects. - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - EXPECT_EQ(4, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(4u); -} - -// Expect that the predictor correctly preconnects an already learned resource -// if the host shows up in a subframe. This test is equivalent to -// CrossSiteSimplePredictionAfterOneNavigation, with the second navigation -// (which initiates the preconnect) happening for a subframe load. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SubframeInitiatesPreconnects) { - // Navigate to the normal cross site URL to learn the relationship. - NavigateToCrossSiteHtmlUrl(1 /* num_cors */, "" /* file_suffix */); - EXPECT_EQ(1, observer()->CrossSiteLearned()); - - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - // Navigate again and confirm a preconnect. Note that because the two - // embedded test servers have the same host_piece, an extra preconnect is - // issued. This results in ceil(2 + .33) + 1 = 4 preconnects. - NavigateToDataURLWithContent( - "<iframe src=\"" + embedded_test_server()->GetURL("/title1.html").spec() + - "\"></iframe>"); - EXPECT_EQ(4, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(4u); -} - -// Expect that the predictor correctly learns the subresources a subframe needs -// to preconnect to. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SubframeLearning) { - std::string path = base::StringPrintf( - "/predictor/" - "predictor_cross_site.html?subresourceHost=%s&" - "numCORSResources=1&sendImmediately=1", - cross_site_test_server()->base_url().spec().c_str()); - NavigateToDataURLWithContent( - base::StringPrintf("<iframe src=\"%s\"></iframe>", - embedded_test_server()->GetURL(path).spec().c_str())); - EXPECT_EQ(1, observer()->CrossSiteLearned()); - - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - // Navigate again and confirm a preconnect. Note that because the two - // embedded test servers have the same host_piece, an extra preconnect is - // issued. This results in ceil(2 + .33) + 1 = 4 preconnects. - NavigateToDataURLWithContent( - "<iframe src=\"" + embedded_test_server()->GetURL("/title1.html").spec() + - "\"></iframe>"); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(4u); - EXPECT_EQ(4u, cross_site_connection_listener_->GetAcceptedSocketCount()); - EXPECT_EQ(4, observer()->CrossSitePreconnected()); -} - -// This test navigates to an html file with a tag: -// <meta name="referrer" content="never">. This tests the implementation details -// of the predictor. The current predictor only learns via the referrer header. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, - CrossSiteNoReferrerNoPredictionAfterOneNavigation) { - NavigateToCrossSiteHtmlUrl(2 /* num_cors */, - "_no_referrer" /* file_suffix */); - EXPECT_EQ(0, observer()->CrossSiteLearned()); - EXPECT_EQ(2, observer()->SameSitePreconnected()); - - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - // Navigate again and confirm that no preconnects occurred. - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - EXPECT_EQ(0, observer()->CrossSitePreconnected()); - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, - CrossSiteSimplePredictionAfterTwoNavigations) { - NavigateToCrossSiteHtmlUrl(1 /* num_cors */, "" /* file_suffix */); - EXPECT_EQ(0, observer()->CrossSitePreconnected()); - EXPECT_EQ(1, observer()->CrossSiteLearned()); - - NavigateToCrossSiteHtmlUrl(1 /* num_cors */, "" /* file_suffix */); - EXPECT_EQ(4, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(4u); - - FlushClientSocketsOnUIThread(); - FlushServerSocketsOnUIThread(cross_site_test_server()); - cross_site_connection_listener_->ResetCounts(); - observer()->ResetCounts(); - - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - // Navigate again and confirm a preconnect. Note that because the two - // embedded test servers have the same host_piece, an extra preconnect is - // issued. This results in ceil(((2 + .33) + .33)*.66) + 1 = 3 preconnects. - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - EXPECT_EQ(3, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(3u); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, - CrossSiteSimplePredictionAfterTwoNavigations2) { - NavigateToCrossSiteHtmlUrl(2 /* num_cors */, "" /* file_suffix */); - EXPECT_EQ(0, observer()->CrossSitePreconnected()); - EXPECT_EQ(2, observer()->CrossSiteLearned()); - - NavigateToCrossSiteHtmlUrl(2 /* num_cors */, "" /* file_suffix */); - - EXPECT_EQ(4, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(4u); - - FlushClientSocketsOnUIThread(); - FlushServerSocketsOnUIThread(cross_site_test_server()); - cross_site_connection_listener_->ResetCounts(); - observer()->ResetCounts(); - - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - // ((2 + .66) + .66)*.66 + 1 ~= 3.2. - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - EXPECT_EQ(4, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(4u); -} - -// The first navigation uses a subresource. Subsequent navigations don't use -// that subresource. This tests how the predictor forgets about these bad -// navigations. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ForgetBadPrediction) { - NavigateToCrossSiteHtmlUrl(1 /* num_cors */, "" /* file_suffix */); - EXPECT_EQ(1, observer()->CrossSiteLearned()); - - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - // (2 + .33) + 1 = 3.33. - EXPECT_EQ(4, observer()->CrossSitePreconnected()); - observer()->ResetCounts(); - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - // ceil((2 + .33) * .66) + 1 = 3. - EXPECT_EQ(3, observer()->CrossSitePreconnected()); - observer()->ResetCounts(); - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - // ceil((2 + .33) * .66 * .66) + 1 = 3. - EXPECT_EQ(3, observer()->CrossSitePreconnected()); - observer()->ResetCounts(); - - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - // Finally, (2 + .33) * .66^3 ~= .67. Not enough for a preconnect. - EXPECT_EQ(0, observer()->CrossSitePreconnected()); -} - -// The predictor does not follow redirects if the original url had a non-empty -// path (a path that was more than just "/"). -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, - CrossSiteRedirectNoPredictionWithPath) { - ui_test_utils::NavigateToURL( - browser(), - embedded_test_server()->GetURL(base::StringPrintf( - "/server-redirect?%s", - cross_site_test_server()->GetURL("/title1.html").spec().c_str()))); - EXPECT_EQ(0, observer()->CrossSiteLearned()); - - EXPECT_EQ(2, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(2u); - - FlushClientSocketsOnUIThread(); - FlushServerSocketsOnUIThread(cross_site_test_server()); - cross_site_connection_listener_->ResetCounts(); - observer()->ResetCounts(); - - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - EXPECT_EQ(0, observer()->CrossSitePreconnected()); -} - -// The predictor does follow redirects if the original url had an empty path -// (a path that was more than just "/"). Use the registered "/" path to redirect -// to the target test server. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, - CrossSiteRedirectPredictionWithNoPath) { - ui_test_utils::NavigateToURL(browser(), embedded_test_server()->base_url()); - EXPECT_EQ(1, observer()->CrossSiteLearned()); - - EXPECT_EQ(2, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(2u); - - FlushClientSocketsOnUIThread(); - FlushServerSocketsOnUIThread(cross_site_test_server()); - cross_site_connection_listener_->ResetCounts(); - observer()->ResetCounts(); - - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - // Preconnect 4 sockets because ceil(2 + .33) + 1 = 4. - EXPECT_EQ(4, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(4u); -} - -// This test uses "localhost" instead of "127.0.0.1" to avoid extra preconnects -// to hosts with the same host piece (ignoring port). Note that the preconnect -// observer is not used here due to its strict checks on hostname. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, - CrossSiteRedirectPredictionWithNoPathDifferentHostName) { - std::string same_site_localhost_host = base::StringPrintf( - "%s://localhost:%s", embedded_test_server()->base_url().scheme().c_str(), - embedded_test_server()->base_url().port().c_str()); - // The default predictor observer does not use "localhost". - InstallPredictorObserver(GURL(same_site_localhost_host), - cross_site_test_server()->base_url()); - GURL localhost_source = GURL(base::StringPrintf( - "%s/predictor/" - "predictor_cross_site.html?subresourceHost=%s&numCORSResources=1", - same_site_localhost_host.c_str(), - cross_site_test_server()->base_url().spec().c_str())); - ui_test_utils::NavigateToURL(browser(), localhost_source); - bool result = false; - EXPECT_TRUE(content::ExecuteScriptAndExtractBool( - browser()->tab_strip_model()->GetActiveWebContents(), - "startFetchesAndWaitForReply()", &result)); - EXPECT_TRUE(result); - - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - ui_test_utils::NavigateToURL( - browser(), GURL(base::StringPrintf("%s/title1.html", - same_site_localhost_host.c_str()))); - // Preconnect 3 sockets because ceil(2 + .33) = 3. Note that this time there - // is no additional connection due to same host. - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(3u); -} - -// Perform the "/" redirect twice and make sure the predictor updates twice. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, - CrossSiteTwoRedirectsPredictionWithNoPath) { - // Navigate once and redirect. - ui_test_utils::NavigateToURL(browser(), embedded_test_server()->base_url()); - EXPECT_EQ(1, observer()->CrossSiteLearned()); - - EXPECT_EQ(2, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(2u); - - FlushClientSocketsOnUIThread(); - FlushServerSocketsOnUIThread(cross_site_test_server()); - cross_site_connection_listener_->ResetCounts(); - observer()->ResetCounts(); - - // Navigate again and redirect. - ui_test_utils::NavigateToURL(browser(), embedded_test_server()->base_url()); - EXPECT_EQ(1, observer()->CrossSiteLearned()); - - // 2 + .33 + 1 = 3.33. - EXPECT_EQ(4, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(4u); - - FlushClientSocketsOnUIThread(); - FlushServerSocketsOnUIThread(cross_site_test_server()); - cross_site_connection_listener_->ResetCounts(); - observer()->ResetCounts(); - - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - // 3 preconnects expected because ((2 + .33)*.66 + .33)*.66 + 1 = 2.23. - EXPECT_EQ(3, observer()->CrossSitePreconnected()); - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(3u); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, - RendererInitiatedNavigationPreconnect) { - NavigateToCrossSiteHtmlUrl(1 /* num_cors */, "" /* file_suffix */); - EXPECT_EQ(1, observer()->CrossSiteLearned()); - EXPECT_EQ(0u, cross_site_connection_listener_->GetAcceptedSocketCount()); - - // Now, navigate using a renderer initiated navigation and expect preconnects. - // Need to navigate to about:blank first so the referring site is different - // from the request site. - ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); - EXPECT_TRUE(content::ExecuteScript( - browser()->tab_strip_model()->GetActiveWebContents(), - base::StringPrintf( - "window.location.href='%s'", - embedded_test_server()->GetURL("/title1.html").spec().c_str()))); - - // The renderer initiated navigation is not synchronous, so just wait for the - // preconnects to go through. - // Note that ceil(2 + .33) + 1 = 4. - cross_site_connection_listener_->WaitForAcceptedConnectionsOnUI(4u); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, - PRE_ShutdownStartupCyclePreresolve) { - // Prepare state that will be serialized on this shut-down and read on next - // start-up. Ensure preresolution over preconnection. - LearnAboutInitialNavigation(startup_url_); - // The target URL will have an expected connection count of 2 after this call. - InstallPredictorObserver(referring_url_, target_url_); - LearnFromNavigation(referring_url_, target_url_); - - // In order to reduce the expected connection count < .8, issue predictions 3 - // times. 2 * .66^3 ~= .58. - PrepareFrameSubresources(referring_url_); - PrepareFrameSubresources(referring_url_); - PrepareFrameSubresources(referring_url_); - - // The onload event is required to persist prefs. - ui_test_utils::NavigateToURL(browser(), referring_url_); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ShutdownStartupCyclePreresolve) { - // Make sure this data has been loaded into the Predictor, by inspecting that - // the Predictor starts making the expected hostname requests. - PrepareFrameSubresources(referring_url_); - observer()->WaitUntilHostLookedUp(target_url_); - - // Since the predictor is only enabled after startup, just ensure that - // |startup_url_| is persisted in the prefs. - std::string startup_list; - GetListFromPrefsAsString(prefs::kDnsPrefetchingStartupList, - &startup_list); - EXPECT_THAT(startup_list, HasSubstr(startup_url_.host())); - - // Verify that the |target_url_| is requested by the predictor. - EXPECT_FALSE(observer()->HostFound(target_url_)); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PRE_ClearData) { - // The target url will have a expected connection count of 2 after this call. - InstallPredictorObserver(referring_url_, target_url_); - LearnFromNavigation(referring_url_, target_url_); - - // The onload event is required to persist prefs. - ui_test_utils::NavigateToURL(browser(), referring_url_); -} - -// Ensure predictive data is cleared when the history is cleared. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ClearData) { - std::string cleared_startup_list; - std::string cleared_referral_list; - - // The pref should persist after startup. - GetListFromPrefsAsString(prefs::kDnsPrefetchingStartupList, - &cleared_startup_list); - GetListFromPrefsAsString(prefs::kDnsPrefetchingHostReferralList, - &cleared_referral_list); - EXPECT_THAT(cleared_referral_list, HasSubstr(referring_url_.host())); - EXPECT_THAT(cleared_referral_list, HasSubstr(target_url_.host())); - - // Clear cache which should clear all prefs. - content::BrowsingDataRemover* remover = - content::BrowserContext::GetBrowsingDataRemover(browser()->profile()); - remover->Remove(base::Time(), base::Time::Max(), - ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY, - content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB); - - GetListFromPrefsAsString(prefs::kDnsPrefetchingStartupList, - &cleared_startup_list); - GetListFromPrefsAsString(prefs::kDnsPrefetchingHostReferralList, - &cleared_referral_list); - EXPECT_THAT(cleared_referral_list, Not(HasSubstr(referring_url_.host()))); - EXPECT_THAT(cleared_referral_list, Not(HasSubstr(target_url_.host()))); -} - -// The predictor should not evict recently used (navigated to) referrers. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, DoNotEvictRecentlyUsed) { - observer()->SetStrict(false); - for (int i = 0; i < Predictor::kMaxReferrers; ++i) { - LearnFromNavigation(GURL(base::StringPrintf("http://source%d.test", i)), - GURL(base::StringPrintf("http://target%d.test", i))); - } - ui_test_utils::NavigateToURL(browser(), GURL("http://source0.test")); - - // This will evict http://source1.test. - LearnFromNavigation(GURL("http://new_source"), GURL("http://new_target")); - - base::ListValue referral_list; - base::RunLoop run_loop; - BrowserThread::PostTaskAndReply( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&Predictor::SerializeReferrers, - base::Unretained(predictor()), &referral_list), - run_loop.QuitClosure()); - run_loop.Run(); - - EXPECT_NE( - FindSerializationMotivation(GURL("http://source0.test"), &referral_list), - nullptr); - EXPECT_EQ( - FindSerializationMotivation(GURL("http://source1.test"), &referral_list), - nullptr); -} - -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, DnsPrefetch) { - // Navigate once to make sure all initial hostnames are requested. - ui_test_utils::NavigateToURL(browser(), - embedded_test_server()->GetURL("/title1.html")); - - size_t hosts_looked_up_before_load = observer()->TotalHostsLookedUp(); - - ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL( - "/predictor/dns_prefetch.html")); - observer()->WaitUntilHostLookedUp(GURL(kChromiumUrl)); - ASSERT_FALSE(observer()->HasHostBeenLookedUp(GURL(kInvalidLongUrl))); - - EXPECT_FALSE(observer()->HostFound(GURL(kChromiumUrl))); - ASSERT_EQ(hosts_looked_up_before_load + 1, observer()->TotalHostsLookedUp()); -} - -// Tests that preconnect warms up a socket connection to a test server. -// Note: This test uses a data URI to serve the preconnect hint, to make sure -// that the network stack doesn't just re-use its connection to the test server. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectNonCORS) { - GURL preconnect_url = embedded_test_server()->base_url(); - std::string preconnect_content = - "<link rel=\"preconnect\" href=\"" + preconnect_url.spec() + "\">"; - NavigateToDataURLWithContent(preconnect_content); - connection_listener_->WaitUntilFirstConnectionAccepted(); - EXPECT_EQ(1u, connection_listener_->GetAcceptedSocketCount()); - EXPECT_EQ(0u, connection_listener_->GetReadSocketCount()); -} - -// Tests that preconnect warms up a socket connection to a test server, -// and that that socket is later used when fetching a resource. -// Note: This test uses a data URI to serve the preconnect hint, to make sure -// that the network stack doesn't just re-use its connection to the test server. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectAndFetchNonCORS) { - GURL preconnect_url = embedded_test_server()->base_url(); - // First navigation to content with a preconnect hint. - std::string preconnect_content = - "<link rel=\"preconnect\" href=\"" + preconnect_url.spec() + "\">"; - NavigateToDataURLWithContent(preconnect_content); - connection_listener_->WaitUntilFirstConnectionAccepted(); - EXPECT_EQ(1u, connection_listener_->GetAcceptedSocketCount()); - EXPECT_EQ(0u, connection_listener_->GetReadSocketCount()); - - // Second navigation to content with an img. - std::string img_content = - "<img src=\"" + preconnect_url.spec() + "test.gif\">"; - NavigateToDataURLWithContent(img_content); - connection_listener_->WaitUntilFirstConnectionRead(); - EXPECT_EQ(1u, connection_listener_->GetAcceptedSocketCount()); - EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); -} - -// Tests that preconnect warms up a CORS connection to a test -// server, and that socket is later used when fetching a CORS resource. -// Note: This test uses a data URI to serve the preconnect hint, to make sure -// that the network stack doesn't just re-use its connection to the test server. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectAndFetchCORS) { - GURL preconnect_url = embedded_test_server()->base_url(); - // First navigation to content with a preconnect hint. - std::string preconnect_content = "<link rel=\"preconnect\" href=\"" + - preconnect_url.spec() + "\" crossorigin>"; - NavigateToDataURLWithContent(preconnect_content); - connection_listener_->WaitUntilFirstConnectionAccepted(); - EXPECT_EQ(1u, connection_listener_->GetAcceptedSocketCount()); - EXPECT_EQ(0u, connection_listener_->GetReadSocketCount()); - - // Second navigation to content with a font. - std::string font_content = "<script>var font = new FontFace('FontA', 'url(" + - preconnect_url.spec() + - "test.woff2)');font.load();</script>"; - NavigateToDataURLWithContent(font_content); - connection_listener_->WaitUntilFirstConnectionRead(); - EXPECT_EQ(1u, connection_listener_->GetAcceptedSocketCount()); - EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); -} - -// Tests that preconnect warms up a non-CORS connection to a test -// server, but that socket is not used when fetching a CORS resource. -// Note: This test uses a data URI to serve the preconnect hint, to make sure -// that the network stack doesn't just re-use its connection to the test server. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectNonCORSAndFetchCORS) { - GURL preconnect_url = embedded_test_server()->base_url(); - // First navigation to content with a preconnect hint. - std::string preconnect_content = - "<link rel=\"preconnect\" href=\"" + preconnect_url.spec() + "\">"; - NavigateToDataURLWithContent(preconnect_content); - connection_listener_->WaitUntilFirstConnectionAccepted(); - EXPECT_EQ(1u, connection_listener_->GetAcceptedSocketCount()); - EXPECT_EQ(0u, connection_listener_->GetReadSocketCount()); - - // Second navigation to content with a font. - std::string font_content = "<script>var font = new FontFace('FontA', 'url(" + - preconnect_url.spec() + - "test.woff2)');font.load();</script>"; - NavigateToDataURLWithContent(font_content); - connection_listener_->WaitUntilFirstConnectionRead(); - EXPECT_EQ(2u, connection_listener_->GetAcceptedSocketCount()); - EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); -} - -// Tests that preconnect warms up a CORS connection to a test server, -// but that socket is not used when fetching a non-CORS resource. -// Note: This test uses a data URI to serve the preconnect hint, to make sure -// that the network stack doesn't just re-use its connection to the test server. -IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PreconnectCORSAndFetchNonCORS) { - GURL preconnect_url = embedded_test_server()->base_url(); - // First navigation to content with a preconnect hint. - std::string preconnect_content = "<link rel=\"preconnect\" href=\"" + - preconnect_url.spec() + "\" crossorigin>"; - NavigateToDataURLWithContent(preconnect_content); - connection_listener_->WaitUntilFirstConnectionAccepted(); - EXPECT_EQ(1u, connection_listener_->GetAcceptedSocketCount()); - EXPECT_EQ(0u, connection_listener_->GetReadSocketCount()); - - // Second navigation to content with an img. - std::string img_content = - "<img src=\"" + preconnect_url.spec() + "test.gif\">"; - NavigateToDataURLWithContent(img_content); - connection_listener_->WaitUntilFirstConnectionRead(); - EXPECT_EQ(2u, connection_listener_->GetAcceptedSocketCount()); - EXPECT_EQ(1u, connection_listener_->GetReadSocketCount()); -} - -} // namespace chrome_browser_net
diff --git a/chrome/browser/net/predictor_tab_helper.cc b/chrome/browser/net/predictor_tab_helper.cc deleted file mode 100644 index 3e4a34f1..0000000 --- a/chrome/browser/net/predictor_tab_helper.cc +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/net/predictor_tab_helper.h" - -#include "chrome/browser/net/predictor.h" -#include "chrome/browser/profiles/profile.h" - -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/profiles/profile_helper.h" -#endif // defined(OS_CHROMEOS) - -namespace chrome_browser_net { - -PredictorTabHelper::PredictorTabHelper(content::WebContents* web_contents) - : content::WebContentsObserver(web_contents) {} - -PredictorTabHelper::~PredictorTabHelper() {} - -void PredictorTabHelper::DocumentOnLoadCompletedInMainFrame() { - Profile* profile = - Profile::FromBrowserContext(web_contents()->GetBrowserContext()); - Predictor* predictor = profile->GetNetworkPredictor(); -#if defined(OS_CHROMEOS) - if (chromeos::ProfileHelper::IsSigninProfile(profile)) - return; -#endif - if (predictor) - predictor->SaveStateForNextStartup(); -} - -} // namespace chrome_browser_net
diff --git a/chrome/browser/net/predictor_tab_helper.h b/chrome/browser/net/predictor_tab_helper.h deleted file mode 100644 index 8fa7331..0000000 --- a/chrome/browser/net/predictor_tab_helper.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_NET_PREDICTOR_TAB_HELPER_H_ -#define CHROME_BROWSER_NET_PREDICTOR_TAB_HELPER_H_ - -#include "base/macros.h" -#include "content/public/browser/web_contents_observer.h" -#include "content/public/browser/web_contents_user_data.h" - -namespace chrome_browser_net { - -class PredictorTabHelper - : public content::WebContentsObserver, - public content::WebContentsUserData<PredictorTabHelper> { - public: - ~PredictorTabHelper() override; - - // content::WebContentsObserver: - void DocumentOnLoadCompletedInMainFrame() override; - - private: - explicit PredictorTabHelper(content::WebContents* web_contents); - friend class content::WebContentsUserData<PredictorTabHelper>; - - DISALLOW_COPY_AND_ASSIGN(PredictorTabHelper); -}; - -} // namespace chrome_browser_net - -#endif // CHROME_BROWSER_NET_PREDICTOR_TAB_HELPER_H_
diff --git a/chrome/browser/net/predictor_unittest.cc b/chrome/browser/net/predictor_unittest.cc deleted file mode 100644 index 915c663..0000000 --- a/chrome/browser/net/predictor_unittest.cc +++ /dev/null
@@ -1,474 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/net/predictor.h" - -#include <stddef.h> - -#include <algorithm> -#include <memory> -#include <sstream> -#include <string> - -#include "base/location.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "base/test/scoped_feature_list.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/values.h" -#include "build/build_config.h" -#include "chrome/browser/net/url_info.h" -#include "chrome/common/chrome_features.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "net/base/load_flags.h" -#include "net/base/net_errors.h" -#include "net/http/transport_security_state.h" -#include "net/proxy_resolution/proxy_config_service_fixed.h" -#include "net/proxy_resolution/proxy_resolution_service.h" -#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -using base::Time; -using base::TimeDelta; -namespace chrome_browser_net { - -class PredictorTest : public testing::Test { - public: - PredictorTest() = default; - - private: - content::TestBrowserThreadBundle test_browser_thread_bundle_; -}; - -//------------------------------------------------------------------------------ -// Functions to help synthesize and test serializations of subresource referrer -// lists. - -// Return a motivation_list if we can find one for the given motivating_host (or -// NULL if a match is not found). -static const base::ListValue* FindSerializationMotivation( - const GURL& motivation, - const base::ListValue* referral_list) { - CHECK_LT(0u, referral_list->GetSize()); // Room for version. - int format_version = -1; - CHECK(referral_list->GetInteger(0, &format_version)); - CHECK_EQ(Predictor::kPredictorReferrerVersion, format_version); - const base::ListValue* motivation_list(NULL); - for (size_t i = 1; i < referral_list->GetSize(); ++i) { - referral_list->GetList(i, &motivation_list); - std::string existing_spec; - EXPECT_TRUE(motivation_list->GetString(0, &existing_spec)); - if (motivation == GURL(existing_spec)) - return motivation_list; - } - return NULL; -} - -static base::ListValue* FindSerializationMotivation( - const GURL& motivation, - base::ListValue* referral_list) { - return const_cast<base::ListValue*>(FindSerializationMotivation( - motivation, static_cast<const base::ListValue*>(referral_list))); -} - -// Create a new empty serialization list. -static base::ListValue* NewEmptySerializationList() { - base::ListValue* list = new base::ListValue; - list->AppendInteger(Predictor::kPredictorReferrerVersion); - return list; -} - -// Add a motivating_url and a subresource_url to a serialized list, using -// this given latency. This is a helper function for quickly building these -// lists. -static void AddToSerializedList(const GURL& motivation, - const GURL& subresource, - double use_rate, - base::ListValue* referral_list) { - // Find the motivation if it is already used. - base::ListValue* motivation_list = - FindSerializationMotivation(motivation, referral_list); - if (!motivation_list) { - // This is the first mention of this motivation, so build a list. - motivation_list = new base::ListValue; - motivation_list->AppendString(motivation.spec()); - // Provide empty subresource list. - motivation_list->Append(std::make_unique<base::ListValue>()); - - // ...and make it part of the serialized referral_list. - referral_list->Append(base::WrapUnique(motivation_list)); - // |motivation_list| is invalidated at this point, so it needs to be reset. - referral_list->GetList(referral_list->GetSize() - 1, &motivation_list); - } - - base::ListValue* subresource_list(NULL); - // 0 == url; 1 == subresource_list. - EXPECT_TRUE(motivation_list->GetList(1, &subresource_list)); - - // We won't bother to check for the subresource being there already. Worst - // case, during deserialization, the latency value we supply plus the - // existing value(s) will be added to the referrer. - - subresource_list->AppendString(subresource.spec()); - subresource_list->AppendDouble(use_rate); -} - -// For a given motivation, and subresource, find what latency is currently -// listed. This assume a well formed serialization, which has at most one such -// entry for any pair of names. If no such pair is found, then return false. -// Data is written into use_rate arguments. -static bool GetDataFromSerialization(const GURL& motivation, - const GURL& subresource, - const base::ListValue& referral_list, - double* use_rate) { - const base::ListValue* motivation_list = - FindSerializationMotivation(motivation, &referral_list); - if (!motivation_list) - return false; - const base::ListValue* subresource_list; - EXPECT_TRUE(motivation_list->GetList(1, &subresource_list)); - for (size_t i = 0; i < subresource_list->GetSize();) { - std::string url_spec; - EXPECT_TRUE(subresource_list->GetString(i++, &url_spec)); - EXPECT_TRUE(subresource_list->GetDouble(i++, use_rate)); - if (subresource == GURL(url_spec)) { - return true; - } - } - return false; -} - -TEST_F(PredictorTest, StartupShutdownTest) { - Predictor testing_master(true); - testing_master.Shutdown(); -} - -// Make sure nil referral lists really have no entries, and no latency listed. -TEST_F(PredictorTest, ReferrerSerializationNilTest) { - Predictor predictor(true); - - std::unique_ptr<base::ListValue> referral_list(new base::ListValue); - predictor.SerializeReferrers(referral_list.get()); - EXPECT_EQ(1U, referral_list->GetSize()); - EXPECT_FALSE(GetDataFromSerialization( - GURL("http://a.com:79"), GURL("http://b.com:78"), - *referral_list.get(), NULL)); - - predictor.Shutdown(); -} - -// Make sure that when a serialization list includes a value, that it can be -// deserialized into the database, and can be extracted back out via -// serialization without being changed. -TEST_F(PredictorTest, ReferrerSerializationSingleReferrerTest) { - Predictor predictor(true); - const GURL motivation_url("http://www.google.com:91"); - const GURL subresource_url("http://icons.google.com:90"); - const double kUseRate = 23.4; - std::unique_ptr<base::ListValue> referral_list(NewEmptySerializationList()); - - AddToSerializedList(motivation_url, subresource_url, - kUseRate, referral_list.get()); - - predictor.DeserializeReferrers(*referral_list.get()); - - base::ListValue recovered_referral_list; - predictor.SerializeReferrers(&recovered_referral_list); - EXPECT_EQ(2U, recovered_referral_list.GetSize()); - double rate; - EXPECT_TRUE(GetDataFromSerialization( - motivation_url, subresource_url, recovered_referral_list, &rate)); - EXPECT_EQ(rate, kUseRate); - - predictor.Shutdown(); -} - -// Expect the exact same referral list when the predictor's referrers are -// serialized and deserialized (implies ordering remains the same). -TEST_F(PredictorTest, SerializeAndDeserialize) { - SimplePredictor predictor(true); - - for (int i = 0; i < Predictor::kMaxReferrers * 2; ++i) { - predictor.LearnFromNavigation( - GURL(base::StringPrintf("http://www.source_%d.test", i)), - GURL(base::StringPrintf("http://www.target_%d.test", i))); - } - - base::ListValue referral_list; - predictor.SerializeReferrers(&referral_list); - predictor.DeserializeReferrers(referral_list); - - base::ListValue referral_list2; - predictor.SerializeReferrers(&referral_list2); - - EXPECT_EQ(referral_list, referral_list2); - - predictor.Shutdown(); -} - -// Filling the MRU cache should evict entries that were used less recently. -TEST_F(PredictorTest, FillMRUCache) { - SimplePredictor predictor(true); - - for (int i = 0; i < Predictor::kMaxReferrers * 2; ++i) { - predictor.LearnFromNavigation( - GURL(base::StringPrintf("http://www.source_%d.test", i)), - GURL(base::StringPrintf("http://www.target_%d.test", i))); - } - - base::ListValue referral_list; - predictor.SerializeReferrers(&referral_list); - - for (int i = 0; i < Predictor::kMaxReferrers; ++i) { - EXPECT_EQ(FindSerializationMotivation( - GURL(base::StringPrintf("http://www.source_%d.test", i)), - &referral_list), - nullptr); - } - - for (int i = Predictor::kMaxReferrers; i < Predictor::kMaxReferrers * 2; - ++i) { - EXPECT_NE(FindSerializationMotivation( - GURL(base::StringPrintf("http://www.source_%d.test", i)), - &referral_list), - nullptr); - } - - predictor.Shutdown(); -} - -TEST_F(PredictorTest, PriorityQueuePushPopTest) { - Predictor::HostNameQueue queue; - - GURL first("http://first:80"), second("http://second:90"); - - // First check high priority queue FIFO functionality. - EXPECT_TRUE(queue.IsEmpty()); - queue.Push(first, UrlInfo::LEARNED_REFERAL_MOTIVATED); - EXPECT_FALSE(queue.IsEmpty()); - queue.Push(second, UrlInfo::MOUSE_OVER_MOTIVATED); - EXPECT_FALSE(queue.IsEmpty()); - EXPECT_EQ(queue.Pop(), first); - EXPECT_FALSE(queue.IsEmpty()); - EXPECT_EQ(queue.Pop(), second); - EXPECT_TRUE(queue.IsEmpty()); - - // Then check low priority queue FIFO functionality. - queue.Push(first, UrlInfo::PAGE_SCAN_MOTIVATED); - EXPECT_FALSE(queue.IsEmpty()); - queue.Push(second, UrlInfo::OMNIBOX_MOTIVATED); - EXPECT_FALSE(queue.IsEmpty()); - EXPECT_EQ(queue.Pop(), first); - EXPECT_FALSE(queue.IsEmpty()); - EXPECT_EQ(queue.Pop(), second); - EXPECT_TRUE(queue.IsEmpty()); -} - -TEST_F(PredictorTest, PriorityQueueReorderTest) { - Predictor::HostNameQueue queue; - - // Push all the low priority items. - GURL low1("http://low1:80"), - low2("http://low2:80"), - low3("http://low3:443"), - low4("http://low4:80"), - low5("http://low5:80"), - hi1("http://hi1:80"), - hi2("http://hi2:80"), - hi3("http://hi3:80"); - - EXPECT_TRUE(queue.IsEmpty()); - queue.Push(low1, UrlInfo::PAGE_SCAN_MOTIVATED); - queue.Push(low2, UrlInfo::UNIT_TEST_MOTIVATED); - queue.Push(low3, UrlInfo::LINKED_MAX_MOTIVATED); - queue.Push(low4, UrlInfo::OMNIBOX_MOTIVATED); - queue.Push(low5, UrlInfo::STARTUP_LIST_MOTIVATED); - queue.Push(low4, UrlInfo::OMNIBOX_MOTIVATED); - - // Push all the high prority items - queue.Push(hi1, UrlInfo::LEARNED_REFERAL_MOTIVATED); - queue.Push(hi2, UrlInfo::STATIC_REFERAL_MOTIVATED); - queue.Push(hi3, UrlInfo::MOUSE_OVER_MOTIVATED); - - // Check that high priority stuff comes out first, and in FIFO order. - EXPECT_EQ(queue.Pop(), hi1); - EXPECT_EQ(queue.Pop(), hi2); - EXPECT_EQ(queue.Pop(), hi3); - - // ...and then low priority strings. - EXPECT_EQ(queue.Pop(), low1); - EXPECT_EQ(queue.Pop(), low2); - EXPECT_EQ(queue.Pop(), low3); - EXPECT_EQ(queue.Pop(), low4); - EXPECT_EQ(queue.Pop(), low5); - EXPECT_EQ(queue.Pop(), low4); - - EXPECT_TRUE(queue.IsEmpty()); -} - -TEST_F(PredictorTest, CanonicalizeUrl) { - // Base case, only handles HTTP and HTTPS. - EXPECT_EQ(GURL(), Predictor::CanonicalizeUrl(GURL("ftp://anything"))); - - // Remove path testing. - GURL long_url("http://host:999/path?query=value"); - EXPECT_EQ(Predictor::CanonicalizeUrl(long_url), long_url.GetWithEmptyPath()); - - // Default port cannoncalization. - GURL implied_port("http://test"); - GURL explicit_port("http://test:80"); - EXPECT_EQ(Predictor::CanonicalizeUrl(implied_port), - Predictor::CanonicalizeUrl(explicit_port)); - - // Port is still maintained. - GURL port_80("http://test:80"); - GURL port_90("http://test:90"); - EXPECT_NE(Predictor::CanonicalizeUrl(port_80), - Predictor::CanonicalizeUrl(port_90)); - - // Host is still maintained. - GURL host_1("http://test_1"); - GURL host_2("http://test_2"); - EXPECT_NE(Predictor::CanonicalizeUrl(host_1), - Predictor::CanonicalizeUrl(host_2)); - - // Scheme is maintained (mismatch identified). - GURL http("http://test"); - GURL https("https://test"); - EXPECT_NE(Predictor::CanonicalizeUrl(http), - Predictor::CanonicalizeUrl(https)); - - // Https works fine. - GURL long_https("https://host:999/path?query=value"); - EXPECT_EQ(Predictor::CanonicalizeUrl(long_https), - long_https.GetWithEmptyPath()); -} - -TEST_F(PredictorTest, DiscardPredictorResults) { - SimplePredictor predictor(true); - base::ListValue referral_list; - predictor.SerializeReferrers(&referral_list); - EXPECT_EQ(1U, referral_list.GetSize()); - - GURL host_1("http://test_1"); - GURL host_2("http://test_2"); - predictor.LearnFromNavigation(host_1, host_2); - - referral_list.Clear(); - predictor.SerializeReferrers(&referral_list); - EXPECT_EQ(2U, referral_list.GetSize()); - - predictor.DiscardAllResults(); - referral_list.Clear(); - predictor.SerializeReferrers(&referral_list); - EXPECT_EQ(1U, referral_list.GetSize()); - - predictor.Shutdown(); -} - -class TestPredictorObserver : public PredictorObserver { - public: - // PredictorObserver implementation: - void OnPreconnectUrl(const GURL& url, - const GURL& site_for_cookies, - UrlInfo::ResolutionMotivation motivation, - int count) override { - preconnected_urls_.push_back(url); - } - - std::vector<GURL> preconnected_urls_; -}; - -TEST_F(PredictorTest, NoProxyService) { - // Don't actually try to resolve names. - Predictor::set_max_parallel_resolves(0); - - Predictor testing_master(true); - - GURL goog("http://www.google.com:80"); - testing_master.Resolve(goog, UrlInfo::OMNIBOX_MOTIVATED); - EXPECT_FALSE(testing_master.work_queue_.IsEmpty()); - - testing_master.Shutdown(); -} - -TEST_F(PredictorTest, ProxyDefinitelyEnabled) { - // Don't actually try to resolve names. - Predictor::set_max_parallel_resolves(0); - - Predictor testing_master(true); - - net::ProxyConfig config; - config.proxy_rules().ParseFromString("http=socks://localhost:12345"); - std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service( - net::ProxyResolutionService::CreateFixed(net::ProxyConfigWithAnnotation( - config, TRAFFIC_ANNOTATION_FOR_TESTS))); - testing_master.proxy_resolution_service_ = proxy_resolution_service.get(); - - GURL goog("http://www.google.com:80"); - testing_master.Resolve(goog, UrlInfo::OMNIBOX_MOTIVATED); - - // Proxy is definitely in use, so there is no need to pre-resolve the domain. - EXPECT_TRUE(testing_master.work_queue_.IsEmpty()); - - testing_master.Shutdown(); -} - -TEST_F(PredictorTest, ProxyDefinitelyNotEnabled) { - // Don't actually try to resolve names. - Predictor::set_max_parallel_resolves(0); - - Predictor testing_master(true); - net::ProxyConfigWithAnnotation config = - net::ProxyConfigWithAnnotation::CreateDirect(); - std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service( - net::ProxyResolutionService::CreateFixed(config)); - testing_master.proxy_resolution_service_ = proxy_resolution_service.get(); - - GURL goog("http://www.google.com:80"); - testing_master.Resolve(goog, UrlInfo::OMNIBOX_MOTIVATED); - - // Proxy is not in use, so the name has been registered for pre-resolve. - EXPECT_FALSE(testing_master.work_queue_.IsEmpty()); - - testing_master.Shutdown(); -} - -TEST_F(PredictorTest, ProxyMaybeEnabled) { - // Don't actually try to resolve names. - Predictor::set_max_parallel_resolves(0); - - Predictor testing_master(true); - net::ProxyConfig config = net::ProxyConfig::CreateFromCustomPacURL(GURL( - "http://foopy/proxy.pac")); - std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service( - net::ProxyResolutionService::CreateFixed(net::ProxyConfigWithAnnotation( - config, TRAFFIC_ANNOTATION_FOR_TESTS))); - testing_master.proxy_resolution_service_ = proxy_resolution_service.get(); - - GURL goog("http://www.google.com:80"); - testing_master.Resolve(goog, UrlInfo::OMNIBOX_MOTIVATED); - - // Proxy may not be in use (the PAC script has not yet been evaluated), so the - // name has been registered for pre-resolve. - EXPECT_FALSE(testing_master.work_queue_.IsEmpty()); - - testing_master.Shutdown(); -} - -TEST_F(PredictorTest, PredictorDisabledByNetworkPredictionFeature) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature(features::kNetworkPrediction); - - std::unique_ptr<Predictor> testing_master = - base::WrapUnique(Predictor::CreatePredictor(true)); - EXPECT_FALSE(testing_master->PredictorEnabled()); - testing_master->Shutdown(); -} - -} // namespace chrome_browser_net
diff --git a/chrome/browser/net/referrer.cc b/chrome/browser/net/referrer.cc index c280b82f..6595fc09 100644 --- a/chrome/browser/net/referrer.cc +++ b/chrome/browser/net/referrer.cc
@@ -13,7 +13,6 @@ #include "base/compiler_specific.h" #include "base/logging.h" #include "base/values.h" -#include "chrome/browser/net/predictor.h" namespace chrome_browser_net {
diff --git a/chrome/browser/net/timed_cache.cc b/chrome/browser/net/timed_cache.cc deleted file mode 100644 index 2d0dd94..0000000 --- a/chrome/browser/net/timed_cache.cc +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/net/timed_cache.h" - -#include "url/gurl.h" - -namespace chrome_browser_net { - -TimedCache::TimedCache(const base::TimeDelta& max_duration) - : mru_cache_(UrlMruTimedCache::NO_AUTO_EVICT), - max_duration_(max_duration) { -} - -// Make Clang compilation happy with explicit destructor. -TimedCache::~TimedCache() {} - -bool TimedCache::WasRecentlySeen(const GURL& url) { - DCHECK_EQ(url.GetWithEmptyPath(), url); - // Evict any overly old entries. - base::TimeTicks now = base::TimeTicks::Now(); - UrlMruTimedCache::reverse_iterator eldest = mru_cache_.rbegin(); - while (!mru_cache_.empty()) { - DCHECK(eldest == mru_cache_.rbegin()); - if (now - eldest->second < max_duration_) - break; - eldest = mru_cache_.Erase(eldest); - } - return mru_cache_.end() != mru_cache_.Peek(url); -} - -void TimedCache::SetRecentlySeen(const GURL& url) { - DCHECK_EQ(url.GetWithEmptyPath(), url); - mru_cache_.Put(url, base::TimeTicks::Now()); -} - -} // namespace chrome_browser_net
diff --git a/chrome/browser/net/timed_cache.h b/chrome/browser/net/timed_cache.h deleted file mode 100644 index a808777..0000000 --- a/chrome/browser/net/timed_cache.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_NET_TIMED_CACHE_H_ -#define CHROME_BROWSER_NET_TIMED_CACHE_H_ - -#include "base/containers/mru_cache.h" -#include "base/macros.h" -#include "base/time/time.h" - -class GURL; - -namespace chrome_browser_net { - -// Define a LRU cache that recalls all navigations within the last N seconds. -// When we learn about subresources to possibly preconnect to, it would be a -// waste to preconnect when the original navigation was too long ago. Any -// connected, but unused TCP/IP connection, will generally be reset by the -// server if it is not used quickly (i.e., GET or POST is sent). -class TimedCache { - public: - explicit TimedCache(const base::TimeDelta& max_duration); - ~TimedCache(); - - // Evicts any entries that have been in the FIFO "too long," and then checks - // to see if the given url is (still) in the FIFO cache. - bool WasRecentlySeen(const GURL& url); - - // Adds the given url to the cache, where it will remain for max_duration_. - void SetRecentlySeen(const GURL& url); - - private: - // Our cache will be keyed on a URL (actually, just a scheme/host/port). - // We will always track the time it was last added to the FIFO cache by - // remembering a TimeTicks value. - typedef base::MRUCache<GURL, base::TimeTicks> UrlMruTimedCache; - UrlMruTimedCache mru_cache_; - - // The longest time an entry can persist in the cache, and still be found. - const base::TimeDelta max_duration_; - - DISALLOW_COPY_AND_ASSIGN(TimedCache); -}; - -} // namespace chrome_browser_net - -#endif // CHROME_BROWSER_NET_TIMED_CACHE_H_
diff --git a/chrome/browser/net_benchmarking.cc b/chrome/browser/net_benchmarking.cc index 03aeba4..0c798de 100644 --- a/chrome/browser/net_benchmarking.cc +++ b/chrome/browser/net_benchmarking.cc
@@ -12,7 +12,6 @@ #include "base/command_line.h" #include "base/macros.h" #include "base/time/time.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/predictors/loading_predictor.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/net_benchmarking.mojom.h" @@ -45,10 +44,8 @@ NetBenchmarking::NetBenchmarking( base::WeakPtr<predictors::LoadingPredictor> loading_predictor, - base::WeakPtr<chrome_browser_net::Predictor> predictor, int render_process_id) : loading_predictor_(loading_predictor), - predictor_(predictor), render_process_id_(render_process_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); } @@ -60,13 +57,11 @@ // static void NetBenchmarking::Create( base::WeakPtr<predictors::LoadingPredictor> loading_predictor, - base::WeakPtr<chrome_browser_net::Predictor> predictor, int render_process_id, chrome::mojom::NetBenchmarkingRequest request) { DCHECK_CURRENTLY_ON(BrowserThread::UI); mojo::MakeStrongBinding(std::make_unique<NetBenchmarking>( - std::move(loading_predictor), - std::move(predictor), render_process_id), + std::move(loading_predictor), render_process_id), std::move(request)); } @@ -106,7 +101,5 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); if (loading_predictor_) loading_predictor_->resource_prefetch_predictor()->DeleteAllUrls(); - if (predictor_) - predictor_->DiscardAllResultsAndClearPrefsOnUIThread(); std::move(callback).Run(); }
diff --git a/chrome/browser/net_benchmarking.h b/chrome/browser/net_benchmarking.h index 48218e2..045d2c1 100644 --- a/chrome/browser/net_benchmarking.h +++ b/chrome/browser/net_benchmarking.h
@@ -9,10 +9,6 @@ #include "base/memory/weak_ptr.h" #include "chrome/common/net_benchmarking.mojom.h" -namespace chrome_browser_net { -class Predictor; -} - namespace predictors { class LoadingPredictor; } @@ -24,7 +20,6 @@ class NetBenchmarking : public chrome::mojom::NetBenchmarking { public: NetBenchmarking(base::WeakPtr<predictors::LoadingPredictor> loading_predictor, - base::WeakPtr<chrome_browser_net::Predictor> predictor, int render_process_id); ~NetBenchmarking() override; @@ -32,7 +27,6 @@ // Callers should prefer this over using the constructor directly. static void Create( base::WeakPtr<predictors::LoadingPredictor> loading_predictor, - base::WeakPtr<chrome_browser_net::Predictor> predictor, int render_process_id, chrome::mojom::NetBenchmarkingRequest request); @@ -49,7 +43,6 @@ // These weak pointers should be dereferenced only on the UI thread. base::WeakPtr<predictors::LoadingPredictor> loading_predictor_; - base::WeakPtr<chrome_browser_net::Predictor> predictor_; const int render_process_id_; DISALLOW_COPY_AND_ASSIGN(NetBenchmarking);
diff --git a/chrome/browser/predictors/loading_predictor_config.cc b/chrome/browser/predictors/loading_predictor_config.cc index a793f92..712dbb6c 100644 --- a/chrome/browser/predictors/loading_predictor_config.cc +++ b/chrome/browser/predictors/loading_predictor_config.cc
@@ -8,7 +8,6 @@ #include "base/metrics/field_trial_params.h" #include "chrome/browser/net/prediction_options.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/predictors/resource_prefetch_common.h" #include "chrome/browser/profiles/profile.h" #include "content/public/browser/browser_thread.h" @@ -94,7 +93,7 @@ LoadingPredictorConfig::LoadingPredictorConfig() : mode(0), max_navigation_lifetime_seconds(60), - max_hosts_to_track(chrome_browser_net::Predictor::kMaxReferrers), + max_hosts_to_track(100), max_origins_per_entry(50), max_consecutive_misses(3), max_redirect_consecutive_misses(5),
diff --git a/chrome/browser/predictors/loading_predictor_config_unittest.cc b/chrome/browser/predictors/loading_predictor_config_unittest.cc index 4e8b685a..979e3b00 100644 --- a/chrome/browser/predictors/loading_predictor_config_unittest.cc +++ b/chrome/browser/predictors/loading_predictor_config_unittest.cc
@@ -8,7 +8,6 @@ #include "base/memory/ptr_util.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/net/prediction_options.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/predictors/loading_predictor_config.h" #include "chrome/browser/predictors/resource_prefetch_common.h" #include "chrome/common/pref_names.h" @@ -20,7 +19,6 @@ #include "testing/gtest/include/gtest/gtest.h" using chrome_browser_net::NetworkPredictionOptions; -using NetPredictor = chrome_browser_net::Predictor; using net::NetworkChangeNotifier; namespace { @@ -51,14 +49,6 @@ profile_->GetPrefs()->SetInteger(prefs::kNetworkPredictionOptions, value); } - bool IsNetPredictorEnabled() { - std::unique_ptr<NetPredictor> predictor = base::WrapUnique( - NetPredictor::CreatePredictor(true /* simple_shutdown */)); - bool is_enabled = predictor->PredictorEnabled(); - predictor->Shutdown(); - return is_enabled; - } - protected: content::TestBrowserThreadBundle test_browser_thread_bundle_; std::unique_ptr<TestingProfile> profile_; @@ -76,7 +66,6 @@ EXPECT_TRUE(config.IsLearningEnabled()); EXPECT_TRUE(config.should_disable_other_preconnects); - EXPECT_FALSE(IsNetPredictorEnabled()); EXPECT_TRUE(config.IsPreconnectEnabledForSomeOrigin(profile_.get())); } @@ -89,7 +78,6 @@ EXPECT_FALSE(config.IsLearningEnabled()); EXPECT_FALSE(config.should_disable_other_preconnects); - EXPECT_TRUE(IsNetPredictorEnabled()); EXPECT_FALSE(config.IsPreconnectEnabledForSomeOrigin(profile_.get())); } @@ -104,7 +92,6 @@ EXPECT_TRUE(config.IsLearningEnabled()); EXPECT_TRUE(config.is_origin_learning_enabled); EXPECT_FALSE(config.should_disable_other_preconnects); - EXPECT_TRUE(IsNetPredictorEnabled()); EXPECT_FALSE(config.IsPreconnectEnabledForSomeOrigin(profile_.get())); } @@ -118,7 +105,6 @@ EXPECT_TRUE(config.IsLearningEnabled()); EXPECT_TRUE(config.should_disable_other_preconnects); - EXPECT_FALSE(IsNetPredictorEnabled()); EXPECT_TRUE(config.IsPreconnectEnabledForSomeOrigin(profile_.get())); } @@ -132,7 +118,6 @@ EXPECT_FALSE(config.IsLearningEnabled()); EXPECT_TRUE(config.should_disable_other_preconnects); - EXPECT_FALSE(IsNetPredictorEnabled()); EXPECT_FALSE(config.IsPreconnectEnabledForSomeOrigin(profile_.get())); }
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 79f60d2..82b5a301c2 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -34,7 +34,6 @@ #include "chrome/browser/metrics/chrome_metrics_service_client.h" #include "chrome/browser/net/nqe/ui_network_quality_estimator_service.h" #include "chrome/browser/net/prediction_options.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/net/profile_network_context_service.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/notifications/notification_channels_provider_android.h" @@ -349,6 +348,11 @@ "browser.reset_has_seen_win10_promo_page"; #endif +// Deprecated 8/2018. +const char kDnsPrefetchingStartupList[] = "dns_prefetching.startup_list"; +const char kDnsPrefetchingHostReferralList[] = + "dns_prefetching.host_referral_list"; + // Register prefs used only for migration (clearing or moving to a new key). void RegisterProfilePrefsForMigration( user_prefs::PrefRegistrySyncable* registry) { @@ -362,6 +366,9 @@ registry->RegisterListPref(kDismissedPhysicalWebPageSuggestions); registry->RegisterListPref(kDismissedRecentOfflineTabSuggestions); #endif + + registry->RegisterListPref(kDnsPrefetchingStartupList); + registry->RegisterListPref(kDnsPrefetchingHostReferralList); } } // namespace @@ -513,7 +520,6 @@ ChromeContentBrowserClient::RegisterProfilePrefs(registry); ChromeSSLHostStateDelegate::RegisterProfilePrefs(registry); ChromeVersionService::RegisterProfilePrefs(registry); - chrome_browser_net::Predictor::RegisterProfilePrefs(registry); chrome_browser_net::RegisterPredictionOptionsProfilePrefs(registry); chrome_prefs::RegisterProfilePrefs(registry); dom_distiller::DistilledPagePrefs::RegisterProfilePrefs(registry); @@ -793,4 +799,8 @@ // Added 8/2018. autofill::prefs::MigrateDeprecatedAutofillPrefs(profile_prefs); #endif // defined(OS_ANDROID) + + // Added 8/2018 + profile_prefs->ClearPref(kDnsPrefetchingStartupList); + profile_prefs->ClearPref(kDnsPrefetchingHostReferralList); }
diff --git a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc index c89c63d3..e49cf117 100644 --- a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc +++ b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
@@ -181,18 +181,6 @@ subresource_expected_["/bar.jpg"] = expect_bar_jpg_requested; } - // Verify that all subresources that were expected to be fetched were actually - // fetched. - void VerifyAllSubresourcesFetched() const { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - base::RunLoop().RunUntilIdle(); - - for (const auto& expect : subresource_expected_) { - EXPECT_FALSE(expect.second); - } - } - protected: base::test::ScopedFeatureList scoped_feature_list_; @@ -200,7 +188,6 @@ void TearDownOnMainThread() override { EXPECT_TRUE(https_server_->ShutdownAndWaitUntilComplete()); EXPECT_TRUE(http_server_->ShutdownAndWaitUntilComplete()); - VerifyAllSubresourcesFetched(); InProcessBrowserTest::TearDownOnMainThread(); } @@ -232,6 +219,8 @@ for (const auto& expect : subresource_expected_) { if (gurl.path() == expect.first) { + // Verify that |gurl| is expected to be fetched. This ensures that a + // resource whose loading is blocked is not loaded. EXPECT_TRUE(expect.second); // Subresource should not be fetched again. subresource_expected_[gurl.path()] = false; @@ -282,9 +271,9 @@ }; // Previews InfoBar (which these tests triggers) does not work on Mac. -// See crbug.com/782322 for details. Also occasional flakes on win7/linux -// (crbug.com/789542, crbug.com/866212). -#if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(OS_LINUX) +// See https://crbug.com/782322 for details. Also occasional flakes on win7 +// (https://crbug.com/789542). +#if !defined(OS_MACOSX) && !defined(OS_WIN) #define MAYBE_ResourceLoadingHintsHttpsWhitelisted \ ResourceLoadingHintsHttpsWhitelisted #define MAYBE_ResourceLoadingHintsHttpsWhitelistedRedirectToHttps \ @@ -336,7 +325,6 @@ // SetResourceLoadingHintsPatterns sets 3 resource loading hints patterns. histogram_tester.ExpectBucketCount( "ResourceLoadingHints.CountBlockedSubresourcePatterns", 3, 1); - VerifyAllSubresourcesFetched(); // Load the same webpage to ensure that the resource loading hints are sent // again.
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc index cdcda153..9426898 100644 --- a/chrome/browser/profiles/off_the_record_profile_impl.cc +++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -545,12 +545,6 @@ } #endif // defined(OS_CHROMEOS) -chrome_browser_net::Predictor* OffTheRecordProfileImpl::GetNetworkPredictor() { - // We do not store information about websites visited in OTR profiles which - // is necessary for a Predictor, so we do not have a Predictor at all. - return NULL; -} - GURL OffTheRecordProfileImpl::GetHomePage() { return profile_->GetHomePage(); }
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.h b/chrome/browser/profiles/off_the_record_profile_impl.h index 3ae418b6..77f24ffa 100644 --- a/chrome/browser/profiles/off_the_record_profile_impl.h +++ b/chrome/browser/profiles/off_the_record_profile_impl.h
@@ -85,7 +85,6 @@ void InitChromeOSPreferences() override; #endif // defined(OS_CHROMEOS) - chrome_browser_net::Predictor* GetNetworkPredictor() override; GURL GetHomePage() override; // content::BrowserContext implementation:
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h index f4d62ac..6309ea2 100644 --- a/chrome/browser/profiles/profile.h +++ b/chrome/browser/profiles/profile.h
@@ -32,10 +32,6 @@ class SequencedTaskRunner; } -namespace chrome_browser_net { -class Predictor; -} - namespace content { class WebUI; } @@ -252,9 +248,6 @@ virtual void InitChromeOSPreferences() = 0; #endif // defined(OS_CHROMEOS) - // Returns the Predictor object used for dns prefetch. - virtual chrome_browser_net::Predictor* GetNetworkPredictor() = 0; - // Returns the home page for this profile. virtual GURL GetHomePage() = 0;
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index bf4ef91..04a5df8 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -54,7 +54,6 @@ #include "chrome/browser/download/download_core_service_factory.h" #include "chrome/browser/gcm/gcm_profile_service_factory.h" #include "chrome/browser/media/media_device_id_salt.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/permissions/permission_manager.h" #include "chrome/browser/permissions/permission_manager_factory.h" @@ -450,7 +449,6 @@ last_session_exit_type_(EXIT_NORMAL), start_time_(base::Time::Now()), delegate_(delegate), - predictor_(nullptr), reporting_permissions_checker_factory_(this) { TRACE_EVENT0("browser,startup", "ProfileImpl::ctor") DCHECK(!path.empty()) << "Using an empty path will attempt to write " @@ -492,10 +490,6 @@ set_is_guest_profile(path == ProfileManager::GetGuestProfilePath()); set_is_system_profile(path == ProfileManager::GetSystemProfilePath()); - // If profile_manager is not present, it means we are in a unittest. - predictor_ = chrome_browser_net::Predictor::CreatePredictor( - g_browser_process->profile_manager() == NULL); - // If we are creating the profile synchronously, then we should load the // policy data immediately. bool force_immediate_policy_load = (create_mode == CREATE_MODE_SYNCHRONOUS); @@ -678,7 +672,7 @@ PrefService* local_state = g_browser_process->local_state(); io_data_.Init(media_cache_path, media_cache_max_size, extensions_cookie_path, - GetPath(), predictor_, GetSpecialStoragePolicy(), + GetPath(), GetSpecialStoragePolicy(), reporting_permissions_checker_factory_.CreateChecker(), CreateDomainReliabilityMonitor(local_state)); @@ -1376,10 +1370,6 @@ #endif // defined(OS_CHROMEOS) -chrome_browser_net::Predictor* ProfileImpl::GetNetworkPredictor() { - return predictor_; -} - GURL ProfileImpl::GetHomePage() { // --homepage overrides any preferences. const base::CommandLine& command_line =
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h index d685bdc..a016448 100644 --- a/chrome/browser/profiles/profile_impl.h +++ b/chrome/browser/profiles/profile_impl.h
@@ -139,7 +139,6 @@ base::Time GetStartTime() const override; base::FilePath last_selected_directory() override; void set_last_selected_directory(const base::FilePath& path) override; - chrome_browser_net::Predictor* GetNetworkPredictor() override; GURL GetHomePage() override; bool WasCreatedByVersionOrLater(const std::string& version) override; void SetExitType(ExitType exit_type) override; @@ -288,8 +287,6 @@ Profile::Delegate* delegate_; - chrome_browser_net::Predictor* predictor_; - ReportingPermissionsCheckerFactory reporting_permissions_checker_factory_; // Used to post schedule CT policy updates
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc index 7998a03..a384ac8 100644 --- a/chrome/browser/profiles/profile_impl_io_data.cc +++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -31,7 +31,6 @@ #include "chrome/browser/data_use_measurement/chrome_data_use_ascriber.h" #include "chrome/browser/io_thread.h" #include "chrome/browser/net/chrome_network_delegate.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/net/profile_network_context_service.h" #include "chrome/browser/net/profile_network_context_service_factory.h" #include "chrome/browser/net/quota_policy_channel_id_store.h" @@ -133,12 +132,6 @@ ProfileImplIOData::Handle::~Handle() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (io_data_->predictor_ != NULL) { - // io_data_->predictor_ might be NULL if Init() was never called - // (i.e. we shut down before ProfileImpl::DoFinalInit() got called). - io_data_->predictor_->ShutdownOnUIThread(); - } - // io_data_->data_reduction_proxy_io_data() might be NULL if Init() was // never called. if (io_data_->data_reduction_proxy_io_data()) @@ -152,14 +145,12 @@ int media_cache_max_size, const base::FilePath& extensions_cookie_path, const base::FilePath& profile_path, - chrome_browser_net::Predictor* predictor, storage::SpecialStoragePolicy* special_storage_policy, std::unique_ptr<ReportingPermissionsChecker> reporting_permissions_checker, std::unique_ptr<domain_reliability::DomainReliabilityMonitor> domain_reliability_monitor) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!io_data_->lazy_params_); - DCHECK(predictor); LazyParams* lazy_params = new LazyParams(); @@ -183,8 +174,6 @@ io_data_->profile_path_ = profile_path; io_data_->app_media_cache_max_size_ = media_cache_max_size; - io_data_->predictor_.reset(predictor); - io_data_->InitializeMetricsEnabledStateOnUIThread(); if (io_data_->lazy_params_->domain_reliability_monitor) io_data_->lazy_params_->domain_reliability_monitor->MoveToNetworkThread(); @@ -259,10 +248,6 @@ BrowserThread::GetTaskRunnerForThread(BrowserThread::UI), db_task_runner); - io_data_->predictor_->InitNetworkPredictor(profile_->GetPrefs(), io_thread, - main_request_context_getter_.get(), - io_data_, profile_); - content::NotificationService::current()->Notify( chrome::NOTIFICATION_PROFILE_URL_REQUEST_CONTEXT_GETTER_INITIALIZED, content::Source<Profile>(profile_), @@ -593,7 +578,3 @@ DCHECK(media_request_context); return media_request_context; } - -chrome_browser_net::Predictor* ProfileImplIOData::GetPredictor() { - return predictor_.get(); -}
diff --git a/chrome/browser/profiles/profile_impl_io_data.h b/chrome/browser/profiles/profile_impl_io_data.h index 129a4d7d..0f6ab9b 100644 --- a/chrome/browser/profiles/profile_impl_io_data.h +++ b/chrome/browser/profiles/profile_impl_io_data.h
@@ -16,10 +16,6 @@ class ReportingPermissionsChecker; -namespace chrome_browser_net { -class Predictor; -} // namespace chrome_browser_net - namespace domain_reliability { class DomainReliabilityMonitor; } // namespace domain_reliability @@ -48,7 +44,6 @@ int media_cache_max_size, const base::FilePath& extensions_cookie_path, const base::FilePath& profile_path, - chrome_browser_net::Predictor* predictor, storage::SpecialStoragePolicy* special_storage_policy, std::unique_ptr<ReportingPermissionsChecker> reporting_permissions_checker, @@ -164,7 +159,6 @@ net::URLRequestContext* AcquireIsolatedMediaRequestContext( net::URLRequestContext* app_context, const StoragePartitionDescriptor& partition_descriptor) const override; - chrome_browser_net::Predictor* GetPredictor() override; // Returns a net::ReportingService, if reporting should be enabled. Otherwise, // returns nullptr. @@ -182,8 +176,6 @@ mutable std::unique_ptr<net::CookieStore> extensions_cookie_store_; - mutable std::unique_ptr<chrome_browser_net::Predictor> predictor_; - mutable std::unique_ptr<net::URLRequestContext> media_request_context_; // Parameters needed for isolated apps.
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.cc b/chrome/browser/renderer_host/chrome_render_message_filter.cc index 44e7a65f..a4690c9 100644 --- a/chrome/browser/renderer_host/chrome_render_message_filter.cc +++ b/chrome/browser/renderer_host/chrome_render_message_filter.cc
@@ -17,7 +17,6 @@ #include "chrome/browser/content_settings/cookie_settings_factory.h" #include "chrome/browser/content_settings/tab_specific_content_settings.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/predictors/loading_predictor.h" #include "chrome/browser/predictors/loading_predictor_factory.h" #include "chrome/browser/predictors/preconnect_manager.h" @@ -54,8 +53,6 @@ : BrowserMessageFilter(kRenderFilteredMessageClasses, arraysize(kRenderFilteredMessageClasses)), render_process_id_(render_process_id), - profile_(profile), - predictor_(profile_->GetNetworkPredictor()), preconnect_manager_initialized_(false), cookie_settings_(CookieSettingsFactory::GetForProfile(profile)) { auto* loading_predictor = @@ -112,8 +109,6 @@ BrowserThread::UI, FROM_HERE, base::BindOnce(&predictors::PreconnectManager::StartPreresolveHosts, preconnect_manager_, request.hostname_list)); - } else if (predictor_) { - predictor_->DnsPrefetchList(request.hostname_list); } } @@ -136,10 +131,6 @@ BrowserThread::UI, FROM_HERE, base::BindOnce(&predictors::PreconnectManager::StartPreconnectUrl, preconnect_manager_, url, allow_credentials)); - } else if (predictor_) { - predictor_->PreconnectUrl(url, GURL(), - chrome_browser_net::UrlInfo::EARLY_LOAD_MOTIVATED, - allow_credentials, count); } }
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.h b/chrome/browser/renderer_host/chrome_render_message_filter.h index e1ce2f2..e035fe76 100644 --- a/chrome/browser/renderer_host/chrome_render_message_filter.h +++ b/chrome/browser/renderer_host/chrome_render_message_filter.h
@@ -19,10 +19,6 @@ class GURL; class Profile; -namespace chrome_browser_net { -class Predictor; -} - namespace predictors { class PreconnectManager; } @@ -106,12 +102,6 @@ const int render_process_id_; - // The Profile associated with our renderer process. This must only be - // accessed on the UI thread! - Profile* profile_; - // The Predictor for the associated Profile. It is stored so that it can be - // used on the IO thread. - chrome_browser_net::Predictor* predictor_; // The PreconnectManager for the associated Profile. This must only be // accessed on the UI thread. base::WeakPtr<predictors::PreconnectManager> preconnect_manager_;
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs index 8003e911..870999034 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
@@ -1636,17 +1636,6 @@ }); }); -TEST_F('BackgroundTest', 'DocumentTitleChanged', function() { - var mockFeedback = this.createMockFeedback(); - this.runWithLoadedTree(function(root) {/* - <script> - setTimeout(function() {document.title = 'New title';}, 100); - </script> - */}, function(root) { - mockFeedback.expectSpeech('New title').replay(); - }); -}); - TEST_F('BackgroundTest', 'MathContentViaInnerHtml', function() { var mockFeedback = this.createMockFeedback(); this.runWithLoadedTree(function(root) {/*
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js index 4d8d766..e8b76c9 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
@@ -66,8 +66,6 @@ this.addListener_(EventType.CHILDREN_CHANGED, this.onChildrenChanged); this.addListener_( EventType.DOCUMENT_SELECTION_CHANGED, this.onDocumentSelectionChanged); - this.addListener_( - EventType.DOCUMENT_TITLE_CHANGED, this.onDocumentTitleChanged); this.addListener_(EventType.EXPANDED_CHANGED, this.onEventIfInRange); this.addListener_(EventType.FOCUS, this.onFocus); this.addListener_(EventType.HOVER, this.onHover); @@ -365,16 +363,6 @@ }, /** - * @param {!AutomationEvent} evt - */ - onDocumentTitleChanged: function(evt) { - var t = evt.target; - var output = new Output(); - output.format('$name', t); - output.go(); - }, - - /** * Provides all feedback once a focus event fires. * @param {!AutomationEvent} evt */
diff --git a/chrome/browser/resources/chromeos/login/oobe_eula.html b/chrome/browser/resources/chromeos/login/oobe_eula.html index c877ffb..ddff8a8 100644 --- a/chrome/browser/resources/chromeos/login/oobe_eula.html +++ b/chrome/browser/resources/chromeos/login/oobe_eula.html
@@ -81,7 +81,7 @@ <oobe-back-button on-tap="onEulaBackButtonPressed_"></oobe-back-button> <div class="flex"> </div> - <oobe-text-button inverse on-tap="eulaAccepted_" + <oobe-text-button id="acceptButton" inverse on-tap="eulaAccepted_" disabled="[[acceptButtonDisabled]]"> <div i18n-content="oobeEulaAcceptAndContinueButtonText" id="accept-button-text">
diff --git a/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js b/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js index df8647d..349448f 100644 --- a/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js +++ b/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js
@@ -165,6 +165,10 @@ if (state[StateType.OFFSCREEN] || loc.top < 0 || loc.left < 0) return false; + // Skip things that are disabled. + if (node.restriction === chrome.automation.Restriction.DISABLED) + return false; + // These web containers are not directly actionable. if (role === RoleType.WEB_VIEW || role === RoleType.ROOT_WEB_AREA) return false;
diff --git a/chrome/browser/resources/feedback/js/feedback.js b/chrome/browser/resources/feedback/js/feedback.js index 9dee9b14..9f61d4a 100644 --- a/chrome/browser/resources/feedback/js/feedback.js +++ b/chrome/browser/resources/feedback/js/feedback.js
@@ -227,7 +227,8 @@ } // <if expr="chromeos"> if ($('bluetooth-logs-checkbox') != null && - $('bluetooth-logs-checkbox').checked) { + $('bluetooth-logs-checkbox').checked && + !$('bluetooth-checkbox-container').hidden) { feedbackInfo.sendBluetoothLogs = true; feedbackInfo.categoryTag = 'BluetoothReportWithLogs'; }
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.js b/chrome/browser/resources/local_ntp/most_visited_single.js index 28e72355..3177ae7d7 100644 --- a/chrome/browser/resources/local_ntp/most_visited_single.js +++ b/chrome/browser/resources/local_ntp/most_visited_single.js
@@ -426,7 +426,7 @@ const originalTitle = el.innerText; let truncatedTitle = el.innerText; while (el.scrollHeight > el.offsetHeight && truncatedTitle.length > 0) { - el.innerText = (truncatedTitle = truncatedTitle.slice(0, -1)) + '...'; + el.innerText = (truncatedTitle = truncatedTitle.slice(0, -1)) + '\u2026'; } if (truncatedTitle.length === 0) { console.error('Title truncation failed: ' + originalTitle);
diff --git a/chrome/browser/resources/ntp4/apps_page.js b/chrome/browser/resources/ntp4/apps_page.js index 0f6a257..2ebb920 100644 --- a/chrome/browser/resources/ntp4/apps_page.js +++ b/chrome/browser/resources/ntp4/apps_page.js
@@ -161,7 +161,8 @@ if (this.details_) this.details_.disabled = !app.appData.detailsUrl; this.uninstall_.disabled = !app.appData.mayDisable; - this.appinfo_.hidden = !app.appData.isLocallyInstalled; + if (this.appinfo_) + this.appinfo_.hidden = !app.appData.isLocallyInstalled; this.createShortcutSeparator_.hidden = this.createShortcut_.hidden = !app.appData.mayCreateShortcuts;
diff --git a/chrome/browser/resources/settings/a11y_page/tts_subpage.html b/chrome/browser/resources/settings/a11y_page/tts_subpage.html index 2a0a865..47e2e5ab 100644 --- a/chrome/browser/resources/settings/a11y_page/tts_subpage.html +++ b/chrome/browser/resources/settings/a11y_page/tts_subpage.html
@@ -147,15 +147,11 @@ <div id="extension_name_[[index]]" class="start"> [[extension.name]] </div> - <a href="[[extension.optionsPage]]" - tabindex=-1 - target="_blank" + <paper-button on-click="onEngineSettingsTap_" aria-describedby$="extension_name_[[index]]" hidden$="[[!extension.optionsPage]]"> - <paper-button> - $i18n{settings} - </paper-button> - </a> + $i18n{settings} + </paper-button> </div> </template> </template>
diff --git a/chrome/browser/resources/settings/a11y_page/tts_subpage.js b/chrome/browser/resources/settings/a11y_page/tts_subpage.js index f6e16daa..0e27875 100644 --- a/chrome/browser/resources/settings/a11y_page/tts_subpage.js +++ b/chrome/browser/resources/settings/a11y_page/tts_subpage.js
@@ -360,4 +360,13 @@ chrome.metricsPrivate.recordSparseHashable( 'TextToSpeech.Settings.DefaultVoicePicked', newDefault); }, + + /** + * @param {{model:Object}} event + * @private + */ + onEngineSettingsTap_: function(event) { + chrome.send('wakeTtsEngine'); + window.open(event.model.extension.optionsPage); + }, });
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html index 2605e1a..ec867412 100644 --- a/chrome/browser/resources/settings/basic_page/basic_page.html +++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -110,6 +110,14 @@ </settings-internet-page> </settings-section> </template> + <template is="dom-if" if="[[showPage_(pageVisibility.bluetooth)]]" + restamp> + <settings-section page-title="$i18n{bluetoothPageTitle}" + section="bluetooth"> + <settings-bluetooth-page prefs="{{prefs}}"> + </settings-bluetooth-page> + </settings-section> + </template> <template is="dom-if" if="[[canShowMultideviceSection_(showMultidevice, pageVisibility)]]" restamp> @@ -122,14 +130,6 @@ </settings-multidevice-page-container> </settings-section> </template> - <template is="dom-if" if="[[showPage_(pageVisibility.bluetooth)]]" - restamp> - <settings-section page-title="$i18n{bluetoothPageTitle}" - section="bluetooth"> - <settings-bluetooth-page prefs="{{prefs}}"> - </settings-bluetooth-page> - </settings-section> - </template> </if> <template is="dom-if" if="[[showChangePassword]]" restamp> <settings-section section="changePassword">
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_page.html b/chrome/browser/resources/settings/multidevice_page/multidevice_page.html index 06bd0d8..318785d0 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_page.html +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
@@ -59,6 +59,7 @@ if="[[shouldShowButton_(pageContentData)]]" restamp> <paper-button class="secondary-button" + disabled$="[[shouldDisableButton_(pageContentData)]]" on-click="handleButtonClick_"> [[getButtonText_(pageContentData)]] </paper-button>
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_page.js b/chrome/browser/resources/settings/multidevice_page/multidevice_page.js index c881eb5..3aa25fc7 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_page.js +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_page.js
@@ -124,7 +124,7 @@ case settings.MultiDeviceSettingsMode.NO_HOST_SET: return this.i18n('multideviceSetupButton'); case settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER: - return this.i18n('retry'); + return this.i18n('multideviceVerifyButton'); case settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION: return this.i18n('multideviceVerifyButton'); default: @@ -148,6 +148,15 @@ * @return {boolean} * @private */ + shouldDisableButton_: function() { + return this.pageContentData.mode === + settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER; + }, + + /** + * @return {boolean} + * @private + */ shouldShowToggle_: function() { return this.pageContentData.mode === settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED;
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html index 953176b9..e9427a1 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html +++ b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html
@@ -49,8 +49,7 @@ <paper-button id="addAddress" class="secondary-button header-aligned-button" on-click="onAddAddressTap_" - disabled$="[[eitherIsDisabled_(prefs.autofill.enabled.value, - prefs.autofill.profile_enabled.value)]]"> + disabled$="[[!prefs.autofill.profile_enabled.value]]"> $i18n{add} </paper-button> </div>
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js index 3adbdc5..25bd705 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js +++ b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js
@@ -231,17 +231,6 @@ }, /** - * Returns true if either pref value is false. - * @param {boolean} pref1Value - * @param {boolean} pref2Value - * @return {boolean} - * @private - */ - eitherIsDisabled_: function(pref1Value, pref2Value) { - return !pref1Value || !pref2Value; - }, - - /** * Listens for the save-address event, and calls the private API. * @param {!Event} event * @private
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.html b/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.html index 618aea9..c35d1f8 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.html +++ b/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.html
@@ -66,15 +66,13 @@ <paper-button id="addCreditCard" class="secondary-button header-aligned-button" on-click="onAddCreditCardTap_" - disabled$="[[eitherIsDisabled_(prefs.autofill.enabled.value, - prefs.autofill.credit_card_enabled.value)]]"> + disabled$="[[!prefs.autofill.credit_card_enabled.value]]"> $i18n{add} </paper-button> </div> <div class="settings-box two-line" id="migrateCreditCards" - hidden="[[!checkIfMigratable_(syncStatus, creditCards, - prefs.autofill.enabled.value, - prefs.autofill.credit_card_enabled.value)]]" + hidden$="[[!checkIfMigratable_(syncStatus, creditCards, + prefs.autofill.credit_card_enabled.value)]]" on-click="onMigrateCreditCardsClick_" actionable> <div class="start"> [[migrateCreditCardsLabel_]]
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.js b/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.js index a4ab689..e3c141a 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.js +++ b/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.js
@@ -352,17 +352,6 @@ }, /** - * Returns true if either pref value is false. - * @param {boolean} pref1Value - * @param {boolean} pref2Value - * @return {boolean} - * @private - */ - eitherIsDisabled_: function(pref1Value, pref2Value) { - return !pref1Value || !pref2Value; - }, - - /** * Listens for the save-credit-card event, and calls the private API. * @param {!Event} event * @private @@ -383,15 +372,13 @@ /** * @param {!settings.SyncStatus} syncStatus * @param {!Array<!PaymentsManager.CreditCardEntry>} creditCards - * @param {boolean} autofillEnabled * @param {boolean} creditCardEnabled * @return {boolean} Whether to show the migration button. True iff at least - * one valid local card, enable migration, signed-in & synced and both prefs - * enabled. + * one valid local card, enable migration, signed-in & synced and credit card + * pref enabled. * @private */ - checkIfMigratable_: function( - syncStatus, creditCards, autofillEnabled, creditCardEnabled) { + checkIfMigratable_: function(syncStatus, creditCards, creditCardEnabled) { if (syncStatus == undefined) return false; @@ -403,7 +390,8 @@ if (!this.hasGooglePaymentsAccount_) return false; - if (this.eitherIsDisabled_(autofillEnabled, creditCardEnabled)) + // If credit card enabled pref is false, return false. + if (!creditCardEnabled) return false; // If user not signed-in and synced, return false.
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager.cc b/chrome/browser/safe_browsing/advanced_protection_status_manager.cc index 4fe65b8..34b0f02 100644 --- a/chrome/browser/safe_browsing/advanced_protection_status_manager.cc +++ b/chrome/browser/safe_browsing/advanced_protection_status_manager.cc
@@ -91,7 +91,6 @@ return; is_under_advanced_protection_ = info.is_under_advanced_protection; - primary_account_id_ = info.account_id; if (profile_->GetPrefs()->HasPrefPath( prefs::kAdvancedProtectionLastRefreshInUs)) { @@ -157,8 +156,8 @@ return; // If user signed out primary account, cancel refresh. - if (!primary_account_id_.empty() && primary_account_id_ == info.account_id) { - primary_account_id_.clear(); + std::string primary_account_id = GetPrimaryAccountId(); + if (!primary_account_id.empty() && primary_account_id == info.account_id) { is_under_advanced_protection_ = false; OnAdvancedProtectionDisabled(); } @@ -166,15 +165,12 @@ void AdvancedProtectionStatusManager::GoogleSigninSucceeded( const AccountInfo& account_info) { - primary_account_id_ = account_info.account_id; if (account_info.is_under_advanced_protection) OnAdvancedProtectionEnabled(); } void AdvancedProtectionStatusManager::GoogleSignedOut( const AccountInfo& account_info) { - if (primary_account_id_ == account_info.account_id) - primary_account_id_.clear(); OnAdvancedProtectionDisabled(); } @@ -196,7 +192,8 @@ auto* token_service = ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); - if (!token_service || !IsUserSignedIn() || primary_account_id_.empty()) + std::string primary_account_id = GetPrimaryAccountId(); + if (!token_service || primary_account_id.empty()) return; // Refresh OAuth access token. OAuth2TokenService::ScopeSet scopes; @@ -207,9 +204,9 @@ return; token_consumer_.reset( - new AdvancedProtectionTokenConsumer(primary_account_id_, this)); + new AdvancedProtectionTokenConsumer(primary_account_id, this)); access_token_request_ = token_service->StartRequest( - primary_account_id_, scopes, token_consumer_.get()); + primary_account_id, scopes, token_consumer_.get()); } void AdvancedProtectionStatusManager::ScheduleNextRefresh() { @@ -251,15 +248,10 @@ ->is_under_advanced_protection(); } -bool AdvancedProtectionStatusManager::IsUserSignedIn() { - return signin_manager_ && - !signin_manager_->GetAuthenticatedAccountInfo().account_id.empty(); -} - bool AdvancedProtectionStatusManager::IsPrimaryAccount( const AccountInfo& account_info) { - return IsUserSignedIn() && account_info.account_id == - signin_manager_->GetAuthenticatedAccountId(); + return !account_info.account_id.empty() && + account_info.account_id == GetPrimaryAccountId(); } void AdvancedProtectionStatusManager::OnGetIDToken( @@ -267,16 +259,23 @@ const std::string& id_token) { // Skips if the ID token is not for the primary account. Or user is no longer // signed in. - if (account_id != primary_account_id_ || !IsUserSignedIn()) + std::string primary_account_id = GetPrimaryAccountId(); + if (primary_account_id.empty() || account_id != primary_account_id) return; gaia::TokenServiceFlags service_flags = gaia::ParseServiceFlags(id_token); - // |OnAccountUpdated()| will only be triggered if the advanced protection - // status changed. Therefore, we need to call |UpdateLastRefreshTime()| here - // to force update and persist last refresh time. - account_tracker_service_->SetIsAdvancedProtectionAccount( - primary_account_id_, service_flags.is_under_advanced_protection); - UpdateLastRefreshTime(); + + // If there's a change in advanced protection status, updates account info. + // This also triggers |OnAccountUpdated()|. + if (is_under_advanced_protection_ != + service_flags.is_under_advanced_protection) { + account_tracker_service_->SetIsAdvancedProtectionAccount( + GetPrimaryAccountId(), service_flags.is_under_advanced_protection); + } else if (service_flags.is_under_advanced_protection) { + OnAdvancedProtectionEnabled(); + } else { + OnAdvancedProtectionDisabled(); + } } void AdvancedProtectionStatusManager::OnTokenRefreshDone( @@ -310,4 +309,9 @@ MaybeRefreshOnStartUp(); } +std::string AdvancedProtectionStatusManager::GetPrimaryAccountId() const { + return signin_manager_ ? signin_manager_->GetAuthenticatedAccountId() + : std::string(); +} + } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager.h b/chrome/browser/safe_browsing/advanced_protection_status_manager.h index 377e8046..a5c943f5 100644 --- a/chrome/browser/safe_browsing/advanced_protection_status_manager.h +++ b/chrome/browser/safe_browsing/advanced_protection_status_manager.h
@@ -63,9 +63,6 @@ bool IsRefreshScheduled(); - // If primary user of this profile is signed in. - bool IsUserSignedIn(); - private: FRIEND_TEST_ALL_PREFIXES(AdvancedProtectionStatusManagerTest, NotSignedInOnStartUp); @@ -82,6 +79,8 @@ FRIEND_TEST_ALL_PREFIXES(AdvancedProtectionStatusManagerTest, SignInAndSignOutEvent); FRIEND_TEST_ALL_PREFIXES(AdvancedProtectionStatusManagerTest, AccountRemoval); + FRIEND_TEST_ALL_PREFIXES(AdvancedProtectionStatusManagerTest, + StayInAdvancedProtection); void Initialize(); @@ -130,6 +129,10 @@ // Only called in tests. void SetMinimumRefreshDelay(const base::TimeDelta& delay); + // Gets the account ID of the primary account of |profile_|. + // Returns an empty string if user is not signed in. + std::string GetPrimaryAccountId() const; + // Only called in tests to set a customized minimum delay. AdvancedProtectionStatusManager(Profile* profile, const base::TimeDelta& min_delay); @@ -142,10 +145,6 @@ // Is the profile account under advanced protection. bool is_under_advanced_protection_; - // Account ID of the primary account of |profile_|. If this profile is not - // signed in, this field will be empty. - std::string primary_account_id_; - std::unique_ptr<AdvancedProtectionTokenConsumer> token_consumer_; std::unique_ptr<OAuth2TokenService::Request> access_token_request_;
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc b/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc index f459a39f..98d3929 100644 --- a/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc +++ b/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc
@@ -47,7 +47,6 @@ ~AdvancedProtectionStatusManagerTest() override {} -#if !defined(OS_CHROMEOS) std::string SignIn(const std::string& gaia_id, const std::string& email, bool is_under_advanced_protection) { @@ -57,11 +56,14 @@ account_info.is_under_advanced_protection = is_under_advanced_protection; std::string account_id = account_tracker_service_->SeedAccountInfo(account_info); +#if defined(OS_CHROMEOS) + fake_signin_manager_->SignIn(account_id); +#else fake_signin_manager_->SignIn(gaia_id, email, "password"); +#endif GetTokenService()->UpdateCredentials(account_id, "refresh_token"); return account_id; } -#endif FakeProfileOAuth2TokenService* GetTokenService() { ProfileOAuth2TokenService* service = @@ -104,13 +106,12 @@ } // namespace -#if !defined(OS_CHROMEOS) TEST_F(AdvancedProtectionStatusManagerTest, NotSignedInOnStartUp) { ASSERT_FALSE(testing_profile_->GetPrefs()->HasPrefPath( prefs::kAdvancedProtectionLastRefreshInUs)); AdvancedProtectionStatusManager aps_manager( testing_profile_.get(), base::TimeDelta() /*no min delay*/); - ASSERT_FALSE(aps_manager.IsUserSignedIn()); + ASSERT_TRUE(aps_manager.GetPrimaryAccountId().empty()); // If user's not signed-in. No refresh is required. EXPECT_FALSE(aps_manager.is_under_advanced_protection()); @@ -132,7 +133,7 @@ AdvancedProtectionStatusManager aps_manager( testing_profile_.get(), base::TimeDelta() /*no min delay*/); base::RunLoop().RunUntilIdle(); - ASSERT_TRUE(aps_manager.IsUserSignedIn()); + ASSERT_FALSE(aps_manager.GetPrimaryAccountId().empty()); // An OAuth2 access token request should be sent. ASSERT_TRUE(IsRequestActive()); @@ -158,7 +159,7 @@ AdvancedProtectionStatusManager aps_manager( testing_profile_.get(), base::TimeDelta() /*no min delay*/); base::RunLoop().RunUntilIdle(); - ASSERT_TRUE(aps_manager.IsUserSignedIn()); + ASSERT_FALSE(aps_manager.GetPrimaryAccountId().empty()); // An OAuth2 access token request should be sent. ASSERT_TRUE(IsRequestActive()); @@ -183,7 +184,7 @@ SignIn("gaia_id", "email", /* is_under_advanced_protection = */ false); AdvancedProtectionStatusManager aps_manager( testing_profile_.get(), base::TimeDelta() /*no min delay*/); - ASSERT_TRUE(aps_manager.IsUserSignedIn()); + ASSERT_FALSE(aps_manager.GetPrimaryAccountId().empty()); base::RunLoop().RunUntilIdle(); // An OAuth2 access token request should be sent. ASSERT_TRUE(IsRequestActive()); @@ -230,7 +231,7 @@ SignIn("gaia_id", "email", /* is_under_advanced_protection = */ true); AdvancedProtectionStatusManager aps_manager( testing_profile_.get(), base::TimeDelta() /*no min delay*/); - ASSERT_TRUE(aps_manager.IsUserSignedIn()); + ASSERT_FALSE(aps_manager.GetPrimaryAccountId().empty()); ASSERT_TRUE(aps_manager.is_under_advanced_protection()); // Since user is already under advanced protection, no need to refresh. @@ -240,11 +241,37 @@ aps_manager.UnsubscribeFromSigninEvents(); } +TEST_F(AdvancedProtectionStatusManagerTest, StayInAdvancedProtection) { + base::Time last_update = base::Time::Now(); + testing_profile_->GetPrefs()->SetInt64( + prefs::kAdvancedProtectionLastRefreshInUs, + last_update.ToDeltaSinceWindowsEpoch().InMicroseconds()); + + std::string account_id = + SignIn("gaia_id", "email", /* is_under_advanced_protection = */ true); + AdvancedProtectionStatusManager aps_manager( + testing_profile_.get(), base::TimeDelta() /*no min delay*/); + ASSERT_FALSE(aps_manager.GetPrimaryAccountId().empty()); + ASSERT_TRUE(aps_manager.is_under_advanced_protection()); + + // Simulate gets refresh token. + aps_manager.OnGetIDToken(account_id, kIdTokenAdvancedProtectionEnabled); + EXPECT_GT( + base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromMicroseconds( + testing_profile_->GetPrefs()->GetInt64( + prefs::kAdvancedProtectionLastRefreshInUs))), + last_update); + EXPECT_TRUE(aps_manager.IsRefreshScheduled()); + aps_manager.UnsubscribeFromSigninEvents(); +} + +#if !defined(OS_CHROMEOS) +// Not applicable to Chrome OS. TEST_F(AdvancedProtectionStatusManagerTest, SignInAndSignOutEvent) { AdvancedProtectionStatusManager aps_manager( testing_profile_.get(), base::TimeDelta() /*no min delay*/); ASSERT_FALSE(aps_manager.is_under_advanced_protection()); - ASSERT_FALSE(aps_manager.IsUserSignedIn()); + ASSERT_TRUE(aps_manager.GetPrimaryAccountId().empty()); SignIn("gaia_id", "email", /* is_under_advanced_protection = */ true); EXPECT_TRUE(aps_manager.is_under_advanced_protection()); @@ -257,12 +284,13 @@ EXPECT_FALSE(aps_manager.IsRefreshScheduled()); aps_manager.UnsubscribeFromSigninEvents(); } +#endif TEST_F(AdvancedProtectionStatusManagerTest, AccountRemoval) { AdvancedProtectionStatusManager aps_manager( testing_profile_.get(), base::TimeDelta() /*no min delay*/); ASSERT_FALSE(aps_manager.is_under_advanced_protection()); - ASSERT_FALSE(aps_manager.IsUserSignedIn()); + ASSERT_TRUE(aps_manager.GetPrimaryAccountId().empty()); std::string account_id = SignIn("gaia_id", "email", /* is_under_advanced_protection = */ false); @@ -282,5 +310,5 @@ EXPECT_FALSE(aps_manager.IsRefreshScheduled()); aps_manager.UnsubscribeFromSigninEvents(); } -#endif + } // namespace safe_browsing
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc index 75e2ddb5..cdbdd617d 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc
@@ -31,7 +31,7 @@ arc::ArcServiceManager::Get() ? ARC_GET_INSTANCE_FOR_METHOD( arc::ArcServiceManager::Get()->arc_bridge_service()->app(), - GetAppShortcutItems) + GetAppShortcutGlobalQueryItems) : nullptr; if (!app_instance || query.empty()) { @@ -43,11 +43,12 @@ weak_ptr_factory_.InvalidateWeakPtrs(); app_instance->GetAppShortcutGlobalQueryItems( base::UTF16ToUTF8(query), max_results_, - base::BindOnce(&ArcAppShortcutsSearchProvider::OnGetAppShortcutItems, - weak_ptr_factory_.GetWeakPtr())); + base::BindOnce( + &ArcAppShortcutsSearchProvider::OnGetAppShortcutGlobalQueryItems, + weak_ptr_factory_.GetWeakPtr())); } -void ArcAppShortcutsSearchProvider::OnGetAppShortcutItems( +void ArcAppShortcutsSearchProvider::OnGetAppShortcutGlobalQueryItems( std::vector<arc::mojom::AppShortcutItemPtr> shortcut_items) { SearchProvider::Results search_results; for (auto& item : shortcut_items) {
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h index 313cb60..c951990 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h +++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h
@@ -29,7 +29,7 @@ void Start(const base::string16& query) override; private: - void OnGetAppShortcutItems( + void OnGetAppShortcutGlobalQueryItems( std::vector<arc::mojom::AppShortcutItemPtr> shortcut_items); const int max_results_;
diff --git a/chrome/browser/ui/app_list/test/fake_profile.cc b/chrome/browser/ui/app_list/test/fake_profile.cc index 1037031..97ef0aa 100644 --- a/chrome/browser/ui/app_list/test/fake_profile.cc +++ b/chrome/browser/ui/app_list/test/fake_profile.cc
@@ -183,10 +183,6 @@ void FakeProfile::OnLogin() {} void FakeProfile::InitChromeOSPreferences() {} -chrome_browser_net::Predictor* FakeProfile::GetNetworkPredictor() { - return nullptr; -} - GURL FakeProfile::GetHomePage() { return GURL(); }
diff --git a/chrome/browser/ui/app_list/test/fake_profile.h b/chrome/browser/ui/app_list/test/fake_profile.h index 49d647a..97e5e65 100644 --- a/chrome/browser/ui/app_list/test/fake_profile.h +++ b/chrome/browser/ui/app_list/test/fake_profile.h
@@ -86,7 +86,6 @@ void OnLogin() override; void InitChromeOSPreferences() override; - chrome_browser_net::Predictor* GetNetworkPredictor() override; GURL GetHomePage() override; bool WasCreatedByVersionOrLater(const std::string& version) override; void SetExitType(ExitType exit_type) override;
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm index f94bbcc..a4caa68 100644 --- a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm +++ b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm
@@ -8,7 +8,6 @@ #include "base/mac/mac_util.h" #include "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" -#include "base/test/scoped_feature_list.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/ui/browser.h" @@ -17,7 +16,6 @@ #include "chrome/browser/ui/cocoa/test/cocoa_profile_test.h" #import "chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" -#include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" #include "testing/gtest/include/gtest/gtest.h" @@ -51,8 +49,6 @@ CocoaProfileTest::SetUp(); ASSERT_TRUE(browser()); - feature_list.InitAndEnableFeature(features::kBrowserTouchBar); - command_updater_ = browser()->command_controller(); touch_bar_.reset([[BrowserWindowDefaultTouchBar alloc] @@ -79,9 +75,6 @@ CommandUpdater* command_updater_; // Weak, owned by Browser. - // Used to enable the the browser window touch bar. - base::test::ScopedFeatureList feature_list; - base::scoped_nsobject<BrowserWindowDefaultTouchBar> touch_bar_; };
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc index 7e2af8c..aaad2f0 100644 --- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc +++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
@@ -27,7 +27,6 @@ #include "chrome/browser/extensions/api/omnibox/omnibox_api.h" #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/predictors/autocomplete_action_predictor.h" #include "chrome/browser/predictors/autocomplete_action_predictor_factory.h" #include "chrome/browser/predictors/loading_predictor.h" @@ -502,10 +501,6 @@ loading_predictor->PrepareForPageLoad( match.destination_url, predictors::HintOrigin::OMNIBOX, predictors::AutocompleteActionPredictor::IsPreconnectable(match)); - } else if (profile_->GetNetworkPredictor()) { - profile_->GetNetworkPredictor()->AnticipateOmniboxUrl( - match.destination_url, - predictors::AutocompleteActionPredictor::IsPreconnectable(match)); } // We could prefetch the alternate nav URL, if any, but because there // can be many of these as a user types an initial series of characters,
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc index b8094f7..a91e30b 100644 --- a/chrome/browser/ui/startup/startup_browser_creator.cc +++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -35,7 +35,6 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/startup_helper.h" #include "chrome/browser/first_run/first_run.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/profiles/profile.h" @@ -319,11 +318,6 @@ in_synchronous_profile_launch_ = process_startup == chrome::startup::IS_PROCESS_STARTUP; - // ChromeOS does a direct browser launch from UserSessionManager, so this is - // the earliest place we can enable the log. - if (command_line.HasSwitch(switches::kDnsLogDetails)) - chrome_browser_net::EnablePredictorDetailedLog(true); - // Continue with the incognito profile from here on if Incognito mode // is forced. if (IncognitoModePrefs::ShouldLaunchIncognito(command_line,
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index 17e1fdd..d2d948e 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -32,7 +32,6 @@ #include "chrome/browser/metrics/oom/out_of_memory_reporter.h" #include "chrome/browser/metrics/renderer_uptime_web_contents_observer.h" #include "chrome/browser/net/net_error_tab_helper.h" -#include "chrome/browser/net/predictor_tab_helper.h" #include "chrome/browser/ntp_snippets/bookmark_last_visit_updater.h" #include "chrome/browser/page_load_metrics/page_load_metrics_initialize.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" @@ -195,7 +194,6 @@ web_contents, BookmarkModelFactory::GetForBrowserContext( web_contents->GetBrowserContext())); chrome_browser_net::NetErrorTabHelper::CreateForWebContents(web_contents); - chrome_browser_net::PredictorTabHelper::CreateForWebContents(web_contents); ChromeLanguageDetectionTabHelper::CreateForWebContents(web_contents); ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient( web_contents,
diff --git a/chrome/browser/ui/views/dropdown_bar_host.cc b/chrome/browser/ui/views/dropdown_bar_host.cc index 56918af..355f382 100644 --- a/chrome/browser/ui/views/dropdown_bar_host.cc +++ b/chrome/browser/ui/views/dropdown_bar_host.cc
@@ -50,6 +50,7 @@ // Initialize the host. host_.reset(new ThemeCopyingWidget(browser_view_->GetWidget())); views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); + params.name = "DropdownBarHost"; params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.parent = browser_view_->GetWidget()->GetNativeView(); params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_view.cc b/chrome/browser/ui/views/media_router/cast_dialog_view.cc index 05c37943d..437a072d 100644 --- a/chrome/browser/ui/views/media_router/cast_dialog_view.cc +++ b/chrome/browser/ui/views/media_router/cast_dialog_view.cc
@@ -143,7 +143,9 @@ void CastDialogView::OnControllerInvalidated() { controller_ = nullptr; - MaybeSizeToContents(); + // We don't call HideDialog() here because if the invalidation was caused by + // activating the toolbar icon in order to close the dialog, then it would + // cause the dialog to immediately open again. } void CastDialogView::ButtonPressed(views::Button* sender, @@ -313,6 +315,9 @@ } void CastDialogView::SinkPressed(size_t index) { + if (!controller_) + return; + const UIMediaSink& sink = sink_buttons_.at(index)->sink(); if (sink.route_id.empty()) { base::Optional<MediaCastMode> cast_mode = GetCastModeToUse(sink);
diff --git a/chrome/browser/ui/webui/about_ui.cc b/chrome/browser/ui/webui/about_ui.cc index f177842..6891c0b 100644 --- a/chrome/browser/ui/webui/about_ui.cc +++ b/chrome/browser/ui/webui/about_ui.cc
@@ -39,7 +39,6 @@ #include "chrome/browser/about_flags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/defaults.h" -#include "chrome/browser/net/predictor.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/browser_dialogs.h"
diff --git a/chrome/browser/ui/webui/settings/tts_handler.cc b/chrome/browser/ui/webui/settings/tts_handler.cc index 0984278..e441b17 100644 --- a/chrome/browser/ui/webui/settings/tts_handler.cc +++ b/chrome/browser/ui/webui/settings/tts_handler.cc
@@ -18,12 +18,16 @@ #include "content/public/browser/web_ui.h" #include "extensions/browser/event_router.h" #include "extensions/browser/extension_registry.h" +#include "extensions/browser/process_manager.h" #include "extensions/common/extension.h" #include "extensions/common/extension_set.h" #include "extensions/common/manifest_handlers/options_page_info.h" #include "ui/base/l10n/l10n_util.h" namespace settings { +TtsHandler::TtsHandler() : weak_factory_(this) {} + +TtsHandler::~TtsHandler() {} void TtsHandler::HandleGetAllTtsVoiceData(const base::ListValue* args) { OnVoicesChanged(); @@ -31,8 +35,8 @@ void TtsHandler::HandleGetTtsExtensions(const base::ListValue* args) { // Ensure the built in tts engine is loaded to be able to respond to messages. - TtsExtensionEngine::GetInstance()->LoadBuiltInTtsExtension( - Profile::FromWebUI(web_ui())); + WakeTtsEngine(nullptr); + base::ListValue responses; Profile* profile = Profile::FromWebUI(web_ui()); extensions::ExtensionRegistry* registry = @@ -141,6 +145,9 @@ web_ui()->RegisterMessageCallback( "previewTtsVoice", base::BindRepeating(&TtsHandler::HandlePreviewTtsVoice, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "wakeTtsEngine", + base::BindRepeating(&TtsHandler::WakeTtsEngine, base::Unretained(this))); } void TtsHandler::OnJavascriptAllowed() { @@ -163,4 +170,17 @@ : 0; } +void TtsHandler::WakeTtsEngine(const base::ListValue* args) { + Profile* profile = Profile::FromWebUI(web_ui()); + TtsExtensionEngine::GetInstance()->LoadBuiltInTtsExtension(profile); + extensions::ProcessManager::Get(profile)->WakeEventPage( + extension_misc::kSpeechSynthesisExtensionId, + base::BindOnce(&TtsHandler::OnTtsEngineAwake, + weak_factory_.GetWeakPtr())); +} + +void TtsHandler::OnTtsEngineAwake(bool success) { + OnVoicesChanged(); +} + } // namespace settings
diff --git a/chrome/browser/ui/webui/settings/tts_handler.h b/chrome/browser/ui/webui/settings/tts_handler.h index 94dfef0..0f9d264 100644 --- a/chrome/browser/ui/webui/settings/tts_handler.h +++ b/chrome/browser/ui/webui/settings/tts_handler.h
@@ -5,16 +5,19 @@ #ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_TTS_HANDLER_H_ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_TTS_HANDLER_H_ +#include "base/memory/weak_ptr.h" #include "chrome/browser/speech/tts_controller.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +class Profile; + namespace settings { // Chrome "/manageAccessibility/tts/*" settings page UI handler. class TtsHandler : public SettingsPageUIHandler, public VoicesChangedDelegate { public: - TtsHandler() = default; - ~TtsHandler() override = default; + TtsHandler(); + ~TtsHandler() override; void HandleGetAllTtsVoiceData(const base::ListValue* args); void HandleGetTtsExtensions(const base::ListValue* args); @@ -29,9 +32,13 @@ void OnVoicesChanged() override; private: + void WakeTtsEngine(const base::ListValue* args); + void OnTtsEngineAwake(bool success); int GetVoiceLangMatchScore(const VoiceData* voice, const std::string& app_locale); + base::WeakPtrFactory<TtsHandler> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(TtsHandler); };
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 282e17db8..12073395 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -115,12 +115,6 @@ const base::Feature kBrowserHangFixesExperiment{ "BrowserHangFixesExperiment", base::FEATURE_DISABLED_BY_DEFAULT}; -#if defined(OS_MACOSX) -// Enables or disables the browser's touch bar. -const base::Feature kBrowserTouchBar{"BrowserTouchBar", - base::FEATURE_ENABLED_BY_DEFAULT}; -#endif - // Enables or disables redirecting users who get an interstitial when // accessing https://support.google.com/chrome/answer/6098869 to local // connection help content. @@ -453,7 +447,7 @@ // Delegate permissions to cross-origin iframes when the feature has been // allowed by feature policy. const base::Feature kPermissionDelegation{"PermissionDelegation", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Disables PostScript generation when printing to PostScript capable printers // and instead sends Emf files.
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index a144f0c..3cae097 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -77,10 +77,6 @@ COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kBrowserHangFixesExperiment; -#if defined(OS_MACOSX) -COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kBrowserTouchBar; -#endif - COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kBundledConnectionHelpFeature;
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl index ae3d2198..3471aee 100644 --- a/chrome/common/extensions/api/autotest_private.idl +++ b/chrome/common/extensions/api/autotest_private.idl
@@ -86,6 +86,20 @@ }; callback PlayStoreStateCallback = void (PlayStoreState result); + dictionary HistogramBucket { + // Minimum sample value that can be stored in this bucket (i.e. inclusive). + long min; + // Exclusive maximum value for samples stored this bucket. + long max; + // Number of samples stored in this bucket. + long count; + }; + dictionary Histogram { + // Buckets containing samples. + HistogramBucket[] buckets; + }; + callback HistogramCallback = void (Histogram histogram); + callback IsAppShownCallback = void (boolean appShown); callback VoidCallback = void (); @@ -168,6 +182,11 @@ // |callback|: Called when the operation has completed. static void setPlayStoreEnabled(boolean enabled, VoidCallback callback); + // Get details about a histogram displayed at chrome://histogram. + // |name|: Histogram name, e.g. "Accessibility.CrosAutoclick". + // |callback|: Invoked with details. + static void getHistogram(DOMString name, HistogramCallback callback); + // Run the crostini installer GUI to install the default crostini // vm / container and create sshfs mount. The installer launches the // crostini terminal app on completion. The installer expects that
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index ecec4e88..2a75758 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -431,17 +431,6 @@ // A boolean pref set to true if we're using Link Doctor error pages. const char kAlternateErrorPagesEnabled[] = "alternate_error_pages.enabled"; -// An adaptively identified list of domain names to be pre-fetched during the -// next startup, based on what was actually needed during this startup. -const char kDnsPrefetchingStartupList[] = "dns_prefetching.startup_list"; - -// A list of host names used to fetch web pages, and their commonly used -// sub-resource hostnames (and expected latency benefits from pre-resolving, or -// preconnecting to, such sub-resource hostnames). -// This list is adaptively grown and pruned. -const char kDnsPrefetchingHostReferralList[] = - "dns_prefetching.host_referral_list"; - // Controls if the QUIC protocol is allowed. const char kQuicAllowed[] = "net.quic_allowed";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index ffb27c3..88a4616 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -175,8 +175,6 @@ #endif extern const char kPromptForDownload[]; extern const char kAlternateErrorPagesEnabled[]; -extern const char kDnsPrefetchingStartupList[]; -extern const char kDnsPrefetchingHostReferralList[]; extern const char kQuicAllowed[]; extern const char kNetworkQualities[]; #if defined(OS_ANDROID)
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index e5aa3856..6ccad71 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc
@@ -271,10 +271,10 @@ "https://support.google.com/chromebook?p=instant_tethering"; const char kMultiDeviceLearnMoreURL[] = - "https://support.google.com/chromebook?p=multidevice-placeholder"; + "https://support.google.com/pixelbook/?p=better_together"; const char kAndroidMessagesLearnMoreURL[] = - "https://support.google.com/chromebook?p=messages-for-web-placeholder"; + "https://support.google.com/pixelbook/?p=bettertogether_android_messages"; const char kLanguageSettingsLearnMoreUrl[] = "https://support.google.com/chromebook/answer/1059490";
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc index 8b9319db..b728991e8 100644 --- a/chrome/renderer/searchbox/searchbox_extension.cc +++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -44,6 +44,8 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/base/window_open_disposition.h" #include "ui/events/keycodes/keyboard_codes.h" +#include "ui/gfx/text_constants.h" +#include "ui/gfx/text_elider.h" #include "url/gurl.h" #include "url/url_constants.h" #include "v8/include/v8.h" @@ -89,6 +91,9 @@ const char kLTRHtmlTextDirection[] = "ltr"; const char kRTLHtmlTextDirection[] = "rtl"; +// Max character limit for custom link titles. +const size_t kMaxCustomLinkTitleLength = 150; + void Dispatch(blink::WebLocalFrame* frame, const blink::WebString& script) { if (!frame) return; @@ -858,20 +863,26 @@ if (!search_box || !HasOrigin(GURL(chrome::kChromeSearchMostVisitedUrl))) return; + // Limit the title to |kMaxCustomLinkTitleLength| characters. If truncated, + // adds an ellipsis. + base::string16 truncated_title = + gfx::TruncateString(base::UTF8ToUTF16(title), kMaxCustomLinkTitleLength, + gfx::CHARACTER_BREAK); + const GURL gurl(url); // If rid is -1, adds a new link. Otherwise, updates the existing link // indicated by the rid (empty fields will passed as empty strings). This will // initialize custom links if they have not already been initialized. if (rid == -1) { - if (!gurl.is_valid() || title.empty()) + if (!gurl.is_valid() || truncated_title.empty()) return; - search_box->AddCustomLink(gurl, title); + search_box->AddCustomLink(gurl, base::UTF16ToUTF8(truncated_title)); search_box->LogEvent(NTPLoggingEventType::NTP_CUSTOMIZE_SHORTCUT_ADD); } else { // Check that the URL, if provided, is valid. if (!url.empty() && !gurl.is_valid()) return; - search_box->UpdateCustomLink(rid, gurl, title); + search_box->UpdateCustomLink(rid, gurl, base::UTF16ToUTF8(truncated_title)); search_box->LogEvent(NTPLoggingEventType::NTP_CUSTOMIZE_SHORTCUT_UPDATE); } }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index a056ae6..4e2caf9e 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -670,7 +670,6 @@ "../browser/net/nqe/ui_network_quality_estimator_service_test_util.cc", "../browser/net/nqe/ui_network_quality_estimator_service_test_util.h", "../browser/net/nss_context_chromeos_browsertest.cc", - "../browser/net/predictor_browsertest.cc", "../browser/net/profile_network_context_service_browsertest.cc", "../browser/net/proxy_browsertest.cc", "../browser/net/reporting_browsertest.cc", @@ -2509,13 +2508,11 @@ "../browser/net/dns_probe_service_unittest.cc", "../browser/net/file_downloader_unittest.cc", "../browser/net/net_error_tab_helper_unittest.cc", - "../browser/net/predictor_unittest.cc", "../browser/net/probe_message_unittest.cc", "../browser/net/quota_policy_channel_id_store_unittest.cc", "../browser/net/reporting_permissions_checker_unittest.cc", "../browser/net/spdyproxy/data_reduction_proxy_chrome_settings_unittest.cc", "../browser/net/spdyproxy/data_reduction_proxy_settings_unittest_android.cc", - "../browser/net/url_info_unittest.cc", "../browser/notifications/metrics/notification_metrics_logger_unittest.cc", "../browser/notifications/notification_channels_provider_android_unittest.cc", "../browser/notifications/notification_permission_context_unittest.cc", @@ -5015,6 +5012,7 @@ "../browser/chromeos/login/mixin_based_browser_test.cc", "../browser/chromeos/login/mixin_based_browser_test.h", "../browser/chromeos/login/oobe_browsertest.cc", + "../browser/chromeos/login/oobe_interactive_ui_test.cc", "../browser/chromeos/login/screenshot_testing/SkDiffPixelsMetric.h", "../browser/chromeos/login/screenshot_testing/SkDiffPixelsMetric_cpu.cpp", "../browser/chromeos/login/screenshot_testing/SkImageDiffer.cpp",
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc index abcc696..ad814492 100644 --- a/chrome/test/base/testing_profile.cc +++ b/chrome/test/base/testing_profile.cc
@@ -916,10 +916,6 @@ history::BlockUntilHistoryProcessesPendingRequests(history_service); } -chrome_browser_net::Predictor* TestingProfile::GetNetworkPredictor() { - return NULL; -} - GURL TestingProfile::GetHomePage() { return GURL(chrome::kChromeUINewTabURL); }
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h index 8de5614..5f3f052 100644 --- a/chrome/test/base/testing_profile.h +++ b/chrome/test/base/testing_profile.h
@@ -351,7 +351,6 @@ // history service processes all pending requests. void BlockUntilHistoryProcessesPendingRequests(); - chrome_browser_net::Predictor* GetNetworkPredictor() override; GURL GetHomePage() override; PrefService* GetOffTheRecordPrefs() override;
diff --git a/chrome/test/chromedriver/client/chromedriver.py b/chrome/test/chromedriver/client/chromedriver.py index 21d34add..4fe87a82 100644 --- a/chrome/test/chromedriver/client/chromedriver.py +++ b/chrome/test/chromedriver/client/chromedriver.py
@@ -161,6 +161,10 @@ # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1695 chrome_switches.append('disable-gpu') + if chrome_switches is None: + chrome_switches = [] + chrome_switches.append('force-color-profile=srgb') + if chrome_switches: assert type(chrome_switches) is list options['args'] = chrome_switches @@ -491,6 +495,9 @@ def FullScreenWindow(self): return self.ExecuteCommand(Command.FULLSCREEN_WINDOW) + def TakeScreenshot(self): + return self.ExecuteCommand(Command.SCREENSHOT) + def Quit(self): """Quits the browser and ends the session.""" self.ExecuteCommand(Command.QUIT)
diff --git a/chrome/test/chromedriver/client/webelement.py b/chrome/test/chromedriver/client/webelement.py index f1a0796..6e7a450 100644 --- a/chrome/test/chromedriver/client/webelement.py +++ b/chrome/test/chromedriver/client/webelement.py
@@ -66,3 +66,6 @@ def IsDisplayed(self): return self._Execute(Command.IS_ELEMENT_DISPLAYED) + + def TakeElementScreenshot(self): + return self._Execute(Command.ELEMENT_SCREENSHOT)
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index 195f4e0..79ed9d9 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -1696,6 +1696,19 @@ self._driver.FindElement('id', 'top') thread.join() + def testTakeElementScreenshot(self): + self._driver.Load(self.GetHttpUrlForFile( + '/chromedriver/page_with_redBox.html')) + elementScreenshot = self._driver.FindElement( + 'id', 'box').TakeElementScreenshot() + self.assertIsNotNone(elementScreenshot) + dataActualScreenshot = base64.b64decode(elementScreenshot) + filenameOfGoldenScreenshot = os.path.join(chrome_paths.GetTestData(), + 'chromedriver/goldenScreenshots', + 'redBoxScreenshot.png') + imageGoldenScreenshot = open(filenameOfGoldenScreenshot, 'rb').read() + self.assertEquals(imageGoldenScreenshot, dataActualScreenshot) + class ChromeDriverSiteIsolation(ChromeDriverBaseTestWithWebServer): """Tests for ChromeDriver with the new Site Isolation Chrome feature.
diff --git a/chrome/test/data/chromedriver/goldenScreenshots/redBoxScreenshot.png b/chrome/test/data/chromedriver/goldenScreenshots/redBoxScreenshot.png new file mode 100644 index 0000000..5f2118b --- /dev/null +++ b/chrome/test/data/chromedriver/goldenScreenshots/redBoxScreenshot.png Binary files differ
diff --git a/chrome/test/data/chromedriver/page_with_redBox.html b/chrome/test/data/chromedriver/page_with_redBox.html new file mode 100644 index 0000000..cf736970 --- /dev/null +++ b/chrome/test/data/chromedriver/page_with_redBox.html
@@ -0,0 +1,6 @@ +<!DOCTYPE html> +<html> + <body> + <div id='box' style='width: 200px; height: 100px; background-color: red'></div> + </body> +</html> \ No newline at end of file
diff --git a/chrome/test/data/extensions/api_test/autotest_private/test.js b/chrome/test/data/extensions/api_test/autotest_private/test.js index 015513d..eaaa45ce 100644 --- a/chrome/test/data/extensions/api_test/autotest_private/test.js +++ b/chrome/test/data/extensions/api_test/autotest_private/test.js
@@ -28,7 +28,7 @@ function loginStatus() { chrome.autotestPrivate.loginStatus( chrome.test.callbackPass(function(status) { - chrome.test.assertEq(typeof(status), 'object'); + chrome.test.assertEq(typeof status, 'object'); chrome.test.assertTrue(status.hasOwnProperty("isLoggedIn")); chrome.test.assertTrue(status.hasOwnProperty("isOwner")); chrome.test.assertTrue(status.hasOwnProperty("isScreenLocked")); @@ -43,7 +43,7 @@ function getExtensionsInfo() { chrome.autotestPrivate.getExtensionsInfo( chrome.test.callbackPass(function(extInfo) { - chrome.test.assertEq(typeof(extInfo), 'object'); + chrome.test.assertEq(typeof extInfo, 'object'); chrome.test.assertTrue(extInfo.hasOwnProperty('extensions')); chrome.test.assertTrue(extInfo.extensions.constructor === Array); for (var i = 0; i < extInfo.extensions.length; ++i) { @@ -134,6 +134,24 @@ }); }); }, + function getHistogramExists() { + // Request an arbitrary histogram that is reported once at startup and seems + // unlikely to go away. + chrome.autotestPrivate.getHistogram( + "Startup.BrowserProcessImpl_PreMainMessageLoopRunTime", + chrome.test.callbackPass(function(histogram) { + chrome.test.assertEq(typeof histogram, 'object'); + chrome.test.assertEq(histogram.buckets.length, 1); + chrome.test.assertEq(histogram.buckets[0].count, 1); + chrome.test.assertTrue( + histogram.buckets[0].max > histogram.buckets[0].min); + })); + }, + function getHistogramMissing() { + chrome.autotestPrivate.getHistogram( + 'Foo.Nonexistent', + chrome.test.callbackFail('Histogram Foo.Nonexistent not found')); + }, // This test verifies that Play Store window is not shown by default but // Chrome is shown. function isAppShown() {
diff --git a/chrome/test/data/webui/cr_elements/cr_action_menu_test.js b/chrome/test/data/webui/cr_elements/cr_action_menu_test.js index 78a8800c..88f081b 100644 --- a/chrome/test/data/webui/cr_elements/cr_action_menu_test.js +++ b/chrome/test/data/webui/cr_elements/cr_action_menu_test.js
@@ -60,19 +60,19 @@ test('hidden or disabled items', function() { menu.showAt(dots); down(); - assertEquals(menu.root.activeElement, items[0]); + assertEquals(getDeepActiveElement(), items[0]); menu.close(); items[0].hidden = true; menu.showAt(dots); down(); - assertEquals(menu.root.activeElement, items[1]); + assertEquals(getDeepActiveElement(), items[1]); menu.close(); items[1].disabled = true; menu.showAt(dots); down(); - assertEquals(menu.root.activeElement, items[2]); + assertEquals(getDeepActiveElement(), items[2]); }); test('focus after down/up arrow', function() { @@ -80,30 +80,30 @@ // The menu should be focused when shown, but not on any of the items. assertEquals(menu, document.activeElement); - assertNotEquals(items[0], menu.root.activeElement); - assertNotEquals(items[1], menu.root.activeElement); - assertNotEquals(items[2], menu.root.activeElement); + assertNotEquals(items[0], getDeepActiveElement()); + assertNotEquals(items[1], getDeepActiveElement()); + assertNotEquals(items[2], getDeepActiveElement()); down(); - assertEquals(items[0], menu.root.activeElement); + assertEquals(items[0], getDeepActiveElement()); down(); - assertEquals(items[1], menu.root.activeElement); + assertEquals(items[1], getDeepActiveElement()); down(); - assertEquals(items[2], menu.root.activeElement); + assertEquals(items[2], getDeepActiveElement()); down(); - assertEquals(items[0], menu.root.activeElement); + assertEquals(items[0], getDeepActiveElement()); up(); - assertEquals(items[2], menu.root.activeElement); + assertEquals(items[2], getDeepActiveElement()); up(); - assertEquals(items[1], menu.root.activeElement); + assertEquals(items[1], getDeepActiveElement()); up(); - assertEquals(items[0], menu.root.activeElement); + assertEquals(items[0], getDeepActiveElement()); up(); - assertEquals(items[2], menu.root.activeElement); + assertEquals(items[2], getDeepActiveElement()); items[1].disabled = true; up(); - assertEquals(items[0], menu.root.activeElement); + assertEquals(items[0], getDeepActiveElement()); }); test('pressing up arrow when no focus will focus last item', function() { @@ -111,7 +111,7 @@ assertEquals(menu, document.activeElement); up(); - assertEquals(items[items.length - 1], menu.root.activeElement); + assertEquals(items[items.length - 1], getDeepActiveElement()); }); test('can navigate to dynamically added items', function() { @@ -123,16 +123,16 @@ menu.showAt(dots); down(); - assertEquals(item, menu.root.activeElement); + assertEquals(item, getDeepActiveElement()); down(); - assertEquals(items[0], menu.root.activeElement); + assertEquals(items[0], getDeepActiveElement()); // Can modify children while menu is open. menu.removeChild(item); up(); // Focus should have wrapped around to final item. - assertEquals(items[2], menu.root.activeElement); + assertEquals(items[2], getDeepActiveElement()); }); test('close on resize', function() { @@ -180,27 +180,27 @@ menu.showAt(dots); // Moving mouse on option 1 should focus it. - assertNotEquals(items[0], menu.root.activeElement); + assertNotEquals(items[0], getDeepActiveElement()); makeMouseoverEvent(items[0]); - assertEquals(items[0], menu.root.activeElement); + assertEquals(items[0], getDeepActiveElement()); // Moving mouse on the menu (not on option) should focus the menu. makeMouseoverEvent(menu); - assertNotEquals(items[0], menu.root.activeElement); + assertNotEquals(items[0], getDeepActiveElement()); assertEquals(menu, document.activeElement); // Moving mouse on a disabled item should focus the menu. items[2].setAttribute('disabled', ''); makeMouseoverEvent(items[2]); - assertNotEquals(items[2], menu.root.activeElement); + assertNotEquals(items[2], getDeepActiveElement()); assertEquals(menu, document.activeElement); // Mouse movements should override keyboard focus. down(); down(); - assertEquals(items[1], menu.root.activeElement); + assertEquals(items[1], getDeepActiveElement()); makeMouseoverEvent(items[0]); - assertEquals(items[0], menu.root.activeElement); + assertEquals(items[0], getDeepActiveElement()); }); test('items automatically given accessibility role', function() {
diff --git a/chrome/test/data/webui/settings/autofill_section_test.js b/chrome/test/data/webui/settings/autofill_section_test.js index d7f4f00..0bc77ab 100644 --- a/chrome/test/data/webui/settings/autofill_section_test.js +++ b/chrome/test/data/webui/settings/autofill_section_test.js
@@ -90,9 +90,7 @@ test('testAutofillExtensionIndicator', function() { // Initializing with fake prefs const section = document.createElement('settings-autofill-section'); - section.prefs = { - autofill: {enabled: {}, profile_enabled: {}} - }; + section.prefs = {autofill: {profile_enabled: {}}}; document.body.appendChild(section); assertFalse(!!section.$$('#autofillExtensionIndicator')); @@ -137,8 +135,8 @@ } test('verifyNoAddresses', function() { - const section = createAutofillSection( - [], {enabled: {value: true}, profile_enabled: {value: true}}); + const section = + createAutofillSection([], {profile_enabled: {value: true}}); const addressList = section.$.addressList; assertTrue(!!addressList); @@ -159,9 +157,8 @@ FakeDataMaker.addressEntry(), ]; - const section = createAutofillSection( - addresses, - {enabled: {value: true}, profile_enabled: {value: true}}); + const section = + createAutofillSection(addresses, {profile_enabled: {value: true}}); const addressList = section.$.addressList; assertTrue(!!addressList); @@ -174,8 +171,8 @@ }); test('verifyAddressDisabled', function() { - const section = createAutofillSection( - [], {enabled: {value: true}, profile_enabled: {value: false}}); + const section = + createAutofillSection([], {profile_enabled: {value: false}}); assertFalse(section.$$('#autofillProfileToggle').disabled); assertTrue(section.$$('#addAddress').disabled);
diff --git a/chrome/test/data/webui/settings/multidevice_page_tests.js b/chrome/test/data/webui/settings/multidevice_page_tests.js index 7629a71..56b781e1 100644 --- a/chrome/test/data/webui/settings/multidevice_page_tests.js +++ b/chrome/test/data/webui/settings/multidevice_page_tests.js
@@ -126,4 +126,22 @@ assertTrue(!!getSubpage()); assertFalse(!!getSubpage().$$('settings-multidevice-feature-item')); }); + + test('button is attached but disabled when waiting for server', function() { + setPageContentData( + settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION, + HOST_DEVICE); + let verificationButton = multidevicePage.$$('paper-button'); + assertTrue(!!verificationButton); + // Button should be active because UI is not waiting on server. + assertFalse(verificationButton.disabled); + + setPageContentData( + settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER, + HOST_DEVICE); + verificationButton = multidevicePage.$$('paper-button'); + assertTrue(!!verificationButton); + // Button should be disabled because UI is waiting on server. + assertTrue(verificationButton.disabled); + }); });
diff --git a/chrome/test/data/webui/settings/payments_section_test.js b/chrome/test/data/webui/settings/payments_section_test.js index ceb1cfb2..2819268 100644 --- a/chrome/test/data/webui/settings/payments_section_test.js +++ b/chrome/test/data/webui/settings/payments_section_test.js
@@ -7,7 +7,7 @@ test('testAutofillExtensionIndicator', function() { // Initializing with fake prefs const section = document.createElement('settings-payments-section'); - section.prefs = {autofill: {enabled: {}, credit_card_enabled: {}}}; + section.prefs = {autofill: {credit_card_enabled: {}}}; document.body.appendChild(section); assertFalse(!!section.$$('#autofillExtensionIndicator')); @@ -63,8 +63,8 @@ } test('verifyCreditCardCount', function() { - const section = createPaymentsSection( - [], {enabled: {value: true}, credit_card_enabled: {value: true}}); + const section = + createPaymentsSection([], {credit_card_enabled: {value: true}}); const creditCardList = section.$$('#creditCardList'); assertTrue(!!creditCardList); @@ -77,9 +77,8 @@ }); test('verifyCreditCardsDisabled', function() { - const section = createPaymentsSection( - [], - {enabled: {value: true}, credit_card_enabled: {value: false}}); + const section = + createPaymentsSection([], {credit_card_enabled: {value: false}}); assertFalse(section.$$('#autofillCreditCardToggle').disabled); assertTrue(section.$$('#addCreditCard').disabled); @@ -96,8 +95,7 @@ ]; const section = createPaymentsSection( - creditCards, - {enabled: {value: true}, credit_card_enabled: {value: true}}); + creditCards, {credit_card_enabled: {value: true}}); const creditCardList = section.$$('#creditCardList'); assertTrue(!!creditCardList); assertEquals( @@ -405,8 +403,7 @@ const creditCard = FakeDataMaker.creditCardEntry(); creditCard.metadata.isMigratable = true; const section = createPaymentsSection( - [creditCard], - {enabled: {value: true}, credit_card_enabled: {value: true}}); + [creditCard], {credit_card_enabled: {value: true}}); // Simulate Signed-in and Synced status. sync_test_util.simulateSyncStatus({ @@ -429,8 +426,7 @@ const creditCard = FakeDataMaker.creditCardEntry(); creditCard.metadata.isMigratable = true; const section = createPaymentsSection( - [creditCard], - {enabled: {value: true}, credit_card_enabled: {value: true}}); + [creditCard], {credit_card_enabled: {value: true}}); // Simulate not Signed-in status. Won't show migration button. sync_test_util.simulateSyncStatus({ @@ -453,8 +449,7 @@ const creditCard = FakeDataMaker.creditCardEntry(); creditCard.metadata.isMigratable = true; const section = createPaymentsSection( - [creditCard], - {enabled: {value: true}, credit_card_enabled: {value: true}}); + [creditCard], {credit_card_enabled: {value: true}}); // Simulate not Synced status. Won't show migration button. sync_test_util.simulateSyncStatus({ @@ -477,8 +472,7 @@ const creditCard = FakeDataMaker.creditCardEntry(); creditCard.metadata.isMigratable = false; const section = createPaymentsSection( - [creditCard], - {enabled: {value: true}, credit_card_enabled: {value: true}}); + [creditCard], {credit_card_enabled: {value: true}}); // Simulate Signed-in and Synced status. sync_test_util.simulateSyncStatus({ @@ -501,32 +495,7 @@ const creditCard = FakeDataMaker.creditCardEntry(); creditCard.metadata.isMigratable = true; const section = createPaymentsSection( - [creditCard], - {enabled: {value: true}, credit_card_enabled: {value: false}}); - - // Simulate Signed-in and Synced status. - sync_test_util.simulateSyncStatus({ - signedIn: true, - syncSystemEnabled: true, - }); - - // All migration requirements are met but credit card is disable, verify - // migration button is hidden. - assertTrue(section.$$('#migrateCreditCards').hidden); - }); - - test('verifyMigrationButtonNotShownWhenAutofillDisabled', function() { - // Enable the migration experimental flag and mock Google payments - // account. - loadTimeData.overrideValues( - {migrationEnabled: true, hasGooglePaymentsAccount: true}); - - // Add one migratable credit card. - const creditCard = FakeDataMaker.creditCardEntry(); - creditCard.metadata.isMigratable = true; - const section = createPaymentsSection( - [creditCard], - {enabled: {value: false}, credit_card_enabled: {value: true}}); + [creditCard], {credit_card_enabled: {value: false}}); // Simulate Signed-in and Synced status. sync_test_util.simulateSyncStatus({ @@ -549,8 +518,7 @@ const creditCard = FakeDataMaker.creditCardEntry(); creditCard.metadata.isMigratable = true; const section = createPaymentsSection( - [creditCard], - {enabled: {value: true}, credit_card_enabled: {value: true}}); + [creditCard], {credit_card_enabled: {value: true}}); // Simulate Signed-in and Synced status. sync_test_util.simulateSyncStatus({ @@ -573,8 +541,7 @@ const creditCard = FakeDataMaker.creditCardEntry(); creditCard.metadata.isMigratable = true; const section = createPaymentsSection( - [creditCard], - {enabled: {value: true}, credit_card_enabled: {value: true}}); + [creditCard], {credit_card_enabled: {value: true}}); // Simulate Signed-in and Synced status. sync_test_util.simulateSyncStatus({
diff --git a/chromecast/graphics/gestures/cast_system_gesture_dispatcher.cc b/chromecast/graphics/gestures/cast_system_gesture_dispatcher.cc index 5c5b89a..5cc1d4e 100644 --- a/chromecast/graphics/gestures/cast_system_gesture_dispatcher.cc +++ b/chromecast/graphics/gestures/cast_system_gesture_dispatcher.cc
@@ -5,10 +5,21 @@ #include "chromecast/graphics/gestures/cast_system_gesture_dispatcher.h" #include "base/logging.h" +#include "base/time/default_tick_clock.h" namespace chromecast { -CastSystemGestureDispatcher::CastSystemGestureDispatcher() {} +namespace { +const base::TimeDelta kExpirationTime = base::TimeDelta::FromSeconds(3); +const size_t kMaxSwipes = 3; +} // namespace + +CastSystemGestureDispatcher::CastSystemGestureDispatcher( + const base::TickClock* tick_clock) + : send_gestures_to_root_(false), tick_clock_(tick_clock) {} + +CastSystemGestureDispatcher::CastSystemGestureDispatcher() + : CastSystemGestureDispatcher(base::DefaultTickClock::GetInstance()) {} CastSystemGestureDispatcher::~CastSystemGestureDispatcher() { DCHECK(gesture_handlers_.empty()); @@ -42,11 +53,34 @@ CastSideSwipeEvent event, CastSideSwipeOrigin swipe_origin, const gfx::Point& touch_location) { + // Process previous events and check to see if the user attempted a swipe + // multiple times. This probably indicates that the swipe is not having the + // intended effect in the UI, most likely the highest priority handler is + // consuming the gesture but not taking any action. To prevent the system + // from getting stuck, route new gesture events to the main UI when this + // happens. + base::TimeTicks now = tick_clock_->NowTicks(); + if (event == CastSideSwipeEvent::BEGIN) { + recent_events_.push({now, swipe_origin}); + // Flush events which are older than the prescribed time. + while (!recent_events_.empty() && + recent_events_.front().event_time < now - kExpirationTime) { + recent_events_.pop(); + } + // If there are too many recent swipes, then this gesture should go to the + // root UI. + send_gestures_to_root_ = recent_events_.size() >= kMaxSwipes; + } CastGestureHandler* best_handler = nullptr; Priority highest_priority = Priority::NONE; // Iterate through all handlers. Pick the handler with the highest priority // that is capable of handling the swipe event and is not Priority::NONE. for (auto* gesture_handler : gesture_handlers_) { + if (send_gestures_to_root_ && + gesture_handler->GetPriority() == Priority::ROOT_UI) { + best_handler = gesture_handler; + break; + } if (gesture_handler->CanHandleSwipe(swipe_origin) && gesture_handler->GetPriority() > highest_priority) { best_handler = gesture_handler;
diff --git a/chromecast/graphics/gestures/cast_system_gesture_dispatcher.h b/chromecast/graphics/gestures/cast_system_gesture_dispatcher.h index 1cb588e..7e2a5106 100644 --- a/chromecast/graphics/gestures/cast_system_gesture_dispatcher.h +++ b/chromecast/graphics/gestures/cast_system_gesture_dispatcher.h
@@ -5,7 +5,11 @@ #ifndef CHROMECAST_GRAPHICS_GESTURES_CAST_SYSTEM_GESTURE_DISPATCHER_H_ #define CHROMECAST_GRAPHICS_GESTURES_CAST_SYSTEM_GESTURE_DISPATCHER_H_ +#include <queue> + #include "base/containers/flat_set.h" +#include "base/time/tick_clock.h" +#include "base/time/time.h" #include "chromecast/graphics/gestures/cast_gesture_handler.h" namespace chromecast { @@ -15,6 +19,7 @@ class CastSystemGestureDispatcher : public CastGestureHandler { public: CastSystemGestureDispatcher(); + explicit CastSystemGestureDispatcher(const base::TickClock* tick_clock); ~CastSystemGestureDispatcher() override; @@ -35,6 +40,15 @@ void HandleTapGesture(const gfx::Point& touch_location) override; private: + // Logs a completed gesture event. + struct GestureEvent { + base::TimeTicks event_time; + CastSideSwipeOrigin origin; + }; + + std::queue<GestureEvent> recent_events_; + bool send_gestures_to_root_; + const base::TickClock* const tick_clock_; base::flat_set<CastGestureHandler*> gesture_handlers_; }; } // namespace chromecast
diff --git a/chromecast/graphics/gestures/cast_system_gesture_dispatcher_test.cc b/chromecast/graphics/gestures/cast_system_gesture_dispatcher_test.cc index 0111dd3..0734fd8 100644 --- a/chromecast/graphics/gestures/cast_system_gesture_dispatcher_test.cc +++ b/chromecast/graphics/gestures/cast_system_gesture_dispatcher_test.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "base/test/simple_test_tick_clock.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/point.h" @@ -15,6 +16,13 @@ namespace chromecast { +namespace { + +constexpr base::TimeDelta kTimeoutWindow = base::TimeDelta::FromSeconds(3); +const size_t kMaxSwipesWithinTimeout = 3; + +} // namespace + class MockCastGestureHandler : public CastGestureHandler { public: ~MockCastGestureHandler() override = default; @@ -34,13 +42,16 @@ ~CastSystemGestureDispatcherTest() override = default; void SetUp() override { - gesture_dispatcher_ = std::make_unique<CastSystemGestureDispatcher>(); + test_clock_ = std::make_unique<base::SimpleTestTickClock>(); + gesture_dispatcher_ = + std::make_unique<CastSystemGestureDispatcher>(test_clock_.get()); } void TearDown() override { gesture_dispatcher_.reset(); } protected: std::unique_ptr<CastSystemGestureDispatcher> gesture_dispatcher_; + std::unique_ptr<base::SimpleTestTickClock> test_clock_; }; TEST_F(CastSystemGestureDispatcherTest, SingleHandler) { @@ -106,6 +117,7 @@ EXPECT_CALL(handler_2, HandleSideSwipe(event, origin, point)); gesture_dispatcher_->HandleSideSwipe(event, origin, point); + test_clock_->Advance(kTimeoutWindow); // Test when the higher priority handler can't handle the event. Lower // priority handler should get it instead. origin = CastSideSwipeOrigin::BOTTOM; @@ -113,12 +125,83 @@ EXPECT_CALL(handler_1, HandleSideSwipe(event, origin, point)); EXPECT_CALL(handler_2, HandleSideSwipe(_, _, _)).Times(0); gesture_dispatcher_->HandleSideSwipe(event, origin, point); + test_clock_->Advance(kTimeoutWindow); // Test when no handlers can handle the event. ON_CALL(handler_1, CanHandleSwipe(origin)).WillByDefault(Return(false)); EXPECT_CALL(handler_1, HandleSideSwipe(_, _, _)).Times(0); EXPECT_CALL(handler_2, HandleSideSwipe(_, _, _)).Times(0); gesture_dispatcher_->HandleSideSwipe(event, origin, point); + test_clock_->Advance(kTimeoutWindow); + + gesture_dispatcher_->RemoveGestureHandler(&handler_2); + gesture_dispatcher_->RemoveGestureHandler(&handler_1); +} + +TEST_F(CastSystemGestureDispatcherTest, MultipleSwipesToRootUi) { + MockCastGestureHandler handler_1; + MockCastGestureHandler handler_2; + ON_CALL(handler_1, GetPriority()) + .WillByDefault(Return(CastGestureHandler::Priority::ROOT_UI)); + ON_CALL(handler_2, GetPriority()) + .WillByDefault(Return(CastGestureHandler::Priority::MAIN_ACTIVITY)); + + gesture_dispatcher_->AddGestureHandler(&handler_1); + gesture_dispatcher_->AddGestureHandler(&handler_2); + + // Higher priority handler should get the event. + ON_CALL(handler_1, CanHandleSwipe(_)).WillByDefault(Return(true)); + ON_CALL(handler_2, CanHandleSwipe(_)).WillByDefault(Return(true)); + CastSideSwipeEvent event = CastSideSwipeEvent::BEGIN; + CastSideSwipeOrigin origin = CastSideSwipeOrigin::TOP; + gfx::Point point(0, 0); + + // Trigger N - 1 events within the recent events timeout window. + for (size_t i = 0; i < kMaxSwipesWithinTimeout - 1; ++i) { + EXPECT_CALL(handler_1, HandleSideSwipe(_, _, _)).Times(0); + EXPECT_CALL(handler_2, HandleSideSwipe(event, origin, point)); + gesture_dispatcher_->HandleSideSwipe(event, origin, point); + base::TimeDelta time_between_events = + (kTimeoutWindow - base::TimeDelta::FromSeconds(1)) / + (kMaxSwipesWithinTimeout - 1); + test_clock_->Advance(time_between_events); + } + + // The Nth event will go to the root UI, since there were N BEGIN events that + // happened in rapid succession. This means the main activity is probably not + // handling the events properly, and we should defer to the root UI which is + // assumed to behave properly. + event = CastSideSwipeEvent::BEGIN; + EXPECT_CALL(handler_1, HandleSideSwipe(event, origin, point)); + EXPECT_CALL(handler_2, HandleSideSwipe(_, _, _)).Times(0); + gesture_dispatcher_->HandleSideSwipe(event, origin, point); + + // CONTINUE events still go to the root UI. + event = CastSideSwipeEvent::CONTINUE; + EXPECT_CALL(handler_1, HandleSideSwipe(event, origin, point)); + EXPECT_CALL(handler_2, HandleSideSwipe(_, _, _)).Times(0); + gesture_dispatcher_->HandleSideSwipe(event, origin, point); + + // We are now outside the timeout window. + test_clock_->Advance(kTimeoutWindow); + + // All events will go to the root UI until the next BEGIN event after the + // 3-event timeout. + event = CastSideSwipeEvent::CONTINUE; + EXPECT_CALL(handler_1, HandleSideSwipe(event, origin, point)); + EXPECT_CALL(handler_2, HandleSideSwipe(_, _, _)).Times(0); + gesture_dispatcher_->HandleSideSwipe(event, origin, point); + + event = CastSideSwipeEvent::END; + EXPECT_CALL(handler_1, HandleSideSwipe(event, origin, point)); + EXPECT_CALL(handler_2, HandleSideSwipe(_, _, _)).Times(0); + gesture_dispatcher_->HandleSideSwipe(event, origin, point); + + // Timeout has elapsed, next BEGIN event will go to the main handler. + event = CastSideSwipeEvent::BEGIN; + EXPECT_CALL(handler_1, HandleSideSwipe(_, _, _)).Times(0); + EXPECT_CALL(handler_2, HandleSideSwipe(event, origin, point)); + gesture_dispatcher_->HandleSideSwipe(event, origin, point); gesture_dispatcher_->RemoveGestureHandler(&handler_2); gesture_dispatcher_->RemoveGestureHandler(&handler_1);
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_manager.cc b/chromecast/media/cma/backend/media_pipeline_backend_manager.cc index 697980e..71413b4 100644 --- a/chromecast/media/cma/backend/media_pipeline_backend_manager.cc +++ b/chromecast/media/cma/backend/media_pipeline_backend_manager.cc
@@ -60,11 +60,18 @@ new base::ObserverListThreadSafe<AllowVolumeFeedbackObserver>()), global_volume_multipliers_({{AudioContentType::kMedia, 1.0f}, {AudioContentType::kAlarm, 1.0f}, - {AudioContentType::kCommunication, 1.0f}}, + {AudioContentType::kCommunication, 1.0f}, + {AudioContentType::kOther, 1.0f}}, base::KEEP_FIRST_OF_DUPES), buffer_delegate_(nullptr), weak_factory_(this) { DCHECK(media_task_runner_); + DCHECK(playing_audio_streams_count_.size() == + static_cast<unsigned long>(AudioContentType::kNumTypes)); + DCHECK(playing_noneffects_audio_streams_count_.size() == + static_cast<unsigned long>(AudioContentType::kNumTypes)); + DCHECK(global_volume_multipliers_.size() == + static_cast<unsigned long>(AudioContentType::kNumTypes)); for (int i = 0; i < NUM_DECODER_TYPES; ++i) { decoder_count_[i] = 0; }
diff --git a/chromecast/net/fake_stream_socket_unittest.cc b/chromecast/net/fake_stream_socket_unittest.cc index 10357f1..e3b1cad2 100644 --- a/chromecast/net/fake_stream_socket_unittest.cc +++ b/chromecast/net/fake_stream_socket_unittest.cc
@@ -71,7 +71,7 @@ } TEST_F(FakeStreamSocketTest, ReadAndWriteWithoutPeer) { - scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(1)); + auto io_buffer = base::MakeRefCounted<net::IOBuffer>(1); EXPECT_EQ(net::ERR_IO_PENDING, socket_1_.Read(io_buffer.get(), 1, base::Bind(&Callback))); EXPECT_EQ(net::ERR_SOCKET_NOT_CONNECTED, @@ -83,13 +83,12 @@ socket_1_.SetPeer(&socket_2_); socket_2_.SetPeer(&socket_1_); const std::string kData("DATA"); - scoped_refptr<net::StringIOBuffer> send_buffer( - new net::StringIOBuffer(kData)); + auto send_buffer = base::MakeRefCounted<net::StringIOBuffer>(kData); ASSERT_EQ( static_cast<int>(kData.size()), socket_1_.Write(send_buffer.get(), kData.size(), base::Bind(&Callback), TRAFFIC_ANNOTATION_FOR_TESTS)); - scoped_refptr<net::IOBuffer> receive_buffer(new net::IOBuffer(kData.size())); + auto receive_buffer = base::MakeRefCounted<net::IOBuffer>(kData.size()); ASSERT_EQ(static_cast<int>(kData.size()), socket_2_.Read(receive_buffer.get(), kData.size(), base::Bind(&Callback))); @@ -100,12 +99,11 @@ socket_1_.SetPeer(&socket_2_); socket_2_.SetPeer(&socket_1_); const std::string kData("DATA"); - scoped_refptr<net::IOBuffer> receive_buffer(new net::IOBuffer(kData.size())); + auto receive_buffer = base::MakeRefCounted<net::IOBuffer>(kData.size()); ASSERT_EQ(net::ERR_IO_PENDING, socket_2_.Read(receive_buffer.get(), kData.size(), base::Bind(&Callback))); - scoped_refptr<net::StringIOBuffer> send_buffer( - new net::StringIOBuffer(kData)); + auto send_buffer = base::MakeRefCounted<net::StringIOBuffer>(kData); ASSERT_EQ( static_cast<int>(kData.size()), socket_1_.Write(send_buffer.get(), kData.size(), base::Bind(&Callback), @@ -118,8 +116,7 @@ socket_2_.SetPeer(&socket_1_); // Send 1 MB of data between sockets. const std::string kData("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"); - scoped_refptr<net::StringIOBuffer> send_buffer( - new net::StringIOBuffer(kData)); + auto send_buffer = base::MakeRefCounted<net::StringIOBuffer>(kData); const int kWriteCount = 1024 * 1024 / kData.size(); for (int i = 0; i < kWriteCount; i++) { ASSERT_EQ( @@ -127,7 +124,7 @@ socket_1_.Write(send_buffer.get(), kData.size(), base::Bind(&Callback), TRAFFIC_ANNOTATION_FOR_TESTS)); } - scoped_refptr<net::IOBuffer> receive_buffer(new net::IOBuffer(1024)); + auto receive_buffer = base::MakeRefCounted<net::IOBuffer>(1024); for (int i = 0; i < 1024; i++) { ASSERT_EQ(1024, socket_2_.Read(receive_buffer.get(), 1024, base::Bind(&Callback)));
diff --git a/chromecast/public/volume_control.h b/chromecast/public/volume_control.h index e5305b2e..6e47825 100644 --- a/chromecast/public/volume_control.h +++ b/chromecast/public/volume_control.h
@@ -21,6 +21,7 @@ kAlarm, // Alarm sounds. kCommunication, // Voice communication, eg assistant TTS. kOther, // No content type volume control (only per-stream control). + kNumTypes, // Not a valid type; should always be last in the enum. }; // Observer for volume/mute state changes. This is useful to detect volume
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc index 62efdfa7..42184fb 100644 --- a/chromeos/chromeos_switches.cc +++ b/chromeos/chromeos_switches.cc
@@ -408,6 +408,11 @@ const char kEnterpriseEnrollmentModulusLimit[] = "enterprise-enrollment-modulus-limit"; +// Interval in seconds between Chrome reading external metrics from +// /var/lib/metrics/uma-events. +const char kExternalMetricsCollectionInterval[] = + "external-metrics-collection-interval"; + // An absolute path to the chroot hosting the DriveFS to use. This is only used // when running on Linux, i.e. when IsRunningOnChromeOS() returns false. const char kFakeDriveFsLauncherChrootPath[] =
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h index beb203b3..8543b35 100644 --- a/chromeos/chromeos_switches.h +++ b/chromeos/chromeos_switches.h
@@ -117,6 +117,7 @@ CHROMEOS_EXPORT extern const char kEnterpriseEnableZeroTouchEnrollment[]; CHROMEOS_EXPORT extern const char kEnterpriseEnrollmentInitialModulus[]; CHROMEOS_EXPORT extern const char kEnterpriseEnrollmentModulusLimit[]; +CHROMEOS_EXPORT extern const char kExternalMetricsCollectionInterval[]; CHROMEOS_EXPORT extern const char kFirstExecAfterBoot[]; CHROMEOS_EXPORT extern const char kFakeDriveFsLauncherChrootPath[]; CHROMEOS_EXPORT extern const char kFakeDriveFsLauncherSocketPath[];
diff --git a/chromeos/dbus/pipe_reader.cc b/chromeos/dbus/pipe_reader.cc index e08896a..2f6de4b 100644 --- a/chromeos/dbus/pipe_reader.cc +++ b/chromeos/dbus/pipe_reader.cc
@@ -17,7 +17,7 @@ namespace chromeos { PipeReader::PipeReader(const scoped_refptr<base::TaskRunner>& task_runner) - : io_buffer_(new net::IOBufferWithSize(4096)), + : io_buffer_(base::MakeRefCounted<net::IOBufferWithSize>(4096)), task_runner_(task_runner), weak_ptr_factory_(this) {}
diff --git a/chromeos/printing/ppd_line_reader.cc b/chromeos/printing/ppd_line_reader.cc index 445687e6..e01bb2c 100644 --- a/chromeos/printing/ppd_line_reader.cc +++ b/chromeos/printing/ppd_line_reader.cc
@@ -65,7 +65,7 @@ public: PpdLineReaderImpl(const std::string& ppd_contents, size_t max_line_length) : max_line_length_(max_line_length), - read_buf_(new net::IOBuffer(kReadBufCapacity)) { + read_buf_(base::MakeRefCounted<net::IOBuffer>(kReadBufCapacity)) { input_ = std::make_unique<StringSourceStream>(ppd_contents); if (IsGZipped(ppd_contents)) { input_ = net::GzipSourceStream::Create(std::move(input_), @@ -169,6 +169,8 @@ std::unique_ptr<net::SourceStream> input_; }; +constexpr int PpdLineReaderImpl::kReadBufCapacity; + } // namespace // static
diff --git a/components/arc/usb/usb_host_bridge.cc b/components/arc/usb/usb_host_bridge.cc index 860c29c5..5e2c24b 100644 --- a/components/arc/usb/usb_host_bridge.cc +++ b/components/arc/usb/usb_host_bridge.cc
@@ -211,7 +211,7 @@ void ArcUsbHostBridge::OnDeviceRemoved( scoped_refptr<device::UsbDevice> device) { mojom::UsbHostInstance* usb_host_instance = ARC_GET_INSTANCE_FOR_METHOD( - arc_bridge_service_->usb_host(), OnDeviceAdded); + arc_bridge_service_->usb_host(), OnDeviceRemoved); if (!usb_host_instance) { VLOG(2) << "UsbInstance not ready yet";
diff --git a/components/autofill/core/browser/credit_card_save_manager.cc b/components/autofill/core/browser/credit_card_save_manager.cc index 485d5959..55ad1c4 100644 --- a/components/autofill/core/browser/credit_card_save_manager.cc +++ b/components/autofill/core/browser/credit_card_save_manager.cc
@@ -156,12 +156,15 @@ features::kAutofillUpstreamUpdatePromptExplanation.name); } - int detected_values = GetDetectedValues(); + // We store the detected values in the upload request, because the addresses + // are being possibly modified in the next code block, and we want the + // detected values to reflect addresses *before* they are modified. + upload_request_.detected_values = GetDetectedValues(); // If the user must provide cardholder name, log it and set // |should_request_name_from_user_| so the offer-to-save dialog know to ask // for it. should_request_name_from_user_ = false; - if (detected_values & DetectedValue::USER_PROVIDED_NAME) { + if (upload_request_.detected_values & DetectedValue::USER_PROVIDED_NAME) { upload_decision_metrics_ |= AutofillMetrics::USER_REQUESTED_TO_PROVIDE_CARDHOLDER_NAME; should_request_name_from_user_ = true; @@ -185,7 +188,7 @@ if (observer_for_testing_) observer_for_testing_->OnDecideToRequestUploadSave(); payments_client_->GetUploadDetails( - upload_request_.profiles, detected_values, + upload_request_.profiles, upload_request_.detected_values, upload_request_.active_experiments, app_locale_, base::BindOnce(&CreditCardSaveManager::OnDidGetUploadDetails, weak_ptr_factory_.GetWeakPtr()), @@ -276,12 +279,11 @@ // if there's a network breakdown or Payments outage, resulting in sometimes // showing upload and sometimes offering local save, but such cases should // be rare.) - int detected_values = GetDetectedValues(); bool found_name_and_postal_code_and_cvc = - (detected_values & DetectedValue::CARDHOLDER_NAME || - detected_values & DetectedValue::ADDRESS_NAME) && - detected_values & DetectedValue::POSTAL_CODE && - detected_values & DetectedValue::CVC; + (upload_request_.detected_values & DetectedValue::CARDHOLDER_NAME || + upload_request_.detected_values & DetectedValue::ADDRESS_NAME) && + upload_request_.detected_values & DetectedValue::POSTAL_CODE && + upload_request_.detected_values & DetectedValue::CVC; if (found_name_and_postal_code_and_cvc && !uploading_local_card_) OfferCardLocalSave(upload_request_.card); upload_decision_metrics_ |=
diff --git a/components/autofill/core/browser/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/credit_card_save_manager_unittest.cc index 1906ace..e3b7fca 100644 --- a/components/autofill/core/browser/credit_card_save_manager_unittest.cc +++ b/components/autofill/core/browser/credit_card_save_manager_unittest.cc
@@ -2344,13 +2344,13 @@ // This class is parametrized to allow running all the inheriting tests with and // without a specific feature enabled. See INSTANTIATE_TEST_CASE_P. -class CreditCardSaveManagerGetDetectedValuesTest +class CreditCardSaveManagerFeatureParameterizedTest : public CreditCardSaveManagerTest, public ::testing::WithParamInterface< /*enable_send_only_country_in_get_upload_details=*/bool> { public: - CreditCardSaveManagerGetDetectedValuesTest() {} - ~CreditCardSaveManagerGetDetectedValuesTest() override {} + CreditCardSaveManagerFeatureParameterizedTest() {} + ~CreditCardSaveManagerFeatureParameterizedTest() override {} void SetUp() override { CreditCardSaveManagerTest::SetUp(); @@ -2360,10 +2360,10 @@ } private: - DISALLOW_COPY_AND_ASSIGN(CreditCardSaveManagerGetDetectedValuesTest); + DISALLOW_COPY_AND_ASSIGN(CreditCardSaveManagerFeatureParameterizedTest); }; -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, NothingIfNothingFound) { +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, NothingIfNothingFound) { // Set up our credit card form data. FormData credit_card_form; CreateTestCreditCardFormData(&credit_card_form, true, false); @@ -2381,7 +2381,7 @@ EXPECT_EQ(payments_client_->detected_values_in_upload_details(), 0); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, DetectCvc) { +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectCvc) { // Set up our credit card form data. FormData credit_card_form; CreateTestCreditCardFormData(&credit_card_form, true, false); @@ -2403,7 +2403,7 @@ expected_detected_value); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, DetectCardholderName) { +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectCardholderName) { // Set up our credit card form data. FormData credit_card_form; CreateTestCreditCardFormData(&credit_card_form, true, false); @@ -2426,7 +2426,7 @@ expected_detected_value); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, DetectAddressName) { +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectAddressName) { // Set up a new address profile. AutofillProfile profile; profile.set_guid("00000000-0000-0000-0000-000000000200"); @@ -2455,7 +2455,7 @@ expected_detected_value); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectCardholderAndAddressNameIfMatching) { // Set up a new address profile. AutofillProfile profile; @@ -2486,7 +2486,7 @@ expected_detected_values); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectNoUniqueNameIfNamesConflict) { // Set up a new address profile. AutofillProfile profile; @@ -2511,7 +2511,7 @@ EXPECT_EQ(payments_client_->detected_values_in_upload_details(), 0); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, DetectPostalCode) { +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectPostalCode) { // Set up a new address profile. AutofillProfile profile; profile.set_guid("00000000-0000-0000-0000-000000000200"); @@ -2540,7 +2540,7 @@ expected_detected_value); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectNoUniquePostalCodeIfZipsConflict) { // Set up two new address profiles with conflicting postal codes. AutofillProfile profile1; @@ -2569,7 +2569,7 @@ EXPECT_EQ(payments_client_->detected_values_in_upload_details(), 0); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, DetectAddressLine) { +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectAddressLine) { // Set up a new address profile. AutofillProfile profile; profile.set_guid("00000000-0000-0000-0000-000000000200"); @@ -2598,7 +2598,7 @@ expected_detected_value); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, DetectLocality) { +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectLocality) { // Set up a new address profile. AutofillProfile profile; profile.set_guid("00000000-0000-0000-0000-000000000200"); @@ -2626,7 +2626,8 @@ expected_detected_value); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, DetectAdministrativeArea) { +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, + DetectAdministrativeArea) { // Set up a new address profile. AutofillProfile profile; profile.set_guid("00000000-0000-0000-0000-000000000200"); @@ -2655,7 +2656,7 @@ expected_detected_value); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, DetectCountryCode) { +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectCountryCode) { // Set up a new address profile. AutofillProfile profile; profile.set_guid("00000000-0000-0000-0000-000000000200"); @@ -2684,7 +2685,7 @@ expected_detected_value); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectHasGooglePaymentAccount) { // Set the billing_customer_number Priority Preference to designate existence // of a Payments account. @@ -2713,7 +2714,7 @@ expected_detected_value); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, DetectEverythingAtOnce) { +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectEverythingAtOnce) { // Set up a new address profile. AutofillProfile profile; profile.set_guid("00000000-0000-0000-0000-000000000200"); @@ -2754,7 +2755,7 @@ expected_detected_values); } -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectSubsetOfPossibleFields) { // Set up a new address profile, taking out address line and state. AutofillProfile profile; @@ -2793,7 +2794,7 @@ // This test checks that ADDRESS_LINE, LOCALITY, ADMINISTRATIVE_AREA, and // COUNTRY_CODE don't care about possible conflicts or consistency and are // populated if even one address profile contains it. -TEST_P(CreditCardSaveManagerGetDetectedValuesTest, +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectAddressComponentsAcrossProfiles) { // Set up four new address profiles, each with a different address component. AutofillProfile profile1; @@ -2839,16 +2840,7 @@ expected_detected_values); } -// Every test will appear with suffix /0 (param false) and /1 (param true), e.g. -// CreditCardSaveManagerGetDetectedValuesTest.NothingIfNothingFound/0: -// Feature disabled -// CreditCardSaveManagerGetDetectedValuesTest.NothingIfNothingFound/1: -// Feature enabled. -INSTANTIATE_TEST_CASE_P(, // Empty instatiation name. - CreditCardSaveManagerGetDetectedValuesTest, - ::testing::Values(false, true)); - -TEST_F(CreditCardSaveManagerTest, +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, UploadCreditCard_LogAdditionalErrorsWithUploadDetailsFailure) { // Anything other than "en-US" will cause GetUploadDetails to return a failure // response. @@ -2898,8 +2890,8 @@ 1 /* expected_num_matching_entries */); } -TEST_F( - CreditCardSaveManagerTest, +TEST_P( + CreditCardSaveManagerFeatureParameterizedTest, UploadCreditCard_ShouldOfferLocalSaveIfEverythingDetectedAndPaymentsDeclines) { // Anything other than "en-US" will cause GetUploadDetails to return a failure // response. @@ -2938,8 +2930,8 @@ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded()); } -TEST_F( - CreditCardSaveManagerTest, +TEST_P( + CreditCardSaveManagerFeatureParameterizedTest, UploadCreditCard_ShouldOfferLocalSaveIfEverythingDetectedAndPaymentsDeclines_WithFirstAndLastName) { // Anything other than "en-US" will cause GetUploadDetails to return a failure // response. @@ -2988,8 +2980,8 @@ "Autofill.SaveCardWithFirstAndLastNameComplete.Server", 0); } -TEST_F( - CreditCardSaveManagerTest, +TEST_P( + CreditCardSaveManagerFeatureParameterizedTest, UploadCreditCard_ShouldNotOfferLocalSaveIfSomethingNotDetectedAndPaymentsDeclines) { // Anything other than "en-US" will cause GetUploadDetails to return a failure // response. @@ -3025,7 +3017,7 @@ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded()); } -TEST_F(CreditCardSaveManagerTest, +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, UploadCreditCard_PaymentsDecidesOfferToSaveIfNoCvc) { // Create, fill and submit an address form in order to establish a recent // profile which can be selected for the upload request. @@ -3067,7 +3059,7 @@ 1 /* expected_num_matching_entries */); } -TEST_F(CreditCardSaveManagerTest, +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, UploadCreditCard_PaymentsDecidesOfferToSaveIfNoName) { // Create, fill and submit an address form in order to establish a recent // profile which can be selected for the upload request. @@ -3110,7 +3102,7 @@ 1 /* expected_num_matching_entries */); } -TEST_F(CreditCardSaveManagerTest, +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, UploadCreditCard_PaymentsDecidesOfferToSaveIfConflictingNames) { // Create, fill and submit an address form in order to establish a recent // profile which can be selected for the upload request. @@ -3152,7 +3144,7 @@ 1 /* expected_num_matching_entries */); } -TEST_F(CreditCardSaveManagerTest, +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, UploadCreditCard_PaymentsDecidesOfferToSaveIfNoZip) { // Set up a new address profile without a postal code. AutofillProfile profile; @@ -3196,7 +3188,7 @@ 1 /* expected_num_matching_entries */); } -TEST_F(CreditCardSaveManagerTest, +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, UploadCreditCard_PaymentsDecidesOfferToSaveIfConflictingZips) { // Set up two new address profiles with conflicting postal codes. AutofillProfile profile1; @@ -3252,7 +3244,7 @@ 1 /* expected_num_matching_entries */); } -TEST_F(CreditCardSaveManagerTest, +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, UploadCreditCard_PaymentsDecidesOfferToSaveIfNothingFound) { // Set up a new address profile without a name or postal code. AutofillProfile profile; @@ -3301,6 +3293,157 @@ 1 /* expected_num_matching_entries */); } +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, + UploadCreditCard_UploadOfLocalCard) { + // Add a local credit card whose |TypeAndLastFourDigits| matches what we will + // enter below. + CreditCard local_card; + test::SetCreditCardInfo(&local_card, "Flo Master", "4111111111111111", + NextMonth().c_str(), NextYear().c_str(), "1"); + local_card.set_record_type(CreditCard::LOCAL_CARD); + personal_data_.AddCreditCard(local_card); + + // Create, fill and submit an address form in order to establish a recent + // profile which can be selected for the upload request. + FormData address_form; + test::CreateTestAddressFormData(&address_form); + FormsSeen(std::vector<FormData>(1, address_form)); + ExpectUniqueFillableFormParsedUkm(); + + ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form); + FormSubmitted(address_form); + + // Set up our credit card form data. + FormData credit_card_form; + CreateTestCreditCardFormData(&credit_card_form, true, false); + FormsSeen(std::vector<FormData>(1, credit_card_form)); + ExpectFillableFormParsedUkm(2 /* num_fillable_forms_parsed */); + + // Edit the data, and submit. + credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master"); + credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111"); + credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth()); + credit_card_form.fields[3].value = ASCIIToUTF16(NextYear()); + credit_card_form.fields[4].value = ASCIIToUTF16("123"); + + base::HistogramTester histogram_tester; + + EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0); + FormSubmitted(credit_card_form); + EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded()); + + // Verify that metrics noted it was an existing local card for which credit + // card upload was offered and accepted. + histogram_tester.ExpectUniqueSample( + "Autofill.UploadOfferedCardOrigin", + AutofillMetrics::OFFERING_UPLOAD_OF_LOCAL_CARD, 1); + histogram_tester.ExpectUniqueSample( + "Autofill.UploadAcceptedCardOrigin", + AutofillMetrics::USER_ACCEPTED_UPLOAD_OF_LOCAL_CARD, 1); +} + +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, + UploadCreditCard_UploadOfNewCard) { + // Create, fill and submit an address form in order to establish a recent + // profile which can be selected for the upload request. + FormData address_form; + test::CreateTestAddressFormData(&address_form); + FormsSeen(std::vector<FormData>(1, address_form)); + ExpectUniqueFillableFormParsedUkm(); + + ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form); + FormSubmitted(address_form); + + // Set up our credit card form data. + FormData credit_card_form; + CreateTestCreditCardFormData(&credit_card_form, true, false); + FormsSeen(std::vector<FormData>(1, credit_card_form)); + ExpectFillableFormParsedUkm(2 /* num_fillable_forms_parsed */); + + // Edit the data, and submit. + credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master"); + credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111"); + credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth()); + credit_card_form.fields[3].value = ASCIIToUTF16(NextYear()); + credit_card_form.fields[4].value = ASCIIToUTF16("123"); + + base::HistogramTester histogram_tester; + + EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0); + FormSubmitted(credit_card_form); + EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded()); + + // Verify that metrics noted it was a brand new card for which credit card + // upload was offered and accepted. + histogram_tester.ExpectUniqueSample( + "Autofill.UploadOfferedCardOrigin", + AutofillMetrics::OFFERING_UPLOAD_OF_NEW_CARD, 1); + histogram_tester.ExpectUniqueSample( + "Autofill.UploadAcceptedCardOrigin", + AutofillMetrics::USER_ACCEPTED_UPLOAD_OF_NEW_CARD, 1); +} + +// This test ensures that if offer-to-upload is denied by Google Payments, local +// save is not offered if the card is already a local card. +TEST_P(CreditCardSaveManagerFeatureParameterizedTest, + UploadCreditCard_DenyingUploadOfLocalCardShouldNotOfferLocalSave) { + // Anything other than "en-US" will cause GetUploadDetails to return a failure + // response. + credit_card_save_manager_->SetAppLocale("pt-BR"); + + // Add a local credit card whose |TypeAndLastFourDigits| matches what we will + // enter below. + CreditCard local_card; + test::SetCreditCardInfo(&local_card, "Flo Master", "4111111111111111", + NextMonth().c_str(), NextYear().c_str(), "1"); + local_card.set_record_type(CreditCard::LOCAL_CARD); + personal_data_.AddCreditCard(local_card); + + // Create, fill and submit an address form in order to establish a recent + // profile which can be selected for the upload request. + FormData address_form; + test::CreateTestAddressFormData(&address_form); + FormsSeen(std::vector<FormData>(1, address_form)); + ExpectUniqueFillableFormParsedUkm(); + + ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form); + FormSubmitted(address_form); + + // Set up our credit card form data. + FormData credit_card_form; + CreateTestCreditCardFormData(&credit_card_form, true, false); + FormsSeen(std::vector<FormData>(1, credit_card_form)); + ExpectFillableFormParsedUkm(2 /* num_fillable_forms_parsed */); + + // Edit the data, and submit. + credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master"); + credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111"); + credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth()); + credit_card_form.fields[3].value = ASCIIToUTF16(NextYear()); + credit_card_form.fields[4].value = ASCIIToUTF16("123"); + + base::HistogramTester histogram_tester; + + // Neither local or upload save should be offered in this case. + EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0); + FormSubmitted(credit_card_form); + EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded()); + + // Verify that metrics noted it was an existing local card for which credit + // card upload was offered and accepted. + histogram_tester.ExpectTotalCount("Autofill.UploadOfferedCardOrigin", 0); + histogram_tester.ExpectTotalCount("Autofill.UploadAcceptedCardOrigin", 0); +} + +// Every test will appear with suffix /0 (param false) and /1 (param true), e.g. +// CreditCardSaveManagerFeatureParameterizedTest.NothingIfNothingFound/0: +// Feature disabled +// CreditCardSaveManagerFeatureParameterizedTest.NothingIfNothingFound/1: +// Feature enabled. +INSTANTIATE_TEST_CASE_P(, // Empty instatiation name. + CreditCardSaveManagerFeatureParameterizedTest, + ::testing::Values(false, true)); + TEST_F( CreditCardSaveManagerTest, UploadCreditCard_AddUpdatePromptExplanationFlagStateToRequestIfExperimentOn) { @@ -3367,146 +3510,6 @@ EXPECT_TRUE(payments_client_->active_experiments_in_request().empty()); } -TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadOfLocalCard) { - // Add a local credit card whose |TypeAndLastFourDigits| matches what we will - // enter below. - CreditCard local_card; - test::SetCreditCardInfo(&local_card, "Flo Master", "4111111111111111", - NextMonth().c_str(), NextYear().c_str(), "1"); - local_card.set_record_type(CreditCard::LOCAL_CARD); - personal_data_.AddCreditCard(local_card); - - // Create, fill and submit an address form in order to establish a recent - // profile which can be selected for the upload request. - FormData address_form; - test::CreateTestAddressFormData(&address_form); - FormsSeen(std::vector<FormData>(1, address_form)); - ExpectUniqueFillableFormParsedUkm(); - - ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form); - FormSubmitted(address_form); - - // Set up our credit card form data. - FormData credit_card_form; - CreateTestCreditCardFormData(&credit_card_form, true, false); - FormsSeen(std::vector<FormData>(1, credit_card_form)); - ExpectFillableFormParsedUkm(2 /* num_fillable_forms_parsed */); - - // Edit the data, and submit. - credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master"); - credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111"); - credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth()); - credit_card_form.fields[3].value = ASCIIToUTF16(NextYear()); - credit_card_form.fields[4].value = ASCIIToUTF16("123"); - - base::HistogramTester histogram_tester; - - EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0); - FormSubmitted(credit_card_form); - EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded()); - - // Verify that metrics noted it was an existing local card for which credit - // card upload was offered and accepted. - histogram_tester.ExpectUniqueSample( - "Autofill.UploadOfferedCardOrigin", - AutofillMetrics::OFFERING_UPLOAD_OF_LOCAL_CARD, 1); - histogram_tester.ExpectUniqueSample( - "Autofill.UploadAcceptedCardOrigin", - AutofillMetrics::USER_ACCEPTED_UPLOAD_OF_LOCAL_CARD, 1); -} - -TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadOfNewCard) { - // Create, fill and submit an address form in order to establish a recent - // profile which can be selected for the upload request. - FormData address_form; - test::CreateTestAddressFormData(&address_form); - FormsSeen(std::vector<FormData>(1, address_form)); - ExpectUniqueFillableFormParsedUkm(); - - ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form); - FormSubmitted(address_form); - - // Set up our credit card form data. - FormData credit_card_form; - CreateTestCreditCardFormData(&credit_card_form, true, false); - FormsSeen(std::vector<FormData>(1, credit_card_form)); - ExpectFillableFormParsedUkm(2 /* num_fillable_forms_parsed */); - - // Edit the data, and submit. - credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master"); - credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111"); - credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth()); - credit_card_form.fields[3].value = ASCIIToUTF16(NextYear()); - credit_card_form.fields[4].value = ASCIIToUTF16("123"); - - base::HistogramTester histogram_tester; - - EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0); - FormSubmitted(credit_card_form); - EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded()); - - // Verify that metrics noted it was a brand new card for which credit card - // upload was offered and accepted. - histogram_tester.ExpectUniqueSample( - "Autofill.UploadOfferedCardOrigin", - AutofillMetrics::OFFERING_UPLOAD_OF_NEW_CARD, 1); - histogram_tester.ExpectUniqueSample( - "Autofill.UploadAcceptedCardOrigin", - AutofillMetrics::USER_ACCEPTED_UPLOAD_OF_NEW_CARD, 1); -} - -// This test ensures that if offer-to-upload is denied by Google Payments, local -// save is not offered if the card is already a local card. -TEST_F(CreditCardSaveManagerTest, - UploadCreditCard_DenyingUploadOfLocalCardShouldNotOfferLocalSave) { - // Anything other than "en-US" will cause GetUploadDetails to return a failure - // response. - credit_card_save_manager_->SetAppLocale("pt-BR"); - - // Add a local credit card whose |TypeAndLastFourDigits| matches what we will - // enter below. - CreditCard local_card; - test::SetCreditCardInfo(&local_card, "Flo Master", "4111111111111111", - NextMonth().c_str(), NextYear().c_str(), "1"); - local_card.set_record_type(CreditCard::LOCAL_CARD); - personal_data_.AddCreditCard(local_card); - - // Create, fill and submit an address form in order to establish a recent - // profile which can be selected for the upload request. - FormData address_form; - test::CreateTestAddressFormData(&address_form); - FormsSeen(std::vector<FormData>(1, address_form)); - ExpectUniqueFillableFormParsedUkm(); - - ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form); - FormSubmitted(address_form); - - // Set up our credit card form data. - FormData credit_card_form; - CreateTestCreditCardFormData(&credit_card_form, true, false); - FormsSeen(std::vector<FormData>(1, credit_card_form)); - ExpectFillableFormParsedUkm(2 /* num_fillable_forms_parsed */); - - // Edit the data, and submit. - credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master"); - credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111"); - credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth()); - credit_card_form.fields[3].value = ASCIIToUTF16(NextYear()); - credit_card_form.fields[4].value = ASCIIToUTF16("123"); - - base::HistogramTester histogram_tester; - - // Neither local or upload save should be offered in this case. - EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0); - FormSubmitted(credit_card_form); - EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded()); - - // Verify that metrics noted it was an existing local card for which credit - // card upload was offered and accepted. - histogram_tester.ExpectTotalCount("Autofill.UploadOfferedCardOrigin", 0); - histogram_tester.ExpectTotalCount("Autofill.UploadAcceptedCardOrigin", 0); -} - TEST_F(CreditCardSaveManagerTest, UploadCreditCard_EloDisallowed) { scoped_feature_list_.InitAndEnableFeature( features::kAutofillUpstreamDisallowElo);
diff --git a/components/autofill/core/browser/payments/full_card_request_unittest.cc b/components/autofill/core/browser/payments/full_card_request_unittest.cc index a846f471..6b6dbda 100644 --- a/components/autofill/core/browser/payments/full_card_request_unittest.cc +++ b/components/autofill/core/browser/payments/full_card_request_unittest.cc
@@ -59,8 +59,11 @@ // The personal data manager. class MockPersonalDataManager : public PersonalDataManager { public: - MockPersonalDataManager() : PersonalDataManager("en-US") {} + MockPersonalDataManager() : PersonalDataManager("en-US") { + testing::DefaultValue<bool>::Set(true); + } ~MockPersonalDataManager() override {} + MOCK_CONST_METHOD0(IsSyncFeatureEnabled, bool()); MOCK_METHOD1(UpdateCreditCard, void(const CreditCard& credit_card)); MOCK_METHOD1(UpdateServerCreditCard, void(const CreditCard& credit_card)); };
diff --git a/components/autofill/core/browser/payments/payments_client.cc b/components/autofill/core/browser/payments/payments_client.cc index d626c67..27e1855 100644 --- a/components/autofill/core/browser/payments/payments_client.cc +++ b/components/autofill/core/browser/payments/payments_client.cc
@@ -237,9 +237,12 @@ class UnmaskCardRequest : public PaymentsRequest { public: UnmaskCardRequest(const PaymentsClient::UnmaskRequestDetails& request_details, + const bool full_sync_enabled, base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const std::string&)> callback) - : request_details_(request_details), callback_(std::move(callback)) { + : request_details_(request_details), + full_sync_enabled_(full_sync_enabled), + callback_(std::move(callback)) { DCHECK( CreditCard::MASKED_SERVER_CARD == request_details.card.record_type() || CreditCard::FULL_SERVER_CARD == request_details.card.record_type()); @@ -267,6 +270,13 @@ } request_dict.Set("context", std::move(context)); + if (ShouldUseActiveSignedInAccount()) { + std::unique_ptr<base::DictionaryValue> chrome_user_context( + new base::DictionaryValue()); + chrome_user_context->SetBoolean("full_sync_enabled", full_sync_enabled_); + request_dict.Set("chrome_user_context", std::move(chrome_user_context)); + } + int value = 0; if (base::StringToInt(request_details_.user_response.exp_month, &value)) request_dict.SetInteger("expiration_month", value); @@ -297,6 +307,7 @@ private: PaymentsClient::UnmaskRequestDetails request_details_; + const bool full_sync_enabled_; base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const std::string&)> callback_; @@ -309,6 +320,7 @@ const std::vector<AutofillProfile>& addresses, const int detected_values, const std::vector<const char*>& active_experiments, + const bool full_sync_enabled, const std::string& app_locale, base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const base::string16&, @@ -317,6 +329,7 @@ : addresses_(addresses), detected_values_(detected_values), active_experiments_(active_experiments), + full_sync_enabled_(full_sync_enabled), app_locale_(app_locale), callback_(std::move(callback)), billable_service_number_(billable_service_number) {} @@ -335,6 +348,13 @@ context->SetInteger("billable_service", billable_service_number_); request_dict.Set("context", std::move(context)); + if (ShouldUseActiveSignedInAccount()) { + std::unique_ptr<base::DictionaryValue> chrome_user_context( + new base::DictionaryValue()); + chrome_user_context->SetBoolean("full_sync_enabled", full_sync_enabled_); + request_dict.Set("chrome_user_context", std::move(chrome_user_context)); + } + std::unique_ptr<base::ListValue> addresses(new base::ListValue()); for (const AutofillProfile& profile : addresses_) { // These addresses are used by Payments to (1) accurately determine the @@ -380,6 +400,7 @@ const std::vector<AutofillProfile> addresses_; const int detected_values_; const std::vector<const char*> active_experiments_; + const bool full_sync_enabled_; std::string app_locale_; base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const base::string16&, @@ -393,9 +414,12 @@ class UploadCardRequest : public PaymentsRequest { public: UploadCardRequest(const PaymentsClient::UploadRequestDetails& request_details, + const bool full_sync_enabled, base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const std::string&)> callback) - : request_details_(request_details), callback_(std::move(callback)) {} + : request_details_(request_details), + full_sync_enabled_(full_sync_enabled), + callback_(std::move(callback)) {} ~UploadCardRequest() override {} std::string GetRequestUrlPath() override { return kUploadCardRequestPath; } @@ -423,6 +447,13 @@ } request_dict.Set("context", std::move(context)); + if (ShouldUseActiveSignedInAccount()) { + std::unique_ptr<base::DictionaryValue> chrome_user_context( + new base::DictionaryValue()); + chrome_user_context->SetBoolean("full_sync_enabled", full_sync_enabled_); + request_dict.Set("chrome_user_context", std::move(chrome_user_context)); + } + SetStringIfNotEmpty(request_details_.card, CREDIT_CARD_NAME_FULL, app_locale, "cardholder_name", &request_dict); @@ -481,6 +512,7 @@ private: const PaymentsClient::UploadRequestDetails request_details_; + const bool full_sync_enabled_; base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const std::string&)> callback_; @@ -492,9 +524,11 @@ MigrateCardsRequest( const PaymentsClient::MigrationRequestDetails& request_details, const std::vector<MigratableCreditCard>& migratable_credit_cards, + const bool full_sync_enabled, MigrateCardsCallback callback) : request_details_(request_details), migratable_credit_cards_(migratable_credit_cards), + full_sync_enabled_(full_sync_enabled), callback_(std::move(callback)) {} ~MigrateCardsRequest() override {} @@ -522,6 +556,13 @@ } request_dict.Set("context", std::move(context)); + if (ShouldUseActiveSignedInAccount()) { + std::unique_ptr<base::DictionaryValue> chrome_user_context( + new base::DictionaryValue()); + chrome_user_context->SetBoolean("full_sync_enabled", full_sync_enabled_); + request_dict.Set("chrome_user_context", std::move(chrome_user_context)); + } + request_dict.SetString("context_token", request_details_.context_token); std::string all_pans_data = std::string(); @@ -597,6 +638,7 @@ const PaymentsClient::MigrationRequestDetails request_details_; const std::vector<MigratableCreditCard>& migratable_credit_cards_; + const bool full_sync_enabled_; MigrateCardsCallback callback_; std::unique_ptr<std::unordered_map<std::string, std::string>> save_result_; std::string display_text_; @@ -652,7 +694,9 @@ base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const std::string&)> callback) { IssueRequest( - std::make_unique<UnmaskCardRequest>(request_details, std::move(callback)), + std::make_unique<UnmaskCardRequest>( + request_details, account_info_getter_->IsSyncFeatureEnabled(), + std::move(callback)), true); } @@ -666,7 +710,8 @@ std::unique_ptr<base::DictionaryValue>)> callback, const int billable_service_number) { IssueRequest(std::make_unique<GetUploadDetailsRequest>( - addresses, detected_values, active_experiments, app_locale, + addresses, detected_values, active_experiments, + account_info_getter_->IsSyncFeatureEnabled(), app_locale, std::move(callback), billable_service_number), false); } @@ -676,7 +721,9 @@ base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const std::string&)> callback) { IssueRequest( - std::make_unique<UploadCardRequest>(request_details, std::move(callback)), + std::make_unique<UploadCardRequest>( + request_details, account_info_getter_->IsSyncFeatureEnabled(), + std::move(callback)), true); } @@ -686,7 +733,8 @@ MigrateCardsCallback callback) { IssueRequest( std::make_unique<MigrateCardsRequest>( - request_details, migratable_credit_cards, std::move(callback)), + request_details, migratable_credit_cards, + account_info_getter_->IsSyncFeatureEnabled(), std::move(callback)), /*authenticate=*/true); }
diff --git a/components/autofill/core/browser/payments/payments_client.h b/components/autofill/core/browser/payments/payments_client.h index 02d6fca..0c689ae 100644 --- a/components/autofill/core/browser/payments/payments_client.h +++ b/components/autofill/core/browser/payments/payments_client.h
@@ -87,6 +87,7 @@ ~UploadRequestDetails(); int64_t billing_customer_number = 0; + int detected_values; CreditCard card; base::string16 cvc; std::vector<AutofillProfile> profiles;
diff --git a/components/autofill/core/browser/payments/payments_client_unittest.cc b/components/autofill/core/browser/payments/payments_client_unittest.cc index 4550d30..ec135c8e 100644 --- a/components/autofill/core/browser/payments/payments_client_unittest.cc +++ b/components/autofill/core/browser/payments/payments_client_unittest.cc
@@ -321,6 +321,51 @@ EXPECT_EQ("1234", real_pan_); } +TEST_F(PaymentsClientTest, UnmaskIncludesChromeUserContext) { + scoped_feature_list_.InitWithFeatures( + {features::kAutofillGetPaymentsIdentityFromSync}, // Enabled + {features::kAutofillEnableAccountWalletStorage}); // Disabled + + StartUnmasking(); + IssueOAuthToken(); + ReturnResponse(net::HTTP_OK, "{}"); + + // ChromeUserContext was set. + EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos); + EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos); +} + +TEST_F(PaymentsClientTest, + UnmaskIncludesChromeUserContextIfWalletStorageFlagEnabled) { + scoped_feature_list_.InitWithFeatures( + {features::kAutofillEnableAccountWalletStorage}, // Enabled + {features::kAutofillGetPaymentsIdentityFromSync}); // Disabled + + StartUnmasking(); + IssueOAuthToken(); + ReturnResponse(net::HTTP_OK, "{}"); + + // ChromeUserContext was set. + EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos); + EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos); +} + +TEST_F(PaymentsClientTest, UnmaskExcludesChromeUserContextIfExperimentsOff) { + scoped_feature_list_.InitWithFeatures( + {}, // Enabled + {features::kAutofillEnableAccountWalletStorage, + features::kAutofillGetPaymentsIdentityFromSync}); // Disabled + + StartUnmasking(); + IssueOAuthToken(); + ReturnResponse(net::HTTP_OK, "{}"); + + // ChromeUserContext was not set. + EXPECT_TRUE(!GetUploadData().empty()); + EXPECT_TRUE(GetUploadData().find("chrome_user_context") == std::string::npos); + EXPECT_TRUE(GetUploadData().find("full_sync_enabled") == std::string::npos); +} + TEST_F(PaymentsClientTest, GetDetailsSuccess) { StartGettingUploadDetails(); ReturnResponse( @@ -363,6 +408,46 @@ std::string::npos); } +TEST_F(PaymentsClientTest, GetDetailsIncludesChromeUserContext) { + scoped_feature_list_.InitWithFeatures( + {features::kAutofillGetPaymentsIdentityFromSync}, // Enabled + {features::kAutofillEnableAccountWalletStorage}); // Disabled + + StartGettingUploadDetails(); + + // ChromeUserContext was set. + EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos); + EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos); +} + +TEST_F(PaymentsClientTest, + GetDetailsIncludesChromeUserContextIfWalletStorageFlagEnabled) { + scoped_feature_list_.InitWithFeatures( + {features::kAutofillEnableAccountWalletStorage}, // Enabled + {features::kAutofillGetPaymentsIdentityFromSync}); // Disabled + + StartGettingUploadDetails(); + + // ChromeUserContext was set. + EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos); + EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos); +} + +TEST_F(PaymentsClientTest, + GetDetailsExcludesChromeUserContextIfExperimentsOff) { + scoped_feature_list_.InitWithFeatures( + {}, // Enabled + {features::kAutofillEnableAccountWalletStorage, + features::kAutofillGetPaymentsIdentityFromSync}); // Disabled + + StartGettingUploadDetails(); + + // ChromeUserContext was not set. + EXPECT_TRUE(!GetUploadData().empty()); + EXPECT_TRUE(GetUploadData().find("chrome_user_context") == std::string::npos); + EXPECT_TRUE(GetUploadData().find("full_sync_enabled") == std::string::npos); +} + TEST_F(PaymentsClientTest, GetUploadAccountFromSyncTest) { EnableAutofillGetPaymentsIdentityFromSync(); // Set up a different account. @@ -600,6 +685,48 @@ EXPECT_TRUE(GetUploadData().find("&s7e_13_cvc=") != std::string::npos); } +TEST_F(PaymentsClientTest, UploadIncludesChromeUserContext) { + scoped_feature_list_.InitWithFeatures( + {features::kAutofillGetPaymentsIdentityFromSync}, // Enabled + {features::kAutofillEnableAccountWalletStorage}); // Disabled + + StartUploading(/*include_cvc=*/true); + IssueOAuthToken(); + + // ChromeUserContext was set. + EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos); + EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos); +} + +TEST_F(PaymentsClientTest, + UploadIncludesChromeUserContextIfWalletStorageFlagEnabled) { + scoped_feature_list_.InitWithFeatures( + {features::kAutofillEnableAccountWalletStorage}, // Enabled + {features::kAutofillGetPaymentsIdentityFromSync}); // Disabled + + StartUploading(/*include_cvc=*/true); + IssueOAuthToken(); + + // ChromeUserContext was set. + EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos); + EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos); +} + +TEST_F(PaymentsClientTest, UploadExcludesChromeUserContextIfExperimentsOff) { + scoped_feature_list_.InitWithFeatures( + {}, // Enabled + {features::kAutofillEnableAccountWalletStorage, + features::kAutofillGetPaymentsIdentityFromSync}); // Disabled + + StartUploading(/*include_cvc=*/true); + IssueOAuthToken(); + + // ChromeUserContext was not set. + EXPECT_TRUE(!GetUploadData().empty()); + EXPECT_TRUE(GetUploadData().find("chrome_user_context") == std::string::npos); + EXPECT_TRUE(GetUploadData().find("full_sync_enabled") == std::string::npos); +} + TEST_F(PaymentsClientTest, UploadDoesNotIncludeCvcInRequestIfNotProvided) { StartUploading(/*include_cvc=*/false); IssueOAuthToken(); @@ -675,6 +802,49 @@ EXPECT_TRUE(GetUploadData().find("cardholder_name") == std::string::npos); } +TEST_F(PaymentsClientTest, MigrationRequestIncludesChromeUserContext) { + scoped_feature_list_.InitWithFeatures( + {features::kAutofillGetPaymentsIdentityFromSync}, // Enabled + {features::kAutofillEnableAccountWalletStorage}); // Disabled + + StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true); + IssueOAuthToken(); + + // ChromeUserContext was set. + EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos); + EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos); +} + +TEST_F(PaymentsClientTest, + MigrationRequestIncludesChromeUserContextIfWalletStorageFlagEnabled) { + scoped_feature_list_.InitWithFeatures( + {features::kAutofillEnableAccountWalletStorage}, // Enabled + {features::kAutofillGetPaymentsIdentityFromSync}); // Disabled + + StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true); + IssueOAuthToken(); + + // ChromeUserContext was set. + EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos); + EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos); +} + +TEST_F(PaymentsClientTest, + MigrationRequestExcludesChromeUserContextIfExperimentsOff) { + scoped_feature_list_.InitWithFeatures( + {}, // Enabled + {features::kAutofillEnableAccountWalletStorage, + features::kAutofillGetPaymentsIdentityFromSync}); // Disabled + + StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true); + IssueOAuthToken(); + + // ChromeUserContext was not set. + EXPECT_TRUE(!GetUploadData().empty()); + EXPECT_TRUE(GetUploadData().find("chrome_user_context") == std::string::npos); + EXPECT_TRUE(GetUploadData().find("full_sync_enabled") == std::string::npos); +} + TEST_F(PaymentsClientTest, MigrationSuccessWithSaveResult) { StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true); IssueOAuthToken();
diff --git a/components/feed/BUILD.gn b/components/feed/BUILD.gn index 74cffcf..4cc4b96 100644 --- a/components/feed/BUILD.gn +++ b/components/feed/BUILD.gn
@@ -29,4 +29,8 @@ deps = [ "core:core_unit_tests", ] + + if (!is_ios) { + deps += [ "content:content_unit_tests" ] + } }
diff --git a/components/feed/content/BUILD.gn b/components/feed/content/BUILD.gn index 3a49db2..86059fa 100644 --- a/components/feed/content/BUILD.gn +++ b/components/feed/content/BUILD.gn
@@ -25,3 +25,19 @@ "//components/offline_pages/core/prefetch", ] } + +source_set("content_unit_tests") { + testonly = true + sources = [ + "feed_offline_host_unittest.cc", + ] + + deps = [ + ":feed_content", + "//base", + "//base/test:test_support", + "//components/offline_pages/core:test_support", + "//components/offline_pages/core/prefetch:test_support", + "//testing/gtest:gtest", + ] +}
diff --git a/components/feed/content/feed_host_service.h b/components/feed/content/feed_host_service.h index 53ec042..776444a 100644 --- a/components/feed/content/feed_host_service.h +++ b/components/feed/content/feed_host_service.h
@@ -46,6 +46,9 @@ std::unique_ptr<FeedSchedulerHost> scheduler_host_; std::unique_ptr<FeedContentDatabase> content_database_; std::unique_ptr<FeedJournalDatabase> journal_database_; + + // Depends on the |scheduler_host_|, so must come after in this file to be + // destroyed before the scheduler. std::unique_ptr<FeedOfflineHost> offline_host_; DISALLOW_COPY_AND_ASSIGN(FeedHostService);
diff --git a/components/feed/content/feed_offline_host.cc b/components/feed/content/feed_offline_host.cc index 94eef9a..0ab6347d 100644 --- a/components/feed/content/feed_offline_host.cc +++ b/components/feed/content/feed_offline_host.cc
@@ -4,19 +4,24 @@ #include "components/feed/content/feed_offline_host.h" +#include "url/gurl.h" + namespace feed { FeedOfflineHost::FeedOfflineHost( offline_pages::OfflinePageModel* offline_page_model, offline_pages::PrefetchService* prefetch_service, - FeedSchedulerHost* feed_scheduler_host) + base::RepeatingClosure on_suggestion_consumed, + base::RepeatingClosure on_suggestions_shown) : offline_page_model_(offline_page_model), prefetch_service_(prefetch_service), - feed_scheduler_host_(feed_scheduler_host), + on_suggestion_consumed_(on_suggestion_consumed), + on_suggestions_shown_(on_suggestions_shown), weak_ptr_factory_(this) { DCHECK(offline_page_model_); DCHECK(prefetch_service_); - DCHECK(feed_scheduler_host_); + DCHECK(!on_suggestion_consumed_.is_null()); + DCHECK(!on_suggestions_shown_.is_null()); } FeedOfflineHost::~FeedOfflineHost() = default; @@ -50,11 +55,11 @@ } void FeedOfflineHost::ReportArticleListViewed() { - // TODO(skym): Call FeedSchedulerHost::OnSuggestionsShown(). + on_suggestion_consumed_.Run(); } void FeedOfflineHost::ReportArticleViewed(GURL article_url) { - // TODO(skym): Call FeedSchedulerHost::OnSuggestionConsumed(). + on_suggestions_shown_.Run(); } void FeedOfflineHost::OfflinePageModelLoaded(
diff --git a/components/feed/content/feed_offline_host.h b/components/feed/content/feed_offline_host.h index ad8799d..09f192f1 100644 --- a/components/feed/content/feed_offline_host.h +++ b/components/feed/content/feed_offline_host.h
@@ -23,8 +23,6 @@ namespace feed { -class FeedSchedulerHost; - // Responsible for wiring up connections for Feed operations pertaining to // articles that can be loaded from Offline Pages component. Most significantly // this class connects Prefetch and the Feed, and tracks offlined articles the @@ -35,7 +33,8 @@ public: FeedOfflineHost(offline_pages::OfflinePageModel* offline_page_model, offline_pages::PrefetchService* prefetch_service, - FeedSchedulerHost* feed_scheduler_host); + base::RepeatingClosure on_suggestion_consumed, + base::RepeatingClosure on_suggestions_shown); ~FeedOfflineHost() override; // Synchronously returns the offline id of the given page. The host will only @@ -85,7 +84,9 @@ // them. This is guaranteed by the FeedHostServiceFactory. offline_pages::OfflinePageModel* offline_page_model_; offline_pages::PrefetchService* prefetch_service_; - FeedSchedulerHost* feed_scheduler_host_; + + base::RepeatingClosure on_suggestion_consumed_; + base::RepeatingClosure on_suggestions_shown_; base::WeakPtrFactory<FeedOfflineHost> weak_ptr_factory_;
diff --git a/components/feed/content/feed_offline_host_unittest.cc b/components/feed/content/feed_offline_host_unittest.cc new file mode 100644 index 0000000..a1c9ba2 --- /dev/null +++ b/components/feed/content/feed_offline_host_unittest.cc
@@ -0,0 +1,60 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/feed/content/feed_offline_host.h" + +#include <memory> + +#include "base/bind.h" +#include "components/offline_pages/core/prefetch/stub_prefetch_service.h" +#include "components/offline_pages/core/stub_offline_page_model.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace feed { + +class FeedOfflineHostTest : public ::testing::Test { + public: + FeedOfflineHost* host() { return host_.get(); } + int get_suggestion_consumed_count() { return suggestion_consumed_count_; } + int get_suggestions_shown_count() { return suggestions_shown_count_; } + + protected: + FeedOfflineHostTest() { + host_ = std::make_unique<FeedOfflineHost>( + &offline_page_model_, &prefetch_service_, + base::BindRepeating(&FeedOfflineHostTest::OnSuggestionConsumed, + base::Unretained(this)), + base::BindRepeating(&FeedOfflineHostTest::OnSuggestionsShown, + base::Unretained(this))); + } + + void OnSuggestionConsumed() { ++suggestion_consumed_count_; } + void OnSuggestionsShown() { ++suggestions_shown_count_; } + + offline_pages::StubOfflinePageModel offline_page_model_; + offline_pages::StubPrefetchService prefetch_service_; + std::unique_ptr<FeedOfflineHost> host_; + int suggestion_consumed_count_ = 0; + int suggestions_shown_count_ = 0; +}; + +TEST_F(FeedOfflineHostTest, ReportArticleListViewed) { + EXPECT_EQ(0, get_suggestion_consumed_count()); + host()->ReportArticleListViewed(); + EXPECT_EQ(1, get_suggestion_consumed_count()); + host()->ReportArticleListViewed(); + EXPECT_EQ(2, get_suggestion_consumed_count()); + EXPECT_EQ(0, get_suggestions_shown_count()); +} + +TEST_F(FeedOfflineHostTest, OnSuggestionsShown) { + EXPECT_EQ(0, get_suggestions_shown_count()); + host()->ReportArticleViewed(GURL("https://www.one.com")); + EXPECT_EQ(1, get_suggestions_shown_count()); + host()->ReportArticleViewed(GURL("https://www.one.com")); + EXPECT_EQ(2, get_suggestions_shown_count()); + EXPECT_EQ(0, get_suggestion_consumed_count()); +} + +} // namespace feed
diff --git a/components/ntp_snippets/features.cc b/components/ntp_snippets/features.cc index cdae24a5..9da28447 100644 --- a/components/ntp_snippets/features.cc +++ b/components/ntp_snippets/features.cc
@@ -164,7 +164,7 @@ } // Default referrer for the content suggestions. -const char kDefaultReferrerUrl[] = "https://feed.google.com/"; +const char kDefaultReferrerUrl[] = "https://discover.google.com/"; // Provides ability to customize the referrer URL. // When specifying a referrer through a field trial, it must contain a path.
diff --git a/components/ntp_snippets/features_unittest.cc b/components/ntp_snippets/features_unittest.cc index 7d60fa35..63ad254 100644 --- a/components/ntp_snippets/features_unittest.cc +++ b/components/ntp_snippets/features_unittest.cc
@@ -20,12 +20,12 @@ TEST(FeaturesTest, GetContentSuggestionsReferrerURL_DefaultValue) { base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature(kArticleSuggestionsFeature); - EXPECT_EQ("https://feed.google.com/", GetContentSuggestionsReferrerURL()); + EXPECT_EQ("https://discover.google.com/", GetContentSuggestionsReferrerURL()); // In code this will be often used inside of a GURL. - EXPECT_EQ("https://feed.google.com/", + EXPECT_EQ("https://discover.google.com/", GURL(GetContentSuggestionsReferrerURL())); - EXPECT_EQ("https://feed.google.com/", + EXPECT_EQ("https://discover.google.com/", GURL(GetContentSuggestionsReferrerURL()).spec()); }
diff --git a/components/nux/email/email_handler.cc b/components/nux/email/email_handler.cc index fe15114c..b613d32 100644 --- a/components/nux/email/email_handler.cc +++ b/components/nux/email/email_handler.cc
@@ -154,6 +154,18 @@ IDR_NUX_EMAIL_CHOOSER_JS); // Add icons + html_source->AddResourcePath("email/aol_1x.png", IDR_NUX_EMAIL_AOL_1X); + html_source->AddResourcePath("email/aol_2x.png", IDR_NUX_EMAIL_AOL_2X); + html_source->AddResourcePath("email/gmail_1x.png", IDR_NUX_EMAIL_GMAIL_1X); + html_source->AddResourcePath("email/gmail_2x.png", IDR_NUX_EMAIL_GMAIL_2X); + html_source->AddResourcePath("email/icloud_1x.png", IDR_NUX_EMAIL_ICLOUD_1X); + html_source->AddResourcePath("email/icloud_2x.png", IDR_NUX_EMAIL_ICLOUD_2X); + html_source->AddResourcePath("email/outlook_1x.png", + IDR_NUX_EMAIL_OUTLOOK_1X); + html_source->AddResourcePath("email/outlook_2x.png", + IDR_NUX_EMAIL_OUTLOOK_2X); + html_source->AddResourcePath("email/yahoo_1x.png", IDR_NUX_EMAIL_YAHOO_1X); + html_source->AddResourcePath("email/yahoo_2x.png", IDR_NUX_EMAIL_YAHOO_2X); // Add constants to loadtime data for (size_t i = 0; i < (size_t)EmailProviders::kCount; ++i) {
diff --git a/components/nux/email/resources/aol_1x.png b/components/nux/email/resources/aol_1x.png new file mode 100644 index 0000000..a0c2be3b --- /dev/null +++ b/components/nux/email/resources/aol_1x.png Binary files differ
diff --git a/components/nux/email/resources/aol_2x.png b/components/nux/email/resources/aol_2x.png new file mode 100644 index 0000000..016b54ee --- /dev/null +++ b/components/nux/email/resources/aol_2x.png Binary files differ
diff --git a/components/nux/email/resources/email_chooser.html b/components/nux/email/resources/email_chooser.html index 8485c5c8..d176251 100644 --- a/components/nux/email/resources/email_chooser.html +++ b/components/nux/email/resources/email_chooser.html
@@ -51,11 +51,12 @@ } .option .email-icon { + background-position: center; + background-repeat: no-repeat; + background-size: contain; + height: 40px; margin: 0; margin-bottom: 4px; - /* TODO(scottchen): Replace below with logo once available. */ - background: red; - height: 40px; width: 40px; } @@ -92,6 +93,36 @@ margin-top: 64px; justify-content: space-between; } + + .gmail { + background-image: -webkit-image-set( + url(chrome://welcome/email/gmail_1x.png) 1x, + url(chrome://welcome/email/gmail_2x.png) 2x); + } + + .yahoo { + background-image: -webkit-image-set( + url(chrome://welcome/email/yahoo_1x.png) 1x, + url(chrome://welcome/email/yahoo_2x.png) 2x); + } + + .aol { + background-image: -webkit-image-set( + url(chrome://welcome/email/aol_1x.png) 1x, + url(chrome://welcome/email/aol_2x.png) 2x); + } + + .icloud { + background-image: -webkit-image-set( + url(chrome://welcome/email/icloud_1x.png) 1x, + url(chrome://welcome/email/icloud_2x.png) 2x); + } + + .outlook { + background-image: -webkit-image-set( + url(chrome://welcome/email/outlook_1x.png) 1x, + url(chrome://welcome/email/outlook_2x.png) 2x); + } </style> <template is="dom-repeat" items="[[emailList]]">
diff --git a/components/nux/email/resources/gmail_1x.png b/components/nux/email/resources/gmail_1x.png new file mode 100644 index 0000000..63f6ea94 --- /dev/null +++ b/components/nux/email/resources/gmail_1x.png Binary files differ
diff --git a/components/nux/email/resources/gmail_2x.png b/components/nux/email/resources/gmail_2x.png new file mode 100644 index 0000000..c7296e60 --- /dev/null +++ b/components/nux/email/resources/gmail_2x.png Binary files differ
diff --git a/components/nux/email/resources/icloud_1x.png b/components/nux/email/resources/icloud_1x.png new file mode 100644 index 0000000..51083cb --- /dev/null +++ b/components/nux/email/resources/icloud_1x.png Binary files differ
diff --git a/components/nux/email/resources/icloud_2x.png b/components/nux/email/resources/icloud_2x.png new file mode 100644 index 0000000..8304aec --- /dev/null +++ b/components/nux/email/resources/icloud_2x.png Binary files differ
diff --git a/components/nux/email/resources/outlook_1x.png b/components/nux/email/resources/outlook_1x.png new file mode 100644 index 0000000..1866a9d --- /dev/null +++ b/components/nux/email/resources/outlook_1x.png Binary files differ
diff --git a/components/nux/email/resources/outlook_2x.png b/components/nux/email/resources/outlook_2x.png new file mode 100644 index 0000000..72221a3 --- /dev/null +++ b/components/nux/email/resources/outlook_2x.png Binary files differ
diff --git a/components/nux/email/resources/yahoo_1x.png b/components/nux/email/resources/yahoo_1x.png new file mode 100644 index 0000000..f4e0831 --- /dev/null +++ b/components/nux/email/resources/yahoo_1x.png Binary files differ
diff --git a/components/nux/email/resources/yahoo_2x.png b/components/nux/email/resources/yahoo_2x.png new file mode 100644 index 0000000..00d96c1 --- /dev/null +++ b/components/nux/email/resources/yahoo_2x.png Binary files differ
diff --git a/components/offline_pages/core/prefetch/BUILD.gn b/components/offline_pages/core/prefetch/BUILD.gn index b360751..9025df4c 100644 --- a/components/offline_pages/core/prefetch/BUILD.gn +++ b/components/offline_pages/core/prefetch/BUILD.gn
@@ -132,6 +132,8 @@ "prefetch_task_test_base.h", "store/prefetch_store_test_util.cc", "store/prefetch_store_test_util.h", + "stub_prefetch_service.cc", + "stub_prefetch_service.h", "test_download_client.cc", "test_download_client.h", "test_download_service.cc",
diff --git a/components/offline_pages/core/prefetch/stub_prefetch_service.cc b/components/offline_pages/core/prefetch/stub_prefetch_service.cc new file mode 100644 index 0000000..0fcd9188 --- /dev/null +++ b/components/offline_pages/core/prefetch/stub_prefetch_service.cc
@@ -0,0 +1,75 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/offline_pages/core/prefetch/stub_prefetch_service.h" + +#include "url/gurl.h" + +namespace offline_pages { + +void StubPrefetchService::SetContentSuggestionsService( + ntp_snippets::ContentSuggestionsService* content_suggestions) {} + +void StubPrefetchService::SetSuggestionProvider( + SuggestionsProvider* suggestions_provider) {} + +void StubPrefetchService::NewSuggestionsAvailable() {} + +void StubPrefetchService::RemoveSuggestion(GURL url) {} + +PrefetchGCMHandler* StubPrefetchService::GetPrefetchGCMHandler() { + return nullptr; +} + +OfflineEventLogger* StubPrefetchService::GetLogger() { + return nullptr; +} + +OfflineMetricsCollector* StubPrefetchService::GetOfflineMetricsCollector() { + return nullptr; +} + +PrefetchDispatcher* StubPrefetchService::GetPrefetchDispatcher() { + return nullptr; +} + +PrefetchNetworkRequestFactory* +StubPrefetchService::GetPrefetchNetworkRequestFactory() { + return nullptr; +} + +PrefetchDownloader* StubPrefetchService::GetPrefetchDownloader() { + return nullptr; +} + +PrefetchStore* StubPrefetchService::GetPrefetchStore() { + return nullptr; +} + +PrefetchImporter* StubPrefetchService::GetPrefetchImporter() { + return nullptr; +} + +PrefetchBackgroundTaskHandler* +StubPrefetchService::GetPrefetchBackgroundTaskHandler() { + return nullptr; +} + +PrefetchConfiguration* StubPrefetchService::GetPrefetchConfiguration() { + return nullptr; +} + +ThumbnailFetcher* StubPrefetchService::GetThumbnailFetcher() { + return nullptr; +} + +OfflinePageModel* StubPrefetchService::GetOfflinePageModel() { + return nullptr; +} + +SuggestedArticlesObserver* StubPrefetchService::GetSuggestedArticlesObserver() { + return nullptr; +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/stub_prefetch_service.h b/components/offline_pages/core/prefetch/stub_prefetch_service.h new file mode 100644 index 0000000..496f4f36 --- /dev/null +++ b/components/offline_pages/core/prefetch/stub_prefetch_service.h
@@ -0,0 +1,38 @@ +// 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. + +#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_STUB_PREFETCH_SERVICE_H_ +#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_STUB_PREFETCH_SERVICE_H_ + +#include "components/offline_pages/core/prefetch/prefetch_service.h" + +namespace offline_pages { + +// Stub implementation of PrefetchService interface for testing. +class StubPrefetchService : public PrefetchService { + public: + void SetContentSuggestionsService( + ntp_snippets::ContentSuggestionsService* content_suggestions) override; + void SetSuggestionProvider( + SuggestionsProvider* suggestions_provider) override; + void NewSuggestionsAvailable() override; + void RemoveSuggestion(GURL url) override; + PrefetchGCMHandler* GetPrefetchGCMHandler() override; + OfflineEventLogger* GetLogger() override; + OfflineMetricsCollector* GetOfflineMetricsCollector() override; + PrefetchDispatcher* GetPrefetchDispatcher() override; + PrefetchNetworkRequestFactory* GetPrefetchNetworkRequestFactory() override; + PrefetchDownloader* GetPrefetchDownloader() override; + PrefetchStore* GetPrefetchStore() override; + PrefetchImporter* GetPrefetchImporter() override; + PrefetchBackgroundTaskHandler* GetPrefetchBackgroundTaskHandler() override; + PrefetchConfiguration* GetPrefetchConfiguration() override; + ThumbnailFetcher* GetThumbnailFetcher() override; + OfflinePageModel* GetOfflinePageModel() override; + SuggestedArticlesObserver* GetSuggestedArticlesObserver() override; +}; + +} // namespace offline_pages + +#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_STUB_PREFETCH_SERVICE_H_
diff --git a/components/resources/nux_email.grdp b/components/resources/nux_email.grdp index 063d3b47..437612f 100644 --- a/components/resources/nux_email.grdp +++ b/components/resources/nux_email.grdp
@@ -1,9 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> <grit-part> - <include name="IDR_NUX_EMAIL_HTML" file="../nux/email/resources/nux_email.html" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_JS" file="../nux/email/resources/nux_email.js" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_PROXY_HTML" file="../nux/email/resources/nux_email_proxy.html" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_PROXY_JS" file="../nux/email/resources/nux_email_proxy.js" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_AOL_1X" file="../nux/email/resources/aol_1x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_AOL_2X" file="../nux/email/resources/aol_2x.png" type="BINDATA" /> <include name="IDR_NUX_EMAIL_CHOOSER_HTML" file="../nux/email/resources/email_chooser.html" type="BINDATA" /> <include name="IDR_NUX_EMAIL_CHOOSER_JS" file="../nux/email/resources/email_chooser.js" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_GMAIL_1X" file="../nux/email/resources/gmail_1x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_GMAIL_2X" file="../nux/email/resources/gmail_2x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_HTML" file="../nux/email/resources/nux_email.html" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_ICLOUD_1X" file="../nux/email/resources/icloud_1x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_ICLOUD_2X" file="../nux/email/resources/icloud_2x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_JS" file="../nux/email/resources/nux_email.js" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_OUTLOOK_1X" file="../nux/email/resources/outlook_1x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_OUTLOOK_2X" file="../nux/email/resources/outlook_2x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_PROXY_HTML" file="../nux/email/resources/nux_email_proxy.html" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_PROXY_JS" file="../nux/email/resources/nux_email_proxy.js" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_YAHOO_1X" file="../nux/email/resources/yahoo_1x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_YAHOO_2X" file="../nux/email/resources/yahoo_2x.png" type="BINDATA" /> </grit-part>
diff --git a/components/subresource_filter/core/common/indexed_ruleset_unittest.cc b/components/subresource_filter/core/common/indexed_ruleset_unittest.cc index 4ca98c0..a48bea50 100644 --- a/components/subresource_filter/core/common/indexed_ruleset_unittest.cc +++ b/components/subresource_filter/core/common/indexed_ruleset_unittest.cc
@@ -9,6 +9,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/strings/string_piece.h" +#include "base/strings/utf_string_conversions.h" #include "components/subresource_filter/core/common/first_party_origin.h" #include "components/url_pattern_index/proto/rules.pb.h" #include "components/url_pattern_index/url_pattern.h" @@ -132,6 +133,85 @@ EXPECT_TRUE(ShouldAllow("https://example.com?filter_out=true")); } +// Ensure patterns containing non-ascii characters are disallowed. +TEST_F(SubresourceFilterIndexedRulesetTest, NonAsciiPatterns) { + // non-ascii character é. + std::string non_ascii = base::WideToUTF8(L"\u00E9"); + ASSERT_FALSE(AddSimpleRule(non_ascii)); + Finish(); + + EXPECT_TRUE(ShouldAllow("https://example.com/q=" + non_ascii)); +} + +// Ensure that specifying non-ascii characters in percent encoded form in +// patterns works. +TEST_F(SubresourceFilterIndexedRulesetTest, PercentEncodedPatterns) { + // Percent encoded form of é. + ASSERT_TRUE(AddSimpleRule("%C3%A9")); + Finish(); + + EXPECT_FALSE( + ShouldAllow("https://example.com/q=" + base::WideToUTF8(L"\u00E9"))); +} + +// Ensures that specifying patterns in punycode works for matching IDN domains. +TEST_F(SubresourceFilterIndexedRulesetTest, IDNHosts) { + // ҏӊԟҭв.com + const std::string punycode = "xn--b1a9p8c1e8r.com"; + ASSERT_TRUE(AddSimpleRule(punycode)); + Finish(); + + EXPECT_FALSE(ShouldAllow("https://" + punycode)); + EXPECT_FALSE(ShouldAllow( + base::WideToUTF8(L"https://\x048f\x04ca\x051f\x04ad\x0432.com"))); +} + +// Ensure patterns containing non-ascii domains are disallowed. +TEST_F(SubresourceFilterIndexedRulesetTest, NonAsciiDomain) { + const char* kUrl = "http://example.com"; + + // ґғ.com + std::string non_ascii_domain = base::WideToUTF8(L"\x0491\x0493.com"); + + auto rule = MakeUrlRule(UrlPattern(kUrl, testing::kSubstring)); + testing::AddDomains({non_ascii_domain}, &rule); + ASSERT_FALSE(AddUrlRule(rule)); + + rule = MakeUrlRule(UrlPattern(kUrl, testing::kSubstring)); + std::string non_ascii_excluded_domain = "~" + non_ascii_domain; + testing::AddDomains({non_ascii_excluded_domain}, &rule); + ASSERT_FALSE(AddUrlRule(rule)); + + Finish(); +} + +// Ensure patterns with percent encoded hosts match correctly. +TEST_F(SubresourceFilterIndexedRulesetTest, PercentEncodedHostPattern) { + const char* kPercentEncodedHost = "http://%2C.com/"; + ASSERT_TRUE(AddSimpleRule(kPercentEncodedHost)); + Finish(); + + EXPECT_FALSE(ShouldAllow("http://,.com/")); + EXPECT_FALSE(ShouldAllow(kPercentEncodedHost)); +} + +// Verifies the behavior for rules having percent encoded domains. +TEST_F(SubresourceFilterIndexedRulesetTest, PercentEncodedDomain) { + const char* kUrl = "http://example.com"; + std::string percent_encoded_host = "%2C.com"; + + auto rule = MakeUrlRule(UrlPattern(kUrl, testing::kSubstring)); + testing::AddDomains({percent_encoded_host}, &rule); + ASSERT_TRUE(AddUrlRule(rule)); + Finish(); + + // Note: This should actually fail. However url_pattern_index lower cases all + // domains. Hence it doesn't correctly deal with domains having escape + // characters which are percent-encoded in upper case by Chrome's url parser. + EXPECT_TRUE(ShouldAllow(kUrl, "http://" + percent_encoded_host)); + EXPECT_TRUE(ShouldAllow(kUrl, "http://,.com")); +} + TEST_F(SubresourceFilterIndexedRulesetTest, SimpleBlacklistAndWhitelist) { ASSERT_TRUE(AddSimpleRule("?filter=")); ASSERT_TRUE(AddSimpleWhitelistRule("whitelisted.com/?filter="));
diff --git a/components/url_pattern_index/flat/url_pattern_index.fbs b/components/url_pattern_index/flat/url_pattern_index.fbs index b7ffd7d2..27816497 100644 --- a/components/url_pattern_index/flat/url_pattern_index.fbs +++ b/components/url_pattern_index/flat/url_pattern_index.fbs
@@ -87,11 +87,15 @@ // The list of domains to be included/excluded from the filter's affected set. // Should either be null or have at least a single element. The domains // should be in lower-case and kept sorted as defined by - // url_pattern_index::CompareDomains. + // url_pattern_index::CompareDomains. The entries must consist of only ascii + // characters. Use punycode encoding for internationalized domains. domains_included : [string]; domains_excluded : [string]; - // A URL pattern in the format defined by |url_pattern_type|. + // A URL pattern in the format defined by |url_pattern_type|. This should + // only consist of ascii characters, since it's matched against a url where + // the host is encoded in the punycode format (in case of internationalized + // domains) and any other non-ascii characters are percent-escaped in utf-8. url_pattern : string; // An id which uniquely identifies the rule. Clients must ensure uniqueness if
diff --git a/components/url_pattern_index/url_pattern_index.cc b/components/url_pattern_index/url_pattern_index.cc index a09240a..20308ac 100644 --- a/components/url_pattern_index/url_pattern_index.cc +++ b/components/url_pattern_index/url_pattern_index.cc
@@ -133,16 +133,16 @@ IsMeaningful(); } - // Returns whether the |rule| can be converted to its FlatBuffers equivalent. - // The conversion is not possible if the rule has attributes not supported by - // this client version. - bool is_convertible() const { return is_convertible_; } - // Writes the URL |rule| to the FlatBuffer using the |builder|, and returns - // the offset to the serialized rule. + // the offset to the serialized rule. Returns an empty offset in case the rule + // can't be converted. The conversion is not possible if the rule has + // attributes not supported by this client version. UrlRuleOffset SerializeConvertedRule( flatbuffers::FlatBufferBuilder* builder) const { - DCHECK(is_convertible()); + if (!is_convertible_) + return UrlRuleOffset(); + + DCHECK_NE(rule_.url_pattern_type(), proto::URL_PATTERN_TYPE_REGEXP); FlatDomainsOffset domains_included_offset; FlatDomainsOffset domains_excluded_offset; @@ -155,12 +155,15 @@ domains_included.reserve(rule_.domains_size()); for (const auto& domain_list_item : rule_.domains()) { - // Note: The |domain| can have non-ASCII UTF-8 characters, but - // ToLowerASCII leaves these intact. - // TODO(pkalinnikov): Convert non-ASCII characters to lower case too. - // TODO(pkalinnikov): Possibly convert Punycode to IDN here or directly - // assume this is done in the proto::UrlRule. const std::string& domain = domain_list_item.domain(); + + // Non-ascii characters in domains are unsupported. + if (!base::IsStringASCII(domain)) + return UrlRuleOffset(); + + // Note: This is not always correct. Chrome's URL parser uses upper-case + // for percent encoded hosts. E.g. https://,.com is encoded as + // https://%2C.com. auto offset = builder->CreateSharedString( HasNoUpperAscii(domain) ? domain : base::ToLowerASCII(domain)); @@ -190,6 +193,10 @@ } } + // Non-ascii characters in patterns are unsupported. + if (!base::IsStringASCII(rule_.url_pattern())) + return UrlRuleOffset(); + auto url_pattern_offset = builder->CreateString(rule_.url_pattern()); return flat::CreateUrlRule( @@ -349,9 +356,6 @@ flatbuffers::FlatBufferBuilder* builder) { DCHECK(builder); UrlRuleFlatBufferConverter converter(rule); - if (!converter.is_convertible()) - return UrlRuleOffset(); - DCHECK_NE(rule.url_pattern_type(), proto::URL_PATTERN_TYPE_REGEXP); return converter.SerializeConvertedRule(builder); } @@ -376,6 +380,20 @@ const auto* rule = flatbuffers::GetTemporaryPointer(*flat_builder_, offset); DCHECK(rule); + +// Sanity check that the rule does not have fields with non-ascii characters. +#if DCHECK_IS_ON() + DCHECK(base::IsStringASCII(ToStringPiece(rule->url_pattern()))); + if (rule->domains_included()) { + for (auto* domain : *rule->domains_included()) + DCHECK(base::IsStringASCII(ToStringPiece(domain))); + } + if (rule->domains_excluded()) { + for (auto* domain : *rule->domains_excluded()) + DCHECK(base::IsStringASCII(ToStringPiece(domain))); + } +#endif + NGram ngram = GetMostDistinctiveNGram(ToStringPiece(rule->url_pattern())); if (ngram) {
diff --git a/content/browser/accessibility/accessibility_mode_browsertest.cc b/content/browser/accessibility/accessibility_mode_browsertest.cc index 8bbb734..c68ecf5 100644 --- a/content/browser/accessibility/accessibility_mode_browsertest.cc +++ b/content/browser/accessibility/accessibility_mode_browsertest.cc
@@ -18,7 +18,7 @@ #include "content/shell/browser/shell.h" #include "content/test/accessibility_browser_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" namespace content {
diff --git a/content/browser/accessibility/browser_accessibility_com_win.cc b/content/browser/accessibility/browser_accessibility_com_win.cc index c874c05..d729646 100644 --- a/content/browser/accessibility/browser_accessibility_com_win.cc +++ b/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -20,7 +20,7 @@ #include "content/common/accessibility_messages.h" #include "content/public/common/content_client.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" #include "ui/accessibility/ax_role_properties.h" #include "ui/accessibility/ax_text_utils.h" #include "ui/base/win/accessibility_ids_win.h"
diff --git a/content/browser/accessibility/browser_accessibility_state_impl.h b/content/browser/accessibility/browser_accessibility_state_impl.h index 9b57bbd..d3d09e3 100644 --- a/content/browser/accessibility/browser_accessibility_state_impl.h +++ b/content/browser/accessibility/browser_accessibility_state_impl.h
@@ -11,8 +11,8 @@ #include "base/macros.h" #include "base/memory/singleton.h" #include "content/public/browser/browser_accessibility_state.h" +#include "ui/accessibility/ax_mode.h" #include "ui/accessibility/ax_mode_observer.h" -#include "ui/accessibility/ax_modes.h" namespace content {
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc index 72e60fd..918c7b6 100644 --- a/content/browser/frame_host/navigation_handle_impl.cc +++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -72,26 +72,34 @@ *to_update = result; } +// LOG_NAVIGATION_TIMING_HISTOGRAM logs |value| for "Navigation.<histogram>" UMA +// and (depending on |transition|) also for +// "Navigation.<histogram>.BackForward/Reload/NewNavigation" UMA. +// +// kMaxTime and kBuckets constants are consistent with +// UMA_HISTOGRAM_MEDIUM_TIMES, but a custom kMinTime is used for high fidelity +// near the low end of measured values. +// // TODO(csharrison,nasko): This macro is incorrect for subframe navigations, // which will only have subframe-specific transition types. This means that all // subframes currently are tagged as NewNavigations. -#define LOG_NAVIGATION_TIMING_HISTOGRAM(histogram, transition, value, \ - max_time) \ +#define LOG_NAVIGATION_TIMING_HISTOGRAM(histogram, transition, value) \ do { \ const base::TimeDelta kMinTime = base::TimeDelta::FromMilliseconds(1); \ + const base::TimeDelta kMaxTime = base::TimeDelta::FromMinutes(3); \ const int kBuckets = 50; \ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram, value, kMinTime, \ - max_time, kBuckets); \ + kMaxTime, kBuckets); \ if (transition & ui::PAGE_TRANSITION_FORWARD_BACK) { \ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".BackForward", \ - value, kMinTime, max_time, kBuckets); \ + value, kMinTime, kMaxTime, kBuckets); \ } else if (ui::PageTransitionCoreTypeIs(transition, \ ui::PAGE_TRANSITION_RELOAD)) { \ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".Reload", value, \ - kMinTime, max_time, kBuckets); \ + kMinTime, kMaxTime, kBuckets); \ } else if (ui::PageTransitionIsNewNavigation(transition)) { \ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".NewNavigation", \ - value, kMinTime, max_time, kBuckets); \ + value, kMinTime, kMaxTime, kBuckets); \ } else { \ NOTREACHED() << "Invalid page transition: " << transition; \ } \ @@ -852,30 +860,23 @@ frame_tree_node_->current_frame_host()->GetProcess()->GetID(); LogIsSameProcess(transition_, is_same_process_); - // TODO(csharrison,nasko): Increase the max value to 3 minutes in M68 or - // M69. base::TimeDelta delta = ready_to_commit_time_ - navigation_start_; - LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit", transition_, delta, - base::TimeDelta::FromSeconds(10)); + LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit", transition_, delta); if (IsInMainFrame()) { LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit.MainFrame", - transition_, delta, - base::TimeDelta::FromSeconds(10)); + transition_, delta); } else { LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit.Subframe", - transition_, delta, - base::TimeDelta::FromSeconds(10)); + transition_, delta); } if (is_same_process_) { LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit.SameProcess", - transition_, delta, - base::TimeDelta::FromSeconds(10)); + transition_, delta); } else { LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit.CrossProcess", - transition_, delta, - base::TimeDelta::FromSeconds(10)); + transition_, delta); } } @@ -927,44 +928,39 @@ base::TimeTicks now = base::TimeTicks::Now(); base::TimeDelta delta = now - navigation_start_; ui::PageTransition transition = GetPageTransition(); - // 3 minutes aligns with UMA_HISTOGRAM_MEDIUM_TIMES. - const base::TimeDelta kMaxTime = base::TimeDelta::FromMinutes(3); - LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit", transition, delta, - kMaxTime); + LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit", transition, delta); if (IsInMainFrame()) { LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.MainFrame", transition, - delta, kMaxTime); + delta); } else { LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.Subframe", transition, - delta, kMaxTime); + delta); } if (is_same_process_) { LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess", transition, - delta, kMaxTime); + delta); if (IsInMainFrame()) { LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess.MainFrame", - transition, delta, kMaxTime); + transition, delta); } else { LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess.Subframe", - transition, delta, kMaxTime); + transition, delta); } } else { LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess", transition, - delta, kMaxTime); + delta); if (IsInMainFrame()) { LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess.MainFrame", - transition, delta, kMaxTime); + transition, delta); } else { LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess.Subframe", - transition, delta, kMaxTime); + transition, delta); } } - // 10 seconds aligns with UMA_HISTOGRAM_TIMES. if (!ready_to_commit_time_.is_null()) { LOG_NAVIGATION_TIMING_HISTOGRAM("ReadyToCommitUntilCommit", transition_, - now - ready_to_commit_time_, - base::TimeDelta::FromSeconds(10)); + now - ready_to_commit_time_); } }
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 2733e0d9..01f060b 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -76,7 +76,7 @@ #include "third_party/blink/public/web/commit_result.mojom.h" #include "third_party/blink/public/web/web_text_direction.h" #include "third_party/blink/public/web/web_tree_scope_type.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/mojo/window_open_disposition.mojom.h" #include "ui/base/page_transition_types.h"
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc index 4541da4..cc6ea8c 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private.cc +++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -335,9 +335,6 @@ if (swiftshader_available) return true; - if (in_process_gpu_) - return true; - if (card_disabled_) { if (reason) { *reason = "GPU access is disabled ";
diff --git a/content/browser/renderer_host/input/touch_action_filter.cc b/content/browser/renderer_host/input/touch_action_filter.cc index 8ac9be14..db33ffd 100644 --- a/content/browser/renderer_host/input/touch_action_filter.cc +++ b/content/browser/renderer_host/input/touch_action_filter.cc
@@ -66,6 +66,8 @@ "scrollbegin-gestures", base::debug::CrashKeySize::Size256); base::debug::SetCrashKeyString(crash_key, gesture_sequence_); gesture_sequence_.clear(); + // https://crbug.com/869375, temporary fix to prevent crash. + SetTouchAction(cc::kTouchActionAuto); } suppress_manipulation_events_ = ShouldSuppressManipulation(*gesture_event); @@ -92,6 +94,8 @@ "scrollupdate-gestures", base::debug::CrashKeySize::Size256); base::debug::SetCrashKeyString(crash_key, gesture_sequence_); gesture_sequence_.clear(); + // https://crbug.com/869375, temporary fix to prevent crash. + SetTouchAction(cc::kTouchActionAuto); } if (IsYAxisActionDisallowed(scrolling_touch_action_.value())) { gesture_event->data.scroll_update.delta_y = 0; @@ -146,6 +150,8 @@ "tapunconfirmed-gestures", base::debug::CrashKeySize::Size256); base::debug::SetCrashKeyString(crash_key, gesture_sequence_); gesture_sequence_.clear(); + // https://crbug.com/869375, temporary fix to prevent crash. + SetTouchAction(cc::kTouchActionAuto); } allow_current_double_tap_event_ = (scrolling_touch_action_.value() & cc::kTouchActionDoubleTapZoom) != 0; @@ -255,6 +261,9 @@ } void TouchActionFilter::ReportTouchAction() { + // https://crbug.com/869375, temporary fix to prevent crash. + if (!scrolling_touch_action_.has_value()) + SetTouchAction(cc::kTouchActionAuto); // Report the effective touch action computed by blink such as // kTouchActionNone, kTouchActionPanX, etc. // Since |cc::kTouchActionAuto| is equivalent to |cc::kTouchActionMax|, we
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index bf02935..e4bafbdf 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3120,7 +3120,11 @@ renderer_cmd->AppendSwitch(switches::kDisableDatabases); } -#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) +#if defined(OS_ANDROID) + if (browser_cmd.HasSwitch(switches::kDisableGpuCompositing)) { + renderer_cmd->AppendSwitch(switches::kDisableGpuCompositing); + } +#elif !defined(OS_CHROMEOS) #if !BUILDFLAG(ENABLE_MUS) // If gpu compositing is not being used, tell the renderer at startup. This // is inherently racey, as it may change while the renderer is being launched, @@ -3131,11 +3135,11 @@ // no need to check this state and forward it. if (ImageTransportFactory::GetInstance()->IsGpuCompositingDisabled()) renderer_cmd->AppendSwitch(switches::kDisableGpuCompositing); -#else +#else // BUILDFLAG(ENABLE_MUS) // TODO(tonikitoo): Check if renderer should use software compositing // through some mechanism that isn't ImageTransportFactory with mus. -#endif -#endif +#endif // !BUILDFLAG(ENABLE_MUS) +#endif // defined(OS_ANDROID) // Add kWaitForDebugger to let renderer process wait for a debugger. if (browser_cmd.HasSwitch(switches::kWaitForDebuggerChildren)) {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 042b256..1f14fd9 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -60,7 +60,7 @@ #include "third_party/blink/public/mojom/color_chooser/color_chooser.mojom.h" #include "third_party/blink/public/mojom/page/display_cutout.mojom.h" #include "third_party/blink/public/platform/web_drag_operation.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" #include "ui/base/page_transition_types.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/size.h"
diff --git a/content/common/content_param_traits.cc b/content/common/content_param_traits.cc index cac6c15..59f0865a 100644 --- a/content/common/content_param_traits.cc +++ b/content/common/content_param_traits.cc
@@ -19,7 +19,7 @@ #include "third_party/blink/public/common/message_port/message_port_channel.h" #include "third_party/blink/public/common/message_port/transferable_message.h" #include "third_party/blink/public/mojom/message_port/message_port.mojom.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" #include "ui/base/ui_base_features.h" #include "ui/events/blink/web_input_event_traits.h" // #include "ui/gfx/ipc/geometry/gfx_param_traits.h"
diff --git a/content/common/content_param_traits.h b/content/common/content_param_traits.h index e9a29ff..6f58e7b 100644 --- a/content/common/content_param_traits.h +++ b/content/common/content_param_traits.h
@@ -19,7 +19,7 @@ #include "ipc/ipc_mojo_param_traits.h" #include "storage/common/blob_storage/blob_handle.h" #include "third_party/blink/public/platform/web_input_event.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" namespace blink { class MessagePortChannel;
diff --git a/content/common/frame_message_enums.h b/content/common/frame_message_enums.h index c2b16621f..85943bf1 100644 --- a/content/common/frame_message_enums.h +++ b/content/common/frame_message_enums.h
@@ -5,7 +5,7 @@ #ifndef CONTENT_COMMON_FRAME_MESSAGE_ENUMS_H_ #define CONTENT_COMMON_FRAME_MESSAGE_ENUMS_H_ -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" struct FrameMsg_Navigate_Type { public:
diff --git a/content/public/browser/browser_accessibility_state.h b/content/public/browser/browser_accessibility_state.h index 3c969f9..484214b 100644 --- a/content/public/browser/browser_accessibility_state.h +++ b/content/public/browser/browser_accessibility_state.h
@@ -8,7 +8,7 @@ #include "base/callback_forward.h" #include "content/common/content_export.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" namespace content {
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h index 786eecf..73a83f9 100644 --- a/content/public/browser/web_contents.h +++ b/content/public/browser/web_contents.h
@@ -33,7 +33,7 @@ #include "third_party/blink/public/common/frame/sandbox_flags.h" #include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" #include "ui/accessibility/ax_tree_update.h" #include "ui/base/window_open_disposition.h" #include "ui/gfx/geometry/rect.h"
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 8c1a929..5c16b2f 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -377,7 +377,7 @@ // Save the scroll anchor and use it to restore scroll position. const base::Feature kScrollAnchorSerialization{ - "ScrollAnchorSerialization", base::FEATURE_DISABLED_BY_DEFAULT}; + "ScrollAnchorSerialization", base::FEATURE_ENABLED_BY_DEFAULT}; // Make sendBeacon throw for a Blob with a non simple type. const base::Feature kSendBeaconThrowForBlobWithNonSimpleType{ @@ -477,7 +477,7 @@ // Enable WebAssembly baseline compilation and tier up. const base::Feature kWebAssemblyBaseline{"WebAssemblyBaseline", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Enable WebAssembly threads. // https://github.com/WebAssembly/threads
diff --git a/content/public/renderer/render_frame.h b/content/public/renderer/render_frame.h index 292a3abb..77df96a 100644 --- a/content/public/renderer/render_frame.h +++ b/content/public/renderer/render_frame.h
@@ -24,7 +24,7 @@ #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/web/web_navigation_policy.h" #include "third_party/blink/public/web/web_triggering_event_info.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" namespace blink { class AssociatedInterfaceProvider;
diff --git a/content/public/test/test_browser_thread_bundle.cc b/content/public/test/test_browser_thread_bundle.cc index f2f0b5c..93f0ec21 100644 --- a/content/public/test/test_browser_thread_bundle.cc +++ b/content/public/test/test_browser_thread_bundle.cc
@@ -21,6 +21,19 @@ namespace content { +namespace { + +base::test::ScopedTaskEnvironment::MainThreadType GetThreadTypeFromOptions( + int options) { + if (options & TestBrowserThreadBundle::PLAIN_MAINLOOP) + return base::test::ScopedTaskEnvironment::MainThreadType::DEFAULT; + if (options & TestBrowserThreadBundle::IO_MAINLOOP) + return base::test::ScopedTaskEnvironment::MainThreadType::IO; + return base::test::ScopedTaskEnvironment::MainThreadType::UI; +} + +} // namespace + TestBrowserThreadBundle::TestBrowserThreadBundle() : TestBrowserThreadBundle(DEFAULT) {} @@ -81,6 +94,8 @@ CHECK(!(options_ & IO_MAINLOOP) || !(options_ & REAL_IO_THREAD)); // There must be a thread to start to use DONT_CREATE_BROWSER_THREADS CHECK((options_ & ~IO_MAINLOOP) != DONT_CREATE_BROWSER_THREADS); + // Check for conflicting main loop options. + CHECK(!(options_ & IO_MAINLOOP) || !(options_ & PLAIN_MAINLOOP)); #if defined(OS_WIN) // Similar to Chrome's UI thread, we need to initialize COM separately for @@ -96,15 +111,15 @@ // ScopedTaskEnvironment may already exist if this TestBrowserThreadBundle is // instantiated in a test whose parent fixture provides a // ScopedTaskEnvironment. - if (!base::MessageLoopCurrent::IsSet()) { + if (!base::ThreadTaskRunnerHandle::IsSet()) { scoped_task_environment_ = std::make_unique<base::test::ScopedTaskEnvironment>( - options_ & IO_MAINLOOP - ? base::test::ScopedTaskEnvironment::MainThreadType::IO - : base::test::ScopedTaskEnvironment::MainThreadType::UI); + GetThreadTypeFromOptions(options_)); } - CHECK(options_ & IO_MAINLOOP ? base::MessageLoopCurrentForIO::IsSet() - : base::MessageLoopCurrentForUI::IsSet()); + if (options_ & IO_MAINLOOP) + CHECK(base::MessageLoopCurrentForIO::IsSet()); + else if (!(options_ & PLAIN_MAINLOOP)) + CHECK(base::MessageLoopCurrentForUI::IsSet()); // Set the current thread as the UI thread. ui_thread_ = std::make_unique<TestBrowserThread>(
diff --git a/content/public/test/test_browser_thread_bundle.h b/content/public/test/test_browser_thread_bundle.h index 5b7c8d6..84348a1 100644 --- a/content/public/test/test_browser_thread_bundle.h +++ b/content/public/test/test_browser_thread_bundle.h
@@ -109,6 +109,8 @@ // Used to specify the type of MessageLoop that backs the UI thread, and // which of the named BrowserThreads should be backed by a real // threads. The UI thread is always the main thread in a unit test. + // TODO(https://crbug.com/881041): The mainloop types are mutually exclusive, + // and can be removed from here and given as a separate constructor argument. enum Options { DEFAULT = 0, // The main thread will use a MessageLoopForIO (and support the @@ -116,6 +118,9 @@ IO_MAINLOOP = 1 << 0, REAL_IO_THREAD = 1 << 1, DONT_CREATE_BROWSER_THREADS = 1 << 2, + // The main thread will use a plain main loop instead of a MessageLoopForUI. + // (i.e. will support ThreadTaskRunnerHandle::Get() and RunLoop only). + PLAIN_MAINLOOP = 1 << 3, }; TestBrowserThreadBundle();
diff --git a/content/renderer/accessibility/blink_ax_tree_source.h b/content/renderer/accessibility/blink_ax_tree_source.h index 2adf7bf..81e87f0 100644 --- a/content/renderer/accessibility/blink_ax_tree_source.h +++ b/content/renderer/accessibility/blink_ax_tree_source.h
@@ -12,7 +12,7 @@ #include "content/common/ax_content_node_data.h" #include "third_party/blink/public/web/web_ax_object.h" #include "third_party/blink/public/web/web_document.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" #include "ui/accessibility/ax_node_data.h" #include "ui/accessibility/ax_tree_source.h"
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 31ba4a12..fe1866a6 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -93,7 +93,7 @@ #include "third_party/blink/public/web/web_meaningful_layout.h" #include "third_party/blink/public/web/web_script_execution_callback.h" #include "third_party/blink/public/web/web_triggering_event_info.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" #include "ui/gfx/range/range.h" #include "url/gurl.h" #include "url/origin.h"
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 0647169..c1727c2 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -88,7 +88,7 @@ #include "third_party/blink/public/web/web_settings.h" #include "third_party/blink/public/web/web_view.h" #include "third_party/blink/public/web/web_window_features.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" #include "ui/events/base_event_utils.h" #include "ui/events/event.h" #include "ui/events/keycodes/dom/dom_code.h"
diff --git a/content/test/accessibility_browser_test_utils.h b/content/test/accessibility_browser_test_utils.h index 93e3aaa7..5c0a4df 100644 --- a/content/test/accessibility_browser_test_utils.h +++ b/content/test/accessibility_browser_test_utils.h
@@ -7,7 +7,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" #include "ui/accessibility/ax_node_data.h" #include "ui/accessibility/ax_tree.h"
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 79d09a8..c81ad220 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -321,8 +321,6 @@ # Win / Intel self.Fail('conformance/rendering/rendering-stencil-large-viewport.html', ['win', 'intel', 'd3d11'], bug=782317) - self.Fail('conformance2/glsl3/short-circuiting-in-loop-condition.html', - ['win', 'intel'], bug=843369) # Seems to cause the harness to fail immediately afterward self.Skip('conformance2/textures/video/tex-2d-rgba16f-rgba-half_float.html',
diff --git a/device/bluetooth/bluetooth_socket_mac.mm b/device/bluetooth/bluetooth_socket_mac.mm index ea9a325..28dcb492 100644 --- a/device/bluetooth/bluetooth_socket_mac.mm +++ b/device/bluetooth/bluetooth_socket_mac.mm
@@ -687,8 +687,7 @@ DCHECK(!is_connecting()); int data_size = base::checked_cast<int>(length); - scoped_refptr<net::IOBufferWithSize> buffer( - new net::IOBufferWithSize(data_size)); + auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(data_size); memcpy(buffer->data(), data, buffer->size()); // If there is a pending read callback, call it now. @@ -728,8 +727,8 @@ // |writeAsync| accepts buffers of max. mtu bytes per call, so we need to emit // multiple write operations if buffer_size > mtu. uint16_t mtu = channel_->GetOutgoingMTU(); - scoped_refptr<net::DrainableIOBuffer> send_buffer( - new net::DrainableIOBuffer(buffer.get(), buffer_size)); + auto send_buffer = + base::MakeRefCounted<net::DrainableIOBuffer>(buffer.get(), buffer_size); while (send_buffer->BytesRemaining() > 0) { int byte_count = send_buffer->BytesRemaining(); if (byte_count > mtu)
diff --git a/device/bluetooth/bluetooth_socket_net.cc b/device/bluetooth/bluetooth_socket_net.cc index 422be8c..079fd310 100644 --- a/device/bluetooth/bluetooth_socket_net.cc +++ b/device/bluetooth/bluetooth_socket_net.cc
@@ -168,8 +168,7 @@ return; } - scoped_refptr<net::IOBufferWithSize> buffer( - new net::IOBufferWithSize(buffer_size)); + auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(buffer_size); int read_result = tcp_socket_->Read(buffer.get(), buffer->size(),
diff --git a/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc index da1b0859..ae8c7388 100644 --- a/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc +++ b/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc
@@ -208,8 +208,7 @@ error_callback_count_ = 0; // Send data to the socket, expect all of the data to be sent. - scoped_refptr<net::StringIOBuffer> write_buffer( - new net::StringIOBuffer("test")); + auto write_buffer = base::MakeRefCounted<net::StringIOBuffer>("test"); { base::RunLoop run_loop; @@ -281,7 +280,7 @@ // Send data again; since the socket is closed we should get a system error // equivalent to the connection reset error. - write_buffer = new net::StringIOBuffer("second test"); + write_buffer = base::MakeRefCounted<net::StringIOBuffer>("second test"); { base::RunLoop run_loop;
diff --git a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc index 9e37d13..d037494 100644 --- a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc +++ b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc
@@ -573,7 +573,7 @@ EXTENSION_FUNCTION_VALIDATE(params_.get()); io_buffer_size_ = params_->data.size(); - io_buffer_ = new net::WrappedIOBuffer( + io_buffer_ = base::MakeRefCounted<net::WrappedIOBuffer>( reinterpret_cast<const char*>(params_->data.data())); BluetoothApiSocket* socket = GetSocket(params_->socket_id);
diff --git a/extensions/browser/api/display_source/display_source_apitestbase.cc b/extensions/browser/api/display_source/display_source_apitestbase.cc index 30e29fc..04482ca 100644 --- a/extensions/browser/api/display_source/display_source_apitestbase.cc +++ b/extensions/browser/api/display_source/display_source_apitestbase.cc
@@ -500,7 +500,7 @@ DCHECK(socket_.get()); const int kBufferSize = 512; - recvfrom_buffer_ = new net::IOBuffer(kBufferSize); + recvfrom_buffer_ = base::MakeRefCounted<net::IOBuffer>(kBufferSize); int net_result = socket_->RecvFrom( recvfrom_buffer_.get(), kBufferSize, &end_point_,
diff --git a/extensions/browser/api/socket/socket.cc b/extensions/browser/api/socket/socket.cc index 23dac927..e8d21a9 100644 --- a/extensions/browser/api/socket/socket.cc +++ b/extensions/browser/api/socket/socket.cc
@@ -53,8 +53,8 @@ WriteRequest& request = write_queue_.front(); DCHECK(request.byte_count >= request.bytes_written); - io_buffer_write_ = new net::WrappedIOBuffer(request.io_buffer->data() + - request.bytes_written); + io_buffer_write_ = base::MakeRefCounted<net::WrappedIOBuffer>( + request.io_buffer->data() + request.bytes_written); int result = WriteImpl( io_buffer_write_.get(), request.byte_count - request.bytes_written, base::Bind(&Socket::OnWriteComplete, base::Unretained(this)));
diff --git a/extensions/browser/api/socket/udp_socket.cc b/extensions/browser/api/socket/udp_socket.cc index f9b8aa9..2c784d2 100644 --- a/extensions/browser/api/socket/udp_socket.cc +++ b/extensions/browser/api/socket/udp_socket.cc
@@ -231,8 +231,7 @@ return; } - scoped_refptr<net::IOBuffer> io_buffer = - new net::IOBuffer(data.value().size()); + auto io_buffer = base::MakeRefCounted<net::IOBuffer>(data.value().size()); memcpy(io_buffer->data(), data.value().data(), data.value().size()); if (!read_callback_.is_null()) {
diff --git a/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc b/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc index c0aeac5..86c4d754 100644 --- a/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc +++ b/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc
@@ -364,7 +364,7 @@ params_ = sockets_tcp::Send::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(params_.get()); io_buffer_size_ = params_->data.size(); - io_buffer_ = new net::WrappedIOBuffer( + io_buffer_ = base::MakeRefCounted<net::WrappedIOBuffer>( reinterpret_cast<const char*>(params_->data.data())); return true; }
diff --git a/extensions/browser/api/sockets_udp/sockets_udp_api.cc b/extensions/browser/api/sockets_udp/sockets_udp_api.cc index 3b169c9..70121fe 100644 --- a/extensions/browser/api/sockets_udp/sockets_udp_api.cc +++ b/extensions/browser/api/sockets_udp/sockets_udp_api.cc
@@ -240,7 +240,7 @@ params_ = sockets_udp::Send::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(params_.get()); io_buffer_size_ = params_->data.size(); - io_buffer_ = new net::WrappedIOBuffer( + io_buffer_ = base::MakeRefCounted<net::WrappedIOBuffer>( reinterpret_cast<const char*>(params_->data.data())); return true;
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc index 72571f4..a285967 100644 --- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc +++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
@@ -121,12 +121,19 @@ const base::Optional<std::vector<std::string>>& to_be_removed_request_headers, const base::Optional<net::HttpRequestHeaders>& modified_request_headers) { - DCHECK(!modified_request_headers.has_value()) << "Redirect with modified " - "headers was not supported " - "yet. crbug.com/845683"; + if (to_be_removed_request_headers) { + for (const std::string& header : *to_be_removed_request_headers) + request_.headers.RemoveHeader(header); + } - if (target_loader_.is_bound()) - target_loader_->FollowRedirect(base::nullopt, base::nullopt); + if (modified_request_headers) + request_.headers.MergeFrom(*modified_request_headers); + + if (target_loader_.is_bound()) { + target_loader_->FollowRedirect(to_be_removed_request_headers, + modified_request_headers); + } + Restart(); }
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 837466b..771fae4 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1334,6 +1334,7 @@ ENTERPRISE_HARDWAREPLATFORM_GETHARDWAREPLATFORMINFO = 1271, FILEMANAGERPRIVATEINTERNAL_SHAREPATHWITHCROSTINICONTAINER = 1272, AUTOTESTPRIVATE_SETCROSTINIENABLED = 1273, + AUTOTESTPRIVATE_GETHISTOGRAM = 1274, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/google_apis/gcm/base/socket_stream.cc b/google_apis/gcm/base/socket_stream.cc index 0c0fada..e7af5c6 100644 --- a/google_apis/gcm/base/socket_stream.cc +++ b/google_apis/gcm/base/socket_stream.cc
@@ -223,7 +223,8 @@ mojo::ScopedDataPipeProducerHandle stream) : stream_(std::move(stream)), stream_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL), - io_buffer_(new net::IOBufferWithSize(kDefaultBufferSize)), + io_buffer_( + base::MakeRefCounted<net::IOBufferWithSize>(kDefaultBufferSize)), next_pos_(0), last_error_(net::OK), weak_ptr_factory_(this) {
diff --git a/gpu/ipc/host/shader_disk_cache.cc b/gpu/ipc/host/shader_disk_cache.cc index 3a33f6b..2f3a9cad 100644 --- a/gpu/ipc/host/shader_disk_cache.cc +++ b/gpu/ipc/host/shader_disk_cache.cc
@@ -260,7 +260,7 @@ } op_type_ = WRITE_DATA; - scoped_refptr<net::StringIOBuffer> io_buf = new net::StringIOBuffer(shader_); + auto io_buf = base::MakeRefCounted<net::StringIOBuffer>(shader_); return entry_->WriteData(1, 0, io_buf.get(), shader_.length(), base::Bind(&ShaderDiskCacheEntry::OnOpComplete, weak_ptr_factory_.GetWeakPtr()), @@ -354,7 +354,7 @@ return rv; op_type_ = READ_COMPLETE; - buf_ = new net::IOBufferWithSize(entry_->GetDataSize(1)); + buf_ = base::MakeRefCounted<net::IOBufferWithSize>(entry_->GetDataSize(1)); return entry_->ReadData(1, 0, buf_.get(), buf_->size(), base::Bind(&ShaderDiskReadHelper::OnOpComplete, weak_ptr_factory_.GetWeakPtr()));
diff --git a/gpu/vulkan/BUILD.gn b/gpu/vulkan/BUILD.gn index 59d257e..a3a32d8 100644 --- a/gpu/vulkan/BUILD.gn +++ b/gpu/vulkan/BUILD.gn
@@ -61,6 +61,11 @@ "//base", "//ui/gfx", ] + + data_deps = [] + if (is_fuchsia) { + data_deps += [ "//third_party/fuchsia-sdk:vulkan_layers" ] + } } # TODO(cblume): These tests should run on each platform -- crbug.com/858614
diff --git a/gpu/vulkan/vulkan_instance.cc b/gpu/vulkan/vulkan_instance.cc index 30d15d9..b612179 100644 --- a/gpu/vulkan/vulkan_instance.cc +++ b/gpu/vulkan/vulkan_instance.cc
@@ -46,7 +46,8 @@ } bool VulkanInstance::Initialize( - const std::vector<const char*>& required_extensions) { + const std::vector<const char*>& required_extensions, + const std::vector<const char*>& required_layers) { DCHECK(!vk_instance_); VulkanFunctionPointers* vulkan_function_pointers = @@ -124,6 +125,9 @@ enabled_layer_names.push_back(layer_property.layerName); } #endif + enabled_layer_names.insert(std::end(enabled_layer_names), + std::begin(required_layers), + std::end(required_layers)); VkInstanceCreateInfo instance_create_info = {}; instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
diff --git a/gpu/vulkan/vulkan_instance.h b/gpu/vulkan/vulkan_instance.h index af9f502..31a2a477 100644 --- a/gpu/vulkan/vulkan_instance.h +++ b/gpu/vulkan/vulkan_instance.h
@@ -21,7 +21,13 @@ ~VulkanInstance(); - bool Initialize(const std::vector<const char*>& required_extensions); + // Creates the vulkan instance. + // + // The extensions in |required_extensions| and the layers in |required_layers| + // will be enabled in the created instance. See the "Extended Functionality" + // section of vulkan specification for more information. + bool Initialize(const std::vector<const char*>& required_extensions, + const std::vector<const char*>& required_layers); void Destroy();
diff --git a/gpu/vulkan/x/vulkan_implementation_x11.cc b/gpu/vulkan/x/vulkan_implementation_x11.cc index 402e2d87..78fbe4c 100644 --- a/gpu/vulkan/x/vulkan_implementation_x11.cc +++ b/gpu/vulkan/x/vulkan_implementation_x11.cc
@@ -34,7 +34,7 @@ if (!vulkan_function_pointers->vulkan_loader_library_) return false; - if (!vulkan_instance_.Initialize(required_extensions)) { + if (!vulkan_instance_.Initialize(required_extensions, {})) { vulkan_instance_.Destroy(); return false; }
diff --git a/ios/chrome/browser/browsing_data/cache_counter_unittest.cc b/ios/chrome/browser/browsing_data/cache_counter_unittest.cc index 2a95cd9..420cc94 100644 --- a/ios/chrome/browser/browsing_data/cache_counter_unittest.cc +++ b/ios/chrome/browser/browsing_data/cache_counter_unittest.cc
@@ -195,8 +195,7 @@ next_step_ = STEP_CALLBACK; std::string data = "entry data"; - scoped_refptr<net::StringIOBuffer> buffer = - new net::StringIOBuffer(data); + auto buffer = base::MakeRefCounted<net::StringIOBuffer>(data); rv = entry_->WriteData( 0, 0, buffer.get(), data.size(),
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm index 6e0ae4d5..cf7d7d2 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -473,6 +473,7 @@ // Configure the table view. self.sharedState.tableView.accessibilityIdentifier = @"bookmarksTableView"; self.sharedState.tableView.estimatedRowHeight = kEstimatedRowHeight; + self.sharedState.tableView.rowHeight = UITableViewAutomaticDimension; self.tableView.sectionHeaderHeight = 0; // Setting a sectionFooterHeight of 0 will be the same as not having a // footerView, which shows a cell separator for the last cell. Removing this @@ -1885,16 +1886,6 @@ #pragma mark - UITableViewDelegate -- (CGFloat)tableView:(UITableView*)tableView - heightForRowAtIndexPath:(NSIndexPath*)indexPath { - NSInteger sectionIdentifier = [self.sharedState.tableViewModel - sectionIdentifierForSection:indexPath.section]; - if (sectionIdentifier == BookmarkHomeSectionIdentifierBookmarks) { - return kEstimatedRowHeight; - } - return UITableViewAutomaticDimension; -} - - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath { NSInteger sectionIdentifier = [self.sharedState.tableViewModel
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm index e8a2773..94a1f31 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -885,7 +885,8 @@ // Ensure the Bottom 1 of Folder 1 is visible. That means both folder and // scroll position are restored successfully. - [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Bottom 1")] + [[EarlGrey + selectElementWithMatcher:grey_accessibilityLabel(@"Bottom 1, 127.0.0.1")] assertWithMatcher:grey_sufficientlyVisible()]; } @@ -1088,6 +1089,8 @@ base::SysNSStringToUTF16(@"Top URL"), dummyURL); // Add URLs to Folder 1. + bookmark_model->AddURL(folder1, 0, base::SysNSStringToUTF16(dummyTitle), + dummyURL); bookmark_model->AddURL(folder1, 0, base::SysNSStringToUTF16(@"Bottom 1"), dummyURL); for (int i = 0; i < 20; i++) { @@ -1603,7 +1606,7 @@ // verify the editable textfield is gone. [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"bookmark_editing_text")] - assertWithMatcher:grey_nil()]; + assertWithMatcher:grey_notVisible()]; } + (void)tapOnContextMenuButton:(int)menuButtonId
diff --git a/ios/net/chunked_data_stream_uploader_unittest.cc b/ios/net/chunked_data_stream_uploader_unittest.cc index 64996b0d..a2842de 100644 --- a/ios/net/chunked_data_stream_uploader_unittest.cc +++ b/ios/net/chunked_data_stream_uploader_unittest.cc
@@ -82,7 +82,7 @@ // Network layer callback is called next, and the application data is expected // to be read to the |buffer|. - scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kDefaultIOBufferSize); + auto buffer = base::MakeRefCounted<net::IOBuffer>(kDefaultIOBufferSize); int bytes_read = uploader_->Read( buffer.get(), kDefaultIOBufferSize, base::BindRepeating(&ChunkedDataStreamUploaderTest::CompletionCallback, @@ -111,7 +111,7 @@ // layer data available. TEST_F(ChunkedDataStreamUploaderTest, InternalReadReadyFirst) { // Network layer callback is called and the request is pending. - scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kDefaultIOBufferSize); + auto buffer = base::MakeRefCounted<net::IOBuffer>(kDefaultIOBufferSize); int ret = uploader_->Read( buffer.get(), kDefaultIOBufferSize, base::BindRepeating(&ChunkedDataStreamUploaderTest::CompletionCallback, @@ -141,7 +141,7 @@ // Tests that null data is correctly handled when the callback comes first. TEST_F(ChunkedDataStreamUploaderTest, NullContentWithReadFirst) { - scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kDefaultIOBufferSize); + auto buffer = base::MakeRefCounted<net::IOBuffer>(kDefaultIOBufferSize); int ret = uploader_->Read( buffer.get(), kDefaultIOBufferSize, base::BindRepeating(&ChunkedDataStreamUploaderTest::CompletionCallback, @@ -160,7 +160,7 @@ delegate_->SetReadData("", 0); uploader_->UploadWhenReady(true); - scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kDefaultIOBufferSize); + auto buffer = base::MakeRefCounted<net::IOBuffer>(kDefaultIOBufferSize); int bytes_read = uploader_->Read( buffer.get(), kDefaultIOBufferSize, base::BindRepeating(&ChunkedDataStreamUploaderTest::CompletionCallback, @@ -179,7 +179,7 @@ delegate_->SetReadData(kTestData, sizeof(kTestData)); uploader_->UploadWhenReady(false); - scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kDefaultIOBufferSize); + auto buffer = base::MakeRefCounted<net::IOBuffer>(kDefaultIOBufferSize); int bytes_read = uploader_->Read( buffer.get(), kDefaultIOBufferSize, base::BindRepeating(&ChunkedDataStreamUploaderTest::CompletionCallback,
diff --git a/ios/net/crn_http_protocol_handler.mm b/ios/net/crn_http_protocol_handler.mm index 93e43a7..923509b3 100644 --- a/ios/net/crn_http_protocol_handler.mm +++ b/ios/net/crn_http_protocol_handler.mm
@@ -615,8 +615,8 @@ read_buffer_size_ = std::max(read_buffer_size_ / 2, kIOBufferMinSize); } read_buffer_.reset(static_cast<char*>(malloc(read_buffer_size_))); - read_buffer_wrapper_ = - new WrappedIOBuffer(static_cast<const char*>(read_buffer_.get())); + read_buffer_wrapper_ = base::MakeRefCounted<WrappedIOBuffer>( + static_cast<const char*>(read_buffer_.get())); } HttpProtocolHandlerCore::~HttpProtocolHandlerCore() {
diff --git a/ios/third_party/material_components_ios/README.chromium b/ios/third_party/material_components_ios/README.chromium index c779d60..780c15b 100644 --- a/ios/third_party/material_components_ios/README.chromium +++ b/ios/third_party/material_components_ios/README.chromium
@@ -1,7 +1,7 @@ Name: Material Components for iOS URL: https://github.com/material-components/material-components-ios Version: 0 -Revision: 3c3b852f96c0e2351fa4d8512e175b35f92e757a +Revision: e58ee91454ff891892f2ac239a3e9875063da454 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/ios/web_view/public/cwv_autofill_controller_delegate.h b/ios/web_view/public/cwv_autofill_controller_delegate.h index 0e75946..a02059b 100644 --- a/ios/web_view/public/cwv_autofill_controller_delegate.h +++ b/ios/web_view/public/cwv_autofill_controller_delegate.h
@@ -7,8 +7,6 @@ #import <Foundation/Foundation.h> -#import "cwv_export.h" - NS_ASSUME_NONNULL_BEGIN @class CWVAutofillController; @@ -22,7 +20,6 @@ CWVStoragePolicyAllow, // Allow storage. }; -CWV_EXPORT // Protocol to receive callbacks related to autofill. // |fieldName| is the 'name' attribute of a html field. // |formName| is the 'name' attribute of a html <form>.
diff --git a/ios/web_view/public/cwv_autofill_data_manager_delegate.h b/ios/web_view/public/cwv_autofill_data_manager_delegate.h index 3507e467..1b5c178 100644 --- a/ios/web_view/public/cwv_autofill_data_manager_delegate.h +++ b/ios/web_view/public/cwv_autofill_data_manager_delegate.h
@@ -7,13 +7,10 @@ #import <Foundation/Foundation.h> -#import "cwv_export.h" - NS_ASSUME_NONNULL_BEGIN @class CWVAutofillDataManager; -CWV_EXPORT // Protocol to receive change notifications from CWVAutofillDataManager. @protocol CWVAutofillDataManagerDelegate<NSObject>
diff --git a/ios/web_view/public/cwv_navigation_delegate.h b/ios/web_view/public/cwv_navigation_delegate.h index 2dc65dc2..d8385a836 100644 --- a/ios/web_view/public/cwv_navigation_delegate.h +++ b/ios/web_view/public/cwv_navigation_delegate.h
@@ -7,7 +7,6 @@ #import <Foundation/Foundation.h> -#import "cwv_export.h" #import "cwv_navigation_type.h" @protocol CRIWVTranslateDelegate; @@ -15,7 +14,6 @@ // Navigation delegate protocol for CWVWebViews. Allows embedders to hook // page loading and receive events for navigation. -CWV_EXPORT @protocol CWVNavigationDelegate<NSObject> @optional
diff --git a/ios/web_view/public/cwv_script_command.h b/ios/web_view/public/cwv_script_command.h index 1080e8b..86404563 100644 --- a/ios/web_view/public/cwv_script_command.h +++ b/ios/web_view/public/cwv_script_command.h
@@ -33,7 +33,6 @@ // Provides a method for receiving commands from JavaScript running in a web // page. -CWV_EXPORT @protocol CWVScriptCommandHandler<NSObject> - (BOOL)webView:(CWVWebView*)webView
diff --git a/ios/web_view/public/cwv_scroll_view_delegate.h b/ios/web_view/public/cwv_scroll_view_delegate.h index 0001d26..794333a6 100644 --- a/ios/web_view/public/cwv_scroll_view_delegate.h +++ b/ios/web_view/public/cwv_scroll_view_delegate.h
@@ -7,8 +7,6 @@ #import <CoreGraphics/CoreGraphics.h> -#import "cwv_export.h" - NS_ASSUME_NONNULL_BEGIN @class CWVScrollView; @@ -18,7 +16,6 @@ // These methods are forwarded from the internal UIScrollViewDelegate. Please // see the <UIKit/UIScrollViewDelegate.h> documentation for details about the // following methods. -CWV_EXPORT @protocol CWVScrollViewDelegate<NSObject> @optional - (void)scrollViewWillBeginDragging:(CWVScrollView*)scrollView;
diff --git a/ios/web_view/public/cwv_translation_controller_delegate.h b/ios/web_view/public/cwv_translation_controller_delegate.h index 01b83c5..99f2729 100644 --- a/ios/web_view/public/cwv_translation_controller_delegate.h +++ b/ios/web_view/public/cwv_translation_controller_delegate.h
@@ -4,8 +4,6 @@ #import <Foundation/Foundation.h> -#import "cwv_export.h" - #ifndef IOS_WEB_VIEW_PUBLIC_CWV_TRANSLATION_CONTROLLER_DELEGATE_H #define IOS_WEB_VIEW_PUBLIC_CWV_TRANSLATION_CONTROLLER_DELEGATE_H @@ -15,7 +13,6 @@ @class CWVTranslationLanguage; // Updates delegate on translation progress. -CWV_EXPORT @protocol CWVTranslationControllerDelegate<NSObject> @optional
diff --git a/jingle/glue/chrome_async_socket.cc b/jingle/glue/chrome_async_socket.cc index c1b4773..ebe8aec8 100644 --- a/jingle/glue/chrome_async_socket.cc +++ b/jingle/glue/chrome_async_socket.cc
@@ -38,11 +38,11 @@ error_(ERROR_NONE), net_error_(net::OK), read_state_(IDLE), - read_buf_(new net::IOBufferWithSize(read_buf_size)), + read_buf_(base::MakeRefCounted<net::IOBufferWithSize>(read_buf_size)), read_start_(0U), read_end_(0U), write_state_(IDLE), - write_buf_(new net::IOBufferWithSize(write_buf_size)), + write_buf_(base::MakeRefCounted<net::IOBufferWithSize>(write_buf_size)), write_end_(0U), traffic_annotation_(traffic_annotation), weak_ptr_factory_(this) {
diff --git a/jingle/glue/fake_ssl_client_socket_unittest.cc b/jingle/glue/fake_ssl_client_socket_unittest.cc index f02344279..706512d5 100644 --- a/jingle/glue/fake_ssl_client_socket_unittest.cc +++ b/jingle/glue/fake_ssl_client_socket_unittest.cc
@@ -193,14 +193,13 @@ if (fake_ssl_client_socket.IsConnected()) { int read_len = arraysize(kReadTestData); int read_buf_len = 2 * read_len; - scoped_refptr<net::IOBuffer> read_buf( - new net::IOBuffer(read_buf_len)); + auto read_buf = base::MakeRefCounted<net::IOBuffer>(read_buf_len); int read_status = fake_ssl_client_socket.Read( read_buf.get(), read_buf_len, test_completion_callback.callback()); ExpectStatus(mode, read_len, read_status, &test_completion_callback); - scoped_refptr<net::IOBuffer> write_buf( - new net::StringIOBuffer(kWriteTestData)); + auto write_buf = + base::MakeRefCounted<net::StringIOBuffer>(kWriteTestData); int write_status = fake_ssl_client_socket.Write( write_buf.get(), arraysize(kWriteTestData), test_completion_callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS);
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 7f46170..4d7ffadc 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -429,6 +429,10 @@ const base::Feature kRecordMediaEngagementScores{ "RecordMediaEngagementScores", base::FEATURE_ENABLED_BY_DEFAULT}; +// Enables Media Engagement Index recording for Web Audio playbacks. +const base::Feature kRecordWebAudioEngagement{"RecordWebAudioEngagement", + base::FEATURE_ENABLED_BY_DEFAULT}; + // The following Media Engagement flags are not enabled on mobile platforms: // - MediaEngagementBypassAutoplayPolicies: enables the Media Engagement Index // data to be esude to override autoplay policies. An origin with a high MEI
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 854d1ddc..3c9e8f06 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -109,6 +109,7 @@ MEDIA_EXPORT extern const base::Feature kLowDelayVideoRenderingOnLiveStream; MEDIA_EXPORT extern const base::Feature kMediaCastOverlayButton; MEDIA_EXPORT extern const base::Feature kRecordMediaEngagementScores; +MEDIA_EXPORT extern const base::Feature kRecordWebAudioEngagement; MEDIA_EXPORT extern const base::Feature kMediaEngagementBypassAutoplayPolicies; MEDIA_EXPORT extern const base::Feature kMemoryPressureBasedSourceBufferGC; MEDIA_EXPORT extern const base::Feature kMojoVideoDecoder;
diff --git a/media/cast/net/udp_transport_impl.cc b/media/cast/net/udp_transport_impl.cc index 9c95376e..8175004 100644 --- a/media/cast/net/udp_transport_impl.cc +++ b/media/cast/net/udp_transport_impl.cc
@@ -177,7 +177,7 @@ while (true) { if (length_or_status == net::ERR_IO_PENDING) { next_packet_.reset(new Packet(media::cast::kMaxIpPacketSize)); - recv_buf_ = new net::WrappedIOBuffer( + recv_buf_ = base::MakeRefCounted<net::WrappedIOBuffer>( reinterpret_cast<char*>(&next_packet_->front())); length_or_status = udp_socket_->RecvFrom( recv_buf_.get(), media::cast::kMaxIpPacketSize, &recv_addr_, @@ -250,8 +250,8 @@ } } - scoped_refptr<net::IOBuffer> buf = - new net::WrappedIOBuffer(reinterpret_cast<char*>(&packet->data.front())); + auto buf = base::MakeRefCounted<net::WrappedIOBuffer>( + reinterpret_cast<char*>(&packet->data.front())); int result; base::RepeatingCallback<void(int)> callback = base::BindRepeating(
diff --git a/media/cast/test/utility/udp_proxy.cc b/media/cast/test/utility/udp_proxy.cc index 47c3dbfb..12bbf07 100644 --- a/media/cast/test/utility/udp_proxy.cc +++ b/media/cast/test/utility/udp_proxy.cc
@@ -730,8 +730,8 @@ VLOG(1) << "Sending packet, len = " << packet->size(); // We ignore all problems, callbacks and errors. // If it didn't work we just drop the packet at and call it a day. - scoped_refptr<net::IOBuffer> buf = - new net::WrappedIOBuffer(reinterpret_cast<char*>(&packet->front())); + auto buf = base::MakeRefCounted<net::WrappedIOBuffer>( + reinterpret_cast<char*>(&packet->front())); size_t buf_size = packet->size(); int result; if (destination.address().empty()) { @@ -814,8 +814,8 @@ void PollRead() { while (true) { packet_.reset(new Packet(kMaxPacketSize)); - scoped_refptr<net::IOBuffer> recv_buf = - new net::WrappedIOBuffer(reinterpret_cast<char*>(&packet_->front())); + auto recv_buf = base::MakeRefCounted<net::WrappedIOBuffer>( + reinterpret_cast<char*>(&packet_->front())); int len = socket_->RecvFrom( recv_buf.get(), kMaxPacketSize,
diff --git a/media/filters/decoder_selector.cc b/media/filters/decoder_selector.cc index f15fbdf..9463749 100644 --- a/media/filters/decoder_selector.cc +++ b/media/filters/decoder_selector.cc
@@ -10,6 +10,7 @@ #include "base/callback_helpers.h" #include "base/location.h" #include "base/logging.h" +#include "base/metrics/histogram_functions.h" #include "base/single_thread_task_runner.h" #include "build/build_config.h" #include "media/base/audio_decoder.h" @@ -90,11 +91,45 @@ is_selecting_decoders_ = false; + if (is_codec_changing_) { + is_codec_changing_ = false; + + std::string stream_type; + switch (StreamType) { + case DemuxerStream::AUDIO: + stream_type = "Audio"; + break; + case DemuxerStream::VIDEO: + stream_type = "Video"; + break; + default: + NOTREACHED(); + } + + std::string decoder_type = is_platform_decoder_ ? "HW" : "SW"; + + base::UmaHistogramTimes( + "Media.MSE.CodecChangeTime." + stream_type + "." + decoder_type, + base::TimeTicks::Now() - codec_change_start_); + } + // Discard any remaining decoder instances, they won't be used. decoders_.clear(); } template <DemuxerStream::Type StreamType> +void DecoderSelector<StreamType>::NotifyConfigChanged() { + DVLOG(2) << __func__; + DCHECK(task_runner_->BelongsToCurrentThread()); + + DecoderConfig config = traits_->GetDecoderConfig(stream_); + if (config.codec() != config_.codec()) { + is_codec_changing_ = true; + codec_change_start_ = base::TimeTicks::Now(); + } +} + +template <DemuxerStream::Type StreamType> void DecoderSelector<StreamType>::InitializeDecoder() { DVLOG(2) << __func__; DCHECK(task_runner_->BelongsToCurrentThread()); @@ -115,6 +150,7 @@ // Initialize the first decoder on the list. decoder_ = std::move(decoders_.front()); decoders_.erase(decoders_.begin()); + is_platform_decoder_ = decoder_->IsPlatformDecoder(); DVLOG(2) << __func__ << ": initializing " << decoder_->GetDisplayName(); const bool is_live = stream_->liveness() == DemuxerStream::LIVENESS_LIVE;
diff --git a/media/filters/decoder_selector.h b/media/filters/decoder_selector.h index 75d62d5..458d380 100644 --- a/media/filters/decoder_selector.h +++ b/media/filters/decoder_selector.h
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "media/base/demuxer_stream.h" #include "media/base/pipeline_status.h" #include "media/filters/decoder_stream_traits.h" @@ -85,6 +86,10 @@ // calls to SelectDecoder() will select from the full list of decoders. void FinalizeDecoderSelection(); + // Signals that a config change has started being processed. + // Currently only for metric collection. + void NotifyConfigChanged(); + private: void InitializeDecoder(); void OnDecoderInitializeDone(bool success); @@ -112,6 +117,11 @@ std::unique_ptr<Decoder> decoder_; std::unique_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream_; + // Metrics. + bool is_platform_decoder_ = false; + bool is_codec_changing_ = false; + base::TimeTicks codec_change_start_; + base::WeakPtrFactory<DecoderSelector> weak_this_factory_; DISALLOW_IMPLICIT_CONSTRUCTORS(DecoderSelector);
diff --git a/media/filters/decoder_stream.cc b/media/filters/decoder_stream.cc index 75a672d..df32d6d 100644 --- a/media/filters/decoder_stream.cc +++ b/media/filters/decoder_stream.cc
@@ -689,6 +689,7 @@ << " decoder config changed midstream, new config: " << config.AsHumanReadableString(); + decoder_selector_.NotifyConfigChanged(); if (config_change_observer_cb_) config_change_observer_cb_.Run(config);
diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc index ac470a6..3ebb6454d 100644 --- a/media/formats/mp4/mp4_stream_parser.cc +++ b/media/formats/mp4/mp4_stream_parser.cc
@@ -799,6 +799,10 @@ subsamples = decrypt_config->subsamples(); } + // This may change if analysis results indicate runs_->is_keyframe() is + // opposite of what the coded frame contains. + bool is_keyframe = runs_->is_keyframe(); + std::vector<uint8_t> frame_buf(buf, buf + sample_size); if (video) { if (runs_->video_description().video_codec == kCodecH264 || @@ -806,7 +810,7 @@ runs_->video_description().video_codec == kCodecDolbyVision) { DCHECK(runs_->video_description().frame_bitstream_converter); if (!runs_->video_description().frame_bitstream_converter->ConvertFrame( - &frame_buf, runs_->is_keyframe(), &subsamples)) { + &frame_buf, is_keyframe, &subsamples)) { MEDIA_LOG(ERROR, media_log_) << "Failed to prepare video sample for decode"; return ParseResult::kError; @@ -827,14 +831,25 @@ // if the analysis mismatches the container's keyframe metadata for // |frame_buf|. if (analysis.is_keyframe.has_value() && - runs_->is_keyframe() != analysis.is_keyframe.value()) { + is_keyframe != analysis.is_keyframe.value()) { LIMITED_MEDIA_LOG(DEBUG, media_log_, num_video_keyframe_mismatches_, kMaxVideoKeyframeMismatchLogs) << "ISO-BMFF container metadata for video frame indicates that the " "frame is " - << (runs_->is_keyframe() ? "" : "not ") + << (is_keyframe ? "" : "not ") << "a keyframe, but the video frame contents indicate the " "opposite."; + // As of September 2018, it appears that all of Edge, Firefox, Safari + // work with content that marks non-avc-keyframes as a keyframe in the + // container. Encoders/muxers/old streams still exist that produce + // all-keyframe mp4 video tracks, though many of the coded frames are + // not keyframes (likely workaround due to the impact on low-latency + // live streams until https://crbug.com/229412 was fixed). We'll trust + // the AVC frame's keyframe-ness over the mp4 container's metadata if + // they mismatch. If other out-of-order codecs in mp4 (e.g. HEVC, DV) + // implement keyframe analysis in their frame_bitstream_converter, we'll + // similarly trust that analysis instead of the mp4. + is_keyframe = analysis.is_keyframe.value(); } } } @@ -868,9 +883,9 @@ StreamParserBuffer::Type buffer_type = audio ? DemuxerStream::AUDIO : DemuxerStream::VIDEO; - scoped_refptr<StreamParserBuffer> stream_buf = StreamParserBuffer::CopyFrom( - &frame_buf[0], frame_buf.size(), runs_->is_keyframe(), buffer_type, - runs_->track_id()); + scoped_refptr<StreamParserBuffer> stream_buf = + StreamParserBuffer::CopyFrom(&frame_buf[0], frame_buf.size(), is_keyframe, + buffer_type, runs_->track_id()); if (decrypt_config) stream_buf->set_decrypt_config(std::move(decrypt_config)); @@ -898,8 +913,7 @@ } DVLOG(3) << "Emit " << (audio ? "audio" : "video") << " frame: " - << " track_id=" << runs_->track_id() - << ", key=" << runs_->is_keyframe() + << " track_id=" << runs_->track_id() << ", key=" << is_keyframe << ", dur=" << runs_->duration().InMilliseconds() << ", dts=" << runs_->dts().InMilliseconds() << ", cts=" << runs_->cts().InMilliseconds()
diff --git a/media/formats/mp4/mp4_stream_parser_unittest.cc b/media/formats/mp4/mp4_stream_parser_unittest.cc index ccb0800..58c1cdb2 100644 --- a/media/formats/mp4/mp4_stream_parser_unittest.cc +++ b/media/formats/mp4/mp4_stream_parser_unittest.cc
@@ -62,7 +62,8 @@ MP4StreamParserTest() : configs_received_(false), lower_bound_( - DecodeTimestamp::FromPresentationTime(base::TimeDelta::Max())) { + DecodeTimestamp::FromPresentationTime(base::TimeDelta::Max())), + verifying_keyframeness_sequence_(false) { std::set<int> audio_object_types; audio_object_types.insert(kISO_14496_3); parser_.reset(new MP4StreamParser(audio_object_types, false, false)); @@ -78,6 +79,7 @@ DecodeTimestamp lower_bound_; StreamParser::TrackId audio_track_id_; StreamParser::TrackId video_track_id_; + bool verifying_keyframeness_sequence_; bool AppendData(const uint8_t* data, size_t length) { return parser_->Parse(data, length); @@ -139,6 +141,11 @@ return true; } + // Useful in single-track test media cases that need to verify + // keyframe/non-keyframe sequence in output of parse. + MOCK_METHOD0(ParsedKeyframe, void()); + MOCK_METHOD0(ParsedNonKeyframe, void()); + bool NewBuffersF(const StreamParser::BufferQueueMap& buffer_queue_map) { DecodeTimestamp lowest_end_dts = kNoDecodeTimestamp(); for (const auto& it : buffer_queue_map) { @@ -157,6 +164,14 @@ << ", dur=" << buf->duration().InSecondsF(); // Ensure that track ids are properly assigned on all emitted buffers. EXPECT_EQ(it.first, buf->track_id()); + + // Let single-track tests verify the sequence of keyframes/nonkeyframes. + if (verifying_keyframeness_sequence_) { + if (buf->is_key_frame()) + ParsedKeyframe(); + else + ParsedNonKeyframe(); + } } } @@ -298,9 +313,13 @@ // Frame 1: AVC Non-IDR, tfhd.default_sample_flags: not sync sample, depends // on others. // This is the base case; see also the "Mismatches" cases, below. + InSequence s; // The EXPECT* sequence matters for this test. auto params = GetDefaultInitParametersExpectations(); params.detected_audio_track_count = 0; InitializeParserWithInitParametersExpectations(params); + verifying_keyframeness_sequence_ = true; + EXPECT_CALL(*this, ParsedKeyframe()); + EXPECT_CALL(*this, ParsedNonKeyframe()); ParseMP4File("bear-640x360-v-2frames_frag.mp4", 512); } @@ -310,12 +329,16 @@ // others. // Frame 1: AVC Non-IDR, tfhd.default_sample_flags: not sync sample, depends // on others. + InSequence s; // The EXPECT* sequence matters for this test. auto params = GetDefaultInitParametersExpectations(); params.detected_audio_track_count = 0; InitializeParserWithInitParametersExpectations(params); + verifying_keyframeness_sequence_ = true; EXPECT_MEDIA_LOG(DebugLog( "ISO-BMFF container metadata for video frame indicates that the frame is " "not a keyframe, but the video frame contents indicate the opposite.")); + EXPECT_CALL(*this, ParsedKeyframe()); + EXPECT_CALL(*this, ParsedNonKeyframe()); ParseMP4File("bear-640x360-v-2frames-keyframe-is-non-sync-sample_frag.mp4", 512); } @@ -326,12 +349,16 @@ // depend on others. // Frame 1: AVC Non-IDR, tfhd.default_sample_flags: SYNC sample, DOES NOT // depend on others. + InSequence s; // The EXPECT* sequence matters for this test. auto params = GetDefaultInitParametersExpectations(); params.detected_audio_track_count = 0; InitializeParserWithInitParametersExpectations(params); + verifying_keyframeness_sequence_ = true; + EXPECT_CALL(*this, ParsedKeyframe()); EXPECT_MEDIA_LOG(DebugLog( "ISO-BMFF container metadata for video frame indicates that the frame is " "a keyframe, but the video frame contents indicate the opposite.")); + EXPECT_CALL(*this, ParsedNonKeyframe()); ParseMP4File("bear-640x360-v-2frames-nonkeyframe-is-sync-sample_frag.mp4", 512); }
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index 399117da..949f67e 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -531,7 +531,7 @@ } } -if (use_v4l2_codec || use_vaapi) { +if (is_chromeos || is_linux) { test("jpeg_decode_accelerator_unittest") { deps = [ "//base",
diff --git a/media/gpu/jpeg_decode_accelerator_unittest.cc b/media/gpu/jpeg_decode_accelerator_unittest.cc index fe691796..280bfc86 100644 --- a/media/gpu/jpeg_decode_accelerator_unittest.cc +++ b/media/gpu/jpeg_decode_accelerator_unittest.cc
@@ -25,6 +25,7 @@ #include "base/strings/stringprintf.h" #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/timer/elapsed_timer.h" #include "build/build_config.h" #include "media/base/test_data_util.h" #include "media/filters/jpeg_parser.h" @@ -228,7 +229,7 @@ auto jda_factories = GpuJpegDecodeAcceleratorFactory::GetAcceleratorFactories(); - if (jda_factories.size() == 0) { + if (jda_factories.empty()) { LOG(ERROR) << "JpegDecodeAccelerator not supported on this platform."; SetState(CS_ERROR); return; @@ -328,7 +329,7 @@ VideoPixelFormat::PIXEL_FORMAT_ARGB, image_file->visible_size, gfx::Rect(image_file->visible_size), image_file->visible_size, base::TimeDelta()); - LOG_ASSERT(argb_out_frame.get()); + LOG_ASSERT(argb_out_frame); LOG_ASSERT(in_frame->visible_rect() == argb_out_frame->visible_rect()); // Note that we use J420ToARGB instead of I420ToARGB so that the @@ -380,9 +381,8 @@ LOG_ASSERT(hw_out_frame_->stride(plane) == sw_out_frame_->stride(plane)); const int stride = hw_out_frame_->stride(plane); for (size_t row = 0; row < rows; ++row) { - for (size_t col = 0; col < columns; ++col) { + for (size_t col = 0; col < columns; ++col) mean_abs_difference += std::abs(hw_data[col] - sw_data[col]); - } hw_data += stride; sw_data += stride; } @@ -398,9 +398,8 @@ DCHECK_LT(static_cast<size_t>(bitstream_buffer_id), test_image_files_.size()); ParsedJpegImage* image_file = test_image_files_[bitstream_buffer_id]; - if (do_prepare_memory) { + if (do_prepare_memory) PrepareMemory(bitstream_buffer_id); - } base::SharedMemoryHandle dup_handle; dup_handle = base::SharedMemory::DuplicateHandle(in_shm_->handle()); @@ -615,6 +614,7 @@ const int32_t bitstream_buffer_id = 0; scoped_client->client()->PrepareMemory(bitstream_buffer_id); + const base::ElapsedTimer timer; for (int index = 0; index < decode_times; index++) { decoder_thread.task_runner()->PostTask( FROM_HERE, base::BindOnce(&JpegClient::StartDecode, @@ -622,6 +622,12 @@ bitstream_buffer_id, false)); ASSERT_EQ(scoped_client->client()->note()->Wait(), CS_DECODE_PASS); } + const base::TimeDelta elapsed_time = timer.Elapsed(); + LOG(INFO) << elapsed_time << " for " << decode_times + << " iterations (avg: " << elapsed_time / decode_times << ") -- " + << test_image_files_[0]->visible_size.ToString() << ", (" + << test_image_files_[0]->visible_size.GetArea() << " pixels) " + << test_image_files_[0]->filename(); } void JpegDecodeAcceleratorTest::PerfDecodeBySW(int decode_times) { @@ -634,12 +640,18 @@ const int32_t bitstream_buffer_id = 0; client->PrepareMemory(bitstream_buffer_id); - for (int index = 0; index < decode_times; index++) { + const base::ElapsedTimer timer; + for (int index = 0; index < decode_times; index++) client->GetSoftwareDecodeResult(bitstream_buffer_id); - } + const base::TimeDelta elapsed_time = timer.Elapsed(); + LOG(INFO) << elapsed_time << " for " << decode_times + << " iterations (avg: " << elapsed_time / decode_times << ") -- " + << test_image_files_[0]->visible_size.ToString() << ", (" + << test_image_files_[0]->visible_size.GetArea() << " pixels) " + << test_image_files_[0]->filename(); } -// Return a VideoFrame that contains YUV data using 4:2:0 subsampling. The +// Returns a VideoFrame that contains YUV data using 4:2:0 subsampling. The // visible size is 3x3, and the coded size is 4x4 which is 3x3 rounded up to the // next even dimensions. scoped_refptr<VideoFrame> GetTestDecodedData() { @@ -694,12 +706,16 @@ v_data[v_stride + 1] = 0x54; // Previously 0x11. expected_abs_mean_diff += 0x54 - 0x11; expected_abs_mean_diff /= 3 * 3 + 2 * 2 * 2; - EXPECT_NEAR(expected_abs_mean_diff, client.GetMeanAbsoluteDifference(), 1e-7); + + constexpr double kMaxAllowedDifference = 1e-7; + EXPECT_NEAR(expected_abs_mean_diff, client.GetMeanAbsoluteDifference(), + kMaxAllowedDifference); // Change some non-visible data in the software decoding result, i.e., part of // the stride padding. This should not affect the absolute mean difference. y_data[3] = 0xAB; - EXPECT_NEAR(expected_abs_mean_diff, client.GetMeanAbsoluteDifference(), 1e-7); + EXPECT_NEAR(expected_abs_mean_diff, client.GetMeanAbsoluteDifference(), + kMaxAllowedDifference); } TEST_F(JpegDecodeAcceleratorTest, SimpleDecode) { @@ -779,17 +795,15 @@ TEST_F(JpegDecodeAcceleratorTest, PerfJDA) { // Only the first image will be used for perf testing. - for (auto& image : g_env->image_data_user_) { + for (auto& image : g_env->image_data_user_) test_image_files_.push_back(image.get()); - } PerfDecodeByJDA(g_env->perf_decode_times_); } TEST_F(JpegDecodeAcceleratorTest, PerfSW) { // Only the first image will be used for perf testing. - for (auto& image : g_env->image_data_user_) { + for (auto& image : g_env->image_data_user_) test_image_files_.push_back(image.get()); - } PerfDecodeBySW(g_env->perf_decode_times_); }
diff --git a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc index 2d41181..3d90254f 100644 --- a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc +++ b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc
@@ -26,6 +26,7 @@ #include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" #include "media/base/bind_to_current_loop.h" #include "media/base/media_switches.h" #include "media/base/unaligned_shared_memory.h" @@ -181,7 +182,6 @@ at_client(false), picture_id(-1), texture_id(0), - egl_sync(EGL_NO_SYNC_KHR), cleared(false) {} V4L2SliceVideoDecodeAccelerator::OutputRecord::OutputRecord(OutputRecord&&) = @@ -229,26 +229,6 @@ } } -struct V4L2SliceVideoDecodeAccelerator::EGLSyncKHRRef { - EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); - ~EGLSyncKHRRef(); - EGLDisplay const egl_display; - EGLSyncKHR egl_sync; -}; - -V4L2SliceVideoDecodeAccelerator::EGLSyncKHRRef::EGLSyncKHRRef( - EGLDisplay egl_display, - EGLSyncKHR egl_sync) - : egl_display(egl_display), egl_sync(egl_sync) {} - -V4L2SliceVideoDecodeAccelerator::EGLSyncKHRRef::~EGLSyncKHRRef() { - // We don't check for eglDestroySyncKHR failures, because if we get here - // with a valid sync object, something went wrong and we are getting - // destroyed anyway. - if (egl_sync != EGL_NO_SYNC_KHR) - eglDestroySyncKHR(egl_display, egl_sync); -} - V4L2SliceVideoDecodeAccelerator::PictureRecord::PictureRecord( bool cleared, const Picture& picture) @@ -1167,23 +1147,22 @@ DCHECK(!output_record.at_client); DCHECK_NE(output_record.picture_id, -1); - if (output_record.egl_sync != EGL_NO_SYNC_KHR) { + if (output_record.egl_fence) { // If we have to wait for completion, wait. Note that free_output_buffers_ // is a FIFO queue, so we always wait on the buffer that has been in the // queue the longest. Every 100ms we check whether the decoder is shutting - // down, or we might get stuck waiting on a sync that will never come: + // down, or we might get stuck waiting on a fence that will never come: // https://crbug.com/845645 while (!IsDestroyPending()) { - constexpr EGLTimeKHR wait_ns = - 100 * base::Time::kNanosecondsPerMicrosecond * - base::Time::kMicrosecondsPerMillisecond; // 100ms - EGLint result = eglClientWaitSyncKHR(egl_display_, output_record.egl_sync, - 0, wait_ns); + const EGLTimeKHR wait_ns = + base::TimeDelta::FromMilliseconds(100).InNanoseconds(); + EGLint result = + output_record.egl_fence->ClientWaitWithTimeoutNanos(wait_ns); if (result == EGL_CONDITION_SATISFIED_KHR) { break; } else if (result == EGL_FALSE) { // This will cause tearing, but is safe otherwise. - DVLOGF(1) << "eglClientWaitSyncKHR failed!"; + DVLOGF(1) << "GLFenceEGL::ClientWaitWithTimeoutNanos failed!"; break; } DCHECK_EQ(result, EGL_TIMEOUT_EXPIRED_KHR); @@ -1192,12 +1171,7 @@ if (IsDestroyPending()) return false; - if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) { - VLOGF(1) << "eglDestroySyncKHR failed!"; - NOTIFY_ERROR(PLATFORM_FAILURE); - return false; - } - output_record.egl_sync = EGL_NO_SYNC_KHR; + output_record.egl_fence.reset(); } struct v4l2_buffer qbuf; @@ -1530,10 +1504,7 @@ for (auto& output_record : output_buffer_map_) { DCHECK(!output_record.at_device); - if (output_record.egl_sync != EGL_NO_SYNC_KHR) { - if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) - VLOGF(1) << "eglDestroySyncKHR failed."; - } + output_record.egl_fence.reset(); picture_buffers_to_dismiss.push_back(output_record.picture_id); } @@ -1649,7 +1620,7 @@ OutputRecord& output_record = output_buffer_map_[i]; DCHECK(!output_record.at_device); DCHECK(!output_record.at_client); - DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); + DCHECK(!output_record.egl_fence); DCHECK_EQ(output_record.picture_id, -1); DCHECK(output_record.dmabuf_fds.empty()); DCHECK_EQ(output_record.cleared, false); @@ -1761,7 +1732,7 @@ } OutputRecord& output_record = output_buffer_map_[buffer_index]; - DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); + DCHECK(!output_record.egl_fence); DCHECK(!output_record.at_client); DCHECK(!output_record.at_device); @@ -1871,7 +1842,7 @@ DCHECK(child_task_runner_->BelongsToCurrentThread()); DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id; - std::unique_ptr<EGLSyncKHRRef> egl_sync_ref; + std::unique_ptr<gl::GLFenceEGL> egl_fence; if (!make_context_current_cb_.is_null()) { if (!make_context_current_cb_.Run()) { @@ -1880,27 +1851,24 @@ return; } - EGLSyncKHR egl_sync = - eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); - if (egl_sync == EGL_NO_SYNC_KHR) { - VLOGF(1) << "eglCreateSyncKHR() failed"; + egl_fence = gl::GLFenceEGL::Create(); + if (!egl_fence) { + VLOGF(1) << "gl::GLFenceEGL::Create() failed"; NOTIFY_ERROR(PLATFORM_FAILURE); return; } - - egl_sync_ref.reset(new EGLSyncKHRRef(egl_display_, egl_sync)); } decoder_thread_task_runner_->PostTask( FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ReusePictureBufferTask, base::Unretained(this), picture_buffer_id, - base::Passed(&egl_sync_ref))); + base::Passed(&egl_fence))); } void V4L2SliceVideoDecodeAccelerator::ReusePictureBufferTask( int32_t picture_buffer_id, - std::unique_ptr<EGLSyncKHRRef> egl_sync_ref) { + std::unique_ptr<gl::GLFenceEGL> egl_fence) { DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id; DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); @@ -1913,7 +1881,7 @@ // It's possible that we've already posted a DismissPictureBuffer for this // picture, but it has not yet executed when this ReusePictureBuffer was // posted to us by the client. In that case just ignore this (we've already - // dismissed it and accounted for that) and let the sync object get + // dismissed it and accounted for that) and let the fence object get // destroyed. DVLOGF(3) << "got picture id=" << picture_buffer_id << " not in use (anymore?)."; @@ -1927,14 +1895,11 @@ return; } - DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); + DCHECK(!output_record.egl_fence); DCHECK(!output_record.at_device); output_record.at_client = false; - if (egl_sync_ref) { - output_record.egl_sync = egl_sync_ref->egl_sync; - // Take ownership of the EGLSync. - egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; - } + // Take ownership of the EGL fence. + output_record.egl_fence = std::move(egl_fence); surfaces_at_display_.erase(it); }
diff --git a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h index 9a39dee..0c0893b 100644 --- a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h +++ b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h
@@ -27,7 +27,7 @@ #include "media/gpu/vp8_decoder.h" #include "media/gpu/vp9_decoder.h" #include "media/video/video_decode_accelerator.h" -#include "ui/gl/gl_image.h" +#include "ui/gl/gl_fence_egl.h" namespace media { @@ -92,7 +92,7 @@ int32_t picture_id; GLuint client_texture_id; GLuint texture_id; - EGLSyncKHR egl_sync; + std::unique_ptr<gl::GLFenceEGL> egl_fence; std::vector<base::ScopedFD> dmabuf_fds; bool cleared; }; @@ -337,10 +337,11 @@ // Return false if no buffers are pending on decoder_input_queue_. bool TrySetNewBistreamBuffer(); - // Auto-destruction reference for EGLSync (for message-passing). - struct EGLSyncKHRRef; + // Task to flag the specified picture buffer for reuse, executed on the + // decoder_thread_. The picture buffer can only be reused after the specified + // fence has been signaled. void ReusePictureBufferTask(int32_t picture_buffer_id, - std::unique_ptr<EGLSyncKHRRef> egl_sync_ref); + std::unique_ptr<gl::GLFenceEGL> egl_fence); // Called to actually send |dec_surface| to the client - as a result of // decoding the stream in |bitstream_id| - after it is decoded preserving
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc index 1a54a3e3..39420e3 100644 --- a/media/gpu/vaapi/vaapi_wrapper.cc +++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -23,6 +23,7 @@ #include "base/numerics/safe_conversions.h" #include "base/stl_util.h" #include "base/sys_info.h" +#include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "media/base/media_switches.h" @@ -1138,6 +1139,7 @@ const gfx::Size& size, VAImage* image, void** mem) { + TRACE_EVENT0("media,gpu", "VaapiWrapper::GetVaImage"); base::AutoLock auto_lock(*va_lock_); VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); @@ -1525,6 +1527,7 @@ } bool VaapiWrapper::Execute(VASurfaceID va_surface_id) { + TRACE_EVENT0("media,gpu", "VaapiWrapper::Execute"); base::AutoLock auto_lock(*va_lock_); DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size();
diff --git a/services/ws/focus_handler.cc b/services/ws/focus_handler.cc index cdebcb4..c7a2eda6 100644 --- a/services/ws/focus_handler.cc +++ b/services/ws/focus_handler.cc
@@ -12,6 +12,7 @@ #include "services/ws/window_service_delegate.h" #include "services/ws/window_tree.h" #include "ui/aura/client/focus_client.h" +#include "ui/wm/public/activation_client.h" namespace ws { @@ -72,9 +73,31 @@ ClientChange change(window_tree_->property_change_tracker_.get(), window, ClientChangeType::kFocus); + + // FocusController has a special API to reset focus inside the active window, + // which happens when a view requests focus (e.g. the find bar). + // https://crbug.com/880533 + wm::ActivationClient* activation_client = + wm::GetActivationClient(window->GetRootWindow()); + if (activation_client) { + aura::Window* active_window = activation_client->GetActiveWindow(); + if (active_window && active_window->Contains(window)) { + focus_client->ResetFocusWithinActiveWindow(window); + if (focus_client->GetFocusedWindow() != window) { + DVLOG(1) << "SetFocus failed (FocusClient::ResetFocusWithinActiveWindow" + << " failed for " << window->GetName() << ")"; + return false; + } + if (server_window) + server_window->set_focus_owner(window_tree_); + return true; + } + } + focus_client->FocusWindow(window); if (focus_client->GetFocusedWindow() != window) { - DVLOG(1) << "SetFocus failed (FocusClient::FocusWindow call failed)"; + DVLOG(1) << "SetFocus failed (FocusClient::FocusWindow call failed for " + << window->GetName() << ")"; return false; }
diff --git a/services/ws/focus_handler_unittest.cc b/services/ws/focus_handler_unittest.cc index c7f33260..266873a 100644 --- a/services/ws/focus_handler_unittest.cc +++ b/services/ws/focus_handler_unittest.cc
@@ -105,6 +105,22 @@ EXPECT_TRUE(setup.window_tree_test_helper()->SetFocus(window)); } +// Regression test for https://crbug.com/880533 +TEST(FocusHandlerTest, FocusChildOfActiveWindow) { + WindowServiceTestSetup setup; + aura::Window* top_level = + setup.window_tree_test_helper()->NewTopLevelWindow(); + top_level->Show(); + setup.focus_controller()->ActivateWindow(top_level); + EXPECT_EQ(top_level, setup.focus_controller()->GetActiveWindow()); + + aura::Window* child = setup.window_tree_test_helper()->NewWindow(); + top_level->AddChild(child); + child->Show(); + EXPECT_TRUE(setup.window_tree_test_helper()->SetFocus(child)); + EXPECT_TRUE(child->HasFocus()); +} + TEST(FocusHandlerTest, NotifyOnFocusChange) { WindowServiceTestSetup setup; aura::Window* top_level =
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index 7349d5c4..e0b94df 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -155,18 +155,6 @@ #define SK_SUPPORT_LEGACY_TILED_BITMAPS #endif -// The matrix image filter imperceptibly alters the following two layout tests: -// fast/css/transformed-mask.html -// fast/reflections/opacity-reflection-transform.html -// and changes the following cc_unittests: -// LayerTreeHostCommonTest.VisibleRectWithScalingClippingAndFilters -// LayerTreeHostCommonTest.VisibleRectWithClippingAndFilters -// Landing the fix in Skia behind this flag will allow those all to be updated -// together in Chrome (along with the removal of this flag). -#ifndef SK_IGNORE_MATRIX_IMAGE_FILTER_FIX -#define SK_IGNORE_MATRIX_IMAGE_FILTER_FIX -#endif - // remove after rebaselining svg layout tests #ifndef SK_SUPPORT_LEGACY_SVG_ARC_TO #define SK_SUPPORT_LEGACY_SVG_ARC_TO
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index d5148a5..609d9fd 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -13171,6 +13171,54 @@ "--browser=release", "--passthrough", "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9 --use-cmd-decoder=passthrough" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_d3d9_passthrough_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912-24.20.100.6286", + "os": "Windows-10", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 2 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9 --use-cmd-decoder=validating" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_d3d9_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912-24.20.100.6286", + "os": "Windows-10", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 2 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough" ], "isolate_name": "telemetry_gpu_integration_test",
diff --git a/testing/buildbot/filters/mac_window_server_killers.browser_tests.filter b/testing/buildbot/filters/mac_window_server_killers.browser_tests.filter index 26a84ea..1a14f113 100644 --- a/testing/buildbot/filters/mac_window_server_killers.browser_tests.filter +++ b/testing/buildbot/filters/mac_window_server_killers.browser_tests.filter
@@ -170,7 +170,6 @@ -PluginPowerSaverBrowserTest.* -PolicyTest.* -PolicyToolUITest.* --PredictorBrowserTest.* -PrefsFunctionalTest.* -PrefsTabHelperBrowserTest.* -PrerenderBrowserTest.*
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter index d875909..5ad53115 100644 --- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -96,31 +96,6 @@ # the network service. -ExtensionWebRequestApiTest.WebRequestBlockingSetCookieHeader -# https://crbug.com/809583 -# Switch Predictor from using ResourceThrottle and ResourceDispatcherHost to -# using WebContentsObserver and NavigationHandle. --PredictorBrowserTest.CrossSiteNoReferrerNoPredictionAfterOneNavigation --PredictorBrowserTest.CrossSiteRedirectNoPredictionWithPath --PredictorBrowserTest.CrossSiteRedirectPredictionWithNoPath --PredictorBrowserTest.CrossSiteRedirectPredictionWithNoPathDifferentHostName --PredictorBrowserTest.CrossSiteSimplePredictionAfterOneNavigation --PredictorBrowserTest.CrossSiteSimplePredictionAfterOneNavigationNoInterceptor --PredictorBrowserTest.CrossSiteSimplePredictionAfterTwoNavigations --PredictorBrowserTest.CrossSiteSimplePredictionAfterTwoNavigations2 --PredictorBrowserTest.CrossSiteTwoRedirectsPredictionWithNoPath --PredictorBrowserTest.CrossSiteUseOneSocket --PredictorBrowserTest.CrossSiteUseThreeSockets --PredictorBrowserTest.DoNotEvictRecentlyUsed --PredictorBrowserTest.DontPredictBasedOnSubresources --PredictorBrowserTest.ForgetBadPrediction --PredictorBrowserTest.PreconnectAndFetchCORS --PredictorBrowserTest.PreconnectAndFetchNonCORS --PredictorBrowserTest.PredictBasedOnSubframeRedirect --PredictorBrowserTest.RendererInitiatedNavigationPreconnect --PredictorBrowserTest.SubframeCrossSitePrediction --PredictorBrowserTest.SubframeInitiatesPreconnects --PredictorBrowserTest.SubframeLearning - # https://crbug.com/773295 # Remove this test when there are no more clients left that use URLFetcher. -VariationsHttpHeadersBrowserTest.TestStrippingHeadersFromInternalRequest
diff --git a/testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter b/testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter index 30424562..24ebc183 100644 --- a/testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter +++ b/testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter
@@ -19,6 +19,5 @@ # TODO(dpapad): The following tests are failing with optimize_webui=true. Fix # them and move them to the list above. --CrElementsActionMenuTest.All -CrElementsInputTest.All -MaterialBookmarksFocusTest.All
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 54540a6d..49a13a2 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1269,18 +1269,6 @@ 'linux-chromeos-dbg', # https://crbug.com/859307 ], }, - 'webgl_conformance_d3d9_passthrough_tests': { - 'remove_from': [ - # TODO(jdarpinian): Re-enable when http://crbug.com/841789 is fixed. - 'Win10 FYI Exp Release (Intel HD 630)', - ], - }, - 'webgl_conformance_d3d9_tests': { - 'remove_from': [ - # TODO(jdarpinian): Re-enable when http://crbug.com/841789 is fixed. - 'Win10 FYI Exp Release (Intel HD 630)', - ], - }, 'webgl_conformance_tests': { 'modifications': { # On desktop platforms these don't take very long (~7 minutes),
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index dd246aa..9844f8cb 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2454,6 +2454,12 @@ "enable_features": [ "ContentSuggestionsFaviconsFromNewServer" ] + }, + { + "name": "Enabled_10", + "enable_features": [ + "ContentSuggestionsFaviconsFromNewServer" + ] } ] } @@ -3858,25 +3864,6 @@ ] } ], - "ScrollAnchorSerialization": [ - { - "platforms": [ - "android", - "chromeos", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "ScrollAnchorSerialization" - ] - } - ] - } - ], "SearchEnginePromo": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index e5492a6..44aaa8d9 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -288,6 +288,16 @@ crbug.com/708345 external/wpt/css/css-tables/height-distribution/extra-height-given-to-all-row-groups-004.html [ Failure ] crbug.com/708345 external/wpt/css/css-tables/height-distribution/extra-height-given-to-all-row-groups-005.html [ Failure ] crbug.com/694374 external/wpt/css/css-tables/anonymous-table-ws-001.html [ Failure ] +crbug.com/174167 external/wpt/css/css-tables/visibility-collapse-col-001.html [ Failure ] +crbug.com/174167 external/wpt/css/css-tables/visibility-collapse-col-002.html [ Failure ] +crbug.com/174167 external/wpt/css/css-tables/visibility-collapse-col-003.html [ Failure ] +crbug.com/174167 external/wpt/css/css-tables/visibility-collapse-col-004-dynamic.html [ Failure ] +crbug.com/174167 external/wpt/css/css-tables/visibility-collapse-col-005.html [ Failure ] +crbug.com/174167 external/wpt/css/css-tables/visibility-collapse-colspan-001.html [ Failure ] +crbug.com/174167 external/wpt/css/css-tables/visibility-collapse-colspan-002.html [ Failure ] +crbug.com/174167 external/wpt/css/css-tables/visibility-collapse-colspan-003.html [ Failure ] +crbug.com/174167 external/wpt/css/css-tables/visibility-collapse-rowcol-001.html [ Failure ] +crbug.com/174167 external/wpt/css/css-tables/visibility-collapse-rowcol-002.html [ Failure ] # [css-contain]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/audioparam-setValueCurve-exceptions-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/audioparam-setValueCurve-exceptions-expected.txt deleted file mode 100644 index 4c36f41..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/audioparam-setValueCurve-exceptions-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -FAIL - Test Exceptions from setValueCurveAtTime - Uncaught Error: Audit.define:: Duplicate task definition. -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/audioparam-setValueCurve-exceptions.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/audioparam-setValueCurve-exceptions.html index 98f64a0..3706299 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/audioparam-setValueCurve-exceptions.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/audioparam-setValueCurve-exceptions.html
@@ -314,85 +314,21 @@ g.gain.setValueCurveAtTime(curve, startTime, curveDuration); }, `second g.gain.setValueCurveAtTime([${curve}], ${startTime}, ${curveDuration})`) - .throw('NotSupportedError'); + .throw(DOMException, 'NotSupportedError'); // Same start time, shorter end time should( () => { g.gain.setValueCurveAtTime(curve, startTime, curveDurationShorter); }, `g.gain.setValueCurveAtTime([${curve}], ${startTime}, ${curveDurationShorter})`) - .throw('NotSupportedError'); + .throw(DOMException, 'NotSupportedError'); // Earlier start time, end time after the start time an another curve should( () => { g.gain.setValueCurveAtTime(curve, startTimeEarlier, curveDuration); }, `g.gain.setValueCurveAtTime([${curve}], ${startTimeEarlier}, ${curveDuration})`) - .throw('NotSupportedError'); - // Start time after the start time of the other curve, but earlier that - // its end. - should( - () => { - g.gain.setValueCurveAtTime(curve, startTimeLater, curveDuration); - }, - `g.gain.setValueCurveAtTime([${curve}], ${startTimeLater}, ${curveDuration})`) - .throw('NotSupportedError'); - - task.done(); - }); - - audit.define('curve overlap', (task, should) => { - let context = - new OfflineAudioContext(1, testDurationFrames, sampleRate); - let g = context.createGain(); - let startTime = 5; - let startTimeLater = 10; - let startTimeEarlier = 2.5; - let curveDuration = 10; - let curveDurationShorter = 5; - let curve = [1, 2, 3]; - - // Having an event that ends at time t and then starting a ramp at time - // t should work. - should( - () => { - g.gain.linearRampToValueAtTime(1.0, startTime); - }, - `g.gain.linearRampToValueAtTime(1.0, ${startTime})`) - .notThrow(); - - // An initial curve event, starting from the end of the linear ramp. - should( - () => { - g.gain.setValueCurveAtTime(curve, startTime, curveDuration); - }, - `g.gain.setValueCurveAtTime([${curve}], ${startTime}, ${curveDuration})`) - .notThrow(); - - // Check that an exception is thrown when trying to overlap two curves, - // in various ways - - // Same start time and end time (curve exactly overlapping) - should( - () => { - g.gain.setValueCurveAtTime(curve, startTime, curveDuration); - }, - `second g.gain.setValueCurveAtTime([${curve}], ${startTime}, ${curveDuration})`) - .throw('NotSupportedError'); - // Same start time, shorter end time - should( - () => { - g.gain.setValueCurveAtTime(curve, startTime, curveDurationShorter); - }, - `g.gain.setValueCurveAtTime([${curve}], ${startTime}, ${curveDurationShorter})`) - .throw('NotSupportedError'); - // Earlier start time, end time after the start time of an another curve - should( - () => { - g.gain.setValueCurveAtTime(curve, startTimeEarlier, curveDuration); - }, - `g.gain.setValueCurveAtTime([${curve}], ${startTimeEarlier}, ${curveDuration})`) - .throw('NotSupportedError'); + .throw(DOMException, 'NotSupportedError'); // Start time after the start time of the other curve, but earlier than // its end. should( @@ -400,7 +336,22 @@ g.gain.setValueCurveAtTime(curve, startTimeLater, curveDuration); }, `g.gain.setValueCurveAtTime([${curve}], ${startTimeLater}, ${curveDuration})`) - .throw('NotSupportedError'); + .throw(DOMException, 'NotSupportedError'); + + // New event wholly contained inside existing event + should( + () => { + g.gain.setValueCurveAtTime(curve, startTime + 1, curveDuration - 1); + }, + `g.gain.setValueCurveAtTime([${curve}], ${startTime+1}, ${curveDuration-1})`) + .throw(DOMException, 'NotSupportedError'); + // Old event completely contained inside new event + should( + () => { + g.gain.setValueCurveAtTime(curve, startTime - 1, curveDuration + 1); + }, + `g.gain.setValueCurveAtTime([${curve}], ${startTime-1}, ${curveDuration+1})`) + .throw(DOMException, 'NotSupportedError'); // Setting an event exactly at the end of the curve should work. should( () => {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/ctor-panner-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/ctor-panner-expected.txt deleted file mode 100644 index 6a65dca..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/ctor-panner-expected.txt +++ /dev/null
@@ -1,97 +0,0 @@ -This is a testharness.js-based test. -Found 93 tests; 88 PASS, 5 FAIL, 0 TIMEOUT, 0 NOTRUN. -PASS # AUDIT TASK RUNNER STARTED. -PASS > [initialize] -PASS context = new OfflineAudioContext(...) did not throw an exception. -PASS < [initialize] All assertions passed. (total 1 assertions) -PASS > [invalid constructor] -PASS new PannerNode() threw TypeError: "Failed to construct 'PannerNode': 1 argument required, but only 0 present.". -PASS new PannerNode(1) threw TypeError: "Failed to construct 'PannerNode': parameter 1 is not of type 'BaseAudioContext'.". -PASS new PannerNode(context, 42) threw TypeError: "Failed to construct 'PannerNode': parameter 2 ('options') is not an object.". -PASS < [invalid constructor] All assertions passed. (total 3 assertions) -PASS > [default constructor] -PASS node0 = new PannerNode(context) did not throw an exception. -PASS node0 instanceof PannerNode is equal to true. -PASS node0.numberOfInputs is equal to 1. -PASS node0.numberOfOutputs is equal to 1. -PASS node0.channelCount is equal to 2. -PASS node0.channelCountMode is equal to clamped-max. -PASS node0.channelInterpretation is equal to speakers. -PASS node0.panningModel is equal to equalpower. -PASS node0.positionX.value is equal to 0. -PASS node0.positionY.value is equal to 0. -PASS node0.positionZ.value is equal to 0. -PASS node0.orientationX.value is equal to 1. -PASS node0.orientationY.value is equal to 0. -PASS node0.orientationZ.value is equal to 0. -PASS node0.distanceModel is equal to inverse. -PASS node0.refDistance is equal to 1. -PASS node0.maxDistance is equal to 10000. -PASS node0.rolloffFactor is equal to 1. -PASS node0.coneInnerAngle is equal to 360. -PASS node0.coneOuterAngle is equal to 360. -PASS node0.coneOuterGain is equal to 0. -PASS context.listener.positionX.value is equal to 0. -PASS context.listener.positionY.value is equal to 0. -PASS context.listener.positionZ.value is equal to 0. -PASS context.listener.forwardX.value is equal to 0. -PASS context.listener.forwardY.value is equal to 0. -PASS context.listener.forwardZ.value is equal to -1. -PASS context.listener.upX.value is equal to 0. -PASS context.listener.upY.value is equal to 1. -PASS context.listener.upZ.value is equal to 0. -PASS < [default constructor] All assertions passed. (total 30 assertions) -PASS > [test AudioNodeOptions] -PASS node1 = new PannerNode(c, {"channelCount":1}) did not throw an exception. -PASS node1.channelCount is equal to 1. -PASS node2 = new PannerNode(c, {"channelCount":2}) did not throw an exception. -PASS node2.channelCount is equal to 2. -PASS new PannerNode(c, {"channelCount":0}) threw NotSupportedError: "Failed to construct 'PannerNode': The channelCount provided (0) is outside the range [1, 2].". -PASS new PannerNode(c, {"channelCount":3}) threw NotSupportedError: "Failed to construct 'PannerNode': The channelCount provided (3) is outside the range [1, 2].". -PASS new PannerNode(c, {"channelCount":99}) threw NotSupportedError: "Failed to construct 'PannerNode': The channelCount provided (99) is outside the range [1, 2].". -PASS node3 = new PannerNode(c, {"channelCountMode":"clamped-max"}) did not throw an exception. -PASS node3.channelCountMode is equal to clamped-max. -PASS node4 = new PannerNode(c, {"channelCountMode":"explicit"}) did not throw an exception. -PASS node4.channelCountMode is equal to explicit. -PASS new PannerNode(c, {"channelCountMode":"max"}) threw NotSupportedError: "Failed to construct 'PannerNode': Panner: 'max' is not allowed". -PASS new PannerNode(c, " + JSON.stringify(options) + ") threw TypeError: "Failed to construct 'PannerNode': The provided value 'foobar' is not a valid enum value of type ChannelCountMode.". -PASS node5 = new PannerNode(c, {"channelInterpretation":"speakers"}) did not throw an exception. -PASS node5.channelInterpretation is equal to speakers. -PASS node6 = new PannerNode(c, {"channelInterpretation":"discrete"}) did not throw an exception. -PASS node6.channelInterpretation is equal to discrete. -PASS new PannerNode(c, {"channelInterpretation":"foobar"}) threw TypeError: "Failed to construct 'PannerNode': The provided value 'foobar' is not a valid enum value of type ChannelInterpretation.". -PASS new PannerNode(c, {"maxDistance":-1}) threw RangeError: "Failed to construct 'PannerNode': The maxDistance provided (-1) is less than the minimum bound (0).". -PASS node7 = new PannerNode(c, {"maxDistance":100}) did not throw an exception. -PASS node7.maxDistance is equal to 100. -FAIL X new PannerNode(c, {"rolloffFactor":-1}) did not throw an exception. assert_true: expected true got false -PASS node8 = new PannerNode(c, {"rolloffFactor":0.5}) did not throw an exception. -PASS node8.rolloffFactor is equal to 0.5. -FAIL X new PannerNode(c, {"coneOuterGain":-1}) did not throw an exception. assert_true: expected true got false -FAIL X new PannerNode(c, {"coneOuterGain":1.1}) did not throw an exception. assert_true: expected true got false -PASS node9 = new PannerNode(c, {"coneOuterGain":0.5}) did not throw an exception. -PASS node9.coneOuterGain is equal to 0.5. -FAIL < [test AudioNodeOptions] 3 out of 28 assertions were failed. assert_true: expected true got false -PASS > [constructor with options] -PASS node = new PannerNode(c, {"panningModel":"HRTF","positionX":1.4142135623730951,"positionY":2.8284271247461903,"positionZ":4.242640687119286,"orientationX":-1.4142135623730951,"orientationY":-2.8284271247461903,"orientationZ":-4.242640687119286,"distanceModel":"linear","refDistance":3.141592653589793,"maxDistance":6.283185307179586,"rolloffFactor":9.42477796076938,"coneInnerAngle":12.566370614359172,"coneOuterAngle":15.707963267948966,"coneOuterGain":0.3141592653589793}) did not throw an exception. -PASS node instanceof PannerNode is equal to true. -PASS node.panningModel is equal to HRTF. -PASS node.positionX.value is equal to 1.4142135381698608. -PASS node.positionY.value is equal to 2.8284270763397217. -PASS node.positionZ.value is equal to 4.242640495300293. -PASS node.orientationX.value is equal to -1.4142135381698608. -PASS node.orientationY.value is equal to -2.8284270763397217. -PASS node.orientationZ.value is equal to -4.242640495300293. -PASS node.distanceModel is equal to linear. -PASS node.refDistance is equal to 3.141592653589793. -PASS node.maxDistance is equal to 6.283185307179586. -PASS node.rolloffFactor is equal to 9.42477796076938. -PASS node.coneInnerAngle is equal to 12.566370614359172. -PASS node.coneOuterAngle is equal to 15.707963267948966. -PASS node.coneOuterGain is equal to 0.3141592653589793. -PASS node.channelCount is equal to 2. -PASS node.channelCountMode is equal to clamped-max. -PASS node.channelInterpretation is equal to speakers. -PASS < [constructor with options] All assertions passed. (total 19 assertions) -FAIL # AUDIT TASK RUNNER FINISHED: 1 out of 5 tasks were failed. assert_true: expected true got false -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/ctor-panner.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/ctor-panner.html index cdad597..d330c9c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/ctor-panner.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/ctor-panner.html
@@ -218,6 +218,16 @@ }, 'new PannerNode(c, ' + JSON.stringify(options) + ')') .throw(RangeError); + options = {rolloffFactor: 0}; + should( + () => { + node = new PannerNode(context, options); + }, + 'node8 = new PannerNode(c, ' + JSON.stringify(options) + ')') + .notThrow(); + should(node.rolloffFactor, 'node8.rolloffFactor') + .beEqualTo(options.rolloffFactor); + options = {rolloffFactor: 0.5}; should( () => { @@ -228,6 +238,16 @@ should(node.rolloffFactor, 'node8.rolloffFactor') .beEqualTo(options.rolloffFactor); + options = {rolloffFactor: 100}; + should( + () => { + node = new PannerNode(context, options); + }, + 'node8 = new PannerNode(c, ' + JSON.stringify(options) + ')') + .notThrow(); + should(node.rolloffFactor, 'node8.rolloffFactor') + .beEqualTo(options.rolloffFactor); + // Test coneOuterGain options = {coneOuterGain: -1}; should( @@ -235,14 +255,23 @@ node = new PannerNode(context, options); }, 'new PannerNode(c, ' + JSON.stringify(options) + ')') - .throw('InvalidStateError'); + .throw(DOMException, 'InvalidStateError'); options = {coneOuterGain: 1.1}; should( () => { node = new PannerNode(context, options); }, 'new PannerNode(c, ' + JSON.stringify(options) + ')') - .throw('InvalidStateError'); + .throw(DOMException, 'InvalidStateError'); + options = {coneOuterGain: 0.0}; + should( + () => { + node = new PannerNode(context, options); + }, + 'node9 = new PannerNode(c, ' + JSON.stringify(options) + ')') + .notThrow(); + should(node.coneOuterGain, 'node9.coneOuterGain') + .beEqualTo(options.coneOuterGain); options = {coneOuterGain: 0.5}; should( () => { @@ -253,6 +282,16 @@ should(node.coneOuterGain, 'node9.coneOuterGain') .beEqualTo(options.coneOuterGain); + options = {coneOuterGain: 1.0}; + should( + () => { + node = new PannerNode(context, options); + }, + 'node9 = new PannerNode(c, ' + JSON.stringify(options) + ')') + .notThrow(); + should(node.coneOuterGain, 'node9.coneOuterGain') + .beEqualTo(options.coneOuterGain); + task.done(); });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/panner-rolloff-clamping.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/panner-rolloff-clamping.html index e1519f8..387f873 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/panner-rolloff-clamping.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/panner-rolloff-clamping.html
@@ -17,41 +17,19 @@ let audit = Audit.createTaskRunner(); - audit.define('linear-clamp-low', (task, should) => { - runTest(should, { - distanceModel: 'linear', - // Fairly arbitrary value outside the nominal range - rolloffFactor: -1, - clampedRolloff: 0 - }).then(() => task.done()); - }); - - audit.define('linear-clamp-high', (task, should) => { - runTest(should, { - distanceModel: 'linear', - // Fairly arbitrary value outside the nominal range - rolloffFactor: 2, - clampedRolloff: 1 - }).then(() => task.done()); - }); - - audit.define('inverse-clamp', (task, should) => { - runTest(should, { - distanceModel: 'inverse', - // Fairly arbitrary value outside the nominal range - rolloffFactor: -1, - clampedRolloff: 0 - }).then(() => task.done()); - }); - - audit.define('exponential-clamp', (task, should) => { - runTest(should, { - distanceModel: 'exponential', - // Fairly arbitrary value outside the nominal range - rolloffFactor: -2, - clampedRolloff: 0 - }).then(() => task.done()); - }); + audit.define( + { + label: 'linear-clamp-high', + description: 'rolloffFactor clamping for linear distance model' + }, + (task, should) => { + runTest(should, { + distanceModel: 'linear', + // Fairly arbitrary value outside the nominal range + rolloffFactor: 2, + clampedRolloff: 1 + }).then(() => task.done()); + }); // Test clamping of the rolloffFactor. The test is done by comparing the // output of a panner with the rolloffFactor set outside the nominal range
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/transformed-mask-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css/transformed-mask-expected.png index d9b40f0a..325df34 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/css/transformed-mask-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/transformed-mask-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/reflections/opacity-reflection-transform-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/reflections/opacity-reflection-transform-expected.png index 4b38f1cb..3b0016e 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/reflections/opacity-reflection-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/reflections/opacity-reflection-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png index 5a12b1f28..154bf2ca 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/reflections/opacity-reflection-transform-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/reflections/opacity-reflection-transform-expected.png index 1498516..1071d689 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/reflections/opacity-reflection-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/reflections/opacity-reflection-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png index ed4ebea..1a664f1 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png index ffe69da..41d3fcb 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/reflections/opacity-reflection-transform-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/reflections/opacity-reflection-transform-expected.png index 298a6a55..fec821c15 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/reflections/opacity-reflection-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/reflections/opacity-reflection-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png index b7e7755b9..3b91b6b5 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png Binary files differ
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index 17b635e..b36bd0c 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -30,6 +30,7 @@ #include <limits> #include "base/auto_reset.h" +#include "base/debug/crash_logging.h" #include "base/memory/ptr_util.h" #include "third_party/blink/public/platform/modules/remoteplayback/web_remote_playback_availability.h" #include "third_party/blink/public/platform/modules/remoteplayback/web_remote_playback_client.h" @@ -377,6 +378,13 @@ const ContentType& content_type) { DEFINE_STATIC_LOCAL(const String, codecs, ("codecs")); + // TODO(https://crbug.com/809912): Finding source of mime parsing crash. + static base::debug::CrashKeyString* content_type_crash_key = + base::debug::AllocateCrashKeyString("media_content_type", + base::debug::CrashKeySize::Size256); + base::debug::ScopedCrashKeyString scoped_crash_key( + content_type_crash_key, content_type.Raw().Utf8().data()); + String type = content_type.GetType().DeprecatedLower(); // The codecs string is not lower-cased because MP4 values are case sensitive // per http://tools.ietf.org/html/rfc4281#page-7.
diff --git a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.cc b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.cc index de141ded..0908a2f 100644 --- a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.cc +++ b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.cc
@@ -19,7 +19,7 @@ void InsertOpportunity(const NGLayoutOpportunity& opportunity, Vector<NGLayoutOpportunity, 4>* opportunities) { if (opportunities->IsEmpty()) { - opportunities->push_back(opportunity); + opportunities->emplace_back(opportunity); return; } @@ -72,7 +72,7 @@ Vector<scoped_refptr<const NGExclusion>, 1>* out_edges) { for (const auto& edge : edges) { if (edge->rect.BlockEndOffset() > block_offset) - out_edges->push_back(edge); + out_edges->emplace_back(edge); } } @@ -183,7 +183,7 @@ left_float_clear_offset_(LayoutUnit::Min()), right_float_clear_offset_(LayoutUnit::Min()) { // The exclusion space must always have at least one shelf, at -Infinity. - shelves_.push_back(NGShelf(/* block_offset */ LayoutUnit::Min())); + shelves_.emplace_back(/* block_offset */ LayoutUnit::Min()); } void NGExclusionSpace::Add(scoped_refptr<const NGExclusion> exclusion) { @@ -203,35 +203,34 @@ } if (derived_geometry_) - derived_geometry_->Add(exclusion); + derived_geometry_->Add(*exclusion); both_clear_offset_ = std::max(both_clear_offset_, exclusion->rect.BlockEndOffset()); - exclusions_->push_back(std::move(exclusion)); + exclusions_->emplace_back(std::move(exclusion)); num_exclusions_++; } -void NGExclusionSpace::DerivedGeometry::Add( - scoped_refptr<const NGExclusion> exclusion) { +void NGExclusionSpace::DerivedGeometry::Add(const NGExclusion& exclusion) { last_float_block_start_ = - std::max(last_float_block_start_, exclusion->rect.BlockStartOffset()); + std::max(last_float_block_start_, exclusion.rect.BlockStartOffset()); - const LayoutUnit exclusion_end_offset = exclusion->rect.BlockEndOffset(); + const LayoutUnit exclusion_end_offset = exclusion.rect.BlockEndOffset(); // Update the members used for clearance calculations. - if (exclusion->type == EFloat::kLeft) { + if (exclusion.type == EFloat::kLeft) { left_float_clear_offset_ = - std::max(left_float_clear_offset_, exclusion->rect.BlockEndOffset()); - } else if (exclusion->type == EFloat::kRight) { + std::max(left_float_clear_offset_, exclusion.rect.BlockEndOffset()); + } else if (exclusion.type == EFloat::kRight) { right_float_clear_offset_ = - std::max(right_float_clear_offset_, exclusion->rect.BlockEndOffset()); + std::max(right_float_clear_offset_, exclusion.rect.BlockEndOffset()); } // If the exclusion takes up no inline space, we shouldn't pay any further // attention to it. The only thing it can affect is block-axis positioning of // subsequent floats (dealt with above). - if (exclusion->rect.LineEndOffset() <= exclusion->rect.LineStartOffset()) + if (exclusion.rect.LineEndOffset() <= exclusion.rect.LineStartOffset()) return; #if DCHECK_IS_ON() @@ -286,7 +285,7 @@ // 20 +---+ // |NEW| // +---+ - bool is_below = exclusion->rect.BlockStartOffset() > shelf.block_offset; + bool is_below = exclusion.rect.BlockStartOffset() > shelf.block_offset; if (is_below) { // We may have created a new opportunity, by closing off an area. @@ -321,9 +320,9 @@ // against that edge. bool has_solid_edges = HasSolidEdges(shelf.line_left_edges, shelf.block_offset, - exclusion->rect.BlockStartOffset()) && + exclusion.rect.BlockStartOffset()) && HasSolidEdges(shelf.line_right_edges, shelf.block_offset, - exclusion->rect.BlockStartOffset()); + exclusion.rect.BlockStartOffset()); // This just checks if the exclusion overlaps the bounds of the shelf. // @@ -340,8 +339,8 @@ // In the above example the "NEW" exclusion *doesn't* overlap with the // above drawn shelf, and a new opportunity hasn't been created. bool is_overlapping = - exclusion->rect.LineStartOffset() < shelf.line_right && - exclusion->rect.LineEndOffset() > shelf.line_left; + exclusion.rect.LineStartOffset() < shelf.line_right && + exclusion.rect.LineEndOffset() > shelf.line_left; // Insert a closed-off layout opportunity if needed. if (has_solid_edges && is_overlapping) { @@ -349,7 +348,7 @@ NGBfcRect( /* start_offset */ {shelf.line_left, shelf.block_offset}, /* end_offset */ {shelf.line_right, - exclusion->rect.BlockStartOffset()}), + exclusion.rect.BlockStartOffset()}), shelf.has_shape_exclusions ? base::AdoptRef(new NGShapeExclusions( *shelf.shape_exclusions)) : nullptr); @@ -372,25 +371,25 @@ // We need to reduce the size of the shelf. if (is_below || is_intersecting) { - if (exclusion->type == EFloat::kLeft) { - if (exclusion->rect.LineEndOffset() >= shelf.line_left) { + if (exclusion.type == EFloat::kLeft) { + if (exclusion.rect.LineEndOffset() >= shelf.line_left) { // The edges need to be cleared if it pushes the shelf edge in. - if (exclusion->rect.LineEndOffset() > shelf.line_left) + if (exclusion.rect.LineEndOffset() > shelf.line_left) shelf.line_left_edges.clear(); - shelf.line_left = exclusion->rect.LineEndOffset(); - shelf.line_left_edges.push_back(exclusion); + shelf.line_left = exclusion.rect.LineEndOffset(); + shelf.line_left_edges.emplace_back(&exclusion); } - shelf.shape_exclusions->line_left_shapes.push_back(exclusion); + shelf.shape_exclusions->line_left_shapes.emplace_back(&exclusion); } else { - DCHECK_EQ(exclusion->type, EFloat::kRight); - if (exclusion->rect.LineStartOffset() <= shelf.line_right) { + DCHECK_EQ(exclusion.type, EFloat::kRight); + if (exclusion.rect.LineStartOffset() <= shelf.line_right) { // The edges need to be cleared if it pushes the shelf edge in. - if (exclusion->rect.LineStartOffset() < shelf.line_right) + if (exclusion.rect.LineStartOffset() < shelf.line_right) shelf.line_right_edges.clear(); - shelf.line_right = exclusion->rect.LineStartOffset(); - shelf.line_right_edges.push_back(exclusion); + shelf.line_right = exclusion.rect.LineStartOffset(); + shelf.line_right_edges.emplace_back(&exclusion); } - shelf.shape_exclusions->line_right_shapes.push_back(exclusion); + shelf.shape_exclusions->line_right_shapes.emplace_back(&exclusion); } // We collect all exclusions in shape_exclusions (even if they don't @@ -398,7 +397,7 @@ // included in the shape line algorithm). We use this bool to track // if the shape exclusions should be copied to the resulting layout // opportunity. - if (exclusion->shape_data) + if (exclusion.shape_data) shelf.has_shape_exclusions = true; // Just in case the shelf has a negative inline-size. @@ -578,7 +577,7 @@ derived_geometry_ = std::make_unique<DerivedGeometry>(); DCHECK_LE(num_exclusions_, exclusions_->size()); for (size_t i = 0; i < num_exclusions_; ++i) - derived_geometry_->Add(exclusions_->GetVector()[i]); + derived_geometry_->Add(*exclusions_->GetVector()[i]); } return *derived_geometry_;
diff --git a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h index b45d208..5f2ec900 100644 --- a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h +++ b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
@@ -191,7 +191,7 @@ struct DerivedGeometry { DerivedGeometry(); - void Add(scoped_refptr<const NGExclusion> exclusion); + void Add(const NGExclusion& exclusion); NGLayoutOpportunity FindLayoutOpportunity( const NGBfcOffset& offset,
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc index 91906eb..f585f52 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
@@ -525,7 +525,8 @@ for (unsigned i = fragment_start; i < fragment_end; i++) { NGLineBoxFragmentBuilder::Child& child = (*line_box)[i]; if (child.layout_result) { - box.AddChild(std::move(child.layout_result), child.offset - offset); + box.AddChild(*child.layout_result, child.offset - offset); + child.layout_result.reset(); } else if (child.fragment) { box.AddChild(std::move(child.fragment), child.offset - offset); }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc index 9956afc3..b6ee9a0 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc
@@ -117,8 +117,8 @@ for (auto& child : children) { if (child.layout_result) { DCHECK(!child.fragment); - AddChild(std::move(child.layout_result), child.offset); - DCHECK(!child.layout_result); + AddChild(*child.layout_result, child.offset); + child.layout_result.reset(); } else if (child.fragment) { AddChild(std::move(child.fragment), child.offset); DCHECK(!child.fragment);
diff --git a/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc b/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc index 92a8543b..8f2c5bf 100644 --- a/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc +++ b/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc
@@ -117,7 +117,7 @@ marker_offset.block_offset); DCHECK(container_builder); - container_builder->AddChild(std::move(marker_layout_result), marker_offset); + container_builder->AddChild(*marker_layout_result, marker_offset); return true; } @@ -140,7 +140,7 @@ NGLogicalOffset offset(InlineOffset(marker_size.inline_size), LayoutUnit()); DCHECK(container_builder); - container_builder->AddChild(std::move(marker_layout_result), offset); + container_builder->AddChild(*marker_layout_result, offset); return marker_size.block_size; }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc index 5e9d7da..12782ee 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -926,7 +926,7 @@ PositionOrPropagateListMarker(*layout_result, &logical_offset); - container_builder_.AddChild(layout_result, logical_offset); + container_builder_.AddChild(*layout_result, logical_offset); container_builder_.PropagateBreak(layout_result); // The margins we store will be used by e.g. getComputedStyle(). @@ -1277,7 +1277,7 @@ layout_result->AdjoiningFloatTypes()); } - container_builder_.AddChild(layout_result, logical_offset); + container_builder_.AddChild(*layout_result, logical_offset); if (child.IsBlock()) container_builder_.PropagateBreak(layout_result); @@ -2071,7 +2071,8 @@ child_fragment, positioned_float.bfc_offset, bfc_offset, container_builder_.Size().inline_size, ConstraintSpace().Direction()); - container_builder_.AddChild(positioned_float.layout_result, logical_offset); + container_builder_.AddChild(*positioned_float.layout_result, + logical_offset); container_builder_.PropagateBreak(positioned_float.layout_result); } }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc index 2111d00..1257581c 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -582,8 +582,8 @@ // Copies data back to the legacy layout tree for a given child fragment. void NGBlockNode::CopyChildFragmentPosition( const NGPhysicalFragment& fragment, - const NGPhysicalOffset& fragment_offset, - const NGPhysicalOffset& additional_offset) { + const NGPhysicalOffset fragment_offset, + const NGPhysicalOffset additional_offset) { LayoutBox* layout_box = ToLayoutBox(fragment.GetLayoutObject()); if (!layout_box) return;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.h b/third_party/blink/renderer/core/layout/ng/ng_block_node.h index 6db2cf1d..f0b9868 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.h +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.h
@@ -119,8 +119,8 @@ const NGPhysicalBoxFragment&); void CopyChildFragmentPosition( const NGPhysicalFragment& fragment, - const NGPhysicalOffset& fragment_offset, - const NGPhysicalOffset& additional_offset = NGPhysicalOffset()); + const NGPhysicalOffset fragment_offset, + const NGPhysicalOffset additional_offset = NGPhysicalOffset()); void CopyBaselinesFromOldLayout(const NGConstraintSpace&, NGFragmentBuilder*); LayoutUnit AtomicInlineBaselineFromOldLayout(const NGBaselineRequest&,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc index ff9e3aef..c746315 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
@@ -120,7 +120,7 @@ ToNGPhysicalBoxFragment(result->PhysicalFragment().get())); NGLogicalOffset logical_offset(column_inline_offset, column_block_offset); - container_builder_.AddChild(result, logical_offset); + container_builder_.AddChild(*result, logical_offset); LayoutUnit space_shortage = result->MinimalSpaceShortage(); if (space_shortage > LayoutUnit()) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc index 7441e91..02ff8195 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
@@ -48,15 +48,15 @@ } NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddChild( - scoped_refptr<NGLayoutResult> child, + const NGLayoutResult& child, const NGLogicalOffset& child_offset) { // Collect the child's out of flow descendants. // child_offset is offset of inline_start/block_start vertex. // Candidates need offset of top/left vertex. - const auto& out_of_flow_descendants = child->OutOfFlowPositionedDescendants(); + const auto& out_of_flow_descendants = child.OutOfFlowPositionedDescendants(); if (!out_of_flow_descendants.IsEmpty()) { NGLogicalOffset top_left_offset; - NGPhysicalSize child_size = child->PhysicalFragment()->Size(); + NGPhysicalSize child_size = child.PhysicalFragment()->Size(); switch (GetWritingMode()) { case WritingMode::kHorizontalTb: top_left_offset = @@ -91,7 +91,7 @@ } } - return AddChild(child->PhysicalFragment(), child_offset); + return AddChild(child.PhysicalFragment(), child_offset); } NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddChild(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h index ca26100..7c88074 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h +++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
@@ -69,7 +69,7 @@ NGContainerFragmentBuilder& SetUnpositionedListMarker( const NGUnpositionedListMarker&); - virtual NGContainerFragmentBuilder& AddChild(scoped_refptr<NGLayoutResult>, + virtual NGContainerFragmentBuilder& AddChild(const NGLayoutResult&, const NGLogicalOffset&); // This version of AddChild will not propagate floats/out_of_flow.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc index ed84346c..c31bd45d 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
@@ -144,7 +144,7 @@ for (size_t i = 0; i < line->line_items.size(); ++i) { FlexItem& flex_item = line->line_items[i]; container_builder_.AddChild( - flex_item.layout_result, + *flex_item.layout_result, {flex_item.desired_location.X(), flex_item.desired_location.Y()}); }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc b/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc index 2d4e50f..efb0076 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc
@@ -62,7 +62,7 @@ exclusion_space = std::make_unique<NGExclusionSpace>(*exclusion_space_); } return base::AdoptRef(new NGLayoutResult( - PhysicalFragment(), oof_positioned_descendants, positioned_floats, + root_fragment_.fragment_, oof_positioned_descendants, positioned_floats, unpositioned_list_marker_, std::move(exclusion_space), bfc_line_offset_, bfc_block_offset_, end_margin_strut_, intrinsic_block_size_, minimal_space_shortage_, initial_break_before_, final_break_after_,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_link.h b/third_party/blink/renderer/core/layout/ng/ng_link.h index f7722a7..a36f9d4 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_link.h +++ b/third_party/blink/renderer/core/layout/ng/ng_link.h
@@ -23,7 +23,9 @@ NGLink() = default; NGLink(scoped_refptr<const NGPhysicalFragment> fragment, NGPhysicalOffset offset) - : fragment_(fragment), offset_(offset) {} + : fragment_(std::move(fragment)), offset_(offset) {} + NGLink(NGLink&& o) noexcept + : fragment_(std::move(o.fragment_)), offset_(o.offset_) {} ~NGLink() = default; // Returns the offset relative to the parent fragment's content-box. @@ -44,10 +46,12 @@ friend class NGFragmentBuilder; friend class NGLineBoxFragmentBuilder; friend class NGLayoutResult; + + DISALLOW_COPY_AND_ASSIGN(NGLink); }; } // namespace blink -WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(blink::NGLink); +WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::NGLink); #endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LINK_H_
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc index bebfe5f9..62a1d2f 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -65,7 +65,7 @@ NGLogicalOffset offset; scoped_refptr<NGLayoutResult> result = LayoutDescendant(candidate, &offset); - container_builder_->AddChild(std::move(result), offset); + container_builder_->AddChild(*result, offset); if (candidate.node.GetLayoutBox() != only_layout) candidate.node.UseOldOutOfFlowPositioning(); } else {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc index 07d9d76..485de1bc 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
@@ -56,7 +56,7 @@ scoped_refptr<const NGPhysicalBoxFragment> page( ToNGPhysicalBoxFragment(result->PhysicalFragment().get())); - container_builder_.AddChild(result, page_offset); + container_builder_.AddChild(*result, page_offset); NGBoxFragment logical_fragment(writing_mode, ConstraintSpace().Direction(), *page);
diff --git a/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js b/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js index b719c59..ad8f3d9 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js +++ b/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js
@@ -75,7 +75,7 @@ this._boundBlur = this._onBlur.bind(this); this._textEditor.element.addEventListener('focusout', this._boundBlur, false); this._boundWheel = event => { - if (UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) + if (this._executionLocation && UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) event.preventDefault(); }; this._textEditor.element.addEventListener('wheel', this._boundWheel, true);
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc index a7db4ba..5a3c163 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
@@ -551,12 +551,43 @@ // Events of type |kSetValueCurveEnd| or |kCancelValues| never // conflict. if (!(test_type == ParamEvent::kSetValueCurveEnd || - test_type == ParamEvent::kCancelValues) && - events_[i]->Time() > event->Time() && events_[i]->Time() < end_time) { - exception_state.ThrowDOMException( - DOMExceptionCode::kNotSupportedError, - EventToString(*event) + " overlaps " + EventToString(*events_[i])); - return; + test_type == ParamEvent::kCancelValues)) { + if (test_type == ParamEvent::kSetValueCurve) { + // A SetValueCurve overlapping an existing SetValueCurve requires + // special care. + double test_end_time = events_[i]->Time() + events_[i]->Duration(); + // Test if old event starts somewhere in the middle of the new event. + bool overlap = (events_[i]->Time() >= event->Time() && + events_[i]->Time() < end_time); + // Test if old event ends somewhere in the middle of the new event. + overlap = overlap || + (test_end_time > event->Time() && test_end_time < end_time); + // Test if new event starts somewhere in the middle of the old event. + overlap = overlap || (event->Time() >= events_[i]->Time() && + event->Time() < test_end_time); + // Test if new event ends somewhere in the middle of the old event. + overlap = overlap || (end_time >= events_[i]->Time() && + end_time < test_end_time); + if (overlap) { + // If the start time of the event overlaps the start/end of an + // existing event or if the existing event end overlaps the + // start/end of the event, it's an error. + exception_state.ThrowDOMException( + DOMExceptionCode::kNotSupportedError, + EventToString(*event) + " overlaps " + + EventToString(*events_[i])); + return; + } + } else { + if (events_[i]->Time() > event->Time() && + events_[i]->Time() < end_time) { + exception_state.ThrowDOMException( + DOMExceptionCode::kNotSupportedError, + EventToString(*event) + " overlaps " + + EventToString(*events_[i])); + return; + } + } } } else { // Otherwise, make sure this event doesn't overlap any existing
diff --git a/third_party/blink/renderer/modules/webaudio/panner_node.cc b/third_party/blink/renderer/modules/webaudio/panner_node.cc index 51821b01..fac20df4 100644 --- a/third_party/blink/renderer/modules/webaudio/panner_node.cc +++ b/third_party/blink/renderer/modules/webaudio/panner_node.cc
@@ -740,10 +740,10 @@ node->setRefDistance(options.refDistance(), exception_state); node->setMaxDistance(options.maxDistance(), exception_state); - node->setRolloffFactor(options.rolloffFactor()); + node->setRolloffFactor(options.rolloffFactor(), exception_state); node->setConeInnerAngle(options.coneInnerAngle()); node->setConeOuterAngle(options.coneOuterAngle()); - node->setConeOuterGain(options.coneOuterGain()); + node->setConeOuterGain(options.coneOuterGain(), exception_state); return node; } @@ -818,7 +818,15 @@ return GetPannerHandler().RolloffFactor(); } -void PannerNode::setRolloffFactor(double factor) { +void PannerNode::setRolloffFactor(double factor, + ExceptionState& exception_state) { + if (factor < 0) { + exception_state.ThrowRangeError( + ExceptionMessages::IndexExceedsMinimumBound<double>("rolloffFactor", + factor, 0)); + return; + } + GetPannerHandler().SetRolloffFactor(factor); } @@ -842,7 +850,17 @@ return GetPannerHandler().ConeOuterGain(); } -void PannerNode::setConeOuterGain(double gain) { +void PannerNode::setConeOuterGain(double gain, + ExceptionState& exception_state) { + if (gain < 0 || gain > 1) { + exception_state.ThrowDOMException( + DOMExceptionCode::kInvalidStateError, + ExceptionMessages::IndexOutsideRange<double>( + "coneOuterGain", gain, 0, ExceptionMessages::kInclusiveBound, 1, + ExceptionMessages::kInclusiveBound)); + return; + } + GetPannerHandler().SetConeOuterGain(gain); }
diff --git a/third_party/blink/renderer/modules/webaudio/panner_node.h b/third_party/blink/renderer/modules/webaudio/panner_node.h index b1f2896d..2e4851c 100644 --- a/third_party/blink/renderer/modules/webaudio/panner_node.h +++ b/third_party/blink/renderer/modules/webaudio/panner_node.h
@@ -236,13 +236,13 @@ double maxDistance() const; void setMaxDistance(double, ExceptionState&); double rolloffFactor() const; - void setRolloffFactor(double); + void setRolloffFactor(double, ExceptionState&); double coneInnerAngle() const; void setConeInnerAngle(double); double coneOuterAngle() const; void setConeOuterAngle(double); double coneOuterGain() const; - void setConeOuterGain(double); + void setConeOuterGain(double, ExceptionState&); private: PannerNode(BaseAudioContext&);
diff --git a/third_party/blink/renderer/modules/webaudio/panner_node.idl b/third_party/blink/renderer/modules/webaudio/panner_node.idl index 3acde7e5..25a19fc 100644 --- a/third_party/blink/renderer/modules/webaudio/panner_node.idl +++ b/third_party/blink/renderer/modules/webaudio/panner_node.idl
@@ -61,10 +61,10 @@ [RaisesException=Setter] attribute double refDistance; [RaisesException=Setter] attribute double maxDistance; - attribute double rolloffFactor; + [RaisesException=Setter] attribute double rolloffFactor; // Directional sound cone attribute double coneInnerAngle; attribute double coneOuterAngle; - attribute double coneOuterGain; + [RaisesException=Setter] attribute double coneOuterGain; };
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc index ab70452..5662fe5 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc
@@ -93,15 +93,15 @@ const scoped_refptr<const ShapeResult>& word_result = results[resolved_index]; word_offset -= word_result->NumCharacters(); advance = - FillGlyphsForResult(word_result.get(), run_info.run, run_info.from, - run_info.to, advance, word_offset); + FillGlyphsForResult(word_result.get(), run_info.run.ToStringView(), + run_info.from, run_info.to, advance, word_offset); } } else { unsigned word_offset = 0; for (const auto& word_result : results) { advance = - FillGlyphsForResult(word_result.get(), run_info.run, run_info.from, - run_info.to, advance, word_offset); + FillGlyphsForResult(word_result.get(), run_info.run.ToStringView(), + run_info.from, run_info.to, advance, word_offset); word_offset += word_result->NumCharacters(); } } @@ -138,7 +138,7 @@ unsigned resolved_offset = word_offset - (run_info.run.Rtl() ? word_result->NumCharacters() : 0); advance += FillTextEmphasisGlyphsForRun( - word_result->runs_[i].get(), run_info.run, + word_result->runs_[i].get(), run_info.run.ToStringView(), run_info.run.CharactersLength(), run_info.run.Direction(), run_info.from, run_info.to, emphasis_data, advance, resolved_offset); } @@ -164,9 +164,8 @@ namespace { -template <typename TextContainerType> inline bool IsSkipInkException(const ShapeResultBloberizer& bloberizer, - const TextContainerType& text, + const StringView& text, unsigned character_index) { // We want to skip descenders in general, but it is undesirable renderings for // CJK characters. @@ -175,14 +174,13 @@ text.CodepointAt(character_index)); } -template <typename TextContainerType> inline void AddGlyphToBloberizer(ShapeResultBloberizer& bloberizer, float advance, hb_direction_t direction, CanvasRotationInVertical canvas_rotation, const SimpleFontData* font_data, const HarfBuzzRunGlyphData& glyph_data, - const TextContainerType& text, + const StringView& text, unsigned character_index) { FloatPoint start_offset = HB_DIRECTION_IS_HORIZONTAL(direction) ? FloatPoint(advance, 0) @@ -243,9 +241,8 @@ } // namespace -template <typename TextContainerType> float ShapeResultBloberizer::FillGlyphsForResult(const ShapeResult* result, - const TextContainerType& text, + const StringView& text, unsigned from, unsigned to, float initial_advance, @@ -328,10 +325,9 @@ return advance; } -template <typename TextContainerType> float ShapeResultBloberizer::FillTextEmphasisGlyphsForRun( const ShapeResult::RunInfo* run, - const TextContainerType& text, + const StringView& text, unsigned text_length, TextDirection direction, unsigned from,
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h index a3204c4..27e80e6 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h
@@ -108,11 +108,8 @@ private: friend class ShapeResultBloberizerTestInfo; - // Where TextContainerType can be either a TextRun or a StringView. - // For legacy layout and LayoutNG respectively. - template <typename TextContainerType> float FillGlyphsForResult(const ShapeResult*, - const TextContainerType&, + const StringView&, unsigned from, unsigned to, float initial_advance, @@ -128,9 +125,8 @@ float FillFastHorizontalGlyphs(const ShapeResultBuffer&, TextDirection); float FillFastHorizontalGlyphs(const ShapeResult*, float advance = 0); - template <typename TextContainerType> float FillTextEmphasisGlyphsForRun(const ShapeResult::RunInfo*, - const TextContainerType&, + const StringView&, unsigned text_length, TextDirection, unsigned from,
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 270f915..98aa5ece 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1265,7 +1265,6 @@ }, { name: "VisibilityCollapseColumn", - status: "experimental", }, { name: "WakeLock",
diff --git a/third_party/blink/renderer/platform/wtf/ref_vector.h b/third_party/blink/renderer/platform/wtf/ref_vector.h index 8634f6d..e35758618 100644 --- a/third_party/blink/renderer/platform/wtf/ref_vector.h +++ b/third_party/blink/renderer/platform/wtf/ref_vector.h
@@ -38,6 +38,10 @@ wtf_size_t size() const { return vector_.size(); } bool IsEmpty() const { return !size(); } void push_back(const T& decoration) { vector_.push_back(decoration); } + template <typename... Args> + T& emplace_back(Args&&... args) { + return vector_.emplace_back(std::forward<Args>(args)...); + } const Vector<T>& GetVector() const { return vector_; } Vector<T>* GetMutableVector() { return &vector_; }
diff --git a/third_party/fuchsia-sdk/BUILD.gn b/third_party/fuchsia-sdk/BUILD.gn index e55594a7..ed179d5 100644 --- a/third_party/fuchsia-sdk/BUILD.gn +++ b/third_party/fuchsia-sdk/BUILD.gn
@@ -428,3 +428,19 @@ "vmo.cpp", ] } + +copy("vulkan_layers") { + sources = [ + "sdk/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_core_validation.json", + "sdk/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_image_pipe_swapchain.json", + "sdk/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_object_tracker.json", + "sdk/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_parameter_validation.json", + "sdk/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_standard_validation.json", + "sdk/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_threading.json", + "sdk/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_unique_objects.json", + ] + + outputs = [ + "${root_gen_dir}/data/vulkan/explicit_layer.d/{{source_file_part}}", + ] +}
diff --git a/tools/cfi/blacklist.txt b/tools/cfi/blacklist.txt index 761574a5..bffce270 100644 --- a/tools/cfi/blacklist.txt +++ b/tools/cfi/blacklist.txt
@@ -143,6 +143,7 @@ # Calls to auto-generated stubs by generate_stubs.py src:*audio/pulse/pulse_stubs.cc +src:*media/gpu/vaapi/va_stubs.cc # Calls to auto-generated stubs by generate_library_loader.py src:*chrome/browser/speech/tts_linux.cc
diff --git a/tools/grit/repack.gni b/tools/grit/repack.gni index 55f81d7..fba90db4 100644 --- a/tools/grit/repack.gni +++ b/tools/grit/repack.gni
@@ -49,6 +49,9 @@ script = "//tools/grit/pak_util.py" inputs = invoker.sources + foreach(_invoker_source, invoker.sources) { + inputs += [ "${_invoker_source}.info" ] + } outputs = [ invoker.output, "${invoker.output}.info",
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 3562437c..ba24bbd 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -16593,6 +16593,7 @@ <int value="1272" label="FILEMANAGERPRIVATEINTERNAL_SHAREPATHWITHCROSTINICONTAINER"/> <int value="1273" label="AUTOTESTPRIVATE_SETCROSTINIENABLED"/> + <int value="1274" label="AUTOTESTPRIVATE_GETHISTOGRAM"/> </enum> <enum name="ExtensionIconState">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 9115e65..ec57639 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -42741,6 +42741,17 @@ </summary> </histogram> +<histogram base="true" name="Media.MSE.CodecChangeTime" units="ms" + expires_after="2019-09-04"> + <owner>wolenetz@chromium.org</owner> + <owner>sandersd@chromium.org</owner> + <summary> + Duration of config changes that include codec changes, measured from before + decoder flush until after the first output frame is returned. The HW/SW + suffix indicates the type of the decoder that was ultimately selected. + </summary> +</histogram> + <histogram name="Media.MSE.DemuxerDestructionTime" units="ms"> <owner>wolenetz@chromium.org</owner> <summary> @@ -123379,6 +123390,14 @@ <affected-histogram name="MediaRouter.Cast.App.Availability"/> </histogram_suffixes> +<histogram_suffixes name="MediaStreamAndDecoderType" separator="."> + <suffix name="Audio.HW" label="Platform audio decoder"/> + <suffix name="Audio.SW" label="Software audio decoder"/> + <suffix name="Video.HW" label="Platform video decoder"/> + <suffix name="Video.SW" label="Software video decoder"/> + <affected-histogram name="Media.MSE.CodecChangeTime"/> +</histogram_suffixes> + <histogram_suffixes name="MediaTimelineWidths" separator="."> <suffix name="32_47"/> <suffix name="48_79"/>
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn index fd2eac3..9232ca1 100644 --- a/ui/accessibility/BUILD.gn +++ b/ui/accessibility/BUILD.gn
@@ -41,6 +41,8 @@ "ax_export.h", "ax_host_delegate.cc", "ax_host_delegate.h", + "ax_mode.h", + "ax_mode_observer.h", "ax_node.cc", "ax_node.h", "ax_node_data.cc",
diff --git a/ui/accessibility/PRESUBMIT.py b/ui/accessibility/PRESUBMIT.py index b0d4034..4465933 100644 --- a/ui/accessibility/PRESUBMIT.py +++ b/ui/accessibility/PRESUBMIT.py
@@ -9,8 +9,8 @@ AX_MOJOM = 'ui/accessibility/ax_enums.mojom' AUTOMATION_IDL = 'chrome/common/extensions/api/automation.idl' -AX_JS_FILE = 'content/browser/resources/accessibility/accessibility.js' -AX_MODE_HEADER = 'ui/accessibility/ax_modes.h' +AX_JS_FILE = 'chrome/browser/resources/accessibility/accessibility.js' +AX_MODE_HEADER = 'ui/accessibility/ax_mode.h' def InitialLowerCamelCase(unix_name): words = unix_name.split('_')
diff --git a/ui/accessibility/ax_modes.h b/ui/accessibility/ax_mode.h similarity index 95% rename from ui/accessibility/ax_modes.h rename to ui/accessibility/ax_mode.h index b601576..ac52a5e 100644 --- a/ui/accessibility/ax_modes.h +++ b/ui/accessibility/ax_mode.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_ACCESSIBILITY_PLATFORM_AX_MODE_H_ -#define UI_ACCESSIBILITY_PLATFORM_AX_MODE_H_ +#ifndef UI_ACCESSIBILITY_AX_MODE_H_ +#define UI_ACCESSIBILITY_AX_MODE_H_ namespace ui { @@ -89,4 +89,4 @@ } // namespace ui -#endif // UI_ACCESSIBILITY_PLATFORM_AX_MODE_H_ +#endif // UI_ACCESSIBILITY_AX_MODE_H_
diff --git a/ui/accessibility/ax_mode_observer.h b/ui/accessibility/ax_mode_observer.h index f517c36..1f2f2af 100644 --- a/ui/accessibility/ax_mode_observer.h +++ b/ui/accessibility/ax_mode_observer.h
@@ -6,7 +6,7 @@ #define UI_ACCESSIBILITY_PLATFORM_AX_MODE_OBSERVER_H_ #include "ui/accessibility/ax_export.h" -#include "ui/accessibility/ax_modes.h" +#include "ui/accessibility/ax_mode.h" namespace ui {
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc index 7b7f71a..3665fc62 100644 --- a/ui/accessibility/ax_tree.cc +++ b/ui/accessibility/ax_tree.cc
@@ -349,16 +349,11 @@ bool root_updated = false; if (update.node_id_to_clear != 0) { AXNode* node = GetFromId(update.node_id_to_clear); - if (!node) { - error_ = base::StringPrintf("Bad node_id_to_clear: %d", - update.node_id_to_clear); - return false; - } // Only destroy the root if the root was replaced and not if it's simply // updated. To figure out if the root was simply updated, we compare the ID // of the new root with the existing root ID. - if (node == root_) { + if (node && node == root_) { if (update.root_id != old_root_id) { // Clear root_ before calling DestroySubtree so that root_ doesn't ever // point to an invalid node. @@ -372,7 +367,7 @@ // If the root has simply been updated, we treat it like an update to any // other node. - if (root_ && (node != root_ || root_updated)) { + if (node && root_ && (node != root_ || root_updated)) { for (int i = 0; i < node->child_count(); ++i) DestroySubtree(node->ChildAtIndex(i), &update_state); std::vector<AXNode*> children;
diff --git a/ui/accessibility/ax_tree_serializer.h b/ui/accessibility/ax_tree_serializer.h index 5b835a4..6a5bf14 100644 --- a/ui/accessibility/ax_tree_serializer.h +++ b/ui/accessibility/ax_tree_serializer.h
@@ -162,6 +162,10 @@ // Visit all of the descendants of |node| once. void WalkAllDescendants(AXSourceNode node); + // Delete the entire client subtree but don't set the did_reset_ flag + // like when Reset() is called. + void InternalReset(); + // The tree source. AXTreeSource<AXSourceNode, AXNodeData, AXTreeData>* tree_; @@ -177,6 +181,11 @@ // The maximum number of nodes to serialize in a given call to // SerializeChanges, or 0 if there's no maximum. size_t max_node_count_ = 0; + + // Keeps track of if Reset() was called. If so, we need to always + // explicitly set node_id_to_clear to ensure that the next serialized + // tree is treated as a completely new tree and not a partial update. + bool did_reset_ = false; }; // In order to keep track of what nodes the client knows about, we keep a @@ -203,6 +212,12 @@ template <typename AXSourceNode, typename AXNodeData, typename AXTreeData> void AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::Reset() { + InternalReset(); + did_reset_ = true; +} + +template <typename AXSourceNode, typename AXNodeData, typename AXTreeData> +void AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::InternalReset() { client_tree_data_ = AXTreeData(); // Normally we use DeleteClientSubtree to remove nodes from the tree, @@ -371,7 +386,7 @@ // If there's no LCA, just tell the client to destroy the whole // tree and then we'll serialize everything from the new root. out_update->node_id_to_clear = client_root_->id; - Reset(); + InternalReset(); } else if (need_delete) { // Otherwise, if we need to reserialize a subtree, first we need // to delete those nodes in our client tree so that @@ -394,7 +409,19 @@ // DumpAccessibilityTreeTest.AccessibilityAriaOwns. WalkAllDescendants(lca); - return SerializeChangedNodes(lca, out_update); + if (!SerializeChangedNodes(lca, out_update)) + return false; + + // If we had a reset, ensure that the old tree is cleared before the client + // unserializes this update. If we didn't do this, there's a chance that + // treating this update as an incremental update could result in some + // reparenting. + if (did_reset_) { + out_update->node_id_to_clear = tree_->GetId(lca); + did_reset_ = false; + } + + return true; } template <typename AXSourceNode, typename AXNodeData, typename AXTreeData> @@ -444,7 +471,8 @@ int id = tree_->GetId(node); ClientTreeNode* client_node = ClientTreeNodeById(id); if (!client_node) { - Reset(); + if (client_root_) + Reset(); client_root_ = new ClientTreeNode(); client_node = client_root_; client_node->id = id;
diff --git a/ui/accessibility/ax_tree_serializer_unittest.cc b/ui/accessibility/ax_tree_serializer_unittest.cc index 023945043..3a5724b 100644 --- a/ui/accessibility/ax_tree_serializer_unittest.cc +++ b/ui/accessibility/ax_tree_serializer_unittest.cc
@@ -389,4 +389,76 @@ ASSERT_EQ(static_cast<size_t>(5), update.nodes.size()); } +// If a tree serializer is reset, that means it doesn't know about +// the state of the client tree anymore. The safest thing to do in +// that circumstance is to force the client to clear everything. +TEST_F(AXTreeSerializerTest, ResetUpdatesNodeIdToClear) { + // (1 (2 (3 (4 (5))))) + treedata0_.root_id = 1; + treedata0_.nodes.resize(5); + treedata0_.nodes[0].id = 1; + treedata0_.nodes[0].child_ids.push_back(2); + treedata0_.nodes[1].id = 2; + treedata0_.nodes[1].child_ids.push_back(3); + treedata0_.nodes[2].id = 3; + treedata0_.nodes[2].child_ids.push_back(4); + treedata0_.nodes[3].id = 4; + treedata0_.nodes[3].child_ids.push_back(5); + treedata0_.nodes[4].id = 5; + + // Node 5 has been reparented from being a child of node 4, + // to a child of node 2. + // (1 (2 (3 (4) 5))) + treedata1_.root_id = 1; + treedata1_.nodes.resize(5); + treedata1_.nodes[0].id = 1; + treedata1_.nodes[0].child_ids.push_back(2); + treedata1_.nodes[1].id = 2; + treedata1_.nodes[1].child_ids.push_back(3); + treedata1_.nodes[1].child_ids.push_back(5); + treedata1_.nodes[2].id = 3; + treedata1_.nodes[2].child_ids.push_back(4); + treedata1_.nodes[3].id = 4; + treedata1_.nodes[4].id = 5; + + CreateTreeSerializer(); + + serializer_->Reset(); + + AXTreeUpdate update; + ASSERT_TRUE(serializer_->SerializeChanges(tree1_->GetFromId(4), &update)); + + // The update should unserialize without errors. + AXTree dst_tree(treedata0_); + EXPECT_TRUE(dst_tree.Unserialize(update)) << dst_tree.error(); +} + +// Ensure that calling Reset doesn't cause any problems if +// the root changes. +TEST_F(AXTreeSerializerTest, ResetWorksWithNewRootId) { + // (1 (2)) + treedata0_.root_id = 1; + treedata0_.nodes.resize(2); + treedata0_.nodes[0].id = 1; + treedata0_.nodes[0].child_ids.push_back(2); + treedata0_.nodes[1].id = 2; + + // (3 (4)) + treedata1_.root_id = 3; + treedata1_.nodes.resize(2); + treedata1_.nodes[0].id = 3; + treedata1_.nodes[0].child_ids.push_back(4); + treedata1_.nodes[1].id = 4; + + CreateTreeSerializer(); + serializer_->Reset(); + + AXTreeUpdate update; + ASSERT_TRUE(serializer_->SerializeChanges(tree1_->GetFromId(4), &update)); + + // The update should unserialize without errors. + AXTree dst_tree(treedata0_); + EXPECT_TRUE(dst_tree.Unserialize(update)) << dst_tree.error(); +} + } // namespace ui
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc index bb1d3a24..b2f6589 100644 --- a/ui/accessibility/ax_tree_unittest.cc +++ b/ui/accessibility/ax_tree_unittest.cc
@@ -323,25 +323,6 @@ update.ToString()); } -TEST(AXTreeTest, DeleteUnknownSubtreeFails) { - AXNodeData root; - root.id = 1; - - AXTreeUpdate initial_state; - initial_state.root_id = 1; - initial_state.nodes.push_back(root); - AXTree tree(initial_state); - - // This should fail because we're asking it to delete - // a subtree rooted at id=2, which doesn't exist. - AXTreeUpdate update; - update.node_id_to_clear = 2; - update.nodes.resize(1); - update.nodes[0].id = 1; - EXPECT_FALSE(tree.Unserialize(update)); - ASSERT_EQ("Bad node_id_to_clear: 2", tree.error()); -} - TEST(AXTreeTest, LeaveOrphanedDeletedSubtreeFails) { AXTreeUpdate initial_state; initial_state.root_id = 1;
diff --git a/ui/accessibility/platform/ax_platform_node.h b/ui/accessibility/platform/ax_platform_node.h index 9430ddb..278107b 100644 --- a/ui/accessibility/platform/ax_platform_node.h +++ b/ui/accessibility/platform/ax_platform_node.h
@@ -11,8 +11,8 @@ #include "build/build_config.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_export.h" +#include "ui/accessibility/ax_mode.h" #include "ui/accessibility/ax_mode_observer.h" -#include "ui/accessibility/ax_modes.h" #include "ui/gfx/native_widget_types.h" namespace ui {
diff --git a/ui/aura/test/event_generator_delegate_aura.cc b/ui/aura/test/event_generator_delegate_aura.cc index 4cc27e4..32ecd0761 100644 --- a/ui/aura/test/event_generator_delegate_aura.cc +++ b/ui/aura/test/event_generator_delegate_aura.cc
@@ -142,6 +142,29 @@ ? &event_targeter_ : EventGeneratorDelegateAura::GetEventSource(target); } + gfx::Point CenterOfTarget(const ui::EventTarget* target) const override { + if (target != &event_targeter_) + return EventGeneratorDelegateAura::CenterOfTarget(target); + return display::Screen::GetScreen() + ->GetPrimaryDisplay() + .bounds() + .CenterPoint(); + } + void ConvertPointFromTarget(const ui::EventTarget* target, + gfx::Point* point) const override { + if (target != &event_targeter_) + EventGeneratorDelegateAura::ConvertPointFromTarget(target, point); + } + void ConvertPointToTarget(const ui::EventTarget* target, + gfx::Point* point) const override { + if (target != &event_targeter_) + EventGeneratorDelegateAura::ConvertPointToTarget(target, point); + } + void ConvertPointFromHost(const ui::EventTarget* hosted_target, + gfx::Point* point) const override { + if (hosted_target != &event_targeter_) + EventGeneratorDelegateAura::ConvertPointFromHost(hosted_target, point); + } void DispatchEventToPointerWatchers(ui::EventTarget* target, const ui::PointerEvent& event) override { // Does nothing as events are injected into mus, which should trigger
diff --git a/ui/base/webui/i18n_source_stream_unittest.cc b/ui/base/webui/i18n_source_stream_unittest.cc index 3484f649..5ef13bc 100644 --- a/ui/base/webui/i18n_source_stream_unittest.cc +++ b/ui/base/webui/i18n_source_stream_unittest.cc
@@ -87,7 +87,7 @@ // Helpful function to initialize the test fixture. void Init() { - output_buffer_ = new net::IOBuffer(output_buffer_size_); + output_buffer_ = base::MakeRefCounted<net::IOBuffer>(output_buffer_size_); std::unique_ptr<net::MockSourceStream> source(new net::MockSourceStream()); source_ = source.get();
diff --git a/ui/ozone/platform/drm/gpu/vulkan_implementation_gbm.cc b/ui/ozone/platform/drm/gpu/vulkan_implementation_gbm.cc index b5173934..2760024 100644 --- a/ui/ozone/platform/drm/gpu/vulkan_implementation_gbm.cc +++ b/ui/ozone/platform/drm/gpu/vulkan_implementation_gbm.cc
@@ -31,7 +31,7 @@ "VK_KHR_external_fence_capabilities", "VK_KHR_get_physical_device_properties2", }; - if (!vulkan_instance_.Initialize(required_extensions)) { + if (!vulkan_instance_.Initialize(required_extensions, {})) { vulkan_instance_.Destroy(); return false; }
diff --git a/ui/ozone/platform/scenic/BUILD.gn b/ui/ozone/platform/scenic/BUILD.gn index 4ba23191..faedc7c1 100644 --- a/ui/ozone/platform/scenic/BUILD.gn +++ b/ui/ozone/platform/scenic/BUILD.gn
@@ -4,6 +4,10 @@ assert(is_fuchsia) +import("//gpu/vulkan/features.gni") + +visibility = [ "//ui/ozone/*" ] + source_set("scenic") { sources = [ "client_native_pixmap_factory_scenic.cc", @@ -44,4 +48,13 @@ "//ui/ozone/common", "//ui/platform_window", ] + + if (enable_vulkan) { + sources += [ + "vulkan_implementation_scenic.cc", + "vulkan_implementation_scenic.h", + "vulkan_magma.h", + ] + defines += [ "VK_USE_PLATFORM_MAGMA_KHR" ] + } }
diff --git a/ui/ozone/platform/scenic/scenic_session.cc b/ui/ozone/platform/scenic/scenic_session.cc index 4d186dd..c29bc82c 100644 --- a/ui/ozone/platform/scenic/scenic_session.cc +++ b/ui/ozone/platform/scenic/scenic_session.cc
@@ -103,6 +103,21 @@ return image_id; } +ScenicSession::ResourceId ScenicSession::CreateImagePipe( + fidl::InterfaceRequest<fuchsia::images::ImagePipe> request) { + fuchsia::ui::gfx::ImagePipeArgs image_pipe; + image_pipe.image_pipe_request = std::move(request); + + fuchsia::ui::gfx::ResourceArgs resource; + resource.set_image_pipe(std::move(image_pipe)); + + ResourceId image_pipe_id = AllocateResourceId(); + EnqueueGfxCommand( + NewCreateResourceCommand(image_pipe_id, std::move(resource))); + + return image_pipe_id; +} + ScenicSession::ResourceId ScenicSession::ImportResource( fuchsia::ui::gfx::ImportSpec spec, zx::eventpair import_token) {
diff --git a/ui/ozone/platform/scenic/scenic_session.h b/ui/ozone/platform/scenic/scenic_session.h index e63997c..ad81b47 100644 --- a/ui/ozone/platform/scenic/scenic_session.h +++ b/ui/ozone/platform/scenic/scenic_session.h
@@ -59,6 +59,8 @@ ResourceId CreateImage(ResourceId memory_id, ResourceId memory_offset, fuchsia::images::ImageInfo info); + ResourceId CreateImagePipe( + fidl::InterfaceRequest<fuchsia::images::ImagePipe> request); ResourceId ImportResource(fuchsia::ui::gfx::ImportSpec spec, zx::eventpair import_token); ResourceId CreateEntityNode();
diff --git a/ui/ozone/platform/scenic/scenic_surface_factory.cc b/ui/ozone/platform/scenic/scenic_surface_factory.cc index 636f3a8..7b444c4 100644 --- a/ui/ozone/platform/scenic/scenic_surface_factory.cc +++ b/ui/ozone/platform/scenic/scenic_surface_factory.cc
@@ -15,6 +15,10 @@ #include "ui/ozone/platform/scenic/scenic_window_canvas.h" #include "ui/ozone/platform/scenic/scenic_window_manager.h" +#if BUILDFLAG(ENABLE_VULKAN) +#include "ui/ozone/platform/scenic/vulkan_implementation_scenic.h" +#endif + namespace ui { namespace { @@ -100,4 +104,11 @@ return new ScenicPixmap(widget, size, format); } +#if BUILDFLAG(ENABLE_VULKAN) +std::unique_ptr<gpu::VulkanImplementation> +ScenicSurfaceFactory::CreateVulkanImplementation() { + return std::make_unique<ui::VulkanImplementationScenic>(window_manager_); +} +#endif + } // namespace ui
diff --git a/ui/ozone/platform/scenic/scenic_surface_factory.h b/ui/ozone/platform/scenic/scenic_surface_factory.h index 077b513..016b09f 100644 --- a/ui/ozone/platform/scenic/scenic_surface_factory.h +++ b/ui/ozone/platform/scenic/scenic_surface_factory.h
@@ -9,6 +9,7 @@ #include <vector> #include "base/macros.h" +#include "gpu/vulkan/buildflags.h" #include "ui/ozone/public/gl_ozone.h" #include "ui/ozone/public/surface_factory_ozone.h" @@ -33,6 +34,10 @@ gfx::Size size, gfx::BufferFormat format, gfx::BufferUsage usage) override; +#if BUILDFLAG(ENABLE_VULKAN) + std::unique_ptr<gpu::VulkanImplementation> CreateVulkanImplementation() + override; +#endif private: ScenicWindowManager* const window_manager_;
diff --git a/ui/ozone/platform/scenic/scenic_window.cc b/ui/ozone/platform/scenic/scenic_window.cc index 13b3d78..3f9f6264 100644 --- a/ui/ozone/platform/scenic/scenic_window.cc +++ b/ui/ozone/platform/scenic/scenic_window.cc
@@ -225,6 +225,7 @@ scenic_session_.SetNodeShape(shape_id_, rect_id); scenic_session_.SetNodeTranslation(shape_id_, translation); scenic_session_.ReleaseResource(rect_id); + scenic_session_.Present(); delegate_->OnBoundsChanged(size_rect); }
diff --git a/ui/ozone/platform/scenic/scenic_window.h b/ui/ozone/platform/scenic/scenic_window.h index 912fd04..8aecd40 100644 --- a/ui/ozone/platform/scenic/scenic_window.h +++ b/ui/ozone/platform/scenic/scenic_window.h
@@ -43,8 +43,7 @@ ScenicSession::ResourceId node_id() const { return node_id_; } float device_pixel_ratio() const { return device_pixel_ratio_; } - // Overrides texture of the window. This is used by ScenicWindowCanvas. - // TODO(spang): Deprecate software rendering on fuchsia. + // Sets texture of the window to a scenic resource. void SetTexture(ScenicSession::ResourceId texture); // PlatformWindow implementation.
diff --git a/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc b/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc new file mode 100644 index 0000000..a8af3f8b --- /dev/null +++ b/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc
@@ -0,0 +1,132 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/ozone/platform/scenic/vulkan_implementation_scenic.h" + +#include <lib/zx/channel.h> + +#include "base/files/file_path.h" +#include "base/fuchsia/fuchsia_logging.h" +#include "base/native_library.h" +#include "gpu/vulkan/vulkan_function_pointers.h" +#include "gpu/vulkan/vulkan_instance.h" +#include "gpu/vulkan/vulkan_surface.h" +#include "ui/gfx/gpu_fence.h" +#include "ui/ozone/platform/scenic/scenic_window.h" +#include "ui/ozone/platform/scenic/scenic_window_manager.h" +#include "ui/ozone/platform/scenic/vulkan_magma.h" + +namespace ui { + +VulkanImplementationScenic::VulkanImplementationScenic( + ScenicWindowManager* scenic_window_manager) + : scenic_window_manager_(scenic_window_manager) {} + +VulkanImplementationScenic::~VulkanImplementationScenic() = default; + +bool VulkanImplementationScenic::InitializeVulkanInstance() { + base::NativeLibraryLoadError error; + base::NativeLibrary handle = + base::LoadNativeLibrary(base::FilePath("libvulkan.so"), &error); + if (!handle) { + LOG(ERROR) << "Failed to load vulkan: " << error.ToString(); + return false; + } + + gpu::VulkanFunctionPointers* vulkan_function_pointers = + gpu::GetVulkanFunctionPointers(); + vulkan_function_pointers->vulkan_loader_library_ = handle; + std::vector<const char*> required_extensions = { + VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_MAGMA_SURFACE_EXTENSION_NAME, + }; + std::vector<const char*> required_layers = { + "VK_LAYER_GOOGLE_image_pipe_swapchain", + }; + if (!vulkan_instance_.Initialize(required_extensions, required_layers)) { + vulkan_instance_.Destroy(); + return false; + } + + vkCreateMagmaSurfaceKHR_ = vkGetInstanceProcAddr( + vulkan_instance_.vk_instance(), "vkCreateMagmaSurfaceKHR"); + if (!vkCreateMagmaSurfaceKHR_) { + vulkan_instance_.Destroy(); + return false; + } + + vkGetPhysicalDeviceMagmaPresentationSupportKHR_ = + vkGetInstanceProcAddr(vulkan_instance_.vk_instance(), + "vkGetPhysicalDeviceMagmaPresentationSupportKHR"); + if (!vkGetPhysicalDeviceMagmaPresentationSupportKHR_) { + vulkan_instance_.Destroy(); + return false; + } + + return true; +} + +VkInstance VulkanImplementationScenic::GetVulkanInstance() { + return vulkan_instance_.vk_instance(); +} + +std::unique_ptr<gpu::VulkanSurface> +VulkanImplementationScenic::CreateViewSurface(gfx::AcceleratedWidget window) { + ScenicWindow* scenic_window = scenic_window_manager_->GetWindow(window); + if (!scenic_window) + return nullptr; + ScenicSession* scenic_session = scenic_window->scenic_session(); + fuchsia::images::ImagePipePtr image_pipe; + ScenicSession::ResourceId image_pipe_id = + scenic_session->CreateImagePipe(image_pipe.NewRequest()); + scenic_window->SetTexture(image_pipe_id); + scenic_session->ReleaseResource(image_pipe_id); + scenic_session->Present(); + + VkSurfaceKHR surface; + VkMagmaSurfaceCreateInfoKHR surface_create_info = {}; + surface_create_info.sType = VK_STRUCTURE_TYPE_MAGMA_SURFACE_CREATE_INFO_KHR; + surface_create_info.imagePipeHandle = + image_pipe.Unbind().TakeChannel().release(); + + VkResult result = + reinterpret_cast<PFN_vkCreateMagmaSurfaceKHR>(vkCreateMagmaSurfaceKHR_)( + GetVulkanInstance(), &surface_create_info, nullptr, &surface); + if (result != VK_SUCCESS) { + // This shouldn't fail, and we don't know whether imagePipeHandle was closed + // if it does. + LOG(FATAL) << "vkCreateMagmaSurfaceKHR failed: " << result; + } + + return std::make_unique<gpu::VulkanSurface>(GetVulkanInstance(), surface); +} + +bool VulkanImplementationScenic::GetPhysicalDevicePresentationSupport( + VkPhysicalDevice physical_device, + const std::vector<VkQueueFamilyProperties>& queue_family_properties, + uint32_t queue_family_index) { + // TODO(spang): vkGetPhysicalDeviceMagmaPresentationSupportKHR returns false + // here. Use it once it is fixed. + NOTIMPLEMENTED(); + return true; +} + +std::vector<const char*> +VulkanImplementationScenic::GetRequiredDeviceExtensions() { + return {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; +} + +VkFence VulkanImplementationScenic::CreateVkFenceForGpuFence( + VkDevice vk_device) { + NOTIMPLEMENTED(); + return VK_NULL_HANDLE; +} + +std::unique_ptr<gfx::GpuFence> +VulkanImplementationScenic::ExportVkFenceToGpuFence(VkDevice vk_device, + VkFence vk_fence) { + NOTIMPLEMENTED(); + return nullptr; +} + +} // namespace ui
diff --git a/ui/ozone/platform/scenic/vulkan_implementation_scenic.h b/ui/ozone/platform/scenic/vulkan_implementation_scenic.h new file mode 100644 index 0000000..ecd61cd --- /dev/null +++ b/ui/ozone/platform/scenic/vulkan_implementation_scenic.h
@@ -0,0 +1,49 @@ +// 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. + +#ifndef UI_OZONE_PLATFORM_SCENIC_VULKAN_IMPLEMENTATION_SCENIC_H_ +#define UI_OZONE_PLATFORM_SCENIC_VULKAN_IMPLEMENTATION_SCENIC_H_ + +#include <memory> + +#include "gpu/vulkan/vulkan_implementation.h" +#include "gpu/vulkan/vulkan_instance.h" + +namespace ui { + +class ScenicWindowManager; + +class VulkanImplementationScenic : public gpu::VulkanImplementation { + public: + VulkanImplementationScenic(ScenicWindowManager* scenic_window_manager); + ~VulkanImplementationScenic() override; + + // VulkanImplementation: + bool InitializeVulkanInstance() override; + VkInstance GetVulkanInstance() override; + std::unique_ptr<gpu::VulkanSurface> CreateViewSurface( + gfx::AcceleratedWidget window) override; + bool GetPhysicalDevicePresentationSupport( + VkPhysicalDevice device, + const std::vector<VkQueueFamilyProperties>& queue_family_properties, + uint32_t queue_family_index) override; + std::vector<const char*> GetRequiredDeviceExtensions() override; + VkFence CreateVkFenceForGpuFence(VkDevice vk_device) override; + std::unique_ptr<gfx::GpuFence> ExportVkFenceToGpuFence( + VkDevice vk_device, + VkFence vk_fence) override; + + private: + ScenicWindowManager* const scenic_window_manager_; + gpu::VulkanInstance vulkan_instance_; + + PFN_vkVoidFunction vkCreateMagmaSurfaceKHR_ = nullptr; + PFN_vkVoidFunction vkGetPhysicalDeviceMagmaPresentationSupportKHR_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(VulkanImplementationScenic); +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_SCENIC_VULKAN_IMPLEMENTATION_SCENIC_H_
diff --git a/ui/ozone/platform/scenic/vulkan_magma.h b/ui/ozone/platform/scenic/vulkan_magma.h new file mode 100644 index 0000000..df222e8 --- /dev/null +++ b/ui/ozone/platform/scenic/vulkan_magma.h
@@ -0,0 +1,159 @@ +// 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. + +#ifndef UI_OZONE_PLATFORM_SCENIC_VULKAN_MAGMA_H_ +#define UI_OZONE_PLATFORM_SCENIC_VULKAN_MAGMA_H_ + +// These definitions are from +// https://fuchsia.googlesource.com/third_party/vulkan_loader_and_validation_layers/+/master/include/vulkan/vulkan.h +// TODO(spang): Remove these once the definitions go upstream. + +#include <vulkan/vulkan.h> + +#if !defined(VK_KHR_external_memory_fuchsia) +#define VK_KHR_external_memory_fuchsia 1 +#define VK_KHR_EXTERNAL_MEMORY_FUCHSIA_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_MEMORY_FUCHSIA_EXTENSION_NAME \ + "VK_KHR_external_memory_fuchsia" + +typedef struct VkImportMemoryFuchsiaHandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBitsKHR handleType; + uint32_t handle; +} VkImportMemoryFuchsiaHandleInfoKHR; + +typedef struct VkMemoryFuchsiaHandlePropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryFuchsiaHandlePropertiesKHR; + +typedef struct VkMemoryGetFuchsiaHandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBitsKHR handleType; +} VkMemoryGetFuchsiaHandleInfoKHR; + +typedef VkResult(VKAPI_PTR* PFN_vkGetMemoryFuchsiaHandleKHR)( + VkDevice device, + const VkMemoryGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, + uint32_t* pFuchsiaHandle); +typedef VkResult(VKAPI_PTR* PFN_vkGetMemoryFuchsiaHandlePropertiesKHR)( + VkDevice device, + VkExternalMemoryHandleTypeFlagBitsKHR handleType, + uint32_t fuchsiaHandle, + VkMemoryFuchsiaHandlePropertiesKHR* pMemoryFuchsiaHandleProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFuchsiaHandleKHR( + VkDevice device, + const VkMemoryGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, + uint32_t* pFuchsiaHandle); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFuchsiaHandlePropertiesKHR( + VkDevice device, + VkExternalMemoryHandleTypeFlagBitsKHR handleType, + uint32_t fuchsiaHandle, + VkMemoryFuchsiaHandlePropertiesKHR* pMemoryFuchsiaHandleProperties); +#endif + +#endif // !defined(VK_KHR_external_memory_fuchsia) + +#if !defined(VK_KHR_external_semaphore_fuchsia) +#define VK_KHR_external_semaphore_fuchsia 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_FUCHSIA_SPEC_VERSION 1 +#define VK_KHR_EXTERNAL_SEMAPHORE_FUCHSIA_EXTENSION_NAME \ + "VK_KHR_external_semaphore_fuchsia" + +typedef struct VkImportSemaphoreFuchsiaHandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkSemaphoreImportFlagsKHR flags; + VkExternalSemaphoreHandleTypeFlagBitsKHR handleType; + uint32_t handle; +} VkImportSemaphoreFuchsiaHandleInfoKHR; + +typedef struct VkSemaphoreGetFuchsiaHandleInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkExternalSemaphoreHandleTypeFlagBitsKHR handleType; +} VkSemaphoreGetFuchsiaHandleInfoKHR; + +typedef VkResult(VKAPI_PTR* PFN_vkImportSemaphoreFuchsiaHandleKHR)( + VkDevice device, + const VkImportSemaphoreFuchsiaHandleInfoKHR* + pImportSemaphoreFuchsiaHandleInfo); +typedef VkResult(VKAPI_PTR* PFN_vkGetSemaphoreFuchsiaHandleKHR)( + VkDevice device, + const VkSemaphoreGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, + uint32_t* pFuchsiaHandle); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL +vkImportSemaphoreFuchsiaHandleKHR(VkDevice device, + const VkImportSemaphoreFuchsiaHandleInfoKHR* + pImportSemaphoreFuchsiaHandleInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFuchsiaHandleKHR( + VkDevice device, + const VkSemaphoreGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo, + uint32_t* pFuchsiaHandle); +#endif + +#endif // !defined(VK_KHR_external_semaphore_fuchsia) + +#if defined(VK_USE_PLATFORM_MAGMA_KHR) && !defined(VK_KHR_magma_surface) +#define VK_KHR_magma_surface 1 +#define VK_KHR_MAGMA_SURFACE_SPEC_VERSION 1 +#define VK_KHR_MAGMA_SURFACE_EXTENSION_NAME "VK_KHR_magma_surface" + +typedef VkFlags VkMagmaSurfaceCreateFlagsKHR; + +typedef struct VkMagmaSurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t imagePipeHandle; + uint32_t width; + uint32_t height; +} VkMagmaSurfaceCreateInfoKHR; + +typedef VkResult(VKAPI_PTR* PFN_vkCreateMagmaSurfaceKHR)( + VkInstance instance, + const VkMagmaSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +typedef VkBool32(VKAPI_PTR* PFN_vkGetPhysicalDeviceMagmaPresentationSupportKHR)( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL +vkCreateMagmaSurfaceKHR(VkInstance instance, + const VkMagmaSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); + +VKAPI_ATTR VkBool32 VKAPI_CALL +vkGetPhysicalDeviceMagmaPresentationSupportKHR(VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex); +#endif +#endif // defined(VK_USE_PLATFORM_MAGMA_KHR) && !defined(VK_KHR_magma_surface) + +#if !defined(VK_GOOGLE_image_usage_scanout) + +#define VK_GOOGLE_image_usage_scanout 1 +#define VK_GOOGLE_IMAGE_USAGE_SCANOUT_SPEC_VERSION 1 +#define VK_GOOGLE_IMAGE_USAGE_SCANOUT_EXTENSION_NAME \ + "VK_GOOGLE_image_usage_scanout" + +#define VK_STRUCTURE_TYPE_MAGMA_SURFACE_CREATE_INFO_KHR \ + (static_cast<VkStructureType>(1001002000)) + +#endif // !defined(VK_GOOGLE_image_usage_scanout) + +#endif // UI_OZONE_PLATFORM_MAGMA_VULKAN_MAGMA_H_
diff --git a/ui/views/accessibility/view_ax_platform_node_delegate.cc b/ui/views/accessibility/view_ax_platform_node_delegate.cc index 4f212d0..9b7a15cd 100644 --- a/ui/views/accessibility/view_ax_platform_node_delegate.cc +++ b/ui/views/accessibility/view_ax_platform_node_delegate.cc
@@ -306,7 +306,8 @@ // Search child widgets first, since they're on top in the z-order. std::vector<Widget*> child_widgets; - PopulateChildWidgetVector(&child_widgets, nullptr); + bool is_tab_modal_showing; + PopulateChildWidgetVector(&child_widgets, &is_tab_modal_showing); for (Widget* child_widget : child_widgets) { View* child_root_view = child_widget->GetRootView(); gfx::Point point(x, y);
diff --git a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js index ec1ac2d..4540331 100644 --- a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js +++ b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
@@ -271,7 +271,7 @@ var options = this.querySelectorAll('.dropdown-item'); var numOptions = options.length; var focusedIndex = - Array.prototype.indexOf.call(options, this.root.activeElement); + Array.prototype.indexOf.call(options, getDeepActiveElement()); // Handle case where nothing is focused and up is pressed. if (focusedIndex === -1 && step === -1)
diff --git a/ui/webui/resources/js/util.js b/ui/webui/resources/js/util.js index a5099bf9..7139d9b 100644 --- a/ui/webui/resources/js/util.js +++ b/ui/webui/resources/js/util.js
@@ -33,6 +33,18 @@ } /** + * @return {?Element} The currently focused element (including elements that are + * behind a shadow root), or null if nothing is focused. + */ +function getDeepActiveElement() { + var a = document.activeElement; + while (a && a.shadowRoot && a.shadowRoot.activeElement) { + a = a.shadowRoot.activeElement; + } + return a; +} + +/** * Add an accessible message to the page that will be announced to * users who have spoken feedback on, but will be invisible to all * other users. It's removed right away so it doesn't clutter the DOM.
diff --git a/webrunner/app/main.cc b/webrunner/app/main.cc index 2f5b2ee4..214fbe6 100644 --- a/webrunner/app/main.cc +++ b/webrunner/app/main.cc
@@ -51,8 +51,12 @@ base::MessageLoopForIO message_loop; auto web_context = CreateContext(); + + // Run until the WebContentRunner is ready to exit. base::RunLoop run_loop; - webrunner::WebContentRunner runner(std::move(web_context)); + + webrunner::WebContentRunner runner(std::move(web_context), + run_loop.QuitClosure()); base::fuchsia::ServiceDirectory* directory = base::fuchsia::ServiceDirectory::GetDefault(); @@ -61,7 +65,6 @@ base::fuchsia::ScopedServiceBinding<fuchsia::sys::Runner> runner_binding( directory, &runner); - // Quit the process after the app manager closes the Runner connection. runner_binding.SetOnLastClientCallback(run_loop.QuitClosure()); // The RunLoop runs until all Components have been closed, at which point the
diff --git a/webrunner/app/web_content_runner.cc b/webrunner/app/web_content_runner.cc index a134993..9c968e6 100644 --- a/webrunner/app/web_content_runner.cc +++ b/webrunner/app/web_content_runner.cc
@@ -16,9 +16,12 @@ namespace webrunner { -WebContentRunner::WebContentRunner(chromium::web::ContextPtr context) - : context_(std::move(context)) { +WebContentRunner::WebContentRunner(chromium::web::ContextPtr context, + base::OnceClosure on_idle_closure) + : context_(std::move(context)), + on_idle_closure_(std::move(on_idle_closure)) { DCHECK(context_); + DCHECK(on_idle_closure_); } WebContentRunner::~WebContentRunner() = default; @@ -36,6 +39,11 @@ void WebContentRunner::DestroyComponent(ComponentControllerImpl* component) { controllers_.erase(controllers_.find(component)); + + // Quit the RunLoop if there are no more connected clients. + if (controllers_.empty() && on_idle_closure_) { + std::move(on_idle_closure_).Run(); + } } } // namespace webrunner
diff --git a/webrunner/app/web_content_runner.h b/webrunner/app/web_content_runner.h index e5a46ae..93c50ec 100644 --- a/webrunner/app/web_content_runner.h +++ b/webrunner/app/web_content_runner.h
@@ -24,7 +24,10 @@ public: // |content|: Context (e.g. persisted profile storage) under which all web // content launched through this Runner instance will be run. - explicit WebContentRunner(chromium::web::ContextPtr context); + // |on_idle_closure|: A callback which is invoked when the WebContentRunner + // has entered an idle state and may be safely torn down. + WebContentRunner(chromium::web::ContextPtr context, + base::OnceClosure on_idle_closure); ~WebContentRunner() override; chromium::web::Context* context() { return context_.get(); } @@ -43,6 +46,7 @@ chromium::web::ContextPtr context_; std::set<std::unique_ptr<ComponentControllerImpl>, base::UniquePtrComparator> controllers_; + base::OnceClosure on_idle_closure_; DISALLOW_COPY_AND_ASSIGN(WebContentRunner); };