diff --git a/DEPS b/DEPS index a358ddd..c941902 100644 --- a/DEPS +++ b/DEPS
@@ -122,10 +122,6 @@ # Wildcards are supported (e.g. "qemu.*"). 'checkout_fuchsia_boot_images': "qemu.x64,qemu.arm64", - # By default, do not check out files required to run fuchsia tests in - # qemu on linux-arm64 machines. - 'checkout_fuchsia_for_arm64_host': False, - # By Default, do not checkout AEMU, as it is too big. This can be overridden # e.g. with custom_vars. # TODO(chonggu): Delete once AEMU package is small enough. @@ -172,11 +168,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': 'a53e47fe9483117e65e05a006e88c2cccf974a1a', + 'skia_revision': '0fd4f01b9b83f9c24e1e07ba96124ae8e3836a62', # 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': 'fdd7f4213eb74e4f796b3a9ef2cddb51e93bbfe9', + 'v8_revision': 'f2af41c8eab1506a56d1e12051aba072b7b0c5cd', # 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. @@ -184,15 +180,15 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '50919254cbc716d09703f93c2d38a0368809dbda', + 'angle_revision': '012d15196023467be913ef6d537417be91e68e16', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'c03ce008b9fe5056e3dc225473602419e987e94c', + 'swiftshader_revision': '31edef751a8d8428db1fc9e0f68c345ab987811f', # 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': '636832d9a6668392ecea50fd43fcd06c4a3a2b79', + 'pdfium_revision': '5eb17d38f7f7021a08c13cf986f68a363a4d82f2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -235,7 +231,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': 'd9164777415c9e1611a038676c2eef56540b120a', + 'catapult_revision': '56af378833d9fbcf30b7976ce97d8943879505b6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -303,15 +299,15 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'shaderc_revision': 'f7e05c734266528849e861da7bee3ac734df80e6', + 'shaderc_revision': 'f0bfbce62d427c755b767aa09e306346189d7c22', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '16787735601c0b5fe9b485fb79f6c647a51281fd', + 'dawn_revision': '600a26d50a04d82cade2f52c79a2d7ad9e71b89b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': '7a4d20901fbbf2cf46e84d363350608873f2594f', + 'quiche_revision': 'ac35d459a91137d44e9418cc41e808a6d9bb466d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -871,7 +867,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'fc61fb037d2c47749e2485c383ab86b372b66055', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9b2e22593bbfa8d2774e955c2da25c2caa58bba5', 'condition': 'checkout_linux', }, @@ -896,7 +892,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '039522eb577eb99dc9b931c2c63e327239aa0c8a', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'ea1884b651e69975e897b15cf2063f36317538a4', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -945,19 +941,6 @@ 'condition': 'checkout_linux', }, - # TODO(steveroe): Get this from GCS instead of CIPD once the arm64 sdk is - # released using the same version specified in build/fuchsia/linux.sdk.sha1. - 'src/third_party/fuchsia-sdk-arm64': { - 'packages': [ - { - 'package': 'fuchsia/sdk/core/linux-arm64', - 'version': 'xbqDSJKkLORclZW8h9et17dVsOjaxurf7RElMu0fGvUC', - }, - ], - 'condition': 'host_os == "linux" and (checkout_fuchsia and checkout_fuchsia_for_arm64_host)', - 'dep_type': 'cipd', - }, - 'src/third_party/grpc/src': { 'url': Var('chromium_git') + '/external/github.com/grpc/grpc.git' + '@' + '74b981a6a3d9ba17f3acae1d72b9109325ef656d', }, @@ -1311,7 +1294,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'e9709db85ca95f1cc0cc65d9a2a0928ea9184841', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '27521bd0f067af6d75d4b80478d46fcb17314b33', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1352,17 +1335,6 @@ 'src/third_party/pywebsocket/src': Var('chromium_git') + '/external/github.com/google/pywebsocket.git' + '@' + '2d7b73c3acbd0f41dcab487ae5c97c6feae06ce2', - 'src/third_party/qemu-linux-arm64': { - 'packages': [ - { - 'package': 'fuchsia/qemu/linux-arm64', - 'version': 'b1b61a39e3ab0935cd030f27e01740578b04b967' - }, - ], - 'condition': 'host_os == "linux" and (checkout_fuchsia and checkout_fuchsia_for_arm64_host)', - 'dep_type': 'cipd', - }, - 'src/third_party/qemu-linux-x64': { 'packages': [ { @@ -1579,7 +1551,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0db29887459d7d2d5509f8f72ee0081b1138fb14', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8f729062729eacc875332a3bc62777f6ba78fadb', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/renderer/js_java_interaction/js_java_configurator.cc b/android_webview/renderer/js_java_interaction/js_java_configurator.cc index 0c5fd29..46280d30 100644 --- a/android_webview/renderer/js_java_interaction/js_java_configurator.cc +++ b/android_webview/renderer/js_java_interaction/js_java_configurator.cc
@@ -83,7 +83,8 @@ mojo::PendingAssociatedReceiver<mojom::JsJavaConfigurator> pending_receiver) { receiver_.Bind(std::move(pending_receiver), - render_frame()->GetTaskRunner(blink::TaskType::kInternalIPC)); + render_frame()->GetTaskRunner( + blink::TaskType::kInternalNavigationAssociated)); } mojom::JsToJavaMessaging* JsJavaConfigurator::GetJsToJavaMessage(
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index f5bb92c..ae8c1a3c 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -858,11 +858,6 @@ std::move(callback)); } -void AppListControllerImpl::UpdateAfterHomeLauncherShown() { - // Show or hide the expand arrow view. - UpdateExpandArrowVisibility(); -} - base::Optional<base::TimeDelta> AppListControllerImpl::GetOptionalAnimationDuration() { if (model_->state() == ash::AppListState::kStateEmbeddedAssistant) { @@ -1407,6 +1402,12 @@ last_target_visible_ = real_target_visibility; last_target_visible_display_id_ = display_id; + // Update the arrow visibility when starting to show the home screen + // (presumably, the visibility has already been updated if home is being + // hidden). + if (real_target_visibility && IsTabletMode()) + UpdateExpandArrowVisibility(); + if (client_) client_->OnAppListVisibilityWillChange(real_target_visibility);
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h index 457f3e391..799d4e8a 100644 --- a/ash/app_list/app_list_controller_impl.h +++ b/ash/app_list/app_list_controller_impl.h
@@ -283,7 +283,6 @@ float opacity, base::Optional<AnimationInfo> animation_info, UpdateAnimationSettingsCallback callback) override; - void UpdateAfterHomeLauncherShown() override; base::Optional<base::TimeDelta> GetOptionalAnimationDuration() override; void OnHomeLauncherAnimationComplete(bool shown, int64_t display_id) override; void OnHomeLauncherTargetPositionChanged(bool showing,
diff --git a/ash/app_list/app_list_controller_impl_unittest.cc b/ash/app_list/app_list_controller_impl_unittest.cc index 8a064458..758569f 100644 --- a/ash/app_list/app_list_controller_impl_unittest.cc +++ b/ash/app_list/app_list_controller_impl_unittest.cc
@@ -155,10 +155,8 @@ // Activate w1 then press home launcher button. Expand arrow view should show // because w1 still exists. wm::ActivateWindow(w1.get()); - Shell::Get() - ->home_screen_controller() - ->home_launcher_gesture_handler() - ->ShowHomeLauncher(display::Screen::GetScreen()->GetPrimaryDisplay()); + Shell::Get()->home_screen_controller()->GoHome( + display::Screen::GetScreen()->GetPrimaryDisplay().id()); EXPECT_EQ(WindowStateType::kMinimized, WindowState::Get(w1.get())->GetStateType()); EXPECT_TRUE(GetExpandArrowViewVisibility()); @@ -867,10 +865,8 @@ // hidden. std::unique_ptr<aura::Window> w( AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400))); - Shell::Get() - ->home_screen_controller() - ->home_launcher_gesture_handler() - ->ShowHomeLauncher(display::Screen::GetScreen()->GetPrimaryDisplay()); + Shell::Get()->home_screen_controller()->GoHome( + display::Screen::GetScreen()->GetPrimaryDisplay().id()); EXPECT_FALSE(w->IsVisible()); EXPECT_EQ(AppListViewState::kFullscreenAllApps, GetAppListView()->app_list_state()); @@ -940,10 +936,8 @@ // hidden. std::unique_ptr<aura::Window> w( AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400))); - Shell::Get() - ->home_screen_controller() - ->home_launcher_gesture_handler() - ->ShowHomeLauncher(display::Screen::GetScreen()->GetPrimaryDisplay()); + Shell::Get()->home_screen_controller()->GoHome( + display::Screen::GetScreen()->GetPrimaryDisplay().id()); EXPECT_FALSE(w->IsVisible()); EXPECT_EQ(AppListViewState::kFullscreenAllApps, GetAppListView()->app_list_state());
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc index 90b5d65..e42aec4 100644 --- a/ash/app_list/views/app_list_view.cc +++ b/ash/app_list/views/app_list_view.cc
@@ -1860,6 +1860,16 @@ } float AppListView::GetAppListTransitionProgress(int flags) const { + // During transition between home and overview in tablet mode, the app list + // widget gets scaled down from full screen state - if this is the case, + // the app list layout should match the current app list state, so return + // the progress for the current app list state. + const gfx::Transform transform = GetWidget()->GetLayer()->transform(); + if (is_tablet_mode_ && transform.IsScaleOrTranslation() && + !transform.IsIdentityOrTranslation()) { + return GetTransitionProgressForState(app_list_state_); + } + int current_height = GetCurrentAppListHeight(); if (flags & kProgressFlagWithTransform) { current_height -=
diff --git a/ash/home_screen/home_launcher_gesture_handler.cc b/ash/home_screen/home_launcher_gesture_handler.cc index 36d40fd8..c48538a 100644 --- a/ash/home_screen/home_launcher_gesture_handler.cc +++ b/ash/home_screen/home_launcher_gesture_handler.cc
@@ -501,8 +501,6 @@ } if (is_final_state_show) { - home_screen_delegate->UpdateAfterHomeLauncherShown(); - std::vector<aura::Window*> windows_to_hide_minimize; windows_to_hide_minimize.push_back(GetActiveWindow());
diff --git a/ash/home_screen/home_screen_delegate.h b/ash/home_screen/home_screen_delegate.h index 495a2e4..683284e 100644 --- a/ash/home_screen/home_screen_delegate.h +++ b/ash/home_screen/home_screen_delegate.h
@@ -90,9 +90,6 @@ base::Optional<AnimationInfo> animation_info, UpdateAnimationSettingsCallback callback) = 0; - // Updates the home launcher view after its show animation has completed. - virtual void UpdateAfterHomeLauncherShown() = 0; - // Returns an optional animation duration which is going to be used to set // the transition animation if provided. virtual base::Optional<base::TimeDelta> GetOptionalAnimationDuration() = 0;
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc index 8754954..26daf257 100644 --- a/ash/wm/desks/desks_unittests.cc +++ b/ash/wm/desks/desks_unittests.cc
@@ -4,13 +4,17 @@ #include <vector> +#include "ash/display/screen_orientation_controller.h" #include "ash/display/screen_orientation_controller_test_api.h" #include "ash/multi_user/multi_user_window_manager_impl.h" #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/event_rewriter_controller.h" #include "ash/public/cpp/multi_user_window_manager.h" #include "ash/public/cpp/multi_user_window_manager_delegate.h" +#include "ash/public/cpp/shelf_types.h" #include "ash/screen_util.h" +#include "ash/shelf/shelf.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/sticky_keys/sticky_keys_controller.h" #include "ash/style/ash_color_provider.h" @@ -43,12 +47,14 @@ #include "ash/wm/workspace_controller.h" #include "base/stl_util.h" #include "base/test/scoped_feature_list.h" +#include "base/threading/thread_task_runner_handle.h" #include "components/session_manager/session_manager_types.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/window_parenting_client.h" #include "ui/aura/test/test_window_delegate.h" #include "ui/base/ui_base_types.h" #include "ui/chromeos/events/event_rewriter_chromeos.h" +#include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor_extra/shadow.h" #include "ui/display/display.h" #include "ui/display/test/display_manager_test_api.h" @@ -2042,6 +2048,48 @@ EXPECT_TRUE(controller->desks()[0]->is_active()); } +TEST_F(DesksTest, AutohiddenShelfAnimatesAfterDeskSwitch) { + Shelf* shelf = GetPrimaryShelf(); + ShelfWidget* shelf_widget = shelf->shelf_widget(); + const gfx::Rect shown_shelf_bounds = shelf_widget->GetWindowBoundsInScreen(); + + shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + + // Enable animations so that we can make sure that they occur. + ui::ScopedAnimationDurationScaleMode regular_animations( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + + NewDesk(); + + // Create a window on the first desk so that the shelf will auto-hide there. + std::unique_ptr<views::Widget> widget = CreateTestWidget(); + widget->Maximize(); + // LayoutShelf() forces the animation to completion, at which point the + // shelf should go off the screen. + shelf->shelf_layout_manager()->LayoutShelf(); + EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState()); + EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState()); + const gfx::Rect hidden_shelf_bounds = shelf_widget->GetWindowBoundsInScreen(); + EXPECT_NE(shown_shelf_bounds, hidden_shelf_bounds); + + // Go to the second desk. + ActivateDesk(DesksController::Get()->desks()[1].get()); + // The shelf should now want to show itself, but as the shelf animation is + // just starting, it should still be hidden. If this fails, the change was + // not animated. + EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState()); + EXPECT_EQ(shelf_widget->GetWindowBoundsInScreen(), hidden_shelf_bounds); + // Let's wait until the shelf animates to a fully shown state. + while (shelf_widget->GetWindowBoundsInScreen() != shown_shelf_bounds) { + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), + base::TimeDelta::FromMilliseconds(200)); + run_loop.Run(); + } + EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState()); +} + class DesksWithSplitViewTest : public AshTestBase { public: DesksWithSplitViewTest() = default;
diff --git a/ash/wm/overview/overview_window_drag_controller.cc b/ash/wm/overview/overview_window_drag_controller.cc index 67b7f2aa..5f72a3e2 100644 --- a/ash/wm/overview/overview_window_drag_controller.cc +++ b/ash/wm/overview/overview_window_drag_controller.cc
@@ -9,6 +9,7 @@ #include <utility> #include "ash/display/mouse_cursor_event_filter.h" +#include "ash/display/screen_orientation_controller.h" #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/presentation_time_recorder.h" #include "ash/screen_util.h"
diff --git a/ash/wm/splitview/split_view_drag_indicators.cc b/ash/wm/splitview/split_view_drag_indicators.cc index 33105c7..11c5c78 100644 --- a/ash/wm/splitview/split_view_drag_indicators.cc +++ b/ash/wm/splitview/split_view_drag_indicators.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "ash/display/screen_orientation_controller.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/window_animation_types.h" #include "ash/screen_util.h"
diff --git a/ash/wm/splitview/split_view_highlight_view.cc b/ash/wm/splitview/split_view_highlight_view.cc index d121ebd..6796559 100644 --- a/ash/wm/splitview/split_view_highlight_view.cc +++ b/ash/wm/splitview/split_view_highlight_view.cc
@@ -4,6 +4,7 @@ #include "ash/wm/splitview/split_view_highlight_view.h" +#include "ash/display/screen_orientation_controller.h" #include "ash/shell.h" #include "ash/wm/overview/rounded_rect_view.h" #include "ash/wm/splitview/split_view_controller.h"
diff --git a/ash/wm/splitview/split_view_utils.h b/ash/wm/splitview/split_view_utils.h index 47940e0..b328c81 100644 --- a/ash/wm/splitview/split_view_utils.h +++ b/ash/wm/splitview/split_view_utils.h
@@ -6,7 +6,6 @@ #define ASH_WM_SPLITVIEW_SPLIT_VIEW_UTILS_H_ #include "ash/ash_export.h" -#include "ash/display/screen_orientation_controller.h" #include "ash/wm/splitview/split_view_controller.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/transform.h"
diff --git a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc index e414e2d..0479a1a 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc
@@ -4,6 +4,7 @@ #include "ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h" +#include "ash/display/screen_orientation_controller.h" #include "ash/root_window_controller.h" #include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h"
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager.cc b/ash/wm/tablet_mode/tablet_mode_window_manager.cc index 31f6265..0a7d2e0 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_manager.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_manager.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "ash/display/screen_orientation_controller.h" #include "ash/public/cpp/app_types.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/shell_window_ids.h"
diff --git a/base/task/thread_pool/job_task_source.cc b/base/task/thread_pool/job_task_source.cc index be52945d..7b4fa80 100644 --- a/base/task/thread_pool/job_task_source.cc +++ b/base/task/thread_pool/job_task_source.cc
@@ -338,12 +338,12 @@ #endif // DCHECK_IS_ON() -Optional<Task> JobTaskSource::TakeTask(TaskSource::Transaction* transaction) { +Task JobTaskSource::TakeTask(TaskSource::Transaction* transaction) { // JobTaskSource members are not lock-protected so no need to acquire a lock // if |transaction| is nullptr. DCHECK_GT(state_.Load().worker_count(), 0U); DCHECK(primary_task_); - return base::make_optional<Task>(from_here_, primary_task_, TimeDelta()); + return Task(from_here_, primary_task_, TimeDelta()); } bool JobTaskSource::DidProcessTask(TaskSource::Transaction* transaction) { @@ -375,12 +375,12 @@ return SequenceSortKey(traits_.priority(), queue_time_); } -Optional<Task> JobTaskSource::Clear(TaskSource::Transaction* transaction) { +Task JobTaskSource::Clear(TaskSource::Transaction* transaction) { Cancel(); // Nothing is cleared since other workers might still racily run tasks. For // simplicity, the destructor will take care of it once all references are // released. - return base::make_optional<Task>(from_here_, DoNothing(), TimeDelta()); + return Task(from_here_, DoNothing(), TimeDelta()); } } // namespace internal
diff --git a/base/task/thread_pool/job_task_source.h b/base/task/thread_pool/job_task_source.h index 57838679..c1fc6c38e 100644 --- a/base/task/thread_pool/job_task_source.h +++ b/base/task/thread_pool/job_task_source.h
@@ -181,8 +181,8 @@ // TaskSource: RunStatus WillRunTask() override; - Optional<Task> TakeTask(TaskSource::Transaction* transaction) override; - Optional<Task> Clear(TaskSource::Transaction* transaction) override; + Task TakeTask(TaskSource::Transaction* transaction) override; + Task Clear(TaskSource::Transaction* transaction) override; bool DidProcessTask(TaskSource::Transaction* transaction) override; SequenceSortKey GetSortKey() const override;
diff --git a/base/task/thread_pool/job_task_source_unittest.cc b/base/task/thread_pool/job_task_source_unittest.cc index 413771f..d48fdf89 100644 --- a/base/task/thread_pool/job_task_source_unittest.cc +++ b/base/task/thread_pool/job_task_source_unittest.cc
@@ -58,7 +58,7 @@ TaskSource::RunStatus::kAllowedNotSaturated); auto task = registered_task_source.TakeTask(); - std::move(task->task).Run(); + std::move(task.task).Run(); EXPECT_TRUE(registered_task_source.DidProcessTask()); } { @@ -73,7 +73,7 @@ EXPECT_EQ(RegisteredTaskSource::CreateForTesting(task_source).WillRunTask(), TaskSource::RunStatus::kDisallowed); - std::move(task->task).Run(); + std::move(task.task).Run(); EXPECT_EQ(0U, task_source->GetRemainingConcurrency()); // Returns false because the task source is out of tasks. EXPECT_FALSE(registered_task_source.DidProcessTask()); @@ -115,7 +115,7 @@ { EXPECT_EQ(1U, task_source->GetRemainingConcurrency()); auto task = registered_task_source_c.Clear(); - std::move(task->task).Run(); + std::move(task.task).Run(); registered_task_source_c.DidProcessTask(); EXPECT_EQ(0U, task_source->GetRemainingConcurrency()); } @@ -127,19 +127,19 @@ // Another outstanding RunStatus can still call Clear. { auto task = registered_task_source_d.Clear(); - std::move(task->task).Run(); + std::move(task.task).Run(); registered_task_source_d.DidProcessTask(); EXPECT_EQ(0U, task_source->GetRemainingConcurrency()); } // A task that was already acquired can still run. - std::move(task_a->task).Run(); + std::move(task_a.task).Run(); registered_task_source_a.DidProcessTask(); // A valid outstanding RunStatus can also take and run a task. { auto task = registered_task_source_b.TakeTask(); - std::move(task->task).Run(); + std::move(task.task).Run(); registered_task_source_b.DidProcessTask(); } } @@ -174,13 +174,13 @@ TaskSource::RunStatus::kDisallowed); // A task that was already acquired can still run. - std::move(task_a->task).Run(); + std::move(task_a.task).Run(); registered_task_source_a.DidProcessTask(); // A RegisteredTaskSource that's ready can also take and run a task. { auto task = registered_task_source_b.TakeTask(); - std::move(task->task).Run(); + std::move(task.task).Run(); registered_task_source_b.DidProcessTask(); } } @@ -209,13 +209,13 @@ EXPECT_EQ(RegisteredTaskSource::CreateForTesting(task_source).WillRunTask(), TaskSource::RunStatus::kDisallowed); - std::move(task_a->task).Run(); + std::move(task_a.task).Run(); // Adding a task before closing the first run operation should cause the task // source to re-enqueue. job_task->SetNumTasksToRun(2); EXPECT_TRUE(registered_task_source_a.DidProcessTask()); - std::move(task_b->task).Run(); + std::move(task_b.task).Run(); EXPECT_TRUE(registered_task_source_b.DidProcessTask()); auto registered_task_source_c = @@ -224,7 +224,7 @@ TaskSource::RunStatus::kAllowedSaturated); auto task_c = registered_task_source_c.TakeTask(); - std::move(task_c->task).Run(); + std::move(task_c.task).Run(); EXPECT_FALSE(registered_task_source_c.DidProcessTask()); } @@ -284,7 +284,7 @@ EXPECT_TRUE(task_source->WillJoin()); - std::move(worker_task->task).Run(); + std::move(worker_task.task).Run(); EXPECT_FALSE(registered_task_source.DidProcessTask()); EXPECT_FALSE(task_source->RunJoinTask()); @@ -320,10 +320,10 @@ EXPECT_EQ(RegisteredTaskSource::CreateForTesting(task_source).WillRunTask(), TaskSource::RunStatus::kDisallowed); - std::move(task_a->task).Run(); + std::move(task_a.task).Run(); EXPECT_FALSE(registered_task_source_a.DidProcessTask()); - std::move(task_b->task).Run(); + std::move(task_b.task).Run(); EXPECT_FALSE(registered_task_source_b.DidProcessTask()); } @@ -352,7 +352,7 @@ .WillOnce(Return(false)) .WillOnce(Return(true)); - std::move(task->task).Run(); + std::move(task.task).Run(); EXPECT_FALSE(registered_task_source.DidProcessTask()); } @@ -382,7 +382,7 @@ // Running the task should not fail even though max concurrency remained at 1, // since ShouldYield() returned true. - std::move(task->task).Run(); + std::move(task.task).Run(); registered_task_source.DidProcessTask(); } @@ -411,7 +411,7 @@ TaskSource::RunStatus::kAllowedSaturated); auto task = registered_task_source.TakeTask(); - EXPECT_DCHECK_DEATH(std::move(task->task).Run()); + EXPECT_DCHECK_DEATH(std::move(task.task).Run()); registered_task_source.DidProcessTask(); }
diff --git a/base/task/thread_pool/priority_queue.cc b/base/task/thread_pool/priority_queue.cc index 85eae1fe..bbef766 100644 --- a/base/task/thread_pool/priority_queue.cc +++ b/base/task/thread_pool/priority_queue.cc
@@ -91,8 +91,7 @@ while (!container_.empty()) { auto task_source = PopTaskSource(); auto task = task_source.Clear(); - if (task) - std::move(task->task).Run(); + std::move(task.task).Run(); } }
diff --git a/base/task/thread_pool/sequence.cc b/base/task/thread_pool/sequence.cc index ea7ce30..25a76ef 100644 --- a/base/task/thread_pool/sequence.cc +++ b/base/task/thread_pool/sequence.cc
@@ -73,7 +73,7 @@ return 1; } -Optional<Task> Sequence::TakeTask(TaskSource::Transaction* transaction) { +Task Sequence::TakeTask(TaskSource::Transaction* transaction) { CheckedAutoLockMaybe auto_lock(transaction ? nullptr : &lock_); DCHECK(has_worker_); @@ -82,7 +82,7 @@ auto next_task = std::move(queue_.front()); queue_.pop(); - return std::move(next_task); + return next_task; } bool Sequence::DidProcessTask(TaskSource::Transaction* transaction) { @@ -107,19 +107,19 @@ return SequenceSortKey(traits_.priority(), queue_.front().queue_time); } -Optional<Task> Sequence::Clear(TaskSource::Transaction* transaction) { +Task Sequence::Clear(TaskSource::Transaction* transaction) { CheckedAutoLockMaybe auto_lock(transaction ? nullptr : &lock_); // See comment on TaskSource::task_runner_ for lifetime management details. if (!queue_.empty() && !has_worker_) ReleaseTaskRunner(); - return base::make_optional<Task>(FROM_HERE, - base::BindOnce( - [](base::queue<Task> queue) { - while (!queue.empty()) - queue.pop(); - }, - std::move(queue_)), - TimeDelta()); + return Task(FROM_HERE, + base::BindOnce( + [](base::queue<Task> queue) { + while (!queue.empty()) + queue.pop(); + }, + std::move(queue_)), + TimeDelta()); } void Sequence::ReleaseTaskRunner() {
diff --git a/base/task/thread_pool/sequence.h b/base/task/thread_pool/sequence.h index ca505ae..7da7184b 100644 --- a/base/task/thread_pool/sequence.h +++ b/base/task/thread_pool/sequence.h
@@ -99,8 +99,8 @@ // TaskSource: RunStatus WillRunTask() override; - Optional<Task> TakeTask(TaskSource::Transaction* transaction) override; - Optional<Task> Clear(TaskSource::Transaction* transaction) override; + Task TakeTask(TaskSource::Transaction* transaction) override; + Task Clear(TaskSource::Transaction* transaction) override; bool DidProcessTask(TaskSource::Transaction* transaction) override; SequenceSortKey GetSortKey() const override;
diff --git a/base/task/thread_pool/sequence_unittest.cc b/base/task/thread_pool/sequence_unittest.cc index c5166239..ab78d8a 100644 --- a/base/task/thread_pool/sequence_unittest.cc +++ b/base/task/thread_pool/sequence_unittest.cc
@@ -140,7 +140,7 @@ // Verify the sort key. EXPECT_EQ(TaskPriority::BEST_EFFORT, best_effort_sort_key.priority()); - EXPECT_EQ(take_best_effort_task->queue_time, + EXPECT_EQ(take_best_effort_task.queue_time, best_effort_sort_key.next_task_sequenced_time()); // DidProcessTask for correctness. @@ -174,7 +174,7 @@ // Verify the sort key. EXPECT_EQ(TaskPriority::USER_VISIBLE, foreground_sort_key.priority()); - EXPECT_EQ(take_foreground_task->queue_time, + EXPECT_EQ(take_foreground_task.queue_time, foreground_sort_key.next_task_sequenced_time()); // DidProcessTask for correctness. @@ -209,7 +209,7 @@ RegisteredTaskSource::CreateForTesting(sequence); { registered_task_source.WillRunTask(); - EXPECT_TRUE(registered_task_source.TakeTask(&sequence_transaction)); + IgnoreResult(registered_task_source.TakeTask(&sequence_transaction)); registered_task_source.DidProcessTask(&sequence_transaction); } EXPECT_DCHECK_DEATH({
diff --git a/base/task/thread_pool/task_source.cc b/base/task/thread_pool/task_source.cc index 9674346b..76454c3 100644 --- a/base/task/thread_pool/task_source.cc +++ b/base/task/thread_pool/task_source.cc
@@ -126,8 +126,7 @@ return run_status; } -Optional<Task> RegisteredTaskSource::TakeTask( - TaskSource::Transaction* transaction) { +Task RegisteredTaskSource::TakeTask(TaskSource::Transaction* transaction) { DCHECK(!transaction || transaction->task_source() == get()); #if DCHECK_IS_ON() DCHECK_EQ(State::kReady, run_step_); @@ -135,8 +134,7 @@ return task_source_->TakeTask(transaction); } -Optional<Task> RegisteredTaskSource::Clear( - TaskSource::Transaction* transaction) { +Task RegisteredTaskSource::Clear(TaskSource::Transaction* transaction) { DCHECK(!transaction || transaction->task_source() == get()); return task_source_->Clear(transaction); }
diff --git a/base/task/thread_pool/task_source.h b/base/task/thread_pool/task_source.h index 4dfa087..c95aae4b 100644 --- a/base/task/thread_pool/task_source.h +++ b/base/task/thread_pool/task_source.h
@@ -184,14 +184,14 @@ // Implementations of TakeTask(), DidProcessTask() and Clear() must ensure // proper synchronization iff |transaction| is nullptr. - virtual Optional<Task> TakeTask(TaskSource::Transaction* transaction) = 0; + virtual Task TakeTask(TaskSource::Transaction* transaction) = 0; virtual bool DidProcessTask(TaskSource::Transaction* transaction) = 0; // This may be called for each outstanding RegisteredTaskSource that's ready. // The implementation needs to support this being called multiple times; // unless it guarantees never to hand-out multiple RegisteredTaskSources that // are concurrently ready. - virtual Optional<Task> Clear(TaskSource::Transaction* transaction) = 0; + virtual Task Clear(TaskSource::Transaction* transaction) = 0; virtual SequenceSortKey GetSortKey() const = 0; @@ -264,10 +264,7 @@ // only after WillRunTask() returned RunStatus::kAllowed*. |transaction| is // optional and should only be provided if this operation is already part of // a transaction. - // - // Because this method cannot be called on an empty TaskSource, the returned - // Optional<Task> is never nullopt. - Optional<Task> TakeTask(TaskSource::Transaction* transaction = nullptr) + Task TakeTask(TaskSource::Transaction* transaction = nullptr) WARN_UNUSED_RESULT; // Must be called after WillRunTask() or once the task was run if TakeTask() @@ -280,8 +277,7 @@ // Returns a task that clears this TaskSource to make it empty. |transaction| // is optional and should only be provided if this operation is already part // of a transaction. - Optional<Task> Clear(TaskSource::Transaction* transaction = nullptr) - WARN_UNUSED_RESULT; + Task Clear(TaskSource::Transaction* transaction = nullptr) WARN_UNUSED_RESULT; private: friend class TaskTracker;
diff --git a/base/task/thread_pool/worker_thread_unittest.cc b/base/task/thread_pool/worker_thread_unittest.cc index cd430ed0..203f8a4 100644 --- a/base/task/thread_pool/worker_thread_unittest.cc +++ b/base/task/thread_pool/worker_thread_unittest.cc
@@ -217,7 +217,7 @@ // Verify the number of Tasks in |registered_task_source|. for (int i = 0; i < outer_->TasksPerSequence() - 1; ++i) { registered_task_source.WillRunTask(); - EXPECT_TRUE(registered_task_source.TakeTask()); + IgnoreResult(registered_task_source.TakeTask()); EXPECT_EQ(i == outer_->TasksPerSequence() - 2, !registered_task_source.DidProcessTask()); }
diff --git a/build/android/pylib/gtest/gtest_test_instance.py b/build/android/pylib/gtest/gtest_test_instance.py index 2b2c5e7..634ab7220 100644 --- a/build/android/pylib/gtest/gtest_test_instance.py +++ b/build/android/pylib/gtest/gtest_test_instance.py
@@ -26,6 +26,7 @@ 'android_browsertests', 'components_browsertests', 'content_browsertests', + 'weblayer_browsertests', ] RUN_IN_SUB_THREAD_TEST_SUITES = [
diff --git a/build/fuchsia/fidlgen_js/test/simple.fidl b/build/fuchsia/fidlgen_js/test/simple.fidl index 3e4412c..66e1c1f 100644 --- a/build/fuchsia/fidlgen_js/test/simple.fidl +++ b/build/fuchsia/fidlgen_js/test/simple.fidl
@@ -49,9 +49,9 @@ }; union UnionOfStructs { - StructWithBool swb; - StructWithUint swu; - LargerStructWithArray lswa; + 1: StructWithBool swb; + 2: StructWithUint swu; + 3: LargerStructWithArray lswa; }; struct StructOfMultipleUnions {
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index f0ff35a0..a8b298d8 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8897331871501701008 \ No newline at end of file +8897305778828297248 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 6128bd99..6c2ab78a 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8897334129707393184 \ No newline at end of file +8897308657886416976 \ No newline at end of file
diff --git a/chrome/VERSION b/chrome/VERSION index bdd94ae..e078d7e 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=80 MINOR=0 -BUILD=3964 +BUILD=3965 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index dda43d25..af896cd 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -52,7 +52,6 @@ "java/src/org/chromium/chrome/browser/SearchGeolocationDisclosureTabHelper.java", "java/src/org/chromium/chrome/browser/ServiceTabLauncher.java", "java/src/org/chromium/chrome/browser/ShortcutHelper.java", - "java/src/org/chromium/chrome/browser/SingleTabActivity.java", "java/src/org/chromium/chrome/browser/SnackbarActivity.java", "java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java", "java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java index 37e3780..0be1851 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
@@ -234,6 +234,7 @@ mResetHandler.resetWithTabList( mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter(), false, mShowTabsInMruOrder); + setInitialScrollIndexOffset(); } }; @@ -420,15 +421,20 @@ mHandler.removeCallbacks(mSoftClearTabListRunnable); mHandler.removeCallbacks(mClearTabListRunnable); boolean quick = false; - if (TabFeatureUtilities.isTabToGtsAnimationEnabled() - && mTabModelSelector.getTabModelFilterProvider() - .getCurrentTabModelFilter() - .isTabModelRestored()) { - quick = mResetHandler.resetWithTabList( - mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter(), false, - mShowTabsInMruOrder); + if (mTabModelSelector.getTabModelFilterProvider() + .getCurrentTabModelFilter() + .isTabModelRestored()) { + if (TabFeatureUtilities.isTabToGtsAnimationEnabled()) { + quick = mResetHandler.resetWithTabList( + mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter(), + false, mShowTabsInMruOrder); + } + setInitialScrollIndexOffset(); } + return quick; + } + private void setInitialScrollIndexOffset() { int initialPosition = Math.max( mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter().index() - INITIAL_SCROLL_INDEX_OFFSET, @@ -436,7 +442,6 @@ // In MRU order, selected Tab is always at the first position. if (mShowTabsInMruOrder) initialPosition = 0; mContainerViewModel.set(INITIAL_SCROLL_INDEX, initialPosition); - return quick; } @Override
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java index 0964ab50..43a818a 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.tasks.tab_management; -import android.os.Build; import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; @@ -15,7 +14,6 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.flags.FeatureUtilities; @@ -38,8 +36,6 @@ */ @RunWith(ChromeJUnit4ClassRunner.class) @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) -@DisableIf.Build(message = "crbug.com/1022200", sdk_is_greater_than = Build.VERSION_CODES.KITKAT, - sdk_is_less_than = Build.VERSION_CODES.M) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class TabSelectionEditorTest { @Rule
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java index 821ba65..04fc3a7e 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java
@@ -57,7 +57,7 @@ @Override public boolean matchesSafely(Root root) { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) { + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) { return withDecorView( withClassName(is(TabSelectionEditorLayout.class.getName()))) .matches(root);
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java index 6e5baf0f..b99bf602 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java
@@ -467,6 +467,18 @@ } @Test + public void setInitialScrollIndexOnRestoreCompleted() { + initAndAssertAllProperties(); + mMediator.showOverview(true); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(true)); + + mModel.set(TabListContainerProperties.INITIAL_SCROLL_INDEX, 1); + + mTabModelObserverCaptor.getValue().restoreCompleted(); + assertThat(mModel.get(TabListContainerProperties.INITIAL_SCROLL_INDEX), equalTo(0)); + } + + @Test public void showOverviewDoesNotUpdateResetHandlerBeforeRestoreCompleted() { initAndAssertAllProperties(); doReturn(false).when(mTabModelFilter).isTabModelRestored(); @@ -509,6 +521,17 @@ } @Test + public void prepareOverviewSetsInitialScrollIndexAfterRestoreCompleted() { + initAndAssertAllProperties(); + doReturn(true).when(mTabModelFilter).isTabModelRestored(); + + mModel.set(TabListContainerProperties.INITIAL_SCROLL_INDEX, 1); + + mMediator.prepareOverview(); + assertThat(mModel.get(TabListContainerProperties.INITIAL_SCROLL_INDEX), equalTo(0)); + } + + @Test @DisableFeatures(ChromeFeatureList.TAB_GROUPS_UI_IMPROVEMENTS_ANDROID) public void openDialogButton_FlagDisabled() { FeatureUtilities.setTabGroupsAndroidEnabledForTesting(false);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/OWNERS index e80e4240..506101d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/OWNERS
@@ -1,6 +1,5 @@ per-file ChromeApplication.java=agrieve@chromium.org per-file ShortcutHelper.java=dominickn@chromium.org -per-file SingleTabActivity.java=dominickn@chromium.org # This is For simple changes of adding/removing features. For more structural # changes, use the normal OWNERS rules.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java deleted file mode 100644 index a9ea4ca..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java +++ /dev/null
@@ -1,132 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser; - -import android.os.Bundle; -import android.util.Pair; - -import org.chromium.chrome.browser.dependency_injection.ChromeActivityComponent; -import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tab.TabBuilder; -import org.chromium.chrome.browser.tab.TabDelegateFactory; -import org.chromium.chrome.browser.tab.TabState; -import org.chromium.chrome.browser.tabmodel.SingleTabModelSelector; -import org.chromium.chrome.browser.tabmodel.TabLaunchType; -import org.chromium.chrome.browser.tabmodel.TabModelSelector; -import org.chromium.chrome.browser.tabmodel.TabSelectionType; -import org.chromium.chrome.browser.tabmodel.document.TabDelegate; - -/** - * Base class for task-focused activities that need to display a single tab. - * @param <C> - type of associated Dagger component. - * - * Example applications that might use this Activity would be webapps and streaming media - * activities - anything where maintaining multiple tabs is unnecessary. - */ -public abstract class SingleTabActivity<C extends ChromeActivityComponent> - extends ChromeActivity<C> { - protected static final String BUNDLE_TAB_ID = "tabId"; - - @Override - protected TabModelSelector createTabModelSelector() { - return new SingleTabModelSelector(this, this, false); - } - - @Override - protected Pair<? extends TabCreator, ? extends TabCreator> createTabCreators() { - return Pair.create(createNormalTabCreator(), null); - } - - /** Creates TabDelegates for opening new Tabs. */ - protected TabCreator createNormalTabCreator() { - return new TabDelegate(false /* incognito */); - } - - @Override - public void initializeState() { - super.initializeState(); - - createAndShowTab(); - } - - protected void createAndShowTab() { - Tab tab = createTab(); - getTabModelSelector().setTab(tab); - tab.show(TabSelectionType.FROM_NEW); - } - - @Override - public SingleTabModelSelector getTabModelSelector() { - return (SingleTabModelSelector) super.getTabModelSelector(); - } - - /** - * Creates the {@link Tab} used by the {@link SingleTabActivity}. - * If the {@code savedInstanceState} exists, then the user did not intentionally close the app - * by swiping it away in the recent tasks list. In that case, we try to restore the tab from - * disk. - */ - protected Tab createTab() { - Tab tab = null; - TabState tabState = null; - int tabId = Tab.INVALID_TAB_ID; - Bundle savedInstanceState = getSavedInstanceState(); - if (savedInstanceState != null) { - tabId = savedInstanceState.getInt(BUNDLE_TAB_ID, Tab.INVALID_TAB_ID); - if (tabId != Tab.INVALID_TAB_ID) { - tabState = restoreTabState(savedInstanceState, tabId); - } - } - boolean unfreeze = tabId != Tab.INVALID_TAB_ID && tabState != null; - if (unfreeze) { - tab = TabBuilder.createFromFrozenState() - .setId(tabId) - .setWindow(getWindowAndroid()) - .setDelegateFactory(createTabDelegateFactory()) - .setTabState(tabState) - .setUnfreeze(unfreeze) - .build(); - } else { - tab = new TabBuilder() - .setWindow(getWindowAndroid()) - .setLaunchType(TabLaunchType.FROM_CHROME_UI) - .setDelegateFactory(createTabDelegateFactory()) - .setTabState(tabState) - .setUnfreeze(unfreeze) - .build(); - } - return tab; - } - - /** - * @return {@link TabDelegateFactory} to be used while creating the associated {@link Tab}. - */ - protected abstract TabDelegateFactory createTabDelegateFactory(); - - /** - * Restore {@link TabState} from a given {@link Bundle} and tabId. - * @param saveInstanceState The saved bundle for the last recorded state. - * @param tabId ID of the tab restored from. - */ - protected abstract TabState restoreTabState(Bundle savedInstanceState, int tabId); - - @Override - protected boolean handleBackPressed() { - Tab tab = getActivityTab(); - if (tab == null) return false; - - if (exitFullscreenIfShowing()) return true; - - if (tab.canGoBack()) { - tab.goBack(); - return true; - } - - return false; - } - - @Override - public void onUpdateStateChanged() {} -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index 1abb84d..8aa67f27 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -17,6 +17,7 @@ import android.os.Bundle; import android.os.StrictMode; import android.text.TextUtils; +import android.util.Pair; import android.view.ViewGroup; import androidx.annotation.Nullable; @@ -33,7 +34,6 @@ import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.IntentHandler; -import org.chromium.chrome.browser.SingleTabActivity; import org.chromium.chrome.browser.WarmupManager; import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate; import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider.CustomTabsUiType; @@ -48,9 +48,14 @@ import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabBrowserControlsState; +import org.chromium.chrome.browser.tab.TabBuilder; import org.chromium.chrome.browser.tab.TabDelegateFactory; import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.tab.TabState; +import org.chromium.chrome.browser.tabmodel.SingleTabModelSelector; +import org.chromium.chrome.browser.tabmodel.TabLaunchType; +import org.chromium.chrome.browser.tabmodel.TabModelSelector; +import org.chromium.chrome.browser.tabmodel.TabSelectionType; import org.chromium.chrome.browser.ui.widget.TintedDrawable; import org.chromium.chrome.browser.usage_stats.UsageStatsService; import org.chromium.chrome.browser.util.AndroidTaskUtils; @@ -72,13 +77,15 @@ /** * Displays a webapp in a nearly UI-less Chrome (InfoBars still appear). */ -public class WebappActivity extends SingleTabActivity<WebappActivityComponent> { +public class WebappActivity extends ChromeActivity<WebappActivityComponent> { public static final String WEBAPP_SCHEME = "webapp"; private static final String TAG = "WebappActivity"; private static final String HISTOGRAM_NAVIGATION_STATUS = "Webapp.NavigationStatus"; private static final long MS_BEFORE_NAVIGATING_BACK_FROM_INTERSTITIAL = 1000; + protected static final String BUNDLE_TAB_ID = "tabId"; + private WebappInfo mWebappInfo; private CustomTabToolbarCoordinator mToolbarCoordinator; @@ -194,6 +201,8 @@ @Override public void initializeState() { super.initializeState(); + + createAndShowTab(); mTabController.setInitialTab(getActivityTab()); initializeUI(getSavedInstanceState()); } @@ -393,8 +402,12 @@ } } - @Override - protected TabState restoreTabState(Bundle savedInstanceState, int tabId) { + /** + * Restore {@link TabState} from a given {@link Bundle} and tabId. + * @param saveInstanceState The saved bundle for the last recorded state. + * @param tabId ID of the tab restored from. + */ + private TabState restoreTabState(Bundle savedInstanceState, int tabId) { return TabState.restoreTabState(savedInstanceState); } @@ -768,14 +781,15 @@ return null; } - @Override - protected TabDelegateFactory createTabDelegateFactory() { + /** + * @return {@link TabDelegateFactory} to be used while creating the associated {@link Tab}. + */ + private TabDelegateFactory createTabDelegateFactory() { mWebappDelegateFactory = new WebappDelegateFactory(this); return mWebappDelegateFactory; } - @Override - protected TabCreator createNormalTabCreator() { + private TabCreator createNormalTabCreator() { return new WebappTabDelegate(false /* incognito */, mWebappInfo); } @@ -847,4 +861,66 @@ protected void removeSplashscreenObserver(SplashscreenObserver observer) { mSplashController.removeObserver(observer); } + + @Override + protected TabModelSelector createTabModelSelector() { + return new SingleTabModelSelector(this, this, false); + } + + @Override + protected Pair<? extends TabCreator, ? extends TabCreator> createTabCreators() { + return Pair.create(createNormalTabCreator(), null); + } + + protected void createAndShowTab() { + Tab tab = createTab(); + getTabModelSelector().setTab(tab); + tab.show(TabSelectionType.FROM_NEW); + } + + @Override + public SingleTabModelSelector getTabModelSelector() { + return (SingleTabModelSelector) super.getTabModelSelector(); + } + + /** + * Creates the {@link Tab} used by the {@link SingleTabActivity}. + * If the {@code savedInstanceState} exists, then the user did not intentionally close the app + * by swiping it away in the recent tasks list. In that case, we try to restore the tab from + * disk. + */ + protected Tab createTab() { + Tab tab = null; + TabState tabState = null; + int tabId = Tab.INVALID_TAB_ID; + Bundle savedInstanceState = getSavedInstanceState(); + if (savedInstanceState != null) { + tabId = savedInstanceState.getInt(BUNDLE_TAB_ID, Tab.INVALID_TAB_ID); + if (tabId != Tab.INVALID_TAB_ID) { + tabState = restoreTabState(savedInstanceState, tabId); + } + } + boolean unfreeze = tabId != Tab.INVALID_TAB_ID && tabState != null; + if (unfreeze) { + tab = TabBuilder.createFromFrozenState() + .setId(tabId) + .setWindow(getWindowAndroid()) + .setDelegateFactory(createTabDelegateFactory()) + .setTabState(tabState) + .setUnfreeze(unfreeze) + .build(); + } else { + tab = new TabBuilder() + .setWindow(getWindowAndroid()) + .setLaunchType(TabLaunchType.FROM_CHROME_UI) + .setDelegateFactory(createTabDelegateFactory()) + .setTabState(tabState) + .setUnfreeze(unfreeze) + .build(); + } + return tab; + } + + @Override + public void onUpdateStateChanged() {} }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDelegateFactory.java index c13e518..9c42d5d9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDelegateFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDelegateFactory.java
@@ -9,7 +9,6 @@ import org.chromium.base.ContextUtils; import org.chromium.chrome.browser.ShortcutHelper; -import org.chromium.chrome.browser.SingleTabActivity; import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulator; import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator; import org.chromium.chrome.browser.fullscreen.ComposedBrowserControlsVisibilityDelegate; @@ -26,7 +25,7 @@ /** * A {@link TabDelegateFactory} class to be used in all {@link Tab} instances owned by a - * {@link SingleTabActivity}. + * {@link WebappActivity}. */ public class WebappDelegateFactory extends TabDelegateFactoryImpl { private static class WebappWebContentsDelegateAndroid
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java index 6040d13..d21d8ef 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
@@ -8,9 +8,11 @@ import static android.support.test.espresso.Espresso.pressBack; import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.RootMatchers.isDialog; import static android.support.test.espresso.matcher.ViewMatchers.hasSibling; import static android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA; import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.isEnabled; import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription; import static android.support.test.espresso.matcher.ViewMatchers.withId; import static android.support.test.espresso.matcher.ViewMatchers.withText; @@ -20,6 +22,8 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.core.AllOf.allOf; +import android.os.Handler; +import android.os.Looper; import android.support.test.espresso.action.ViewActions; import android.support.test.filters.MediumTest; @@ -30,23 +34,28 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.chromium.base.Callback; import org.chromium.base.task.PostTask; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.download.home.filter.FilterCoordinator; import org.chromium.chrome.browser.download.home.list.UiUtils; +import org.chromium.chrome.browser.download.home.rename.RenameUtils; import org.chromium.chrome.browser.download.home.toolbar.DownloadHomeToolbar; import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory; import org.chromium.chrome.browser.download.ui.StubbedProvider; +import org.chromium.chrome.browser.modaldialog.AppModalPresenter; import org.chromium.chrome.browser.snackbar.SnackbarManager; import org.chromium.chrome.browser.util.UrlConstants; import org.chromium.chrome.download.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ui.DummyUiActivityTestCase; import org.chromium.components.feature_engagement.Tracker; +import org.chromium.components.offline_items_collection.ContentId; import org.chromium.components.offline_items_collection.OfflineItem; import org.chromium.components.offline_items_collection.OfflineItemFilter; import org.chromium.components.offline_items_collection.OfflineItemState; +import org.chromium.components.offline_items_collection.RenameResult; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modaldialog.ModalDialogManager; @@ -63,7 +72,7 @@ private Tracker mTracker; @Mock private SnackbarManager mSnackbarManager; - @Mock + private ModalDialogManager.Presenter mAppModalPresenter; private ModalDialogManager mModalDialogManager; @@ -91,7 +100,14 @@ features.put(ChromeFeatureList.OFFLINE_HOME, false); ChromeFeatureList.setTestFeatures(features); - mStubbedOfflineContentProvider = new StubbedOfflineContentProvider(); + mStubbedOfflineContentProvider = new StubbedOfflineContentProvider() { + @Override + public void renameItem(ContentId id, String name, Callback<Integer> callback) { + new Handler(Looper.getMainLooper()) + .post(() -> callback.onResult(handleRename(name))); + } + }; + OfflineContentAggregatorFactory.setOfflineContentProviderForTests( mStubbedOfflineContentProvider); @@ -119,6 +135,8 @@ .setUseNewDownloadPathThumbnails(true) .build(); + mAppModalPresenter = new AppModalPresenter(getActivity()); + mModalDialogManager = new ModalDialogManager(mAppModalPresenter, ModalDialogManager.ModalDialogType.APP); @@ -339,6 +357,36 @@ @Test @MediumTest + public void testRenameItem() throws Exception { + TestThreadUtils.runOnUiThreadBlocking(() -> { setUpUi(); }); + + RenameUtils.disableNativeForTesting(); + + // Rename a non-offline-page item using three dot menu. + // Open menu for a list item, it should have the rename option. + onView(allOf(withId(R.id.more), hasSibling(withText("page 4")))) + .perform(ViewActions.click()); + // Rename an item. The rename dialog should popup. + onView(withText("Rename")).check(matches(isDisplayed())).perform(ViewActions.click()); + + // Test rename dialog with error message. + renameFileAndVerifyErrorMessage("name_conflict", R.string.rename_failure_name_conflict); + renameFileAndVerifyErrorMessage("name_too_long", R.string.rename_failure_name_too_long); + renameFileAndVerifyErrorMessage("name_invalid", R.string.rename_failure_name_invalid); + renameFileAndVerifyErrorMessage("rename_unavailable", R.string.rename_failure_unavailable); + + // Test empty input. + onView(withId(R.id.file_name)).inRoot(isDialog()).perform(ViewActions.clearText()); + onView(withText("OK")).inRoot(isDialog()).check(matches(not(isEnabled()))); + + // Test successful commit. + renameFileAndVerifyErrorMessage("rename_file_successful", -1); + + // TODO(hesen): Test rename extension dialog. + } + + @Test + @MediumTest public void testShareItem() throws Exception { TestThreadUtils.runOnUiThreadBlocking(() -> { setUpUi(); }); @@ -385,4 +433,43 @@ onView(withText("page 3")).check(item2 ? matches(isDisplayed()) : doesNotExist()); onView(withText("page 4")).check(item3 ? matches(isDisplayed()) : doesNotExist()); } + + private void renameFileAndVerifyErrorMessage(String name, int expectErrorMsgId) { + onView(withId(R.id.file_name)) + .inRoot(isDialog()) + .perform(ViewActions.clearText()) + .perform(ViewActions.typeText(name)); + + onView(withText("OK")) + .inRoot(isDialog()) + .check(matches(isDisplayed())) + .perform(ViewActions.click()); + + if (expectErrorMsgId != -1) { + onView(withText(getActivity().getResources().getString(expectErrorMsgId))) + .inRoot(isDialog()) + .check(matches(isDisplayed())); + } + } + + private int /*@RenameResult*/ handleRename(String name) { + int result = RenameResult.SUCCESS; + switch (name) { + case "name_conflict": + result = RenameResult.FAILURE_NAME_CONFLICT; + break; + case "name_too_long": + result = RenameResult.FAILURE_NAME_TOO_LONG; + break; + case "name_invalid": + result = RenameResult.FAILURE_NAME_INVALID; + break; + case "rename_unavailable": + result = RenameResult.FAILURE_UNAVAILABLE; + break; + default: + break; + } + return result; + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/OWNERS new file mode 100644 index 0000000..c2dc2bc --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/OWNERS
@@ -0,0 +1 @@ +file://chrome/android/java/src/org/chromium/chrome/browser/tasks/OWNERS
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java index f980343b..f66f364 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java
@@ -8,7 +8,6 @@ import static org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil.TAB_SWITCHER_ON_RETURN_MS; -import android.app.Activity; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; @@ -18,47 +17,51 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ActivityState; -import org.chromium.base.ApplicationStatus; -import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeSwitches; -import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.flags.FeatureUtilities; +import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -import org.chromium.chrome.test.util.MenuUtils; +import org.chromium.chrome.test.util.ApplicationTestUtils; +import org.chromium.chrome.test.util.RenderTestRule; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; -import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.EmbeddedTestServer; import org.chromium.ui.test.util.UiRestriction; -import java.util.concurrent.TimeoutException; - /** * Tests the functionality of return to chrome features that open overview mode if the timeout * has passed. */ @RunWith(ChromeJUnit4ClassRunner.class) @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, + "enable-features=" + ChromeFeatureList.TAB_SWITCHER_ON_RETURN + "<Study", + "force-fieldtrials=Study/Group"}) public class ReturnToChromeTest { + private static final String BASE_PARAMS = + "force-fieldtrial-params=Study.Group:" + TAB_SWITCHER_ON_RETURN_MS + "/0"; @Rule public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); - private ChromeTabbedActivity mActivity; + private String mUrl; + + @Rule + public RenderTestRule mRenderTestRule = new RenderTestRule(); @Before public void setUp() { FeatureUtilities.setGridTabSwitcherEnabledForTesting(true); - mActivityTestRule.startMainActivityOnBlankPage(); - mActivity = mActivityTestRule.getActivity(); + EmbeddedTestServer testServer = + EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); + mUrl = testServer.getURL("/chrome/test/data/android/navigate/simple.html"); - setupTabs(); + mActivityTestRule.startMainActivityOnBlankPage(); } /** @@ -68,19 +71,14 @@ @Test @SmallTest @Feature({"ReturnToChrome"}) - @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, - "enable-features=" + ChromeFeatureList.TAB_SWITCHER_ON_RETURN + "<FakeStudyName", - "force-fieldtrials=FakeStudyName/Enabled", - "force-fieldtrial-params=FakeStudyName.Enabled:" + TAB_SWITCHER_ON_RETURN_MS - + "/100000"}) - public void - testTabSwitcherModeNotTriggeredWithinThreshold() throws Exception { - finishActivityCompletely(); + @CommandLineFlags.Add({BASE_PARAMS + "/" + TAB_SWITCHER_ON_RETURN_MS + "/100000"}) + public void testTabSwitcherModeNotTriggeredWithinThreshold() throws Exception { + TabUiTestHelper.prepareTabsWithThumbnail(mActivityTestRule, 2, 0, mUrl); + ApplicationTestUtils.finishActivity(mActivityTestRule.getActivity()); mActivityTestRule.startMainActivityFromLauncher(); - mActivity = mActivityTestRule.getActivity(); - Assert.assertFalse(mActivity.getLayoutManager().overviewVisible()); + Assert.assertFalse(mActivityTestRule.getActivity().getLayoutManager().overviewVisible()); } /** @@ -90,18 +88,14 @@ @Test @SmallTest @Feature({"ReturnToChrome"}) - @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, - "enable-features=" + ChromeFeatureList.TAB_SWITCHER_ON_RETURN + "<FakeStudyName", - "force-fieldtrials=FakeStudyName/Enabled", - "force-fieldtrial-params=FakeStudyName.Enabled:" + TAB_SWITCHER_ON_RETURN_MS + "/0"}) - public void - testTabSwitcherModeTriggeredBeyondThreshold() throws Exception { - finishActivityCompletely(); + @CommandLineFlags.Add({BASE_PARAMS + "/" + TAB_SWITCHER_ON_RETURN_MS + "/0"}) + public void testTabSwitcherModeTriggeredBeyondThreshold() throws Exception { + TabUiTestHelper.prepareTabsWithThumbnail(mActivityTestRule, 2, 0, mUrl); + ApplicationTestUtils.finishActivity(mActivityTestRule.getActivity()); mActivityTestRule.startMainActivityFromLauncher(); - mActivity = mActivityTestRule.getActivity(); - Assert.assertTrue(mActivity.getLayoutManager().overviewVisible()); + Assert.assertTrue(mActivityTestRule.getActivity().getLayoutManager().overviewVisible()); CriteriaHelper.pollUiThread(Criteria.equals(true, mActivityTestRule.getActivity() @@ -112,44 +106,29 @@ assertEquals(2, mActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount()); } - private void setupTabs() { - TestThreadUtils.runOnUiThreadBlocking( - () -> mActivityTestRule.getActivity().getTabModelSelector().closeAllTabs()); - EmbeddedTestServer testServer = - EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); - final String url = testServer.getURL("/chrome/test/data/android/navigate/simple.html"); + @Test + @SmallTest + @Feature({"ReturnToChrome", "RenderTest"}) + @CommandLineFlags.Add({BASE_PARAMS + "/" + TAB_SWITCHER_ON_RETURN_MS + "/0"}) + public void testInitialScrollIndex() throws Exception { + TabUiTestHelper.prepareTabsWithThumbnail(mActivityTestRule, 10, 0, mUrl); + ApplicationTestUtils.finishActivity(mActivityTestRule.getActivity()); - // Add 2 tabs. - MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(), - mActivity, org.chromium.chrome.R.id.new_tab_menu_id); - mActivityTestRule.loadUrl(url); - MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(), - mActivity, org.chromium.chrome.R.id.new_tab_menu_id); - mActivityTestRule.loadUrl(url); + mActivityTestRule.startMainActivityFromLauncher(); - assertEquals(2, mActivity.getTabModelSelector().getTotalTabCount()); - } + Assert.assertTrue(mActivityTestRule.getActivity().getLayoutManager().overviewVisible()); - private void finishActivityCompletely() throws TimeoutException { - final CallbackHelper activityCallback = new CallbackHelper(); - ApplicationStatus.ActivityStateListener stateListener = - new ApplicationStatus.ActivityStateListener() { - @Override - public void onActivityStateChange(Activity activity, int newState) { - if (newState == ActivityState.STOPPED) { - activityCallback.notifyCalled(); - ApplicationStatus.unregisterActivityStateListener(this); - } - } - }; + CriteriaHelper.pollUiThread(Criteria.equals(true, + mActivityTestRule.getActivity() + .getTabModelSelector() + .getTabModelFilterProvider() + .getCurrentTabModelFilter()::isTabModelRestored)); - ApplicationStatus.registerStateListenerForAllActivities(stateListener); - try { - mActivity.finish(); - activityCallback.waitForCallback("Activity did not stop as expected", 0); - mActivityTestRule.setActivity(null); - } finally { - ApplicationStatus.unregisterActivityStateListener(stateListener); - } + assertEquals(10, mActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount()); + assertEquals(9, mActivityTestRule.getActivity().getCurrentTabModel().index()); + // Make sure the grid tab switcher is scrolled down to show the selected tab. + mRenderTestRule.render(mActivityTestRule.getActivity().findViewById( + org.chromium.chrome.tab_ui.R.id.tab_list_view), + "10_web_tabs-select_last"); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tasks/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/tasks/OWNERS new file mode 100644 index 0000000..c2dc2bc --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tasks/OWNERS
@@ -0,0 +1 @@ +file://chrome/android/java/src/org/chromium/chrome/browser/tasks/OWNERS
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd index 5b556b12..f0d4fb5 100644 --- a/chrome/app/chromium_strings.grd +++ b/chrome/app/chromium_strings.grd
@@ -667,17 +667,10 @@ </message> <!-- App list --> - <if expr="enable_app_list"> - <if expr="not use_titlecase"> - <message name="IDS_APP_LIST_EXTENSIONS_UNINSTALL" desc="Title text for the context menu item of a non-platform-app app list item that removes the app."> - Remove from Chromium... - </message> - </if> - <if expr="use_titlecase"> - <message name="IDS_APP_LIST_EXTENSIONS_UNINSTALL" desc="In Title Case: Title text for the context menu item of a non-platform-app app list item that removes the app."> - Remove From Chromium... - </message> - </if> + <if expr="chromeos"> + <message name="IDS_APP_LIST_EXTENSIONS_UNINSTALL" desc="Title text for the context menu item of a non-platform-app app list item that removes the app."> + Remove from Chromium... + </message> </if> <!-- App shortcuts -->
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index c203838..58baeee 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -9022,7 +9022,7 @@ </if> <!-- App List. --> - <if expr="enable_app_list"> + <if expr="chromeos"> <message name="IDS_SEARCH_BOX_ACCESSIBILITY_NAME" desc="Hint text for the search box in fullscreen app list window with additional instructions to use the arrow keys in Accessibility mode."> Search your device, apps, and web. Use the arrow keys to navigate your apps. </message> @@ -9041,80 +9041,41 @@ <message name="IDS_APP_LIST_APPEND_SUGGESTION_ACCESSIBILITY_NAME" desc="The spoken feedback for appending suggestion button"> Append the suggestion <ph name="SUGGESTION_NAME">$1<ex>Harry Potter</ex></ph> to search box </message> - <if expr="not use_titlecase"> - <message name="IDS_APP_LIST_CONTEXT_MENU_NEW_TAB" desc="Title text for the 'open new' context menu item of an app list item configured to open in a tab"> - New tab - </message> - <message name="IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW" desc="Title text for the 'open new' context menu item of an app list item configured to open windowed"> - New window - </message> - <message name="IDS_APP_LIST_CONTEXT_MENU_PIN" desc="Title text for the 'pin' context menu item of an app list item."> - Pin to shelf - </message> - <message name="IDS_APP_LIST_CONTEXT_MENU_UNPIN" desc="Title text for the 'unpin' context menu item of an app list item."> - Unpin from shelf - </message> - <message name="IDS_APP_LIST_CONTEXT_MENU_PIN_ENFORCED_BY_POLICY" desc="Short text for the pin/unpin context menu to tell user the setting is enforced by policy of an app list item"> - Pinned by administrator - </message> - <message name="IDS_APP_LIST_UNINSTALL_ITEM" - desc="Title text for the 'uninstall' context menu item of an app list item."> - Uninstall - </message> - <message name="IDS_APP_LIST_REMOVE_SHORTCUT" - desc="Title text for the 'remove' context menu item of an app list shortcut item."> - Remove - </message> - <message name="IDS_APP_LIST_NEW_WINDOW" desc="The text label of the New Window menu item"> - New window - </message> - <message name="IDS_APP_LIST_NEW_INCOGNITO_WINDOW" desc="The text label of the New incognito window menu item"> - New incognito window - </message> - <message name="IDS_APP_LIST_OEM_DEFAULT_FOLDER_NAME" desc="The default name for OEM folders in the App Launcher"> - OEM folder - </message> - <message name="IDS_APP_LIST_CROSTINI_DEFAULT_FOLDER_NAME" desc="The default name for the Linux (Crostini) apps folder in the App Launcher"> - Linux apps - </message> - </if> - <if expr="use_titlecase"> - <message name="IDS_APP_LIST_CONTEXT_MENU_NEW_TAB" desc="Title text for the 'open new' context menu item of an app list item configured to open in a tab"> - New Tab - </message> - <message name="IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW" desc="Title text for the 'open new' context menu item of an app list item configured to open windowed"> - New Window - </message> - <message name="IDS_APP_LIST_CONTEXT_MENU_PIN" desc="Title text for the 'pin' context menu item of an app list item."> - Pin to Shelf - </message> - <message name="IDS_APP_LIST_CONTEXT_MENU_UNPIN" desc="Title text for the 'unpin' context menu item of an app list item."> - Unpin from Shelf - </message> - <message name="IDS_APP_LIST_CONTEXT_MENU_PIN_ENFORCED_BY_POLICY" desc="Short text for the pin/unpin context menu to tell user the setting is enforced by policy of an app list item"> - Pinned by administrator - </message> - <message name="IDS_APP_LIST_UNINSTALL_ITEM" - desc="Title text for the 'uninstall' context menu item of an app list item."> - Uninstall - </message> - <message name="IDS_APP_LIST_REMOVE_SHORTCUT" - desc="Title text for the 'remove' context menu item of an app list shortcut item."> - Remove - </message> - <message name="IDS_APP_LIST_NEW_WINDOW" desc="The text label of the New Window menu item"> - New Window - </message> - <message name="IDS_APP_LIST_NEW_INCOGNITO_WINDOW" desc="The text label of the New incognito window menu item"> - New Incognito Window - </message> - <message name="IDS_APP_LIST_OEM_DEFAULT_FOLDER_NAME" desc="The default name for OEM folders in the App Launcher"> - OEM Folder - </message> - <message name="IDS_APP_LIST_CROSTINI_DEFAULT_FOLDER_NAME" desc="The default name for the Linux (Crostini) apps folder in the App Launcher"> - Linux Apps - </message> - </if> + <message name="IDS_APP_LIST_CONTEXT_MENU_NEW_TAB" desc="Title text for the 'open new' context menu item of an app list item configured to open in a tab"> + New tab + </message> + <message name="IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW" desc="Title text for the 'open new' context menu item of an app list item configured to open windowed"> + New window + </message> + <message name="IDS_APP_LIST_CONTEXT_MENU_PIN" desc="Title text for the 'pin' context menu item of an app list item."> + Pin to shelf + </message> + <message name="IDS_APP_LIST_CONTEXT_MENU_UNPIN" desc="Title text for the 'unpin' context menu item of an app list item."> + Unpin from shelf + </message> + <message name="IDS_APP_LIST_CONTEXT_MENU_PIN_ENFORCED_BY_POLICY" desc="Short text for the pin/unpin context menu to tell user the setting is enforced by policy of an app list item"> + Pinned by administrator + </message> + <message name="IDS_APP_LIST_UNINSTALL_ITEM" + desc="Title text for the 'uninstall' context menu item of an app list item."> + Uninstall + </message> + <message name="IDS_APP_LIST_REMOVE_SHORTCUT" + desc="Title text for the 'remove' context menu item of an app list shortcut item."> + Remove + </message> + <message name="IDS_APP_LIST_NEW_WINDOW" desc="The text label of the New Window menu item"> + New window + </message> + <message name="IDS_APP_LIST_NEW_INCOGNITO_WINDOW" desc="The text label of the New incognito window menu item"> + New incognito window + </message> + <message name="IDS_APP_LIST_OEM_DEFAULT_FOLDER_NAME" desc="The default name for OEM folders in the App Launcher"> + OEM folder + </message> + <message name="IDS_APP_LIST_CROSTINI_DEFAULT_FOLDER_NAME" desc="The default name for the Linux (Crostini) apps folder in the App Launcher"> + Linux apps + </message> </if> <!-- Translated apps strings -->
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd index 7fdba8c7..a1e7470 100644 --- a/chrome/app/google_chrome_strings.grd +++ b/chrome/app/google_chrome_strings.grd
@@ -677,17 +677,10 @@ </message> <!-- App list --> - <if expr="enable_app_list"> - <if expr="not use_titlecase"> - <message name="IDS_APP_LIST_EXTENSIONS_UNINSTALL" desc="Title text for the context menu item of a non-platform-app app list item that removes the app."> - Remove from Chrome... - </message> - </if> - <if expr="use_titlecase"> - <message name="IDS_APP_LIST_EXTENSIONS_UNINSTALL" desc="In Title Case: Title text for the context menu item of a non-platform-app app list item that removes the app."> - Remove From Chrome... - </message> - </if> + <if expr="chromeos"> + <message name="IDS_APP_LIST_EXTENSIONS_UNINSTALL" desc="Title text for the context menu item of a non-platform-app app list item that removes the app."> + Remove from Chrome... + </message> </if> <!-- App shortcuts -->
diff --git a/chrome/app/theme/chrome_unscaled_resources.grd b/chrome/app/theme/chrome_unscaled_resources.grd index 00fe281..e055fd5 100644 --- a/chrome/app/theme/chrome_unscaled_resources.grd +++ b/chrome/app/theme/chrome_unscaled_resources.grd
@@ -109,23 +109,6 @@ <include name="IDR_PROFILE_AVATAR_2X_25" file="default_200_percent/common/profile_avatar_sun_cloud.png" type="BINDATA" /> <include name="IDR_PROFILE_AVATAR_2X_26" file="default_200_percent/common/profile_avatar_placeholder.png" type="BINDATA" /> </if> - <if expr="is_linux and enable_app_list"> - <!-- App Launcher icons for desktop icon. --> - <if expr="_google_chrome"> - <then> - <include name="IDR_APP_LIST_16" file="google_chrome/linux/app_list_16.png" type="BINDATA" /> - <include name="IDR_APP_LIST_32" file="google_chrome/linux/app_list_32.png" type="BINDATA" /> - <include name="IDR_APP_LIST_48" file="google_chrome/linux/app_list_48.png" type="BINDATA" /> - <include name="IDR_APP_LIST_256" file="google_chrome/linux/app_list_256.png" type="BINDATA" /> - </then> - <else> - <include name="IDR_APP_LIST_16" file="chromium/linux/app_list_16.png" type="BINDATA" /> - <include name="IDR_APP_LIST_32" file="chromium/linux/app_list_32.png" type="BINDATA" /> - <include name="IDR_APP_LIST_48" file="chromium/linux/app_list_48.png" type="BINDATA" /> - <include name="IDR_APP_LIST_256" file="chromium/linux/app_list_256.png" type="BINDATA" /> - </else> - </if> - </if> <if expr="is_macosx"> <include name="IDR_APPS_FOLDER_16" file="mac/apps_folder_16.png" type="BINDATA" /> <include name="IDR_APPS_FOLDER_32" file="mac/apps_folder_32.png" type="BINDATA" />
diff --git a/chrome/app/theme/chromium/linux/app_list_16.png b/chrome/app/theme/chromium/linux/app_list_16.png deleted file mode 100644 index 1212a8d..0000000 --- a/chrome/app/theme/chromium/linux/app_list_16.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/chromium/linux/app_list_256.png b/chrome/app/theme/chromium/linux/app_list_256.png deleted file mode 100644 index a78a3a636..0000000 --- a/chrome/app/theme/chromium/linux/app_list_256.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/chromium/linux/app_list_32.png b/chrome/app/theme/chromium/linux/app_list_32.png deleted file mode 100644 index d5b26cd..0000000 --- a/chrome/app/theme/chromium/linux/app_list_32.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/chromium/linux/app_list_48.png b/chrome/app/theme/chromium/linux/app_list_48.png deleted file mode 100644 index 88dea89..0000000 --- a/chrome/app/theme/chromium/linux/app_list_48.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 7273eaf5..4644c026 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3064,6 +3064,8 @@ "enterprise_reporting/profile_report_generator.h", "enterprise_reporting/report_generator.cc", "enterprise_reporting/report_generator.h", + "enterprise_reporting/report_request_queue_generator.cc", + "enterprise_reporting/report_request_queue_generator.h", "enterprise_reporting/report_scheduler.cc", "enterprise_reporting/report_scheduler.h", "enterprise_reporting/report_uploader.cc", @@ -5690,6 +5692,10 @@ "chromeos/policy/fake_device_cloud_policy_manager.h", "chromeos/settings/device_settings_test_helper.cc", "chromeos/settings/device_settings_test_helper.h", + "ui/app_list/test/chrome_app_list_test_support.cc", + "ui/app_list/test/chrome_app_list_test_support.h", + "ui/app_list/test/test_app_list_controller_delegate.cc", + "ui/app_list/test/test_app_list_controller_delegate.h", ] configs += [ "//build/config/linux/dbus" ] deps += [ "//chromeos:test_support" ] @@ -5702,15 +5708,6 @@ ] } - if (enable_app_list) { - sources += [ - "ui/app_list/test/chrome_app_list_test_support.cc", - "ui/app_list/test/chrome_app_list_test_support.h", - "ui/app_list/test/test_app_list_controller_delegate.cc", - "ui/app_list/test/test_app_list_controller_delegate.h", - ] - } - if (enable_extensions) { sources += [ "extensions/api/messaging/native_messaging_test_util.cc",
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index c2582b9..fc86654 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -84,7 +84,7 @@ <include name="IDR_CERTIFICATE_VIEWER_JS" file="resources\certificate_viewer.js" compress="gzip" type="BINDATA" /> <include name="IDR_CERTIFICATE_VIEWER_CSS" file="resources\certificate_viewer.css" compress="gzip" type="BINDATA" /> </if> - <if expr="enable_app_list"> + <if expr="chromeos"> <include name="IDR_CHROME_APP_MANIFEST" file="resources\chrome_app\manifest.json" type="BINDATA" /> </if> <if expr="enable_printing">
diff --git a/chrome/browser/chromeos/printing/printer_info_cups.cc b/chrome/browser/chromeos/printing/printer_info_cups.cc index 4a03c50..e1236e96 100644 --- a/chrome/browser/chromeos/printing/printer_info_cups.cc +++ b/chrome/browser/chromeos/printing/printer_info_cups.cc
@@ -38,6 +38,21 @@ ::printing::PrinterInfo printer_info; }; +// Enums for Printing.CUPS.HighestIppVersion. Do not delete entries. Keep +// synced with enums.xml. Represents IPP versions 1.0, 1.1, 2.0, 2.1, and 2.2. +// Error is used if the version was unparsable. OutOfRange is used for values +// that are not currently mapped. +enum class IppVersion { + kError, + kUnknown, + k10, + k11, + k20, + k21, + k22, + kMaxValue = k22 +}; + // Returns the length of the portion of |make_and_model| representing the // manufacturer. This is either a value from kMultiWordManufacaturers or the // first token. If there is only one token or less, we assume that it does not @@ -56,6 +71,38 @@ return first_space != base::StringPiece::npos ? first_space : 0; } +using MajorMinor = std::pair<uint32_t, uint32_t>; +using VersionEntry = std::pair<MajorMinor, IppVersion>; + +IppVersion ToIppVersion(const base::Version& version) { + constexpr std::array<VersionEntry, 5> kVersions = { + VersionEntry(MajorMinor((uint32_t)1, (uint32_t)0), IppVersion::k10), + VersionEntry(MajorMinor((uint32_t)1, (uint32_t)1), IppVersion::k11), + VersionEntry(MajorMinor((uint32_t)2, (uint32_t)0), IppVersion::k20), + VersionEntry(MajorMinor((uint32_t)2, (uint32_t)1), IppVersion::k21), + VersionEntry(MajorMinor((uint32_t)2, (uint32_t)2), IppVersion::k22)}; + + if (!version.IsValid()) { + return IppVersion::kError; + } + + const auto& components = version.components(); + if (components.size() != 2) { + return IppVersion::kError; + } + + const auto target = MajorMinor(components[0], components[1]); + auto iter = std::find_if( + kVersions.begin(), kVersions.end(), + [target](const VersionEntry& entry) { return entry.first == target; }); + + if (iter == kVersions.end()) { + return IppVersion::kUnknown; + } + + return iter->second; +} + // Returns true if any of the |ipp_versions| are greater than or equal to 2.0. bool AllowedIpp(const std::vector<base::Version>& ipp_versions) { auto found = @@ -130,6 +177,12 @@ base::UmaHistogramBoolean(kPwgRasterDocumentResolutionSupported, printer_info.supports_pwg_raster_resolution); + DCHECK(!printer_info.ipp_versions.empty()) + << "Properly queried PrinterInfo always has at least one version"; + base::UmaHistogramEnumeration( + "Printing.CUPS.HighestIppVersion", + ToIppVersion(*std::max_element(printer_info.ipp_versions.begin(), + printer_info.ipp_versions.end()))); std::move(callback).Run( result, make.as_string(), model.as_string(), printer_info.make_and_model,
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index bcd21973..639e8b8 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc
@@ -22,6 +22,7 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/guid.h" #include "base/memory/ref_counted.h" #include "base/path_service.h" #include "base/run_loop.h" @@ -49,17 +50,20 @@ #include "chrome/browser/download/download_crx_util.h" #include "chrome/browser/download/download_history.h" #include "chrome/browser/download/download_item_model.h" +#include "chrome/browser/download/download_manager_utils.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/download/download_request_limiter.h" #include "chrome/browser/download/download_shelf.h" #include "chrome/browser/download/download_target_determiner.h" #include "chrome/browser/download/download_test_file_activity_observer.h" +#include "chrome/browser/download/simple_download_manager_coordinator_factory.h" #include "chrome/browser/extensions/install_verifier.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/metrics/subprocess_metrics_provider.h" #include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h" #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h" #include "chrome/browser/reputation/safety_tip_test_utils.h" @@ -84,6 +88,7 @@ #include "components/download/public/common/download_danger_type.h" #include "components/download/public/common/download_interrupt_reasons.h" #include "components/download/public/common/download_item.h" +#include "components/download/public/common/in_progress_download_manager.h" #include "components/history/content/browser/download_conversions.h" #include "components/history/core/browser/download_constants.h" #include "components/history/core/browser/download_row.h" @@ -396,6 +401,65 @@ } #endif +class SimpleDownloadManagerCoordinatorWaiter + : public download::SimpleDownloadManagerCoordinator::Observer { + public: + explicit SimpleDownloadManagerCoordinatorWaiter( + download::SimpleDownloadManagerCoordinator* coordinator) + : coordinator_(coordinator) { + coordinator_->AddObserver(this); + } + + ~SimpleDownloadManagerCoordinatorWaiter() override { + if (coordinator_) + coordinator_->RemoveObserver(this); + } + + void WaitForInitialization() { + if (coordinator_ && coordinator_->initialized()) + return; + base::RunLoop run_loop; + completion_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + return; + } + + private: + void OnDownloadsInitialized(bool active_downloads_only) override { + if (completion_closure_) + std::move(completion_closure_).Run(); + } + + void OnManagerGoingDown( + download::SimpleDownloadManagerCoordinator* coordinator) override { + DCHECK_EQ(coordinator_, coordinator); + coordinator_->RemoveObserver(this); + coordinator_ = nullptr; + } + + download::SimpleDownloadManagerCoordinator* coordinator_; + base::OnceClosure completion_closure_; +}; + +void CreateCompletedDownload(content::DownloadManager* download_manager, + const std::string& guid, + const base::FilePath target_path, + std::vector<GURL> url_chain, + int64_t file_size) { + base::Time current_time = base::Time::Now(); + download_manager->CreateDownloadItem( + guid, 1 /* id */, target_path, target_path, url_chain, + GURL() /* referrer_url */, GURL() /* site_url */, GURL() /* tab_url */, + GURL() /* tab_referrer_url */, url::Origin() /* request_initiator */, + "" /* mime_type */, "" /* original_mime_type */, current_time, + current_time, "" /* etag */, "" /* last_modified */, file_size, file_size, + "" /* hash */, download::DownloadItem::COMPLETE, + download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED, + download::DOWNLOAD_INTERRUPT_REASON_NONE, false /* opened */, + current_time, false /* transient */, + std::vector<download::DownloadItem::ReceivedSlice>()); +} + } // namespace DownloadTestObserverNotInProgress::DownloadTestObserverNotInProgress( @@ -494,6 +558,7 @@ DownloadTest() {} void SetUpOnMainThread() override { + ASSERT_TRUE(CheckTestDir()); ASSERT_TRUE(InitialSetup()); host_resolver()->AddRule("www.a.com", "127.0.0.1"); host_resolver()->AddRule("foo.com", "127.0.0.1"); @@ -508,15 +573,16 @@ file_activity_observer_.reset(); } - // Returning false indicates a failure of the setup, and should be asserted - // in the caller. - bool InitialSetup() { + bool CheckTestDir() { bool have_test_dir = base::PathService::Get(chrome::DIR_TEST_DATA, &test_dir_); EXPECT_TRUE(have_test_dir); - if (!have_test_dir) - return false; + return have_test_dir; + } + // Returning false indicates a failure of the setup, and should be asserted + // in the caller. + bool InitialSetup() { // Sanity check default values for window and tab count. int window_count = chrome::GetTotalBrowserCount(); EXPECT_EQ(1, window_count); @@ -4094,6 +4160,86 @@ ASSERT_EQ(downloaded_data, png_data); } +// Testing the behavior of resuming with only in-progress download manager. +class InProgressDownloadTest : public DownloadTest { + public: + void SetUpOnMainThread() override { EXPECT_TRUE(CheckTestDir()); } +}; + +// Check that if a download exists in both in-progress and history DB, +// resuming the download after loading the in-progress DB and before +// history initialization will continue downloading the item even if it +// is in a terminal state in history DB. +IN_PROC_BROWSER_TEST_F(InProgressDownloadTest, + ResumeInProgressDownloadBeforeLoadingHistory) { + embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory()); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url = embedded_test_server()->GetURL("/downloads/a_zip_file.zip"); + base::FilePath origin(OriginFile( + base::FilePath(FILE_PATH_LITERAL("downloads/a_zip_file.zip")))); + base::ScopedAllowBlockingForTesting allow_blocking; + ASSERT_TRUE(base::PathExists(origin)); + // Gets the file size. + int64_t origin_file_size = 0; + EXPECT_TRUE(base::GetFileSize(origin, &origin_file_size)); + std::string guid = base::GenerateGUID(); + + // Wait for in-progress download manager to initialize. + download::InProgressDownloadManager* in_progress_manager = + DownloadManagerUtils::GetInProgressDownloadManager( + browser()->profile()->GetProfileKey()); + download::SimpleDownloadManagerCoordinator* coordinator = + SimpleDownloadManagerCoordinatorFactory::GetForKey( + browser()->profile()->GetProfileKey()); + SimpleDownloadManagerCoordinatorWaiter coordinator_waiter(coordinator); + coordinator_waiter.WaitForInitialization(); + + base::FilePath target_path; + ASSERT_TRUE( + base::PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &target_path)); + target_path = + target_path.Append(base::FilePath(FILE_PATH_LITERAL("a_zip_file.zip"))); + std::vector<GURL> url_chain; + url_chain.emplace_back(url); + base::Time current_time = base::Time::Now(); + in_progress_manager->AddInProgressDownloadForTest( + std::make_unique<download::DownloadItemImpl>( + in_progress_manager, guid, 1 /* id */, + target_path.AddExtensionASCII("crdownload"), target_path, url_chain, + GURL() /* referrer_url */, GURL() /* site_url */, + GURL() /* tab_url */, GURL() /* tab_referrer_url */, + url::Origin() /* request_initiator */, "" /* mime_type */, + "" /* original_mime_type */, current_time, current_time, + "" /* etag */, "" /* last_modified */, 0 /* received_bytes */, + origin_file_size, 0 /* auto_resume_count */, "" /* hash */, + download::DownloadItem::INTERRUPTED, + download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED, + download::DOWNLOAD_INTERRUPT_REASON_CRASH, false /* paused */, + false /* allow_metered */, false /* opened */, current_time, + false /* transient */, + std::vector<download::DownloadItem::ReceivedSlice>(), + nullptr /* download_entry */)); + + download::DownloadItem* download = coordinator->GetDownloadByGuid(guid); + content::DownloadManager* manager = DownloadManagerForBrowser(browser()); + DownloadCoreService* service = + DownloadCoreServiceFactory::GetForBrowserContext(browser()->profile()); + service->SetDownloadHistoryForTesting(nullptr); + + ASSERT_TRUE(download); + PercentWaiter waiter(download); + // Resume the download first, before download history loads. + download->Resume(true); + // Now simulate that history DB is loaded. + manager->OnHistoryQueryComplete( + base::Bind(CreateCompletedDownload, base::Unretained(manager), guid, + target_path, std::move(url_chain), origin_file_size)); + // Download should continue and complete. + ASSERT_TRUE(waiter.WaitForFinished()); + download::DownloadItem* history_download = manager->GetDownloadByGuid(guid); + CHECK_EQ(download, history_download); +} + #if BUILDFLAG(FULL_SAFE_BROWSING) namespace {
diff --git a/chrome/browser/download/download_core_service.h b/chrome/browser/download/download_core_service.h index d825c09..d4845d2b 100644 --- a/chrome/browser/download/download_core_service.h +++ b/chrome/browser/download/download_core_service.h
@@ -8,11 +8,11 @@ #include <memory> #include "base/macros.h" +#include "chrome/browser/download/download_history.h" #include "components/keyed_service/core/keyed_service.h" #include "extensions/buildflags/buildflags.h" class ChromeDownloadManagerDelegate; -class DownloadHistory; class ExtensionDownloadsEventRouter; namespace content { @@ -65,6 +65,12 @@ virtual void SetDownloadManagerDelegateForTesting( std::unique_ptr<ChromeDownloadManagerDelegate> delegate) = 0; + // Sets the DownloadHistory associated with this object and + // its DownloadManager. Takes ownership of |download_history|, and destroys + // the previous delegate. For testing. + virtual void SetDownloadHistoryForTesting( + std::unique_ptr<DownloadHistory> download_history) {} + // Returns false if at least one extension has disabled the shelf, true // otherwise. virtual bool IsShelfEnabled() = 0;
diff --git a/chrome/browser/download/download_core_service_impl.cc b/chrome/browser/download/download_core_service_impl.cc index 92ae214..3d1e5e6 100644 --- a/chrome/browser/download/download_core_service_impl.cc +++ b/chrome/browser/download/download_core_service_impl.cc
@@ -142,6 +142,11 @@ new_delegate->Shutdown(); } +void DownloadCoreServiceImpl::SetDownloadHistoryForTesting( + std::unique_ptr<DownloadHistory> download_history) { + download_history_ = std::move(download_history); +} + bool DownloadCoreServiceImpl::IsShelfEnabled() { #if defined(OS_ANDROID) return true;
diff --git a/chrome/browser/download/download_core_service_impl.h b/chrome/browser/download/download_core_service_impl.h index a42d8a0..6536439 100644 --- a/chrome/browser/download/download_core_service_impl.h +++ b/chrome/browser/download/download_core_service_impl.h
@@ -49,6 +49,8 @@ void SetDownloadManagerDelegateForTesting( std::unique_ptr<ChromeDownloadManagerDelegate> delegate) override; bool IsShelfEnabled() override; + void SetDownloadHistoryForTesting( + std::unique_ptr<DownloadHistory> download_history) override; // KeyedService void Shutdown() override;
diff --git a/chrome/browser/enterprise_reporting/report_generator.cc b/chrome/browser/enterprise_reporting/report_generator.cc index b46debd..1d9bf0e2 100644 --- a/chrome/browser/enterprise_reporting/report_generator.cc +++ b/chrome/browser/enterprise_reporting/report_generator.cc
@@ -8,8 +8,6 @@ #include "base/bind.h" #include "base/files/file_path.h" -#include "base/metrics/histogram_functions.h" -#include "base/path_service.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "components/policy/core/common/cloud/cloud_policy_util.h" @@ -21,27 +19,8 @@ namespace em = enterprise_management; namespace enterprise_reporting { -namespace { -const size_t kMaximumReportSize = - 5000000; // The report size limitation is 5mb. - -constexpr char kRequestCountMetricsName[] = - "Enterprise.CloudReportingRequestCount"; -constexpr char kRequestSizeMetricsName[] = - "Enterprise.CloudReportingRequestSize"; -constexpr char kBasicRequestSizeMetricsName[] = - "Enterprise.CloudReportingBasicRequestSize"; - -// Because server only stores 20 profiles for each report and when report is -// separated into requests, there is at least one profile per request. It means -// server will truncate the report when there are more than 20 requests. Actions -// are needed if there are many reports exceed this limitation. -const int kRequestCountMetricMaxValue = 21; - -} // namespace - -ReportGenerator::ReportGenerator() : maximum_report_size_(kMaximumReportSize) {} +ReportGenerator::ReportGenerator() = default; ReportGenerator::~ReportGenerator() = default; @@ -52,14 +31,17 @@ } void ReportGenerator::SetMaximumReportSizeForTesting(size_t size) { - maximum_report_size_ = size; + report_request_queue_generator_.SetMaximumReportSizeForTesting(size); } void ReportGenerator::CreateBasicRequest() { +#if !defined(OS_CHROMEOS) basic_request_.set_computer_name(this->GetMachineName()); basic_request_.set_os_user_name(GetOSUserName()); basic_request_.set_serial_number(GetSerialNumber()); basic_request_.set_allocated_os_report(GetOSReport().release()); +#endif + browser_report_generator_.Generate(base::BindOnce( &ReportGenerator::OnBrowserReportReady, weak_ptr_factory_.GetWeakPtr())); } @@ -89,89 +71,11 @@ #endif } -void ReportGenerator::GenerateProfileReportWithIndex(int profile_index) { - DCHECK_LT(profile_index, - basic_request_.browser_report().chrome_user_profile_infos_size()); - - auto basic_profile_report = - basic_request_.browser_report().chrome_user_profile_infos(profile_index); - auto profile_report = profile_report_generator_.MaybeGenerate( - base::FilePath::FromUTF8Unsafe(basic_profile_report.id()), - basic_profile_report.name()); - - // Return if Profile is not loaded and there is no full report. - if (!profile_report) { - return; - } - - // Use size diff to calculate estimated request size after full profile report - // is added. There are still few bytes difference but close enough. - size_t profile_report_incremental_size = - profile_report->ByteSizeLong() - - basic_request_.browser_report() - .chrome_user_profile_infos(profile_index) - .ByteSizeLong(); - size_t current_request_size = requests_.back()->ByteSizeLong(); - - if (current_request_size + profile_report_incremental_size <= - maximum_report_size_) { - // The new full Profile report can be appended into the current request. - requests_.back() - ->mutable_browser_report() - ->mutable_chrome_user_profile_infos(profile_index) - ->Swap(profile_report.get()); - } else if (basic_request_size_ + profile_report_incremental_size <= - maximum_report_size_) { - // The new full Profile report is too big to be appended into the current - // request, move it to the next request if possible. Record metrics for the - // current request's size. - base::UmaHistogramMemoryKB(kRequestSizeMetricsName, - requests_.back()->ByteSizeLong() / 1024); - requests_.push( - std::make_unique<em::ChromeDesktopReportRequest>(basic_request_)); - requests_.back() - ->mutable_browser_report() - ->mutable_chrome_user_profile_infos(profile_index) - ->Swap(profile_report.get()); - } else { - // The new full Profile report is too big to be uploaded, skip this - // Profile report. But we still add the report size into metrics so - // that we could understand the situation better. - base::UmaHistogramMemoryKB( - kRequestSizeMetricsName, - (basic_request_size_ + profile_report_incremental_size) / 1024); - } -} - void ReportGenerator::OnBrowserReportReady( std::unique_ptr<em::BrowserReport> browser_report) { basic_request_.set_allocated_browser_report(browser_report.release()); - basic_request_size_ = basic_request_.ByteSizeLong(); - base::UmaHistogramMemoryKB(kBasicRequestSizeMetricsName, - basic_request_size_ / 1024); - if (basic_request_size_ > maximum_report_size_) { - // Basic request is already too large so we can't upload any valid report. - // Skip all Profiles and response an empty request list. - Response(); - return; - } - - requests_.push( - std::make_unique<em::ChromeDesktopReportRequest>(basic_request_)); - for (int index = 0; - index < basic_request_.browser_report().chrome_user_profile_infos_size(); - index++) { - GenerateProfileReportWithIndex(index); - } - base::UmaHistogramMemoryKB(kRequestSizeMetricsName, - requests_.back()->ByteSizeLong() / 1024); - Response(); -} - -void ReportGenerator::Response() { - base::UmaHistogramExactLinear(kRequestCountMetricsName, requests_.size(), - kRequestCountMetricMaxValue); - std::move(callback_).Run(std::move(requests_)); + Requests requests = report_request_queue_generator_.Generate(basic_request_); + std::move(callback_).Run(std::move(requests)); } } // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise_reporting/report_generator.h b/chrome/browser/enterprise_reporting/report_generator.h index 894414f..d99f82d 100644 --- a/chrome/browser/enterprise_reporting/report_generator.h +++ b/chrome/browser/enterprise_reporting/report_generator.h
@@ -12,7 +12,7 @@ #include "base/macros.h" #include "chrome/browser/enterprise_reporting/browser_report_generator.h" -#include "chrome/browser/enterprise_reporting/profile_report_generator.h" +#include "chrome/browser/enterprise_reporting/report_request_queue_generator.h" #include "components/policy/proto/device_management_backend.pb.h" namespace em = enterprise_management; @@ -21,7 +21,12 @@ class ReportGenerator { public: - using Requests = std::queue<std::unique_ptr<em::ChromeDesktopReportRequest>>; +#if defined(OS_CHROMEOS) + using Request = em::ChromeOsUserReportRequest; +#else + using Request = em::ChromeDesktopReportRequest; +#endif + using Requests = std::queue<std::unique_ptr<Request>>; using ReportCallback = base::OnceCallback<void(Requests)>; ReportGenerator(); @@ -50,24 +55,13 @@ virtual std::string GetSerialNumber(); private: - void GenerateProfileReportWithIndex(int profile_index); - void OnBrowserReportReady(std::unique_ptr<em::BrowserReport> browser_report); - void Response(); - - ProfileReportGenerator profile_report_generator_; + ReportRequestQueueGenerator report_request_queue_generator_; BrowserReportGenerator browser_report_generator_; - ReportCallback callback_; - - Requests requests_; - // Basic information that is shared among requests. - em::ChromeDesktopReportRequest basic_request_; - size_t basic_request_size_; - - size_t maximum_report_size_; + Request basic_request_; base::WeakPtrFactory<ReportGenerator> weak_ptr_factory_{this};
diff --git a/chrome/browser/enterprise_reporting/report_request_queue_generator.cc b/chrome/browser/enterprise_reporting/report_request_queue_generator.cc new file mode 100644 index 0000000..23b5ed4 --- /dev/null +++ b/chrome/browser/enterprise_reporting/report_request_queue_generator.cc
@@ -0,0 +1,126 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/enterprise_reporting/report_request_queue_generator.h" + +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/files/file_path.h" +#include "base/metrics/histogram_functions.h" + +namespace enterprise_reporting { +namespace { + +const size_t kMaximumReportSize = + 5000000; // The report size limitation is 5mb. + +constexpr char kRequestCountMetricsName[] = + "Enterprise.CloudReportingRequestCount"; +constexpr char kRequestSizeMetricsName[] = + "Enterprise.CloudReportingRequestSize"; +constexpr char kBasicRequestSizeMetricsName[] = + "Enterprise.CloudReportingBasicRequestSize"; + +// Because server only stores 20 profiles for each report and when report is +// separated into requests, there is at least one profile per request. It means +// server will truncate the report when there are more than 20 requests. Actions +// are needed if there are many reports exceed this limitation. +const int kRequestCountMetricMaxValue = 21; + +} // namespace + +ReportRequestQueueGenerator::ReportRequestQueueGenerator() + : maximum_report_size_(kMaximumReportSize) {} + +ReportRequestQueueGenerator::~ReportRequestQueueGenerator() = default; + +size_t ReportRequestQueueGenerator::GetMaximumReportSizeForTesting() const { + return maximum_report_size_; +} + +void ReportRequestQueueGenerator::SetMaximumReportSizeForTesting( + size_t maximum_report_size) { + maximum_report_size_ = maximum_report_size; +} + +ReportRequestQueueGenerator::ReportRequests +ReportRequestQueueGenerator::Generate(const ReportRequest& basic_request) { + ReportRequests requests; + size_t basic_request_size = basic_request.ByteSizeLong(); + base::UmaHistogramMemoryKB(kBasicRequestSizeMetricsName, + basic_request_size / 1024); + + if (basic_request_size <= maximum_report_size_) { + requests.push(std::make_unique<ReportRequest>(basic_request)); + int profile_infos_size = + basic_request.browser_report().chrome_user_profile_infos_size(); + for (int index = 0; index < profile_infos_size; index++) { + GenerateProfileReportWithIndex(basic_request, index, &requests); + } + + base::UmaHistogramMemoryKB(kRequestSizeMetricsName, + requests.back()->ByteSizeLong() / 1024); + } + + base::UmaHistogramExactLinear(kRequestCountMetricsName, requests.size(), + kRequestCountMetricMaxValue); + return requests; +} + +void ReportRequestQueueGenerator::GenerateProfileReportWithIndex( + const ReportRequest& basic_request, + int profile_index, + ReportRequests* requests) { + DCHECK_LT(profile_index, + basic_request.browser_report().chrome_user_profile_infos_size()); + + size_t basic_request_size = basic_request.ByteSizeLong(); + auto basic_profile = + basic_request.browser_report().chrome_user_profile_infos(profile_index); + auto profile_report = profile_report_generator_.MaybeGenerate( + base::FilePath::FromUTF8Unsafe(basic_profile.id()), basic_profile.name()); + + // Return if Profile is not loaded and there is no full report. + if (!profile_report) + return; + + // Use size diff to calculate estimated request size after full profile report + // is added. There are still few bytes difference but close enough. + size_t profile_report_incremental_size = + profile_report->ByteSizeLong() - basic_profile.ByteSizeLong(); + size_t current_request_size = requests->back()->ByteSizeLong(); + + if (current_request_size + profile_report_incremental_size <= + maximum_report_size_) { + // The new full Profile report can be appended into the current request. + requests->back() + ->mutable_browser_report() + ->mutable_chrome_user_profile_infos(profile_index) + ->Swap(profile_report.get()); + } else if (basic_request_size + profile_report_incremental_size <= + maximum_report_size_) { + // The new full Profile report is too big to be appended into the current + // request, move it to the next request if possible. Record metrics for the + // current request's size. + base::UmaHistogramMemoryKB(kRequestSizeMetricsName, + requests->back()->ByteSizeLong() / 1024); + requests->push(std::make_unique<ReportRequest>(basic_request)); + requests->back() + ->mutable_browser_report() + ->mutable_chrome_user_profile_infos(profile_index) + ->Swap(profile_report.get()); + } else { + // The new full Profile report is too big to be uploaded, skip this + // Profile report. But we still add the report size into metrics so + // that we could understand the situation better. + base::UmaHistogramMemoryKB( + kRequestSizeMetricsName, + (basic_request_size + profile_report_incremental_size) / 1024); + } +} + +} // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise_reporting/report_request_queue_generator.h b/chrome/browser/enterprise_reporting/report_request_queue_generator.h new file mode 100644 index 0000000..8e003ce4 --- /dev/null +++ b/chrome/browser/enterprise_reporting/report_request_queue_generator.h
@@ -0,0 +1,66 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ENTERPRISE_REPORTING_REPORT_REQUEST_QUEUE_GENERATOR_H_ +#define CHROME_BROWSER_ENTERPRISE_REPORTING_REPORT_REQUEST_QUEUE_GENERATOR_H_ + +#include <memory> +#include <queue> + +#include "base/callback_forward.h" +#include "base/macros.h" +#include "build/build_config.h" +#include "chrome/browser/enterprise_reporting/profile_report_generator.h" +#include "components/policy/proto/device_management_backend.pb.h" + +namespace em = enterprise_management; + +namespace enterprise_reporting { + +// Generate a report request queue that contains full profile information. The +// request number in the queue is decided by the maximum report size setting. +class ReportRequestQueueGenerator { +#if defined(OS_CHROMEOS) + using ReportRequest = em::ChromeOsUserReportRequest; +#else + using ReportRequest = em::ChromeDesktopReportRequest; +#endif + + using ReportRequests = std::queue<std::unique_ptr<ReportRequest>>; + using BrowserReportGetter = + base::RepeatingCallback<em::BrowserReport*(ReportRequest*)>; + + public: + explicit ReportRequestQueueGenerator(); + ReportRequestQueueGenerator(const ReportRequestQueueGenerator&) = delete; + ReportRequestQueueGenerator& operator=(const ReportRequestQueueGenerator&) = + delete; + ~ReportRequestQueueGenerator(); + + // Get the maximum report size. + size_t GetMaximumReportSizeForTesting() const; + + // Set the maximum report size. The full profile info will be skipped or moved + // to another new request if its size exceeds the limit. + void SetMaximumReportSizeForTesting(size_t maximum_report_size); + + // Generate a queue of requests including full profile info based on given + // basic request. + ReportRequests Generate(const ReportRequest& basic_request); + + private: + // Generate request with full profile info at |profile_index| according to + // |basic_request|, then store it into |requests|. + void GenerateProfileReportWithIndex(const ReportRequest& basic_request, + int profile_index, + ReportRequests* requests); + + private: + size_t maximum_report_size_; + ProfileReportGenerator profile_report_generator_; +}; + +} // namespace enterprise_reporting + +#endif // CHROME_BROWSER_ENTERPRISE_REPORTING_REPORT_REQUEST_QUEUE_GENERATOR_H_
diff --git a/chrome/browser/enterprise_reporting/report_request_queue_generator_unittest.cc b/chrome/browser/enterprise_reporting/report_request_queue_generator_unittest.cc new file mode 100644 index 0000000..5d4808e --- /dev/null +++ b/chrome/browser/enterprise_reporting/report_request_queue_generator_unittest.cc
@@ -0,0 +1,278 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/enterprise_reporting/report_request_queue_generator.h" + +#include <vector> + +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/bind_test_util.h" +#include "base/test/metrics/histogram_tester.h" +#include "build/build_config.h" +#include "chrome/browser/enterprise_reporting/browser_report_generator.h" +#include "chrome/browser/profiles/profile_attributes_storage.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "components/account_id/account_id.h" +#include "content/public/browser/plugin_service.h" +#include "content/public/test/browser_task_environment.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/common/extension_builder.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace em = enterprise_management; + +namespace enterprise_reporting { +namespace { + +const char kIdleProfileName1[] = "idle_profile1"; +const char kIdleProfileName2[] = "idle_profile2"; +const char kActiveProfileName1[] = "active_profile1"; +const char kActiveProfileName2[] = "active_profile2"; + +} // namespace + +class ReportRequestQueueGeneratorTest : public ::testing::Test { + public: +#if defined(OS_CHROMEOS) + using Request = em::ChromeOsUserReportRequest; +#else + using Request = em::ChromeDesktopReportRequest; +#endif + + ReportRequestQueueGeneratorTest() + : profile_manager_(TestingBrowserProcess::GetGlobal()) {} + + ~ReportRequestQueueGeneratorTest() override = default; + + void SetUp() override { + ASSERT_TRUE(profile_manager_.SetUp()); + profile_manager_.CreateGuestProfile(); + profile_manager_.CreateSystemProfile(); + content::PluginService::GetInstance()->Init(); + } + + std::set<std::string> CreateIdleProfiles() { + CreateIdleProfile(kIdleProfileName1); + CreateIdleProfile(kIdleProfileName2); + return std::set<std::string>{kIdleProfileName1, kIdleProfileName2}; + } + + std::set<std::string> CreateActiveProfiles() { + CreateActiveProfile(kActiveProfileName1); + CreateActiveProfile(kActiveProfileName2); + return std::set<std::string>{kActiveProfileName1, kActiveProfileName2}; + } + + std::set<std::string> CreateActiveProfilesWithContent() { + CreateActiveProfileWithContent(kActiveProfileName1); + CreateActiveProfileWithContent(kActiveProfileName2); + return std::set<std::string>{kActiveProfileName1, kActiveProfileName2}; + } + + void CreateIdleProfile(std::string profile_name) { + profile_manager_.profile_attributes_storage()->AddProfile( + profile_manager()->profiles_dir().AppendASCII(profile_name), + base::ASCIIToUTF16(profile_name), std::string(), base::string16(), + false, 0, std::string(), EmptyAccountId()); + } + + TestingProfile* CreateActiveProfile(std::string profile_name) { + return profile_manager_.CreateTestingProfile(profile_name); + } + + void CreateActiveProfileWithContent(std::string profile_name) { + TestingProfile* active_profile = CreateActiveProfile(profile_name); + + extensions::ExtensionRegistry* extension_registry = + extensions::ExtensionRegistry::Get(active_profile); + std::string extension_name = + "a super super super super super super super super super super super " + "super super super super super super long extension name"; + extension_registry->AddEnabled( + extensions::ExtensionBuilder(extension_name) + .SetID("abcdefghijklmnoabcdefghijklmnoab") + .Build()); + } + + std::unique_ptr<Request> GenerateBasicRequest() { + auto request = std::make_unique<Request>(); + base::RunLoop run_loop; + + browser_report_generator_.Generate(base::BindLambdaForTesting( + [&run_loop, &request](std::unique_ptr<em::BrowserReport> report) { + request->set_allocated_browser_report(report.release()), + run_loop.Quit(); + })); + + run_loop.Run(); + return request; + } + + std::vector<std::unique_ptr<Request>> GenerateRequests( + const Request& request) { + histogram_tester_ = std::make_unique<base::HistogramTester>(); + std::queue<std::unique_ptr<Request>> requests = + report_request_queue_generator_.Generate(request); + std::vector<std::unique_ptr<Request>> result; + while (!requests.empty()) { + result.push_back(std::move(requests.front())); + requests.pop(); + } + + VerifyMetrics(result); + return result; + } + + void SetAndVerifyMaximumRequestSize(size_t size) { + report_request_queue_generator_.SetMaximumReportSizeForTesting(size); + EXPECT_EQ(size, + report_request_queue_generator_.GetMaximumReportSizeForTesting()); + } + + void VerifyProfiles(const em::BrowserReport& report, + const std::set<std::string>& idle_profile_names, + const std::set<std::string>& active_profile_names) { + EXPECT_EQ((size_t)report.chrome_user_profile_infos_size(), + idle_profile_names.size() + active_profile_names.size()); + + std::set<std::string> mutable_idle_profile_names(idle_profile_names); + std::set<std::string> mutable_active_profile_names(active_profile_names); + std::string profiles_dir = profile_manager_.profiles_dir().AsUTF8Unsafe(); + + for (auto profile : report.chrome_user_profile_infos()) { + // Verify the generated profile id, whose mapping rule varies in + // different cases. + // - Idle: <profiles_dir>/<profile_name> + // - Active: <profiles_dir>/u-<profile_name>-hash + EXPECT_EQ(0u, profile.id().find(profiles_dir)); + EXPECT_LE(0u, profile.id().find(profile.name())); + + if (profile.is_full_report()) + FindAndRemove(mutable_active_profile_names, profile.name()); + else + FindAndRemove(mutable_idle_profile_names, profile.name()); + } + + EXPECT_TRUE(mutable_idle_profile_names.empty()); + EXPECT_TRUE(mutable_active_profile_names.empty()); + } + + void VerifyMetrics(const std::vector<std::unique_ptr<Request>>& requests) { + histogram_tester_->ExpectUniqueSample( + "Enterprise.CloudReportingRequestCount", requests.size(), 1); + histogram_tester_->ExpectUniqueSample( + "Enterprise.CloudReportingBasicRequestSize", + /*basic request size floor to KB*/ 0, 1); + } + + TestingProfileManager* profile_manager() { return &profile_manager_; } + + ReportRequestQueueGenerator* report_request_queue_generator() { + return &report_request_queue_generator_; + } + + base::HistogramTester* histogram_tester() { return histogram_tester_.get(); } + + private: + void FindAndRemove(std::set<std::string>& names, const std::string& name) { + auto it = names.find(name); + EXPECT_NE(names.end(), it); + names.erase(it); + } + + content::BrowserTaskEnvironment task_environment_; + TestingProfileManager profile_manager_; + BrowserReportGenerator browser_report_generator_; + ReportRequestQueueGenerator report_request_queue_generator_; + std::unique_ptr<base::HistogramTester> histogram_tester_; + + DISALLOW_COPY_AND_ASSIGN(ReportRequestQueueGeneratorTest); +}; + +TEST_F(ReportRequestQueueGeneratorTest, GenerateReport) { + auto idle_profile_names = CreateIdleProfiles(); + auto basic_request = GenerateBasicRequest(); + auto requests = GenerateRequests(*basic_request); + EXPECT_EQ(1u, requests.size()); + + VerifyProfiles(requests[0]->browser_report(), idle_profile_names, {}); + histogram_tester()->ExpectBucketCount("Enterprise.CloudReportingRequestSize", + /*report size floor to KB*/ 0, 1); +} + +TEST_F(ReportRequestQueueGeneratorTest, GenerateActiveProfiles) { + auto idle_profile_names = CreateIdleProfiles(); + auto active_profile_names = CreateActiveProfiles(); + auto basic_request = GenerateBasicRequest(); + auto requests = GenerateRequests(*basic_request); + EXPECT_EQ(1u, requests.size()); + + VerifyProfiles(requests[0]->browser_report(), idle_profile_names, + active_profile_names); + histogram_tester()->ExpectBucketCount("Enterprise.CloudReportingRequestSize", + /*report size floor to KB*/ 0, 1); +} + +TEST_F(ReportRequestQueueGeneratorTest, BasicReportIsTooBig) { + // Set a super small limitation. + SetAndVerifyMaximumRequestSize(5); + + // Because the limitation is so small, no request can be created. + CreateIdleProfiles(); + auto basic_request = GenerateBasicRequest(); + auto requests = GenerateRequests(*basic_request); + EXPECT_EQ(0u, requests.size()); + + histogram_tester()->ExpectTotalCount("Enterprise.CloudReportingRequestSize", + 0); +} + +TEST_F(ReportRequestQueueGeneratorTest, ReportSeparation) { + CreateActiveProfilesWithContent(); + auto basic_request = GenerateBasicRequest(); + auto requests = GenerateRequests(*basic_request); + EXPECT_EQ(1u, requests.size()); + + // Set the limitation just below the size of the report so that it needs to be + // separated into two requests later. + SetAndVerifyMaximumRequestSize(requests[0]->ByteSizeLong() - 30); + requests = GenerateRequests(*basic_request); + EXPECT_EQ(2u, requests.size()); + + // The first profile is activated in the first request only while the second + // profile is activated in the second request. + VerifyProfiles(requests[0]->browser_report(), {kActiveProfileName1}, + {kActiveProfileName2}); + VerifyProfiles(requests[1]->browser_report(), {kActiveProfileName2}, + {kActiveProfileName1}); + histogram_tester()->ExpectBucketCount("Enterprise.CloudReportingRequestSize", + /*report size floor to KB*/ 0, 2); +} + +TEST_F(ReportRequestQueueGeneratorTest, ProfileReportIsTooBig) { + CreateActiveProfileWithContent(kActiveProfileName1); + auto basic_request = GenerateBasicRequest(); + auto requests = GenerateRequests(*basic_request); + EXPECT_EQ(1u, requests.size()); + + // Set the limitation just below the size of the report. + SetAndVerifyMaximumRequestSize(requests[0]->ByteSizeLong() - 30); + + // Add a smaller Profile. + CreateActiveProfile(kActiveProfileName2); + basic_request = GenerateBasicRequest(); + requests = GenerateRequests(*basic_request); + EXPECT_EQ(1u, requests.size()); + + // Only the second Profile is activated while the first one is too big to be + // reported. + VerifyProfiles(requests[0]->browser_report(), {kActiveProfileName1}, + {kActiveProfileName2}); + histogram_tester()->ExpectBucketCount("Enterprise.CloudReportingRequestSize", + /*report size floor to KB*/ 0, 2); +} + +} // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise_reporting/report_uploader.cc b/chrome/browser/enterprise_reporting/report_uploader.cc index 38795ba..18332ac 100644 --- a/chrome/browser/enterprise_reporting/report_uploader.cc +++ b/chrome/browser/enterprise_reporting/report_uploader.cc
@@ -47,10 +47,15 @@ } void ReportUploader::Upload() { - client_->UploadChromeDesktopReport( - std::make_unique<em::ChromeDesktopReportRequest>(*requests_.front()), - base::BindRepeating(&ReportUploader::OnRequestFinished, - weak_ptr_factory_.GetWeakPtr())); + auto request = std::make_unique<Request>(*requests_.front()); + auto callback = base::BindRepeating(&ReportUploader::OnRequestFinished, + weak_ptr_factory_.GetWeakPtr()); + +#if defined(OS_CHROMEOS) + // Pending for another change list for cloud_policy_client. +#else + client_->UploadChromeDesktopReport(std::move(request), std::move(callback)); +#endif } void ReportUploader::OnRequestFinished(bool status) {
diff --git a/chrome/browser/enterprise_reporting/report_uploader.h b/chrome/browser/enterprise_reporting/report_uploader.h index 44b6900..e035e1b 100644 --- a/chrome/browser/enterprise_reporting/report_uploader.h +++ b/chrome/browser/enterprise_reporting/report_uploader.h
@@ -18,7 +18,11 @@ } // namespace base namespace enterprise_management { +#if defined(OS_CHROMEOS) +class ChromeOsUserReportRequest; +#else class ChromeDesktopReportRequest; +#endif } // namespace enterprise_management namespace policy { @@ -48,7 +52,13 @@ // invalid dm token. }; - using Requests = std::queue<std::unique_ptr<em::ChromeDesktopReportRequest>>; +#if defined(OS_CHROMEOS) + using Request = em::ChromeOsUserReportRequest; +#else + using Request = em::ChromeDesktopReportRequest; +#endif + + using Requests = std::queue<std::unique_ptr<Request>>; // A callback to notify the upload result. using ReportCallback = base::OnceCallback<void(ReportStatus status)>;
diff --git a/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc b/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc index 8e07d2b..5b98694 100644 --- a/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc +++ b/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc
@@ -62,9 +62,6 @@ bool IsComponentExtensionWhitelisted(int manifest_resource_id) { switch (manifest_resource_id) { // Please keep the list in alphabetical order. -#if BUILDFLAG(ENABLE_APP_LIST) - case IDR_CHROME_APP_MANIFEST: -#endif #if BUILDFLAG(ENABLE_PRINTING) case IDR_CLOUDPRINT_MANIFEST: #endif @@ -74,9 +71,6 @@ case IDR_HANGOUT_SERVICES_MANIFEST: #endif case IDR_IDENTITY_API_SCOPE_APPROVAL_MANIFEST: -#if defined(OS_CHROMEOS) - case IDR_IMAGE_LOADER_MANIFEST: -#endif case IDR_NETWORK_SPEECH_SYNTHESIS_MANIFEST: case IDR_WEBSTORE_MANIFEST: @@ -84,6 +78,7 @@ // Separate ChromeOS list, as it is quite large. case IDR_ARC_SUPPORT_MANIFEST: case IDR_AUDIO_PLAYER_MANIFEST: + case IDR_CHROME_APP_MANIFEST: case IDR_CONNECTIVITY_DIAGNOSTICS_LAUNCHER_MANIFEST: case IDR_CONNECTIVITY_DIAGNOSTICS_MANIFEST: case IDR_CROSH_BUILTIN_MANIFEST: @@ -92,6 +87,7 @@ case IDR_FILEMANAGER_MANIFEST: case IDR_FIRST_RUN_DIALOG_MANIFEST: case IDR_GALLERY_MANIFEST: + case IDR_IMAGE_LOADER_MANIFEST: case IDR_KEYBOARD_MANIFEST: case IDR_MOBILE_MANIFEST: case IDR_VIDEO_PLAYER_MANIFEST:
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc index 279b8eb..e82ddd9e 100644 --- a/chrome/browser/extensions/component_loader.cc +++ b/chrome/browser/extensions/component_loader.cc
@@ -328,15 +328,6 @@ } } -#if BUILDFLAG(ENABLE_APP_LIST) -void ComponentLoader::AddChromeApp() { - AddWithNameAndDescription( - IDR_CHROME_APP_MANIFEST, base::FilePath(FILE_PATH_LITERAL("chrome_app")), - l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME), - l10n_util::GetStringUTF8(IDS_CHROME_SHORTCUT_DESCRIPTION)); -} -#endif // BUILDFLAG(ENABLE_APP_LIST) - void ComponentLoader::AddWebStoreApp() { #if defined(OS_CHROMEOS) if (!IsNormalSession()) @@ -350,6 +341,13 @@ } #if defined(OS_CHROMEOS) +void ComponentLoader::AddChromeApp() { + AddWithNameAndDescription( + IDR_CHROME_APP_MANIFEST, base::FilePath(FILE_PATH_LITERAL("chrome_app")), + l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME), + l10n_util::GetStringUTF8(IDS_CHROME_SHORTCUT_DESCRIPTION)); +} + void ComponentLoader::AddFileManagerExtension() { AddWithNameAndDescription( IDR_FILEMANAGER_MANIFEST, @@ -453,9 +451,9 @@ if (!skip_session_components) { AddWebStoreApp(); -#if BUILDFLAG(ENABLE_APP_LIST) +#if defined(OS_CHROMEOS) AddChromeApp(); -#endif // BUILDFLAG(ENABLE_APP_LIST) +#endif // defined(OS_CHROMEOS) } AddDefaultComponentExtensionsWithBackgroundPages(skip_session_components);
diff --git a/chrome/browser/extensions/component_loader.h b/chrome/browser/extensions/component_loader.h index 59dea62..a001aae 100644 --- a/chrome/browser/extensions/component_loader.h +++ b/chrome/browser/extensions/component_loader.h
@@ -170,13 +170,10 @@ const base::FilePath& root_directory, const std::string& name_string, const std::string& description_string); -#if BUILDFLAG(ENABLE_APP_LIST) - void AddChromeApp(); -#endif // BUILDFLAG(ENABLE_APP_LIST) - void AddWebStoreApp(); #if defined(OS_CHROMEOS) + void AddChromeApp(); void AddFileManagerExtension(); void AddVideoPlayerExtension(); void AddAudioPlayerExtension();
diff --git a/chrome/browser/media/history/OWNERS b/chrome/browser/media/history/OWNERS index 93b41f3..442bd195 100644 --- a/chrome/browser/media/history/OWNERS +++ b/chrome/browser/media/history/OWNERS
@@ -1,6 +1,6 @@ # TEAM: media-dev@chromium.org # COMPONENT: Internals>Media>History -evliu@google.org +evliu@google.com beccahughes@chromium.org steimel@chromium.org
diff --git a/chrome/browser/media/history/media_history_contents_observer.cc b/chrome/browser/media/history/media_history_contents_observer.cc index 0b62f02..12f10c0 100644 --- a/chrome/browser/media/history/media_history_contents_observer.cc +++ b/chrome/browser/media/history/media_history_contents_observer.cc
@@ -9,19 +9,23 @@ MediaHistoryContentsObserver::MediaHistoryContentsObserver( content::WebContents* web_contents) - : content::WebContentsObserver(web_contents) { + : content::WebContentsObserver(web_contents), service_(nullptr) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - service_ = media_history::MediaHistoryKeyedServiceFactory::GetForProfile( - Profile::FromBrowserContext(web_contents->GetBrowserContext())); - DCHECK(service_); + Profile* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + if (!profile->IsOffTheRecord()) { + service_ = + media_history::MediaHistoryKeyedServiceFactory::GetForProfile(profile); + DCHECK(service_); + } } MediaHistoryContentsObserver::~MediaHistoryContentsObserver() = default; void MediaHistoryContentsObserver::MediaWatchTimeChanged( const content::MediaPlayerWatchTime& watch_time) { - service_->GetMediaHistoryStore()->SavePlayback(watch_time); + if (service_) + service_->GetMediaHistoryStore()->SavePlayback(watch_time); } WEB_CONTENTS_USER_DATA_KEY_IMPL(MediaHistoryContentsObserver)
diff --git a/chrome/browser/media/history/media_history_playback_table.cc b/chrome/browser/media/history/media_history_playback_table.cc index 78ac3138..8ce53f2 100644 --- a/chrome/browser/media/history/media_history_playback_table.cc +++ b/chrome/browser/media/history/media_history_playback_table.cc
@@ -28,6 +28,9 @@ "url TEXT," "timestamp_ms INTEGER," "watch_time_ms INTEGER," + "has_video INTEGER," + "has_audio INTEGER," + "last_updated_time_s BIGINT NOT NULL," "CONSTRAINT fk_origin " "FOREIGN KEY (origin_id) " "REFERENCES origin(id) " @@ -64,12 +67,17 @@ sql::Statement statement(DB()->GetCachedStatement( SQL_FROM_HERE, "INSERT INTO playback " - "(origin_id, url, watch_time_ms, timestamp_ms) " - "VALUES ((SELECT id FROM origin WHERE origin = ?), ?, ?, ?)")); + "(origin_id, url, watch_time_ms, timestamp_ms, has_video, has_audio, " + "last_updated_time_s) " + "VALUES ((SELECT id FROM origin WHERE origin = ?), ?, ?, ?, ?, ?, ?)")); statement.BindString(0, watch_time.origin.spec()); statement.BindString(1, watch_time.url.spec()); statement.BindInt(2, watch_time.cumulative_watch_time.InMilliseconds()); statement.BindInt(3, watch_time.last_timestamp.InMilliseconds()); + statement.BindInt(4, watch_time.has_video); + statement.BindInt(5, watch_time.has_audio); + statement.BindInt64(6, + base::Time::Now().ToDeltaSinceWindowsEpoch().InSeconds()); if (!statement.Run()) { return false; }
diff --git a/chrome/browser/media/history/media_history_store_unittest.cc b/chrome/browser/media/history/media_history_store_unittest.cc index f59cc89..c3361a0 100644 --- a/chrome/browser/media/history/media_history_store_unittest.cc +++ b/chrome/browser/media/history/media_history_store_unittest.cc
@@ -76,8 +76,10 @@ GURL url("http://google.com/test"); content::MediaPlayerWatchTime watch_time( url, url.GetOrigin(), base::TimeDelta::FromMilliseconds(123), - base::TimeDelta::FromMilliseconds(321)); + base::TimeDelta::FromMilliseconds(321), true, false); GetMediaHistoryStore()->SavePlayback(watch_time); + int64_t now_in_seconds_before = + base::Time::Now().ToDeltaSinceWindowsEpoch().InSeconds(); // Save the watch time a second time. GetMediaHistoryStore()->SavePlayback(watch_time); @@ -85,9 +87,13 @@ // Wait until the playbacks have finished saving. content::RunAllTasksUntilIdle(); + int64_t now_in_seconds_after = + base::Time::Now().ToDeltaSinceWindowsEpoch().InSeconds(); + // Verify that the playback table contains the expected number of items sql::Statement select_from_playback_statement(GetDB().GetUniqueStatement( - "SELECT id, url, origin_id, watch_time_ms, timestamp_ms FROM playback")); + "SELECT id, url, origin_id, watch_time_ms, timestamp_ms, has_video, " + "has_audio, last_updated_time_s FROM playback")); ASSERT_TRUE(select_from_playback_statement.is_valid()); int playback_row_count = 0; while (select_from_playback_statement.Step()) { @@ -98,6 +104,12 @@ EXPECT_EQ(1, select_from_playback_statement.ColumnInt(2)); EXPECT_EQ(123, select_from_playback_statement.ColumnInt(3)); EXPECT_EQ(321, select_from_playback_statement.ColumnInt(4)); + EXPECT_EQ(1, select_from_playback_statement.ColumnInt(5)); + EXPECT_EQ(0, select_from_playback_statement.ColumnInt(6)); + EXPECT_LE(now_in_seconds_before, + select_from_playback_statement.ColumnInt64(7)); + EXPECT_GE(now_in_seconds_after, + select_from_playback_statement.ColumnInt64(7)); } EXPECT_EQ(2, playback_row_count);
diff --git a/chrome/browser/page_load_metrics/observers/third_party_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/third_party_metrics_observer.cc index 30152a2..12d874a4 100644 --- a/chrome/browser/page_load_metrics/observers/third_party_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/third_party_metrics_observer.cc
@@ -5,8 +5,19 @@ #include "chrome/browser/page_load_metrics/observers/third_party_metrics_observer.h" #include "base/metrics/histogram_macros.h" +#include "components/page_load_metrics/browser/page_load_metrics_util.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" +namespace { + +// The maximum number of subframes that we've recorded timings for that we can +// keep track of in memory. +const int kMaxRecordedFrames = 50; + +} // namespace + ThirdPartyMetricsObserver::CookieAccessTypes::CookieAccessTypes( AccessType access_type) { switch (access_type) { @@ -99,6 +110,60 @@ local ? StorageType::kLocalStorage : StorageType::kSessionStorage); } +void ThirdPartyMetricsObserver::OnDidFinishSubFrameNavigation( + content::NavigationHandle* navigation_handle) { + DCHECK(navigation_handle->GetNetworkIsolationKey().GetTopFrameOrigin()); + + if (!navigation_handle->HasCommitted()) + return; + + // A RenderFrameHost is navigating. Since this is a new navigation we want to + // capture its paint timing. Remove the RFH from the list of recorded frames. + // This is guaranteed to be called before receiving the first paint update for + // the navigation. + recorded_frames_.erase(navigation_handle->GetRenderFrameHost()); +} + +void ThirdPartyMetricsObserver::OnFrameDeleted( + content::RenderFrameHost* render_frame_host) { + recorded_frames_.erase(render_frame_host); +} + +void ThirdPartyMetricsObserver::OnTimingUpdate( + content::RenderFrameHost* subframe_rfh, + const page_load_metrics::mojom::PageLoadTiming& timing) { + if (!timing.paint_timing->first_contentful_paint) + return; + + // Filter out top-frames + if (!subframe_rfh) + return; + + // Filter out navigations that we've already recorded, or if we've reached our + // frame limit. + const auto it = recorded_frames_.find(subframe_rfh); + if (it != recorded_frames_.end() || + recorded_frames_.size() >= kMaxRecordedFrames) { + return; + } + + // Filter out first-party frames. + content::RenderFrameHost* top_frame = + GetDelegate().GetWebContents()->GetMainFrame(); + if (!top_frame || top_frame->GetLastCommittedOrigin().IsSameOriginWith( + subframe_rfh->GetLastCommittedOrigin())) { + return; + } + + if (page_load_metrics::WasStartedInForegroundOptionalEventInForeground( + timing.paint_timing->first_contentful_paint, GetDelegate())) { + PAGE_LOAD_HISTOGRAM( + "PageLoad.Clients.ThirdParty.Frames.NavigationToFirstContentfulPaint", + timing.paint_timing->first_contentful_paint.value()); + recorded_frames_.insert(subframe_rfh); + } +} + void ThirdPartyMetricsObserver::OnCookieAccess(const GURL& url, const GURL& first_party_url, bool blocked_by_policy,
diff --git a/chrome/browser/page_load_metrics/observers/third_party_metrics_observer.h b/chrome/browser/page_load_metrics/observers/third_party_metrics_observer.h index 08453cc..e1629ee 100644 --- a/chrome/browser/page_load_metrics/observers/third_party_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/third_party_metrics_observer.h
@@ -38,6 +38,12 @@ const GURL& first_party_url, bool local, bool blocked_by_policy) override; + void OnDidFinishSubFrameNavigation( + content::NavigationHandle* navigation_handle) override; + void OnFrameDeleted(content::RenderFrameHost* render_frame_host) override; + void OnTimingUpdate( + content::RenderFrameHost* subframe_rfh, + const page_load_metrics::mojom::PageLoadTiming& timing) override; private: enum class AccessType { kRead, kWrite }; @@ -75,6 +81,10 @@ // frame's. std::map<url::Origin, StorageAccessTypes> third_party_storage_access_types_; + // A set of RenderFrameHosts that we've recorded timing data for. The + // RenderFrameHosts are later removed when they navigate again or are deleted. + std::set<content::RenderFrameHost*> recorded_frames_; + // If the page has any blocked_by_policy cookie or DOM storage access (e.g., // block third-party cookies is enabled) then we don't want to record any // metrics for the page.
diff --git a/chrome/browser/page_load_metrics/observers/third_party_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/third_party_metrics_observer_browsertest.cc index b7ed0e5..f01fbbc 100644 --- a/chrome/browser/page_load_metrics/observers/third_party_metrics_observer_browsertest.cc +++ b/chrome/browser/page_load_metrics/observers/third_party_metrics_observer_browsertest.cc
@@ -7,6 +7,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/network_session_configurator/common/network_switches.h" +#include "components/page_load_metrics/browser/page_load_metrics_test_waiter.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" @@ -24,7 +25,8 @@ "PageLoad.Clients.ThirdParty.Origins.LocalStorageAccess"; const char kAccessSessionStorageHistogram[] = "PageLoad.Clients.ThirdParty.Origins.SessionStorageAccess"; - +const char kSubframeFCPHistogram[] = + "PageLoad.Clients.ThirdParty.Frames.NavigationToFirstContentfulPaint"; class ThirdPartyMetricsObserverBrowserTest : public InProcessBrowserTest { protected: ThirdPartyMetricsObserverBrowserTest() @@ -52,6 +54,33 @@ ui_test_utils::NavigateToURL(browser(), main_url); } + void NavigateToPageWithFrameAndWaitForFrame( + const std::string& host, + page_load_metrics::PageLoadMetricsTestWaiter* waiter) { + GURL main_url(https_server()->GetURL(host, "/iframe.html")); + + waiter->AddSubframeNavigationExpectation(); + NavigateToPageWithFrame(host); + waiter->Wait(); + } + + void NavigateFrameAndWaitForFCP( + const std::string& host, + const std::string& path, + page_load_metrics::PageLoadMetricsTestWaiter* waiter) { + // Waiting for the frame to navigate ensures that any previous RFHs for this + // frame have been deleted and therefore won't pollute any future frame + // expectations (such as FCP). + waiter->AddSubframeNavigationExpectation(); + NavigateFrameTo(host, path); + waiter->Wait(); + + waiter->AddSubFrameExpectation( + page_load_metrics::PageLoadMetricsTestWaiter::TimingField:: + kFirstContentfulPaint); + waiter->Wait(); + } + void NavigateFrameTo(const std::string& host, const std::string& path) { GURL page = https_server()->GetURL(host, path); NavigateFrameToUrl(page); @@ -74,6 +103,53 @@ DISALLOW_COPY_AND_ASSIGN(ThirdPartyMetricsObserverBrowserTest); }; +IN_PROC_BROWSER_TEST_F(ThirdPartyMetricsObserverBrowserTest, + OneFirstPartyFrame_NoTimingRecorded) { + base::HistogramTester histogram_tester; + page_load_metrics::PageLoadMetricsTestWaiter waiter( + browser()->tab_strip_model()->GetActiveWebContents()); + NavigateToPageWithFrameAndWaitForFrame("a.com", &waiter); + + // Navigate the frame to a first-party. + NavigateFrameAndWaitForFCP("a.com", "/select.html", &waiter); + histogram_tester.ExpectTotalCount(kSubframeFCPHistogram, 0); +} + +IN_PROC_BROWSER_TEST_F(ThirdPartyMetricsObserverBrowserTest, + OneThirdPartyFrame_OneTimingRecorded) { + base::HistogramTester histogram_tester; + + page_load_metrics::PageLoadMetricsTestWaiter waiter( + browser()->tab_strip_model()->GetActiveWebContents()); + NavigateToPageWithFrameAndWaitForFrame("a.com", &waiter); + + // Navigate the frame to a third-party. + NavigateFrameAndWaitForFCP("b.com", "/select.html", &waiter); + histogram_tester.ExpectTotalCount(kSubframeFCPHistogram, 1); +} + +IN_PROC_BROWSER_TEST_F(ThirdPartyMetricsObserverBrowserTest, + ThreeThirdPartyFrames_ThreeTimingsRecorded) { + base::HistogramTester histogram_tester; + + page_load_metrics::PageLoadMetricsTestWaiter waiter( + browser()->tab_strip_model()->GetActiveWebContents()); + NavigateToPageWithFrameAndWaitForFrame("a.com", &waiter); + + // Navigate the frame to a third-party. + NavigateFrameAndWaitForFCP("b.com", "/select.html", &waiter); + + // Navigate the frame to a different third-party. + NavigateFrameAndWaitForFCP("c.com", "/select.html", &waiter); + + // Navigate the frame to a repeat third-party. + NavigateFrameAndWaitForFCP("b.com", "/select.html", &waiter); + + // Navigate the frame to first-party. + NavigateFrameAndWaitForFCP("a.com", "/select.html", &waiter); + histogram_tester.ExpectTotalCount(kSubframeFCPHistogram, 3); +} + IN_PROC_BROWSER_TEST_F(ThirdPartyMetricsObserverBrowserTest, NoStorageEvent) { base::HistogramTester histogram_tester; NavigateToPageWithFrame("a.com");
diff --git a/chrome/browser/page_load_metrics/observers/third_party_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/third_party_metrics_observer_unittest.cc index 83b4bbd3..88315e9e 100644 --- a/chrome/browser/page_load_metrics/observers/third_party_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/third_party_metrics_observer_unittest.cc
@@ -6,6 +6,11 @@ #include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h" #include "components/page_load_metrics/browser/page_load_tracker.h" +#include "components/page_load_metrics/common/page_load_metrics.mojom.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/navigation_simulator.h" +#include "content/public/test/test_renderer_host.h" #include "net/cookies/canonical_cookie.h" #include "testing/gtest/include/gtest/gtest.h" @@ -17,6 +22,12 @@ "PageLoad.Clients.ThirdParty.Origins.LocalStorageAccess"; const char kAccessSessionStorageHistogram[] = "PageLoad.Clients.ThirdParty.Origins.SessionStorageAccess"; +const char kSubframeFCPHistogram[] = + "PageLoad.Clients.ThirdParty.Frames.NavigationToFirstContentfulPaint"; + +using content::NavigationSimulator; +using content::RenderFrameHost; +using content::RenderFrameHostTester; class ThirdPartyMetricsObserverTest : public page_load_metrics::PageLoadMetricsObserverTestHarness { @@ -27,10 +38,133 @@ tracker->AddObserver(base::WrapUnique(new ThirdPartyMetricsObserver())); } + // Returns the final RenderFrameHost after navigation commits. + RenderFrameHost* NavigateFrame(const std::string& url, + content::RenderFrameHost* frame) { + auto navigation_simulator = + NavigationSimulator::CreateRendererInitiated(GURL(url), frame); + navigation_simulator->Commit(); + return navigation_simulator->GetFinalRenderFrameHost(); + } + + // Returns the final RenderFrameHost after navigation commits. + content::RenderFrameHost* NavigateMainFrame(const std::string& url) { + return NavigateFrame(url, web_contents()->GetMainFrame()); + } + + // Returns the final RenderFrameHost after navigation commits. + RenderFrameHost* CreateAndNavigateSubFrame(const std::string& url, + content::RenderFrameHost* parent) { + RenderFrameHost* subframe = + RenderFrameHostTester::For(parent)->AppendChild("frame_name"); + auto navigation_simulator = + NavigationSimulator::CreateRendererInitiated(GURL(url), subframe); + navigation_simulator->Commit(); + + return navigation_simulator->GetFinalRenderFrameHost(); + } + private: DISALLOW_COPY_AND_ASSIGN(ThirdPartyMetricsObserverTest); }; +TEST_F(ThirdPartyMetricsObserverTest, NoThirdPartyFrame_NoneRecorded) { + RenderFrameHost* main_frame = NavigateMainFrame("https://top.com"); + RenderFrameHost* sub_frame = + CreateAndNavigateSubFrame("https://top.com/foo", main_frame); + + page_load_metrics::mojom::PageLoadTiming timing; + page_load_metrics::InitPageLoadTimingForTest(&timing); + timing.paint_timing->first_contentful_paint = base::TimeDelta::FromSeconds(1); + tester()->SimulateTimingUpdate(timing, sub_frame); + tester()->histogram_tester().ExpectTotalCount(kSubframeFCPHistogram, 0); +} + +TEST_F(ThirdPartyMetricsObserverTest, OneThirdPartyFrame_OneRecorded) { + RenderFrameHost* main_frame = NavigateMainFrame("https://top.com"); + RenderFrameHost* sub_frame = + CreateAndNavigateSubFrame("https://x-origin.com", main_frame); + + page_load_metrics::mojom::PageLoadTiming timing; + page_load_metrics::InitPageLoadTimingForTest(&timing); + timing.paint_timing->first_contentful_paint = base::TimeDelta::FromSeconds(1); + tester()->SimulateTimingUpdate(timing, sub_frame); + tester()->histogram_tester().ExpectUniqueSample(kSubframeFCPHistogram, 1000, + 1); +} + +TEST_F(ThirdPartyMetricsObserverTest, + OneThirdPartyFrameWithTwoSameUpdates_OneRecorded) { + RenderFrameHost* main_frame = NavigateMainFrame("https://top.com"); + RenderFrameHost* sub_frame = + CreateAndNavigateSubFrame("https://x-origin.com", main_frame); + + page_load_metrics::mojom::PageLoadTiming timing; + page_load_metrics::InitPageLoadTimingForTest(&timing); + timing.paint_timing->first_contentful_paint = base::TimeDelta::FromSeconds(1); + tester()->SimulateTimingUpdate(timing, sub_frame); + tester()->SimulateTimingUpdate(timing, sub_frame); + tester()->histogram_tester().ExpectUniqueSample(kSubframeFCPHistogram, 1000, + 1); +} + +TEST_F(ThirdPartyMetricsObserverTest, SixtyFrames_FiftyRecorded) { + RenderFrameHost* main_frame = NavigateMainFrame("https://top.com"); + + // Add more frames than we're supposed to track. + for (int i = 0; i < 60; ++i) { + RenderFrameHost* sub_frame = + CreateAndNavigateSubFrame("https://x-origin.com", main_frame); + + page_load_metrics::mojom::PageLoadTiming timing; + page_load_metrics::InitPageLoadTimingForTest(&timing); + timing.paint_timing->first_contentful_paint = + base::TimeDelta::FromSeconds(1); + tester()->SimulateTimingUpdate(timing, sub_frame); + } + + // Keep this synchronized w/ the max frame count in the cc file. + tester()->histogram_tester().ExpectTotalCount(kSubframeFCPHistogram, 50); +} + +TEST_F(ThirdPartyMetricsObserverTest, ThreeThirdPartyFrames_ThreeRecorded) { + RenderFrameHost* main_frame = NavigateMainFrame("https://top.com"); + + // Create three third-party frames. + RenderFrameHost* sub_frame_a = + CreateAndNavigateSubFrame("https://x-origin.com", main_frame); + RenderFrameHost* sub_frame_b = + CreateAndNavigateSubFrame("https://y-origin.com", main_frame); + RenderFrameHost* sub_frame_c = + CreateAndNavigateSubFrame("https://x-origin.com", main_frame); + + // Create a same-origin frame. + RenderFrameHost* sub_frame_d = + CreateAndNavigateSubFrame("https://top.com/foo", main_frame); + + page_load_metrics::mojom::PageLoadTiming timing; + page_load_metrics::InitPageLoadTimingForTest(&timing); + timing.paint_timing->first_contentful_paint = base::TimeDelta::FromSeconds(1); + tester()->SimulateTimingUpdate(timing, sub_frame_a); + + timing.paint_timing->first_contentful_paint = base::TimeDelta::FromSeconds(2); + tester()->SimulateTimingUpdate(timing, sub_frame_b); + + timing.paint_timing->first_contentful_paint = base::TimeDelta::FromSeconds(3); + tester()->SimulateTimingUpdate(timing, sub_frame_c); + + timing.paint_timing->first_contentful_paint = base::TimeDelta::FromSeconds(4); + tester()->SimulateTimingUpdate(timing, sub_frame_d); + + tester()->histogram_tester().ExpectTotalCount(kSubframeFCPHistogram, 3); + tester()->histogram_tester().ExpectTimeBucketCount( + kSubframeFCPHistogram, base::TimeDelta::FromSeconds(1), 1); + tester()->histogram_tester().ExpectTimeBucketCount( + kSubframeFCPHistogram, base::TimeDelta::FromSeconds(2), 1); + tester()->histogram_tester().ExpectTimeBucketCount( + kSubframeFCPHistogram, base::TimeDelta::FromSeconds(3), 1); +} + TEST_F(ThirdPartyMetricsObserverTest, NoCookiesRead_NoneRecorded) { NavigateAndCommit(GURL("https://top.com")); tester()->NavigateToUntrackedUrl();
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc index dccebbf..80c9618 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -479,6 +479,8 @@ auto waiter = CreatePageLoadMetricsTestWaiter(); waiter->AddPageExpectation(TimingField::kFirstLayout); waiter->AddPageExpectation(TimingField::kLoadEvent); + waiter->AddPageExpectation(TimingField::kFirstPaint); + waiter->AddPageExpectation(TimingField::kFirstContentfulPaint); waiter->AddSubFrameExpectation(TimingField::kFirstPaint); waiter->AddSubFrameExpectation(TimingField::kFirstContentfulPaint); ui_test_utils::NavigateToURL(browser(), a_url); @@ -495,6 +497,8 @@ auto waiter = CreatePageLoadMetricsTestWaiter(); waiter->AddPageExpectation(TimingField::kFirstLayout); waiter->AddPageExpectation(TimingField::kLoadEvent); + waiter->AddPageExpectation(TimingField::kFirstPaint); + waiter->AddPageExpectation(TimingField::kFirstContentfulPaint); waiter->AddSubFrameExpectation(TimingField::kFirstPaint); waiter->AddSubFrameExpectation(TimingField::kFirstContentfulPaint); ui_test_utils::NavigateToURL(
diff --git a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc index 3ec1a373..750efa3 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
@@ -57,7 +57,8 @@ #include "content/public/common/url_constants.h" #include "content/public/test/navigation_simulator.h" #include "content/public/test/web_contents_tester.h" -#include "mojo/public/cpp/bindings/associated_binding.h" +#include "mojo/public/cpp/bindings/associated_receiver.h" +#include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "testing/gmock/include/gmock/gmock.h" @@ -144,15 +145,14 @@ : public autofill::mojom::PasswordAutofillAgent { public: FakePasswordAutofillAgent() - : called_set_logging_state_(false), - logging_state_active_(false), - binding_(this) {} + : called_set_logging_state_(false), logging_state_active_(false) {} ~FakePasswordAutofillAgent() override = default; - void BindRequest(mojo::ScopedInterfaceEndpointHandle handle) { - binding_.Bind(autofill::mojom::PasswordAutofillAgentAssociatedRequest( - std::move(handle))); + void BindReceiver(mojo::ScopedInterfaceEndpointHandle handle) { + receiver_.Bind( + mojo::PendingAssociatedReceiver<autofill::mojom::PasswordAutofillAgent>( + std::move(handle))); } bool called_set_logging_state() { return called_set_logging_state_; } @@ -187,7 +187,8 @@ // Records data received via SetLoggingState() call. bool logging_state_active_; - mojo::AssociatedBinding<autofill::mojom::PasswordAutofillAgent> binding_; + mojo::AssociatedReceiver<autofill::mojom::PasswordAutofillAgent> receiver_{ + this}; }; std::unique_ptr<KeyedService> CreateTestSyncService( @@ -247,7 +248,7 @@ web_contents()->GetMainFrame()->GetRemoteAssociatedInterfaces(); remote_interfaces->OverrideBinderForTesting( autofill::mojom::PasswordAutofillAgent::Name_, - base::BindRepeating(&FakePasswordAutofillAgent::BindRequest, + base::BindRepeating(&FakePasswordAutofillAgent::BindReceiver, base::Unretained(&fake_agent_))); prefs_.registry()->RegisterBooleanPref(
diff --git a/chrome/browser/performance_manager/docs/freezing_opt_out_opt_in.md b/chrome/browser/performance_manager/docs/freezing_opt_out_opt_in.md index 1796ae27..09a0888 100644 --- a/chrome/browser/performance_manager/docs/freezing_opt_out_opt_in.md +++ b/chrome/browser/performance_manager/docs/freezing_opt_out_opt_in.md
@@ -21,7 +21,7 @@ Once a page is frozen, it cannot run any tasks. In particular, callbacks associated with DOM timers, XHR requests or the push API will not run until the page is resumed. To verify the behavior of your site when it is frozen, go to -chrome://discards and click [Freeze] next to a background tab which contains +`chrome://discards` and click [Freeze] next to a background tab which contains your site. See [Will my site be frozen?](#Will-my-site-be-frozen_) for how Chrome tries to avoid frezing sites when this is likely to break functionality.
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index ed9946e..b47a286a3 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -145,10 +145,6 @@ #include "printing/buildflags/buildflags.h" #include "rlz/buildflags/buildflags.h" -#if BUILDFLAG(ENABLE_APP_LIST) -#include "chrome/browser/ui/app_list/app_list_syncable_service.h" -#endif - #if BUILDFLAG(ENABLE_BACKGROUND_MODE) #include "chrome/browser/background/background_mode_manager.h" #endif @@ -241,6 +237,7 @@ #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/app_mode/kiosk_cryptohome_remover.h" #include "chrome/browser/chromeos/app_mode/web_app/web_kiosk_app_manager.h" +#include "chrome/browser/chromeos/apps/apk_web_app_service.h" #include "chrome/browser/chromeos/arc/policy/arc_policy_bridge.h" #include "chrome/browser/chromeos/arc/session/arc_session_manager.h" #include "chrome/browser/chromeos/bluetooth/debug_logs_manager.h" @@ -301,6 +298,9 @@ #include "chrome/browser/extensions/extension_assets_manager_chromeos.h" #include "chrome/browser/media/protected_media_identifier_permission_context.h" #include "chrome/browser/metrics/chromeos_metrics_provider.h" +#include "chrome/browser/ui/app_list/app_list_syncable_service.h" +#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" +#include "chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h" #include "chrome/browser/ui/ash/chrome_launcher_prefs.h" #include "chrome/browser/ui/webui/certificates_handler.h" #include "chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h" @@ -326,12 +326,6 @@ #include "chrome/browser/extensions/default_apps.h" #endif -#if defined(OS_CHROMEOS) && BUILDFLAG(ENABLE_APP_LIST) -#include "chrome/browser/chromeos/apps/apk_web_app_service.h" -#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" -#include "chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h" -#endif - #if defined(OS_MACOSX) #include "chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac.h" #include "chrome/browser/ui/cocoa/confirm_quit.h" @@ -895,9 +889,6 @@ AppShortcutManager::RegisterProfilePrefs(registry); DeviceIDFetcher::RegisterProfilePrefs(registry); DevToolsWindow::RegisterProfilePrefs(registry); -#if BUILDFLAG(ENABLE_APP_LIST) - app_list::AppListSyncableService::RegisterProfilePrefs(registry); -#endif // BUILDFLAG(ENABLE_APP_LIST) extensions::CommandService::RegisterProfilePrefs(registry); extensions::TabsCaptureVisibleTabFunction::RegisterProfilePrefs(registry); NewTabUI::RegisterProfilePrefs(registry); @@ -934,9 +925,13 @@ #endif #if defined(OS_CHROMEOS) + app_list::AppListSyncableService::RegisterProfilePrefs(registry); + app_list::ArcAppReinstallSearchProvider::RegisterProfilePrefs(registry); arc::prefs::RegisterProfilePrefs(registry); + ArcAppListPrefs::RegisterProfilePrefs(registry); certificate_manager::CertificatesHandler::RegisterProfilePrefs(registry); chromeos::AccountManager::RegisterPrefs(registry); + chromeos::ApkWebAppService::RegisterProfilePrefs(registry); chromeos::assistant::prefs::RegisterProfilePrefsForBrowser(registry); chromeos::bluetooth::DebugLogsManager::RegisterPrefs(registry); chromeos::CupsPrintersManager::RegisterProfilePrefs(registry); @@ -973,12 +968,6 @@ ::onc::RegisterProfilePrefs(registry); #endif -#if defined(OS_CHROMEOS) && BUILDFLAG(ENABLE_APP_LIST) - app_list::ArcAppReinstallSearchProvider::RegisterProfilePrefs(registry); - ArcAppListPrefs::RegisterProfilePrefs(registry); - chromeos::ApkWebAppService::RegisterProfilePrefs(registry); -#endif - #if BUILDFLAG(ENABLE_RLZ) ChromeRLZTrackerDelegate::RegisterProfilePrefs(registry); #endif
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc index 02b0a7a..a3b17dc6 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -37,6 +37,7 @@ #include "chrome/browser/invalidation/deprecated_profile_invalidation_provider_factory.h" #include "chrome/browser/language/language_model_manager_factory.h" #include "chrome/browser/language/url_language_histogram_factory.h" +#include "chrome/browser/media/history/media_history_keyed_service_factory.h" #include "chrome/browser/media/media_engagement_service.h" #include "chrome/browser/media/media_engagement_service_factory.h" #include "chrome/browser/media/router/media_router_factory.h" @@ -88,6 +89,7 @@ #include "components/safe_browsing/buildflags.h" #include "components/spellcheck/spellcheck_buildflags.h" #include "extensions/buildflags/buildflags.h" +#include "media/base/media_switches.h" #include "ppapi/buildflags/buildflags.h" #include "printing/buildflags/buildflags.h" @@ -202,9 +204,6 @@ #if defined(OS_CHROMEOS) chromeos::EnsureBrowserContextKeyedServiceFactoriesBuilt(); -#endif - -#if BUILDFLAG(ENABLE_APP_LIST) app_list::AppListSyncableServiceFactory::GetInstance(); #endif @@ -294,6 +293,8 @@ #if !defined(OS_ANDROID) MediaGalleriesPreferencesFactory::GetInstance(); #endif + if (base::FeatureList::IsEnabled(media::kUseMediaHistoryStore)) + media_history::MediaHistoryKeyedServiceFactory::GetInstance(); #if defined(OS_WIN) || defined(OS_MACOSX) || \ (defined(OS_LINUX) && !defined(OS_CHROMEOS)) metrics::DesktopProfileSessionDurationsServiceFactory::GetInstance();
diff --git a/chrome/browser/resources/chromeos/switch_access/nodes/back_button_node.js b/chrome/browser/resources/chromeos/switch_access/nodes/back_button_node.js index 98dc70b..61e41dcc 100644 --- a/chrome/browser/resources/chromeos/switch_access/nodes/back_button_node.js +++ b/chrome/browser/resources/chromeos/switch_access/nodes/back_button_node.js
@@ -10,7 +10,7 @@ * @param {!SARootNode} group */ constructor(group) { - super(false /* isGroup */); + super(); /** * The group that the back button is shown for. * @private {!SARootNode} @@ -66,6 +66,11 @@ } /** @override */ + isGroup() { + return false; + } + + /** @override */ asRootNode() { return null; }
diff --git a/chrome/browser/resources/chromeos/switch_access/nodes/group_node.js b/chrome/browser/resources/chromeos/switch_access/nodes/group_node.js index 3ace9b1..51981b101 100644 --- a/chrome/browser/resources/chromeos/switch_access/nodes/group_node.js +++ b/chrome/browser/resources/chromeos/switch_access/nodes/group_node.js
@@ -15,7 +15,7 @@ * @private */ constructor(children) { - super(true /* isGroup */); + super(); /** @type {!Array<!SAChildNode>} */ this.children_ = children; @@ -71,6 +71,11 @@ } /** @override */ + isGroup() { + return true; + } + + /** @override */ asRootNode() { const root = new SARootNode();
diff --git a/chrome/browser/resources/chromeos/switch_access/nodes/node_wrapper.js b/chrome/browser/resources/chromeos/switch_access/nodes/node_wrapper.js index 8109c6f..1d2ea159 100644 --- a/chrome/browser/resources/chromeos/switch_access/nodes/node_wrapper.js +++ b/chrome/browser/resources/chromeos/switch_access/nodes/node_wrapper.js
@@ -14,9 +14,12 @@ * @param {?SARootNode} parent */ constructor(baseNode, parent) { - super(SwitchAccessPredicate.isGroup(baseNode, parent)); + super(); /** @private {!AutomationNode} */ this.baseNode_ = baseNode; + + /** @private {boolean} */ + this.isGroup_ = SwitchAccessPredicate.isGroup(this.baseNode_, parent); } /** @override */ @@ -139,6 +142,11 @@ } /** @override */ + isGroup() { + return this.isGroup_; + } + + /** @override */ asRootNode() { if (!this.isGroup()) { return null;
diff --git a/chrome/browser/resources/chromeos/switch_access/nodes/switch_access_node.js b/chrome/browser/resources/chromeos/switch_access/nodes/switch_access_node.js index 0455814..a690ba8 100644 --- a/chrome/browser/resources/chromeos/switch_access/nodes/switch_access_node.js +++ b/chrome/browser/resources/chromeos/switch_access/nodes/switch_access_node.js
@@ -13,12 +13,7 @@ * @abstract */ class SAChildNode { - /** - * @param {boolean} isGroup - */ - constructor(isGroup) { - this.isGroup_ = isGroup; - + constructor() { /** @private {?SAChildNode} */ this.previous_ = null; @@ -71,10 +66,9 @@ /** * Returns whether this node should be displayed as a group. * @return {boolean} + * @abstract */ - isGroup() { - return this.isGroup_; - } + isGroup() {} /** * Returns a list of all the actions available for this node. @@ -159,7 +153,7 @@ * @return {string} */ debugString(wholeTree, prefix = '', currentNode = null) { - if (this.isGroup_ && wholeTree) { + if (this.isGroup() && wholeTree) { return this.asRootNode().debugString( wholeTree, prefix + ' ', currentNode); } @@ -176,7 +170,7 @@ str += 'loc(' + RectHelper.toString(loc) + ') '; } - if (this.isGroup_) { + if (this.isGroup()) { str += '[isGroup]'; }
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.html b/chrome/browser/resources/settings/internet_page/internet_detail_page.html index 2d27c7dc..ef3b08e 100644 --- a/chrome/browser/resources/settings/internet_page/internet_detail_page.html +++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
@@ -38,10 +38,6 @@ padding-bottom: 40px; } - iron-collapse { - margin: 10px 0; - } - iron-icon { margin-inline-end: 10px; }
diff --git a/chrome/browser/resources/tab_strip/tab.html b/chrome/browser/resources/tab_strip/tab.html index 7d3add55..07309d58 100644 --- a/chrome/browser/resources/tab_strip/tab.html +++ b/chrome/browser/resources/tab_strip/tab.html
@@ -21,7 +21,6 @@ :host([active]) #tab { box-shadow: 0 0 0 2px var(--tabstrip-tab-active-border-color); - outline: none; } #title { @@ -276,7 +275,7 @@ </div> <h2 id="titleText"></h2> <tabstrip-alert-indicators id="alertIndicators"></tabstrip-alert-indicators> - <button id="close"> + <button id="close" aria-describedby="titleText"> <span id="closeIcon"></span> </button> </header>
diff --git a/chrome/browser/resources/tab_strip/tab.js b/chrome/browser/resources/tab_strip/tab.js index 5911027..780b6dde 100644 --- a/chrome/browser/resources/tab_strip/tab.js +++ b/chrome/browser/resources/tab_strip/tab.js
@@ -88,6 +88,8 @@ this.tabEl_.addEventListener('click', () => this.onClick_()); this.tabEl_.addEventListener('contextmenu', e => this.onContextMenu_(e)); + this.tabEl_.addEventListener( + 'keydown', e => this.onKeyDown_(/** @type {!KeyboardEvent} */ (e))); this.closeButtonEl_.addEventListener('click', e => this.onClose_(e)); this.addEventListener('swipe', () => this.onSwipe_()); @@ -151,6 +153,10 @@ this.tab_ = Object.freeze(tab); } + focus() { + this.tabEl_.focus(); + } + /** @return {!HTMLElement} */ getDragImage() { return this.tabEl_; @@ -212,6 +218,16 @@ } /** + * @param {!KeyboardEvent} event + * @private + */ + onKeyDown_(event) { + if (event.key === 'Enter' || event.key === ' ') { + this.onClick_(); + } + } + + /** * @param {boolean} dragging */ setDragging(dragging) {
diff --git a/chrome/browser/resources/tab_strip/tab_list.js b/chrome/browser/resources/tab_strip/tab_list.js index e824b72..c8a645b 100644 --- a/chrome/browser/resources/tab_strip/tab_list.js +++ b/chrome/browser/resources/tab_strip/tab_list.js
@@ -48,6 +48,10 @@ */ this.animationPromises = Promise.resolve(); + /** @private {!Function} */ + this.documentVisibilityChangeListener_ = () => + this.onDocumentVisibilityChange_(); + /** * The TabElement that is currently being dragged. * @private {!TabElement|undefined} @@ -91,6 +95,12 @@ /** @type {!Element} */ ( this.shadowRoot.querySelector('#tabsContainer')); + /** @private {!Function} */ + this.windowBlurListener_ = () => this.onWindowBlur_(); + + /** @private {!Function} */ + this.windowFocusListener_ = () => this.onWindowFocus_(); + addWebUIListener( 'layout-changed', layout => this.applyCSSDictionary_(layout)); addWebUIListener('theme-changed', () => this.fetchAndUpdateColors_()); @@ -105,8 +115,11 @@ 'dragend', (e) => this.onDragEnd_(/** @type {!DragEvent} */ (e))); this.addEventListener( 'dragover', (e) => this.onDragOver_(/** @type {!DragEvent} */ (e))); + document.addEventListener( - 'visibilitychange', () => this.onVisibilityChange_()); + 'visibilitychange', this.documentVisibilityChangeListener_); + window.addEventListener('blur', this.windowBlurListener_); + window.addEventListener('focus', this.windowFocusListener_); if (loadTimeData.getBoolean('showDemoOptions')) { this.shadowRoot.querySelector('#demoOptions').style.display = 'block'; @@ -157,12 +170,21 @@ addWebUIListener( 'tab-moved', (tabId, newIndex) => this.onTabMoved_(tabId, newIndex)); addWebUIListener('tab-removed', tabId => this.onTabRemoved_(tabId)); + addWebUIListener( + 'tab-replaced', (oldId, newId) => this.onTabReplaced_(oldId, newId)); addWebUIListener('tab-updated', tab => this.onTabUpdated_(tab)); addWebUIListener( 'tab-active-changed', tabId => this.onTabActivated_(tabId)); }); } + disconnectedCallback() { + document.removeEventListener( + 'visibilitychange', this.documentVisibilityChangeListener_); + window.removeEventListener('blur', this.windowBlurListener_); + window.removeEventListener('focus', this.windowFocusListener_); + } + /** * @param {!TabData} tab * @return {!TabElement} @@ -244,6 +266,13 @@ } } + /** @private */ + onDocumentVisibilityChange_() { + this.moveOrScrollToActiveTab_(); + Array.from(this.tabsContainerElement_.children) + .forEach((tabElement) => this.updateThumbnailTrackStatus_(tabElement)); + } + /** * @param {!DragEvent} event * @private @@ -387,6 +416,21 @@ } /** + * @param {number} oldId + * @param {number} newId + * @private + */ + onTabReplaced_(oldId, newId) { + const tabElement = this.findTabElement_(oldId); + if (!tabElement) { + return; + } + + tabElement.tab = /** @type {!TabData} */ ( + Object.assign({}, tabElement.tab, {id: newId})); + } + + /** * @param {!TabData} tab * @private */ @@ -412,10 +456,18 @@ } /** @private */ - onVisibilityChange_() { - this.moveOrScrollToActiveTab_(); - Array.from(this.tabsContainerElement_.children) - .forEach((tabElement) => this.updateThumbnailTrackStatus_(tabElement)); + onWindowBlur_() { + if (this.shadowRoot.activeElement) { + // Blur the currently focused element when the window is blurred. This + // prevents the screen reader from momentarily reading out the + // previously focused element when the focus returns to this window. + this.shadowRoot.activeElement.blur(); + } + } + + /** @private */ + onWindowFocus_() { + this.shadowRoot.querySelector('tabstrip-tab').focus(); } /**
diff --git a/chrome/browser/resources/tab_strip/tab_strip.html b/chrome/browser/resources/tab_strip/tab_strip.html index 4382b8d..fc32d7b3 100644 --- a/chrome/browser/resources/tab_strip/tab_strip.html +++ b/chrome/browser/resources/tab_strip/tab_strip.html
@@ -3,6 +3,7 @@ <head> <meta charset="utf-8"> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> + <title>$i18n{tabListTitle}</title> <style> html { --google-grey-50-rgb: 248, 249, 250;
diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc index 688a4ad6..c8fc2cd 100644 --- a/chrome/browser/shell_integration_linux.cc +++ b/chrome/browser/shell_integration_linux.cc
@@ -249,15 +249,6 @@ const char kXdgOpenShebang[] = "#!/usr/bin/env xdg-open"; #endif -// TODO(loyso): shell_integraion_linux.cc won't compile with app_list disabled? -#if BUILDFLAG(ENABLE_APP_LIST) -#if BUILDFLAG(GOOGLE_CHROME_BRANDING) -const char kAppListDesktopName[] = "chrome-app-list"; -#else // BUILDFLAG(CHROMIUM_BRANDING) -const char kAppListDesktopName[] = "chromium-app-list"; -#endif -#endif - } // namespace // Allows LaunchXdgUtility to join a process. @@ -644,49 +635,6 @@ #endif } -#if BUILDFLAG(ENABLE_APP_LIST) -bool CreateAppListDesktopShortcut( - const std::string& wm_class, - const std::string& title) { - base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, - base::BlockingType::MAY_BLOCK); - - base::FilePath desktop_name(kAppListDesktopName); - base::FilePath shortcut_filename = desktop_name.AddExtension("desktop"); - - // We do not want duplicate shortcuts. Delete any that already exist and - // replace them. - DeleteShortcutInApplicationsMenu(shortcut_filename, base::FilePath()); - - base::FilePath chrome_exe_path = GetChromeExePath(); - if (chrome_exe_path.empty()) { - NOTREACHED(); - return false; - } - - gfx::ImageFamily icon_images; - ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance(); - icon_images.Add(*resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_16)); - icon_images.Add(*resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_32)); - icon_images.Add(*resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_48)); - icon_images.Add(*resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_256)); - std::string icon_name = CreateShortcutIcon(icon_images, desktop_name); - - base::CommandLine command_line(chrome_exe_path); - command_line.AppendSwitch(switches::kShowAppList); - std::string contents = - GetDesktopFileContentsForCommand(command_line, - wm_class, - GURL(), - base::UTF8ToUTF16(title), - icon_name, - kAppListCategories, - false); - return CreateShortcutInApplicationsMenu( - shortcut_filename, contents, base::FilePath(), ""); -} -#endif - } // namespace shell_integration_linux namespace shell_integration {
diff --git a/chrome/browser/shell_integration_linux.h b/chrome/browser/shell_integration_linux.h index 3e7f6b65..f376ae97 100644 --- a/chrome/browser/shell_integration_linux.h +++ b/chrome/browser/shell_integration_linux.h
@@ -11,6 +11,10 @@ #include "chrome/common/buildflags.h" #include "url/gurl.h" +#if defined(OS_CHROMEOS) +#error shell_integration_linux is for desktop linux only. +#endif + namespace base { class CommandLine; class Environment; @@ -86,14 +90,6 @@ std::string GetDirectoryFileContents(const base::string16& title, const std::string& icon_name); -#if BUILDFLAG(ENABLE_APP_LIST) -// Create shortcuts in the application menu for the app launcher. Duplicate -// shortcuts are avoided, so if a requested shortcut already exists it is -// deleted first. Also creates the icon required by the shortcut. -bool CreateAppListDesktopShortcut(const std::string& wm_class, - const std::string& title); -#endif - // Windows that correspond to web apps need to have a deterministic (and // different) WMClass than normal chrome windows so the window manager groups // them as a separate application.
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc index 5376da21..5309580 100644 --- a/chrome/browser/sync/chrome_sync_client.cc +++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -90,13 +90,6 @@ #include "extensions/browser/api/storage/backend_task_runner.h" #include "extensions/buildflags/buildflags.h" -#if BUILDFLAG(ENABLE_APP_LIST) -#include "ash/public/cpp/app_list/app_list_switches.h" -#include "chrome/browser/ui/app_list/app_list_syncable_service.h" -#include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" -#include "chromeos/constants/chromeos_switches.h" -#endif // BUILDFLAG(ENABLE_APP_LIST) - #if BUILDFLAG(ENABLE_EXTENSIONS) #include "chrome/browser/extensions/api/storage/settings_sync_util.h" #include "chrome/browser/extensions/extension_sync_service.h" @@ -120,6 +113,7 @@ #endif // BUILDFLAG(ENABLE_SPELLCHECK) #if defined(OS_CHROMEOS) +#include "ash/public/cpp/app_list/app_list_switches.h" #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/printing/printers_model_type_controller.h" #include "chrome/browser/chromeos/printing/printers_sync_bridge.h" @@ -127,10 +121,13 @@ #include "chrome/browser/chromeos/printing/synced_printers_manager_factory.h" #include "chrome/browser/chromeos/sync/os_preferences_model_type_controller.h" #include "chrome/browser/sync/wifi_configuration_sync_service_factory.h" +#include "chrome/browser/ui/app_list/app_list_syncable_service.h" +#include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" #include "chrome/browser/ui/app_list/arc/arc_package_sync_model_type_controller.h" #include "chrome/browser/ui/app_list/arc/arc_package_syncable_service.h" #include "chromeos/components/sync_wifi/wifi_configuration_sync_service.h" #include "chromeos/constants/chromeos_features.h" +#include "chromeos/constants/chromeos_switches.h" #include "components/arc/arc_util.h" #endif // defined(OS_CHROMEOS) @@ -400,7 +397,7 @@ } #endif // !defined(OS_ANDROID) -#if BUILDFLAG(ENABLE_APP_LIST) +#if defined(OS_CHROMEOS) // Temporarily Disable AppListSyncableService for tablet form factor devices. // See crbug/1013732 for details. if (!chromeos::switches::IsTabletFormFactor()) { @@ -409,7 +406,7 @@ syncer::APP_LIST, model_type_store_factory, GetSyncableServiceForType(syncer::APP_LIST), dump_stack)); } -#endif // BUILDFLAG(ENABLE_APP_LIST) +#endif // defined(OS_CHROMEOS) #if defined(OS_LINUX) || defined(OS_WIN) // Dictionary sync is enabled by default. @@ -495,11 +492,11 @@ case syncer::EXTENSIONS: return GetWeakPtrOrNull(ExtensionSyncService::Get(profile_)); #endif // BUILDFLAG(ENABLE_EXTENSIONS) -#if BUILDFLAG(ENABLE_APP_LIST) +#if defined(OS_CHROMEOS) case syncer::APP_LIST: return GetWeakPtrOrNull( app_list::AppListSyncableServiceFactory::GetForProfile(profile_)); -#endif // BUILDFLAG(ENABLE_APP_LIST) +#endif // defined(OS_CHROMEOS) #if !defined(OS_ANDROID) case syncer::THEMES: return ThemeServiceFactory::GetForProfile(profile_)->
diff --git a/chrome/browser/sync/profile_sync_service_factory_unittest.cc b/chrome/browser/sync/profile_sync_service_factory_unittest.cc index 1a6f92245..86576f2 100644 --- a/chrome/browser/sync/profile_sync_service_factory_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_factory_unittest.cc
@@ -79,15 +79,12 @@ datatypes.push_back(syncer::SEARCH_ENGINES); #endif // !defined(OS_ANDROID) -#if BUILDFLAG(ENABLE_APP_LIST) - datatypes.push_back(syncer::APP_LIST); -#endif // BUILDFLAG(ENABLE_APP_LIST) - #if defined(OS_LINUX) || defined(OS_WIN) datatypes.push_back(syncer::DICTIONARY); #endif #if defined(OS_CHROMEOS) + datatypes.push_back(syncer::APP_LIST); if (arc::IsArcAllowedForProfile(profile())) datatypes.push_back(syncer::ARC_PACKAGE); if (chromeos::features::IsSplitSettingsSyncEnabled()) {
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc index f3bc200..554dd60 100644 --- a/chrome/browser/sync/test/integration/sync_test.cc +++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -86,16 +86,13 @@ #include "chrome/browser/sync/test/integration/printers_helper.h" #include "chrome/browser/sync/test/integration/sync_arc_package_helper.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h" +#include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h" #include "chromeos/components/account_manager/account_manager.h" #include "chromeos/components/account_manager/account_manager_factory.h" #include "chromeos/constants/chromeos_switches.h" #include "components/arc/arc_util.h" #endif // defined(OS_CHROMEOS) -#if BUILDFLAG(ENABLE_APP_LIST) -#include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h" -#endif // BUILDFLAG(ENABLE_APP_LIST) - using syncer::ProfileSyncService; namespace switches {
diff --git a/chrome/browser/sync/test/integration/sync_test.h b/chrome/browser/sync/test/integration/sync_test.h index 97abb9a..068f7dcc 100644 --- a/chrome/browser/sync/test/integration/sync_test.h +++ b/chrome/browser/sync/test/integration/sync_test.h
@@ -29,9 +29,9 @@ #include "net/url_request/url_request_status.h" #include "services/network/test/test_url_loader_factory.h" -#if BUILDFLAG(ENABLE_APP_LIST) +#if defined(OS_CHROMEOS) #include "chrome/browser/ui/app_list/app_list_syncable_service.h" -#endif // BUILDFLAG(ENABLE_APP_LIST) +#endif // defined(OS_CHROMEOS) // The E2E tests are designed to run against real backend servers. To identify // those tests we use *E2ETest* test name filter and run disabled tests. @@ -509,7 +509,7 @@ // Disable extension install verification. extensions::ScopedInstallVerifierBypassForTest ignore_install_verification_; -#if BUILDFLAG(ENABLE_APP_LIST) +#if defined(OS_CHROMEOS) // A factory-like callback to create a model updater for testing, which will // take the place of the real updater in AppListSyncableService for testing. std::unique_ptr<
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index d1c702e..d3bdaf9 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -33,7 +33,7 @@ "app_list/app_list_util.cc", "app_list/app_list_util.h", - # All other browser/ui/app_list files go under enable_app_list below. + # All other browser/ui/app_list files go under is_chromeos below. "autofill/autofill_bubble_handler.h", "autofill/autofill_popup_controller.h", "autofill/autofill_popup_controller_impl.cc", @@ -3477,8 +3477,9 @@ } } - if (enable_app_list) { + if (is_chromeos) { sources += [ + "app_icon_loader_delegate.h", "app_list/app_context_menu.cc", "app_list/app_context_menu.h", "app_list/app_context_menu_delegate.h", @@ -3495,10 +3496,72 @@ "app_list/app_list_syncable_service.h", "app_list/app_list_syncable_service_factory.cc", "app_list/app_list_syncable_service_factory.h", + "app_list/app_service/app_service_app_icon_loader.cc", + "app_list/app_service/app_service_app_icon_loader.h", + "app_list/app_service/app_service_app_item.cc", + "app_list/app_service/app_service_app_item.h", + "app_list/app_service/app_service_app_model_builder.cc", + "app_list/app_service/app_service_app_model_builder.h", + "app_list/arc/arc_app_context_menu.cc", + "app_list/arc/arc_app_context_menu.h", + "app_list/arc/arc_app_dialog.h", + "app_list/arc/arc_app_icon.cc", + "app_list/arc/arc_app_icon.h", + "app_list/arc/arc_app_icon_descriptor.cc", + "app_list/arc/arc_app_icon_descriptor.h", + "app_list/arc/arc_app_icon_loader.cc", + "app_list/arc/arc_app_icon_loader.h", + "app_list/arc/arc_app_item.cc", + "app_list/arc/arc_app_item.h", + "app_list/arc/arc_app_launcher.cc", + "app_list/arc/arc_app_launcher.h", + "app_list/arc/arc_app_list_prefs.cc", + "app_list/arc/arc_app_list_prefs.h", + "app_list/arc/arc_app_list_prefs_factory.cc", + "app_list/arc/arc_app_list_prefs_factory.h", + "app_list/arc/arc_app_model_builder.cc", + "app_list/arc/arc_app_model_builder.h", + "app_list/arc/arc_app_scoped_pref_update.cc", + "app_list/arc/arc_app_scoped_pref_update.h", + "app_list/arc/arc_app_utils.cc", + "app_list/arc/arc_app_utils.h", + "app_list/arc/arc_data_removal_dialog.h", + "app_list/arc/arc_default_app_list.cc", + "app_list/arc/arc_default_app_list.h", + "app_list/arc/arc_fast_app_reinstall_starter.cc", + "app_list/arc/arc_fast_app_reinstall_starter.h", + "app_list/arc/arc_package_sync_model_type_controller.cc", + "app_list/arc/arc_package_sync_model_type_controller.h", + "app_list/arc/arc_package_syncable_service.cc", + "app_list/arc/arc_package_syncable_service.h", + "app_list/arc/arc_package_syncable_service_factory.cc", + "app_list/arc/arc_package_syncable_service_factory.h", + "app_list/arc/arc_pai_starter.cc", + "app_list/arc/arc_pai_starter.h", + "app_list/arc/arc_playstore_app_context_menu.cc", + "app_list/arc/arc_playstore_app_context_menu.h", + "app_list/arc/arc_usb_host_permission_manager.cc", + "app_list/arc/arc_usb_host_permission_manager.h", + "app_list/arc/arc_usb_host_permission_manager_factory.cc", + "app_list/arc/arc_usb_host_permission_manager_factory.h", + "app_list/arc/arc_vpn_provider_manager.cc", + "app_list/arc/arc_vpn_provider_manager.h", + "app_list/arc/arc_vpn_provider_manager_factory.cc", + "app_list/arc/arc_vpn_provider_manager_factory.h", "app_list/chrome_app_list_item.cc", "app_list/chrome_app_list_item.h", "app_list/chrome_app_list_model_updater.cc", "app_list/chrome_app_list_model_updater.h", + "app_list/crostini/crostini_app_context_menu.cc", + "app_list/crostini/crostini_app_context_menu.h", + "app_list/crostini/crostini_app_icon.cc", + "app_list/crostini/crostini_app_icon.h", + "app_list/crostini/crostini_app_icon_loader.cc", + "app_list/crostini/crostini_app_icon_loader.h", + "app_list/crostini/crostini_app_item.cc", + "app_list/crostini/crostini_app_item.h", + "app_list/crostini/crostini_app_model_builder.cc", + "app_list/crostini/crostini_app_model_builder.h", "app_list/extension_app_context_menu.cc", "app_list/extension_app_context_menu.h", "app_list/extension_app_item.cc", @@ -3509,8 +3572,22 @@ "app_list/extension_app_utils.h", "app_list/extension_uninstaller.cc", "app_list/extension_uninstaller.h", + "app_list/internal_app/internal_app_context_menu.cc", + "app_list/internal_app/internal_app_context_menu.h", + "app_list/internal_app/internal_app_icon_loader.cc", + "app_list/internal_app/internal_app_icon_loader.h", + "app_list/internal_app/internal_app_item.cc", + "app_list/internal_app/internal_app_item.h", + "app_list/internal_app/internal_app_metadata.cc", + "app_list/internal_app/internal_app_metadata.h", + "app_list/internal_app/internal_app_model_builder.cc", + "app_list/internal_app/internal_app_model_builder.h", "app_list/md_icon_normalizer.cc", "app_list/md_icon_normalizer.h", + "app_list/page_break_app_item.cc", + "app_list/page_break_app_item.h", + "app_list/page_break_constants.cc", + "app_list/page_break_constants.h", "app_list/search/answer_card/answer_card_result.cc", "app_list/search/answer_card/answer_card_result.h", "app_list/search/answer_card/answer_card_search_provider.cc", @@ -3519,6 +3596,8 @@ "app_list/search/app_result.h", "app_list/search/app_search_provider.cc", "app_list/search/app_search_provider.h", + "app_list/search/app_service_app_result.cc", + "app_list/search/app_service_app_result.h", "app_list/search/arc/arc_app_data_search_provider.cc", "app_list/search/arc/arc_app_data_search_provider.h", "app_list/search/arc/arc_app_data_search_result.cc", @@ -3609,183 +3688,6 @@ "app_list/search/zero_state_file_provider.h", "app_list/search/zero_state_file_result.cc", "app_list/search/zero_state_file_result.h", - ] - deps += [ - # TODO(wutao): Put new icons resources to ash/public/cpp/vector_icons/ - # when UX provides them. - "//ash/app_list", - "//ash/public/cpp/app_list/vector_icons", - "//ash/resources/vector_icons", - "//chrome/browser/ui/app_list/search/cros_action_history:cros_action_proto", - "//chrome/browser/ui/app_list/search/search_result_ranker:app_launch_event_logger_proto", - "//chrome/browser/ui/app_list/search/search_result_ranker:app_launch_predictor_proto", - "//chrome/browser/ui/app_list/search/search_result_ranker:app_list_launch_recorder_proto", - "//chrome/browser/ui/app_list/search/search_result_ranker:recurrence_ranker_proto", - "//chrome/browser/ui/app_list/search/search_result_ranker:search_ranking_event_proto", - "//components/assist_ranker", - "//components/assist_ranker/proto", - "//ui/file_manager:file_manager", - ] - - if (is_chromeos) { - sources += [ - "app_icon_loader_delegate.h", - "app_list/app_service/app_service_app_icon_loader.cc", - "app_list/app_service/app_service_app_icon_loader.h", - "app_list/app_service/app_service_app_item.cc", - "app_list/app_service/app_service_app_item.h", - "app_list/app_service/app_service_app_model_builder.cc", - "app_list/app_service/app_service_app_model_builder.h", - "app_list/arc/arc_app_context_menu.cc", - "app_list/arc/arc_app_context_menu.h", - "app_list/arc/arc_app_dialog.h", - "app_list/arc/arc_app_icon.cc", - "app_list/arc/arc_app_icon.h", - "app_list/arc/arc_app_icon_descriptor.cc", - "app_list/arc/arc_app_icon_descriptor.h", - "app_list/arc/arc_app_icon_loader.cc", - "app_list/arc/arc_app_icon_loader.h", - "app_list/arc/arc_app_item.cc", - "app_list/arc/arc_app_item.h", - "app_list/arc/arc_app_launcher.cc", - "app_list/arc/arc_app_launcher.h", - "app_list/arc/arc_app_list_prefs.cc", - "app_list/arc/arc_app_list_prefs.h", - "app_list/arc/arc_app_list_prefs_factory.cc", - "app_list/arc/arc_app_list_prefs_factory.h", - "app_list/arc/arc_app_model_builder.cc", - "app_list/arc/arc_app_model_builder.h", - "app_list/arc/arc_app_scoped_pref_update.cc", - "app_list/arc/arc_app_scoped_pref_update.h", - "app_list/arc/arc_app_utils.cc", - "app_list/arc/arc_app_utils.h", - "app_list/arc/arc_data_removal_dialog.h", - "app_list/arc/arc_default_app_list.cc", - "app_list/arc/arc_default_app_list.h", - "app_list/arc/arc_fast_app_reinstall_starter.cc", - "app_list/arc/arc_fast_app_reinstall_starter.h", - "app_list/arc/arc_package_sync_model_type_controller.cc", - "app_list/arc/arc_package_sync_model_type_controller.h", - "app_list/arc/arc_package_syncable_service.cc", - "app_list/arc/arc_package_syncable_service.h", - "app_list/arc/arc_package_syncable_service_factory.cc", - "app_list/arc/arc_package_syncable_service_factory.h", - "app_list/arc/arc_pai_starter.cc", - "app_list/arc/arc_pai_starter.h", - "app_list/arc/arc_playstore_app_context_menu.cc", - "app_list/arc/arc_playstore_app_context_menu.h", - "app_list/arc/arc_usb_host_permission_manager.cc", - "app_list/arc/arc_usb_host_permission_manager.h", - "app_list/arc/arc_usb_host_permission_manager_factory.cc", - "app_list/arc/arc_usb_host_permission_manager_factory.h", - "app_list/arc/arc_vpn_provider_manager.cc", - "app_list/arc/arc_vpn_provider_manager.h", - "app_list/arc/arc_vpn_provider_manager_factory.cc", - "app_list/arc/arc_vpn_provider_manager_factory.h", - "app_list/crostini/crostini_app_context_menu.cc", - "app_list/crostini/crostini_app_context_menu.h", - "app_list/crostini/crostini_app_icon.cc", - "app_list/crostini/crostini_app_icon.h", - "app_list/crostini/crostini_app_icon_loader.cc", - "app_list/crostini/crostini_app_icon_loader.h", - "app_list/crostini/crostini_app_item.cc", - "app_list/crostini/crostini_app_item.h", - "app_list/crostini/crostini_app_model_builder.cc", - "app_list/crostini/crostini_app_model_builder.h", - "app_list/internal_app/internal_app_context_menu.cc", - "app_list/internal_app/internal_app_context_menu.h", - "app_list/internal_app/internal_app_icon_loader.cc", - "app_list/internal_app/internal_app_icon_loader.h", - "app_list/internal_app/internal_app_item.cc", - "app_list/internal_app/internal_app_item.h", - "app_list/internal_app/internal_app_metadata.cc", - "app_list/internal_app/internal_app_metadata.h", - "app_list/internal_app/internal_app_model_builder.cc", - "app_list/internal_app/internal_app_model_builder.h", - "app_list/page_break_app_item.cc", - "app_list/page_break_app_item.h", - "app_list/page_break_constants.cc", - "app_list/page_break_constants.h", - "app_list/search/app_service_app_result.cc", - "app_list/search/app_service_app_result.h", - "ash/launcher/app_window_base.cc", - "ash/launcher/app_window_base.h", - "ash/launcher/arc_app_shelf_id.cc", - "ash/launcher/arc_app_shelf_id.h", - "ash/launcher/arc_app_window.cc", - "ash/launcher/arc_app_window.h", - "ash/launcher/arc_app_window_launcher_controller.cc", - "ash/launcher/arc_app_window_launcher_controller.h", - "ash/launcher/arc_app_window_launcher_item_controller.cc", - "ash/launcher/arc_app_window_launcher_item_controller.h", - "ash/launcher/arc_launcher_context_menu.cc", - "ash/launcher/arc_launcher_context_menu.h", - "ash/launcher/arc_shelf_spinner_item_controller.cc", - "ash/launcher/arc_shelf_spinner_item_controller.h", - "ash/launcher/crostini_app_display.cc", - "ash/launcher/crostini_app_display.h", - "ash/launcher/crostini_app_window_shelf_controller.cc", - "ash/launcher/crostini_app_window_shelf_controller.h", - "ash/launcher/crostini_shelf_context_menu.cc", - "ash/launcher/crostini_shelf_context_menu.h", - "ash/launcher/internal_app_shelf_context_menu.cc", - "ash/launcher/internal_app_shelf_context_menu.h", - "ash/launcher/internal_app_window_shelf_controller.cc", - "ash/launcher/internal_app_window_shelf_controller.h", - "ash/launcher/launcher_app_service_app_updater.cc", - "ash/launcher/launcher_app_service_app_updater.h", - "ash/launcher/launcher_arc_app_updater.cc", - "ash/launcher/launcher_arc_app_updater.h", - "ash/launcher/launcher_crostini_app_updater.cc", - "ash/launcher/launcher_crostini_app_updater.h", - "ash/launcher/shelf_spinner_controller.cc", - "ash/launcher/shelf_spinner_controller.h", - "ash/launcher/shelf_spinner_item_controller.cc", - "ash/launcher/shelf_spinner_item_controller.h", - "views/arc_app_dialog_view.cc", - "views/arc_data_removal_dialog_view.cc", - "views/crostini/crostini_ansible_software_config_view.cc", - "views/crostini/crostini_ansible_software_config_view.h", - "views/crostini/crostini_app_restart_view.cc", - "views/crostini/crostini_app_restart_view.h", - "views/crostini/crostini_app_uninstaller_view.cc", - "views/crostini/crostini_app_uninstaller_view.h", - "views/crostini/crostini_force_close_view.cc", - "views/crostini/crostini_force_close_view.h", - "views/crostini/crostini_installer_view.cc", - "views/crostini/crostini_installer_view.h", - "views/crostini/crostini_uninstaller_view.cc", - "views/crostini/crostini_uninstaller_view.h", - "views/crostini/crostini_upgrade_container_view.cc", - "views/crostini/crostini_upgrade_container_view.h", - "views/crostini/crostini_upgrade_view.cc", - "views/crostini/crostini_upgrade_view.h", - "views/plugin_vm/plugin_vm_launcher_view.cc", - "views/plugin_vm/plugin_vm_launcher_view.h", - ] - deps += [ - "//chrome/browser/chromeos/crostini:crostini_installer_types_mojom", - "//chrome/services/app_service/public/cpp:app_update", - "//chrome/services/app_service/public/cpp:icon_loader", - "//components/services/app_service/public/cpp:app_file_handling", - ] - } - } - - if (is_chromeos) { - deps += [ - "//ash/public/cpp", - "//chromeos/services/assistant:lib", - "//chromeos/services/assistant/public/mojom", - "//chromeos/services/network_config/public/mojom", - "//services/audio/public/mojom", - "//services/device/public/mojom", - "//services/identity/public/mojom", - "//services/media_session/public/mojom", - "//services/preferences/public/mojom", - ] - - sources += [ "ash/assistant/assistant_client.cc", "ash/assistant/assistant_client.h", "ash/assistant/assistant_context_util.cc", @@ -3804,6 +3706,89 @@ "ash/assistant/proactive_suggestions_client_impl.h", "ash/assistant/proactive_suggestions_loader.cc", "ash/assistant/proactive_suggestions_loader.h", + "ash/launcher/app_window_base.cc", + "ash/launcher/app_window_base.h", + "ash/launcher/arc_app_shelf_id.cc", + "ash/launcher/arc_app_shelf_id.h", + "ash/launcher/arc_app_window.cc", + "ash/launcher/arc_app_window.h", + "ash/launcher/arc_app_window_launcher_controller.cc", + "ash/launcher/arc_app_window_launcher_controller.h", + "ash/launcher/arc_app_window_launcher_item_controller.cc", + "ash/launcher/arc_app_window_launcher_item_controller.h", + "ash/launcher/arc_launcher_context_menu.cc", + "ash/launcher/arc_launcher_context_menu.h", + "ash/launcher/arc_shelf_spinner_item_controller.cc", + "ash/launcher/arc_shelf_spinner_item_controller.h", + "ash/launcher/crostini_app_display.cc", + "ash/launcher/crostini_app_display.h", + "ash/launcher/crostini_app_window_shelf_controller.cc", + "ash/launcher/crostini_app_window_shelf_controller.h", + "ash/launcher/crostini_shelf_context_menu.cc", + "ash/launcher/crostini_shelf_context_menu.h", + "ash/launcher/internal_app_shelf_context_menu.cc", + "ash/launcher/internal_app_shelf_context_menu.h", + "ash/launcher/internal_app_window_shelf_controller.cc", + "ash/launcher/internal_app_window_shelf_controller.h", + "ash/launcher/launcher_app_service_app_updater.cc", + "ash/launcher/launcher_app_service_app_updater.h", + "ash/launcher/launcher_arc_app_updater.cc", + "ash/launcher/launcher_arc_app_updater.h", + "ash/launcher/launcher_crostini_app_updater.cc", + "ash/launcher/launcher_crostini_app_updater.h", + "ash/launcher/shelf_spinner_controller.cc", + "ash/launcher/shelf_spinner_controller.h", + "ash/launcher/shelf_spinner_item_controller.cc", + "ash/launcher/shelf_spinner_item_controller.h", + "views/arc_app_dialog_view.cc", + "views/arc_data_removal_dialog_view.cc", + "views/crostini/crostini_ansible_software_config_view.cc", + "views/crostini/crostini_ansible_software_config_view.h", + "views/crostini/crostini_app_restart_view.cc", + "views/crostini/crostini_app_restart_view.h", + "views/crostini/crostini_app_uninstaller_view.cc", + "views/crostini/crostini_app_uninstaller_view.h", + "views/crostini/crostini_force_close_view.cc", + "views/crostini/crostini_force_close_view.h", + "views/crostini/crostini_installer_view.cc", + "views/crostini/crostini_installer_view.h", + "views/crostini/crostini_uninstaller_view.cc", + "views/crostini/crostini_uninstaller_view.h", + "views/crostini/crostini_upgrade_container_view.cc", + "views/crostini/crostini_upgrade_container_view.h", + "views/crostini/crostini_upgrade_view.cc", + "views/crostini/crostini_upgrade_view.h", + "views/plugin_vm/plugin_vm_launcher_view.cc", + "views/plugin_vm/plugin_vm_launcher_view.h", + ] + deps += [ + # TODO(wutao): Put new icons resources to ash/public/cpp/vector_icons/ + # when UX provides them. + "//ash/app_list", + "//ash/public/cpp", + "//ash/public/cpp/app_list/vector_icons", + "//ash/resources/vector_icons", + "//chrome/browser/chromeos/crostini:crostini_installer_types_mojom", + "//chrome/browser/ui/app_list/search/cros_action_history:cros_action_proto", + "//chrome/browser/ui/app_list/search/search_result_ranker:app_launch_event_logger_proto", + "//chrome/browser/ui/app_list/search/search_result_ranker:app_launch_predictor_proto", + "//chrome/browser/ui/app_list/search/search_result_ranker:app_list_launch_recorder_proto", + "//chrome/browser/ui/app_list/search/search_result_ranker:recurrence_ranker_proto", + "//chrome/browser/ui/app_list/search/search_result_ranker:search_ranking_event_proto", + "//chrome/services/app_service/public/cpp:app_update", + "//chrome/services/app_service/public/cpp:icon_loader", + "//chromeos/services/assistant:lib", + "//chromeos/services/assistant/public/mojom", + "//chromeos/services/network_config/public/mojom", + "//components/assist_ranker", + "//components/assist_ranker/proto", + "//components/services/app_service/public/cpp:app_file_handling", + "//services/audio/public/mojom", + "//services/device/public/mojom", + "//services/identity/public/mojom", + "//services/media_session/public/mojom", + "//services/preferences/public/mojom", + "//ui/file_manager:file_manager", ] }
diff --git a/chrome/browser/ui/apps/app_info_dialog.h b/chrome/browser/ui/apps/app_info_dialog.h index e4ea140..91b5e34 100644 --- a/chrome/browser/ui/apps/app_info_dialog.h +++ b/chrome/browser/ui/apps/app_info_dialog.h
@@ -6,9 +6,8 @@ #define CHROME_BROWSER_UI_APPS_APP_INFO_DIALOG_H_ #include "base/callback_forward.h" -#include "chrome/common/buildflags.h" -#if BUILDFLAG(ENABLE_APP_LIST) +#if defined(OS_CHROMEOS) #include "ui/gfx/native_widget_types.h" #endif @@ -39,7 +38,7 @@ // Returns true if the app info dialog is available on the current platform. bool CanShowAppInfoDialog(); -#if BUILDFLAG(ENABLE_APP_LIST) +#if defined(OS_CHROMEOS) // Shows the chrome app information as a frameless window for the given |app| // and |profile| at the given |app_info_bounds|. void ShowAppInfoInAppList(gfx::NativeWindow parent,
diff --git a/chrome/browser/ui/search/search_ipc_router.cc b/chrome/browser/ui/search/search_ipc_router.cc index 3fb3ffe1..77ab9e08 100644 --- a/chrome/browser/ui/search/search_ipc_router.cc +++ b/chrome/browser/ui/search/search_ipc_router.cc
@@ -454,7 +454,7 @@ } void SearchIPCRouter::StopAutocomplete(bool clear_result) { - if (!policy_->ShouldProcessStopAutocomplete(is_active_tab_)) { + if (!policy_->ShouldProcessStopAutocomplete()) { return; }
diff --git a/chrome/browser/ui/search/search_ipc_router.h b/chrome/browser/ui/search/search_ipc_router.h index e56d10f..a3be7fd 100644 --- a/chrome/browser/ui/search/search_ipc_router.h +++ b/chrome/browser/ui/search/search_ipc_router.h
@@ -207,7 +207,7 @@ virtual bool ShouldProcessOptOutOfSearchSuggestions() = 0; virtual bool ShouldProcessThemeChangeMessages() = 0; virtual bool ShouldProcessQueryAutocomplete(bool is_active_tab) = 0; - virtual bool ShouldProcessStopAutocomplete(bool is_active_tab) = 0; + virtual bool ShouldProcessStopAutocomplete() = 0; virtual bool ShouldProcessBlocklistPromo() = 0; virtual bool ShouldProcessDeleteAutocompleteMatch() = 0; };
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_impl.cc b/chrome/browser/ui/search/search_ipc_router_policy_impl.cc index 1305e636..9d6b624 100644 --- a/chrome/browser/ui/search/search_ipc_router_policy_impl.cc +++ b/chrome/browser/ui/search/search_ipc_router_policy_impl.cc
@@ -137,9 +137,8 @@ return is_active_tab && !is_incognito_ && search::IsInstantNTP(web_contents_); } -bool SearchIPCRouterPolicyImpl::ShouldProcessStopAutocomplete( - bool is_active_tab) { - return is_active_tab && !is_incognito_ && search::IsInstantNTP(web_contents_); +bool SearchIPCRouterPolicyImpl::ShouldProcessStopAutocomplete() { + return !is_incognito_ && search::IsInstantNTP(web_contents_); } bool SearchIPCRouterPolicyImpl::ShouldProcessBlocklistPromo() {
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_impl.h b/chrome/browser/ui/search/search_ipc_router_policy_impl.h index 7c3a83b7..37599bfb 100644 --- a/chrome/browser/ui/search/search_ipc_router_policy_impl.h +++ b/chrome/browser/ui/search/search_ipc_router_policy_impl.h
@@ -55,7 +55,7 @@ bool ShouldProcessOptOutOfSearchSuggestions() override; bool ShouldProcessThemeChangeMessages() override; bool ShouldProcessQueryAutocomplete(bool is_active_tab) override; - bool ShouldProcessStopAutocomplete(bool is_active_tab) override; + bool ShouldProcessStopAutocomplete() override; bool ShouldProcessBlocklistPromo() override; bool ShouldProcessDeleteAutocompleteMatch() override;
diff --git a/chrome/browser/ui/search/search_ipc_router_unittest.cc b/chrome/browser/ui/search/search_ipc_router_unittest.cc index 2aa416d8d..4023a56 100644 --- a/chrome/browser/ui/search/search_ipc_router_unittest.cc +++ b/chrome/browser/ui/search/search_ipc_router_unittest.cc
@@ -112,7 +112,7 @@ QueryAutocomplete, void(const base::string16& input, chrome::mojom::EmbeddedSearch::QueryAutocompleteCallback callback)); - MOCK_METHOD1(StopAutocomplete, void(bool clear_result)); + MOCK_METHOD1(StopAutocomplete, void(bool)); MOCK_METHOD1(BlocklistPromo, void(const std::string& promo_id)); }; @@ -149,7 +149,7 @@ MOCK_METHOD0(ShouldSendLocalBackgroundSelected, bool()); MOCK_METHOD0(ShouldProcessThemeChangeMessages, bool()); MOCK_METHOD1(ShouldProcessQueryAutocomplete, bool(bool)); - MOCK_METHOD1(ShouldProcessStopAutocomplete, bool(bool)); + MOCK_METHOD0(ShouldProcessStopAutocomplete, bool()); MOCK_METHOD0(ShouldProcessBlocklistPromo, bool()); MOCK_METHOD0(ShouldProcessDeleteAutocompleteMatch, bool()); }; @@ -1119,3 +1119,15 @@ callback; GetSearchIPCRouter().DeleteAutocompleteMatch(0u, callback.Get()); } + +TEST_F(SearchIPCRouterTest, IgnoreStopAutoComplete) { + NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar")); + SetupMockDelegateAndPolicy(); + MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy(); + EXPECT_CALL(*mock_delegate(), StopAutocomplete(_)).Times(0); + EXPECT_CALL(*policy, ShouldProcessStopAutocomplete()) + .Times(1) + .WillOnce(Return(false)); + + GetSearchIPCRouter().StopAutocomplete(false); +}
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index f688acd4..4d80dee 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -28,6 +28,7 @@ #include "chrome/browser/history/top_sites_factory.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/installable/installable_manager.h" +#include "chrome/browser/media/history/media_history_contents_observer.h" #include "chrome/browser/media/media_engagement_service.h" #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_observer.h" #include "chrome/browser/metrics/oom/out_of_memory_reporter.h" @@ -99,6 +100,7 @@ #include "components/ukm/content/source_url_recorder.h" #include "content/public/browser/web_contents.h" #include "extensions/buildflags/buildflags.h" +#include "media/base/media_switches.h" #include "printing/buildflags/buildflags.h" #if defined(OS_ANDROID) @@ -380,6 +382,9 @@ if (MediaEngagementService::IsEnabled()) MediaEngagementService::CreateWebContentsObserver(web_contents); + if (base::FeatureList::IsEnabled(media::kUseMediaHistoryStore)) + MediaHistoryContentsObserver::CreateForWebContents(web_contents); + if (performance_manager::PerformanceManager::IsAvailable()) { performance_manager::PerformanceManagerTabHelper::CreateForWebContents( web_contents);
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc index acfd3ac..ebae5209 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc
@@ -28,7 +28,7 @@ #include "ui/views/window/native_frame_view.h" #include "ui/views/window/non_client_view.h" -#if BUILDFLAG(ENABLE_APP_LIST) +#if defined(OS_CHROMEOS) #include "ash/public/cpp/app_list/app_list_config.h" #include "third_party/skia/include/core/SkPaint.h" #include "ui/native_theme/native_theme.h" @@ -46,7 +46,7 @@ views::BubbleBorder::SMALL_SHADOW; #endif -#if BUILDFLAG(ENABLE_APP_LIST) +#if defined(OS_CHROMEOS) // The background for App List dialogs, which appears as a rounded rectangle // with the same border radius and color as the app list contents. class AppListOverlayBackground : public views::Background { @@ -71,7 +71,7 @@ private: DISALLOW_COPY_AND_ASSIGN(AppListOverlayBackground); }; -#endif // ENABLE_APP_LIST +#endif // defined(OS_CHROMEOS) // Base container for modal dialogs. Encases a content view in a modal dialog // with an accelerator to close on escape. @@ -103,7 +103,7 @@ DISALLOW_COPY_AND_ASSIGN(BaseDialogContainer); }; -#if BUILDFLAG(ENABLE_APP_LIST) +#if defined(OS_CHROMEOS) // The contents view for an App List Dialog, which covers the entire app list // and adds a close button. @@ -153,7 +153,7 @@ DISALLOW_COPY_AND_ASSIGN(AppListDialogContainer); }; -#endif // ENABLE_APP_LIST +#endif // defined(OS_CHROMEOS) // A BubbleFrameView that allows its client view to extend all the way to the // top of the dialog, overlapping the BubbleFrameView's close button. This @@ -218,12 +218,12 @@ } // namespace -#if BUILDFLAG(ENABLE_APP_LIST) +#if defined(OS_CHROMEOS) views::DialogDelegateView* CreateAppListContainerForView( std::unique_ptr<views::View> view) { return new AppListDialogContainer(std::move(view)); } -#endif // ENABLE_APP_LIST +#endif // defined(OS_CHROMEOS) views::DialogDelegateView* CreateDialogContainerForView( std::unique_ptr<views::View> view,
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.h b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.h index d9a17f5..61c9757 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.h +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.h
@@ -8,7 +8,6 @@ #include <memory> #include "base/callback_forward.h" -#include "chrome/common/buildflags.h" #include "ui/gfx/geometry/size.h" namespace views { @@ -16,14 +15,14 @@ class View; } -#if BUILDFLAG(ENABLE_APP_LIST) +#if defined(OS_CHROMEOS) // Creates a new dialog containing |view| that can be displayed inside the app // list, covering the entire app list and adding a close button. views::DialogDelegateView* CreateAppListContainerForView( std::unique_ptr<views::View> view); -#endif // ENABLE_APP_LIST +#endif // defined(OS_CHROMEOS) // Creates a new native dialog of the given |size| containing |view| with a // close button and draggable titlebar.
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc index bc1e6f32..c77ec0c 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc
@@ -64,7 +64,7 @@ #endif } -#if BUILDFLAG(ENABLE_APP_LIST) +#if defined(OS_CHROMEOS) void ShowAppInfoInAppList(gfx::NativeWindow parent, const gfx::Rect& app_info_bounds, Profile* profile,
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc index f720d164..f5d9e920 100644 --- a/chrome/browser/ui/views/download/download_item_view.cc +++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -28,6 +28,7 @@ #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_stats.h" #include "chrome/browser/download/drag_download_item.h" +#include "chrome/browser/icon_loader.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/advanced_protection_status_manager.h" #include "chrome/browser/safe_browsing/advanced_protection_status_manager_factory.h" @@ -63,6 +64,7 @@ #include "ui/gfx/color_palette.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/image/image.h" +#include "ui/gfx/image/image_skia_operations.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/text_elider.h" #include "ui/gfx/text_utils.h" @@ -100,6 +102,12 @@ // Amount of time between accessible alert events. constexpr auto kAccessibleAlertInterval = base::TimeDelta::FromSeconds(30); +// The size of the file icon. +constexpr int kFileIconSize = 24; + +// The offset from the file icon to the danger icon. +constexpr int kDangerIconOffset = 8; + // The separator is drawn as a border. It's one dp wide. class SeparatorBorder : public views::Border { public: @@ -271,9 +279,18 @@ : gfx::kPlaceholderColor; } -void DownloadItemView::OnExtractIconComplete(gfx::Image icon_bitmap) { - if (!icon_bitmap.IsEmpty()) +void DownloadItemView::OnExtractIconComplete(IconLoader::IconSize icon_size, + gfx::Image icon_bitmap) { + if (!icon_bitmap.IsEmpty()) { + if (icon_size == IconLoader::IconSize::NORMAL) { + // We want a 24x24 icon, but on Windows only 16x16 and 32x32 are + // available. So take the NORMAL icon and downsize it. + icon_ = gfx::ImageSkiaOperations::CreateResizedImage( + *icon_bitmap.ToImageSkia(), skia::ImageOperations::RESIZE_BEST, + gfx::Size(kFileIconSize, kFileIconSize)); + } shelf_->SchedulePaint(); + } } void DownloadItemView::MaybeSubmitDownloadToFeedbackService( @@ -709,15 +726,6 @@ } void DownloadItemView::DrawIcon(gfx::Canvas* canvas) { - if (IsShowingWarningDialog() || IsShowingDeepScanning()) { - int icon_x = base::i18n::IsRTL() - ? width() - kWarningIconSize - kStartPadding - : kStartPadding; - int icon_y = (height() - kWarningIconSize) / 2; - canvas->DrawImageInt(GetWarningIcon(), icon_x, icon_y); - return; - } - // Paint download progress. DownloadItem::DownloadState state = model_->GetState(); canvas->Save(); @@ -728,7 +736,15 @@ int progress_y = (height() - DownloadShelf::kProgressIndicatorSize) / 2; canvas->Translate(gfx::Vector2d(progress_x, progress_y)); - if (state == DownloadItem::IN_PROGRESS) { + const gfx::ImageSkia* current_icon = nullptr; + IconManager* im = g_browser_process->icon_manager(); + gfx::Image* image_ptr = im->LookupIconFromFilepath( + model_->GetTargetFilePath(), IconLoader::SMALL); + if (image_ptr) + current_icon = image_ptr->ToImageSkia(); + + if (state == DownloadItem::IN_PROGRESS && !IsShowingDeepScanning() && + !IsShowingWarningDialog()) { base::TimeDelta progress_time = previous_progress_elapsed_; if (!model_->IsPaused()) progress_time += base::TimeTicks::Now() - progress_start_time_; @@ -743,26 +759,34 @@ DownloadShelf::PaintDownloadComplete( canvas, *GetThemeProvider(), complete_animation_->GetCurrentValue()); } + } else { + current_icon = &icon_; } canvas->Restore(); - // Fetch the already-loaded icon. - IconManager* im = g_browser_process->icon_manager(); - gfx::Image* icon = im->LookupIconFromFilepath(model_->GetTargetFilePath(), - IconLoader::SMALL); - if (!icon) + if (!current_icon) return; // Draw the icon image. - constexpr int kFiletypeIconOffset = - (DownloadShelf::kProgressIndicatorSize - 16) / 2; + int kFiletypeIconOffset = + (DownloadShelf::kProgressIndicatorSize - current_icon->height()) / 2; int icon_x = progress_x + kFiletypeIconOffset; int icon_y = progress_y + kFiletypeIconOffset; cc::PaintFlags flags; // Use an alpha to make the image look disabled. if (!GetEnabled()) flags.setAlpha(120); - canvas->DrawImageInt(*icon->ToImageSkia(), icon_x, icon_y, flags); + canvas->DrawImageInt(*current_icon, icon_x, icon_y, flags); + + // Overlay the danger icon if appropriate. + if (IsShowingWarningDialog() || IsShowingDeepScanning()) { + int icon_x = + (base::i18n::IsRTL() ? width() - kWarningIconSize - kStartPadding + : kStartPadding) + + kDangerIconOffset; + int icon_y = (height() - kWarningIconSize) / 2 + kDangerIconOffset; + canvas->DrawImageInt(GetWarningIcon(), icon_x, icon_y); + } } void DownloadItemView::OpenDownload() { @@ -809,7 +833,11 @@ last_download_item_path_ = model_->GetTargetFilePath(); im->LoadIcon(last_download_item_path_, IconLoader::SMALL, base::Bind(&DownloadItemView::OnExtractIconComplete, - base::Unretained(this)), + base::Unretained(this), IconLoader::IconSize::SMALL), + &cancelable_task_tracker_); + im->LoadIcon(last_download_item_path_, IconLoader::NORMAL, + base::Bind(&DownloadItemView::OnExtractIconComplete, + base::Unretained(this), IconLoader::NORMAL), &cancelable_task_tracker_); }
diff --git a/chrome/browser/ui/views/download/download_item_view.h b/chrome/browser/ui/views/download/download_item_view.h index 5301ad525..c961f51e 100644 --- a/chrome/browser/ui/views/download/download_item_view.h +++ b/chrome/browser/ui/views/download/download_item_view.h
@@ -77,7 +77,7 @@ // Returns the base color for text on this download item, based on |theme|. static SkColor GetTextColorForThemeProvider(const ui::ThemeProvider* theme); - void OnExtractIconComplete(gfx::Image icon); + void OnExtractIconComplete(IconLoader::IconSize icon_size, gfx::Image icon); // Returns the DownloadUIModel object belonging to this item. DownloadUIModel* model() { return model_.get(); } @@ -158,10 +158,10 @@ static constexpr int kLabelPadding = 8; // Height/width of the warning icon, also in dp. - static constexpr int kWarningIconSize = 24; + static constexpr int kWarningIconSize = 20; // Height/width of the erro icon, also in dp. - static constexpr int kErrorIconSize = 27; + static constexpr int kErrorIconSize = 20; void OpenDownload(); @@ -423,6 +423,9 @@ // Deep scanning modal dialog confirming choice to "open now". TabModalConfirmDialog* open_now_modal_dialog_; + // Icon for the download. + gfx::ImageSkia icon_; + // Method factory used to delay reenabling of the item when opening the // downloaded file. base::WeakPtrFactory<DownloadItemView> weak_ptr_factory_{this};
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 986bdd5..21bfbaf 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -2342,6 +2342,10 @@ // (Windows) or Ctrl+Back/Forward (Chrome OS). If one of these is // invisible or has no focusable children, it will be automatically // skipped. +#if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) + if (webui_tab_strip_) + panes->push_back(webui_tab_strip_); +#endif panes->push_back(toolbar_button_provider_->GetAsAccessiblePaneView()); if (tabstrip_) panes->push_back(tabstrip_);
diff --git a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc index 6a99049..cfecf83 100644 --- a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc +++ b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc
@@ -143,6 +143,8 @@ // fired. web_view_->GetWebContents()->WasHidden(); + web_view_->set_allow_accelerators(true); + SetLayoutManager(std::make_unique<views::FillLayout>()); web_view_->LoadInitialURL(GURL(chrome::kChromeUITabStripURL)); extensions::ChromeExtensionWebContentsObserver::CreateForWebContents( @@ -236,9 +238,11 @@ SetVisible(true); animation_.SetSlideDuration(base::TimeDelta::FromMilliseconds(250)); animation_.Show(); + web_view_->SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); } else { animation_.SetSlideDuration(base::TimeDelta::FromMilliseconds(200)); animation_.Hide(); + web_view_->SetFocusBehavior(FocusBehavior::NEVER); } auto_closer_->set_enabled(target_visible); } @@ -315,6 +319,12 @@ const ui::Event& event) { if (sender->GetID() == VIEW_ID_WEBUI_TAB_STRIP_TAB_COUNTER) { SetContainerTargetVisibility(!GetVisible()); + + if (GetVisible() && sender->HasFocus()) { + // Automatically move focus to the tab strip WebUI if the focus is + // currently on the toggle button. + SetPaneFocus(web_view_); + } } else if (sender->GetID() == VIEW_ID_WEBUI_TAB_STRIP_NEW_TAB_BUTTON) { chrome::ExecuteCommand(browser_, IDC_NEW_TAB); } else {
diff --git a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.h b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.h index 28d262b..56feb5a 100644 --- a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.h +++ b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.h
@@ -13,6 +13,7 @@ #include "chrome/common/buildflags.h" #include "ui/events/event_handler.h" #include "ui/gfx/animation/slide_animation.h" +#include "ui/views/accessible_pane_view.h" #include "ui/views/view.h" #if !BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) @@ -33,8 +34,8 @@ class TabCounterModelObserver; class WebUITabStripContainerView : public TabStripUI::Embedder, - public views::View, public gfx::AnimationDelegate, + public views::AccessiblePaneView, public views::ButtonListener, public views::ViewObserver { public:
diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/crashes_ui.cc index 08075f51..121cac7 100644 --- a/chrome/browser/ui/webui/crashes_ui.cc +++ b/chrome/browser/ui/webui/crashes_ui.cc
@@ -20,16 +20,19 @@ #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" #include "chrome/browser/metrics/metrics_reporting_state.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/common/url_constants.h" #include "chrome/grit/chromium_strings.h" #include "components/crash/core/browser/crashes_ui_util.h" #include "components/grit/components_resources.h" #include "components/grit/components_scaled_resources.h" +#include "components/signin/public/identity_manager/identity_manager.h" #include "components/version_info/version_info.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_message_handler.h" +#include "google_apis/gaia/gaia_auth_util.h" #include "ui/base/resource/resource_bundle.h" #if defined(OS_CHROMEOS) @@ -181,6 +184,14 @@ using_crashpad = crash_reporter::IsCrashpadEnabled(); #endif + bool is_internal = false; + auto* identity_manager = + IdentityManagerFactory::GetForProfile(Profile::FromWebUI(web_ui())); + if (identity_manager) { + is_internal = gaia::IsGoogleInternalAccountEmail( + identity_manager->GetPrimaryAccountInfo().email); + } + // Manual uploads currently are supported only for Crashpad-using platforms // and only if crash uploads are not disabled by policy. bool support_manual_uploads = @@ -201,6 +212,7 @@ base::Value version(version_info::GetVersionNumber()); base::Value os_string(base::SysInfo::OperatingSystemName() + " " + base::SysInfo::OperatingSystemVersion()); + base::Value is_google_account(is_internal); std::vector<const base::Value*> args; args.push_back(&enabled); @@ -209,6 +221,7 @@ args.push_back(&crash_list); args.push_back(&version); args.push_back(&os_string); + args.push_back(&is_google_account); web_ui()->CallJavascriptFunctionUnsafe( crash_reporter::kCrashesUIUpdateCrashList, args); } @@ -247,7 +260,7 @@ // static base::RefCountedMemory* CrashesUI::GetFaviconResourceBytes( - ui::ScaleFactor scale_factor) { + ui::ScaleFactor scale_factor) { return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( IDR_CRASH_SAD_FAVICON, scale_factor); }
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc index c042414..76043fc 100644 --- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc +++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc
@@ -171,11 +171,21 @@ base::Value(move->to_index)); break; } - - case TabStripModelChange::kReplaced: - case TabStripModelChange::kGroupChanged: + case TabStripModelChange::kReplaced: { + auto* replace = change.GetReplace(); + FireWebUIListener("tab-replaced", + base::Value(extensions::ExtensionTabUtil::GetTabId( + replace->old_contents)), + base::Value(extensions::ExtensionTabUtil::GetTabId( + replace->new_contents))); + break; + } + case TabStripModelChange::kGroupChanged: { + // Not yet implmented. + break; + } case TabStripModelChange::kSelectionOnly: - // Not yet implemented. + // Multi-selection is not supported for touch. break; } @@ -460,6 +470,7 @@ base::FeatureList::IsEnabled(features::kWebUITabStripDemoOptions)); static constexpr LocalizedString kStrings[] = { + {"tabListTitle", IDS_ACCNAME_TAB_LIST}, {"closeTab", IDS_ACCNAME_CLOSE}, {"tabCrashed", IDS_TAB_AX_LABEL_CRASHED_FORMAT}, {"tabNetworkError", IDS_TAB_AX_LABEL_NETWORK_ERROR_FORMAT},
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_linux.cc b/chrome/browser/web_applications/components/web_app_shortcut_linux.cc index daed85c..cf994922 100644 --- a/chrome/browser/web_applications/components/web_app_shortcut_linux.cc +++ b/chrome/browser/web_applications/components/web_app_shortcut_linux.cc
@@ -30,12 +30,6 @@ const char kDirectoryFilename[] = "chrome-apps.directory"; -#if BUILDFLAG(ENABLE_APP_LIST) -// The Categories for the App Launcher desktop shortcut. Should be the same as -// the Chrome desktop shortcut, so they are in the same sub-menu. -const char kAppListCategories[] = "Network;WebBrowser;"; -#endif - std::string CreateShortcutIcon(const gfx::ImageFamily& icon_images, const base::FilePath& shortcut_filename) { if (icon_images.empty())
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index 7e705c6..b10ae04 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -36,7 +36,6 @@ header = "buildflags.h" flags = [ "BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED=$builtin_cert_verifier_policy_supported", - "ENABLE_APP_LIST=$enable_app_list", "ENABLE_BACKGROUND_MODE=$enable_background_mode", "ENABLE_BACKGROUND_CONTENTS=$enable_background_contents", "ENABLE_BASIC_PRINT_DIALOG=$enable_basic_print_dialog",
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 944a2ff..060a6e1 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -2397,9 +2397,6 @@ const char kRLZBrand[] = "rlz.brand"; // Whether RLZ pings are disabled. const char kRLZDisabled[] = "rlz.disabled"; -#endif - -#if BUILDFLAG(ENABLE_APP_LIST) // Keeps local state of app list while sync service is not available. const char kAppListLocalState[] = "app_list.local_state"; #endif
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index e7fc549..fec4266 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -819,11 +819,8 @@ #if defined(OS_CHROMEOS) extern const char kRLZBrand[]; extern const char kRLZDisabled[]; -#endif - -#if BUILDFLAG(ENABLE_APP_LIST) extern const char kAppListLocalState[]; -#endif // BUILDFLAG(ENABLE_APP_LIST) +#endif extern const char kAppShortcutsVersion[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index f85cbbe67..a833fe2 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3696,8 +3696,7 @@ "../browser/enterprise_reporting/policy_info_unittest.cc", "../browser/enterprise_reporting/profile_report_generator_unittest.cc", "../browser/enterprise_reporting/report_generator_unittest.cc", - "../browser/enterprise_reporting/report_scheduler_unittest.cc", - "../browser/enterprise_reporting/report_uploader_unittest.cc", + "../browser/enterprise_reporting/report_request_queue_generator_unittest.cc", "../browser/enterprise_reporting/request_timer_unittest.cc", "../browser/first_run/first_run_unittest.cc", "../browser/font_family_cache_unittest.cc", @@ -3985,6 +3984,15 @@ if (is_mac) { deps += [ ":firefox_importer_interface" ] } + + # TODO(anqing): finally these two set of unit test will be suitable to + # other platforms, rather than Chrome OS only. + if (!is_chromeos) { + sources += [ + "../browser/enterprise_reporting/report_scheduler_unittest.cc", + "../browser/enterprise_reporting/report_uploader_unittest.cc", + ] + } } if (!is_android) {
diff --git a/chrome/test/data/android/render_tests/ReturnToChromeTest.10_web_tabs-select_last.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/ReturnToChromeTest.10_web_tabs-select_last.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..2a49f34 --- /dev/null +++ b/chrome/test/data/android/render_tests/ReturnToChromeTest.10_web_tabs-select_last.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +ca7317919b3080d8417090e4dca23f1329353842 \ No newline at end of file
diff --git a/chrome/test/data/webui/tab_strip/tab_list_test.js b/chrome/test/data/webui/tab_strip/tab_list_test.js index 563dd6e9b..ddc3abf 100644 --- a/chrome/test/data/webui/tab_strip/tab_list_test.js +++ b/chrome/test/data/webui/tab_strip/tab_list_test.js
@@ -511,4 +511,21 @@ assertEquals( testTabsApiProxy.getCallCount('setThumbnailTracked'), tabs.length); }); + + test( + 'focusing and blurring the window focuses and blurs the first tab', + () => { + window.dispatchEvent(new Event('focus')); + assertEquals(document.activeElement, tabList); + assertEquals(tabList.shadowRoot.activeElement, getUnpinnedTabs()[0]); + + window.dispatchEvent(new Event('blur')); + assertEquals(tabList.shadowRoot.activeElement, null); + }); + + test('should update the ID when a tab is replaced', () => { + assertEquals(getUnpinnedTabs()[0].tab.id, 0); + webUIListenerCallback('tab-replaced', tabs[0].id, 1000); + assertEquals(getUnpinnedTabs()[0].tab.id, 1000); + }); });
diff --git a/chrome/test/data/webui/tab_strip/tab_test.js b/chrome/test/data/webui/tab_strip/tab_test.js index 8fe8a14c..ca159f5 100644 --- a/chrome/test/data/webui/tab_strip/tab_test.js +++ b/chrome/test/data/webui/tab_strip/tab_test.js
@@ -311,4 +311,22 @@ titleTextElement.getAttribute('aria-label'), 'My tab has a network error'); }); + + test('focusing on the host moves focus to inner tab element', () => { + tabElement.focus(); + assertEquals( + tabElement.shadowRoot.activeElement, + tabElement.shadowRoot.querySelector('#tab')); + }); + + test('supports Enter and Space key for activating tab', async () => { + const innerTabElement = tabElement.shadowRoot.querySelector('#tab'); + innerTabElement.dispatchEvent(new KeyboardEvent('keydown', {key: 'Enter'})); + assertEquals(await testTabsApiProxy.whenCalled('activateTab'), tab.id); + testTabsApiProxy.reset(); + + innerTabElement.dispatchEvent(new KeyboardEvent('keydown', {key: ' '})); + assertEquals(await testTabsApiProxy.whenCalled('activateTab'), tab.id); + testTabsApiProxy.reset(); + }); });
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index b5eb650..6172136 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -12644.0.0 \ No newline at end of file +12657.0.0 \ No newline at end of file
diff --git a/chromeos/components/multidevice/beacon_seed.cc b/chromeos/components/multidevice/beacon_seed.cc index 368a3d9..0a80083 100644 --- a/chromeos/components/multidevice/beacon_seed.cc +++ b/chromeos/components/multidevice/beacon_seed.cc
@@ -45,6 +45,22 @@ return cryptauth_seed; } +BeaconSeed FromCryptAuthV2Seed(cryptauthv2::BeaconSeed cryptauth_seed) { + return BeaconSeed( + cryptauth_seed.data(), + base::Time::FromJavaTime(cryptauth_seed.start_time_millis()), + base::Time::FromJavaTime(cryptauth_seed.end_time_millis())); +} + +cryptauthv2::BeaconSeed ToCryptAuthV2Seed(BeaconSeed multidevice_seed) { + cryptauthv2::BeaconSeed cryptauth_seed; + cryptauth_seed.set_data(multidevice_seed.data()); + cryptauth_seed.set_start_time_millis( + multidevice_seed.start_time().ToJavaTime()); + cryptauth_seed.set_end_time_millis(multidevice_seed.end_time().ToJavaTime()); + return cryptauth_seed; +} + std::vector<cryptauth::BeaconSeed> ToCryptAuthSeedList( const std::vector<BeaconSeed>& multidevice_seed_list) { std::vector<cryptauth::BeaconSeed> cryptauth_beacon_seeds; @@ -67,6 +83,18 @@ return multidevice_beacon_seeds; } +std::vector<BeaconSeed> FromCryptAuthV2SeedRepeatedPtrField( + const google::protobuf::RepeatedPtrField<cryptauthv2::BeaconSeed>& + cryptauth_seed_list) { + std::vector<BeaconSeed> multidevice_beacon_seeds; + std::transform(cryptauth_seed_list.begin(), cryptauth_seed_list.end(), + std::back_inserter(multidevice_beacon_seeds), + [](auto cryptauth_beacon_seed) { + return FromCryptAuthV2Seed(cryptauth_beacon_seed); + }); + return multidevice_beacon_seeds; +} + std::ostream& operator<<(std::ostream& stream, const BeaconSeed& beacon_seed) { std::string base_64_data; base::Base64Encode(beacon_seed.data(), &base_64_data);
diff --git a/chromeos/components/multidevice/beacon_seed.h b/chromeos/components/multidevice/beacon_seed.h index 1074c95..59992dff 100644 --- a/chromeos/components/multidevice/beacon_seed.h +++ b/chromeos/components/multidevice/beacon_seed.h
@@ -5,12 +5,14 @@ #ifndef CHROMEOS_COMPONENTS_MULTIDEVICE_BEACON_SEED_H_ #define CHROMEOS_COMPONENTS_MULTIDEVICE_BEACON_SEED_H_ +#include <google/protobuf/repeated_field.h> #include <ostream> #include <string> #include <vector> #include "base/time/time.h" #include "chromeos/services/device_sync/proto/cryptauth_api.pb.h" +#include "chromeos/services/device_sync/proto/cryptauth_better_together_device_metadata.pb.h" namespace chromeos { @@ -44,11 +46,19 @@ BeaconSeed FromCryptAuthSeed(cryptauth::BeaconSeed cryptauth_seed); cryptauth::BeaconSeed ToCryptAuthSeed(BeaconSeed multidevice_seed); + +BeaconSeed FromCryptAuthV2Seed(cryptauthv2::BeaconSeed cryptauth_seed); +cryptauthv2::BeaconSeed ToCryptAuthV2Seed(BeaconSeed multidevice_seed); + std::vector<cryptauth::BeaconSeed> ToCryptAuthSeedList( const std::vector<BeaconSeed>& cryptauth_seed_list); std::vector<BeaconSeed> FromCryptAuthSeedList( const std::vector<cryptauth::BeaconSeed>& cryptauth_seed_list); +std::vector<BeaconSeed> FromCryptAuthV2SeedRepeatedPtrField( + const google::protobuf::RepeatedPtrField<cryptauthv2::BeaconSeed>& + cryptauth_seed_list); + std::ostream& operator<<(std::ostream& stream, const BeaconSeed& beacon_seed); } // namespace multidevice
diff --git a/chromeos/services/device_sync/BUILD.gn b/chromeos/services/device_sync/BUILD.gn index 6127ccf..6dc05293 100644 --- a/chromeos/services/device_sync/BUILD.gn +++ b/chromeos/services/device_sync/BUILD.gn
@@ -127,6 +127,8 @@ "remote_device_provider.h", "remote_device_provider_impl.cc", "remote_device_provider_impl.h", + "remote_device_v2_loader.cc", + "remote_device_v2_loader.h", "software_feature_manager.h", "software_feature_manager_impl.cc", "software_feature_manager_impl.h", @@ -272,6 +274,7 @@ "device_sync_service_unittest.cc", "remote_device_loader_unittest.cc", "remote_device_provider_impl_unittest.cc", + "remote_device_v2_loader_unittest.cc", "software_feature_manager_impl_unittest.cc", "sync_scheduler_impl_unittest.cc", ]
diff --git a/chromeos/services/device_sync/remote_device_v2_loader.cc b/chromeos/services/device_sync/remote_device_v2_loader.cc new file mode 100644 index 0000000..f2926ff3 --- /dev/null +++ b/chromeos/services/device_sync/remote_device_v2_loader.cc
@@ -0,0 +1,125 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/services/device_sync/remote_device_v2_loader.h" + +#include <utility> + +#include "base/bind.h" +#include "base/memory/ptr_util.h" +#include "base/no_destructor.h" +#include "chromeos/components/multidevice/beacon_seed.h" +#include "chromeos/components/multidevice/logging/logging.h" +#include "chromeos/components/multidevice/secure_message_delegate_impl.h" +#include "chromeos/services/device_sync/async_execution_time_metrics_logger.h" +#include "chromeos/services/device_sync/cryptauth_task_metrics_logger.h" + +namespace chromeos { + +namespace device_sync { + +// static +RemoteDeviceV2Loader::Factory* RemoteDeviceV2Loader::Factory::test_factory_ = + nullptr; + +// static +RemoteDeviceV2Loader::Factory* RemoteDeviceV2Loader::Factory::Get() { + if (test_factory_) + return test_factory_; + + static base::NoDestructor<RemoteDeviceV2Loader::Factory> factory; + return factory.get(); +} + +// static +void RemoteDeviceV2Loader::Factory::SetFactoryForTesting( + Factory* test_factory) { + test_factory_ = test_factory; +} + +RemoteDeviceV2Loader::Factory::~Factory() = default; + +std::unique_ptr<RemoteDeviceV2Loader> +RemoteDeviceV2Loader::Factory::BuildInstance() { + return base::WrapUnique(new RemoteDeviceV2Loader()); +} + +RemoteDeviceV2Loader::RemoteDeviceV2Loader() + : secure_message_delegate_( + multidevice::SecureMessageDelegateImpl::Factory::NewInstance()) {} + +RemoteDeviceV2Loader::~RemoteDeviceV2Loader() = default; + +void RemoteDeviceV2Loader::Load( + const CryptAuthDeviceRegistry::InstanceIdToDeviceMap& id_to_device_map, + const std::string& user_id, + const std::string& user_private_key, + LoadCallback callback) { + DCHECK(!user_id.empty()); + DCHECK(!user_private_key.empty()); + + DCHECK(callback_.is_null()); + callback_ = std::move(callback); + + DCHECK(id_to_device_map_.empty()); + id_to_device_map_ = id_to_device_map; + if (id_to_device_map_.empty()) { + std::move(callback_).Run(remote_devices_); + return; + } + + DCHECK(remaining_ids_to_process_.empty()); + for (const auto& id_device_pair : id_to_device_map_) + remaining_ids_to_process_.insert(id_device_pair.first); + + for (const auto& id_device_pair : id_to_device_map_) { + if (!id_device_pair.second.better_together_device_metadata || + id_device_pair.second.better_together_device_metadata->public_key() + .empty()) { + AddRemoteDevice(id_device_pair.second, user_id, std::string() /* psk */); + continue; + } + + // Performs ECDH key agreement to generate a shared secret between the local + // device and the remote device of |id_device_pair|. + secure_message_delegate_->DeriveKey( + user_private_key, + id_device_pair.second.better_together_device_metadata->public_key(), + base::Bind(&RemoteDeviceV2Loader::OnPskDerived, base::Unretained(this), + id_device_pair.second, user_id)); + } +} + +void RemoteDeviceV2Loader::OnPskDerived(const CryptAuthDevice& device, + const std::string& user_id, + const std::string& psk) { + if (psk.empty()) + PA_LOG(WARNING) << "Derived persistent symmetric key is empty."; + + AddRemoteDevice(device, user_id, psk); +} + +void RemoteDeviceV2Loader::AddRemoteDevice(const CryptAuthDevice& device, + const std::string& user_id, + const std::string& psk) { + const base::Optional<cryptauthv2::BetterTogetherDeviceMetadata>& + beto_metadata = device.better_together_device_metadata; + remote_devices_.emplace_back( + user_id, device.instance_id(), device.device_name, + beto_metadata ? beto_metadata->no_pii_device_name() : std::string(), + beto_metadata ? beto_metadata->public_key() : std::string(), psk, + device.last_update_time.ToJavaTime(), device.feature_states, + beto_metadata ? multidevice::FromCryptAuthV2SeedRepeatedPtrField( + beto_metadata->beacon_seeds()) + : std::vector<multidevice::BeaconSeed>()); + + remaining_ids_to_process_.erase(device.instance_id()); + + if (remaining_ids_to_process_.empty()) + std::move(callback_).Run(remote_devices_); +} + +} // namespace device_sync + +} // namespace chromeos
diff --git a/chromeos/services/device_sync/remote_device_v2_loader.h b/chromeos/services/device_sync/remote_device_v2_loader.h new file mode 100644 index 0000000..82566601 --- /dev/null +++ b/chromeos/services/device_sync/remote_device_v2_loader.h
@@ -0,0 +1,94 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_SERVICES_DEVICE_SYNC_REMOTE_DEVICE_V2_LOADER_H_ +#define CHROMEOS_SERVICES_DEVICE_SYNC_REMOTE_DEVICE_V2_LOADER_H_ + +#include <memory> +#include <string> + +#include "base/callback.h" +#include "base/containers/flat_set.h" +#include "chromeos/components/multidevice/remote_device.h" +#include "chromeos/services/device_sync/cryptauth_device.h" +#include "chromeos/services/device_sync/cryptauth_device_registry.h" + +namespace chromeos { + +namespace multidevice { +class SecureMessageDelegate; +} // namespace multidevice + +namespace device_sync { + +// Converts the given CryptAuthDevices into RemoteDevices. Some RemoteDevice +// fields are left empty if the CryptAuthDevice does not have +// CryptAuthBetterTogetherDeviceMetadata, for instance, if the metadata cannot +// be decrypted. If the public key is available for a device, a persistent +// symmetric key (PSK) is derived and added to the RemoteDevice; otherwise, the +// PSK is set to an empty string. +// +// A RemoteDeviceV2Loader object is designed to be used for only one Load() +// call. For a new attempt, a new object should be created. Note: The async +// calls to SecureMessage are guarded by the default DBus timeout (currently +// 25s). +class RemoteDeviceV2Loader { + public: + using LoadCallback = + base::OnceCallback<void(const multidevice::RemoteDeviceList&)>; + + class Factory { + public: + static Factory* Get(); + static void SetFactoryForTesting(Factory* test_factory); + virtual ~Factory(); + virtual std::unique_ptr<RemoteDeviceV2Loader> BuildInstance(); + + private: + static Factory* test_factory_; + }; + + virtual ~RemoteDeviceV2Loader(); + + // Converts the input CryptAuthDevices to RemoteDevices. All devices are + // converted but some remote device information might be missing, for + // instance, if the CryptAuthBetterTogetherMetadata is not available. + // |id_to_device_map|: A map from Instance ID to CryptAuthDevice which will be + // converted to a list of RemoteDevices. + // |user_id|: The account ID of the user who owns the devices. + // |user_private_key|: The private key of the user's local device. Used to + // derive the persistent symmetric key (PSK). + // |callback|: Invoked when the conversion is complete. + virtual void Load( + const CryptAuthDeviceRegistry::InstanceIdToDeviceMap& id_to_device_map, + const std::string& user_id, + const std::string& user_private_key, + LoadCallback callback); + + private: + RemoteDeviceV2Loader(); + + // Disallow copy and assign. + RemoteDeviceV2Loader(const RemoteDeviceV2Loader&) = delete; + RemoteDeviceV2Loader& operator=(const RemoteDeviceV2Loader&) = delete; + + void OnPskDerived(const CryptAuthDevice& device, + const std::string& user_id, + const std::string& psk); + void AddRemoteDevice(const CryptAuthDevice& device, + const std::string& user_id, + const std::string& psk); + + LoadCallback callback_; + CryptAuthDeviceRegistry::InstanceIdToDeviceMap id_to_device_map_; + base::flat_set<std::string> remaining_ids_to_process_; + multidevice::RemoteDeviceList remote_devices_; + std::unique_ptr<multidevice::SecureMessageDelegate> secure_message_delegate_; +}; + +} // namespace device_sync + +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_DEVICE_SYNC_REMOTE_DEVICE_V2_LOADER_H_
diff --git a/chromeos/services/device_sync/remote_device_v2_loader_unittest.cc b/chromeos/services/device_sync/remote_device_v2_loader_unittest.cc new file mode 100644 index 0000000..823d3b8b --- /dev/null +++ b/chromeos/services/device_sync/remote_device_v2_loader_unittest.cc
@@ -0,0 +1,217 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <algorithm> +#include <memory> +#include <string> +#include <utility> + +#include "base/bind.h" +#include "chromeos/components/multidevice/fake_secure_message_delegate.h" +#include "chromeos/components/multidevice/remote_device.h" +#include "chromeos/services/device_sync/cryptauth_device.h" +#include "chromeos/services/device_sync/proto/cryptauth_devicesync.pb.h" +#include "chromeos/services/device_sync/proto/cryptauth_v2_test_util.h" +#include "chromeos/services/device_sync/remote_device_v2_loader.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { + +namespace device_sync { + +namespace { + +// Prefixes for RemoteDevice fields. +const char kDeviceNamePrefix[] = "device_name"; +const char kNoPiiDeviceNamePrefix[] = "no_pii_here"; +const char kPublicKeyPrefix[] = "public_key"; +const char kInstanceIdPrefix[] = "instance_id"; +const char kPskPlaceholder[] = "psk_placeholder"; + +// The id of the user who the remote devices belong to. +const char kUserId[] = "example@gmail.com"; + +// The public key of the user's local device. +const char kUserPublicKey[] = "user_public_key"; + +// BeaconSeed values. +const int64_t kBeaconSeedStartTimeMs = 1000; +const int64_t kBeaconSeedEndTimeMs = 2000; +const char kBeaconSeedData[] = "beacon_seed_data"; + +// The "DeviceSync:BetterTogether" public key prefix. +const char kDeviceSyncBetterTogetherPublicKeyPrefix[] = "ds_beto_pub_key"; + +// Last update time in milliseconds +const int64_t kLastUpdateTimeMs = 3000; + +// Creates a CryptAuthDevice with |suffix| appended to each predetermined string +// field. If |has_beto_metadata| is false, +// CryptAuthDevice.better_together_device_metadata is not set, and if +// |has_public_key| is false, +// CryptAuthDevice.better_together_device_metadata.public_key is not set. +CryptAuthDevice CreateCryptAuthDevice(const std::string& suffix, + bool has_beto_metadata, + bool has_public_key) { + base::Optional<cryptauthv2::BetterTogetherDeviceMetadata> beto_metadata; + + if (has_beto_metadata) { + beto_metadata = cryptauthv2::BetterTogetherDeviceMetadata(); + beto_metadata->set_no_pii_device_name(kNoPiiDeviceNamePrefix + suffix); + + cryptauthv2::BeaconSeed* beacon_seed = beto_metadata->add_beacon_seeds(); + beacon_seed->set_start_time_millis(kBeaconSeedStartTimeMs); + beacon_seed->set_end_time_millis(kBeaconSeedEndTimeMs); + beacon_seed->set_data(kBeaconSeedData + suffix); + + if (has_public_key) + beto_metadata->set_public_key(kPublicKeyPrefix + suffix); + } + + return CryptAuthDevice(kInstanceIdPrefix + suffix, kDeviceNamePrefix + suffix, + kDeviceSyncBetterTogetherPublicKeyPrefix + suffix, + base::Time::FromJavaTime(kLastUpdateTimeMs), + beto_metadata, + {{multidevice::SoftwareFeature::kBetterTogetherHost, + multidevice::SoftwareFeatureState::kSupported}}); +} + +// Creates a RemoteDevice with |suffix| appended to each predetermined string +// field. If |has_beto_metadata| is false, RemoteDevice.pii_free_name is not +// set. If |has_public_key| is false, RemoteDevice.public_key and +// RemoteDevice.persistent_symmetric_key is not set. If |has_beacon_seeds| is +// false, RemoteDevice.beacon_seeds is not set. +multidevice::RemoteDevice CreateRemoteDevice(const std::string& suffix, + bool has_pii_free_name, + bool has_public_key, + bool has_beacon_seeds) { + std::string pii_free_name = + has_pii_free_name ? kNoPiiDeviceNamePrefix + suffix : std::string(); + std::string public_key = + has_public_key ? kPublicKeyPrefix + suffix : std::string(); + std::string psk = has_public_key ? kPskPlaceholder : std::string(); + + std::vector<multidevice::BeaconSeed> beacon_seeds; + if (has_beacon_seeds) { + beacon_seeds.emplace_back(kBeaconSeedData + suffix, + base::Time::FromJavaTime(kBeaconSeedStartTimeMs), + base::Time::FromJavaTime(kBeaconSeedEndTimeMs)); + } + + return multidevice::RemoteDevice( + kUserId, kInstanceIdPrefix + suffix, kDeviceNamePrefix + suffix, + pii_free_name, public_key, psk, kLastUpdateTimeMs, + {{multidevice::SoftwareFeature::kBetterTogetherHost, + multidevice::SoftwareFeatureState::kSupported}}, + beacon_seeds); +} + +} // namespace + +class DeviceSyncRemoteDeviceV2LoaderTest : public testing::Test { + public: + DeviceSyncRemoteDeviceV2LoaderTest() + : fake_secure_message_delegate_factory_( + std::make_unique<multidevice::FakeSecureMessageDelegateFactory>()), + user_private_key_(fake_secure_message_delegate_factory_->instance() + ->GetPrivateKeyForPublicKey(kUserPublicKey)) {} + + ~DeviceSyncRemoteDeviceV2LoaderTest() override = default; + + // testing::Test: + void SetUp() override { + multidevice::SecureMessageDelegateImpl::Factory::SetInstanceForTesting( + fake_secure_message_delegate_factory_.get()); + } + + // testing::Test: + void TearDown() override { + multidevice::SecureMessageDelegateImpl::Factory::SetInstanceForTesting( + nullptr); + } + + void CallLoad(std::vector<CryptAuthDevice> device_list) { + CryptAuthDeviceRegistry::InstanceIdToDeviceMap id_to_device_map; + for (const auto& device : device_list) + id_to_device_map.insert_or_assign(device.instance_id(), device); + + loader_ = RemoteDeviceV2Loader::Factory::Get()->BuildInstance(); + loader_->Load( + id_to_device_map, kUserId, user_private_key_, + base::BindOnce(&DeviceSyncRemoteDeviceV2LoaderTest::OnLoadFinished, + base::Unretained(this))); + } + + void OnLoadFinished(const multidevice::RemoteDeviceList& remote_devices) { + remote_devices_ = remote_devices; + } + + void VerifyLoad( + const multidevice::RemoteDeviceList& expected_remote_devices) { + ASSERT_TRUE(remote_devices_); + EXPECT_EQ(expected_remote_devices.size(), remote_devices_->size()); + + for (const auto& expected_device : expected_remote_devices) { + std::string expected_instance_id = expected_device.instance_id; + auto it = std::find_if( + remote_devices_->begin(), remote_devices_->end(), + [&expected_instance_id](const multidevice::RemoteDevice& device) { + return device.instance_id == expected_instance_id; + }); + + ASSERT_FALSE(it == remote_devices_->end()); + multidevice::RemoteDevice remote_device = *it; + + // Because of the way FakeSecureMessageDelegate is implemented, we do not + // know the form of the derived persistent symmetric key, only if it is + // empty or not. After checking if both the actual and expected keys are + // empty or not empty, replace the placeholder PSK with the PSK of the + // expected RemoteDevice. This allows us to directly compare two + // RemoteDevice objects. + EXPECT_EQ(expected_device.persistent_symmetric_key.empty(), + remote_device.persistent_symmetric_key.empty()); + remote_device.persistent_symmetric_key = + expected_device.persistent_symmetric_key; + + EXPECT_EQ(expected_device, remote_device); + } + } + + protected: + // Null until Load() finishes. + base::Optional<multidevice::RemoteDeviceList> remote_devices_; + + std::unique_ptr<multidevice::FakeSecureMessageDelegateFactory> + fake_secure_message_delegate_factory_; + std::string user_private_key_; + std::unique_ptr<RemoteDeviceV2Loader> loader_; +}; + +TEST_F(DeviceSyncRemoteDeviceV2LoaderTest, NoDevices) { + CallLoad({} /* device_list */); + VerifyLoad({} /* expected_remote_devices */); +} + +TEST_F(DeviceSyncRemoteDeviceV2LoaderTest, Success) { + CallLoad({CreateCryptAuthDevice("device1", true /* has_beto_metadata */, + true /* has_public_key */), + CreateCryptAuthDevice("device2", true /* has_beto_metadata */, + false /* has_public_key */), + CreateCryptAuthDevice("device3", false /* has_beto_metadata */, + false /* has_public_key */)}); + + VerifyLoad({CreateRemoteDevice("device1", true /* has_pii_free_name */, + true /* has_public_key */, + true /* has_beacon_seeds */), + CreateRemoteDevice("device2", true /* has_pii_free_name */, + false /* has_public_key */, + true /* has_beacon_seeds */), + CreateRemoteDevice("device3", false /* has_pii_free_name */, + false /* has_public_key */, + false /* has_beacon_seeds */)}); +} + +} // namespace device_sync + +} // namespace chromeos
diff --git a/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc b/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc index 105805d..f8128be4 100644 --- a/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc +++ b/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc
@@ -367,6 +367,9 @@ customer_data->push_back( CustomerDataFromSpecifics(autofill_specifics.customer_data())); break; + case sync_pb::AutofillWalletSpecifics::CREDIT_CARD_CLOUD_TOKEN_DATA: + // TODO(crbug.com/1020740): Implement this type. + break; case sync_pb::AutofillWalletSpecifics::UNKNOWN: // Just ignore new entry types that the client doesn't know about. break;
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc index c9bc282..8c02ed1 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
@@ -46,6 +46,8 @@ return specifics.address().id(); case AutofillWalletSpecifics::CUSTOMER_DATA: return specifics.customer_data().id(); + case AutofillWalletSpecifics::CREDIT_CARD_CLOUD_TOKEN_DATA: + return specifics.cloud_token_data().masked_card_id(); case AutofillWalletSpecifics::UNKNOWN: NOTREACHED(); return std::string();
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc index 12e7e536..861880b 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
@@ -144,6 +144,10 @@ AutofillWalletSpecifics_WalletInfoType_CUSTOMER_DATA: return "CustomerData"; case sync_pb::AutofillWalletSpecifics_WalletInfoType:: + AutofillWalletSpecifics_WalletInfoType_CREDIT_CARD_CLOUD_TOKEN_DATA: + // TODO(crbug.com/1020740): Implement for this type. + return "CloudTokenData"; + case sync_pb::AutofillWalletSpecifics_WalletInfoType:: AutofillWalletSpecifics_WalletInfoType_UNKNOWN: return "Unknown"; }
diff --git a/components/components_strings.grd b/components/components_strings.grd index 68e303e..5508c516 100644 --- a/components/components_strings.grd +++ b/components/components_strings.grd
@@ -368,6 +368,9 @@ <message name="IDS_ACCNAME_PARTICLE_DISC" desc="The accessible name for the Account Consistency Disc on New Tab Page"> Google Account </message> + <message name="IDS_ACCNAME_TAB_LIST" desc="The accessible name for the tab strip."> + Tab list + </message> <message name="IDS_UTILITY_PROCESS_JSON_PARSER_NAME" desc="The name of the utility process used for parsing JSON files."> JSON Parser
diff --git a/components/crash/core/browser/resources/crashes.js b/components/crash/core/browser/resources/crashes.js index 4c2a9fd0..65e54743 100644 --- a/components/crash/core/browser/resources/crashes.js +++ b/components/crash/core/browser/resources/crashes.js
@@ -20,10 +20,11 @@ * @param {array} crashes The list of crashes. * @param {string} version The browser version. * @param {string} os The OS name and version. + * @param {boolean} isGoogleAccount whether primary account is internal. */ function updateCrashList( enabled, dynamicBackend, manualUploads, - crashes, version, os) { + crashes, version, os, isGoogleAccount) { $('countBanner').textContent = loadTimeData.getStringF('crashCountFormat', crashes.length.toLocaleString()); @@ -55,9 +56,23 @@ var title = document.createElement('h3'); var uploaded = crash.state == 'uploaded'; if (uploaded) { - title.textContent = loadTimeData.getStringF('crashHeaderFormat', - crash.id, - crash.local_id); + const crashHeaderText = loadTimeData.getString('crashHeaderFormat'); + const pieces = loadTimeData + .getSubstitutedStringPieces( + crashHeaderText, crash.id, crash.local_id) + .map(piece => { + // Create crash/ link for Googler Accounts. + if (isGoogleAccount && piece.value === crash.id) { + const crashLink = document.createElement('a'); + crashLink.href = `http://crash/${crash.id}`; + crashLink.target = '_blank'; + crashLink.textContent = crash.id; + return crashLink; + } else { + return piece.value; + } + }); + title.append.apply(title, pieces); } else { title.textContent = loadTimeData.getStringF('crashHeaderFormatLocalOnly', crash.local_id);
diff --git a/components/dom_distiller/core/css/distilledpage_desktop.css b/components/dom_distiller/core/css/distilledpage_desktop.css index 0a9eb03..e2aaa19 100644 --- a/components/dom_distiller/core/css/distilledpage_desktop.css +++ b/components/dom_distiller/core/css/distilledpage_desktop.css
@@ -98,6 +98,10 @@ font-size: 13px; font-family: 'Roboto Regular', 'Roboto', sans-serif; color: #3C4043; + + /* The z-index is set so that any "positioned" elements in the article text + * (e.g. footnotes) are rendered below the dialog. */ + z-index: 1; } #settingsDialog h2 { @@ -232,7 +236,8 @@ margin-top: -4px; /* Render the thumb on top of the tickmarks. We can't just rearrange the HTML - * because the tickmarks need to render above the slider's track. */ + * because the tickmarks need to render above the slider's track but below the + * thumb. */ position: relative; z-index: 1; }
diff --git a/components/download/internal/common/download_db_cache.cc b/components/download/internal/common/download_db_cache.cc index d1fdf2d..9ff1755 100644 --- a/components/download/internal/common/download_db_cache.cc +++ b/components/download/internal/common/download_db_cache.cc
@@ -43,10 +43,19 @@ if (current.download_info) current_info = current.download_info->in_progress_info; - base::FilePath current_path = - current_info ? current_info->current_path : base::FilePath(); - - bool paused = current_info ? current_info->paused : false; + base::FilePath current_path; + bool paused = false; + GURL url; + DownloadItem::DownloadState state = DownloadItem::DownloadState::IN_PROGRESS; + DownloadInterruptReason interrupt_reason = DOWNLOAD_INTERRUPT_REASON_NONE; + if (current_info) { + base::FilePath current_path = current_info->current_path; + paused = current_info->paused; + if (!current_info->url_chain.empty()) + url = current_info->url_chain.back(); + state = current_info->state; + interrupt_reason = current_info->interrupt_reason; + } // When download path is determined, Chrome should commit the history // immediately. Otherwise the file will be left permanently on the external @@ -57,6 +66,9 @@ if (previous.value() == current) return ShouldUpdateDownloadDBResult::NO_UPDATE; + if (IsDownloadDone(url, state, interrupt_reason)) + return ShouldUpdateDownloadDBResult::UPDATE_IMMEDIATELY; + return ShouldUpdateDownloadDBResult::UPDATE; }
diff --git a/components/download/internal/common/in_progress_download_manager.cc b/components/download/internal/common/in_progress_download_manager.cc index d9ac5f6..235140d5 100644 --- a/components/download/internal/common/in_progress_download_manager.cc +++ b/components/download/internal/common/in_progress_download_manager.cc
@@ -402,7 +402,12 @@ : DownloadPathReservationTracker::OVERWRITE, base::Bind(&OnPathReserved, callback, download->GetDangerType(), intermediate_path_cb_, download->GetForcedFilePath())); -#endif +#else + callback.Run(download->GetTargetFilePath(), + DownloadItem::TARGET_DISPOSITION_OVERWRITE, + download->GetDangerType(), download->GetFullPath(), + DOWNLOAD_INTERRUPT_REASON_NONE); +#endif // defined(OS_ANDROID) } void InProgressDownloadManager::ResumeInterruptedDownload(
diff --git a/components/offline_items_collection/core/throttled_offline_content_provider_unittest.cc b/components/offline_items_collection/core/throttled_offline_content_provider_unittest.cc index 9d52894..72ce529 100644 --- a/components/offline_items_collection/core/throttled_offline_content_provider_unittest.cc +++ b/components/offline_items_collection/core/throttled_offline_content_provider_unittest.cc
@@ -13,14 +13,11 @@ #include "components/offline_items_collection/core/test_support/scoped_mock_offline_content_provider.h" #include "components/offline_items_collection/core/throttled_offline_content_provider.h" #include "testing/gmock/include/gmock/gmock.h" -#include "testing/gmock_mutant.h" #include "testing/gtest/include/gtest/gtest.h" using testing::_; -using testing::CallbackToFunctor; using testing::Eq; using testing::InvokeWithoutArgs; -using testing::Return; namespace offline_items_collection { namespace { @@ -335,25 +332,27 @@ OfflineItem item5(ContentId("5", "E")); OfflineItem item6(ContentId("6", "F")); - auto updater = base::Bind(&MockOfflineContentProvider::NotifyOnItemUpdated, - base::Unretained(&wrapped_provider_)); - // Set up reentrancy calls back into the provider. EXPECT_CALL(wrapped_provider_, OpenItem(_, _)) - .WillRepeatedly(InvokeWithoutArgs( - CallbackToFunctor(base::Bind(updater, item2, base::nullopt)))); + .WillRepeatedly(InvokeWithoutArgs([=]() { + wrapped_provider_.NotifyOnItemUpdated(item2, base::nullopt); + })); EXPECT_CALL(wrapped_provider_, RemoveItem(_)) - .WillRepeatedly(InvokeWithoutArgs( - CallbackToFunctor(base::Bind(updater, item3, base::nullopt)))); + .WillRepeatedly(InvokeWithoutArgs([=]() { + wrapped_provider_.NotifyOnItemUpdated(item3, base::nullopt); + })); EXPECT_CALL(wrapped_provider_, CancelDownload(_)) - .WillRepeatedly(InvokeWithoutArgs( - CallbackToFunctor(base::Bind(updater, item4, base::nullopt)))); + .WillRepeatedly(InvokeWithoutArgs([=]() { + wrapped_provider_.NotifyOnItemUpdated(item4, base::nullopt); + })); EXPECT_CALL(wrapped_provider_, PauseDownload(_)) - .WillRepeatedly(InvokeWithoutArgs( - CallbackToFunctor(base::Bind(updater, item5, base::nullopt)))); + .WillRepeatedly(InvokeWithoutArgs([=]() { + wrapped_provider_.NotifyOnItemUpdated(item5, base::nullopt); + })); EXPECT_CALL(wrapped_provider_, ResumeDownload(_, _)) - .WillRepeatedly(InvokeWithoutArgs( - CallbackToFunctor(base::Bind(updater, item6, base::nullopt)))); + .WillRepeatedly(InvokeWithoutArgs([=]() { + wrapped_provider_.NotifyOnItemUpdated(item6, base::nullopt); + })); { EXPECT_CALL(observer, OnItemUpdated(item1, Eq(base::nullopt))).Times(1);
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc index 68446166..3b1f9d53 100644 --- a/components/omnibox/browser/autocomplete_controller.cc +++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -566,11 +566,13 @@ } } + const auto last_result_for_logging = result_.GetMatchDedupComparators(); + if (regenerate_result) result_.Reset(); - AutocompleteResult last_result; - last_result.Swap(&result_); + AutocompleteResult old_matches_to_reuse; + old_matches_to_reuse.Swap(&result_); for (Providers::const_iterator i(providers_.begin()); i != providers_.end(); ++i) @@ -584,7 +586,7 @@ // Sort the matches and trim to a small number of "best" matches. const AutocompleteMatch* preserve_default_match = nullptr; - if (!in_start_ && !regenerate_result && last_default_match && + if (!in_start_ && last_default_match && base::FeatureList::IsEnabled( omnibox::kOmniboxPreserveDefaultMatchAgainstAsyncUpdate)) { preserve_default_match = &last_default_match.value(); @@ -600,12 +602,15 @@ if (!done_) { // This conditional needs to match the conditional in Start that invokes // StartExpireTimer. - result_.CopyOldMatches(input_, &last_result, template_url_service_); + result_.TransferOldMatches(input_, &old_matches_to_reuse, + template_url_service_); } // Log metrics for how many matches are asynchronously changed. - if (!in_start_) - AutocompleteResult::LogAsynchronousUpdateMetrics(last_result, result_); + if (!in_start_) { + AutocompleteResult::LogAsynchronousUpdateMetrics(last_result_for_logging, + result_); + } UpdateKeywordDescriptions(&result_); UpdateAssociatedKeywords(&result_);
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc index 2a27d698..77717b9 100644 --- a/components/omnibox/browser/autocomplete_result.cc +++ b/components/omnibox/browser/autocomplete_result.cc
@@ -107,7 +107,7 @@ AutocompleteResult::~AutocompleteResult() {} -void AutocompleteResult::CopyOldMatches( +void AutocompleteResult::TransferOldMatches( const AutocompleteInput& input, AutocompleteResult* old_matches, TemplateURLService* template_url_service) { @@ -755,17 +755,24 @@ return res; } +std::vector<AutocompleteResult::MatchDedupComparator> +AutocompleteResult::GetMatchDedupComparators() const { + std::vector<MatchDedupComparator> comparators; + for (const auto& match : *this) + comparators.push_back(AutocompleteResult::GetMatchComparisonFields(match)); + return comparators; +} + // static void AutocompleteResult::LogAsynchronousUpdateMetrics( - const AutocompleteResult& old_result, + const std::vector<MatchDedupComparator>& old_result, const AutocompleteResult& new_result) { constexpr char kAsyncMatchChangeHistogramName[] = - "Omnibox.MatchStability.AsyncMatchChange"; + "Omnibox.MatchStability.AsyncMatchChange2"; size_t min_size = std::min(old_result.size(), new_result.size()); for (size_t i = 0; i < min_size; ++i) { - if (GetMatchComparisonFields(old_result.match_at(i)) != - GetMatchComparisonFields(new_result.match_at(i))) { + if (old_result[i] != GetMatchComparisonFields(new_result.match_at(i))) { base::UmaHistogramExactLinear(kAsyncMatchChangeHistogramName, i, kMaxAutocompletePositionValue); }
diff --git a/components/omnibox/browser/autocomplete_result.h b/components/omnibox/browser/autocomplete_result.h index d36b860e..9b67f558 100644 --- a/components/omnibox/browser/autocomplete_result.h +++ b/components/omnibox/browser/autocomplete_result.h
@@ -28,6 +28,7 @@ public: typedef ACMatches::const_iterator const_iterator; typedef ACMatches::iterator iterator; + using MatchDedupComparator = std::pair<GURL, bool>; // Max number of matches we'll show from the various providers. static size_t GetMaxMatches(bool is_zero_suggest = false); @@ -35,12 +36,11 @@ AutocompleteResult(); ~AutocompleteResult(); - // Copies matches from |old_matches| to provide a consistant result set. See - // comments in code for specifics. Will clear |old_matches| if this result is - // empty(). - void CopyOldMatches(const AutocompleteInput& input, - AutocompleteResult* old_matches, - TemplateURLService* template_url_service); + // Moves matches from |old_matches| to provide a consistent result set. + // |old_matches| is mutated during this, and should not be used afterwards. + void TransferOldMatches(const AutocompleteInput& input, + AutocompleteResult* old_matches, + TemplateURLService* template_url_service); // Adds a new set of matches to the result set. Does not re-sort. Calls // PossiblySwapContentsAndDescriptionForURLSuggestion(input)" on all added @@ -149,9 +149,13 @@ // See base/trace_event/memory_usage_estimator.h for more info. size_t EstimateMemoryUsage() const; + // Get a list of comparators used for deduping for the matches in this result. + std::vector<MatchDedupComparator> GetMatchDedupComparators() const; + // Logs metrics for when |new_result| replaces |old_result| asynchronously. + // |old_result| a list of the comparators for the old matches. static void LogAsynchronousUpdateMetrics( - const AutocompleteResult& old_result, + const std::vector<MatchDedupComparator>& old_result, const AutocompleteResult& new_result); private: @@ -209,7 +213,7 @@ // collapse similar URLs if necessary, and whether the match is a calculator // suggestion, because we don't want to dedupe them against URLs that simply // happen to go to the same destination. - static std::pair<GURL, bool> GetMatchComparisonFields( + static MatchDedupComparator GetMatchComparisonFields( const AutocompleteMatch& match); // This method reduces the number of navigation suggestions to that of
diff --git a/components/omnibox/browser/autocomplete_result_unittest.cc b/components/omnibox/browser/autocomplete_result_unittest.cc index b01f9d7..a1ee48b5 100644 --- a/components/omnibox/browser/autocomplete_result_unittest.cc +++ b/components/omnibox/browser/autocomplete_result_unittest.cc
@@ -149,10 +149,13 @@ size_t expected_count); // Creates an AutocompleteResult from |last| and |current|. The two are - // merged by |CopyOldMatches| and compared by |AssertResultMatches|. - void RunCopyOldMatchesTest(const TestData* last, size_t last_size, - const TestData* current, size_t current_size, - const TestData* expected, size_t expected_size); + // merged by |TransferOldMatches| and compared by |AssertResultMatches|. + void RunTransferOldMatchesTest(const TestData* last, + size_t last_size, + const TestData* current, + size_t current_size, + const TestData* expected, + size_t expected_size); // Returns a (mock) AutocompleteProvider of given |provider_id|. MockAutocompleteProvider* GetProvider(int provider_id) { @@ -214,10 +217,12 @@ } } -void AutocompleteResultTest::RunCopyOldMatchesTest( - const TestData* last, size_t last_size, - const TestData* current, size_t current_size, - const TestData* expected, size_t expected_size) { +void AutocompleteResultTest::RunTransferOldMatchesTest(const TestData* last, + size_t last_size, + const TestData* current, + size_t current_size, + const TestData* expected, + size_t expected_size) { AutocompleteInput input(base::ASCIIToUTF16("a"), metrics::OmniboxEventProto::OTHER, TestSchemeClassifier()); @@ -233,8 +238,8 @@ AutocompleteResult current_result; current_result.AppendMatches(input, current_matches); current_result.SortAndCull(input, template_url_service_.get()); - current_result.CopyOldMatches(input, &last_result, - template_url_service_.get()); + current_result.TransferOldMatches(input, &last_result, + template_url_service_.get()); AssertResultMatches(current_result, expected, expected_size); } @@ -273,7 +278,7 @@ // Tests that if the new results have a lower max relevance score than last, // any copied results have their relevance shifted down. -TEST_F(AutocompleteResultTest, CopyOldMatches) { +TEST_F(AutocompleteResultTest, TransferOldMatches) { TestData last[] = { { 0, 1, 1000, true }, { 1, 1, 500, true }, @@ -286,15 +291,15 @@ { 1, 1, 399, true }, }; - ASSERT_NO_FATAL_FAILURE(RunCopyOldMatchesTest(last, base::size(last), current, - base::size(current), result, - base::size(result))); + ASSERT_NO_FATAL_FAILURE(RunTransferOldMatchesTest( + last, base::size(last), current, base::size(current), result, + base::size(result))); } // Tests that if the new results have a lower max relevance score than last, // any copied results have their relevance shifted down when the allowed to // be default constraint comes into play. -TEST_F(AutocompleteResultTest, CopyOldMatchesAllowedToBeDefault) { +TEST_F(AutocompleteResultTest, TransferOldMatchesAllowedToBeDefault) { TestData last[] = { { 0, 1, 1300, true }, { 1, 1, 1200, true }, @@ -312,13 +317,13 @@ { 2, 1, 899, true }, }; - ASSERT_NO_FATAL_FAILURE(RunCopyOldMatchesTest(last, base::size(last), current, - base::size(current), result, - base::size(result))); + ASSERT_NO_FATAL_FAILURE(RunTransferOldMatchesTest( + last, base::size(last), current, base::size(current), result, + base::size(result))); } // Tests that matches are copied correctly from two distinct providers. -TEST_F(AutocompleteResultTest, CopyOldMatchesMultipleProviders) { +TEST_F(AutocompleteResultTest, TransferOldMatchesMultipleProviders) { TestData last[] = { { 0, 1, 1300, false }, { 1, 2, 1250, true }, @@ -341,14 +346,15 @@ { 4, 1, 499, false }, }; - ASSERT_NO_FATAL_FAILURE(RunCopyOldMatchesTest(last, base::size(last), current, - base::size(current), result, - base::size(result))); + ASSERT_NO_FATAL_FAILURE(RunTransferOldMatchesTest( + last, base::size(last), current, base::size(current), result, + base::size(result))); } // Tests that matches are copied correctly from two distinct providers when // one provider doesn't have a current legal default match. -TEST_F(AutocompleteResultTest, CopyOldMatchesWithOneProviderWithoutDefault) { +TEST_F(AutocompleteResultTest, + TransferOldMatchesWithOneProviderWithoutDefault) { TestData last[] = { { 0, 2, 1250, true }, { 1, 2, 1150, true }, @@ -369,9 +375,9 @@ { 7, 1, 500, true }, }; - ASSERT_NO_FATAL_FAILURE(RunCopyOldMatchesTest(last, base::size(last), current, - base::size(current), result, - base::size(result))); + ASSERT_NO_FATAL_FAILURE(RunTransferOldMatchesTest( + last, base::size(last), current, base::size(current), result, + base::size(result))); } // Tests that matches with empty destination URLs aren't treated as duplicates @@ -844,6 +850,7 @@ last_result.AppendMatches(input, last_matches); for (auto& match : last_result) match.ComputeStrippedDestinationURL(input, template_url_service_.get()); + const auto last_comparators = last_result.GetMatchDedupComparators(); ACMatches current_matches; PopulateAutocompleteMatches(current, base::size(current), ¤t_matches); @@ -856,12 +863,13 @@ base::HistogramTester histograms; // Do the logging. - AutocompleteResult::LogAsynchronousUpdateMetrics(last_result, current_result); + AutocompleteResult::LogAsynchronousUpdateMetrics(last_comparators, + current_result); // Expect the default match, third match, and last two matches to be logged // as changed, and nothing else. EXPECT_THAT( - histograms.GetAllSamples("Omnibox.MatchStability.AsyncMatchChange"), + histograms.GetAllSamples("Omnibox.MatchStability.AsyncMatchChange2"), testing::ElementsAre(base::Bucket(0, 1), base::Bucket(2, 1), base::Bucket(3, 1), base::Bucket(4, 1))); }
diff --git a/components/page_load_metrics/browser/page_load_metrics_test_waiter.cc b/components/page_load_metrics/browser/page_load_metrics_test_waiter.cc index 9de8d573c..d953fa6f 100644 --- a/components/page_load_metrics/browser/page_load_metrics_test_waiter.cc +++ b/components/page_load_metrics/browser/page_load_metrics_test_waiter.cc
@@ -39,10 +39,6 @@ CHECK_NE(field, TimingField::kLoadTimingInfo) << "LOAD_TIMING_INFO should only be used as a page-level expectation"; subframe_expected_fields_.Set(field); - // If the given field is also a page-level field, then add a page-level - // expectation as well - if (IsPageLevelField(field)) - page_expected_fields_.Set(field); } void PageLoadMetricsTestWaiter::AddWebFeatureExpectation( @@ -53,9 +49,8 @@ } } -void PageLoadMetricsTestWaiter::AddSubframeNavigationExpectation( - size_t expected_subframe_navigations) { - expected_subframe_navigations_ = expected_subframe_navigations; +void PageLoadMetricsTestWaiter::AddSubframeNavigationExpectation() { + expected_subframe_navigation_ = true; } void PageLoadMetricsTestWaiter::AddMinimumCompleteResourcesExpectation( @@ -184,7 +179,7 @@ if (SubframeNavigationExpectationsSatisfied()) return; - ++observed_subframe_navigations_; + expected_subframe_navigation_ = false; if (ExpectationsSatisfied() && run_loop_) run_loop_->Quit(); @@ -199,17 +194,6 @@ run_loop_->Quit(); } -bool PageLoadMetricsTestWaiter::IsPageLevelField(TimingField field) { - switch (field) { - case TimingField::kFirstPaint: - case TimingField::kFirstContentfulPaint: - case TimingField::kFirstMeaningfulPaint: - return true; - default: - return false; - } -} - PageLoadMetricsTestWaiter::TimingFieldBitSet PageLoadMetricsTestWaiter::GetMatchedBits( const page_load_metrics::mojom::PageLoadTiming& timing, @@ -279,7 +263,7 @@ bool PageLoadMetricsTestWaiter::SubframeNavigationExpectationsSatisfied() const { - return observed_subframe_navigations_ >= expected_subframe_navigations_; + return !expected_subframe_navigation_; } bool PageLoadMetricsTestWaiter::ExpectationsSatisfied() const {
diff --git a/components/page_load_metrics/browser/page_load_metrics_test_waiter.h b/components/page_load_metrics/browser/page_load_metrics_test_waiter.h index 0d86084..aa43af5 100644 --- a/components/page_load_metrics/browser/page_load_metrics_test_waiter.h +++ b/components/page_load_metrics/browser/page_load_metrics_test_waiter.h
@@ -50,8 +50,8 @@ // Add a single WebFeature expectation. void AddWebFeatureExpectation(blink::mojom::WebFeature web_feature); - // Add number of subframe navigations expectation. - void AddSubframeNavigationExpectation(size_t expected_subframe_navigations); + // Wait for the subframe to navigate at least once. + void AddSubframeNavigationExpectation(); // Add a minimum completed resource expectation. void AddMinimumCompleteResourcesExpectation( @@ -165,8 +165,6 @@ bool operator()(const gfx::Size a, const gfx::Size b) const; }; - static bool IsPageLevelField(TimingField field); - static TimingFieldBitSet GetMatchedBits( const page_load_metrics::mojom::PageLoadTiming& timing, const page_load_metrics::mojom::PageLoadMetadata& metadata); @@ -225,12 +223,11 @@ TimingFieldBitSet subframe_expected_fields_; std::bitset<static_cast<size_t>(blink::mojom::WebFeature::kNumberOfFeatures)> expected_web_features_; - size_t expected_subframe_navigations_ = 0; + size_t expected_subframe_navigation_ = false; TimingFieldBitSet observed_page_fields_; std::bitset<static_cast<size_t>(blink::mojom::WebFeature::kNumberOfFeatures)> observed_web_features_; - size_t observed_subframe_navigations_ = 0; std::set<gfx::Size, FrameSizeComparator> expected_frame_sizes_; std::set<gfx::Size, FrameSizeComparator> observed_frame_sizes_;
diff --git a/components/sync/protocol/autofill_specifics.proto b/components/sync/protocol/autofill_specifics.proto index 3a436f3..5fd34f3 100644 --- a/components/sync/protocol/autofill_specifics.proto +++ b/components/sync/protocol/autofill_specifics.proto
@@ -86,6 +86,8 @@ // optional AutofillCreditCardSpecifics deprecated_credit_card = 6; } +// TODO(crbug.com/1020740): Deprecated, remove this once dependent change is +// done. Use WalletCreditCardCloudTokenData instead. message CloudTokenData { // Last 4-5 digits of the Cloud Primary Account Number (CPAN). optional string suffix = 1; @@ -158,7 +160,10 @@ // Issuing Bank name which is internationalized (e.g. "Chase", "工商银行") optional string bank_name = 10; - // This field will be set if a cloud token is available for the instrument. + // TODO(crbug.com/1020740): Deprecated, remove this once dependent change is + // done. + // Use WalletCreditCardCloudTokenData instead. This field will be set if + // a cloud token is available for the instrument. optional CloudTokenData cloud_token_data = 11; } @@ -209,12 +214,38 @@ optional string id = 1; } +// Contains information about the cloud token data of server credit cards. +message WalletCreditCardCloudTokenData { + // Server-generated ID string for the card this cloud token data is related + // to. This should match the id in WalletMaskedCreditCard for to fetch the + // corresponding actual card data. Note this is not unique across all cloud + // token data, which means one card can have multiple sets of cloud token data + // with the same masked_card_id. + optional string masked_card_id = 1; + + // Last 4-5 digits of the Cloud Primary Account Number (CPAN). + optional string suffix = 2; + + // CPAN Month number 1-12. + optional int32 exp_month = 3; + + // CPAN Four-digit year (e.g. 2017). + optional int32 exp_year = 4; + + // URL of the card art to be displayed for CPAN. + optional string art_fife_url = 5; + + // Opaque identifier for the cloud token. + optional string instrument_token = 6; +} + message AutofillWalletSpecifics { enum WalletInfoType { UNKNOWN = 0; MASKED_CREDIT_CARD = 1; POSTAL_ADDRESS = 2; CUSTOMER_DATA = 3; + CREDIT_CARD_CLOUD_TOKEN_DATA = 4; } optional WalletInfoType type = 1; @@ -228,6 +259,10 @@ // This field exists if and only if the "type" field equals to CUSTOMER_DATA. optional PaymentsCustomerData customer_data = 4; + + // This field exists if and only if the "type" field equals to + // CREDIT_CARD_CLOUD_TOKEN_DATA. + optional WalletCreditCardCloudTokenData cloud_token_data = 5; } // Wallet card and address usage information that can be synced.
diff --git a/components/sync/protocol/proto_enum_conversions.cc b/components/sync/protocol/proto_enum_conversions.cc index 7e7153a..a533f5d 100644 --- a/components/sync/protocol/proto_enum_conversions.cc +++ b/components/sync/protocol/proto_enum_conversions.cc
@@ -48,12 +48,13 @@ const char* ProtoEnumToString( sync_pb::AutofillWalletSpecifics::WalletInfoType wallet_info_type) { ASSERT_ENUM_BOUNDS(sync_pb::AutofillWalletSpecifics, WalletInfoType, UNKNOWN, - CUSTOMER_DATA); + CREDIT_CARD_CLOUD_TOKEN_DATA); switch (wallet_info_type) { ENUM_CASE(sync_pb::AutofillWalletSpecifics, UNKNOWN); ENUM_CASE(sync_pb::AutofillWalletSpecifics, MASKED_CREDIT_CARD); ENUM_CASE(sync_pb::AutofillWalletSpecifics, POSTAL_ADDRESS); ENUM_CASE(sync_pb::AutofillWalletSpecifics, CUSTOMER_DATA); + ENUM_CASE(sync_pb::AutofillWalletSpecifics, CREDIT_CARD_CLOUD_TOKEN_DATA); } NOTREACHED(); return "";
diff --git a/components/sync/protocol/proto_value_conversions.cc b/components/sync/protocol/proto_value_conversions.cc index febc158..02d4fa817 100644 --- a/components/sync/protocol/proto_value_conversions.cc +++ b/components/sync/protocol/proto_value_conversions.cc
@@ -217,6 +217,10 @@ if (proto.type() != sync_pb::AutofillWalletSpecifics::CUSTOMER_DATA) { value->Remove("customer_data", nullptr); } + if (proto.type() != + sync_pb::AutofillWalletSpecifics::CREDIT_CARD_CLOUD_TOKEN_DATA) { + value->Remove("cloud_token_data", nullptr); + } return value; } @@ -354,6 +358,7 @@ IMPLEMENT_PROTO_TO_VALUE(UrlDirective) IMPLEMENT_PROTO_TO_VALUE(UserConsentSpecifics) IMPLEMENT_PROTO_TO_VALUE(UserEventSpecifics) +IMPLEMENT_PROTO_TO_VALUE(WalletCreditCardCloudTokenData) IMPLEMENT_PROTO_TO_VALUE(WalletMaskedCreditCard) IMPLEMENT_PROTO_TO_VALUE(WalletMetadataSpecifics) IMPLEMENT_PROTO_TO_VALUE(WalletPostalAddress)
diff --git a/components/sync/protocol/proto_value_conversions.h b/components/sync/protocol/proto_value_conversions.h index c77cf0c9..7ebb383 100644 --- a/components/sync/protocol/proto_value_conversions.h +++ b/components/sync/protocol/proto_value_conversions.h
@@ -69,6 +69,7 @@ class UrlDirective; class UserConsentSpecifics; class UserEventSpecifics; +class WalletCreditCardCloudTokenData; class WalletMaskedCreditCard; class WalletMetadataSpecifics; class WalletPostalAddress; @@ -249,6 +250,9 @@ std::unique_ptr<base::DictionaryValue> UserEventSpecificsToValue( const sync_pb::UserEventSpecifics& user_event_specifics); +std::unique_ptr<base::DictionaryValue> WalletCreditCardCloudTokenDataToValue( + const sync_pb::WalletCreditCardCloudTokenData& cloud_token_data); + std::unique_ptr<base::DictionaryValue> WalletMaskedCreditCardToValue( const sync_pb::WalletMaskedCreditCard& wallet_masked_card);
diff --git a/components/sync/protocol/proto_value_conversions_unittest.cc b/components/sync/protocol/proto_value_conversions_unittest.cc index b818693..d82d52e 100644 --- a/components/sync/protocol/proto_value_conversions_unittest.cc +++ b/components/sync/protocol/proto_value_conversions_unittest.cc
@@ -139,30 +139,43 @@ specifics.mutable_masked_card()->set_name_on_card("Igloo"); specifics.mutable_address()->set_recipient_name("John"); specifics.mutable_customer_data()->set_id("123456"); + specifics.mutable_cloud_token_data()->set_masked_card_id("1111"); specifics.set_type(sync_pb::AutofillWalletSpecifics::UNKNOWN); auto value = AutofillWalletSpecificsToValue(specifics); EXPECT_FALSE(value->Get("masked_card", nullptr)); EXPECT_FALSE(value->Get("address", nullptr)); EXPECT_FALSE(value->Get("customer_data", nullptr)); + EXPECT_FALSE(value->Get("cloud_token_data", nullptr)); specifics.set_type(sync_pb::AutofillWalletSpecifics::MASKED_CREDIT_CARD); value = AutofillWalletSpecificsToValue(specifics); EXPECT_TRUE(value->Get("masked_card", nullptr)); EXPECT_FALSE(value->Get("address", nullptr)); EXPECT_FALSE(value->Get("customer_data", nullptr)); + EXPECT_FALSE(value->Get("cloud_token_data", nullptr)); specifics.set_type(sync_pb::AutofillWalletSpecifics::POSTAL_ADDRESS); value = AutofillWalletSpecificsToValue(specifics); EXPECT_FALSE(value->Get("masked_card", nullptr)); EXPECT_TRUE(value->Get("address", nullptr)); EXPECT_FALSE(value->Get("customer_data", nullptr)); + EXPECT_FALSE(value->Get("cloud_token_data", nullptr)); specifics.set_type(sync_pb::AutofillWalletSpecifics::CUSTOMER_DATA); value = AutofillWalletSpecificsToValue(specifics); EXPECT_FALSE(value->Get("masked_card", nullptr)); EXPECT_FALSE(value->Get("address", nullptr)); EXPECT_TRUE(value->Get("customer_data", nullptr)); + EXPECT_FALSE(value->Get("cloud_token_data", nullptr)); + + specifics.set_type( + sync_pb::AutofillWalletSpecifics::CREDIT_CARD_CLOUD_TOKEN_DATA); + value = AutofillWalletSpecificsToValue(specifics); + EXPECT_FALSE(value->Get("masked_card", nullptr)); + EXPECT_FALSE(value->Get("address", nullptr)); + EXPECT_FALSE(value->Get("customer_data", nullptr)); + EXPECT_TRUE(value->Get("cloud_token_data", nullptr)); } TEST(ProtoValueConversionsTest, BookmarkSpecificsData) {
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h index 3bb1ed1..58b159c 100644 --- a/components/sync/protocol/proto_visitors.h +++ b/components/sync/protocol/proto_visitors.h
@@ -173,6 +173,7 @@ VISIT(masked_card); VISIT(address); VISIT(customer_data); + VISIT(cloud_token_data); } VISIT_PROTO_FIELDS(const sync_pb::BookmarkSpecifics& proto) { @@ -1078,6 +1079,15 @@ VISIT(id); } +VISIT_PROTO_FIELDS(const sync_pb::WalletCreditCardCloudTokenData& proto) { + VISIT(masked_card_id); + VISIT(suffix); + VISIT(exp_month); + VISIT(exp_year); + VISIT(art_fife_url); + VISIT(instrument_token); +} + VISIT_PROTO_FIELDS(const sync_pb::WalletSyncFlags& proto) { VISIT(enabled); }
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc index 52438fb..c148b70 100644 --- a/content/browser/download/download_manager_impl.cc +++ b/content/browser/download/download_manager_impl.cc
@@ -924,11 +924,23 @@ received_bytes, total_bytes, hash, state, danger_type, interrupt_reason, opened, last_access_time, transient, received_slices)); if (in_progress_download) { - // If the download item from history db is already in terminal state, - // remove it from the in-progress db. Otherwise, use the in-progress db one. - if (item->IsDone()) { + // If a download is in both history DB and in-progress DB, we should + // be able to remove the in-progress entry if the following 2 conditions + // are both met: + // 1. The download state in the history DB is a terminal state. + // 2. The download is not currently in progress. + // The situation could happen when browser crashes when download just + // reaches a terminal state. If the download is already in progress, we + // should wait for it to complete so that both DBs will be updated + // afterwards. + if (item->IsDone() && in_progress_download->GetState() != + download::DownloadItem::IN_PROGRESS) { in_progress_manager_->RemoveInProgressDownload(guid); } else { + // If one of the conditions are not met, use the in-progress download + // entry. + // TODO(qinmin): return nullptr so that the history DB will delete + // the download. item = std::move(in_progress_download); item->SetDelegate(this); }
diff --git a/content/browser/sms/sms_fetcher_impl.cc b/content/browser/sms/sms_fetcher_impl.cc index a60d341..06a7716 100644 --- a/content/browser/sms/sms_fetcher_impl.cc +++ b/content/browser/sms/sms_fetcher_impl.cc
@@ -6,6 +6,7 @@ #include "base/callback.h" #include "content/browser/browser_main_loop.h" +#include "content/browser/sms/sms_parser.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/content_browser_client.h" #include "content/public/common/content_client.h" @@ -72,8 +73,14 @@ } void SmsFetcherImpl::OnRemote(base::Optional<std::string> sms) { - // TODO(crbug.com/1015645): implementation left pending deliberately. - NOTIMPLEMENTED(); + if (!sms) + return; + + base::Optional<SmsParser::Result> result = SmsParser::Parse(*sms); + if (!result) + return; + + Notify(result->origin, result->one_time_code, *sms); } bool SmsFetcherImpl::OnReceive(const url::Origin& origin,
diff --git a/content/browser/sms/sms_fetcher_impl_unittest.cc b/content/browser/sms/sms_fetcher_impl_unittest.cc new file mode 100644 index 0000000..e18c1756 --- /dev/null +++ b/content/browser/sms/sms_fetcher_impl_unittest.cc
@@ -0,0 +1,203 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/sms/sms_fetcher_impl.h" + +#include "content/browser/sms/test/mock_sms_provider.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/common/content_client.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" +#include "url/origin.h" + +using ::testing::_; +using ::testing::Invoke; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::StrictMock; + +namespace content { + +namespace { + +const url::Origin kTestOrigin = url::Origin::Create(GURL("https://a.com")); + +class MockContentBrowserClient : public ContentBrowserClient { + public: + MockContentBrowserClient() = default; + ~MockContentBrowserClient() override = default; + + MOCK_METHOD3(FetchRemoteSms, + void(BrowserContext*, + const url::Origin&, + base::OnceCallback<void(base::Optional<std::string>)>)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockContentBrowserClient); +}; + +class MockSubscriber : public SmsFetcher::Subscriber { + public: + MockSubscriber() = default; + ~MockSubscriber() override = default; + + MOCK_METHOD2(OnReceive, + void(const std::string& one_time_code, const std::string& sms)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockSubscriber); +}; + +class SmsFetcherImplTest : public testing::Test { + public: + SmsFetcherImplTest() = default; + ~SmsFetcherImplTest() override = default; + + void SetUp() override { + original_client_ = SetBrowserClientForTesting(&client_); + } + + void TearDown() override { + if (original_client_) + SetBrowserClientForTesting(original_client_); + } + + protected: + MockContentBrowserClient* client() { return &client_; } + MockSmsProvider* provider() { return &provider_; } + + private: + ContentBrowserClient* original_client_ = nullptr; + NiceMock<MockContentBrowserClient> client_; + NiceMock<MockSmsProvider> provider_; + + DISALLOW_COPY_AND_ASSIGN(SmsFetcherImplTest); +}; + +} // namespace + +TEST_F(SmsFetcherImplTest, ReceiveFromLocalSmsProvider) { + StrictMock<MockSubscriber> subscriber; + SmsFetcherImpl fetcher(nullptr, provider()); + + EXPECT_CALL(*provider(), Retrieve()).WillOnce(Invoke([&]() { + provider()->NotifyReceive(kTestOrigin, "123", "hello"); + })); + + EXPECT_CALL(subscriber, OnReceive("123", "hello")); + + fetcher.Subscribe(kTestOrigin, &subscriber); +} + +TEST_F(SmsFetcherImplTest, ReceiveFromRemoteProvider) { + StrictMock<MockSubscriber> subscriber; + SmsFetcherImpl fetcher(nullptr, provider()); + + const std::string& sms = "For: https://a.com?otp=123"; + + EXPECT_CALL(*client(), FetchRemoteSms(_, _, _)) + .WillOnce(Invoke( + [&](BrowserContext*, const url::Origin&, + base::OnceCallback<void(base::Optional<std::string>)> callback) { + std::move(callback).Run(sms); + })); + + EXPECT_CALL(subscriber, OnReceive("123", sms)); + + fetcher.Subscribe(kTestOrigin, &subscriber); +} + +TEST_F(SmsFetcherImplTest, RemoteProviderTimesOut) { + StrictMock<MockSubscriber> subscriber; + SmsFetcherImpl fetcher(nullptr, provider()); + + EXPECT_CALL(*client(), FetchRemoteSms(_, _, _)) + .WillOnce(Invoke( + [&](BrowserContext*, const url::Origin&, + base::OnceCallback<void(base::Optional<std::string>)> callback) { + std::move(callback).Run(base::nullopt); + })); + + EXPECT_CALL(subscriber, OnReceive(_, _)).Times(0); + + fetcher.Subscribe(kTestOrigin, &subscriber); +} + +TEST_F(SmsFetcherImplTest, ReceiveFromOtherOrigin) { + StrictMock<MockSubscriber> subscriber; + const url::Origin origin = url::Origin::Create(GURL("https://a.com")); + + SmsFetcherImpl fetcher(nullptr, provider()); + + EXPECT_CALL(*client(), FetchRemoteSms(_, _, _)) + .WillOnce(Invoke( + [&](BrowserContext*, const url::Origin&, + base::OnceCallback<void(base::Optional<std::string>)> callback) { + std::move(callback).Run("For: https://b.com?otp=123"); + })); + + EXPECT_CALL(subscriber, OnReceive(_, _)).Times(0); + + fetcher.Subscribe(origin, &subscriber); +} + +TEST_F(SmsFetcherImplTest, ReceiveFromBothProviders) { + StrictMock<MockSubscriber> subscriber; + SmsFetcherImpl fetcher(nullptr, provider()); + + const std::string& sms = "hello \nFor: https://a.com?otp=123"; + + EXPECT_CALL(*client(), FetchRemoteSms(_, _, _)) + .WillOnce(Invoke( + [&](BrowserContext*, const url::Origin&, + base::OnceCallback<void(base::Optional<std::string>)> callback) { + std::move(callback).Run(sms); + })); + + EXPECT_CALL(*provider(), Retrieve()).WillOnce(Invoke([&]() { + provider()->NotifyReceive(sms); + })); + + // Expects subscriber to be notified just once. + EXPECT_CALL(subscriber, OnReceive("123", sms)); + + fetcher.Subscribe(kTestOrigin, &subscriber); +} + +TEST_F(SmsFetcherImplTest, OneOriginTwoSubscribers) { + StrictMock<MockSubscriber> subscriber1; + StrictMock<MockSubscriber> subscriber2; + + SmsFetcherImpl fetcher(nullptr, provider()); + + fetcher.Subscribe(kTestOrigin, &subscriber1); + fetcher.Subscribe(kTestOrigin, &subscriber2); + + EXPECT_CALL(subscriber1, OnReceive("123", "foo")); + provider()->NotifyReceive(kTestOrigin, "123", "foo"); + + EXPECT_CALL(subscriber2, OnReceive("456", "bar")); + provider()->NotifyReceive(kTestOrigin, "456", "bar"); +} + +TEST_F(SmsFetcherImplTest, TwoOriginsTwoSubscribers) { + StrictMock<MockSubscriber> subscriber1; + StrictMock<MockSubscriber> subscriber2; + + const url::Origin origin1 = url::Origin::Create(GURL("https://a.com")); + const url::Origin origin2 = url::Origin::Create(GURL("https://b.com")); + + SmsFetcherImpl fetcher(nullptr, provider()); + fetcher.Subscribe(origin1, &subscriber1); + fetcher.Subscribe(origin2, &subscriber2); + + EXPECT_CALL(subscriber2, OnReceive("456", "bar")); + provider()->NotifyReceive(origin2, "456", "bar"); + + EXPECT_CALL(subscriber1, OnReceive("123", "foo")); + provider()->NotifyReceive(origin1, "123", "foo"); +} + +} // namespace content \ No newline at end of file
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 1c63b46a..e4cc95a 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -7246,10 +7246,10 @@ return base::BindRepeating( [](base::WeakPtr<RenderFrameHostDelegate> delegate, GURL last_committed_url, base::TimeDelta total_watch_time, - base::TimeDelta time_stamp) { - content::MediaPlayerWatchTime watch_time(last_committed_url, - last_committed_url.GetOrigin(), - total_watch_time, time_stamp); + base::TimeDelta time_stamp, bool has_video, bool has_audio) { + content::MediaPlayerWatchTime watch_time( + last_committed_url, last_committed_url.GetOrigin(), + total_watch_time, time_stamp, has_video, has_audio); // Save the watch time if the delegate is still alive. if (delegate)
diff --git a/content/public/browser/media_player_watch_time.cc b/content/public/browser/media_player_watch_time.cc index 553e5cf..b4f771b 100644 --- a/content/public/browser/media_player_watch_time.cc +++ b/content/public/browser/media_player_watch_time.cc
@@ -10,11 +10,15 @@ GURL url, GURL origin, base::TimeDelta cumulative_watch_time, - base::TimeDelta last_timestamp) + base::TimeDelta last_timestamp, + bool has_video, + bool has_audio) : url(url), origin(origin), cumulative_watch_time(cumulative_watch_time), - last_timestamp(last_timestamp) {} + last_timestamp(last_timestamp), + has_video(has_video), + has_audio(has_audio) {} MediaPlayerWatchTime::MediaPlayerWatchTime(const MediaPlayerWatchTime& other) = default;
diff --git a/content/public/browser/media_player_watch_time.h b/content/public/browser/media_player_watch_time.h index 19f9866..e2592b4 100644 --- a/content/public/browser/media_player_watch_time.h +++ b/content/public/browser/media_player_watch_time.h
@@ -15,7 +15,9 @@ MediaPlayerWatchTime(GURL url, GURL origin, base::TimeDelta cumulative_watch_time, - base::TimeDelta last_timestamp); + base::TimeDelta last_timestamp, + bool has_video, + bool has_audio); MediaPlayerWatchTime(const MediaPlayerWatchTime& other); ~MediaPlayerWatchTime() = default; @@ -23,6 +25,8 @@ GURL origin; base::TimeDelta cumulative_watch_time; base::TimeDelta last_timestamp; + bool has_video; + bool has_audio; }; } // namespace content
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc index d3eb266..fa1228b6 100644 --- a/content/public/test/browser_test_base.cc +++ b/content/public/test/browser_test_base.cc
@@ -108,6 +108,10 @@ namespace content { namespace { +// Whether an instance of BrowserTestBase has already been created in this +// process. Browser tests should each be run in a new process. +bool g_instance_already_created = false; + #if defined(OS_POSIX) // On SIGSEGV or SIGTERM (sent by the runner on timeouts), dump a stack trace // (to make debugging easier) and also exit with a known error code (so that @@ -173,6 +177,11 @@ enable_pixel_output_(false), use_software_compositing_(false), set_up_called_(false) { + CHECK(!g_instance_already_created) + << "Each browser test should be run in a new process. If you are adding " + "a new browser test suite that runs on Android, please add it to " + "//build/android/pylib/gtest/gtest_test_instance.py."; + g_instance_already_created = true; #if defined(OS_LINUX) ui::test::EnableTestConfigForPlatformWindows(); #endif
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 0860a47a..a8cb25b 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -2270,35 +2270,43 @@ void RenderFrameImpl::BindFullscreen( mojo::PendingAssociatedReceiver<mojom::FullscreenVideoElementHandler> receiver) { - fullscreen_receiver_.Bind(std::move(receiver), - GetTaskRunner(blink::TaskType::kInternalIPC)); + fullscreen_receiver_.Bind( + std::move(receiver), + GetTaskRunner(blink::TaskType::kInternalNavigationAssociated)); } void RenderFrameImpl::BindAutoplayConfiguration( mojo::PendingAssociatedReceiver<blink::mojom::AutoplayConfigurationClient> receiver) { autoplay_configuration_receiver_.Bind( - std::move(receiver), GetTaskRunner(blink::TaskType::kInternalIPC)); + std::move(receiver), + GetTaskRunner(blink::TaskType::kInternalNavigationAssociated)); } void RenderFrameImpl::BindFrame( const service_manager::BindSourceInfo& browser_info, mojo::PendingReceiver<mojom::Frame> receiver) { browser_info_ = browser_info; - frame_receiver_.Bind(std::move(receiver), - GetTaskRunner(blink::TaskType::kInternalIPC)); + // It's not unfreezable at the moment because Frame::SetLifecycleState + // has to run for the frozen frames. + // TODO(altimin): Move SetLifecycleState to a dedicated scheduling interface. + frame_receiver_.Bind( + std::move(receiver), + GetTaskRunner(blink::TaskType::kInternalFrameLifecycleControl)); } void RenderFrameImpl::BindFrameBindingsControl( mojo::PendingAssociatedReceiver<mojom::FrameBindingsControl> receiver) { frame_bindings_control_receiver_.Bind( - std::move(receiver), GetTaskRunner(blink::TaskType::kInternalIPC)); + std::move(receiver), + GetTaskRunner(blink::TaskType::kInternalNavigationAssociated)); } void RenderFrameImpl::BindFrameNavigationControl( mojo::PendingAssociatedReceiver<mojom::FrameNavigationControl> receiver) { frame_navigation_control_receiver_.Bind( - std::move(receiver), GetTaskRunner(blink::TaskType::kInternalIPC)); + std::move(receiver), + GetTaskRunner(blink::TaskType::kInternalNavigationAssociated)); } void RenderFrameImpl::BindNavigationClient( @@ -3042,13 +3050,13 @@ remote_associated_interfaces_ = std::make_unique<blink::AssociatedInterfaceProvider>( std::move(remote_interfaces), - GetTaskRunner(blink::TaskType::kInternalIPC)); + GetTaskRunner(blink::TaskType::kInternalNavigationAssociated)); } else { // In some tests the thread may be null, // so set up a self-contained interface provider instead. remote_associated_interfaces_ = std::make_unique<blink::AssociatedInterfaceProvider>( - GetTaskRunner(blink::TaskType::kInternalIPC)); + GetTaskRunner(blink::TaskType::kInternalNavigationAssociated)); } } return remote_associated_interfaces_.get(); @@ -4129,7 +4137,7 @@ service_manager::mojom::InterfaceProviderPtrInfo( mojo::ScopedMessagePipeHandle(params_reply.new_interface_provider), 0u), - GetTaskRunner(blink::TaskType::kInternalIPC)); + GetTaskRunner(blink::TaskType::kInternalDefault)); DCHECK(params_reply.browser_interface_broker_handle.is_valid());
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index f496c51..2bb1463 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1786,6 +1786,7 @@ "../browser/service_worker/service_worker_version_unittest.cc", "../browser/shareable_file_reference_unittest.cc", "../browser/site_instance_impl_unittest.cc", + "../browser/sms/sms_fetcher_impl_unittest.cc", "../browser/sms/sms_parser_unittest.cc", "../browser/sms/sms_service_unittest.cc", "../browser/speech/tts_controller_unittest.cc",
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt index 85cdbd9..bc9154b 100644 --- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -45,9 +45,3 @@ crbug.com/609629 [ android qualcomm-adreno-(tm)-420 ] GpuCrash_GPUProcessCrashesExactlyOncePerVisitToAboutGpuCrash [ Skip ] crbug.com/609629 [ android qualcomm-adreno-(tm)-420 ] ContextLost_WebGLContextLostFromGPUProcessExit [ Skip ] crbug.com/609629 [ android qualcomm-adreno-(tm)-420 ] ContextLost_WebGLContextLostInHiddenTab [ Skip ] - -# TODO(crbug.com/681341): enable these new tests immediately after they land. -# Disabled upon landing only to avoid having the entire CL reverted if the new -# tests turn out to be flaky. -crbug.com/681341 ContextLost_MacWebGLMultisamplingHighPowerSwitchLosesContext [ Skip ] -crbug.com/681341 ContextLost_MacWebGLPreserveDBHighPowerSwitchLosesContext [ Skip ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt index f4f7d48..b19bc1a 100644 --- a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
@@ -5,11 +5,3 @@ # Seems to have become flaky on Windows recently. crbug.com/700522 [ win ] GpuProcess_one_extra_workaround [ RetryOnFailure ] - -# TODO(crbug.com/681341): enable these new tests immediately after they land. -# Disabled upon landing only to avoid having the entire CL reverted if the new -# tests turn out to be flaky. -crbug.com/681341 GpuProcess_mac_webgl_backgrounded_high_performance [ Skip ] -crbug.com/681341 GpuProcess_mac_webgl_high_performance [ Skip ] -crbug.com/681341 GpuProcess_mac_webgl_low_power [ Skip ] -crbug.com/681341 GpuProcess_mac_webgl_terminated_high_performance [ Skip ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index 27caa3e..79d418a 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -233,9 +233,3 @@ crbug.com/1019462 [ android nvidia no-skia-renderer ] Pixel_Video_MP4_Rounded_Corner [ RetryOnFailure ] crbug.com/1019462 [ android nvidia no-skia-renderer ] Pixel_Video_Context_Loss_VP9 [ RetryOnFailure ] crbug.com/1019462 [ android nvidia no-skia-renderer ] Pixel_WebGL2_BlitFramebuffer_Result_Displayed [ RetryOnFailure ] - -# TODO(crbug.com/681341): enable these new tests immediately after they land. -# Disabled upon landing only to avoid having the entire CL reverted if the new -# tests turn out to be flaky. -crbug.com/681341 [ mac ] Pixel_WebGLHighToLowPower [ Skip ] -crbug.com/681341 [ mac ] Pixel_WebGLLowToHighPower [ Skip ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index 17c0e39..8d53e298 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -72,9 +72,6 @@ # ======================== # Fails on all platforms -# Need to merge WEBGL_multi_draw_instanced into WEBGL_multi_draw -crbug.com/890539 conformance/extensions/webgl-multi-draw.html [ Skip ] - # Need to implement new error semantics # https://github.com/KhronosGroup/WebGL/pull/2607 crbug.com/849572 [ passthrough ] conformance/extensions/angle-instanced-arrays-out-of-bounds.html [ Failure ]
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py index f48b1c2..d6ff4b7c 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py
@@ -168,7 +168,6 @@ 'WEBGL_draw_buffers', 'WEBGL_lose_context', 'WEBGL_multi_draw', - 'WEBGL_multi_draw_instanced', 'WEBGL_video_texture', ] else: @@ -190,7 +189,6 @@ 'WEBGL_debug_shaders', 'WEBGL_lose_context', 'WEBGL_multi_draw', - 'WEBGL_multi_draw_instanced', 'WEBGL_video_texture', ]
diff --git a/device/vr/android/gvr/gvr_delegate.cc b/device/vr/android/gvr/gvr_delegate.cc index a09b837..5e92e90c 100644 --- a/device/vr/android/gvr/gvr_delegate.cc +++ b/device/vr/android/gvr/gvr_delegate.cc
@@ -18,63 +18,6 @@ // exposed, use that instead (it defaults to 50ms on most platforms). static constexpr int64_t kPredictionTimeWithoutVsyncNanos = 50000000; -// Time offset used for calculating angular velocity from a pair of predicted -// poses. The precise value shouldn't matter as long as it's nonzero and much -// less than a frame. -static constexpr int64_t kAngularVelocityEpsilonNanos = 1000000; - -gfx::Vector3dF GetAngularVelocityFromPoses(gfx::Transform head_mat, - gfx::Transform head_mat_2, - double epsilon_seconds) { - // The angular velocity is a 3-element vector pointing along the rotation - // axis with magnitude equal to rotation speed in radians/second, expressed - // in the seated frame of reference. - // - // The 1.1 spec isn't very clear on details, clarification requested in - // https://github.com/w3c/webvr/issues/212 . For now, assuming that we - // want a vector in the sitting reference frame. - // - // Assuming that pose prediction is simply based on adding a time * angular - // velocity rotation to the pose, we can approximate the angular velocity - // from the difference between two successive poses. This is a first order - // estimate that assumes small enough rotations so that we can do linear - // approximation. - // - // See: - // https://en.wikipedia.org/wiki/Angular_velocity#Calculation_from_the_orientation_matrix - - gfx::Transform delta_mat; - gfx::Transform inverse_head_mat; - // Calculate difference matrix, and inverse head matrix rotation. - // For the inverse rotation, just transpose the 3x3 subsection. - // - // Assume that epsilon is nonzero since it's based on a compile-time constant - // provided by the caller. - for (int j = 0; j < 3; ++j) { - for (int i = 0; i < 3; ++i) { - delta_mat.matrix().set( - j, i, - (head_mat_2.matrix().get(j, i) - head_mat.matrix().get(j, i)) / - epsilon_seconds); - inverse_head_mat.matrix().set(j, i, head_mat.matrix().get(i, j)); - } - delta_mat.matrix().set(j, 3, 0); - delta_mat.matrix().set(3, j, 0); - inverse_head_mat.matrix().set(j, 3, 0); - inverse_head_mat.matrix().set(3, j, 0); - } - delta_mat.matrix().set(3, 3, 1); - inverse_head_mat.matrix().set(3, 3, 1); - gfx::Transform omega_mat = delta_mat * inverse_head_mat; - gfx::Vector3dF omega_vec(-omega_mat.matrix().get(2, 1), - omega_mat.matrix().get(2, 0), - -omega_mat.matrix().get(1, 0)); - - // Rotate by inverse head matrix to bring into seated space. - inverse_head_mat.TransformVector(&omega_vec); - return omega_vec; -} - } // namespace /* static */ @@ -139,18 +82,6 @@ mojom::VRPosePtr pose = GvrDelegate::VRPosePtrFromGvrPose(*head_mat_ptr); - // Get a second pose a bit later to calculate angular velocity. - target_time.monotonic_system_time_nanos += kAngularVelocityEpsilonNanos; - gvr::Mat4f gvr_head_mat_2 = - gvr_api->GetHeadSpaceFromStartSpaceRotation(target_time); - gfx::Transform head_mat_2; - gvr_utils::GvrMatToTransform(gvr_head_mat_2, &head_mat_2); - - // Add headset angular velocity to the pose. - double epsilon_seconds = kAngularVelocityEpsilonNanos * 1e-9; - pose->angular_velocity = - GetAngularVelocityFromPoses(*head_mat_ptr, head_mat_2, epsilon_seconds); - // The position is emulated unless the current tracking status is 6DoF and is // not still initializing or invalid. pose->emulated_position = true;
diff --git a/device/vr/openvr/openvr_type_converters.cc b/device/vr/openvr/openvr_type_converters.cc index 6b30773..ce8fb793 100644 --- a/device/vr/openvr/openvr_type_converters.cc +++ b/device/vr/openvr/openvr_type_converters.cc
@@ -33,13 +33,6 @@ } pose->position->SetPoint(m[0][3], m[1][3], m[2][3]); - - pose->linear_velocity = - gfx::Vector3dF(hmd_pose.vVelocity.v[0], hmd_pose.vVelocity.v[1], - hmd_pose.vVelocity.v[2]); - pose->angular_velocity = gfx::Vector3dF(hmd_pose.vAngularVelocity.v[0], - hmd_pose.vAngularVelocity.v[1], - hmd_pose.vAngularVelocity.v[2]); } return pose;
diff --git a/device/vr/public/mojom/vr_service.mojom b/device/vr/public/mojom/vr_service.mojom index 32a556e..a054e81a 100644 --- a/device/vr/public/mojom/vr_service.mojom +++ b/device/vr/public/mojom/vr_service.mojom
@@ -198,12 +198,6 @@ // False when position is based on sensors tracking a 6DoF pose. bool emulated_position; - // Velocity/Acceleration is in global coordinates, as rad/s. - gfx.mojom.Vector3dF? angular_velocity; - gfx.mojom.Vector3dF? linear_velocity; - gfx.mojom.Vector3dF? angular_acceleration; - gfx.mojom.Vector3dF? linear_acceleration; - // For WebXR sessions only, reports the state of all active input devices // synced with the head pose. array<XRInputSourceState>? input_state;
diff --git a/device/vr/windows_mixed_reality/wrappers/test/mock_wmr_input_location.cc b/device/vr/windows_mixed_reality/wrappers/test/mock_wmr_input_location.cc index dd6b8534..0f85236 100644 --- a/device/vr/windows_mixed_reality/wrappers/test/mock_wmr_input_location.cc +++ b/device/vr/windows_mixed_reality/wrappers/test/mock_wmr_input_location.cc
@@ -31,20 +31,6 @@ return true; } -bool MockWMRInputLocation::TryGetVelocity( - ABI::Windows::Foundation::Numerics::Vector3* velocity) const { - DCHECK(velocity); - if (!data_.pose_data.is_valid) - return false; - // We could potentially store a history of poses and calculate the velocity, - // but that is more complicated and doesn't currently provide any benefit for - // tests. So, just report 0s. - velocity->X = 0; - velocity->Y = 0; - velocity->Z = 0; - return true; -} - bool MockWMRInputLocation::TryGetOrientation( ABI::Windows::Foundation::Numerics::Quaternion* orientation) const { DCHECK(orientation); @@ -58,20 +44,6 @@ return true; } -bool MockWMRInputLocation::TryGetAngularVelocity( - ABI::Windows::Foundation::Numerics::Vector3* angular_velocity) const { - DCHECK(angular_velocity); - if (!data_.pose_data.is_valid) - return false; - // We could potentially store a history of poses and calculate the angular - // velocity, but that is more complicated and doesn't currently provide any - // benefit for tests. So, just report 0s. - angular_velocity->X = 0; - angular_velocity->Y = 0; - angular_velocity->Z = 0; - return true; -} - bool MockWMRInputLocation::TryGetPositionAccuracy( ABI::Windows::UI::Input::Spatial::SpatialInteractionSourcePositionAccuracy* position_accuracy) const {
diff --git a/device/vr/windows_mixed_reality/wrappers/test/mock_wmr_input_location.h b/device/vr/windows_mixed_reality/wrappers/test/mock_wmr_input_location.h index 34a69b3..8e9aef6 100644 --- a/device/vr/windows_mixed_reality/wrappers/test/mock_wmr_input_location.h +++ b/device/vr/windows_mixed_reality/wrappers/test/mock_wmr_input_location.h
@@ -17,12 +17,8 @@ bool TryGetPosition( ABI::Windows::Foundation::Numerics::Vector3* position) const override; - bool TryGetVelocity( - ABI::Windows::Foundation::Numerics::Vector3* velocity) const override; bool TryGetOrientation(ABI::Windows::Foundation::Numerics::Quaternion* orientation) const override; - bool TryGetAngularVelocity(ABI::Windows::Foundation::Numerics::Vector3* - angular_velocity) const override; bool TryGetPositionAccuracy(ABI::Windows::UI::Input::Spatial:: SpatialInteractionSourcePositionAccuracy* position_accuracy) const override;
diff --git a/device/vr/windows_mixed_reality/wrappers/wmr_input_location.cc b/device/vr/windows_mixed_reality/wrappers/wmr_input_location.cc index e0b8c9b2..8e6ee5e 100644 --- a/device/vr/windows_mixed_reality/wrappers/wmr_input_location.cc +++ b/device/vr/windows_mixed_reality/wrappers/wmr_input_location.cc
@@ -51,16 +51,6 @@ return TryGetValue(ref, position); } -bool WMRInputLocationImpl::TryGetVelocity(WFN::Vector3* velocity) const { - DCHECK(velocity); - if (!location_) - return false; - ComPtr<IReference<WFN::Vector3>> ref; - HRESULT hr = location_->get_Velocity(&ref); - DCHECK(SUCCEEDED(hr)); - return TryGetValue(ref, velocity); -} - bool WMRInputLocationImpl::TryGetOrientation( WFN::Quaternion* orientation) const { DCHECK(orientation); @@ -72,17 +62,6 @@ return TryGetValue(ref, orientation); } -bool WMRInputLocationImpl::TryGetAngularVelocity( - WFN::Vector3* angular_velocity) const { - DCHECK(angular_velocity); - if (!location3_) - return false; - ComPtr<IReference<WFN::Vector3>> ref; - HRESULT hr = location3_->get_AngularVelocity(&ref); - DCHECK(SUCCEEDED(hr)); - return TryGetValue(ref, angular_velocity); -} - bool WMRInputLocationImpl::TryGetPositionAccuracy( ABI::Windows::UI::Input::Spatial::SpatialInteractionSourcePositionAccuracy* position_accuracy) const {
diff --git a/device/vr/windows_mixed_reality/wrappers/wmr_input_location.h b/device/vr/windows_mixed_reality/wrappers/wmr_input_location.h index 2d61915a..2dcaac915 100644 --- a/device/vr/windows_mixed_reality/wrappers/wmr_input_location.h +++ b/device/vr/windows_mixed_reality/wrappers/wmr_input_location.h
@@ -16,14 +16,10 @@ virtual bool TryGetPosition( ABI::Windows::Foundation::Numerics::Vector3* position) const = 0; - virtual bool TryGetVelocity( - ABI::Windows::Foundation::Numerics::Vector3* velocity) const = 0; virtual bool TryGetOrientation( ABI::Windows::Foundation::Numerics::Quaternion* orientation) const = 0; - virtual bool TryGetAngularVelocity( - ABI::Windows::Foundation::Numerics::Vector3* angular_velocity) const = 0; virtual bool TryGetPositionAccuracy( ABI::Windows::UI::Input::Spatial:: SpatialInteractionSourcePositionAccuracy* position_accuracy) @@ -41,16 +37,12 @@ // Uses ISpatialInteractionSourceLocation. bool TryGetPosition( ABI::Windows::Foundation::Numerics::Vector3* position) const override; - bool TryGetVelocity( - ABI::Windows::Foundation::Numerics::Vector3* velocity) const override; // Uses ISpatialInteractionSourceLocation2. bool TryGetOrientation(ABI::Windows::Foundation::Numerics::Quaternion* orientation) const override; // Uses ISpatialInteractionSourceLocation3. - bool TryGetAngularVelocity(ABI::Windows::Foundation::Numerics::Vector3* - angular_velocity) const override; bool TryGetPositionAccuracy(ABI::Windows::UI::Input::Spatial:: SpatialInteractionSourcePositionAccuracy* position_accuracy) const override;
diff --git a/google_apis/gaia/gaia_auth_util.cc b/google_apis/gaia/gaia_auth_util.cc index b584dd3a..93ef07d 100644 --- a/google_apis/gaia/gaia_auth_util.cc +++ b/google_apis/gaia/gaia_auth_util.cc
@@ -24,6 +24,7 @@ namespace { const char kGmailDomain[] = "gmail.com"; +const char kGoogleDomain[] = "google.com"; const char kGooglemailDomain[] = "googlemail.com"; const void* const kURLRequestUserDataKey = &kURLRequestUserDataKey; @@ -105,6 +106,10 @@ return std::string(); } +bool IsGoogleInternalAccountEmail(const std::string& email) { + return ExtractDomainName(email) == kGoogleDomain; +} + bool IsGaiaSignonRealm(const GURL& url) { if (!url.SchemeIsCryptographic()) return false;
diff --git a/google_apis/gaia/gaia_auth_util.h b/google_apis/gaia/gaia_auth_util.h index cc16fb645..4ca1fc0 100644 --- a/google_apis/gaia/gaia_auth_util.h +++ b/google_apis/gaia/gaia_auth_util.h
@@ -52,6 +52,10 @@ // Extract the domain part from the canonical form of the given email. std::string ExtractDomainName(const std::string& email); +// Returns whether the user's email is Google internal. This check is meant +// to be used sparingly since it ship Googler-only code to all users. +bool IsGoogleInternalAccountEmail(const std::string& email); + bool IsGaiaSignonRealm(const GURL& url); // Parses JSON data returned by /ListAccounts call, returning a vector of
diff --git a/google_apis/gaia/gaia_auth_util_unittest.cc b/google_apis/gaia/gaia_auth_util_unittest.cc index 9eb1308..d25a469 100644 --- a/google_apis/gaia/gaia_auth_util_unittest.cc +++ b/google_apis/gaia/gaia_auth_util_unittest.cc
@@ -84,6 +84,11 @@ EXPECT_EQ(domain, ExtractDomainName("who@EXAMPLE.cOm")); } +TEST(GaiaAuthUtilTest, IsGoogleInternalAccountEmail) { + EXPECT_TRUE(IsGoogleInternalAccountEmail("hello@google.com")); + EXPECT_FALSE(IsGoogleInternalAccountEmail("internal@gmail.com")); +} + TEST(GaiaAuthUtilTest, SanitizeMissingDomain) { EXPECT_EQ("nodomain@gmail.com", SanitizeEmail("nodomain")); }
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 7720bd67..8b5960d8 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -2972,8 +2972,8 @@ 'uint32_t counts_shm_id, uint32_t counts_shm_offset, ' 'uint32_t instance_counts_shm_id, ' 'uint32_t instance_counts_shm_offset, GLsizei drawcount', - 'extension': 'WEBGL_multi_draw_instanced', - 'extension_flag': 'webgl_multi_draw_instanced', + 'extension': 'WEBGL_multi_draw', + 'extension_flag': 'webgl_multi_draw', 'data_transfer_methods': ['shm'], 'size_args': { 'firsts': 'drawcount * sizeof(GLint)', @@ -3012,8 +3012,8 @@ 'uint32_t offsets_shm_id, uint32_t offsets_shm_offset, ' 'uint32_t instance_counts_shm_id, ' 'uint32_t instance_counts_shm_offset, GLsizei drawcount', - 'extension': 'WEBGL_multi_draw_instanced', - 'extension_flag': 'webgl_multi_draw_instanced', + 'extension': 'WEBGL_multi_draw', + 'extension_flag': 'webgl_multi_draw', 'data_transfer_methods': ['shm'], 'size_args': { 'counts': 'drawcount * sizeof(GLsizei)', @@ -3032,8 +3032,8 @@ }, 'MultiDrawArraysInstancedWEBGL': { 'type': 'NoCommand', - 'extension': 'WEBGL_multi_draw_instanced', - 'extension_flag': 'webgl_multi_draw_instanced', + 'extension': 'WEBGL_multi_draw', + 'extension_flag': 'webgl_multi_draw', }, 'MultiDrawElementsWEBGL': { 'type': 'NoCommand', @@ -3042,8 +3042,8 @@ }, 'MultiDrawElementsInstancedWEBGL': { 'type': 'NoCommand', - 'extension': 'WEBGL_multi_draw_instanced', - 'extension_flag': 'webgl_multi_draw_instanced', + 'extension': 'WEBGL_multi_draw', + 'extension_flag': 'webgl_multi_draw', }, 'OverlayPromotionHintCHROMIUM': { 'decoder_func': 'DoOverlayPromotionHintCHROMIUM',
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index d6c628c..b3dd53ad 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc
@@ -1565,14 +1565,12 @@ if (!is_passthrough_cmd_decoder_ || gfx::HasExtension(extensions, "GL_ANGLE_multi_draw")) { - feature_flags_.webgl_multi_draw = true; - AddExtensionString("GL_WEBGL_multi_draw"); if (gfx::HasExtension(extensions, "GL_ANGLE_instanced_arrays") || feature_flags_.angle_instanced_arrays || gl_version_info_->is_es3 || gl_version_info_->is_desktop_core_profile) { - feature_flags_.webgl_multi_draw_instanced = true; - AddExtensionString("GL_WEBGL_multi_draw_instanced"); + feature_flags_.webgl_multi_draw = true; + AddExtensionString("GL_WEBGL_multi_draw"); } }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 1b24f828..1fb8be6e 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -137,8 +137,6 @@ const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers"; const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod"; const char kWEBGLMultiDrawExtension[] = "GL_WEBGL_multi_draw"; -const char kWEBGLMultiDrawInstancedExtension[] = - "GL_WEBGL_multi_draw_instanced"; const char kOESFboRenderMipmapExtension[] = "GL_OES_fbo_render_mipmap"; template <typename MANAGER_TYPE, typename OBJECT_TYPE> @@ -2698,7 +2696,6 @@ bool draw_buffers_explicitly_enabled_; bool shader_texture_lod_explicitly_enabled_; bool multi_draw_explicitly_enabled_; - bool multi_draw_instanced_explicitly_enabled_; bool compile_shader_always_succeeds_; @@ -3466,7 +3463,6 @@ draw_buffers_explicitly_enabled_(false), shader_texture_lod_explicitly_enabled_(false), multi_draw_explicitly_enabled_(false), - multi_draw_instanced_explicitly_enabled_(false), compile_shader_always_succeeds_(false), lose_context_when_out_of_memory_(false), should_use_native_gmb_for_backbuffer_(false), @@ -4454,9 +4450,7 @@ if (shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) { resources.ANGLE_multi_draw = - (multi_draw_explicitly_enabled_ && features().webgl_multi_draw) || - (multi_draw_instanced_explicitly_enabled_ && - features().webgl_multi_draw_instanced); + multi_draw_explicitly_enabled_ && features().webgl_multi_draw; } if (((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) && @@ -9748,7 +9742,7 @@ if (workarounds().clear_uniforms_before_first_program_use) program_manager()->ClearUniforms(program); } - if (features().webgl_multi_draw || features().webgl_multi_draw_instanced) + if (features().webgl_multi_draw) program_manager()->UpdateDrawIDUniformLocation(program); } @@ -11736,7 +11730,7 @@ *static_cast< const volatile gles2::cmds::MultiDrawArraysInstancedCHROMIUM*>( cmd_data); - if (!features().webgl_multi_draw_instanced) { + if (!features().webgl_multi_draw) { return error::kUnknownCommand; } @@ -11823,7 +11817,7 @@ *static_cast< const volatile gles2::cmds::MultiDrawElementsInstancedCHROMIUM*>( cmd_data); - if (!features().webgl_multi_draw_instanced) { + if (!features().webgl_multi_draw) { return error::kUnknownCommand; } @@ -13910,8 +13904,6 @@ extension_set.erase(kEXTShaderTextureLodExtension); if (!multi_draw_explicitly_enabled_) extension_set.erase(kWEBGLMultiDrawExtension); - if (!multi_draw_instanced_explicitly_enabled_) - extension_set.erase(kWEBGLMultiDrawInstancedExtension); } if (supports_post_sub_buffer_) extension_set.insert("GL_CHROMIUM_post_sub_buffer"); @@ -16802,7 +16794,6 @@ bool desire_draw_buffers = false; bool desire_shader_texture_lod = false; bool desire_multi_draw = false; - bool desire_multi_draw_instanced = false; if (feature_info_->context_type() == CONTEXT_TYPE_WEBGL1) { desire_standard_derivatives = feature_str.find("GL_OES_standard_derivatives ") != std::string::npos; @@ -16818,23 +16809,19 @@ if (feature_info_->IsWebGLContext()) { desire_multi_draw = feature_str.find("GL_WEBGL_multi_draw ") != std::string::npos; - desire_multi_draw_instanced = - feature_str.find("GL_WEBGL_multi_draw_instanced ") != std::string::npos; } if (desire_standard_derivatives != derivatives_explicitly_enabled_ || desire_fbo_render_mipmap != fbo_render_mipmap_explicitly_enabled_ || desire_frag_depth != frag_depth_explicitly_enabled_ || desire_draw_buffers != draw_buffers_explicitly_enabled_ || desire_shader_texture_lod != shader_texture_lod_explicitly_enabled_ || - desire_multi_draw != multi_draw_explicitly_enabled_ || - desire_multi_draw_instanced != multi_draw_instanced_explicitly_enabled_) { + desire_multi_draw != multi_draw_explicitly_enabled_) { derivatives_explicitly_enabled_ |= desire_standard_derivatives; fbo_render_mipmap_explicitly_enabled_ |= desire_fbo_render_mipmap; frag_depth_explicitly_enabled_ |= desire_frag_depth; draw_buffers_explicitly_enabled_ |= desire_draw_buffers; shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod; multi_draw_explicitly_enabled_ |= desire_multi_draw; - multi_draw_instanced_explicitly_enabled_ |= desire_multi_draw_instanced; DestroyShaderTranslator(); }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc index d1600cd..ee418d31 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
@@ -1842,7 +1842,7 @@ *static_cast< const volatile gles2::cmds::MultiDrawArraysInstancedCHROMIUM*>( cmd_data); - if (!features().webgl_multi_draw_instanced) { + if (!features().webgl_multi_draw) { return error::kUnknownCommand; } @@ -1930,7 +1930,7 @@ *static_cast< const volatile gles2::cmds::MultiDrawElementsInstancedCHROMIUM*>( cmd_data); - if (!features().webgl_multi_draw_instanced) { + if (!features().webgl_multi_draw) { return error::kUnknownCommand; }
diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc index 61dcf1f..1cee0c3a 100644 --- a/media/base/pipeline_impl_unittest.cc +++ b/media/base/pipeline_impl_unittest.cc
@@ -28,7 +28,6 @@ #include "media/base/text_renderer.h" #include "media/base/text_track_config.h" #include "media/base/time_delta_interpolator.h" -#include "testing/gmock_mutant.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/size.h" @@ -37,7 +36,6 @@ using ::base::test::RunOnceClosure; using ::testing::_; using ::testing::AnyNumber; -using ::testing::CreateFunctor; using ::testing::DeleteArg; using ::testing::DoAll; using ::testing::Invoke; @@ -146,28 +144,18 @@ protected: // Sets up expectations to allow the demuxer to initialize. - typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector; - void SetDemuxerExpectations(MockDemuxerStreamVector* streams, - const base::TimeDelta& duration) { + void SetDemuxerExpectations(base::TimeDelta duration) { EXPECT_CALL(callbacks_, OnDurationChange()); EXPECT_CALL(*demuxer_, OnInitialize(_, _)) .WillOnce(DoAll(SaveArg<0>(&demuxer_host_), SetDemuxerProperties(duration), PostCallback<1>(PIPELINE_OK))); - - // Configure the demuxer to return the streams. - std::vector<DemuxerStream*> mock_streams; - for (size_t i = 0; i < streams->size(); ++i) { - DemuxerStream* stream = (*streams)[i]; - mock_streams.push_back(stream); - } - EXPECT_CALL(*demuxer_, GetAllStreams()) - .WillRepeatedly(Return(mock_streams)); + EXPECT_CALL(*demuxer_, GetAllStreams()).WillRepeatedly(Return(streams_)); } - void SetDemuxerExpectations(MockDemuxerStreamVector* streams) { + void SetDemuxerExpectations() { // Initialize with a default non-zero duration. - SetDemuxerExpectations(streams, base::TimeDelta::FromSeconds(10)); + SetDemuxerExpectations(base::TimeDelta::FromSeconds(10)); } std::unique_ptr<StrictMock<MockDemuxerStream>> CreateStream( @@ -178,7 +166,7 @@ } // Sets up expectations to allow the renderer to initialize. - void SetRendererExpectations() { + void ExpectRendererInitialization() { EXPECT_CALL(*renderer_, OnInitialize(_, _, _)) .WillOnce( DoAll(SaveArg<1>(&renderer_client_), PostCallback<2>(PIPELINE_OK))); @@ -219,6 +207,10 @@ if (start_status == PIPELINE_OK) { EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_)); + + if (start_type == Pipeline::StartType::kNormal) + ExpectRendererInitialization(); + if (post_start_status == PostStartStatus::kNormal) SetRendererPostStartExpectations(); } @@ -235,6 +227,7 @@ void CreateAudioStream() { audio_stream_ = CreateStream(DemuxerStream::AUDIO); + streams_.push_back(audio_stream_.get()); } void CreateVideoStream(bool is_encrypted = false) { @@ -242,13 +235,16 @@ video_stream_->set_video_decoder_config( is_encrypted ? TestVideoConfig::NormalEncrypted() : TestVideoConfig::Normal()); + streams_.push_back(video_stream_.get()); + } + + void CreateAudioAndVideoStream() { + CreateAudioStream(); + CreateVideoStream(); } void CreateEncryptedVideoStream() { CreateVideoStream(true); } - MockDemuxerStream* audio_stream() { return audio_stream_.get(); } - MockDemuxerStream* video_stream() { return video_stream_.get(); } - void SetCdmAndExpect(bool expected_result) { EXPECT_CALL(*renderer_, OnSetCdm(_, _)).WillOnce(RunOnceCallback<1>(true)); EXPECT_CALL(callbacks_, OnCdmAttached(expected_result)); @@ -307,7 +303,7 @@ } void ExpectResume(const base::TimeDelta& seek_time) { - SetRendererExpectations(); + ExpectRendererInitialization(); EXPECT_CALL(*demuxer_, OnSeek(seek_time, _)) .WillOnce(RunOnceCallback<1>(PIPELINE_OK)); EXPECT_CALL(*renderer_, SetPlaybackRate(_)); @@ -362,6 +358,7 @@ StrictMock<MockRenderer>* renderer_; std::unique_ptr<StrictMock<MockDemuxerStream>> audio_stream_; std::unique_ptr<StrictMock<MockDemuxerStream>> video_stream_; + std::vector<DemuxerStream*> streams_; RendererClient* renderer_client_; VideoDecoderConfig video_decoder_config_; PipelineMetadata metadata_; @@ -433,10 +430,8 @@ TEST_F(PipelineImplTest, StartSuspendedAndResumeAudioOnly) { CreateAudioStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); + SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000)); - SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000)); StartPipelineAndExpect(PIPELINE_OK, Pipeline::StartType::kSuspendAfterMetadataForAudioOnly, PostStartStatus::kSuspended); @@ -449,13 +444,9 @@ } TEST_F(PipelineImplTest, StartSuspendedAndResumeAudioVideo) { - CreateAudioStream(); - CreateVideoStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - streams.push_back(video_stream()); + CreateAudioAndVideoStream(); + SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000)); - SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000)); StartPipelineAndExpect(PIPELINE_OK, Pipeline::StartType::kSuspendAfterMetadata, PostStartStatus::kSuspended); @@ -468,14 +459,13 @@ } TEST_F(PipelineImplTest, StartSuspendedFailsOnVideoWithAudioOnlyExpectation) { - CreateAudioStream(); - CreateVideoStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - streams.push_back(video_stream()); + CreateAudioAndVideoStream(); + SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000)); - SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000)); - SetRendererExpectations(); + // StartType kSuspendAfterMetadataForAudioOnly only applies to AudioOnly. + // Since this playback has video, renderer will be initialized and the + // pipeline is not suspended. + ExpectRendererInitialization(); StartPipelineAndExpect(PIPELINE_OK, Pipeline::StartType::kSuspendAfterMetadataForAudioOnly, PostStartStatus::kNormal); @@ -484,11 +474,7 @@ TEST_F(PipelineImplTest, DemuxerErrorDuringStop) { CreateAudioStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); base::RunLoop().RunUntilIdle(); @@ -509,11 +495,7 @@ TEST_F(PipelineImplTest, AudioStream) { CreateAudioStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); EXPECT_TRUE(metadata_.has_audio); @@ -522,11 +504,7 @@ TEST_F(PipelineImplTest, VideoStream) { CreateVideoStream(); - MockDemuxerStreamVector streams; - streams.push_back(video_stream()); - - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); EXPECT_FALSE(metadata_.has_audio); @@ -534,14 +512,8 @@ } TEST_F(PipelineImplTest, AudioVideoStream) { - CreateAudioStream(); - CreateVideoStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - streams.push_back(video_stream()); - - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + CreateAudioAndVideoStream(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); EXPECT_TRUE(metadata_.has_audio); @@ -550,20 +522,15 @@ TEST_F(PipelineImplTest, EncryptedStream_SetCdmBeforeStart) { CreateEncryptedVideoStream(); - MockDemuxerStreamVector streams; - streams.push_back(video_stream()); - SetDemuxerExpectations(&streams); + SetDemuxerExpectations(); SetCdmAndExpect(true); - SetRendererExpectations(); StartPipelineAndExpect(PIPELINE_OK); } TEST_F(PipelineImplTest, EncryptedStream_SetCdmAfterStart) { CreateEncryptedVideoStream(); - MockDemuxerStreamVector streams; - streams.push_back(video_stream()); - SetDemuxerExpectations(&streams); + SetDemuxerExpectations(); // Demuxer initialization and metadata reporting don't wait for CDM. EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_)); @@ -576,21 +543,15 @@ base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_))); run_loop.Run(); - SetRendererExpectations(); + ExpectRendererInitialization(); EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK)); SetRendererPostStartExpectations(); SetCdmAndExpect(true); } TEST_F(PipelineImplTest, Seek) { - CreateAudioStream(); - CreateVideoStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - streams.push_back(video_stream()); - - SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000)); - SetRendererExpectations(); + CreateAudioAndVideoStream(); + SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000)); // Initialize then seek! StartPipelineAndExpect(PIPELINE_OK); @@ -603,11 +564,7 @@ TEST_F(PipelineImplTest, SeekAfterError) { CreateAudioStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - - SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000)); - SetRendererExpectations(); + SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000)); // Initialize then seek! StartPipelineAndExpect(PIPELINE_OK); @@ -625,14 +582,8 @@ } TEST_F(PipelineImplTest, SuspendResume) { - CreateAudioStream(); - CreateVideoStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - streams.push_back(video_stream()); - - SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000)); - SetRendererExpectations(); + CreateAudioAndVideoStream(); + SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000)); StartPipelineAndExpect(PIPELINE_OK); @@ -661,11 +612,7 @@ TEST_F(PipelineImplTest, SetVolume) { CreateAudioStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + SetDemuxerExpectations(); // The audio renderer should receive a call to SetVolume(). float expected = 0.5f; @@ -679,12 +626,8 @@ TEST_F(PipelineImplTest, Properties) { CreateVideoStream(); - MockDemuxerStreamVector streams; - streams.push_back(video_stream()); - - const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100); - SetDemuxerExpectations(&streams, kDuration); - SetRendererExpectations(); + const auto kDuration = base::TimeDelta::FromSeconds(100); + SetDemuxerExpectations(kDuration); StartPipelineAndExpect(PIPELINE_OK); EXPECT_EQ(kDuration.ToInternalValue(), @@ -694,12 +637,8 @@ TEST_F(PipelineImplTest, GetBufferedTimeRanges) { CreateVideoStream(); - MockDemuxerStreamVector streams; - streams.push_back(video_stream()); - - const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100); - SetDemuxerExpectations(&streams, kDuration); - SetRendererExpectations(); + const auto kDuration = base::TimeDelta::FromSeconds(100); + SetDemuxerExpectations(kDuration); StartPipelineAndExpect(PIPELINE_OK); RunBufferedTimeRangesTest(kDuration / 8); @@ -726,14 +665,8 @@ } TEST_F(PipelineImplTest, EndedCallback) { - CreateAudioStream(); - CreateVideoStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - streams.push_back(video_stream()); - - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + CreateAudioAndVideoStream(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); // The ended callback shouldn't run until all renderers have ended. @@ -744,11 +677,7 @@ TEST_F(PipelineImplTest, ErrorDuringSeek) { CreateAudioStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); double playback_rate = 1.0; @@ -794,17 +723,14 @@ TEST_F(PipelineImplTest, NoMessageDuringTearDownFromError) { CreateAudioStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); // Trigger additional requests on the pipeline during tear down from error. - base::Callback<void(PipelineStatus)> cb = - base::Bind(&TestNoCallsAfterError, pipeline_.get(), &task_environment_); - ON_CALL(callbacks_, OnError(_)).WillByDefault(Invoke(CreateFunctor(cb))); + ON_CALL(callbacks_, OnError(_)) + .WillByDefault(Invoke([=](PipelineStatus status) { + TestNoCallsAfterError(pipeline_.get(), &task_environment_, status); + })); base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5); @@ -825,10 +751,7 @@ TEST_F(PipelineImplTest, DestroyAfterStop) { CreateAudioStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); ExpectDemuxerStop(); @@ -837,14 +760,8 @@ } TEST_F(PipelineImplTest, Underflow) { - CreateAudioStream(); - CreateVideoStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - streams.push_back(video_stream()); - - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + CreateAudioAndVideoStream(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); // Simulate underflow. @@ -865,10 +782,7 @@ start_time_ = base::TimeDelta::FromSeconds(1); EXPECT_CALL(*demuxer_, GetStartTime()).WillRepeatedly(Return(start_time_)); CreateAudioStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); ExpectDemuxerStop(); pipeline_->Stop(); @@ -877,10 +791,7 @@ TEST_F(PipelineImplTest, GetMediaTime) { CreateAudioStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); // Pipeline should report the same media time returned by the renderer. @@ -901,10 +812,7 @@ // to return the pre-seek time). Verifies fix for http://crbug.com/675556 TEST_F(PipelineImplTest, GetMediaTimeAfterSeek) { CreateAudioStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); // Pipeline should report the same media time returned by the renderer. @@ -938,10 +846,7 @@ TEST_F(PipelineImplTest, RendererErrorsReset) { // Basic setup CreateAudioStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); // Trigger two errors. The second error will be ignored. @@ -958,8 +863,7 @@ base::RunLoop().RunUntilIdle(); ResetRenderer(); - SetDemuxerExpectations(&streams); - SetRendererExpectations(); + SetDemuxerExpectations(); StartPipelineAndExpect(PIPELINE_OK); // New errors should propagate and not be ignored. @@ -1049,10 +953,7 @@ CreateAudioStream(); CreateVideoStream(); - MockDemuxerStreamVector streams; - streams.push_back(audio_stream()); - streams.push_back(video_stream()); - SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000)); + SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000)); if (state == kInitRenderer) { if (stop_or_error == kStop) {
diff --git a/media/base/video_frame_metadata.h b/media/base/video_frame_metadata.h index 86207131..eccadaa 100644 --- a/media/base/video_frame_metadata.h +++ b/media/base/video_frame_metadata.h
@@ -162,9 +162,21 @@ TOP_CONTROLS_SHOWN_RATIO, // If present, this field represents the local time at which the VideoFrame - // was decoded from whichever format it was encoded in. - // Use Get/SetTimeTicks() for this key. - DECODE_TIME, + // was decoded from whichever format it was encoded in. Sometimes only + // DECODE_END_TIME will be present. Use Get/SetTimeTicks() for this key. + DECODE_BEGIN_TIME, + DECODE_END_TIME, + + // If present, this field represents the elapsed time from the submission of + // the encoded packet with the same PTS as this frame to the decoder until + // the decoded frame was ready for presentation. Stored as base::TimeDelta. + PROCESSING_TIME, + + // The RTP timestamp associated with this video frame. Stored as a double + // since base::DictionaryValue doesn't have a uint32_t type. + // + // https://w3c.github.io/webrtc-pc/#dom-rtcrtpcontributingsource + RTP_TIMESTAMP, NUM_KEYS };
diff --git a/media/filters/decoder_stream.cc b/media/filters/decoder_stream.cc index 6ed36f6..ec3ccf0a 100644 --- a/media/filters/decoder_stream.cc +++ b/media/filters/decoder_stream.cc
@@ -630,6 +630,8 @@ return; } + traits_->OnOutputReady(output.get()); + if (read_cb_) { // If |ready_outputs_| was non-empty, the read would have already been // satisifed by Read(). @@ -987,6 +989,7 @@ DCHECK(!unprepared_outputs_.empty()); DCHECK(preparing_output_); + traits_->OnOutputReady(output.get()); CompletePrepare(output.get()); unprepared_outputs_.pop_front(); if (!read_cb_)
diff --git a/media/filters/decoder_stream_traits.cc b/media/filters/decoder_stream_traits.cc index e917f92..e380723f 100644 --- a/media/filters/decoder_stream_traits.cc +++ b/media/filters/decoder_stream_traits.cc
@@ -112,6 +112,9 @@ audio_ts_validator_.reset(new AudioTimestampValidator(config, media_log_)); } +void DecoderStreamTraits<DemuxerStream::AUDIO>::OnOutputReady( + OutputType* buffer) {} + // Video decoder stream traits implementation. // static @@ -201,6 +204,7 @@ frame_metadata_[buffer.timestamp()] = { buffer.discard_padding().first == kInfiniteDuration, // should_drop buffer.duration(), // duration + base::TimeTicks::Now(), // decode_begin_time }; if (!buffer.is_key_frame()) @@ -220,11 +224,6 @@ PostDecodeAction DecoderStreamTraits<DemuxerStream::VIDEO>::OnDecodeDone( OutputType* buffer) { - // Add a timestamp here (after decoding completed) to enable buffering delay - // measurements down the line. - buffer->metadata()->SetTimeTicks(media::VideoFrameMetadata::DECODE_TIME, - base::TimeTicks::Now()); - auto it = frame_metadata_.find(buffer->timestamp()); // If the frame isn't in |frame_metadata_| it probably was erased below on a @@ -234,6 +233,12 @@ if (it == frame_metadata_.end()) return PostDecodeAction::DELIVER; + // Add a timestamp here to enable buffering delay measurements down the line. + buffer->metadata()->SetTimeTicks(VideoFrameMetadata::DECODE_BEGIN_TIME, + it->second.decode_begin_time); + buffer->metadata()->SetTimeTicks(VideoFrameMetadata::DECODE_END_TIME, + base::TimeTicks::Now()); + auto action = it->second.should_drop ? PostDecodeAction::DROP : PostDecodeAction::DELIVER; @@ -252,4 +257,16 @@ return action; } +void DecoderStreamTraits<DemuxerStream::VIDEO>::OnOutputReady( + OutputType* buffer) { + base::TimeTicks decode_begin_time; + if (!buffer->metadata()->GetTimeTicks(VideoFrameMetadata::DECODE_BEGIN_TIME, + &decode_begin_time)) { + return; + } + // Tag buffer with elapsed time since creation. + buffer->metadata()->SetTimeDelta(VideoFrameMetadata::PROCESSING_TIME, + base::TimeTicks::Now() - decode_begin_time); +} + } // namespace media
diff --git a/media/filters/decoder_stream_traits.h b/media/filters/decoder_stream_traits.h index aef034b6..c3a60d9c 100644 --- a/media/filters/decoder_stream_traits.h +++ b/media/filters/decoder_stream_traits.h
@@ -62,6 +62,7 @@ void OnDecode(const DecoderBuffer& buffer); PostDecodeAction OnDecodeDone(OutputType* buffer); void OnStreamReset(DemuxerStream* stream); + void OnOutputReady(OutputType* output); private: void OnConfigChanged(const AudioDecoderConfig& config); @@ -107,6 +108,7 @@ void OnDecode(const DecoderBuffer& buffer); PostDecodeAction OnDecodeDone(OutputType* buffer); void OnStreamReset(DemuxerStream* stream); + void OnOutputReady(OutputType* output); private: base::TimeDelta last_keyframe_timestamp_; @@ -116,6 +118,7 @@ struct FrameMetadata { bool should_drop = false; base::TimeDelta duration = kNoTimestamp; + base::TimeTicks decode_begin_time; }; base::flat_map<base::TimeDelta, FrameMetadata> frame_metadata_;
diff --git a/media/filters/video_decoder_stream_unittest.cc b/media/filters/video_decoder_stream_unittest.cc index 9e40961..ed18480 100644 --- a/media/filters/video_decoder_stream_unittest.cc +++ b/media/filters/video_decoder_stream_unittest.cc
@@ -43,6 +43,7 @@ const int kNumConfigs = 4; const int kNumBuffersInOneConfig = 5; +constexpr base::TimeDelta kPrepareDelay = base::TimeDelta::FromMilliseconds(5); static std::string GetDecoderName(int i) { return std::string("VideoDecoder") + base::NumberToString(i); @@ -144,6 +145,15 @@ base::BindOnce(std::move(output_ready_cb), std::move(frame))); } + void PrepareFrameWithDelay( + scoped_refptr<VideoFrame> frame, + VideoDecoderStream::OutputReadyCB output_ready_cb) { + task_environment_.FastForwardBy(kPrepareDelay); + task_environment_.GetMainThreadTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(std::move(output_ready_cb), std::move(frame))); + } + void OnBytesDecoded(int count) { num_decoded_bytes_unreported_ += count; } // Callback to create a list of decoders for the DecoderSelector to select @@ -463,7 +473,8 @@ SatisfyPendingCallback(DECODER_REINIT); } - base::test::SingleThreadTaskEnvironment task_environment_; + base::test::SingleThreadTaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; StrictMock<MockMediaLog> media_log_; std::unique_ptr<VideoDecoderStream> video_decoder_stream_; @@ -571,6 +582,56 @@ Read(); } +TEST_P(VideoDecoderStreamTest, Read_ProperMetadata) { + // For testing simplicity, omit parallel decode tests with a delay in frames. + if (GetParam().parallel_decoding > 1 && GetParam().decoding_delay > 0) + return; + + if (GetParam().has_prepare) { + // Override the basic PrepareFrame() for a version that moves the MockTime + // by kPrepareDelay. This simulates real work done (e.g. YUV conversion). + video_decoder_stream_->SetPrepareCB( + base::BindRepeating(&VideoDecoderStreamTest::PrepareFrameWithDelay, + base::Unretained(this))); + } + + constexpr base::TimeDelta kDecodeDelay = + base::TimeDelta::FromMilliseconds(10); + + Initialize(); + + // Simulate time elapsed by the decoder. + EnterPendingState(DECODER_DECODE); + task_environment_.FastForwardBy(kDecodeDelay); + + SatisfyPendingCallback(DECODER_DECODE); + + EXPECT_TRUE(frame_read_); + + auto* metadata = frame_read_->metadata(); + + // Verify the decoding metadata is accurate. + base::TimeTicks decode_start; + EXPECT_TRUE(metadata->GetTimeTicks(VideoFrameMetadata::DECODE_BEGIN_TIME, + &decode_start)); + + base::TimeTicks decode_end; + EXPECT_TRUE( + metadata->GetTimeTicks(VideoFrameMetadata::DECODE_END_TIME, &decode_end)); + + EXPECT_EQ(decode_end - decode_start, kDecodeDelay); + + // Verify the processing metadata is accurate. + const base::TimeDelta expected_processing_time = + GetParam().has_prepare ? (kDecodeDelay + kPrepareDelay) : kDecodeDelay; + + base::TimeDelta processing_time; + EXPECT_TRUE(metadata->GetTimeDelta(VideoFrameMetadata::PROCESSING_TIME, + &processing_time)); + + EXPECT_EQ(processing_time, expected_processing_time); +} + TEST_P(VideoDecoderStreamTest, Read_BlockedDemuxer) { Initialize(); demuxer_stream_->HoldNextRead();
diff --git a/media/gpu/android/media_codec_video_decoder.cc b/media/gpu/android/media_codec_video_decoder.cc index decc3e5..293c10b9 100644 --- a/media/gpu/android/media_codec_video_decoder.cc +++ b/media/gpu/android/media_codec_video_decoder.cc
@@ -246,6 +246,10 @@ TRACE_EVENT0("media", "MediaCodecVideoDecoder::Destroy"); // Cancel pending callbacks. + // + // WARNING: This will lose the callback we've given to MediaCodecBridge for + // asynchronous notifications; so we must not leave this function with any + // work necessary from StartTimerOrPumpCodec(). weak_factory_.InvalidateWeakPtrs(); if (media_crypto_context_) { @@ -265,6 +269,10 @@ codec_allocator_weak_factory_.InvalidateWeakPtrs(); CancelPendingDecodes(DecodeStatus::ABORTED); StartDrainingCodec(DrainType::kForDestroy); + + // Per the WARNING above. Validate that no draining work remains. + if (using_async_api_) + DCHECK(!drain_type_.has_value()); } void MediaCodecVideoDecoder::Initialize(const VideoDecoderConfig& config, @@ -1021,7 +1029,7 @@ // TODO(watk): Strongly consider blacklisting VP8 (or specific MediaCodecs) // instead. Draining is responsible for a lot of complexity. if (decoder_config_.codec() != kCodecVP8 || !codec_ || codec_->IsFlushed() || - codec_->IsDrained()) { + codec_->IsDrained() || using_async_api_) { // If the codec isn't already drained or flushed, then we have to remember // that we owe it a flush. We also have to remember not to deliver any // output buffers that might still be in progress in the codec.
diff --git a/media/mojo/clients/mojo_cdm.cc b/media/mojo/clients/mojo_cdm.cc index a777252..6968290 100644 --- a/media/mojo/clients/mojo_cdm.cc +++ b/media/mojo/clients/mojo_cdm.cc
@@ -69,7 +69,6 @@ const SessionExpirationUpdateCB& session_expiration_update_cb) : remote_cdm_(std::move(remote_cdm)), interface_factory_(interface_factory), - client_binding_(this), cdm_id_(CdmContext::kInvalidCdmId), session_message_cb_(session_message_cb), session_closed_cb_(session_closed_cb), @@ -81,9 +80,7 @@ DCHECK(session_keys_change_cb_); DCHECK(session_expiration_update_cb_); - mojom::ContentDecryptionModuleClientAssociatedPtrInfo client_ptr_info; - client_binding_.Bind(mojo::MakeRequest(&client_ptr_info)); - remote_cdm_->SetClient(std::move(client_ptr_info)); + remote_cdm_->SetClient(client_receiver_.BindNewEndpointAndPassRemote()); } MojoCdm::~MojoCdm() {
diff --git a/media/mojo/clients/mojo_cdm.h b/media/mojo/clients/mojo_cdm.h index 4534f00..22a867e 100644 --- a/media/mojo/clients/mojo_cdm.h +++ b/media/mojo/clients/mojo_cdm.h
@@ -21,8 +21,7 @@ #include "media/base/cdm_session_tracker.h" #include "media/base/content_decryption_module.h" #include "media/mojo/mojom/content_decryption_module.mojom.h" -#include "mojo/public/cpp/bindings/associated_binding.h" -#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" @@ -142,7 +141,8 @@ mojo::Remote<mojom::ContentDecryptionModule> remote_cdm_; mojom::InterfaceFactory* interface_factory_; - mojo::AssociatedBinding<ContentDecryptionModuleClient> client_binding_; + mojo::AssociatedReceiver<ContentDecryptionModuleClient> client_receiver_{ + this}; // Protects |cdm_id_|, |decryptor_ptr_|, |decryptor_| and // |decryptor_task_runner_| which could be accessed from other threads.
diff --git a/media/mojo/clients/mojo_renderer.cc b/media/mojo/clients/mojo_renderer.cc index 2d54df3..2af9249 100644 --- a/media/mojo/clients/mojo_renderer.cc +++ b/media/mojo/clients/mojo_renderer.cc
@@ -17,7 +17,6 @@ #include "media/mojo/clients/mojo_demuxer_stream_impl.h" #include "media/mojo/common/media_type_converters.h" #include "media/renderers/video_overlay_factory.h" -#include "mojo/public/cpp/bindings/pending_remote.h" namespace media { @@ -30,7 +29,6 @@ video_overlay_factory_(std::move(video_overlay_factory)), video_renderer_sink_(video_renderer_sink), remote_renderer_pending_remote_(std::move(remote_renderer)), - client_binding_(this), media_time_interpolator_(base::DefaultTickClock::GetInstance()) { DVLOG(1) << __func__; } @@ -96,14 +94,12 @@ BindRemoteRendererIfNeeded(); - mojom::RendererClientAssociatedPtrInfo client_ptr_info; - client_binding_.Bind(mojo::MakeRequest(&client_ptr_info)); - // Using base::Unretained(this) is safe because |this| owns // |remote_renderer_|, and the callback won't be dispatched if // |remote_renderer_| is destroyed. remote_renderer_->Initialize( - std::move(client_ptr_info), std::move(stream_proxies), nullptr, + client_receiver_.BindNewEndpointAndPassRemote(), + std::move(stream_proxies), nullptr, base::Bind(&MojoRenderer::OnInitialized, base::Unretained(this), client)); } @@ -113,9 +109,6 @@ BindRemoteRendererIfNeeded(); - mojom::RendererClientAssociatedPtrInfo client_ptr_info; - client_binding_.Bind(mojo::MakeRequest(&client_ptr_info)); - const MediaUrlParams& url_params = media_resource_->GetMediaUrlParams(); // Using base::Unretained(this) is safe because |this| owns @@ -126,7 +119,8 @@ url_params.top_frame_origin, url_params.allow_credentials, url_params.is_hls); remote_renderer_->Initialize( - std::move(client_ptr_info), base::nullopt, std::move(media_url_params), + client_receiver_.BindNewEndpointAndPassRemote(), base::nullopt, + std::move(media_url_params), base::Bind(&MojoRenderer::OnInitialized, base::Unretained(this), client)); }
diff --git a/media/mojo/clients/mojo_renderer.h b/media/mojo/clients/mojo_renderer.h index c8d668a..ab858cc 100644 --- a/media/mojo/clients/mojo_renderer.h +++ b/media/mojo/clients/mojo_renderer.h
@@ -18,7 +18,7 @@ #include "media/base/renderer.h" #include "media/base/time_delta_interpolator.h" #include "media/mojo/mojom/renderer.mojom.h" -#include "mojo/public/cpp/bindings/associated_binding.h" +#include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" @@ -142,8 +142,8 @@ // Remote Renderer, bound to |task_runner_| during Initialize(). mojo::Remote<mojom::Renderer> remote_renderer_; - // Binding for RendererClient, bound to the |task_runner_|. - mojo::AssociatedBinding<RendererClient> client_binding_; + // Receiver for RendererClient, bound to the |task_runner_|. + mojo::AssociatedReceiver<RendererClient> client_receiver_{this}; bool encountered_error_ = false;
diff --git a/media/mojo/clients/mojo_video_decoder.cc b/media/mojo/clients/mojo_video_decoder.cc index 9e67e16..8527ddb 100644 --- a/media/mojo/clients/mojo_video_decoder.cc +++ b/media/mojo/clients/mojo_video_decoder.cc
@@ -125,7 +125,7 @@ writer_capacity_( GetDefaultDecoderBufferConverterCapacity(DemuxerStream::VIDEO)), media_log_service_(media_log), - media_log_binding_(&media_log_service_), + media_log_receiver_(&media_log_service_), request_overlay_info_cb_(request_overlay_info_cb), target_color_space_(target_color_space), video_decoder_implementation_(implementation) { @@ -346,16 +346,6 @@ remote_decoder_.set_disconnect_handler( base::Bind(&MojoVideoDecoder::Stop, base::Unretained(this))); - // Create |client| interface (bound to |this|). - mojo::PendingAssociatedRemote<mojom::VideoDecoderClient> - client_pending_remote; - client_receiver_.Bind( - client_pending_remote.InitWithNewEndpointAndPassReceiver()); - - // Create |media_log| interface (bound to |media_log_service_|). - mojom::MediaLogAssociatedPtrInfo media_log_ptr_info; - media_log_binding_.Bind(mojo::MakeRequest(&media_log_ptr_info)); - // Create |video_frame_handle_releaser| interface receiver, and bind // |mojo_video_frame_handle_releaser_| to it. mojo::PendingRemote<mojom::VideoFrameHandleReleaser> @@ -384,7 +374,8 @@ } remote_decoder_->Construct( - std::move(client_pending_remote), std::move(media_log_ptr_info), + client_receiver_.BindNewEndpointAndPassRemote(), + media_log_receiver_.BindNewEndpointAndPassRemote(), std::move(video_frame_handle_releaser_receiver), std::move(remote_consumer_handle), std::move(command_buffer_id), video_decoder_implementation_, target_color_space_);
diff --git a/media/mojo/clients/mojo_video_decoder.h b/media/mojo/clients/mojo_video_decoder.h index a051471..f0dba794 100644 --- a/media/mojo/clients/mojo_video_decoder.h +++ b/media/mojo/clients/mojo_video_decoder.h
@@ -14,7 +14,6 @@ #include "media/mojo/clients/mojo_media_log_service.h" #include "media/mojo/mojom/video_decoder.mojom.h" #include "media/video/video_decode_accelerator.h" -#include "mojo/public/cpp/bindings/associated_binding.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" @@ -122,7 +121,7 @@ bool has_connection_error_ = false; mojo::AssociatedReceiver<mojom::VideoDecoderClient> client_receiver_{this}; MojoMediaLogService media_log_service_; - mojo::AssociatedBinding<mojom::MediaLog> media_log_binding_; + mojo::AssociatedReceiver<mojom::MediaLog> media_log_receiver_; RequestOverlayInfoCB request_overlay_info_cb_; bool overlay_info_requested_ = false; gfx::ColorSpace target_color_space_;
diff --git a/media/mojo/mojom/renderer.mojom b/media/mojo/mojom/renderer.mojom index 106a850c..4c6ea9a 100644 --- a/media/mojo/mojom/renderer.mojom +++ b/media/mojo/mojom/renderer.mojom
@@ -26,7 +26,7 @@ // via |media_url_params|. Exactly one of |streams| and |media_urls_params| // should be set. // TODO(sandersd): These should be separate methods or a union type. - Initialize(associated RendererClient client, + Initialize(pending_associated_remote<RendererClient> client, array<pending_remote<DemuxerStream>>? streams, MediaUrlParams? media_url_params) => (bool success);
diff --git a/media/mojo/services/media_metrics_provider.h b/media/mojo/services/media_metrics_provider.h index b231e37..4141ad2 100644 --- a/media/mojo/services/media_metrics_provider.h +++ b/media/mojo/services/media_metrics_provider.h
@@ -37,7 +37,9 @@ using RecordAggregateWatchTimeCallback = base::RepeatingCallback<void(base::TimeDelta total_watch_time, - base::TimeDelta time_stamp)>; + base::TimeDelta time_stamp, + bool has_video, + bool has_audio)>; using GetRecordAggregateWatchTimeCallback = base::RepeatingCallback<RecordAggregateWatchTimeCallback(void)>;
diff --git a/media/mojo/services/mojo_renderer_service.cc b/media/mojo/services/mojo_renderer_service.cc index 19a3f5e3..2585bbf5 100644 --- a/media/mojo/services/mojo_renderer_service.cc +++ b/media/mojo/services/mojo_renderer_service.cc
@@ -66,7 +66,7 @@ MojoRendererService::~MojoRendererService() = default; void MojoRendererService::Initialize( - mojom::RendererClientAssociatedPtrInfo client, + mojo::PendingAssociatedRemote<mojom::RendererClient> client, base::Optional<std::vector<mojo::PendingRemote<mojom::DemuxerStream>>> streams, mojom::MediaUrlParamsPtr media_url_params,
diff --git a/media/mojo/services/mojo_renderer_service.h b/media/mojo/services/mojo_renderer_service.h index de05997..1866dd5 100644 --- a/media/mojo/services/mojo_renderer_service.h +++ b/media/mojo/services/mojo_renderer_service.h
@@ -21,6 +21,8 @@ #include "media/base/renderer_client.h" #include "media/mojo/mojom/renderer.mojom.h" #include "media/mojo/services/media_mojo_export.h" +#include "mojo/public/cpp/bindings/associated_remote.h" +#include "mojo/public/cpp/bindings/pending_associated_remote.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" @@ -53,7 +55,7 @@ // mojom::Renderer implementation. void Initialize( - mojom::RendererClientAssociatedPtrInfo client, + mojo::PendingAssociatedRemote<mojom::RendererClient> client, base::Optional<std::vector<mojo::PendingRemote<mojom::DemuxerStream>>> streams, mojom::MediaUrlParamsPtr media_url_params, @@ -123,7 +125,7 @@ base::RepeatingTimer time_update_timer_; base::TimeDelta last_media_time_; - mojom::RendererClientAssociatedPtr client_; + mojo::AssociatedRemote<mojom::RendererClient> client_; // Holds the CdmContextRef to keep the CdmContext alive for the lifetime of // the |renderer_|.
diff --git a/media/mojo/services/watch_time_recorder.cc b/media/mojo/services/watch_time_recorder.cc index e6624be..eaab5c09 100644 --- a/media/mojo/services/watch_time_recorder.cc +++ b/media/mojo/services/watch_time_recorder.cc
@@ -531,10 +531,11 @@ builder.Record(ukm_recorder); } - // Only save the playback if the video contains both video and audio. - if (properties_->has_video && properties_->has_audio && - total_watch_time > base::TimeDelta()) - std::move(record_playback_cb_).Run(total_watch_time, last_timestamp_); + if (total_watch_time > base::TimeDelta()) { + std::move(record_playback_cb_) + .Run(total_watch_time, last_timestamp_, properties_->has_video, + properties_->has_audio); + } ukm_records_.clear(); }
diff --git a/media/mojo/services/watch_time_recorder.h b/media/mojo/services/watch_time_recorder.h index 5e5fd15..837bc11 100644 --- a/media/mojo/services/watch_time_recorder.h +++ b/media/mojo/services/watch_time_recorder.h
@@ -26,7 +26,9 @@ public: using RecordAggregateWatchTimeCallback = base::OnceCallback<void(base::TimeDelta total_watch_time, - base::TimeDelta time_stamp)>; + base::TimeDelta time_stamp, + bool has_video, + bool has_audio)>; WatchTimeRecorder(mojom::PlaybackPropertiesPtr properties, ukm::SourceId source_id,
diff --git a/media/mojo/services/watch_time_recorder_unittest.cc b/media/mojo/services/watch_time_recorder_unittest.cc index 1d60279..fe3ba05 100644 --- a/media/mojo/services/watch_time_recorder_unittest.cc +++ b/media/mojo/services/watch_time_recorder_unittest.cc
@@ -181,7 +181,7 @@ return base::BindRepeating( [](base::WeakPtr<content::RenderFrameHostDelegate> delegate, GURL last_committed_url, base::TimeDelta total_watch_time, - base::TimeDelta time_stamp) { + base::TimeDelta time_stamp, bool has_video, bool has_audio) { // Do nothing as this mock callback will never be called. }, nullptr, GURL());
diff --git a/media/remoting/demuxer_stream_adapter.cc b/media/remoting/demuxer_stream_adapter.cc index f821030..1b5cb6e1 100644 --- a/media/remoting/demuxer_stream_adapter.cc +++ b/media/remoting/demuxer_stream_adapter.cc
@@ -68,8 +68,8 @@ stream_sender_.Bind(std::move(stream_sender_info)); stream_sender_.set_connection_error_handler( - base::Bind(&DemuxerStreamAdapter::OnFatalError, - weak_factory_.GetWeakPtr(), MOJO_PIPE_ERROR)); + base::BindOnce(&DemuxerStreamAdapter::OnFatalError, + weak_factory_.GetWeakPtr(), MOJO_PIPE_ERROR)); } DemuxerStreamAdapter::~DemuxerStreamAdapter() {
diff --git a/media/remoting/receiver.cc b/media/remoting/receiver.cc index 7974141..add7ea47 100644 --- a/media/remoting/receiver.cc +++ b/media/remoting/receiver.cc
@@ -188,9 +188,9 @@ if (time_update_timer_.IsRunning()) return; SendMediaTimeUpdate(); - time_update_timer_.Start( - FROM_HERE, kTimeUpdateInterval, - base::Bind(&Receiver::SendMediaTimeUpdate, weak_factory_.GetWeakPtr())); + time_update_timer_.Start(FROM_HERE, kTimeUpdateInterval, + base::BindRepeating(&Receiver::SendMediaTimeUpdate, + weak_factory_.GetWeakPtr())); } void Receiver::SetVolume(std::unique_ptr<pb::RpcMessage> message) {
diff --git a/media/test/pipeline_integration_test_base.cc b/media/test/pipeline_integration_test_base.cc index f68852bb..b23baf63 100644 --- a/media/test/pipeline_integration_test_base.cc +++ b/media/test/pipeline_integration_test_base.cc
@@ -13,6 +13,7 @@ #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/time/time.h" +#include "build/build_config.h" #include "media/base/media_log.h" #include "media/base/media_switches.h" #include "media/base/media_tracks.h" @@ -125,7 +126,14 @@ }; PipelineIntegrationTestBase::PipelineIntegrationTestBase() - : hashing_enabled_(false), + : +// Use a UI type message loop on macOS, because it doesn't seem to schedule +// callbacks with enough precision to drive our fake audio output. See +// https://crbug.com/1014646 for more details. +#if defined(OS_MACOSX) + task_environment_(base::test::TaskEnvironment::MainThreadType::UI), +#endif + hashing_enabled_(false), clockless_playback_(false), webaudio_attached_(false), mono_output_(false),
diff --git a/net/BUILD.gn b/net/BUILD.gn index c4bed84..2dd32b07 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -3568,6 +3568,8 @@ "tools/quic/quic_simple_server_session_helper.h", "tools/quic/quic_simple_server_socket.cc", "tools/quic/quic_simple_server_socket.h", + "tools/quic/quic_transport_simple_server.cc", + "tools/quic/quic_transport_simple_server.h", "tools/quic/synchronous_host_resolver.cc", "tools/quic/synchronous_host_resolver.h", ] @@ -3613,6 +3615,19 @@ "//third_party/protobuf:protobuf_lite", ] } + executable("quic_transport_simple_server") { + sources = [ + "tools/quic/quic_transport_simple_server_bin.cc", + ] + deps = [ + ":net", + ":simple_quic_tools", + "//base", + "//build/win:default_exe_manifest", + "//third_party/boringssl", + "//third_party/protobuf:protobuf_lite", + ] + } executable("quic_packet_printer") { sources = [ "third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc", @@ -5837,8 +5852,7 @@ "quic/platform/impl/quic_socket_utils_test.cc", "third_party/quiche/src/epoll_server/simple_epoll_server_test.cc", "third_party/quiche/src/quic/core/chlo_extractor_test.cc", - - #"third_party/quiche/src/quic/core/http/end_to_end_test.cc", + "third_party/quiche/src/quic/core/http/end_to_end_test.cc", "third_party/quiche/src/quic/core/http/quic_spdy_client_session_test.cc", "third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc", "third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base_test.cc",
diff --git a/net/data/proxy_resolver_perftest/no-ads.pac b/net/data/proxy_resolver_perftest/no-ads.pac deleted file mode 100644 index e55fa0f..0000000 --- a/net/data/proxy_resolver_perftest/no-ads.pac +++ /dev/null
@@ -1,1362 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// John's No-ADS proxy auto configuration script -// http://www.schooner.com/~loverso/no-ads/ -// loverso@schooner.com -// Questions/help web forum at http://www.network54.com/Hide/Forum/223428 -// -// Copyright 1996-2004, John LoVerso. All Rights Reserved. -// -// Permission is given to use and distribute this file, as long as this -// copyright message and author notice are not removed. -// -// No responsibility is taken for any errors on inaccuracies inherent -// either to the comments or the code of this program, but if reported -// to me, then an attempt will be made to fix them. -// -// ("no monies exchanged" in Copyright clause removed 11/2001) -// -var noadsver = "$Id: no-ads.pac,v 5.70 2007/05/11 16:56:01 loverso Exp loverso $"; - -// **** -// **** If you do not use a proxy to access the Internet, then the following -// **** line is already fine. -// **** -// **** If you use an a proxy to access the Internet, as required by your -// **** ISP or firewall, then change the line below, replacing -// **** "DIRECT" with "PROXY hostname:port", using the correct hostname:port -// **** for your proxy server. -// **** -var normal = "DIRECT"; - -// *** -// *** If you are not using a blackhold proxy, then you can leave this -// *** setting as is. -// *** -// *** Otherwise, update the next line with the correct hostname:port -// *** of your blackhole proxy server. If you are using Larry Wang's -// *** BHP for Windows, you need to change the "0.0.0.0" to "127.0.0.1" -// *** -var blackhole = "PROXY 0.0.0.0:3421"; - -// *** -// *** If you need a different proxy to access local/internal hosts vs. -// *** the rest of the Internet, set 'localproxy' to that value. Otherwise, -// *** 'localproxy' defaults to the same value as 'normal', so you do -// *** not need to change anything in the normal case. -// *** -// *** Some typical cases: -// *** - 'normal' might be one proxy, and 'localproxy' might be another -// *** - 'normal' might be a proxy, and 'localproxy' might be "DIRECT" -// *** -// *** You will also need to change the LOCAL section below by adding -// *** rules to match your local/internal hosts. -// *** -var localproxy = normal; - -// *** -// *** 'bypass' is the preferred proxy setting for when no-ads is inactive. -// *** Either use '= normal' or '= localproxy' (or perhaps just "DIRECT"). -// *** This only matters when you need to use a localproxy. -// *** (You probably don't need to care about this) -// *** -var bypass = normal; - -/////////////////////////////////////////////////////////////////////////////// -// -// This simple kludge uses a mechanism built into most browsers (IE, Netscape, -// Mozilla, Firefox, and Opera) on most platforms to block connections to -// banner ad servers. -// -// This mechanism uses the "proxy auto configuration" to blackhole requests -// to load ad images without forcing all your traffic through an ad-blocking -// proxy server. Of course, unlike ad-blocking proxy servers, this does not -// otherwise not strip cookies. -// -// "Proxy auto configuration" invokes the JavaScript FindProxyForURL function -// below each time your browser requests a URL. This works even if you have -// JavaScript otherwise disabled in your browser! (Which you should!) -// - -// -// Send me your additions or comments. I'll credit you in the file. -// (But I've removed all email addresses to stop spam harvesters). -// - - -/////////////////////////////////////////////////////////////////////////////// -// -// These are the basic steps needed to use "no-ads.pac". -// Detailed instructions follow below! -// -// 1. Save this as a file (no-ads.pac) on your local disk -// (or, add it to your home page, if you have one) -// 2. Select a no-ads "blackhole". -// 3. Configure your browser to use this file as its auto proxy configuration. -// 4. Clear your browser's cache -// (or else it may still show you ads it has saved on your disk). -// - - -/////////////////////////////////////////////////////////////////////////////// -// -// 1. SAVE THIS FILE -// -// Copy this file to your local machine; use your home directory (UNIX) -// or your Desktop or C:\ directory (Windows). -// - - - -/////////////////////////////////////////////////////////////////////////////// -// -// 2. SELECT A NO-ADS BLACKHOLE -// -// You can skip this section if you are using any version of Internet Explorer. -// You can also skip this section for Netscape 7.1, Mozilla 1.4, or -// Firefox 1.0 (or later), as they include PAC failover support (but do -// read the note in section "2a" below). -// -// -// The basic trick of no-ads is to match the site or URL of annoying web content -// and tell your browser to use a proxy that will deny loading of that resource -// (image, page, etc). -// -// A "black-hole" proxy server is one that always denies loading a web page. -// ("send it off to a blackhole"). -// -// When you initially get "no-ads.pac", it is using this as the blackhole: -// -// "PROXY 0.0.0.0:3421" -// -// This says to use the local host at a port which nothing should be listening -// on. Thus, this is "a server that doesn't repond." -// -// This is a good default for all systems, and especially Windows. -// However, if you are using the Blackhole Proxy Server on Windows, -// be sure to change it to "PROXY 127.0.0.1:3421" -// -// -// Some possibilities for the blackhole: -// -// a. A server that doesn't respond. -// -// *** This works for all versions of Internet Explorer. -// *** This mostly works for Mozilla, Firefox, and Netscape. -// -// If you do nothing, then this is configured to direct annoying -// content to the proxy running on your own host at port 3421. -// Since you shouldn't have anything running on that port, that -// connection will timeout and the annoying content will never be -// loaded. -// -// Older versions of Netscape wait to connect to the proxy server -// (usually it needs to load part of the image to layout the web -// page), and then asks if you want to disable the proxy that -// doesn't answer. -// -// Older versions of Mozilla will give an alert saying it couldn't -// connect to the proxy server. -// -// Mozilla 1.4+, Firefox 1.0+ and Netscape 7.1 will only give -// you this alert if the whole page being display is blocked, -// rather than just an image on that page. Thus, I still -// recommend a blackhole proxy even though it isn't needed. -// -// Opera will disable your auto proxy config if the proxy server -// doesn't respond. -// -// IE doesn't care that the proxy server isn't responding. As -// this avoids a connection for annoying content, it is fastest. -// -// b. A simple, blackhole server -// -// When needed, I run a simple "server" at port 3421 that denies -// all requests. Some options you can use for this: -// -// - On Windows, you can try Larry Wang's black-hole proxy program: -// -// http://leisuresuit10.tripod.com/BlackHoleProxy/ -// -// I can not vouch that his binaries are virus free, but he does -// offer the source code. -// -// - I use this shell script on UNIX; it is invoked via inetd. -// /usr/local/lib/noproxy: -// -// #!/bin/sh -// read a -// read b -// echo HTTP/1.0 501 No Ads Accepted -// echo "" -// exit -// -// Add this line to inetd.conf ('kill -HUP' inetd afterwards): -// -// 3421 stream tcp nowait nobody /usr/local/lib/noproxy noproxy -// -// This simple script doesn't work on Linux because of the -// (IMHO) broken way its TCP stack works. See the bottom of -// http://www.schooner.com/~loverso/no-ads/ for a complete copy -// of the `noproxy' shell script. -// -// If always exec'ing a shell was expensive on your computer -// (it isn't on mine), then you could use a "wait"-style Perl -// script that would accept() incoming connections. -// -// - Sean Burke has a black-hole proxy written in Perl script: -// -// http://www.speech.cs.cmu.edu/~sburke/pub/black_hole_http_server.pl -// (This is a standalone server, not run from inetd). -// -// e. A trick: use an HTTP/1.0 non-proxy server -// -// An HTTP/1.0 non-proxy server will return a 501 error when -// given a proxy request. Thus, just use the address of your -// local intranet web server as your blackhole PROXY. -// The downside of this is that it will probably also log an -// error, which wastes a small amount of resources. -// -// *** -// *** Be sure to update the "blackhole" variable above with a setting of -// *** "PROXY hostname:port" that matches your blackhole server!! -// *** -// -// *** -// *** If you already use a proxy server to access the WWW, -// *** change the "normal" variable above from "DIRECT" to -// *** be "PROXY proxy:port" to match your proxy server. -// *** - - -/////////////////////////////////////////////////////////////////////////////// -// -// 3. TO CONFIGURE YOUR BROWSER -// -// The Proxy Auto Configuration file can be either on the local disk or -// accessed from a web server, with the following constraints: -// -// a. IE4 can only load the PAC from a web server (http:// URL) -// b. Netscape, Mozilla, Firefox and IE (5 or later) can load the -// PAC from anywhere. -// c. Netscape, Mozilla, Firefox and (probably) Opera require the correct -// MIME type when loading the PAC from a web server. -// -// -// To set the Proxy Auto Configuration with Netscape, Mozilla, or Firefox: -// -// 1. Enable Proxy Auto Config: -// -// For Netsacpe/Mozilla: -// -// Open "Edit->Preferences" -// Select "Advanced" -// Select "Proxies" -// -// For Firefox (1.0): -// -// Open "Tools->Options" -// Select "Coonection Settings" on the General tab: -// -// Select the "Auto proxy configuration URL" option. -// Enter URL or path of where you've saved this file, such as: -// -// http://yourserver/no-ads.pac -// -// If you place this on your local disk, you should use a -// file: URL such as: -// -// file:/home/loverso/no-ads.pac (UNIX) -// file:///c:/windows/desktop/no-ads.pac (Windows) -// -// (file:/ and file:// will work in Mozilla, but file:/// is correct -// required for Firefox) -// -// 2. If you are serving this from a web server, these browsers require -// the correct MIME type on the file before using it. You must configure -// your web server to provide a "application/x-ns-proxy-autoconfig" -// MIME type. -// -// a. For Apache, name the file with a ".pac" extension and add this -// line to the http.conf (or the .htaccess file in the same directory): -// -// AddType application/x-ns-proxy-autoconfig .pac -// -// b. For IIS (instructions from Kevin Roth) -// -// Open Internet Services Manager -// Right click on the web site (or directory) you wish to change. -// Choose Properties -// Click the "HTTP Headers" tab -// Click the "File Types" button in the "MIME Map" section -// Click the "New Type..." button -// Enter "pac" for "Associated Extension" -// Enter "application/x-ns-proxy-autoconfig" for "Content Type (MIME)" -// Click OK to close the Add type dialog, the MIME types dialog, -// and the main properties dialog. -// -// (This is definately needed for NS, but not for IE) -// -// -// To set the Proxy Auto Configuration with IE: -// -// 1. Enable Proxy Auto Config: -// -// Open "Tools->Internet Options" -// Select "Connections" tab -// Click "LAN Settings" -// or Choose an entry from "Dial-up settings" and click "Settings" -// -// On the settings dialog, select "Use automatic configuration script" -// Enter the URL of this file in Address field. -// -// http://yourserver/no-ads.pac -// file:///c:/windows/desktop/no-ads.pac (Windows) -// -// You can only use a file: URL with IE5 (or later). -// ("file:///" with with IE versions after 5.0 SP2) -// -// 2. Fix Security Settings (IMPORTANT): -// -// Select "Security" tab -// Select "Local intranet" -// Click "Sites" box -// Unselect "include all sites that bypass the proxy server" option -// -// 3. Disable "Auto Proxy Caching" (IMPORTANT): -// (thanks to Kevin Roth for alerting me of this!) -// -// IE contains a proxy result caching mechanism that will defeat the -// ability to block servers that server both ad and non-ad content. -// To prevent this, add the registry key described in this MS KB article: -// -// http://support.microsoft.com/?kbid=271361 -// -// You can do so by downloading this file and clicking on it to load -// it into the registry. This must be done on a per-user basis. -// http://www.schooner.com/~loverso/no-ads/IE-no-auto-proxy-cache.reg -// -// IE doesn't currently check the MIME type of the PAC file. -// -// To see some notes from MS on PAC in IE, see -// http://msdn.microsoft.com/library/periodic/period99/faq0599.htm -// (they seem to have removed this URL) -// -// -// To set the Proxy Auto Configuration with Opera 6 (6.04 on Windows tested): -// -// 1. Enable Proxy Auto Config: -// Open the Preferences (Alt-P) -// Select "Network" -// Click the "Proxy servers" box -// Select "Use automatic proxy configuration" -// Enter the URL of this file as -// -// http://yourserver/no-ads.pac -// file://c:/windows/desktop/no-ads.pac -// -// (file:/// might be needed; I've not tested Opera lately) -// -// 2. You must use a blackhole proxy for Opera (it will not work with an -// address of a server that does not respond). -// -// 3. Be sure to clear the cache and exit/restart Opera. -// - - -/////////////////////////////////////////////////////////////////////////////// -// -// 4. CLEAR YOUR BROWSER'S CACHE -// -// For Internet Explorer: -// -// Open "Tools->Internet Options" -// Select "Delete Files" under "Temporary Internet Files" -// Click "OK" -// -// For Mozilla/Netscape Navigator: -// -// Open "Edit->Preferences" -// Select "Advanced" -// Select "Proxies" -// Click "Clear Disk Cache" -// Click "Clear Memory Cache" -// -// For Firefox: -// -// Open "Tools->Options" -// Select the "Privay" tab -// Scroll down or go to the "Cache" section -// Click "Clear" -// -// For Opera: -// -// Open "File->Preferences" -// Select "History and cache" -// Click "Empty now" -// - - -/////////////////////////////////////////////////////////////////////////////// -// -// To see the definition of this page's JavaScript contents, see -// -// http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/proxy-live.html -// -// Microsoft includes this in their KB article: -// -// http://support.microsoft.com/support/kb/articles/Q209/2/66.ASP -// -// Special PAC functions: -// Hostname: -// isPlainHostName(host) -// dnsDomainIs(host, domain) -// localHostOrDomainIs(host, hostdom) -// isResolvable(host) -// isInNet(host, pattern, mask) -// Utility: -// dnsResolve(host) -// myIpAddress() -// dnsDomainLevels(host) -// URL: -// shExpMatch(str, shexp) -// Time: -// weekdayRange(wd1, wd2, gmt) -// dateRange(...) -// timeRange(...) -// -// Other functions and methods that may work: -// http://developer.netscape.com/docs/manuals/communicator/jsref/win1.htm -// Note that "alert()" only works with Netscape4 and IE, and Mozilla 1.4+. -// -// NOTE: -// isInNet() will resolve a hostname to an IP address, and cause -// hangs on Mozilla/Firefox. Currently, these are stubbed out and replaced -// with shExpMatch(host, "a.b.c.*"), which doesn't do the same thing, -// but is sufficient for these purposes. -// -// Additional Mozilla/Firefox comments: -// -// All the above PAC functions are implemented in JavaScript, -// and are added to the body of your PAC file when it is loaded. -// See the "components/nsProxyAutoConfig.js" browser install -// directory. -// -// - shExpMatch() is implemented as three pattern.replaces() -// followed by a call to RegExp() (SLOW) -// - isPlainHostname() just checks for lack of "." in the string -// - dnsDomainIs() just matches strings exactly -// - alert() is bound to this.proxyAlert(), which displays a message -// in the JavaScript console window - -/////////////////////////////////////////////////////////////////////////////// -// -// Regular Expressions -// -// Angus Turnbull pointed out the JavaScript 1.2 RE operators to me. -// These should work in NS4 and IE4 (or later), but I have only tested on -// Mozilla (1.3), IE5.5, and IE6. PLEASE TELL ME IF IT WORKS FOR YOU! -// -// A good introduction is at: -// http://www.evolt.org/article/Regular_Expressions_in_JavaScript/17/36435/ -// Some references: -// (old Netscape documentation is gone) -// http://devedge.netscape.com/library/manuals/2000/javascript/1.5/reference/regexp.html -// http://developer.netscape.com/docs/manuals/js/client/jsref/regexp.htm -// http://www.webreference.com/js/column5/ -// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/js56jsobjRegExpression.asp -// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/js56jsgrpRegExpSyntax.asp -// Real-time evaluator: -// http://www.cuneytyilmaz.com/prog/jrx/ -// -// I'm slowly replacing multiple glob patterns with regexps. -// By using RE literals of /.../ rather than the constructor 'new RegExp()', -// the regexps should be compiled as no-ads.pac is loaded. -// -// Important notes: -// - if using the constructor, \ needs to be quoted; thus "\\." is used -// to match a literal '.'. In the RE literal form, I need to end up -// quoting any / for a URL path. -// - Avoid these for now; they are broken or not supported in "older" -// browsers such as NS4 and IE4: -// - look-aheads (?=pat) -// - non-greedy ? - a ? that follows *,+,?, and {}; (s)? is NOT non-greedy -// - -// matches several common URL paths for ad images: -// such as: /banner/ /..._banner/ /banner_... -// but matches several words and includes plurals -var re_banner = /\/(.*_){0,1}(ad|adverts?|adimage|adframe|adserver|admentor|adview|banner|popup|popunder)(s)?[_.\/]/i; - -// matches host names staring with "ad" but not (admin|add|adsl) -// or any hostname starting with "pop", "clicks", and "cash" -// or any hostname containing "banner" -// ^(ad(s)?.{0,4}\.|pop|click|cash|[^.]*banner|[^.]*adserv) -// ^(ad(?!(min|sl|d\.))|pop|click|cash|[^.]*banner|[^.]*adserv) -// ^(ad(?!(min|sl|d\.))|pop|click|cash|[^.]*banner|[^.]*adserv|.*\.ads\.) -var re_adhost = /^(www\.)?(ad(?!(ult|obe.*|min|sl|d|olly.*))|tology|pop|click|cash|[^.]*banner|[^.]*adserv|.+\.ads?\.)/i; - -// neg: -// admin.foobar.com -// add.iahoo.com -// adsl.allow.com -// administration.all.net -// pos: -// fire.ads.ighoo.com -// ads.foo.org -// ad0121.aaaa.com -// adserver.goo.biz -// popup.foo.bar - -/////////////////////////////////////////////////////////////////////////////// - -var isActive = 1; - -function FindProxyForURL(url, host) -{ - // debug - // alert("checking: url=" + url + ", host=" + host); - - // Excellent kludge from Sean M. Burke: - // Enable or disable no-ads for the current browser session. - // - // To disable, visit this URL: http://no-ads.int/off - // To re-enable, visit this URL: http://no-ads.int/on - // - // (this will not work with Mozilla or Opera if the alert()s are present) - // - // This happens before lowercasing the URL, so make sure you use lowercase! - // - if (shExpMatch(host, "no-ads.int")) { - if (shExpMatch(url, "*/on*")) { - isActive = 1; - //alert("no-ads is enabled.\n" + url); - } else if (shExpMatch(url, "*/off*")) { - isActive = 0; - //alert("no-ads has been disabled.\n" + url); - } else if (shExpMatch(url, "*no-ads.int/")) { - alert("no-ads is "+(isActive ? "enabled" : "disabled")+".\n" + url); - } else { - alert("no-ads unknown option.\n" + url); - } - - return blackhole; - } - - if (!isActive) { - // alert("allowing (not active): return " + bypass); - return bypass; - } - - // Suggestion from Quinten Martens - // Make everything lower case. - // WARNING: all shExpMatch rules following MUST be lowercase! - url = url.toLowerCase(); - host = host.toLowerCase(); - - // - // Local/Internal rule - // matches to this rule get the 'local' proxy. - // Adding rules here enables the use of 'local' - // - if (0 - // LOCAL - // add rules such as: - // || dnsDomainIs(host, "schooner.com") - // || isPlainHostName(host) - // or for a single host - // || (host == "some-local-host") - ) { - // alert("allowing (local): return " + localproxy); - return localproxy; - } - - // - // Whitelist section from InvisiBill - // - // Add sites here that should never be matched for ads. - // - if (0 - // WHITELIST - // To add whitelist domains, simple add a line such as: - // || dnsDomainIs(host, "schooner.com") - // or for a single host - // || (host == "some-host-name") - - // Note: whitelisting schooner.com will defeat the "is-it-working" - // test page at http://www.schooner.com/~loverso/no-ads/ads/ - - // Apple.com "Switch" ads - || shExpMatch(url, "*.apple.com/switch/ads/*") - - // SprintPCS - || dnsDomainIs(host, ".sprintpcs.com") - - // Lego - || dnsDomainIs(host, ".lego.com") - - // Dell login popups - || host == "ecomm.dell.com" - - || host == "click2tab.mozdev.org" - || host == "addons.mozilla.org" - - // Uncomment for metacrawler - // || (host == "clickit.go2net.com") - - // Wunderground weather station banners - || shExpMatch(url, "*banners.wunderground.com/cgi-bin/banner/ban/wxbanner*") - || shExpMatch(url, "*banners.wunderground.com/weathersticker/*") - ) { - // alert("allowing (whitelist): return " + normal); - return normal; - } - - // To add more sites, simply include them in the correct format. - // - // The sites below are ones I currently block. Tell me of others you add! - - if (0 - // BLOCK - // Block IE4/5 "favicon.ico" fetches - // (to avoid being tracked as having bookmarked the site) - || shExpMatch(url, "*/favicon.ico") - - ////// - // - // Global Section - // tries to match common names - // - - // RE for common URL paths - || re_banner.test(url) - - // RE for common adserver hostnames. - // The regexp matches all hostnames starting with "ad" that are not - // admin|add|adsl - // (replaces explicit shExpMatch's below) - || re_adhost.test(host) - -// || (re_adhost.test(host) -// && !( -// shExpMatch(host, "add*") -// || shExpMatch(host, "admin*") -// || shExpMatch(host, "adsl*") -// ) -// ) -// // or any subdomain "ads" -// || (dnsDomainLevels(host) > 2 && shExpMatch(host, "*.ads.*")) - - ////// - // - // banner/ad organizations - // Just delete the entire namespace - // - - // doubleclick - || dnsDomainIs(host, ".doubleclick.com") - || dnsDomainIs(host, ".doubleclick.net") - || dnsDomainIs(host, ".rpts.net") - || dnsDomainIs(host, ".2mdn.net") - || dnsDomainIs(host, ".2mdn.com") - - // these set cookies - || dnsDomainIs(host, ".globaltrack.com") - || dnsDomainIs(host, ".burstnet.com") - || dnsDomainIs(host, ".adbureau.net") - || dnsDomainIs(host, ".targetnet.com") - || dnsDomainIs(host, ".humanclick.com") - || dnsDomainIs(host, ".linkexchange.com") - - || dnsDomainIs(host, ".fastclick.com") - || dnsDomainIs(host, ".fastclick.net") - - // one whole class C full of ad servers (fastclick) - // XXX this might need the resolver -// || isInNet(host, "205.180.85.0", "255.255.255.0") - || shExpMatch(host, "205.180.85.*") - - // these use 1x1 images to track you - || dnsDomainIs(host, ".admonitor.com") - || dnsDomainIs(host, ".focalink.com") - - || dnsDomainIs(host, ".websponsors.com") - || dnsDomainIs(host, ".advertising.com") - || dnsDomainIs(host, ".cybereps.com") - || dnsDomainIs(host, ".postmasterdirect.com") - || dnsDomainIs(host, ".mediaplex.com") - || dnsDomainIs(host, ".adtegrity.com") - || dnsDomainIs(host, ".bannerbank.ru") - || dnsDomainIs(host, ".bannerspace.com") - || dnsDomainIs(host, ".theadstop.com") - || dnsDomainIs(host, ".l90.com") - || dnsDomainIs(host, ".webconnect.net") - || dnsDomainIs(host, ".avenuea.com") - || dnsDomainIs(host, ".flycast.com") - || dnsDomainIs(host, ".engage.com") - || dnsDomainIs(host, ".imgis.com") - || dnsDomainIs(host, ".datais.com") - || dnsDomainIs(host, ".link4ads.com") - || dnsDomainIs(host, ".247media.com") - || dnsDomainIs(host, ".hightrafficads.com") - || dnsDomainIs(host, ".tribalfusion.com") - || dnsDomainIs(host, ".rightserve.net") - || dnsDomainIs(host, ".admaximize.com") - || dnsDomainIs(host, ".valueclick.com") - || dnsDomainIs(host, ".adlibris.se") - || dnsDomainIs(host, ".vibrantmedia.com") - || dnsDomainIs(host, ".coremetrics.com") - || dnsDomainIs(host, ".vx2.cc") - || dnsDomainIs(host, ".webpower.com") - || dnsDomainIs(host, ".everyone.net") - || dnsDomainIs(host, ".zedo.com") - || dnsDomainIs(host, ".bigbangmedia.com") - || dnsDomainIs(host, ".ad-annex.com") - || dnsDomainIs(host, ".iwdirect.com") - || dnsDomainIs(host, ".adlink.de") - || dnsDomainIs(host, ".bidclix.net") - || dnsDomainIs(host, ".webclients.net") - || dnsDomainIs(host, ".linkcounter.com") - || dnsDomainIs(host, ".sitetracker.com") - || dnsDomainIs(host, ".adtrix.com") - || dnsDomainIs(host, ".netshelter.net") - || dnsDomainIs(host, ".rn11.com") - // http://vpdc.ru4.com/content/images/66/011.gif - || dnsDomainIs(host, ".ru4.com") - // no '.' for rightmedia.net - || dnsDomainIs(host, "rightmedia.net") - || dnsDomainIs(host, ".casalemedia.com") - || dnsDomainIs(host, ".casalemedia.com") - - // C-J - || dnsDomainIs(host, ".commission-junction.com") - || dnsDomainIs(host, ".qkimg.net") - // emjcd.com ... many others - - // */adv/* - || dnsDomainIs(host, ".bluestreak.com") - - // Virtumundo -- as annoying as they get - || dnsDomainIs(host, ".virtumundo.com") - || dnsDomainIs(host, ".treeloot.com") - || dnsDomainIs(host, ".memberprize.com") - - // internetfuel and _some_ of the sites they redirect to - // (more internetfuel - from Sam G) - || dnsDomainIs(host, ".internetfuel.net") - || dnsDomainIs(host, ".internetfuel.com") - || dnsDomainIs(host, ".peoplecaster.com") - || dnsDomainIs(host, ".cupidsdatabase.com") - || dnsDomainIs(host, ".automotive-times.com") - || dnsDomainIs(host, ".healthy-lifetimes.com") - || dnsDomainIs(host, ".us-world-business.com") - || dnsDomainIs(host, ".internet-2-web.com") - || dnsDomainIs(host, ".my-job-careers.com") - || dnsDomainIs(host, ".freeonline.com") - || dnsDomainIs(host, ".exitfuel.com") - || dnsDomainIs(host, ".netbroadcaster.com") - || dnsDomainIs(host, ".spaceports.com") - || dnsDomainIs(host, ".mircx.com") - || dnsDomainIs(host, ".exitchat.com") - || dnsDomainIs(host, ".atdmt.com") - || dnsDomainIs(host, ".partner2profit.com") - || dnsDomainIs(host, ".centrport.net") - || dnsDomainIs(host, ".centrport.com") - || dnsDomainIs(host, ".rampidads.com") - - ////// - // - // banner servers - // (typically these set cookies or serve animated ads) - // - - || dnsDomainIs(host, "commonwealth.riddler.com") - || dnsDomainIs(host, "banner.freeservers.com") - || dnsDomainIs(host, "usads.futurenet.com") - || dnsDomainIs(host, "banners.egroups.com") - || dnsDomainIs(host, "ngadclient.hearme.com") - || dnsDomainIs(host, "affiliates.allposters.com") - || dnsDomainIs(host, "adincl.go2net.com") - || dnsDomainIs(host, "webads.bizservers.com") - || dnsDomainIs(host, ".addserv.com") - || dnsDomainIs(host, ".falkag.net") - || (host == "promote.pair.com") - - // marketwatch.com (flash ads), but CSS get loaded - || (dnsDomainIs(host, ".mktw.net") - && !shExpMatch(url, "*/css/*")) - || dnsDomainIs(host, ".cjt1.net") - || dnsDomainIs(host, ".bns1.net") - - // "undergroundonline" - // comes from iframe with this url: http://mediamgr.ugo.com/html.ng/size=728x90&affiliate=megagames&channel=games&subchannel=pc&Network=affiliates&rating=g - || dnsDomainIs(host, "image.ugo.com") - || dnsDomainIs(host, "mediamgr.ugo.com") - - // web ads and "cheap Long Distance" - || dnsDomainIs(host, "zonecms.com") - || dnsDomainIs(host, "zoneld.com") - - // AOL - || dnsDomainIs(host, ".atwola.com") - || dnsDomainIs(host, "toolbar.aol.com") - - // animated ads shown at techbargains - || (dnsDomainIs(host, ".overstock.com") - && shExpMatch(url, "*/linkshare/*")) - || (dnsDomainIs(host, ".supermediastore.com") - && shExpMatch(url, "*/lib/supermediastore/*")) - || (dnsDomainIs(host, ".shop4tech.com") - && shExpMatch(url, "*/assets/*")) - || (dnsDomainIs(host, ".softwareandstuff.com") - && shExpMatch(url, "*/media/*")) - || (dnsDomainIs(host, ".buy.com") - && shExpMatch(url, "*/affiliate/*")) - - || (dnsDomainIs(host, "pdaphonehome.com") - && (shExpMatch(url, "*/pocketpcmagbest.gif") - || shExpMatch(url, "*/link-msmobiles.gif"))) - || (dnsDomainIs(host, "ppc4you.com") - && shExpMatch(url, "*/ppc_top_sites.gif")) - - // more animated ads... these really drive me crazy - || (dnsDomainIs(host, ".freewarepalm.com") - && shExpMatch(url, "*/sponsors/*")) - - ////// - // - // popups/unders - // - - || dnsDomainIs(host, "remotead.cnet.com") - || dnsDomainIs(host, ".1st-dating.com") - || dnsDomainIs(host, ".mousebucks.com") - || dnsDomainIs(host, ".yourfreedvds.com") - || dnsDomainIs(host, ".popupsavings.com") - || dnsDomainIs(host, ".popupmoney.com") - || dnsDomainIs(host, ".popuptraffic.com") - || dnsDomainIs(host, ".popupnation.com") - || dnsDomainIs(host, ".infostart.com") - || dnsDomainIs(host, ".popupad.net") - || dnsDomainIs(host, ".usapromotravel.com") - || dnsDomainIs(host, ".goclick.com") - || dnsDomainIs(host, ".trafficwave.net") - || dnsDomainIs(host, ".popupad.net") - || dnsDomainIs(host, ".paypopup.com") - - // Popups from ezboard - || dnsDomainIs(host, ".greenreaper.com") - || dnsDomainIs(host, ".spewey.com") - || dnsDomainIs(host, ".englishharbour.com") - || dnsDomainIs(host, ".casino-trade.com") - || dnsDomainIs(host, "got2goshop.com") - // more ezboard crud (from Miika Asunta) - || dnsDomainIs(host, ".addynamix.com") - || dnsDomainIs(host, ".trafficmp.com") - || dnsDomainIs(host, ".makingmoneyfromhome.net") - || dnsDomainIs(host, ".leadcart.com") - - // http://www.power-mark.com/js/popunder.js - || dnsDomainIs(host, ".power-mark.com") - - ////// - // - // User tracking (worse than ads) && hit counting "services" - // - - // "web trends live" - || dnsDomainIs(host, ".webtrendslive.com") - || dnsDomainIs(host, ".wtlive.com") - - // 1x1 tracking images - // ** (but also used in some pay-for-clicks that I want to follow, - // ** so disabled for now. 9/2001) - // || dnsDomainIs(host, "service.bfast.com") - - // one whole class C full of ad servers - // XXX this might need the resolver -// || isInNet(host, "66.40.16.0", "255.255.255.0") - || shExpMatch(host, "66.40.16.*") - - || dnsDomainIs(host, ".web-stat.com") - || dnsDomainIs(host, ".superstats.com") - || dnsDomainIs(host, ".allhits.ru") - || dnsDomainIs(host, ".list.ru") - || dnsDomainIs(host, ".counted.com") - || dnsDomainIs(host, ".rankyou.com") - || dnsDomainIs(host, ".clickcash.com") - || dnsDomainIs(host, ".clickbank.com") - || dnsDomainIs(host, ".paycounter.com") - || dnsDomainIs(host, ".cashcount.com") - || dnsDomainIs(host, ".clickedyclick.com") - || dnsDomainIs(host, ".clickxchange.com") - || dnsDomainIs(host, ".sitestats.com") - || dnsDomainIs(host, ".site-stats.com") - || dnsDomainIs(host, ".hitbox.com") - || dnsDomainIs(host, ".exitdirect.com") - || dnsDomainIs(host, ".realtracker.com") - || dnsDomainIs(host, ".etracking.com") - || dnsDomainIs(host, ".livestat.com") - || dnsDomainIs(host, ".spylog.com") - || dnsDomainIs(host, ".freestats.com") - || dnsDomainIs(host, ".addfreestats.com") - || dnsDomainIs(host, ".topclicks.net") - || dnsDomainIs(host, ".mystat.pl") - || dnsDomainIs(host, ".hitz4you.de") - || dnsDomainIs(host, ".hitslink.com") - || dnsDomainIs(host, ".thecounter.com") - || dnsDomainIs(host, ".roiservice.com") - || dnsDomainIs(host, ".overture.com") - || dnsDomainIs(host, ".xiti.com") - || dnsDomainIs(host, ".cj.com") - || dnsDomainIs(host, ".anrdoezrs.net") - || dnsDomainIs(host, ".hey.it") - || dnsDomainIs(host, ".ppctracking.net") - || dnsDomainIs(host, ".darkcounter.com") - || dnsDomainIs(host, ".2o7.com") - || dnsDomainIs(host, ".2o7.net") - || dnsDomainIs(host, ".gostats.com") - || dnsDomainIs(host, ".everstats.com") - || dnsDomainIs(host, ".onestat.com") - || dnsDomainIs(host, ".statcounter.com") - || dnsDomainIs(host, ".trafic.ro") - || dnsDomainIs(host, ".exitexchange.com") - - // clickability, via CNN - || dnsDomainIs(host, ".clickability.com") - || dnsDomainIs(host, ".savethis.com") - - ////// - // - // Dead domain parking - // - || dnsDomainIs(host, ".netster.com") - - ////// - // - // Search engine "optimizers" - // - || dnsDomainIs(host, ".searchmarketing.com") - - ////// - // - // Spyware/worms - // - - || dnsDomainIs(host, ".friendgreetings.com") - || dnsDomainIs(host, ".permissionedmedia.com") - || dnsDomainIs(host, ".searchbarcash.com") - - ////// - // - // "Surveys" - // - - || dnsDomainIs(host, ".zoomerang.com") - - ////// - // - // "Casino" ads (scams) - // - - || dnsDomainIs(host, ".aceshigh.com") - || dnsDomainIs(host, ".idealcasino.net") - || dnsDomainIs(host, ".casinobar.net") - || dnsDomainIs(host, ".casinoionair.com") - - || (dnsDomainIs(host, ".go2net.com") - && shExpMatch(url, "*adclick*") - ) - - ////// - // - // Spammers - // - - || dnsDomainIs(host, ".licensed-collectibles.com") - || dnsDomainIs(host, ".webdesignprofessional.com") - - ////// - // - // Directed at extra annoying places - // - - // Attempts to download ad-supported spyware without asking first - || dnsDomainIs(host, ".gator.com") - - // ebay - || ((dnsDomainIs(host, "pics.ebay.com") - || dnsDomainIs(host, "pics.ebaystatic.com")) - && shExpMatch(url, "*/pics/mops/*/*[0-9]x[0-9]*") - ) - || (dnsDomainIs(host, "ebayobjects.com") - && shExpMatch(url, "*search/keywords*") - ) - || dnsDomainIs(host, "admarketplace.com") - || dnsDomainIs(host, "admarketplace.net") - - // Bravenet & Ezboard - || (dnsDomainIs(host, ".ezboard.com") - && shExpMatch(url, "*/bravenet/*") - ) - || (dnsDomainIs(host, ".bravenet.com") - && ( shExpMatch(host, "*counter*") - || shExpMatch(url, "*/jsbanner*") - || shExpMatch(url, "*/bravenet/*") - ) - ) - - // GeoCities - // (checking "toto" from Prakash Persaud) - || (( dnsDomainIs(host,"geo.yahoo.com") - || dnsDomainIs(host,".geocities.com")) - && ( - shExpMatch(url,"*/toto?s*") - || shExpMatch(url, "*geocities.com/js_source*") - || dnsDomainIs(host, "visit.geocities.com") - ) - ) - - // Yahoo ads (direct and via Akamai) - // http://us.a1.yimg.com/us.yimg.com/a/... - || (dnsDomainIs(host,"yimg.com") - && ( shExpMatch(url,"*yimg.com/a/*") - || shExpMatch(url,"*yimg.com/*/adv/*") - ) - ) - // "eyewonder" ads at Yahoo - || dnsDomainIs(host,"qz3.net") - || dnsDomainIs(host,".eyewonder.com") - - // background ad images - || dnsDomainIs(host,"buzzcity.com") - - // FortuneCity - ads and tracking - || (dnsDomainIs(host,".fortunecity.com") - && ( shExpMatch(url,"*/js/adscript*") - || shExpMatch(url,"*/js/fctrack*") - ) - ) - - // zdnet - // tracking webbugs: - // http://gserv.zdnet.com/clear/ns.gif?a000009999999999999+2093 - || (dnsDomainIs(host, ".zdnet.com") - && ( dnsDomainIs(host, "ads3.zdnet.com") - || host == "gserv.zdnet.com" - || shExpMatch(url, "*/texis/cs/ad.html") - || shExpMatch(url, "*/adverts") - ) - ) - - // cnet - // web bugs and ad redirections - // taken care of by hostname rules: - // http://adimg.com.com/... - // http://adlog.com.com/... - // http://dw.com.com/clear/c.gif - // http://dw.com.com/redir?astid=2&destUrl=http%3A%2F%2Fwww.buy ... - // http://mads.com.com/mac-ad?... - || (host == "dw.com.com" || host == "mads.com.com") - || (dnsDomainIs(host, ".com.com") - && ( host == "dw.com.com" - || host == "mads.com.com" - ) - ) - - // nytimes - || (dnsDomainIs(host, ".nytimes.com") - && shExpMatch(url,"*/adx/*") - ) - - // pop-after - || dnsDomainIs(host, ".unicast.net") - - - // Be Free affiliate ads - || dnsDomainIs(host, ".reporting.net") - || dnsDomainIs(host, ".affliate.net") - || (dnsDomainIs(host, ".akamai.net") - && shExpMatch(url, "*.affiliate.net/*") - ) - - // Infospace.com popunder - // for "webmarket.com" & "shopping.dogpile.com" -- just say no! - || (dnsDomainIs(host, ".infospace.com") - && shExpMatch(url, "*/goshopping/*") - ) - || dnsDomainIs(host, ".webmarket.com") - || dnsDomainIs(host, "shopping.dogpile.com") - - // goto.com popunder for information.gopher.com - || dnsDomainIs(host, "information.gopher.com") - - // About.com popunder and floating ad bar - || (dnsDomainIs(host, ".about.com") - && (0 - || shExpMatch(url, "*/sprinks/*") - || shExpMatch(url, "*about.com/0/js/*") - || shExpMatch(url, "*about.com/f/p/*") - ) - ) - - // Dell - || (dnsDomainIs(host, ".dell.com") - && shExpMatch(url, "*/images/affiliates/*") - ) - - // IFilm iframes - || (dnsDomainIs(host, ".ifilm.com") - && (shExpMatch(url, "*/partners/*") - || shExpMatch(url, "*/redirect*") - ) - ) - - // tomshardware - // they are most annoying: - // - cookies on their background images to track you - // - looping shockwave ads - // this kills most of the crud -// || isInNet(host, "216.92.21.0", "255.255.255.0") - || ((dnsDomainIs(host, ".tomshardware.com") - || shExpMatch(host, "216.92.21.*")) - && ( shExpMatch(url, "*/cgi-bin/banner*") - || shExpMatch(url, "*/cgi-bin/bd.m*") - || shExpMatch(url, "*/images/banner/*") - ) - ) - - || shExpMatch(url, "*mapsonus.com/ad.images*") - - // Slashdot: added these when I saw hidden 1x1 images with cookies - || dnsDomainIs(host, "adfu.blockstackers.com") - || (dnsDomainIs(host, "slashdot.org") - && ( - shExpMatch(url, "*/slashdot/pc.gif*") - || shExpMatch(url, "*/pagecount.gif*") - || shExpMatch(url, "*/adlog.pl*") - ) - ) - || dnsDomainIs(host, "googlesyndication.com") - || dnsDomainIs(host, "google-analytics.com") - - // it-aint-cool.com - || (dnsDomainIs(host, "aintitcool.com") - && ( - shExpMatch(url, "*/newline/*") - || shExpMatch(url, "*/drillteammedia/*") - || shExpMatch(url, "*/foxsearchlight/*") - || shExpMatch(url, "*/media/aol*") - || shExpMatch(url, "*swf") - ) - ) - - // Staples & CrossMediaServices - || (dnsDomainIs(host, ".staples.com") - && shExpMatch(url, "*/pixeltracker/*") - ) - || dnsDomainIs(host, "pt.crossmediaservices.com") - - // OfficeMax affiliate art (affArt->affart because of toLowerCase) - || (dnsDomainIs(host, ".officemax.com") - && shExpMatch(url, "*/affart/*") - ) - - // complicated JavaScript for directed ads! -// 1/5/2004: allow /js/ as they now use it for graphs -// || (dnsDomainIs(host, ".anandtech.com") -// && (shExpMatch(url,"*/js/*") -// || shExpMatch(url,"*/bnr_*") -// ) -// ) - - // hardocp - // http://65.119.30.151/UploadFilesForNewegg/onlineads/newegg728hardocp.swf - || (host == "hera.hardocp.com") - || shExpMatch(url,"*/onlineads/*") - - // complicated JavaScript for gliding ads! - || (dnsDomainIs(host, ".fatwallet.com") - && shExpMatch(url,"*/js/*") - ) - - // cnet ads - || dnsDomainIs(host, "promo.search.com") - - // IMDB celeb photos - // (Photos/CMSIcons->photos/cmsicons because of toLowerCase) - || (dnsDomainIs(host, "imdb.com") - && ( shExpMatch(url, "*/photos/cmsicons/*") - || shExpMatch(url, "*/icons/*/celeb/*") - || shExpMatch(url, "*.swf") - ) - ) - // incredibly annoying IMDB shock/flash ads - || dnsDomainIs(host, "kliptracker.com") - || dnsDomainIs(host, "klipmart.com") - - || host == "spinbox.techtracker.com" - - // Amazon affiliate 'search'. retrieves a JS that writes new HTML - // that references one or more images "related to your search". - // (If there is a real use for rcm.amazon.com, let me know) - // http://rcm.amazon.com/e/cm?t=starlingtechnolo&l=st1&search=cynicism&mode=books&p=11&o=1&bg1=CEE7FF&fc1=000000&lc1=083194&lt1=_blank - || host == "rcm.amazon.com" - - ////// - // - // "Other Scum And Villainry" - // - - // Popup from "reserved" domains at register.com - // (I considered blocking all of register.com) - || (dnsDomainIs(host, ".register.com") - && (shExpMatch(url,"*.js") - || shExpMatch(host, "searchtheweb*") - || shExpMatch(host, "futuresite*") - ) - ) - - || dnsDomainIs(host, ".oingo.com") - || dnsDomainIs(host, ".namingsolutions.com") - - // "Data collection" - || dnsDomainIs(host, ".coremetrics.com") - - // Sets your home page - || dnsDomainIs(host, ".firehunt.com") - - // tracking - || dnsDomainIs(host, ".appliedsemantics.com") - - // Scum who buy ad space from the above - // || dnsDomainIs(host, ".hartfordrents.com") - // || dnsDomainIs(host, ".chicagocomputerrentals.com") - // || dnsDomainIs(host, ".ccrsolutions.com") - // || dnsDomainIs(host, ".rushcomputer.com") - // || dnsDomainIs(host, ".localesimates.com") - // || dnsDomainIs(host, ".unitedvision.com") - // XXX this might need the resolver -// || isInNet(host, "216.216.246.31", "255.255.255.255") - || (host == "216.216.246.31") - - // avsforum ads -// || isInNet(host, "216.66.21.35", "255.255.255.255") - || (host == "216.66.21.35") - || dnsDomainIs(host, ".avsads.com") - - // bogus "search" sites at non-existent sites - || dnsDomainIs(host, ".search411.com") - - // palmgear.com - || (dnsDomainIs(host, ".palmgear.com") - && ( shExpMatch(url, "*/adsales/*") - || shExpMatch(url, "*/emailblast*") - ) - ) - - ////// - // - // Contributed adult sites - // - - || dnsDomainIs(host, ".porntrack.com") - || dnsDomainIs(host, ".sexe-portail.com") - || dnsDomainIs(host, ".sextracker.com") - || dnsDomainIs(host, ".sexspy.com") - || dnsDomainIs(host, ".offshoreclicks.com") - || dnsDomainIs(host, ".exxxit.com") - || dnsDomainIs(host, "private-dailer.biz") - || shExpMatch(url, "*retestrak.nl/misc/reet.gif") - || shExpMatch(url, "*dontstayin.com/*.swf") - - // debug - // || (alertmatch("NOT:" + url) && 0) - - ) { - - // alert("blackholing: " + url); - - // deny this request - return blackhole; - - } else { - // debug - // alert("allowing: " + url); - - // all other requests go direct and avoid any overhead - return normal; - } -} - -/////////////////////////////////////////////////////////////////////////////// -// -// This line is just for testing; you can ignore it. But, if you are having -// problems where you think this PAC file isn't being loaded, then change this -// to read "if (1)" and the alert box should appear when the browser loads this -// file. -// -// This works for IE4, IE5, IE5.5, IE6 and Netscape 2.x, 3.x, and 4.x. -// (For IE6, tested on Win2K) -// This does not work for Mozilla before 1.4 (and not for Netscape 6.x). -// In Mozilla 1.4+ and Fireox, this will write to the JavaScript console. -// -if (0) { - alert("no-ads.pac: LOADED:\n" + - " version: "+noadsver+"\n" + - " normal: "+normal+"\n" + - " blackhole: "+blackhole+"\n" + - " localproxy: "+localproxy+"\n" + - " bypass: "+bypass+"\n" - // MSG - ); -} - -// The above should show you that this JavaScript is executed in an -// unprotected global context. NEVER point at someone elses autoconfig file; -// always load from your own copy! - -// an alert that returns true -function alertmatch(str) -{ - // alert("match: "+str); - return 1; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Replacement function for dnsDomainIs(). This is to replace the -// prefix problem, which a leading '.' used to be used for. -// -// dnsDomainIs("bar.com", "bar.com") => true -// dnsDomainIs("www.bar.com", "bar.com") => true -// dnsDomainIs("www.foobar.com", "bar.com") => true <<< incorrect -// -// isInDomain("bar.com", "bar.com") => true -// isInDomain("www.bar.com", "bar.com") => true -// isInDomain("www.foobar.com", "bar.com") => false <<< correct -// -function isInDomain(host, domain) { - if (host.length > domain.length) { - return (host.substring(host.length - domain.length - 1) == "."+domain); - } - return (host == domain); -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Tired of reading boring comments? Try reading today's comics: -// http://www.schooner.com/~loverso/comics/ -// -// or getting a quote from my collection: -// http://www.schooner.com/~loverso/quote/ -// - -// eof - //intelliserv.net - //intellisrv.net - //rambler.ru - //rightmedia.net - //calloffate.com - //fairmeasures.com -
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index a1787e4..dff329b 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc
@@ -1096,10 +1096,13 @@ return ERR_CONTENT_DECODING_FAILED; // On a 408 response from the server ("Request Timeout") on a stale socket, - // retry the request. + // retry the request for HTTP/1.1 but not HTTP/2 or QUIC because those + // multiplex requests and have no need for 408. // Headers can be NULL because of http://crbug.com/384554. if (response_.headers.get() && response_.headers->response_code() == HTTP_REQUEST_TIMEOUT && + HttpResponseInfo::ConnectionInfoToCoarse(response_.connection_info) == + HttpResponseInfo::CONNECTION_INFO_COARSE_HTTP1 && stream_->IsConnectionReused()) { #if BUILDFLAG(ENABLE_REPORTING) GenerateNetworkErrorLoggingReport(OK);
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index 9e8eae7..056d24e 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -313,8 +313,8 @@ // Call NeuterHandshakePackets() at most once per connection. QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_neuter_handshake_packets_once, - true) + FLAGS_quic_reloadable_flag_quic_neuter_handshake_packets_once2, + false) // If true, support HTTP/3 priority in v99. QUIC_FLAG(bool, FLAGS_quic_allow_http3_priority, false) @@ -376,3 +376,8 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_connection_encryption_level, false) + +// If true, do not inject bandwidth in BbrSender::AdjustNetworkParameters. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_bbr_donot_inject_bandwidth, + false)
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index 86a7ad6..cb603a4 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -705,17 +705,22 @@ void CreateSession() { return CreateSession(supported_versions_); } - void CheckWasQuicResponse(HttpNetworkTransaction* trans) { + void CheckWasQuicResponse(HttpNetworkTransaction* trans, + const std::string& status_line) { const HttpResponseInfo* response = trans->GetResponseInfo(); ASSERT_TRUE(response != nullptr); ASSERT_TRUE(response->headers.get() != nullptr); - EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); + EXPECT_EQ(status_line, response->headers->GetStatusLine()); EXPECT_TRUE(response->was_fetched_via_spdy); EXPECT_TRUE(response->was_alpn_negotiated); EXPECT_EQ(QuicHttpStream::ConnectionInfoFromQuicVersion(version_), response->connection_info); } + void CheckWasQuicResponse(HttpNetworkTransaction* trans) { + CheckWasQuicResponse(trans, "HTTP/1.1 200 OK"); + } + void CheckResponsePort(HttpNetworkTransaction* trans, uint16_t port) { const HttpResponseInfo* response = trans->GetResponseInfo(); ASSERT_TRUE(response != nullptr); @@ -784,6 +789,11 @@ EXPECT_TRUE(trans.GetResponseInfo()->proxy_server.is_direct()); } } + void SendRequestAndExpectQuicResponse(const std::string& expected, + const std::string& status_line) { + SendRequestAndExpectQuicResponseMaybeFromProxy(expected, false, 443, + status_line); + } void SendRequestAndExpectQuicResponse(const std::string& expected) { SendRequestAndExpectQuicResponseMaybeFromProxy(expected, false, 443); @@ -1051,14 +1061,15 @@ void SendRequestAndExpectQuicResponseMaybeFromProxy( const std::string& expected, bool used_proxy, - uint16_t port) { + uint16_t port, + const std::string& status_line) { HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get()); HeadersHandler headers_handler; trans.SetBeforeHeadersSentCallback( base::Bind(&HeadersHandler::OnBeforeHeadersSent, base::Unretained(&headers_handler))); RunTransaction(&trans); - CheckWasQuicResponse(&trans); + CheckWasQuicResponse(&trans, status_line); CheckResponsePort(&trans, port); CheckResponseData(&trans, expected); EXPECT_EQ(used_proxy, headers_handler.was_proxied()); @@ -1068,6 +1079,14 @@ EXPECT_TRUE(trans.GetResponseInfo()->proxy_server.is_direct()); } } + + void SendRequestAndExpectQuicResponseMaybeFromProxy( + const std::string& expected, + bool used_proxy, + uint16_t port) { + SendRequestAndExpectQuicResponseMaybeFromProxy(expected, used_proxy, port, + "HTTP/1.1 200 OK"); + } }; INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence, @@ -1492,6 +1511,43 @@ test_socket_performance_watcher_factory_.rtt_notification_received()); } +// Regression test for https://crbug.com/695225 +TEST_P(QuicNetworkTransactionTest, 408Response) { + session_params_.quic_params.origins_to_force_quic_on.insert(HostPortPair()); + + AddQuicAlternateProtocolMapping(MockCryptoClientStream::CONFIRM_HANDSHAKE); + + MockQuicData mock_quic_data(version_); + int packet_num = 1; + if (VersionUsesHttp3(version_.transport_version)) { + mock_quic_data.AddWrite(SYNCHRONOUS, + ConstructInitialSettingsPacket(packet_num++)); + } + mock_quic_data.AddWrite( + SYNCHRONOUS, + ConstructClientRequestHeadersPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true, + true, GetRequestHeaders("GET", "https", "/"))); + mock_quic_data.AddRead( + ASYNC, ConstructServerResponseHeadersPacket( + 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false, + GetResponseHeaders("408 Request Timeout"))); + std::string header = ConstructDataHeader(6); + mock_quic_data.AddRead( + ASYNC, ConstructServerDataPacket( + 2, GetNthClientInitiatedBidirectionalStreamId(0), false, true, + header + "hello!")); + mock_quic_data.AddWrite(SYNCHRONOUS, + ConstructClientAckPacket(packet_num++, 2, 1, 1)); + mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read + + mock_quic_data.AddSocketDataToFactory(&socket_factory_); + + CreateSession(); + + SendRequestAndExpectQuicResponse("hello!", "HTTP/1.1 408 Request Timeout"); +} + TEST_P(QuicNetworkTransactionTest, QuicProxy) { session_params_.enable_quic = true; proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
diff --git a/net/tools/quic/quic_transport_simple_server.cc b/net/tools/quic/quic_transport_simple_server.cc new file mode 100644 index 0000000..b9bc024 --- /dev/null +++ b/net/tools/quic/quic_transport_simple_server.cc
@@ -0,0 +1,137 @@ +// Copyright (c) 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/tools/quic/quic_transport_simple_server.h" + +#include <stdlib.h> + +#include "base/run_loop.h" +#include "base/threading/thread_task_runner_handle.h" +#include "net/base/net_errors.h" +#include "net/quic/address_utils.h" +#include "net/quic/platform/impl/quic_chromium_clock.h" +#include "net/quic/quic_chromium_alarm_factory.h" +#include "net/quic/quic_chromium_connection_helper.h" +#include "net/socket/udp_server_socket.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_default_proof_providers.h" +#include "net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h" +#include "net/tools/quic/quic_simple_server_packet_writer.h" +#include "net/tools/quic/quic_simple_server_socket.h" + +namespace net { +namespace { + +using quic::CryptoHandshakeMessage; +using quic::ParsedQuicVersion; +using quic::PROTOCOL_TLS1_3; +using quic::QUIC_VERSION_99; +using quic::QuicChromiumClock; +using quic::QuicCryptoServerStream; +using quic::QuicSocketAddress; +using quic::QuicTransportSimpleServerSession; + +constexpr char kSourceAddressTokenSecret[] = "test"; +constexpr size_t kMaxReadsPerEvent = 32; +constexpr size_t kMaxNewConnectionsPerEvent = 32; +constexpr int kReadBufferSize = 2 * quic::kMaxIncomingPacketSize; + +} // namespace + +class QuicTransportSimpleServerSessionHelper + : public QuicCryptoServerStream::Helper { + public: + bool CanAcceptClientHello(const CryptoHandshakeMessage& /*message*/, + const QuicSocketAddress& /*client_address*/, + const QuicSocketAddress& /*peer_address*/, + const QuicSocketAddress& /*self_address*/, + std::string* /*error_details*/) const override { + return true; + } +}; + +QuicTransportSimpleServer::QuicTransportSimpleServer( + int port, + QuicTransportSimpleServerSession::Mode mode, + std::vector<url::Origin> accepted_origins) + : port_(port), + version_manager_({ParsedQuicVersion{PROTOCOL_TLS1_3, QUIC_VERSION_99}}), + clock_(QuicChromiumClock::GetInstance()), + crypto_config_(kSourceAddressTokenSecret, + quic::QuicRandom::GetInstance(), + quic::CreateDefaultProofSource(), + quic::KeyExchangeSource::Default()), + dispatcher_(&config_, + &crypto_config_, + &version_manager_, + std::make_unique<QuicChromiumConnectionHelper>( + clock_, + quic::QuicRandom::GetInstance()), + std::make_unique<QuicTransportSimpleServerSessionHelper>(), + std::make_unique<QuicChromiumAlarmFactory>( + base::ThreadTaskRunnerHandle::Get().get(), + clock_), + quic::kQuicDefaultConnectionIdLength, + mode, + accepted_origins), + read_buffer_(base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize)) {} + +QuicTransportSimpleServer::~QuicTransportSimpleServer() {} + +int QuicTransportSimpleServer::Run() { + socket_ = CreateQuicSimpleServerSocket( + IPEndPoint{IPAddress::IPv6AllZeros(), port_}, &server_address_); + if (socket_ == nullptr) + return EXIT_FAILURE; + + dispatcher_.InitializeWithWriter( + new QuicSimpleServerPacketWriter(socket_.get(), &dispatcher_)); + + ScheduleReadPackets(); + base::RunLoop().Run(); + return EXIT_SUCCESS; +} + +void QuicTransportSimpleServer::ScheduleReadPackets() { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&QuicTransportSimpleServer::ReadPackets, + weak_factory_.GetWeakPtr())); +} + +void QuicTransportSimpleServer::ReadPackets() { + dispatcher_.ProcessBufferedChlos(kMaxNewConnectionsPerEvent); + for (size_t i = 0; i < kMaxReadsPerEvent; i++) { + int result = socket_->RecvFrom( + read_buffer_.get(), read_buffer_->size(), &client_address_, + base::BindOnce(&QuicTransportSimpleServer::OnReadComplete, + base::Unretained(this))); + if (result == ERR_IO_PENDING) + return; + ProcessReadPacket(result); + } + ScheduleReadPackets(); +} + +void QuicTransportSimpleServer::OnReadComplete(int result) { + ProcessReadPacket(result); + ReadPackets(); +} + +void QuicTransportSimpleServer::ProcessReadPacket(int result) { + if (result == 0) + result = ERR_CONNECTION_CLOSED; + if (result < 0) { + LOG(ERROR) << "QuicTransportSimpleServer read failed: " + << ErrorToString(result); + dispatcher_.Shutdown(); + exit(EXIT_FAILURE); + return; + } + + quic::QuicReceivedPacket packet(read_buffer_->data(), /*length=*/result, + clock_->Now(), /*owns_buffer=*/false); + dispatcher_.ProcessPacket(ToQuicSocketAddress(server_address_), + ToQuicSocketAddress(client_address_), packet); +} + +} // namespace net
diff --git a/net/tools/quic/quic_transport_simple_server.h b/net/tools/quic/quic_transport_simple_server.h new file mode 100644 index 0000000..64b768d2 --- /dev/null +++ b/net/tools/quic/quic_transport_simple_server.h
@@ -0,0 +1,64 @@ +// Copyright (c) 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_TOOLS_QUIC_QUIC_TRANSPORT_SIMPLE_SERVER_H_ +#define NET_TOOLS_QUIC_QUIC_TRANSPORT_SIMPLE_SERVER_H_ + +#include "base/memory/weak_ptr.h" +#include "net/base/io_buffer.h" +#include "net/base/ip_endpoint.h" +#include "net/quic/platform/impl/quic_chromium_clock.h" +#include "net/socket/udp_server_socket.h" +#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h" +#include "net/third_party/quiche/src/quic/core/quic_config.h" +#include "net/third_party/quiche/src/quic/core/quic_version_manager.h" +#include "net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h" +#include "net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h" +#include "url/origin.h" + +namespace net { + +// Server for QuicTransportSimpleSession. This class is responsible for +// creating a UDP server socket, listening on it and passing the packets +// received to the dispatcher. +class QuicTransportSimpleServer { + public: + QuicTransportSimpleServer(int port, + quic::QuicTransportSimpleServerSession::Mode mode, + std::vector<url::Origin> accepted_origins); + ~QuicTransportSimpleServer(); + + int Run(); + + private: + // Schedules a ReadPackets() call on the next iteration of the event loop. + void ScheduleReadPackets(); + // Reads a fixed number of packets and then reschedules itself. + void ReadPackets(); + // Called when an asynchronous read from the socket is complete. + void OnReadComplete(int result); + // Passes the most recently read packet into the dispatcher. + void ProcessReadPacket(int result); + + const int port_; + + quic::QuicVersionManager version_manager_; + quic::QuicChromiumClock* clock_; // Not owned. + quic::QuicConfig config_; + quic::QuicCryptoServerConfig crypto_config_; + + quic::QuicTransportSimpleServerDispatcher dispatcher_; + std::unique_ptr<UDPServerSocket> socket_; + IPEndPoint server_address_; + + // Results of the potentially asynchronous read operation. + scoped_refptr<IOBufferWithSize> read_buffer_; + IPEndPoint client_address_; + + base::WeakPtrFactory<QuicTransportSimpleServer> weak_factory_{this}; +}; + +} // namespace net + +#endif // NET_TOOLS_QUIC_QUIC_TRANSPORT_SIMPLE_SERVER_H_
diff --git a/net/tools/quic/quic_transport_simple_server_bin.cc b/net/tools/quic/quic_transport_simple_server_bin.cc new file mode 100644 index 0000000..f2537458 --- /dev/null +++ b/net/tools/quic/quic_transport_simple_server_bin.cc
@@ -0,0 +1,61 @@ +// Copyright (c) 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/string_split.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h" +#include "net/tools/quic/quic_transport_simple_server.h" +#include "url/gurl.h" + +DEFINE_QUIC_COMMAND_LINE_FLAG(int, port, 20557, "The port to listen on."); + +DEFINE_QUIC_COMMAND_LINE_FLAG( + std::string, + mode, + "discard", + "The mode used by the SimpleServer. Can be \"echo\" or \"discard\"."); + +DEFINE_QUIC_COMMAND_LINE_FLAG(std::string, + accepted_origins, + "", + "Comma-separated list of accepted origins"); + +int main(int argc, char** argv) { + const char* usage = "quic_transport_simple_server"; + QuicSystemEventLoop event_loop("quic_transport_simple_server"); + std::vector<std::string> non_option_args = + quic::QuicParseCommandLineFlags(usage, argc, argv); + if (!non_option_args.empty()) { + quic::QuicPrintCommandLineFlagHelp(usage); + return 0; + } + + std::string mode_text = GetQuicFlag(FLAGS_mode); + quic::QuicTransportSimpleServerSession::Mode mode; + if (mode_text == "discard") { + mode = quic::QuicTransportSimpleServerSession::DISCARD; + } else if (mode_text == "echo") { + mode = quic::QuicTransportSimpleServerSession::ECHO; + } else { + LOG(ERROR) << "Invalid mode specified: " << mode_text; + return 1; + } + + std::string accepted_origins_text = GetQuicFlag(FLAGS_accepted_origins); + std::vector<url::Origin> accepted_origins; + for (const base::StringPiece& origin : + base::SplitStringPiece(accepted_origins_text, ",", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY)) { + GURL url{origin}; + if (!url.is_valid()) { + LOG(ERROR) << "Failed to parse origin specified: " << origin; + return 1; + } + accepted_origins.push_back(url::Origin::Create(url)); + } + + net::QuicTransportSimpleServer server(GetQuicFlag(FLAGS_port), mode, + accepted_origins); + return server.Run(); +}
diff --git a/remoting/host/mac/permission_wizard.h b/remoting/host/mac/permission_wizard.h index 2c68249b..e53e4bc 100644 --- a/remoting/host/mac/permission_wizard.h +++ b/remoting/host/mac/permission_wizard.h
@@ -6,8 +6,9 @@ #define REMOTING_HOST_MAC_PERMISSION_WIZARD_H_ #include <memory> +#include <string> -#include "base/macros.h" +#include "base/callback.h" #include "base/memory/scoped_refptr.h" namespace base { @@ -21,21 +22,46 @@ // needed MacOS permissions for the host process. class PermissionWizard final { public: - PermissionWizard(); + class Impl; + + // Callback for the Delegate to inform this class whether a permission was + // granted. + using ResultCallback = base::OnceCallback<void(bool granted)>; + + // Interface to delegate the permission-checks. This will be invoked to test + // each permission, and will return (via callback) whether the permission was + // granted. + class Delegate { + public: + virtual ~Delegate() = default; + + // Returns the name of the bundle that needs to be granted permission, as + // it would appear in the System Preferences applet. This will be included + // in the dialog's instructional text. + virtual std::string GetBundleName() = 0; + + // These checks will be invoked on the UI thread, and the result should be + // returned to the callback on the same thread. + // They should cause the bundle-name to be added to System Preferences + // applet. As far as possible, the check should not trigger a system prompt, + // but this may be unavoidable. + virtual void CheckAccessibilityPermission(ResultCallback onResult) = 0; + virtual void CheckScreenRecordingPermission(ResultCallback onResult) = 0; + }; + + explicit PermissionWizard(std::unique_ptr<Delegate> checker); + PermissionWizard(const PermissionWizard&) = delete; + PermissionWizard& operator=(const PermissionWizard&) = delete; ~PermissionWizard(); void Start(scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); private: - class Impl; - // Private implementation, to hide the Objective-C and Cocoa objects from C++ // callers. std::unique_ptr<Impl> impl_; scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(PermissionWizard); }; } // namespace mac
diff --git a/remoting/host/mac/permission_wizard.mm b/remoting/host/mac/permission_wizard.mm index 29791029..289361f8 100644 --- a/remoting/host/mac/permission_wizard.mm +++ b/remoting/host/mac/permission_wizard.mm
@@ -7,15 +7,28 @@ #import <Cocoa/Cocoa.h> #include "base/bind.h" +#include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/task/post_task.h" +#include "base/time/time.h" +#include "base/timer/timer.h" #include "remoting/base/string_resources.h" #include "ui/base/cocoa/window_size_constants.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util_mac.h" +using remoting::mac::PermissionWizard; +using Delegate = PermissionWizard::Delegate; +using ResultCallback = PermissionWizard::ResultCallback; + namespace { +// Interval between permission checks, used to update the UI when the user +// grants permission. +constexpr base::TimeDelta kPollingInterval = base::TimeDelta::FromSeconds(1); + // The steps of the wizard. enum class WizardPage { ACCESSIBILITY, @@ -27,12 +40,99 @@ @interface PermissionWizardController : NSWindowController -- (instancetype)initWithWindow:(NSWindow*)window; +- (instancetype)initWithWindow:(NSWindow*)window + impl:(PermissionWizard::Impl*)impl; - (void)hide; -- (void)initializeWindow; +- (void)start; + +// Used by C++ PermissionWizardImpl to provide the result of a permission check +// to the WindowController. +- (void)onPermissionCheckResult:(bool)result; @end +namespace remoting { +namespace mac { + +// C++ implementation of the PermissionWizard. +class PermissionWizard::Impl { + public: + explicit Impl(std::unique_ptr<PermissionWizard::Delegate> checker); + ~Impl(); + + void Start(); + + std::string GetBundleName(); + + // Called by PermissionWizardController to initiate permission checks. The + // result will be passed back via onPermissionCheckResult(). + void CheckAccessibilityPermission(base::TimeDelta delay); + void CheckScreenRecordingPermission(base::TimeDelta delay); + + private: + void CheckAccessibilityPermissionNow(); + void CheckScreenRecordingPermissionNow(); + + void OnPermissionCheckResult(bool result); + + PermissionWizardController* window_controller_ = nil; + std::unique_ptr<Delegate> checker_; + base::OneShotTimer timer_; + base::WeakPtrFactory<Impl> weak_factory_{this}; +}; + +PermissionWizard::Impl::Impl( + std::unique_ptr<PermissionWizard::Delegate> checker) + : checker_(std::move(checker)) {} + +PermissionWizard::Impl::~Impl() { + [window_controller_ hide]; + [window_controller_ release]; +} + +void PermissionWizard::Impl::Start() { + NSWindow* window = + [[[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater + styleMask:NSWindowStyleMaskTitled + backing:NSBackingStoreBuffered + defer:NO] autorelease]; + window_controller_ = [[PermissionWizardController alloc] initWithWindow:window + impl:this]; + [window_controller_ start]; +} + +std::string PermissionWizard::Impl::GetBundleName() { + return checker_->GetBundleName(); +} + +void PermissionWizard::Impl::CheckAccessibilityPermission( + base::TimeDelta delay) { + timer_.Start(FROM_HERE, delay, this, &Impl::CheckAccessibilityPermissionNow); +} + +void PermissionWizard::Impl::CheckScreenRecordingPermission( + base::TimeDelta delay) { + timer_.Start(FROM_HERE, delay, this, + &Impl::CheckScreenRecordingPermissionNow); +} + +void PermissionWizard::Impl::CheckAccessibilityPermissionNow() { + checker_->CheckAccessibilityPermission(base::BindOnce( + &Impl::OnPermissionCheckResult, weak_factory_.GetWeakPtr())); +} + +void PermissionWizard::Impl::CheckScreenRecordingPermissionNow() { + checker_->CheckScreenRecordingPermission(base::BindOnce( + &Impl::OnPermissionCheckResult, weak_factory_.GetWeakPtr())); +} + +void PermissionWizard::Impl::OnPermissionCheckResult(bool result) { + [window_controller_ onPermissionCheckResult:result]; +} + +} // namespace mac +} // namespace remoting + @implementation PermissionWizardController { NSTextField* _instructionText; NSButton* _cancelButton; @@ -44,12 +144,31 @@ // Whether the relevant permission has been granted for the current page. If // YES, the user will be able to advance to the next page of the wizard. BOOL _hasPermission; + + // Set to YES when the user cancels the wizard. This allows code to + // distinguish between "window hidden because it hasn't been presented yet" + // and "window hidden because user closed it". + BOOL _cancelled; + + // If YES, the wizard will automatically move onto the next page instead of + // showing the "Next" button when permission is granted. This allows the + // wizard to skip past any pages whose permission is already granted. + BOOL _autoAdvance; + + // Reference used for permission-checking. Its lifetime should outlast this + // Controller. + PermissionWizard::Impl* _impl; } -- (instancetype)initWithWindow:(NSWindow*)window { - self = [super initWithWindow:(NSWindow*)window]; +- (instancetype)initWithWindow:(NSWindow*)window + impl:(PermissionWizard::Impl*)impl { + DCHECK(window); + DCHECK(impl); + self = [super initWithWindow:window]; if (self) { + _impl = impl; _page = WizardPage::ACCESSIBILITY; + _autoAdvance = YES; } return self; } @@ -58,6 +177,13 @@ [self close]; } +- (void)start { + [self initializeWindow]; + + // Start polling for permission status. + [self requestPermissionCheck:base::TimeDelta()]; +} + - (void)initializeWindow { self.window.title = l10n_util::GetNSStringF(IDS_MAC_PERMISSION_WIZARD_TITLE, @@ -146,24 +272,29 @@ options:0 metrics:nil views:views]]; - - [self updateUI]; - - [self.window makeKeyAndOrderFront:NSApp]; - [self.window center]; } - (void)onCancel:(id)sender { + _cancelled = YES; [self hide]; } - (void)onNext:(id)sender { - NOTIMPLEMENTED(); + if (_page == WizardPage::ALL_SET) { + // OK button closes the window. + [self hide]; + return; + } + if (_hasPermission) { + [self advanceToNextPage]; + } else { + [self launchSystemPreferences]; + } } // Updates the dialog controls according to the object's state. - (void)updateUI { - // TODO(lambroslambrou): Parameterize the name of the app needing permission. + base::string16 bundleName = base::UTF8ToUTF16(_impl->GetBundleName()); switch (_page) { case WizardPage::ACCESSIBILITY: _instructionText.stringValue = l10n_util::GetNSStringF( @@ -171,7 +302,7 @@ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), l10n_util::GetStringUTF16( IDS_ACCESSIBILITY_PERMISSION_DIALOG_OPEN_BUTTON), - base::SysNSStringToUTF16(@"ChromeRemoteDesktopHost")); + bundleName); break; case WizardPage::SCREEN_RECORDING: _instructionText.stringValue = l10n_util::GetNSStringF( @@ -179,7 +310,7 @@ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), l10n_util::GetStringUTF16( IDS_SCREEN_RECORDING_PERMISSION_DIALOG_OPEN_BUTTON), - base::SysNSStringToUTF16(@"ChromeRemoteDesktopHost")); + bundleName); break; case WizardPage::ALL_SET: _instructionText.stringValue = @@ -221,42 +352,110 @@ } } +- (void)advanceToNextPage { + DCHECK(_hasPermission); + switch (_page) { + case WizardPage::ACCESSIBILITY: + _page = WizardPage::SCREEN_RECORDING; + break; + case WizardPage::SCREEN_RECORDING: + _page = WizardPage::ALL_SET; + [self updateUI]; + return; + default: + NOTREACHED(); + } + + // Kick off a permission check for the new page. The UI will be updated only + // after the result comes back. + _hasPermission = NO; + _autoAdvance = YES; + [self requestPermissionCheck:base::TimeDelta()]; +} + +- (void)requestPermissionCheck:(base::TimeDelta)delay { + DCHECK(!_hasPermission); + switch (_page) { + case WizardPage::ACCESSIBILITY: + _impl->CheckAccessibilityPermission(delay); + break; + case WizardPage::SCREEN_RECORDING: + _impl->CheckScreenRecordingPermission(delay); + return; + default: + NOTREACHED(); + } +} + +- (void)launchSystemPreferences { + switch (_page) { + case WizardPage::ACCESSIBILITY: + // Launch the Security and Preferences pane with Accessibility selected. + [[NSWorkspace sharedWorkspace] + openURL:[NSURL URLWithString: + @"x-apple.systempreferences:com.apple." + @"preference.security?Privacy_Accessibility"]]; + break; + case WizardPage::SCREEN_RECORDING: + // Launch the Security and Preferences pane with Screen Recording + // selected. + [[NSWorkspace sharedWorkspace] + openURL:[NSURL URLWithString: + @"x-apple.systempreferences:com.apple." + @"preference.security?Privacy_ScreenCapture"]]; + return; + default: + NOTREACHED(); + } +} + +- (void)onPermissionCheckResult:(bool)result { + if (_cancelled) + return; + + _hasPermission = result; + + if (_hasPermission && _autoAdvance) { + // Skip showing the "Next" button, and immediately kick off a permission + // check for the next page, if any. + [self advanceToNextPage]; + return; + } + + // Update the whole UI, not just the "Next" button, in case a different page + // was previously shown. + [self updateUI]; + + if (!_hasPermission) { + // Permission denied, so turn off auto-advance for this page, and present + // the dialog to the user if needed. After the user grants this permission, + // they should be able to click "Next" to acknowledge and advance the + // wizard. Note that, if all permissions are granted, the user will not + // see the wizard at all (not even the ALL_SET page). A dialog is only + // shown when a permission-check fails. + _autoAdvance = NO; + if (![self window].visible) { + [self presentWindow]; + } + + // Keep polling until permission is granted. + [self requestPermissionCheck:kPollingInterval]; + } +} + +- (void)presentWindow { + [self.window makeKeyAndOrderFront:NSApp]; + [self.window center]; + [self showWindow:nil]; +} + @end namespace remoting { namespace mac { -class PermissionWizard::Impl { - public: - Impl() = default; - ~Impl(); - - void Start(); - - private: - PermissionWizardController* window_controller_ = nil; -}; - -PermissionWizard::Impl::~Impl() { - // PermissionWizardController is responsible for releasing itself in its - // windowWillClose: method. - [window_controller_ hide]; - window_controller_ = nil; -} - -void PermissionWizard::Impl::Start() { - NSWindow* window = - [[[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater - styleMask:NSWindowStyleMaskTitled - backing:NSBackingStoreBuffered - defer:NO] autorelease]; - window_controller_ = - [[PermissionWizardController alloc] initWithWindow:window]; - [window_controller_ initializeWindow]; - [window_controller_ showWindow:nil]; -} - -PermissionWizard::PermissionWizard() = default; +PermissionWizard::PermissionWizard(std::unique_ptr<Delegate> checker) + : impl_(std::make_unique<PermissionWizard::Impl>(std::move(checker))) {} PermissionWizard::~PermissionWizard() { ui_task_runner_->DeleteSoon(FROM_HERE, impl_.release()); @@ -265,10 +464,8 @@ void PermissionWizard::Start( scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { ui_task_runner_ = ui_task_runner; - impl_ = std::make_unique<PermissionWizard::Impl>(); - ui_task_runner->PostTask(FROM_HERE, - base::BindOnce(&PermissionWizard::Impl::Start, - base::Unretained(impl_.get()))); + ui_task_runner->PostTask( + FROM_HERE, base::BindOnce(&Impl::Start, base::Unretained(impl_.get()))); } } // namespace mac
diff --git a/remoting/host/win/worker_process_launcher_unittest.cc b/remoting/host/win/worker_process_launcher_unittest.cc index 744e11e8..78f756b 100644 --- a/remoting/host/win/worker_process_launcher_unittest.cc +++ b/remoting/host/win/worker_process_launcher_unittest.cc
@@ -27,18 +27,14 @@ #include "remoting/host/win/launch_process_with_token.h" #include "remoting/host/worker_process_ipc_delegate.h" #include "testing/gmock/include/gmock/gmock.h" -#include "testing/gmock_mutant.h" #include "testing/gtest/include/gtest/gtest.h" using base::win::ScopedHandle; using testing::_; using testing::AnyNumber; -using testing::CreateFunctor; -using testing::DoAll; using testing::Expectation; using testing::Invoke; using testing::InvokeWithoutArgs; -using testing::Return; namespace remoting { @@ -434,12 +430,10 @@ Expectation first_connect = EXPECT_CALL(server_listener_, OnChannelConnected(_)) .Times(2) - .WillOnce(InvokeWithoutArgs(CreateFunctor( - &WorkerProcessLauncherTest::TerminateWorker, - base::Unretained(this), - CONTROL_C_EXIT))) - .WillOnce(InvokeWithoutArgs(this, - &WorkerProcessLauncherTest::StopWorker)); + .WillOnce( + InvokeWithoutArgs([=]() { TerminateWorker(CONTROL_C_EXIT); })) + .WillOnce( + InvokeWithoutArgs(this, &WorkerProcessLauncherTest::StopWorker)); EXPECT_CALL(server_listener_, OnPermanentError(_)) .Times(0); @@ -485,10 +479,8 @@ EXPECT_CALL(server_listener_, OnChannelConnected(_)) .Times(1) - .WillOnce(InvokeWithoutArgs(CreateFunctor( - &WorkerProcessLauncherTest::TerminateWorker, - base::Unretained(this), - kMinPermanentErrorExitCode))); + .WillOnce(InvokeWithoutArgs( + [=] { TerminateWorker(kMinPermanentErrorExitCode); })); EXPECT_CALL(server_listener_, OnPermanentError(_)) .Times(1) .WillOnce(InvokeWithoutArgs(this, @@ -516,10 +508,8 @@ EXPECT_CALL(client_listener_, OnCrash(_, _, _)) .Times(1) - .WillOnce(InvokeWithoutArgs(CreateFunctor( - &WorkerProcessLauncherTest::TerminateWorker, - base::Unretained(this), - EXCEPTION_BREAKPOINT))); + .WillOnce( + InvokeWithoutArgs([=]() { TerminateWorker(EXCEPTION_BREAKPOINT); })); EXPECT_CALL(server_listener_, OnWorkerProcessStopped()) .Times(1);
diff --git a/remoting/proto/BUILD.gn b/remoting/proto/BUILD.gn index 07891d1..b905e5c 100644 --- a/remoting/proto/BUILD.gn +++ b/remoting/proto/BUILD.gn
@@ -19,6 +19,7 @@ "event.proto", "file_transfer.proto", "internal.proto", + "layout_key_function.proto", "mux.proto", "process_stats.proto", "test_data_channel_manager.proto",
diff --git a/remoting/proto/control.proto b/remoting/proto/control.proto index 8829120..15e6a7b 100644 --- a/remoting/proto/control.proto +++ b/remoting/proto/control.proto
@@ -10,6 +10,8 @@ package remoting.protocol; +import "layout_key_function.proto"; + // Set the host resolution to match the client. If none of the fields are // present, restore the host resolution instead. message ClientResolution { @@ -137,3 +139,23 @@ // True if this is the default display. optional bool is_default = 8; } + +// Next ID: 2 +message KeyboardLayout { + // Next ID: 3 + message KeyAction { + oneof action { + LayoutKeyFunction function = 1; + string character = 2; + } + } + + // Next ID: 2 + message KeyBehavior { + // Maps shift level to key action. + map<int32, KeyAction> actions = 1; + } + + // Map USB code to key behavior. + map<uint32, KeyBehavior> keys = 1; +}
diff --git a/remoting/proto/file_transfer.proto b/remoting/proto/file_transfer.proto index 33ae17c..ce2aa9c 100644 --- a/remoting/proto/file_transfer.proto +++ b/remoting/proto/file_transfer.proto
@@ -1,3 +1,7 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + syntax = "proto2"; option optimize_for = LITE_RUNTIME;
diff --git a/remoting/proto/layout_key_function.proto b/remoting/proto/layout_key_function.proto new file mode 100644 index 0000000..f6e2498a --- /dev/null +++ b/remoting/proto/layout_key_function.proto
@@ -0,0 +1,103 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package remoting.protocol; + +// List of key functions to identify functional (non-character-generating) keys +// in the keyboard layout. This list is not meant to be exhaustive, but is meant +// to include functions typically assigned to the standard keyboard keys on +// common keyboard layouts. + +// Next ID: 61 +enum LayoutKeyFunction { + // The key action is a function whose type is not recognized. + UNKNOWN = 0; + + // Modifier keys + CONTROL = 1; + ALT = 2; + SHIFT = 3; + // Windows key on Windows, command on Mac, super on Linux. + META = 4; + // Level 3 shift. Commonly labeled AltGr. + ALT_GR = 5; + // Level 5 shift. Used on some Linux layouts. (Level 4 is AltGr + Shift.) + MOD5 = 6; + // On Linux, this defaults to Shift + AltGr (which is distinct from AltGr + + // Shift, which accesses level 4), but it can also be assigned to + // a distinct key. + COMPOSE = 7; + + // Locks + NUM_LOCK = 8; + CAPS_LOCK = 9; + SCROLL_LOCK = 10; + + // Editing and navigation keys + BACKSPACE = 11; + ENTER = 12; + TAB = 13; + INSERT = 14; + DELETE_ = 15; + HOME = 16; + END = 17; + PAGE_UP = 18; + PAGE_DOWN = 19; + CLEAR = 20; + ARROW_UP = 21; + ARROW_DOWN = 22; + ARROW_LEFT = 23; + ARROW_RIGHT = 24; + + // Function keys + F1 = 25; + F2 = 26; + F3 = 27; + F4 = 28; + F5 = 29; + F6 = 30; + F7 = 31; + F8 = 32; + F9 = 33; + F10 = 34; + F11 = 35; + F12 = 36; + F13 = 37; + F14 = 38; + F15 = 39; + F16 = 40; + F17 = 41; + F18 = 42; + F19 = 43; + F20 = 44; + F21 = 45; + F22 = 46; + F23 = 47; + F24 = 48; + + // Other common functional keys + ESCAPE = 49; + CONTEXT_MENU = 50; + PAUSE = 51; + PRINT_SCREEN = 52; + + // Language-specific keys + // Japanese + HANKAKU_ZENKAKU_KANJI = 53; // Backquote + HENKAN = 54; // Convert + MUHENKAN = 55; // NonConvert + KATAKANA_HIRAGANA_ROMAJI = 56; // KanaMode + KANA = 57; // Lang1 (Mac keyboard) + // Note: Windows only identifies the key as "Caps Lock", so the Windows host + // currently sends the CAPS_LOCK function even for shift level 1 (unshifted) + // and doesn't use this function. + EISU = 58; // Unshifted CapsLock (Windows), Lang2 (Mac keyboard) + // Korean + HAN_YEONG = 59; // Lang1 + HANJA = 60; // Lang2 +}
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 765693c..9c6d3e2 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -513,7 +513,7 @@ if (network_service()) network_service_client = network_service()->client(); - restricted_cookie_manager_bindings_.AddBinding( + restricted_cookie_manager_receivers_.Add( std::make_unique<RestrictedCookieManager>( role, url_request_context_->cookie_store(), &cookie_manager_->cookie_settings(), origin, site_for_cookies,
diff --git a/services/network/network_context.h b/services/network/network_context.h index decf283..c240998 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h
@@ -28,7 +28,6 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" -#include "mojo/public/cpp/bindings/strong_binding_set.h" #include "mojo/public/cpp/bindings/unique_receiver_set.h" #include "net/cert/cert_verifier.h" #include "net/cert/cert_verify_result.h" @@ -563,8 +562,8 @@ // Ordering: this must be after |cookie_manager_| since it points to its // CookieSettings object. - mojo::StrongBindingSet<mojom::RestrictedCookieManager> - restricted_cookie_manager_bindings_; + mojo::UniqueReceiverSet<mojom::RestrictedCookieManager> + restricted_cookie_manager_receivers_; int current_resource_scheduler_client_id_ = 0;
diff --git a/storage/browser/quota/quota_settings.cc b/storage/browser/quota/quota_settings.cc index 5e7ff04..b38cc76 100644 --- a/storage/browser/quota/quota_settings.cc +++ b/storage/browser/quota/quota_settings.cc
@@ -34,23 +34,23 @@ int64_t physical_memory_amount) { // The incognito pool size is a fraction of the amount of system memory, // and the amount is capped to a hard limit. - double kIncognitoPoolSizeRatio = 0.1; // 10% - int64_t kMaxIncognitoPoolSize = 300 * kMBytes; + double incognito_pool_size_ratio = 0.1; // 10% + int64_t max_incognito_pool_size = 300 * kMBytes; if (base::FeatureList::IsEnabled(features::kIncognitoDynamicQuota)) { const double lower_bound = features::kIncognitoQuotaRatioLowerBound.Get(); const double upper_bound = features::kIncognitoQuotaRatioUpperBound.Get(); - kIncognitoPoolSizeRatio = + incognito_pool_size_ratio = lower_bound + (base::RandDouble() * (upper_bound - lower_bound)); - kMaxIncognitoPoolSize = std::numeric_limits<int64_t>::max(); + max_incognito_pool_size = std::numeric_limits<int64_t>::max(); } else { - kMaxIncognitoPoolSize = - RandomizeByPercent(kMaxIncognitoPoolSize, kRandomizedPercentage); + max_incognito_pool_size = + RandomizeByPercent(max_incognito_pool_size, kRandomizedPercentage); } storage::QuotaSettings settings; settings.pool_size = std::min( - kMaxIncognitoPoolSize, - static_cast<int64_t>(physical_memory_amount * kIncognitoPoolSizeRatio)); + max_incognito_pool_size, + static_cast<int64_t>(physical_memory_amount * incognito_pool_size_ratio)); settings.per_host_quota = settings.pool_size / 3; settings.session_only_per_host_quota = settings.per_host_quota; settings.refresh_interval = base::TimeDelta::Max();
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index f8284f0..3dcfe5c 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -5295,6 +5295,24 @@ ] } ], + "SafeBrowsingPasswordProtectionForSavedPasswords": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "SafeBrowsingPasswordProtectionForSavedPasswords" + ] + } + ] + } + ], "SafeBrowsingPasswordProtectionForSignedInUsers": [ { "platforms": [ @@ -5724,7 +5742,7 @@ ], "experiments": [ { - "name": "Enabled", + "name": "Enabled_20191107", "enable_features": [ "SetLowPriorityForBeacon" ]
diff --git a/third_party/.gitignore b/third_party/.gitignore index d9f9f32..18645e0 100644 --- a/third_party/.gitignore +++ b/third_party/.gitignore
@@ -84,7 +84,6 @@ /freetype/src /fuchsia-sdk/images /fuchsia-sdk/sdk -/fuchsia-sdk-arm64 /gestures/gestures /gles2_conform /glfw/src @@ -195,7 +194,6 @@ /python_26 /pywebsocket/src /pywebsocket/src -/qemu-linux-arm64 /qemu-linux-x64 /qemu-mac-x64 /quic_trace/src
diff --git a/third_party/blink/public/platform/task_type.h b/third_party/blink/public/platform/task_type.h index a3a275d..b78cab7a 100644 --- a/third_party/blink/public/platform/task_type.h +++ b/third_party/blink/public/platform/task_type.h
@@ -231,6 +231,10 @@ // WebSchedulingTaskQueues. kExperimentalWebScheduling = 67, + // Tasks used to control frame lifecycle - they should run even when the frame + // is frozen. + kInternalFrameLifecycleControl = 68, + /////////////////////////////////////// // The following task types are only for thread-local queues. /////////////////////////////////////// @@ -254,7 +258,7 @@ kWorkerThreadTaskQueueV8 = 47, kWorkerThreadTaskQueueCompositor = 48, - kCount = 68, + kCount = 69, }; } // namespace blink
diff --git a/third_party/blink/renderer/bindings/BUILD.gn b/third_party/blink/renderer/bindings/BUILD.gn index 0609966..9e2797f6 100644 --- a/third_party/blink/renderer/bindings/BUILD.gn +++ b/third_party/blink/renderer/bindings/BUILD.gn
@@ -66,16 +66,11 @@ invoker.component, "--output", rebase_path(invoker.output, root_build_dir), - "--cached-parser-tables-dir", - rebase_path(bindings_scripts_output_dir, root_build_dir), ] if (defined(invoker.deps)) { deps = invoker.deps - } else { - deps = [] } - deps += [ "scripts:cached_lex_yacc_tables" ] } }
diff --git a/third_party/blink/renderer/bindings/scripts/blink_idl_lexer.py b/third_party/blink/renderer/bindings/scripts/blink_idl_lexer.py index e31b171..c14b145 100644 --- a/third_party/blink/renderer/bindings/scripts/blink_idl_lexer.py +++ b/third_party/blink/renderer/bindings/scripts/blink_idl_lexer.py
@@ -79,22 +79,10 @@ # Turn off optimization and caching to help debugging optimize = False outputdir = None - - # Ensure that if we are writing tables, we got a real outputdir. - # Because of the way PLY loads the lexer (via import), it can - # be loaded from anywhere in sys.path; requiring an outputdir - # can help minimize the likelihood of inconsistencies between - # scripts. - assert debug or outputdir - if outputdir: # Need outputdir in path because lex imports the cached lex table - # as a Python module. Putting this at the front of sys.path - # helps ensures that we get the one in outputdir, and not some - # module by the same name that might exist elsewhere in path, - # though it won't guarantee it. - if sys.path[0] != outputdir: - sys.path.insert(0, outputdir) + # as a Python module + sys.path.append(outputdir) if rewrite_tables: tablefile_root = os.path.join(outputdir, LEXTAB)
diff --git a/third_party/blink/renderer/bindings/scripts/blink_idl_parser.py b/third_party/blink/renderer/bindings/scripts/blink_idl_parser.py index 23ec694..a0c2054f 100644 --- a/third_party/blink/renderer/bindings/scripts/blink_idl_parser.py +++ b/third_party/blink/renderer/bindings/scripts/blink_idl_parser.py
@@ -93,14 +93,6 @@ outputdir = None picklefile = None write_tables = True - - # Ensure that if we are writing tables, we got a real outputdir. - # Because of the way PLY loads the lexer (via import), it can - # be loaded from anywhere in sys.path; requiring an outputdir - # can help minimize the likelihood of inconsistencies between - # scripts. - assert debug or not write_tables or outputdir - if outputdir: picklefile = picklefile or os.path.join(outputdir, 'parsetab.pickle') if rewrite_tables:
diff --git a/third_party/blink/renderer/bindings/scripts/blink_idl_parser_test.py b/third_party/blink/renderer/bindings/scripts/blink_idl_parser_test.py index 830637cb..309b463 100644 --- a/third_party/blink/renderer/bindings/scripts/blink_idl_parser_test.py +++ b/third_party/blink/renderer/bindings/scripts/blink_idl_parser_test.py
@@ -16,7 +16,6 @@ def test_missing_semicolon_between_definitions(self): # No semicolon after enum definition. text = '''enum TestEnum { "value" } dictionary TestDictionary {};''' - # We use debug=True to not have to worry about generated parser tables. - parser = BlinkIDLParser(debug=True) + parser = BlinkIDLParser() parser.ParseText(filename='', data=text) self.assertGreater(parser.GetErrors(), 0)
diff --git a/third_party/blink/renderer/bindings/scripts/collect_idl_files.py b/third_party/blink/renderer/bindings/scripts/collect_idl_files.py index 0a72e8a..c6922e5 100644 --- a/third_party/blink/renderer/bindings/scripts/collect_idl_files.py +++ b/third_party/blink/renderer/bindings/scripts/collect_idl_files.py
@@ -28,8 +28,6 @@ help="specify a component name") parser.add_option('--output', type='string', help="the output file path") - parser.add_option('--cached-parser-tables-dir', - help='location of the generated LEX and YACC files') options, args = parser.parse_args() if options.idl_list_file is None: @@ -38,9 +36,6 @@ parser.error("Specify the output file path with --output.") if options.component is None: parser.error("Specify a component with --component.") - if options.cached_parser_tables_dir is None: - parser.error("Specify the location of the generated " - "LEX and YACC files with --cached-parser-tables-dir.") if args: parser.error("Unknown arguments {}".format(args)) @@ -52,7 +47,7 @@ options, _ = parse_options() filepaths = utilities.read_idl_files_list_from_file(options.idl_list_file) - parser = blink_idl_parser.BlinkIDLParser(outputdir=options.cached_parser_tables_dir) + parser = blink_idl_parser.BlinkIDLParser() ast_group = web_idl.AstGroup(web_idl.Component(options.component)) for filepath in filepaths: ast_group.add_ast_node(blink_idl_parser.parse_file(parser, filepath))
diff --git a/third_party/blink/renderer/bindings/scripts/idl_reader.py b/third_party/blink/renderer/bindings/scripts/idl_reader.py index bbb4ad9..3b0895ed 100644 --- a/third_party/blink/renderer/bindings/scripts/idl_reader.py +++ b/third_party/blink/renderer/bindings/scripts/idl_reader.py
@@ -81,7 +81,7 @@ class IdlReader(object): - def __init__(self, interfaces_info=None, outputdir='', debug=False): + def __init__(self, interfaces_info=None, outputdir=''): self.extended_attribute_validator = IDLExtendedAttributeValidator() self.interfaces_info = interfaces_info @@ -90,7 +90,7 @@ else: self.interface_dependency_resolver = None - self.parser = BlinkIDLParser(outputdir=outputdir, debug=debug) + self.parser = BlinkIDLParser(outputdir=outputdir) def read_idl_definitions(self, idl_filename): """Returns a dictionary whose key is component and value is an IdlDefinitions object for an IDL file, including all dependencies."""
diff --git a/third_party/blink/renderer/core/html/forms/OWNERS b/third_party/blink/renderer/core/html/forms/OWNERS index 53439ec87..cbe63714 100644 --- a/third_party/blink/renderer/core/html/forms/OWNERS +++ b/third_party/blink/renderer/core/html/forms/OWNERS
@@ -1,5 +1,6 @@ keishi@chromium.org tkent@chromium.org +masonfreed@chromium.org # TEAM: dom-dev@chromium.org # COMPONENT: Blink>Forms
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index 67aa26be..aceefa8 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1416,16 +1416,13 @@ // TODO(szager): Check occlusion information propagated from out-of-process // parent frame. - // TODO(szager): Remove CHECK's after diagnosing crash. - PaintLayer* enclosing_layer = EnclosingLayer(); - CHECK(enclosing_layer); - CHECK(enclosing_layer->GetLayoutObject() - .FirstFragment() - .HasLocalBorderBoxProperties()); - PropertyTreeState paint_properties = EnclosingLayer() - ->GetLayoutObject() - .FirstFragment() - .LocalBorderBoxProperties(); + auto& first_fragment = EnclosingLayer()->GetLayoutObject().FirstFragment(); + // This can happen for an iframe element which is outside the viewport and has + // therefore never been painted. In that case, we do the safe thing -- report + // it as having distorting visual effects. + if (!first_fragment.HasLocalBorderBoxProperties()) + return true; + auto paint_properties = first_fragment.LocalBorderBoxProperties(); // No filters, no blends, no opacity < 100%. for (const auto* effect = &paint_properties.Effect().Unalias(); effect; @@ -1438,15 +1435,10 @@ } } - // TODO(szager): Remove CHECK's after diagnosing crash. - CHECK(GetDocument().IsActive()); - LocalFrame* frame = GetDocument().GetFrame(); - CHECK(frame); - LayoutView* layout_view = frame->LocalFrameRoot().ContentLayoutObject(); - CHECK(layout_view); - CHECK(layout_view->FirstFragment().HasLocalBorderBoxProperties()); - PropertyTreeState root_properties = - layout_view->FirstFragment().LocalBorderBoxProperties(); + auto& local_frame_root = GetDocument().GetFrame()->LocalFrameRoot(); + auto& root_fragment = local_frame_root.ContentLayoutObject()->FirstFragment(); + CHECK(root_fragment.HasLocalBorderBoxProperties()); + PropertyTreeState root_properties = root_fragment.LocalBorderBoxProperties(); // The only allowed transforms are 2D translation and proportional up-scaling. const auto& translation_2d_or_matrix =
diff --git a/third_party/blink/renderer/core/layout/layout_view.cc b/third_party/blink/renderer/core/layout/layout_view.cc index 9a16efd1..9c631324 100644 --- a/third_party/blink/renderer/core/layout/layout_view.cc +++ b/third_party/blink/renderer/core/layout/layout_view.cc
@@ -462,12 +462,11 @@ void LayoutView::InvalidatePaintForViewAndCompositedLayers() { SetSubtreeShouldDoFullPaintInvalidation(); - // The only way we know how to hit these ASSERTS below this point is via the - // Chromium OS login screen. - DisableCompositingQueryAsserts disabler; - - if (Compositor()->InCompositingMode()) - Compositor()->FullyInvalidatePaint(); + if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { + DisableCompositingQueryAsserts disabler; + if (Compositor()->InCompositingMode()) + Compositor()->FullyInvalidatePaint(); + } } bool LayoutView::MapToVisualRectInAncestorSpace(
diff --git a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc index d5b03a11..af85d18 100644 --- a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc +++ b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
@@ -652,6 +652,8 @@ } void PaintLayerCompositor::FullyInvalidatePaint() { + DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()); + // We're walking all compositing layers and invalidating them, so there's // no need to have up-to-date compositing state. DisableCompositingQueryAsserts disabler;
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index 317a067..c475510 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -290,10 +290,14 @@ if (!GetLayoutObject().HasFilterInducingProperty()) return false; - // https://code.google.com/p/chromium/issues/detail?id=343759 - DisableCompositingQueryAsserts disabler; - return !GetCompositedLayerMapping() || - GetCompositingState() != kPaintsIntoOwnBacking; + if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { + // https://code.google.com/p/chromium/issues/detail?id=343759 + DisableCompositingQueryAsserts disabler; + return !GetCompositedLayerMapping() || + GetCompositingState() != kPaintsIntoOwnBacking; + } else { + return true; + } } PhysicalOffset PaintLayer::SubpixelAccumulation() const { @@ -319,12 +323,7 @@ ClearClipRects(); UpdateLayerPositionRecursive(); - { - // FIXME: Remove incremental compositing updates after fixing the - // chicken/egg issues, https://crbug.com/343756 - DisableCompositingQueryAsserts disabler; - UpdatePaginationRecursive(EnclosingPaginationLayer()); - } + UpdatePaginationRecursive(EnclosingPaginationLayer()); } void PaintLayer::UpdateLayerPositionRecursive() {
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni index 9cb9f435..b6ee2a0 100644 --- a/third_party/blink/renderer/modules/modules_idl_files.gni +++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -432,7 +432,6 @@ "webgl/webgl_draw_buffers.idl", "webgl/webgl_framebuffer.idl", "webgl/webgl_lose_context.idl", - "webgl/webgl_multi_draw_instanced.idl", "webgl/webgl_multi_draw.idl", "webgl/webgl_program.idl", "webgl/webgl_query.idl",
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc index 944a4751..b11f244 100644 --- a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc +++ b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc
@@ -100,9 +100,10 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame( const webrtc::VideoFrame& incoming_frame) { const bool render_immediately = incoming_frame.timestamp_us() == 0; + const base::TimeTicks current_time = base::TimeTicks::Now(); const base::TimeDelta incoming_timestamp = render_immediately - ? base::TimeTicks::Now() - base::TimeTicks() + ? current_time - base::TimeTicks() : base::TimeDelta::FromMicroseconds(incoming_frame.timestamp_us()); const base::TimeTicks render_time = render_immediately ? base::TimeTicks() + incoming_timestamp @@ -208,8 +209,12 @@ video_frame->metadata()->SetTimeTicks( media::VideoFrameMetadata::REFERENCE_TIME, render_time); } - video_frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::DECODE_TIME, - base::TimeTicks::Now()); + video_frame->metadata()->SetTimeTicks( + media::VideoFrameMetadata::DECODE_END_TIME, current_time); + + video_frame->metadata()->SetDouble( + media::VideoFrameMetadata::RTP_TIMESTAMP, + static_cast<double>(incoming_frame.timestamp())); PostCrossThreadTask( *io_task_runner_, FROM_HERE,
diff --git a/third_party/blink/renderer/modules/webgl/BUILD.gn b/third_party/blink/renderer/modules/webgl/BUILD.gn index 286aca1..dfc0d63b 100644 --- a/third_party/blink/renderer/modules/webgl/BUILD.gn +++ b/third_party/blink/renderer/modules/webgl/BUILD.gn
@@ -99,8 +99,6 @@ "webgl_multi_draw.h", "webgl_multi_draw_common.cc", "webgl_multi_draw_common.h", - "webgl_multi_draw_instanced.cc", - "webgl_multi_draw_instanced.h", "webgl_object.cc", "webgl_object.h", "webgl_program.cc",
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc index 23713f10..188a24c 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc +++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc
@@ -33,7 +33,6 @@ #include "third_party/blink/renderer/modules/webgl/webgl_debug_shaders.h" #include "third_party/blink/renderer/modules/webgl/webgl_lose_context.h" #include "third_party/blink/renderer/modules/webgl/webgl_multi_draw.h" -#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.h" #include "third_party/blink/renderer/modules/webgl/webgl_video_texture.h" #include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h" @@ -143,8 +142,6 @@ RegisterExtension<WebGLDebugShaders>(webgl_debug_shaders_); RegisterExtension<WebGLLoseContext>(webgl_lose_context_); RegisterExtension<WebGLMultiDraw>(webgl_multi_draw_, kDraftExtension); - RegisterExtension<WebGLMultiDrawInstanced>(webgl_multi_draw_instanced_, - kDraftExtension); RegisterExtension<WebGLVideoTexture>(webgl_video_texture_, kDraftExtension); RegisterExtension<OVRMultiview2>(ovr_multiview2_); } @@ -167,7 +164,6 @@ visitor->Trace(webgl_debug_shaders_); visitor->Trace(webgl_lose_context_); visitor->Trace(webgl_multi_draw_); - visitor->Trace(webgl_multi_draw_instanced_); visitor->Trace(webgl_video_texture_); WebGL2RenderingContextBase::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h index 5765703e..6b5514f 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h +++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h
@@ -22,7 +22,6 @@ class WebGLDebugRendererInfo; class WebGLLoseContext; class WebGLMultiDraw; -class WebGLMultiDrawInstanced; class KHRParallelShaderCompile; class WebGLVideoTexture; @@ -82,7 +81,6 @@ Member<WebGLDebugShaders> webgl_debug_shaders_; Member<WebGLLoseContext> webgl_lose_context_; Member<WebGLMultiDraw> webgl_multi_draw_; - Member<WebGLMultiDrawInstanced> webgl_multi_draw_instanced_; Member<WebGLVideoTexture> webgl_video_texture_; };
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw.cc b/third_party/blink/renderer/modules/webgl/webgl_multi_draw.cc index cd2a88e4..9316eab 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_multi_draw.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw.cc
@@ -24,7 +24,9 @@ bool WebGLMultiDraw::Supported(WebGLRenderingContextBase* context) { return context->ExtensionsUtil()->SupportsExtension("GL_WEBGL_multi_draw") || - context->ExtensionsUtil()->SupportsExtension("GL_ANGLE_multi_draw"); + (context->ExtensionsUtil()->SupportsExtension("GL_ANGLE_multi_draw") && + context->ExtensionsUtil()->SupportsExtension( + "GL_ANGLE_instanced_arrays")); } const char* WebGLMultiDraw::ExtensionName() { @@ -78,4 +80,65 @@ mode, &counts[countsOffset], type, &offsets[offsetsOffset], drawcount); } +void WebGLMultiDraw::multiDrawArraysInstancedImpl( + GLenum mode, + const base::span<const int32_t>& firsts, + GLuint firstsOffset, + const base::span<const int32_t>& counts, + GLuint countsOffset, + const base::span<const int32_t>& instanceCounts, + GLuint instanceCountsOffset, + GLsizei drawcount) { + WebGLExtensionScopedContext scoped(this); + if (scoped.IsLost() || + !ValidateDrawcount(&scoped, "glMultiDrawArraysInstancedWEBGL", + drawcount) || + !ValidateArray(&scoped, "glMultiDrawArraysInstancedWEBGL", + "firstsOffset out of bounds", firsts.size(), firstsOffset, + drawcount) || + !ValidateArray(&scoped, "glMultiDrawArraysInstancedWEBGL", + "countsOffset out of bounds", counts.size(), countsOffset, + drawcount) || + !ValidateArray(&scoped, "glMultiDrawArraysInstancedWEBGL", + "instanceCountsOffset out of bounds", + instanceCounts.size(), instanceCountsOffset, drawcount)) { + return; + } + + scoped.Context()->ContextGL()->MultiDrawArraysInstancedWEBGL( + mode, &firsts[firstsOffset], &counts[countsOffset], + &instanceCounts[instanceCountsOffset], drawcount); +} + +void WebGLMultiDraw::multiDrawElementsInstancedImpl( + GLenum mode, + const base::span<const int32_t>& counts, + GLuint countsOffset, + GLenum type, + const base::span<const int32_t>& offsets, + GLuint offsetsOffset, + const base::span<const int32_t>& instanceCounts, + GLuint instanceCountsOffset, + GLsizei drawcount) { + WebGLExtensionScopedContext scoped(this); + if (scoped.IsLost() || + !ValidateDrawcount(&scoped, "glMultiDrawElementsInstancedWEBGL", + drawcount) || + !ValidateArray(&scoped, "glMultiDrawElementsInstancedWEBGL", + "countsOffset out of bounds", counts.size(), countsOffset, + drawcount) || + !ValidateArray(&scoped, "glMultiDrawElementsInstancedWEBGL", + "offsetsOffset out of bounds", offsets.size(), + offsetsOffset, drawcount) || + !ValidateArray(&scoped, "glMultiDrawElementsInstancedWEBGL", + "instanceCountsOffset out of bounds", + instanceCounts.size(), instanceCountsOffset, drawcount)) { + return; + } + + scoped.Context()->ContextGL()->MultiDrawElementsInstancedWEBGL( + mode, &counts[countsOffset], type, &offsets[offsetsOffset], + &instanceCounts[instanceCountsOffset], drawcount); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw.h b/third_party/blink/renderer/modules/webgl/webgl_multi_draw.h index 06d6bf3..aa579c1 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_multi_draw.h +++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw.h
@@ -45,6 +45,37 @@ MakeSpan(offsetsList), offsetsOffset, drawcount); } + void multiDrawArraysInstancedWEBGL( + GLenum mode, + Int32ArrayOrLongSequence firstsList, + GLuint firstsOffset, + Int32ArrayOrLongSequence countsList, + GLuint countsOffset, + Int32ArrayOrLongSequence instanceCountsList, + GLuint instanceCountsOffset, + GLsizei drawcount) { + multiDrawArraysInstancedImpl(mode, MakeSpan(firstsList), firstsOffset, + MakeSpan(countsList), countsOffset, + MakeSpan(instanceCountsList), + instanceCountsOffset, drawcount); + } + + void multiDrawElementsInstancedWEBGL( + GLenum mode, + Int32ArrayOrLongSequence countsList, + GLuint countsOffset, + GLenum type, + Int32ArrayOrLongSequence offsetsList, + GLuint offsetsOffset, + Int32ArrayOrLongSequence instanceCountsList, + GLuint instanceCountsOffset, + GLsizei drawcount) { + multiDrawElementsInstancedImpl(mode, MakeSpan(countsList), countsOffset, + type, MakeSpan(offsetsList), offsetsOffset, + MakeSpan(instanceCountsList), + instanceCountsOffset, drawcount); + } + private: void multiDrawArraysImpl(GLenum mode, const base::span<const int32_t>& firsts, @@ -60,6 +91,27 @@ const base::span<const int32_t>& offsets, GLuint offsetsOffset, GLsizei drawcount); + + void multiDrawArraysInstancedImpl( + GLenum mode, + const base::span<const int32_t>& firsts, + GLuint firstsOffset, + const base::span<const int32_t>& counts, + GLuint countsOffset, + const base::span<const int32_t>& instanceCounts, + GLuint instanceCountsOffset, + GLsizei drawcount); + + void multiDrawElementsInstancedImpl( + GLenum mode, + const base::span<const int32_t>& counts, + GLuint countsOffset, + GLenum type, + const base::span<const int32_t>& offsets, + GLuint offsetsOffset, + const base::span<const int32_t>& instanceCounts, + GLuint instanceCountsOffset, + GLsizei drawcount); }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw.idl b/third_party/blink/renderer/modules/webgl/webgl_multi_draw.idl index 37ea035..383b5e0 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_multi_draw.idl +++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw.idl
@@ -20,4 +20,23 @@ (Int32Array or sequence<long>) offsetsList, GLuint offsetsOffset, GLsizei drawcount); + + void multiDrawArraysInstancedWEBGL(GLenum mode, + (Int32Array or sequence<long>) firstsList, + GLuint firstsOffset, + (Int32Array or sequence<long>) countsList, + GLuint countsOffset, + (Int32Array or sequence<long>) instanceCountsList, + GLuint instanceCountsOffset, + GLsizei drawcount); + + void multiDrawElementsInstancedWEBGL(GLenum mode, + (Int32Array or sequence<long>) countsList, + GLuint countsOffset, + GLenum type, + (Int32Array or sequence<long>) offsetsList, + GLuint offsetsOffset, + (Int32Array or sequence<long>) instanceCountsList, + GLuint instanceCountsOffset, + GLsizei drawcount); };
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc index 93dca19..7fb36d5 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc
@@ -37,6 +37,7 @@ return true; } +// static base::span<const int32_t> WebGLMultiDrawCommon::MakeSpan( const Int32ArrayOrLongSequence& array) { if (array.IsInt32Array()) {
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.cc b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.cc deleted file mode 100644 index 4b914c1..0000000 --- a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.cc +++ /dev/null
@@ -1,99 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.h" - -#include "gpu/command_buffer/client/gles2_interface.h" - -namespace blink { - -WebGLMultiDrawInstanced::WebGLMultiDrawInstanced( - WebGLRenderingContextBase* context) - : WebGLExtension(context) { - context->ExtensionsUtil()->EnsureExtensionEnabled( - "GL_WEBGL_multi_draw_instanced"); - context->ExtensionsUtil()->EnsureExtensionEnabled("GL_ANGLE_multi_draw"); -} - -WebGLMultiDrawInstanced* WebGLMultiDrawInstanced::Create( - WebGLRenderingContextBase* context) { - return MakeGarbageCollected<WebGLMultiDrawInstanced>(context); -} - -WebGLExtensionName WebGLMultiDrawInstanced::GetName() const { - return kWebGLMultiDrawInstancedName; -} - -bool WebGLMultiDrawInstanced::Supported(WebGLRenderingContextBase* context) { - return context->ExtensionsUtil()->SupportsExtension( - "GL_WEBGL_multi_draw_instanced") || - (context->ExtensionsUtil()->SupportsExtension("GL_ANGLE_multi_draw") && - context->ExtensionsUtil()->SupportsExtension( - "GL_ANGLE_instanced_arrays")); -} - -const char* WebGLMultiDrawInstanced::ExtensionName() { - return "WEBGL_multi_draw_instanced"; -} - -void WebGLMultiDrawInstanced::multiDrawArraysInstancedImpl( - GLenum mode, - const base::span<const int32_t>& firsts, - GLuint firstsOffset, - const base::span<const int32_t>& counts, - GLuint countsOffset, - const base::span<const int32_t>& instanceCounts, - GLuint instanceCountsOffset, - GLsizei drawcount) { - WebGLExtensionScopedContext scoped(this); - if (scoped.IsLost() || - !ValidateDrawcount(&scoped, "glMultiDrawArraysWEBGL", drawcount) || - !ValidateArray(&scoped, "glMultiDrawArraysWEBGL", - "firstsOffset out of bounds", firsts.size(), firstsOffset, - drawcount) || - !ValidateArray(&scoped, "glMultiDrawArraysWEBGL", - "countsOffset out of bounds", counts.size(), countsOffset, - drawcount) || - !ValidateArray(&scoped, "glMultiDrawElementsWEBGL", - "instanceCountsOffset out of bounds", - instanceCounts.size(), instanceCountsOffset, drawcount)) { - return; - } - - scoped.Context()->ContextGL()->MultiDrawArraysInstancedWEBGL( - mode, &firsts[firstsOffset], &counts[countsOffset], - &instanceCounts[instanceCountsOffset], drawcount); -} - -void WebGLMultiDrawInstanced::multiDrawElementsInstancedImpl( - GLenum mode, - const base::span<const int32_t>& counts, - GLuint countsOffset, - GLenum type, - const base::span<const int32_t>& offsets, - GLuint offsetsOffset, - const base::span<const int32_t>& instanceCounts, - GLuint instanceCountsOffset, - GLsizei drawcount) { - WebGLExtensionScopedContext scoped(this); - if (scoped.IsLost() || - !ValidateDrawcount(&scoped, "glMultiDrawElementsWEBGL", drawcount) || - !ValidateArray(&scoped, "glMultiDrawElementsWEBGL", - "countsOffset out of bounds", counts.size(), countsOffset, - drawcount) || - !ValidateArray(&scoped, "glMultiDrawElementsWEBGL", - "offsetsOffset out of bounds", offsets.size(), - offsetsOffset, drawcount) || - !ValidateArray(&scoped, "glMultiDrawElementsWEBGL", - "instanceCountsOffset out of bounds", - instanceCounts.size(), instanceCountsOffset, drawcount)) { - return; - } - - scoped.Context()->ContextGL()->MultiDrawElementsInstancedWEBGL( - mode, &counts[countsOffset], type, &offsets[offsetsOffset], - &instanceCounts[instanceCountsOffset], drawcount); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.h b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.h deleted file mode 100644 index 540a4d7..0000000 --- a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.h +++ /dev/null
@@ -1,82 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_INSTANCED_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_INSTANCED_H_ - -#include "third_party/blink/renderer/bindings/modules/v8/int32_array_or_long_sequence.h" -#include "third_party/blink/renderer/modules/webgl/webgl_extension.h" -#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" - -namespace blink { -class WebGLMultiDrawInstanced final : public WebGLExtension, - public WebGLMultiDrawCommon { - DEFINE_WRAPPERTYPEINFO(); - - public: - static WebGLMultiDrawInstanced* Create(WebGLRenderingContextBase*); - static bool Supported(WebGLRenderingContextBase*); - static const char* ExtensionName(); - - explicit WebGLMultiDrawInstanced(WebGLRenderingContextBase*); - WebGLExtensionName GetName() const override; - - void multiDrawArraysInstancedWEBGL( - GLenum mode, - Int32ArrayOrLongSequence firstsList, - GLuint firstsOffset, - Int32ArrayOrLongSequence countsList, - GLuint countsOffset, - Int32ArrayOrLongSequence instanceCountsList, - GLuint instanceCountsOffset, - GLsizei drawcount) { - multiDrawArraysInstancedImpl(mode, MakeSpan(firstsList), firstsOffset, - MakeSpan(countsList), countsOffset, - MakeSpan(instanceCountsList), - instanceCountsOffset, drawcount); - } - - void multiDrawElementsInstancedWEBGL( - GLenum mode, - Int32ArrayOrLongSequence countsList, - GLuint countsOffset, - GLenum type, - Int32ArrayOrLongSequence offsetsList, - GLuint offsetsOffset, - Int32ArrayOrLongSequence instanceCountsList, - GLuint instanceCountsOffset, - GLsizei drawcount) { - multiDrawElementsInstancedImpl(mode, MakeSpan(countsList), countsOffset, - type, MakeSpan(offsetsList), offsetsOffset, - MakeSpan(instanceCountsList), - instanceCountsOffset, drawcount); - } - - private: - void multiDrawArraysInstancedImpl( - GLenum mode, - const base::span<const int32_t>& firsts, - GLuint firstsOffset, - const base::span<const int32_t>& counts, - GLuint countsOffset, - const base::span<const int32_t>& instanceCounts, - GLuint instanceCountsOffset, - GLsizei drawcount); - - void multiDrawElementsInstancedImpl( - GLenum mode, - const base::span<const int32_t>& counts, - GLuint countsOffset, - GLenum type, - const base::span<const int32_t>& offsets, - GLuint offsetsOffset, - const base::span<const int32_t>& instanceCounts, - GLuint instanceCountsOffset, - GLsizei drawcount); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_INSTANCED_H_
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.idl b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.idl deleted file mode 100644 index b117010..0000000 --- a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.idl +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// https://www.khronos.org/registry/webgl/extensions/WEBGL_multi_draw_instanced/ - -[NoInterfaceObject] -interface WebGLMultiDrawInstanced { - void multiDrawArraysInstancedWEBGL(GLenum mode, - (Int32Array or sequence<long>) firstsList, - GLuint firstsOffset, - (Int32Array or sequence<long>) countsList, - GLuint countsOffset, - (Int32Array or sequence<long>) instanceCountsList, - GLuint instanceCountsOffset, - GLsizei drawcount); - - void multiDrawElementsInstancedWEBGL(GLenum mode, - (Int32Array or sequence<long>) countsList, - GLuint countsOffset, - GLenum type, - (Int32Array or sequence<long>) offsetsList, - GLuint offsetsOffset, - (Int32Array or sequence<long>) instanceCountsList, - GLuint instanceCountsOffset, - GLsizei drawcount); -};
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc index ad0cef22..ec7cc366 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc
@@ -68,7 +68,6 @@ #include "third_party/blink/renderer/modules/webgl/webgl_draw_buffers.h" #include "third_party/blink/renderer/modules/webgl/webgl_lose_context.h" #include "third_party/blink/renderer/modules/webgl/webgl_multi_draw.h" -#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.h" #include "third_party/blink/renderer/modules/webgl/webgl_video_texture.h" #include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h" @@ -193,8 +192,6 @@ RegisterExtension<WebGLLoseContext>(webgl_lose_context_, kApprovedExtension, kBothPrefixes); RegisterExtension<WebGLMultiDraw>(webgl_multi_draw_, kDraftExtension); - RegisterExtension<WebGLMultiDrawInstanced>(webgl_multi_draw_instanced_, - kDraftExtension); RegisterExtension<WebGLVideoTexture>(webgl_video_texture_, kDraftExtension); } @@ -230,7 +227,6 @@ visitor->Trace(webgl_draw_buffers_); visitor->Trace(webgl_lose_context_); visitor->Trace(webgl_multi_draw_); - visitor->Trace(webgl_multi_draw_instanced_); visitor->Trace(webgl_video_texture_); WebGLRenderingContextBase::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h index 0787548..3bf24b7 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h
@@ -56,7 +56,6 @@ class WebGLDepthTexture; class WebGLLoseContext; class WebGLMultiDraw; -class WebGLMultiDrawInstanced; class WebGLVideoTexture; class WebGLRenderingContext final : public WebGLRenderingContextBase { @@ -130,7 +129,6 @@ Member<WebGLDrawBuffers> webgl_draw_buffers_; Member<WebGLLoseContext> webgl_lose_context_; Member<WebGLMultiDraw> webgl_multi_draw_; - Member<WebGLMultiDrawInstanced> webgl_multi_draw_instanced_; Member<WebGLVideoTexture> webgl_video_texture_; };
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h index 9549f51..ac75d1977 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -639,7 +639,6 @@ friend class WebGLCompressedTextureS3TCsRGB; friend class WebGLMultiDraw; friend class WebGLMultiDrawCommon; - friend class WebGLMultiDrawInstanced; friend class WebGLRenderingContextErrorMessageCallback; friend class WebGLVertexArrayObjectBase; friend class WebGLVideoTexture;
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc index 22c87c4..f8f10fc 100644 --- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc +++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -525,7 +525,7 @@ base::TimeTicks value; if (video_frame && video_frame->metadata()->GetTimeTicks( - media::VideoFrameMetadata::DECODE_TIME, &value)) { + media::VideoFrameMetadata::DECODE_END_TIME, &value)) { TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0("media", "VideoFrameSubmitter", *next_frame_token_, value); TRACE_EVENT_ASYNC_STEP_PAST0("media", "VideoFrameSubmitter",
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index e6eeceac..07363bd 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -711,6 +711,7 @@ // flat-tree instead of shadow-including ancestors for child dirtiness. { name: "FlatTreeStyleRecalc", + status: "stable", }, { name: "FocuslessSpatialNavigation",
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc index 6f1747b5..22e50a1 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -483,6 +483,7 @@ // kWebLocks can be frozen if for entire page, but not for individual // frames. See https://crrev.com/c/1687716 case TaskType::kWebLocks: + case TaskType::kInternalFrameLifecycleControl: return UnpausableTaskQueueTraits(); case TaskType::kInternalTranslation: return ForegroundOnlyTaskQueueTraits();
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc index 5902a7a..780e692 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
@@ -135,6 +135,8 @@ return "InternalContinueScriptLoading"; case TaskType::kExperimentalWebScheduling: return "ExperimentalWebScheduling"; + case TaskType::kInternalFrameLifecycleControl: + return "InternalFrameLifecycleControl"; case TaskType::kCount: return "Count"; }
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc index 710b1872..b387c5e0 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
@@ -207,6 +207,7 @@ case TaskType::kServiceWorkerClientMessage: case TaskType::kInternalContentCapture: case TaskType::kExperimentalWebScheduling: + case TaskType::kInternalFrameLifecycleControl: case TaskType::kCount: NOTREACHED(); break;
diff --git a/third_party/blink/tools/blinkpy/bindings/bindings_tests.py b/third_party/blink/tools/blinkpy/bindings/bindings_tests.py index 56983d1..6db448d8 100644 --- a/third_party/blink/tools/blinkpy/bindings/bindings_tests.py +++ b/third_party/blink/tools/blinkpy/bindings/bindings_tests.py
@@ -105,7 +105,7 @@ shutil.rmtree(name) -def generate_interface_dependencies(runtime_enabled_features, cache_directory): +def generate_interface_dependencies(runtime_enabled_features): def idl_paths_recursive(directory): # This is slow, especially on Windows, due to os.walk making # excess stat() calls. Faster versions may appear in Python 3.5 or @@ -127,7 +127,7 @@ return idl_paths def collect_interfaces_info(idl_path_list): - info_collector = InterfaceInfoCollector(cache_directory) + info_collector = InterfaceInfoCollector() for idl_path in idl_path_list: info_collector.collect_info(idl_path) info = info_collector.get_info_as_dict() @@ -208,9 +208,6 @@ continue directory_with_component = os.path.join(directory, component) for filename in os.listdir(directory_with_component): - if filename in ('lextab.py', 'parsetab.pickle'): - # Ignore tempfiles from PLY. - continue files.append(os.path.join(directory_with_component, filename)) return files @@ -291,10 +288,7 @@ return features_map try: - output_dir = os.path.join(output_directory, 'third_party/blink/renderer/bindings/tests/results') - if not os.path.exists(output_dir): - os.makedirs(output_dir) - generate_interface_dependencies(make_runtime_features_dict(), output_directory) + generate_interface_dependencies(make_runtime_features_dict()) for component in COMPONENT_DIRECTORY: output_dir = os.path.join(output_directory, component) if not os.path.exists(output_dir): @@ -303,7 +297,7 @@ options = IdlCompilerOptions( output_directory=output_dir, impl_output_directory=output_dir, - cache_directory=output_dir, + cache_directory=None, target_component=component) if component == 'core': @@ -314,7 +308,7 @@ partial_interface_options = IdlCompilerOptions( output_directory=partial_interface_output_dir, impl_output_directory=None, - cache_directory=output_dir, + cache_directory=None, target_component='modules') idl_filenames = []
diff --git a/third_party/blink/tools/blinkpy/bindings/collect_idls_into_json.py b/third_party/blink/tools/blinkpy/bindings/collect_idls_into_json.py index bd3ef84..484b2e0 100755 --- a/third_party/blink/tools/blinkpy/bindings/collect_idls_into_json.py +++ b/third_party/blink/tools/blinkpy/bindings/collect_idls_into_json.py
@@ -65,8 +65,7 @@ Returns: a generator which yields IDL node objects """ - # We use debug=True to not have to worry about generated parser tables. - parser = BlinkIDLParser(debug=True) + parser = BlinkIDLParser() for path in paths: definitions = parse_file(parser, path) for definition in definitions.GetChildren():
diff --git a/third_party/blink/tools/blinkpy/bindings/collect_idls_into_json_test.py b/third_party/blink/tools/blinkpy/bindings/collect_idls_into_json_test.py index f61724b..f98971b 100755 --- a/third_party/blink/tools/blinkpy/bindings/collect_idls_into_json_test.py +++ b/third_party/blink/tools/blinkpy/bindings/collect_idls_into_json_test.py
@@ -35,8 +35,7 @@ class TestFunctions(unittest.TestCase): def setUp(self): - # We use debug=True to not have to worry about generated parser tables. - parser = BlinkIDLParser(debug=True) + parser = BlinkIDLParser() path = os.path.join( testdata_path, utilities.read_file_to_list(_FILE)[0]) definitions = parse_file(parser, path)
diff --git a/third_party/blink/web_tests/media/track/track-cue-rendering-vertical.html b/third_party/blink/web_tests/media/track/track-cue-rendering-vertical.html index a37f060..63a44910 100644 --- a/third_party/blink/web_tests/media/track/track-cue-rendering-vertical.html +++ b/third_party/blink/web_tests/media/track/track-cue-rendering-vertical.html
@@ -9,7 +9,10 @@ testRunner.waitUntilDone(); video.onseeked = function() { - testRunner.notifyDone(); + // Wait for one rAF to ensure the thumbnail is onscreen, which helps reduce + // flaky failures. + if (window.testRunner) + requestAnimationFrame(_ => testRunner.notifyDone()); } video.currentTime = 0.75;
diff --git a/third_party/blink/web_tests/media/video-display-toggle.html b/third_party/blink/web_tests/media/video-display-toggle.html index 58a21a9..14508ce7 100644 --- a/third_party/blink/web_tests/media/video-display-toggle.html +++ b/third_party/blink/web_tests/media/video-display-toggle.html
@@ -30,8 +30,10 @@ } function done() { + // Wait for one rAF to ensure the thumbnail is onscreen, which + // helps reduce flaky failures. if (window.testRunner) - testRunner.notifyDone(); + requestAnimationFrame(_ => testRunner.notifyDone()); } </script> </head>
diff --git a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/core/node.js b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/core/node.js index 8fcd9c0..d16cfee 100644 --- a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/core/node.js +++ b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/core/node.js
@@ -88,6 +88,7 @@ cloneNode._renderer = this._renderer; cloneNode._dirtyTRS = this._dirtyTRS; + cloneNode._dirtyWorldMatrix = this._dirtyWorldMatrix; if (this._translation) { cloneNode._translation = vec3.create(); @@ -104,14 +105,12 @@ vec3.copy(cloneNode._scale, this._scale); } - // Only copy the matrices if they're not already dirty. - if (!cloneNode._dirtyTRS && this._matrix) { + if (this._matrix) { cloneNode._matrix = mat4.create(); mat4.copy(cloneNode._matrix, this._matrix); } - cloneNode._dirtyWorldMatrix = this._dirtyWorldMatrix; - if (!cloneNode._dirtyWorldMatrix && this._worldMatrix) { + if (this._worldMatrix) { cloneNode._worldMatrix = mat4.create(); mat4.copy(cloneNode._worldMatrix, this._worldMatrix); } @@ -126,6 +125,7 @@ for (let child of this.children) { cloneNode.addNode(child.clone()); } + cloneNode.setMatrixDirty(); }); return cloneNode; @@ -228,8 +228,8 @@ get worldMatrix() { if (!this._worldMatrix) { - this._dirtyWorldMatrix = true; this._worldMatrix = mat4.create(); + this.setMatrixDirty(); } if (this._dirtyWorldMatrix || this._dirtyTRS) {
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 200ba4bca..75ce86b4 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -33463,6 +33463,16 @@ <int value="4" label="Requested and granted automatically"/> </enum> +<enum name="IppVersion"> + <int value="0" label="Error">Failed to parse version</int> + <int value="1" label="Unknown">Version value not recognized</int> + <int value="2" label="IPP 1.0">IPP 1.0</int> + <int value="3" label="IPP 1.1">IPP 1.1</int> + <int value="4" label="IPP 2.0">IPP 2.0</int> + <int value="5" label="IPP 2.1">IPP 2.1</int> + <int value="6" label="IPP 2.2">IPP 2.2</int> +</enum> + <enum name="IPv6ConnectivityStatus"> <int value="0" label="Incomplete IPv6 Configuration"/> <int value="1" label="Complete IPv6 Configuration"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 42f8d7be..9ea99f1 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -96330,6 +96330,21 @@ </histogram> <histogram name="Omnibox.MatchStability.AsyncMatchChange" units="position" + expires_after="2019-11-10"> + <obsolete> + Deprecated 2019-11-10. Replaced by Omnibox.MatchStability.AsyncMatchChange2. + </obsolete> + <owner>tommycli@chromium.org</owner> + <owner>jdonnelly@chromium.org</owner> + <summary> + This histogram was buggy and the data should be disregarded. + + The original intent was to count asynchronous match updates for each + position. The implementation had a bug, and it overcounted. + </summary> +</histogram> + +<histogram name="Omnibox.MatchStability.AsyncMatchChange2" units="position" expires_after="2020-03-01"> <owner>tommycli@chromium.org</owner> <owner>jdonnelly@chromium.org</owner> @@ -100000,6 +100015,18 @@ </summary> </histogram> +<histogram + name="PageLoad.Clients.ThirdParty.Frames.NavigationToFirstContentfulPaint" + units="ms" expires_after="2021-11-01"> + <owner>jkarlin@chromium.org</owner> + <owner>johnidel@chromium.org</owner> + <summary> + The time from navigation start to the first contentful paint of third-party + frames on pages. Note that this can be significantly delayed due to lazy + loading. + </summary> +</histogram> + <histogram name="PageLoad.Clients.ThirdParty.Origins.CookieRead" units="Count" expires_after="2021-07-01"> <owner>jkarlin@chromium.org</owner> @@ -114960,6 +114987,18 @@ </summary> </histogram> +<histogram name="Printing.CUPS.HighestIppVersion" enum="IppVersion" + expires_after="2020-11-02"> + <owner>skau@chromium.org</owner> + <owner>pawliczek@chromium.org</owner> + <summary> + Records the highest IPP version reported by a printer when we query the + printer for attributes. Useful to understand the population of printers + currently used. Recorded during printer setup for IPP printers. Recorded + only on ChromeOS. + </summary> +</histogram> + <histogram name="Printing.CUPS.IppAttributes" enum="IppAttribute" expires_after="M82"> <owner>vkuzkokov@chromium.org</owner>
diff --git a/ui/base/ime/win/input_method_win_tsf.cc b/ui/base/ime/win/input_method_win_tsf.cc index e0b9a87..5157eb4 100644 --- a/ui/base/ime/win/input_method_win_tsf.cc +++ b/ui/base/ime/win/input_method_win_tsf.cc
@@ -153,6 +153,11 @@ if (IsWindowFocused(focused_before)) { ConfirmCompositionText(/* reset_engine */ true, /* keep_selection */ false); + // set input policy back to manual from automatic + // We will set the policy to automatic when user taps on the edit control so + // software input panel can come up + ui::TSFBridge::GetInstance()->SetInputPanelPolicy( + /*inputPanelPolicyManual*/ true); ui::TSFBridge::GetInstance()->RemoveFocusedClient(focused_before); } } @@ -164,7 +169,6 @@ IsTextInputClientFocused(focused)) { ui::TSFBridge::GetInstance()->SetFocusedClient(toplevel_window_handle_, focused); - // Force to update the input type since client's TextInputStateChanged() // function might not be called if text input types before the client loses // focus and after it acquires focus again are the same.
diff --git a/ui/base/ime/win/tsf_bridge.cc b/ui/base/ime/win/tsf_bridge.cc index 6f87906..778f19b 100644 --- a/ui/base/ime/win/tsf_bridge.cc +++ b/ui/base/ime/win/tsf_bridge.cc
@@ -227,12 +227,18 @@ return; } - UpdateAssociateFocus(); - TSFDocument* document = GetAssociatedDocument(); if (!document) return; - thread_manager_->SetFocus(document->document_manager.Get()); + // We call AssociateFocus for text input type none that also + // triggers SetFocus internally. We don't want to send multiple + // focus notifications for the same text input type so we don't + // call AssociateFocus and SetFocus together. Just calling SetFocus + // should be sufficient for setting focus on a textstore. + if (client_->GetTextInputType() != TEXT_INPUT_TYPE_NONE) + thread_manager_->SetFocus(document->document_manager.Get()); + else + UpdateAssociateFocus(); OnTextLayoutChanged(); } @@ -251,10 +257,7 @@ return; if (!document->text_store) return; - document->text_store->SetInputPanelPolicy(input_panel_policy_manual); - UpdateAssociateFocus(); - thread_manager_->SetFocus(document->document_manager.Get()); } bool TSFBridgeImpl::CancelComposition() { @@ -530,6 +533,7 @@ // the attached document manager will not be destroyed while it is attached. // This should be true as long as TSFBridge::Shutdown() is called late phase // of UI thread shutdown. + // AssociateFocus calls SetFocus on the document manager internally Microsoft::WRL::ComPtr<ITfDocumentMgr> previous_focus; thread_manager_->AssociateFocus(attached_window_handle_, document->document_manager.Get(),
diff --git a/ui/base/ime/win/tsf_input_policy_unittest.cc b/ui/base/ime/win/tsf_input_policy_unittest.cc index 3e31e57aa..ac867cc 100644 --- a/ui/base/ime/win/tsf_input_policy_unittest.cc +++ b/ui/base/ime/win/tsf_input_policy_unittest.cc
@@ -209,6 +209,53 @@ std::unique_ptr<FakeInputMethod> fake_input_method_; }; +class TSFMultipleInputPanelTest : public testing::Test { + protected: + void SetUp() override { + text_store1_ = new TSFTextStore(); + text_store2_ = new TSFTextStore(); + sink1_ = new MockStoreACPSink(); + sink2_ = new MockStoreACPSink(); + EXPECT_EQ(S_OK, text_store1_->AdviseSink(IID_ITextStoreACPSink, + sink1_.get(), TS_AS_ALL_SINKS)); + EXPECT_EQ(S_OK, text_store2_->AdviseSink(IID_ITextStoreACPSink, + sink2_.get(), TS_AS_ALL_SINKS)); + text_store1_->SetFocusedTextInputClient(kWindowHandle, + &text_input_client1_); + text_store1_->SetInputMethodDelegate(&input_method_delegate_); + text_store2_->SetFocusedTextInputClient(kWindowHandle, + &text_input_client2_); + text_store2_->SetInputMethodDelegate(&input_method_delegate_); + fake_input_method_ = std::make_unique<FakeInputMethod>(); + fake_input_method_->SetTSFTextStoreForBridge(text_store1_.get()); + } + + void SwitchToDifferentTSFTextStore() { + fake_input_method_->SetTSFTextStoreForBridge(text_store2_.get()); + } + + void TearDown() override { + EXPECT_EQ(S_OK, text_store1_->UnadviseSink(sink1_.get())); + EXPECT_EQ(S_OK, text_store2_->UnadviseSink(sink2_.get())); + sink1_ = nullptr; + sink2_ = nullptr; + text_store1_ = nullptr; + text_store2_ = nullptr; + } + + // Accessors to the internal state of TSFTextStore. + + base::win::ScopedCOMInitializer com_initializer_; + MockTextInputClient text_input_client1_; + MockTextInputClient text_input_client2_; + MockInputMethodDelegate input_method_delegate_; + scoped_refptr<TSFTextStore> text_store1_; + scoped_refptr<TSFTextStore> text_store2_; + scoped_refptr<MockStoreACPSink> sink1_; + scoped_refptr<MockStoreACPSink> sink2_; + std::unique_ptr<FakeInputMethod> fake_input_method_; +}; + namespace { TEST_F(TSFInputPanelTest, GetStatusTest) { @@ -252,5 +299,38 @@ status.dwStaticFlags); } +TEST_F(TSFMultipleInputPanelTest, InputPaneSwitchForMultipleTSFTextStoreTest) { + TS_STATUS status = {}; + // Invoke the virtual keyboard through InputMethod + // and test if the automatic policy flag has been set or not. + EXPECT_EQ(S_OK, text_store1_->GetStatus(&status)); + EXPECT_EQ((ULONG)TS_SD_INPUTPANEMANUALDISPLAYENABLE, status.dwDynamicFlags); + EXPECT_EQ((ULONG)(TS_SS_TRANSITORY | TS_SS_NOHIDDENTEXT), + status.dwStaticFlags); + fake_input_method_->ShowVirtualKeyboardIfEnabled(); + EXPECT_EQ(S_OK, text_store1_->GetStatus(&status)); + EXPECT_NE((ULONG)TS_SD_INPUTPANEMANUALDISPLAYENABLE, status.dwDynamicFlags); + EXPECT_EQ((ULONG)(TS_SS_TRANSITORY | TS_SS_NOHIDDENTEXT), + status.dwStaticFlags); + fake_input_method_->DetachTextInputClient(nullptr); + SwitchToDifferentTSFTextStore(); + // Different TSFTextStore is in focus so manual policy should be set in the + // previous one + EXPECT_EQ(S_OK, text_store1_->GetStatus(&status)); + EXPECT_EQ((ULONG)TS_SD_INPUTPANEMANUALDISPLAYENABLE, status.dwDynamicFlags); + EXPECT_EQ((ULONG)(TS_SS_TRANSITORY | TS_SS_NOHIDDENTEXT), + status.dwStaticFlags); + EXPECT_EQ(S_OK, text_store2_->GetStatus(&status)); + EXPECT_EQ((ULONG)TS_SD_INPUTPANEMANUALDISPLAYENABLE, status.dwDynamicFlags); + EXPECT_EQ((ULONG)(TS_SS_TRANSITORY | TS_SS_NOHIDDENTEXT), + status.dwStaticFlags); + fake_input_method_->ShowVirtualKeyboardIfEnabled(); + EXPECT_EQ(S_OK, text_store2_->GetStatus(&status)); + EXPECT_NE((ULONG)TS_SD_INPUTPANEMANUALDISPLAYENABLE, status.dwDynamicFlags); + EXPECT_EQ((ULONG)(TS_SS_TRANSITORY | TS_SS_NOHIDDENTEXT), + status.dwStaticFlags); +} + } // namespace + } // namespace ui
diff --git a/ui/base/ime/win/tsf_text_store.cc b/ui/base/ime/win/tsf_text_store.cc index e18fec3..18f724f 100644 --- a/ui/base/ime/win/tsf_text_store.cc +++ b/ui/base/ime/win/tsf_text_store.cc
@@ -1213,6 +1213,10 @@ void TSFTextStore::SetInputPanelPolicy(bool input_panel_policy_manual) { input_panel_policy_manual_ = input_panel_policy_manual; + // This notification tells TSF that the input pane flag has changed. + // TSF queries for the status of this flag using GetStatus and gets + // the updated value. + text_store_acp_sink_->OnStatusChange(TS_SD_INPUTPANEMANUALDISPLAYENABLE); } void TSFTextStore::SendOnLayoutChange() {
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc index 25212c6..3935692 100644 --- a/ui/gfx/render_text.cc +++ b/ui/gfx/render_text.cc
@@ -891,7 +891,9 @@ } void RenderText::ApplyColor(SkColor value, const Range& range) { - colors_.ApplyValue(value, range); + // Do not change styles mid-grapheme to avoid breaking ligatures. + Range expanded_range = ExpandRangeToGraphemeBoundary(range); + colors_.ApplyValue(value, expanded_range); OnTextColorChanged(); } @@ -900,7 +902,9 @@ } void RenderText::ApplyBaselineStyle(BaselineStyle value, const Range& range) { - baselines_.ApplyValue(value, range); + // Do not change styles mid-grapheme to avoid breaking ligatures. + Range expanded_range = ExpandRangeToGraphemeBoundary(range); + baselines_.ApplyValue(value, expanded_range); } void RenderText::ApplyFontSizeOverride(int font_size_override, @@ -919,11 +923,8 @@ void RenderText::ApplyStyle(TextStyle style, bool value, const Range& range) { // Do not change styles mid-grapheme to avoid breaking ligatures. - const size_t start = IsValidCursorIndex(range.start()) ? range.start() : - IndexOfAdjacentGrapheme(range.start(), CURSOR_BACKWARD); - const size_t end = IsValidCursorIndex(range.end()) ? range.end() : - IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD); - styles_[style].ApplyValue(value, Range(start, end)); + Range expanded_range = ExpandRangeToGraphemeBoundary(range); + styles_[style].ApplyValue(value, expanded_range); cached_bounds_and_offset_valid_ = false; // TODO(oshima|msw): Not all style change requires layout changes. @@ -939,7 +940,9 @@ } void RenderText::ApplyWeight(Font::Weight weight, const Range& range) { - weights_.ApplyValue(weight, range); + // Do not change styles mid-grapheme to avoid breaking ligatures. + Range expanded_range = ExpandRangeToGraphemeBoundary(range); + weights_.ApplyValue(weight, expanded_range); cached_bounds_and_offset_valid_ = false; OnLayoutTextAttributeChanged(false); @@ -2101,6 +2104,17 @@ : Range(range_min, range_max); } +Range RenderText::ExpandRangeToGraphemeBoundary(const Range& range) { + const size_t start = + IsValidCursorIndex(range.start()) + ? range.start() + : IndexOfAdjacentGrapheme(range.start(), CURSOR_BACKWARD); + const size_t end = IsValidCursorIndex(range.end()) + ? range.end() + : IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD); + return Range(start, end); +} + internal::TextRunList* RenderText::GetRunList() { NOTREACHED(); return nullptr;
diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h index 0847005..2495fa0 100644 --- a/ui/gfx/render_text.h +++ b/ui/gfx/render_text.h
@@ -811,6 +811,10 @@ // range. Maintains directionality of |range|. Range ExpandRangeToWordBoundary(const Range& range) const; + // Expands |range| to its nearest grapheme boundaries and returns the + // resulting range. + Range ExpandRangeToGraphemeBoundary(const Range& range); + // Returns an implementation-specific run list, if implemented. virtual internal::TextRunList* GetRunList(); virtual const internal::TextRunList* GetRunList() const;
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc index 1e26c23e..c972f9a 100644 --- a/ui/gfx/render_text_unittest.cc +++ b/ui/gfx/render_text_unittest.cc
@@ -672,6 +672,48 @@ {{0, false}, {1, true}, {6, false}})); } +TEST_F(RenderTextTest, ApplyStyleSurrogatePair) { + RenderText* render_text = GetRenderText(); + render_text->SetText(WideToUTF16(L"x\U0001F601x")); + // Apply the style in the middle of a surrogate pair. The style should be + // applied to the whole range of the codepoint. + gfx::Range range(2, 3); + render_text->ApplyWeight(gfx::Font::Weight::BOLD, range); + render_text->ApplyStyle(TEXT_STYLE_ITALIC, true, range); + render_text->ApplyColor(SK_ColorRED, range); + render_text->Draw(canvas()); + + EXPECT_TRUE(test_api()->styles()[TEXT_STYLE_ITALIC].EqualsForTesting( + {{0, false}, {1, true}, {3, false}})); + EXPECT_TRUE(test_api()->colors().EqualsForTesting( + {{0, SK_ColorBLACK}, {1, SK_ColorRED}, {3, SK_ColorBLACK}})); + EXPECT_TRUE( + test_api()->weights().EqualsForTesting({{0, Font::Weight::NORMAL}, + {1, Font::Weight::BOLD}, + {3, Font::Weight::NORMAL}})); +} + +TEST_F(RenderTextTest, ApplyStyleGrapheme) { + RenderText* render_text = GetRenderText(); + render_text->SetText(WideToUTF16(L"x\u0065\u0301x")); + // Apply the style in the middle of a grapheme. The style should be applied to + // the whole range of the grapheme. + gfx::Range range(2, 3); + render_text->ApplyWeight(gfx::Font::Weight::BOLD, range); + render_text->ApplyStyle(TEXT_STYLE_ITALIC, true, range); + render_text->ApplyColor(SK_ColorRED, range); + render_text->Draw(canvas()); + + EXPECT_TRUE(test_api()->styles()[TEXT_STYLE_ITALIC].EqualsForTesting( + {{0, false}, {1, true}, {3, false}})); + EXPECT_TRUE(test_api()->colors().EqualsForTesting( + {{0, SK_ColorBLACK}, {1, SK_ColorRED}, {3, SK_ColorBLACK}})); + EXPECT_TRUE( + test_api()->weights().EqualsForTesting({{0, Font::Weight::NORMAL}, + {1, Font::Weight::BOLD}, + {3, Font::Weight::NORMAL}})); +} + TEST_F(RenderTextTest, AppendTextKeepsStyles) { RenderText* render_text = GetRenderText(); // Setup basic functionality. @@ -5770,7 +5812,7 @@ // Ensure that the width reported by RenderText is sufficient for drawing. Draws // to a canvas and checks if any pixel beyond the bounding rectangle is colored. -TEST_F(RenderTextTest, TextDoesntClip) { +TEST_F(RenderTextTest, DISABLED_TextDoesntClip) { const char* kTestStrings[] = { " ", // TODO(dschuyler): Underscores draw outside GetStringSize; @@ -5850,7 +5892,7 @@ // Ensure that the text will clip to the display rect. Draws to a canvas and // checks whether any pixel beyond the bounding rectangle is colored. -TEST_F(RenderTextTest, TextDoesClip) { +TEST_F(RenderTextTest, DISABLED_TextDoesClip) { const char* kTestStrings[] = {"TEST", "W", "WWWW", "gAXAXWWWW"}; const Size kCanvasSize(300, 50); const int kTestSize = 10;
diff --git a/ui/gl/gl_image_memory.cc b/ui/gl/gl_image_memory.cc index beebc18..85860598 100644 --- a/ui/gl/gl_image_memory.cc +++ b/ui/gl/gl_image_memory.cc
@@ -6,8 +6,13 @@ #include <stdint.h> +#include "base/barrier_closure.h" #include "base/logging.h" +#include "base/numerics/checked_math.h" #include "base/numerics/safe_conversions.h" +#include "base/synchronization/waitable_event.h" +#include "base/system/sys_info.h" +#include "base/task/post_task.h" #include "base/trace_event/trace_event.h" #include "ui/gfx/buffer_format_util.h" #include "ui/gfx/gpu_fence.h" @@ -16,6 +21,7 @@ #include "ui/gl/gl_context.h" #include "ui/gl/gl_enums.h" #include "ui/gl/gl_version_info.h" +#include "ui/gl/scoped_binders.h" using gfx::BufferFormat; @@ -178,6 +184,40 @@ return nullptr; } +void MemcpyTask(const void* src, + void* dst, + size_t bytes, + size_t task_index, + size_t n_tasks, + base::RepeatingClosure* done) { + auto checked_bytes = base::CheckedNumeric<size_t>(bytes); + size_t start = (checked_bytes * task_index / n_tasks).ValueOrDie(); + size_t end = (checked_bytes * (task_index + 1) / n_tasks).ValueOrDie(); + CHECK_LE(start, bytes); + CHECK_LE(end, bytes); + memcpy(static_cast<char*>(dst) + start, static_cast<const char*>(src) + start, + end - start); + done->Run(); +} + +bool SupportsPBO(GLContext* context) { + const GLVersionInfo* version = context->GetVersionInfo(); + return version->IsAtLeastGL(2, 1) || version->IsAtLeastGLES(3, 0) || + context->HasExtension("GL_ARB_pixel_buffer_object") || + context->HasExtension("GL_EXT_pixel_buffer_object") || + context->HasExtension("GL_NV_pixel_buffer_object"); +} + +bool SupportsMapBuffer(GLContext* context) { + return context->GetVersionInfo()->IsAtLeastGL(2, 0) || + context->HasExtension("GL_OES_mapbuffer"); +} + +bool SupportsMapBufferRange(GLContext* context) { + return context->GetVersionInfo()->IsAtLeastGLES(3, 0) || + context->HasExtension("GL_EXT_map_buffer_range"); +} + } // namespace GLImageMemory::GLImageMemory(const gfx::Size& size) @@ -186,7 +226,10 @@ format_(gfx::BufferFormat::RGBA_8888), stride_(0) {} -GLImageMemory::~GLImageMemory() {} +GLImageMemory::~GLImageMemory() { + if (buffer_) + glDeleteBuffersARB(1, &buffer_); +} // static GLImageMemory* GLImageMemory::FromGLImage(GLImage* image) { @@ -213,6 +256,22 @@ memory_ = memory; format_ = format; stride_ = stride; + + GLContext* context = GLContext::GetCurrent(); + if (SupportsPBO(context) && + (SupportsMapBuffer(context) || SupportsMapBufferRange(context))) { + constexpr size_t kTaskBytes = 1024 * 1024; + buffer_bytes_ = gfx::BufferSizeForBufferFormat(size_, format_); + memcpy_tasks_ = std::min<size_t>(buffer_bytes_ / kTaskBytes, + base::SysInfo::NumberOfProcessors()); + if (memcpy_tasks_ > 1) { + glGenBuffersARB(1, &buffer_); + ScopedBufferBinder binder(GL_PIXEL_UNPACK_BUFFER, buffer_); + glBufferData(GL_PIXEL_UNPACK_BUFFER, buffer_bytes_, nullptr, + GL_DYNAMIC_DRAW); + } + } + return true; } @@ -277,8 +336,49 @@ if (data_row_length != size_.width()) glPixelStorei(GL_UNPACK_ROW_LENGTH, data_row_length); - glTexImage2D(target, 0, GetInternalFormat(), size_.width(), size_.height(), 0, - data_format, data_type, gles2_data ? gles2_data.get() : memory_); + const void* src = gles2_data ? gles2_data.get() : memory_; + if (buffer_) { + glTexImage2D(target, 0, GetInternalFormat(), size_.width(), size_.height(), + 0, data_format, data_type, nullptr); + + ScopedBufferBinder binder(GL_PIXEL_UNPACK_BUFFER, buffer_); + + void* dst = nullptr; + if (SupportsMapBuffer(GLContext::GetCurrent())) { + dst = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + } else { + DCHECK(SupportsMapBufferRange(GLContext::GetCurrent())); + dst = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, buffer_bytes_, + GL_MAP_WRITE_BIT); + } + + if (dst) { + base::WaitableEvent event; + base::RepeatingClosure barrier = base::BarrierClosure( + memcpy_tasks_, base::BindOnce(&base::WaitableEvent::Signal, + base::Unretained(&event))); + for (int i = 1; i < memcpy_tasks_; ++i) { + base::PostTask(FROM_HERE, + base::BindOnce(&MemcpyTask, src, dst, buffer_bytes_, i, + memcpy_tasks_, &barrier)); + } + MemcpyTask(src, dst, buffer_bytes_, 0, memcpy_tasks_, &barrier); + event.Wait(); + + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + + glTexSubImage2D(target, 0, 0, 0, size_.width(), size_.height(), + data_format, data_type, 0); + } else { + glDeleteBuffersARB(1, &buffer_); + buffer_ = 0; + } + } + + if (!buffer_) { + glTexImage2D(target, 0, GetInternalFormat(), size_.width(), size_.height(), + 0, data_format, data_type, src); + } if (data_row_length != size_.width()) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
diff --git a/ui/gl/gl_image_memory.h b/ui/gl/gl_image_memory.h index e1c6c3bd..2995a2b 100644 --- a/ui/gl/gl_image_memory.h +++ b/ui/gl/gl_image_memory.h
@@ -64,6 +64,10 @@ gfx::BufferFormat format_; size_t stride_; + unsigned buffer_ = 0; + size_t buffer_bytes_ = 0; + int memcpy_tasks_ = 0; + DISALLOW_COPY_AND_ASSIGN(GLImageMemory); };
diff --git a/ui/gl/gl_surface_glx.cc b/ui/gl/gl_surface_glx.cc index 7ba8cc5..52261c1 100644 --- a/ui/gl/gl_surface_glx.cc +++ b/ui/gl/gl_surface_glx.cc
@@ -459,7 +459,10 @@ return false; } - const auto& visual_info = gl::GLVisualPickerGLX::GetInstance()->rgba_visual(); + auto* visual_picker = gl::GLVisualPickerGLX::GetInstance(); + XVisualInfo visual_info = visual_picker->rgba_visual(); + if (!visual_info.visual) + visual_info = visual_picker->system_visual(); g_visual = visual_info.visual; g_depth = visual_info.depth; g_colormap =
diff --git a/ui/gl/gl_visual_picker_glx.cc b/ui/gl/gl_visual_picker_glx.cc index a412737..7894212 100644 --- a/ui/gl/gl_visual_picker_glx.cc +++ b/ui/gl/gl_visual_picker_glx.cc
@@ -5,6 +5,7 @@ #include "ui/gl/gl_visual_picker_glx.h" #include <algorithm> +#include <cstring> #include <numeric> #include <vector> @@ -19,8 +20,12 @@ namespace { bool IsArgbVisual(const XVisualInfo& visual) { - return visual.depth == 32 && visual.red_mask == 0xff0000 && - visual.green_mask == 0x00ff00 && visual.blue_mask == 0x0000ff; + auto bits = [](auto x) { + return std::bitset<8 * sizeof(decltype(x))>(x).count(); + }; + auto bits_rgb = + bits(visual.red_mask) + bits(visual.green_mask) + bits(visual.blue_mask); + return static_cast<std::size_t>(visual.depth) > bits_rgb; } } // anonymous namespace @@ -36,7 +41,8 @@ // Find the highest scoring visual and return it. Visual* default_visual = DefaultVisual(display_, DefaultScreen(display_)); int highest_score = -1; - XVisualInfo best_visual{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + XVisualInfo best_visual; + memset(&best_visual, 0, sizeof(best_visual)); for (const XVisualInfo& const_visual_info : visuals) { int supports_gl, double_buffer, stereo, alpha_size, depth_size, stencil_size, num_multisample, visual_caveat; @@ -164,6 +170,6 @@ rgba_visual_ = PickBestRgbaVisual(visuals); } -GLVisualPickerGLX::~GLVisualPickerGLX() {} +GLVisualPickerGLX::~GLVisualPickerGLX() = default; } // namespace gl
diff --git a/ui/gl/scoped_binders.cc b/ui/gl/scoped_binders.cc index 0ac1bd6..f44272e 100644 --- a/ui/gl/scoped_binders.cc +++ b/ui/gl/scoped_binders.cc
@@ -164,6 +164,9 @@ case GL_ARRAY_BUFFER: target_getter = GL_ARRAY_BUFFER_BINDING; break; + case GL_PIXEL_UNPACK_BUFFER: + target_getter = GL_PIXEL_UNPACK_BUFFER_BINDING; + break; default: NOTIMPLEMENTED() << " Target not supported."; }
diff --git a/ui/views/accessibility/view_accessibility.cc b/ui/views/accessibility/view_accessibility.cc index 7cc43d93..f4529184 100644 --- a/ui/views/accessibility/view_accessibility.cc +++ b/ui/views/accessibility/view_accessibility.cc
@@ -119,6 +119,8 @@ } void ViewAccessibility::GetAccessibleNodeData(ui::AXNodeData* data) const { + data->id = GetUniqueId().Get(); + // Views may misbehave if their widget is closed; return an unknown role // rather than possibly crashing. const views::Widget* widget = view_->GetWidget();
diff --git a/weblayer/browser/java/BUILD.gn b/weblayer/browser/java/BUILD.gn index 4e1b9bf..d708116 100644 --- a/weblayer/browser/java/BUILD.gn +++ b/weblayer/browser/java/BUILD.gn
@@ -17,6 +17,7 @@ java_cpp_enum("generated_enums") { sources = [ + "//weblayer/public/navigation.h", "//weblayer/public/new_tab_delegate.h", "//weblayer/public/profile.h", ] @@ -95,6 +96,8 @@ "org/chromium/weblayer_private/interfaces/APICallException.java", "org/chromium/weblayer_private/interfaces/BrowserFragmentArgs.java", "org/chromium/weblayer_private/interfaces/BrowsingDataType.java", + "org/chromium/weblayer_private/interfaces/LoadError.java", + "org/chromium/weblayer_private/interfaces/NavigationState.java", "org/chromium/weblayer_private/interfaces/NewTabType.java", "org/chromium/weblayer_private/interfaces/ObjectWrapper.java", "org/chromium/weblayer_private/interfaces/WebLayerVersion.java", @@ -134,7 +137,7 @@ } android_aidl("aidl") { - import_include = [ "org/chromium/weblayer_private/interfaces" ] + import_include = [ "." ] sources = [ "org/chromium/weblayer_private/interfaces/IBrowser.aidl", "org/chromium/weblayer_private/interfaces/IBrowserClient.aidl",
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/NavigationImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/NavigationImpl.java index 79aafa4..e9cb3cb 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/NavigationImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/NavigationImpl.java
@@ -13,6 +13,8 @@ import org.chromium.weblayer_private.interfaces.IClientNavigation; import org.chromium.weblayer_private.interfaces.INavigation; import org.chromium.weblayer_private.interfaces.INavigationControllerClient; +import org.chromium.weblayer_private.interfaces.LoadError; +import org.chromium.weblayer_private.interfaces.NavigationState; import java.util.Arrays; import java.util.List; @@ -37,10 +39,28 @@ return mClientNavigation; } + @NavigationState + private static int implTypeToJavaType(@ImplNavigationState int type) { + switch (type) { + case ImplNavigationState.WAITING_RESPONSE: + return NavigationState.WAITING_RESPONSE; + case ImplNavigationState.RECEIVING_BYTES: + return NavigationState.RECEIVING_BYTES; + case ImplNavigationState.COMPLETE: + return NavigationState.COMPLETE; + case ImplNavigationState.FAILED: + return NavigationState.FAILED; + } + assert false; + return NavigationState.FAILED; + } + @Override + @NavigationState public int getState() { throwIfNativeDestroyed(); - return NavigationImplJni.get().getState(mNativeNavigationImpl, NavigationImpl.this); + return implTypeToJavaType( + NavigationImplJni.get().getState(mNativeNavigationImpl, NavigationImpl.this)); } @Override @@ -62,12 +82,45 @@ return NavigationImplJni.get().isSameDocument(mNativeNavigationImpl, NavigationImpl.this); } + @Override + public boolean isErrorPage() { + throwIfNativeDestroyed(); + return NavigationImplJni.get().isErrorPage(mNativeNavigationImpl, NavigationImpl.this); + } + + @Override + public int getLoadError() { + throwIfNativeDestroyed(); + return implLoadErrorToLoadError( + NavigationImplJni.get().getLoadError(mNativeNavigationImpl, NavigationImpl.this)); + } + private void throwIfNativeDestroyed() { if (mNativeNavigationImpl == 0) { throw new IllegalStateException("Using Navigation after native destroyed"); } } + @LoadError + private static int implLoadErrorToLoadError(@ImplLoadError int loadError) { + switch (loadError) { + case ImplLoadError.NO_ERROR: + return LoadError.NO_ERROR; + case ImplLoadError.HTTP_CLIENT_ERROR: + return LoadError.HTTP_CLIENT_ERROR; + case ImplLoadError.HTTP_SERVER_ERROR: + return LoadError.HTTP_SERVER_ERROR; + case ImplLoadError.SSL_ERROR: + return LoadError.SSL_ERROR; + case ImplLoadError.CONNECTIVITY_ERROR: + return LoadError.CONNECTIVITY_ERROR; + case ImplLoadError.OTHER_ERROR: + return LoadError.OTHER_ERROR; + default: + throw new IllegalArgumentException("Unexpected load error " + loadError); + } + } + @CalledByNative private void onNativeDestroyed() { mNativeNavigationImpl = 0; @@ -81,5 +134,7 @@ String getUri(long nativeNavigationImpl, NavigationImpl caller); String[] getRedirectChain(long nativeNavigationImpl, NavigationImpl caller); boolean isSameDocument(long nativeNavigationImpl, NavigationImpl caller); + boolean isErrorPage(long nativeNavigationImpl, NavigationImpl caller); + int getLoadError(long nativeNavigationImpl, NavigationImpl caller); } }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl index 03b9e55b..c262dee3 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl
@@ -7,6 +7,7 @@ import org.chromium.weblayer_private.interfaces.IBrowserClient; import org.chromium.weblayer_private.interfaces.IObjectWrapper; import org.chromium.weblayer_private.interfaces.ITab; +import org.chromium.weblayer_private.interfaces.IProfile; import java.util.List;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IChildProcessService.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IChildProcessService.aidl index 61dc2ee..87402311 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IChildProcessService.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IChildProcessService.aidl
@@ -4,6 +4,8 @@ package org.chromium.weblayer_private.interfaces; +import org.chromium.weblayer_private.interfaces.IObjectWrapper; + /** Interface to forward service calls to the service implementation. */ interface IChildProcessService { void onCreate() = 0;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigation.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigation.aidl index 8f5b6dd..378a163 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigation.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigation.aidl
@@ -15,4 +15,8 @@ List<String> getRedirectChain() = 2; boolean isSameDocument() = 3; + + boolean isErrorPage() = 4; + + int getLoadError() = 5; }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigationControllerClient.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigationControllerClient.aidl index b94cfecc..60132f87 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigationControllerClient.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigationControllerClient.aidl
@@ -4,6 +4,9 @@ package org.chromium.weblayer_private.interfaces; +import org.chromium.weblayer_private.interfaces.IClientNavigation; +import org.chromium.weblayer_private.interfaces.INavigation; + /** * Interface used by NavigationController to inform the client of changes. This largely duplicates * the NavigationCallback interface, but is a singleton to avoid unnecessary IPC.
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IProfile.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IProfile.aidl index 3b48fbf..27d13d1 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IProfile.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IProfile.aidl
@@ -4,6 +4,8 @@ package org.chromium.weblayer_private.interfaces; +import org.chromium.weblayer_private.interfaces.IObjectWrapper; + interface IProfile { void destroy() = 0;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IRemoteFragmentClient.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IRemoteFragmentClient.aidl index 2b575a0d..34f41b9 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IRemoteFragmentClient.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IRemoteFragmentClient.aidl
@@ -4,6 +4,8 @@ package org.chromium.weblayer_private.interfaces; +import org.chromium.weblayer_private.interfaces.IObjectWrapper; + interface IRemoteFragmentClient { void superOnCreate(in IObjectWrapper savedInstanceState) = 0; void superOnAttach(in IObjectWrapper context) = 1;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/ITab.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/ITab.aidl index 609063e0..b6043ce 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/ITab.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/ITab.aidl
@@ -4,10 +4,12 @@ package org.chromium.weblayer_private.interfaces; -import org.chromium.weblayer_private.interfaces.ITabClient; +import org.chromium.weblayer_private.interfaces.IDownloadCallbackClient; import org.chromium.weblayer_private.interfaces.IFullscreenCallbackClient; import org.chromium.weblayer_private.interfaces.INavigationController; import org.chromium.weblayer_private.interfaces.INavigationControllerClient; +import org.chromium.weblayer_private.interfaces.IObjectWrapper; +import org.chromium.weblayer_private.interfaces.ITabClient; interface ITab { void setClient(in ITabClient client) = 0;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayer.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayer.aidl index 4e9f2a10..34cbb06 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayer.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayer.aidl
@@ -6,8 +6,9 @@ import android.os.Bundle; -import org.chromium.weblayer_private.interfaces.IObjectWrapper; import org.chromium.weblayer_private.interfaces.IBrowserFragment; +import org.chromium.weblayer_private.interfaces.IObjectWrapper; +import org.chromium.weblayer_private.interfaces.IProfile; import org.chromium.weblayer_private.interfaces.IRemoteFragmentClient; interface IWebLayer {
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/LoadError.java b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/LoadError.java new file mode 100644 index 0000000..eba5fbf0 --- /dev/null +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/LoadError.java
@@ -0,0 +1,22 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.weblayer_private.interfaces; + +import androidx.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@IntDef({LoadError.NO_ERROR, LoadError.HTTP_CLIENT_ERROR, LoadError.HTTP_SERVER_ERROR, + LoadError.SSL_ERROR, LoadError.CONNECTIVITY_ERROR, LoadError.OTHER_ERROR}) +@Retention(RetentionPolicy.SOURCE) +public @interface LoadError { + int NO_ERROR = 0; + int HTTP_CLIENT_ERROR = 1; + int HTTP_SERVER_ERROR = 2; + int SSL_ERROR = 3; + int CONNECTIVITY_ERROR = 4; + int OTHER_ERROR = 5; +}
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/NavigationState.java b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/NavigationState.java new file mode 100644 index 0000000..d0c0f608 --- /dev/null +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/NavigationState.java
@@ -0,0 +1,20 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.weblayer_private.interfaces; + +import androidx.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@IntDef({NavigationState.WAITING_RESPONSE, NavigationState.RECEIVING_BYTES, + NavigationState.COMPLETE, NavigationState.FAILED}) +@Retention(RetentionPolicy.SOURCE) +public @interface NavigationState { + int WAITING_RESPONSE = 0; + int RECEIVING_BYTES = 1; + int COMPLETE = 2; + int FAILED = 3; +}
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersion.java b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersion.java index 85513e3f..8e56b297 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersion.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersion.java
@@ -9,4 +9,4 @@ * * Whenever any AIDL file is changed, sVersionNumber must be incremented. * */ -public final class WebLayerVersion { public static final int sVersionNumber = 11; } +public final class WebLayerVersion { public static final int sVersionNumber = 12; }
diff --git a/weblayer/browser/navigation_browsertest.cc b/weblayer/browser/navigation_browsertest.cc new file mode 100644 index 0000000..936e91cf --- /dev/null +++ b/weblayer/browser/navigation_browsertest.cc
@@ -0,0 +1,137 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "weblayer/test/weblayer_browser_test.h" + +#include "base/files/file_path.h" +#include "content/public/test/url_loader_interceptor.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "weblayer/public/navigation.h" +#include "weblayer/public/navigation_controller.h" +#include "weblayer/public/navigation_observer.h" +#include "weblayer/public/tab.h" +#include "weblayer/shell/browser/shell.h" +#include "weblayer/test/interstitial_utils.h" +#include "weblayer/test/weblayer_browser_test_utils.h" + +namespace weblayer { + +namespace { + +class OneShotNavigationObserver : public NavigationObserver { + public: + explicit OneShotNavigationObserver(Shell* shell) : tab_(shell->tab()) { + tab_->GetNavigationController()->AddObserver(this); + } + + ~OneShotNavigationObserver() override { + tab_->GetNavigationController()->RemoveObserver(this); + } + + void WaitForNavigation() { run_loop_.Run(); } + + bool completed() { return completed_; } + bool is_error_page() { return is_error_page_; } + Navigation::LoadError load_error() { return load_error_; } + + private: + // NavigationObserver implementation: + void NavigationCompleted(Navigation* navigation) override { + completed_ = true; + Finish(navigation); + } + + void NavigationFailed(Navigation* navigation) override { Finish(navigation); } + + void Finish(Navigation* navigation) { + is_error_page_ = navigation->IsErrorPage(); + load_error_ = navigation->GetLoadError(); + run_loop_.Quit(); + } + + base::RunLoop run_loop_; + Tab* tab_; + bool completed_ = false; + bool is_error_page_ = false; + Navigation::LoadError load_error_ = Navigation::kNoError; +}; + +} // namespace + +using NavigationBrowserTest = WebLayerBrowserTest; + +IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, NoError) { + EXPECT_TRUE(embedded_test_server()->Start()); + + OneShotNavigationObserver observer(shell()); + shell()->tab()->GetNavigationController()->Navigate( + embedded_test_server()->GetURL("/simple_page.html")); + + observer.WaitForNavigation(); + EXPECT_TRUE(observer.completed()); + EXPECT_FALSE(observer.is_error_page()); + EXPECT_EQ(observer.load_error(), Navigation::kNoError); +} + +IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, HttpClientError) { + EXPECT_TRUE(embedded_test_server()->Start()); + + OneShotNavigationObserver observer(shell()); + shell()->tab()->GetNavigationController()->Navigate( + embedded_test_server()->GetURL("/non_existent.html")); + + observer.WaitForNavigation(); + EXPECT_TRUE(observer.completed()); + EXPECT_FALSE(observer.is_error_page()); + EXPECT_EQ(observer.load_error(), Navigation::kHttpClientError); +} + +IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, HttpServerError) { + EXPECT_TRUE(embedded_test_server()->Start()); + + OneShotNavigationObserver observer(shell()); + shell()->tab()->GetNavigationController()->Navigate( + embedded_test_server()->GetURL("/echo?status=500")); + + observer.WaitForNavigation(); + EXPECT_TRUE(observer.completed()); + EXPECT_FALSE(observer.is_error_page()); + EXPECT_EQ(observer.load_error(), Navigation::kHttpServerError); +} + +IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SSLError) { + net::EmbeddedTestServer https_server_mismatched( + net::EmbeddedTestServer::TYPE_HTTPS); + https_server_mismatched.SetSSLConfig( + net::EmbeddedTestServer::CERT_MISMATCHED_NAME); + https_server_mismatched.AddDefaultHandlers( + base::FilePath(FILE_PATH_LITERAL("weblayer/test/data"))); + + ASSERT_TRUE(https_server_mismatched.Start()); + + OneShotNavigationObserver observer(shell()); + shell()->tab()->GetNavigationController()->Navigate( + https_server_mismatched.GetURL("/simple_page.html")); + + observer.WaitForNavigation(); + EXPECT_FALSE(observer.completed()); + EXPECT_TRUE(observer.is_error_page()); + EXPECT_EQ(observer.load_error(), Navigation::kSSLError); +} + +IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, HttpConnectivityError) { + GURL url("http://doesntexist.com/foo"); + auto interceptor = content::URLLoaderInterceptor::SetupRequestFailForURL( + url, net::ERR_NAME_NOT_RESOLVED); + + OneShotNavigationObserver observer(shell()); + shell()->tab()->GetNavigationController()->Navigate(url); + + observer.WaitForNavigation(); + EXPECT_FALSE(observer.completed()); + EXPECT_TRUE(observer.is_error_page()); + EXPECT_EQ(observer.load_error(), Navigation::kConnectivityError); +} + +} // namespace weblayer
diff --git a/weblayer/browser/navigation_impl.cc b/weblayer/browser/navigation_impl.cc index 073f043d..8b59b41 100644 --- a/weblayer/browser/navigation_impl.cc +++ b/weblayer/browser/navigation_impl.cc
@@ -5,6 +5,7 @@ #include "weblayer/browser/navigation_impl.h" #include "content/public/browser/navigation_handle.h" +#include "net/base/net_errors.h" #if defined(OS_ANDROID) #include "base/android/jni_array.h" @@ -64,13 +65,39 @@ return navigation_handle_->GetRedirectChain(); } -Navigation::State NavigationImpl::GetState() { +NavigationState NavigationImpl::GetState() { NOTIMPLEMENTED() << "TODO: properly implement this"; - return Navigation::State::kWaitingResponse; + return NavigationState::kWaitingResponse; } bool NavigationImpl::IsSameDocument() { return navigation_handle_->IsSameDocument(); } +bool NavigationImpl::IsErrorPage() { + return navigation_handle_->IsErrorPage(); +} + +Navigation::LoadError NavigationImpl::GetLoadError() { + auto error_code = navigation_handle_->GetNetErrorCode(); + if (auto* response_headers = navigation_handle_->GetResponseHeaders()) { + auto response_code = response_headers->response_code(); + if (response_code >= 400 && response_code < 500) + return kHttpClientError; + if (response_code >= 500 && response_code < 600) + return kHttpServerError; + } + + if (error_code == net::OK) + return kNoError; + + if (net::IsCertificateError(error_code)) + return kSSLError; + + if (error_code <= -100 && error_code > -200) + return kConnectivityError; + + return kOtherError; +} + } // namespace weblayer
diff --git a/weblayer/browser/navigation_impl.h b/weblayer/browser/navigation_impl.h index 362c0c4..2aed912 100644 --- a/weblayer/browser/navigation_impl.h +++ b/weblayer/browser/navigation_impl.h
@@ -41,6 +41,14 @@ const base::android::JavaParamRef<jobject>& obj) { return IsSameDocument(); } + bool IsErrorPage(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj) { + return IsErrorPage(); + } + int GetLoadError(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj) { + return static_cast<int>(GetLoadError()); + } base::android::ScopedJavaGlobalRef<jobject> java_navigation() { return java_navigation_; @@ -51,8 +59,10 @@ // Navigation implementation: GURL GetURL() override; const std::vector<GURL>& GetRedirectChain() override; - State GetState() override; + NavigationState GetState() override; bool IsSameDocument() override; + bool IsErrorPage() override; + LoadError GetLoadError() override; content::NavigationHandle* navigation_handle_;
diff --git a/weblayer/public/java/BUILD.gn b/weblayer/public/java/BUILD.gn index fef1b8c..be5b890 100644 --- a/weblayer/public/java/BUILD.gn +++ b/weblayer/public/java/BUILD.gn
@@ -30,9 +30,11 @@ "org/chromium/weblayer/FullscreenCallback.java", "org/chromium/weblayer/ListenableFuture.java", "org/chromium/weblayer/ListenableResult.java", + "org/chromium/weblayer/LoadError.java", "org/chromium/weblayer/NavigationCallback.java", "org/chromium/weblayer/NavigationController.java", "org/chromium/weblayer/Navigation.java", + "org/chromium/weblayer/NavigationState.java", "org/chromium/weblayer/NewTabCallback.java", "org/chromium/weblayer/NewTabType.java", "org/chromium/weblayer/ObserverList.java",
diff --git a/weblayer/public/java/org/chromium/weblayer/LoadError.java b/weblayer/public/java/org/chromium/weblayer/LoadError.java new file mode 100644 index 0000000..2f8d189 --- /dev/null +++ b/weblayer/public/java/org/chromium/weblayer/LoadError.java
@@ -0,0 +1,44 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.weblayer; + +import androidx.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@IntDef({LoadError.NO_ERROR, LoadError.HTTP_CLIENT_ERROR, LoadError.HTTP_SERVER_ERROR, + LoadError.SSL_ERROR, LoadError.CONNECTIVITY_ERROR, LoadError.OTHER_ERROR}) +@Retention(RetentionPolicy.SOURCE) +public @interface LoadError { + /** + * Navigation completed successfully. + */ + int NO_ERROR = org.chromium.weblayer_private.interfaces.LoadError.NO_ERROR; + + /** + * Server responded with 4xx status code. + */ + int HTTP_CLIENT_ERROR = org.chromium.weblayer_private.interfaces.LoadError.HTTP_CLIENT_ERROR; + /** + * Server responded with 5xx status code. + */ + int HTTP_SERVER_ERROR = org.chromium.weblayer_private.interfaces.LoadError.HTTP_SERVER_ERROR; + + /** + * Certificate error. + */ + int SSL_ERROR = org.chromium.weblayer_private.interfaces.LoadError.SSL_ERROR; + + /** + * Problem connecting to server. + */ + int CONNECTIVITY_ERROR = org.chromium.weblayer_private.interfaces.LoadError.CONNECTIVITY_ERROR; + + /** + * An error not listed above occurred. + */ + int OTHER_ERROR = org.chromium.weblayer_private.interfaces.LoadError.OTHER_ERROR; +}
diff --git a/weblayer/public/java/org/chromium/weblayer/Navigation.java b/weblayer/public/java/org/chromium/weblayer/Navigation.java index fb6cd88..2897ddd 100644 --- a/weblayer/public/java/org/chromium/weblayer/Navigation.java +++ b/weblayer/public/java/org/chromium/weblayer/Navigation.java
@@ -21,37 +21,16 @@ */ public final class Navigation extends IClientNavigation.Stub { private final INavigation mNavigationImpl; - // TODO(sky): investigate using java_cpp_enum. - public enum State { - WAITING_RESPONSE, - RECEIVING_BYTES, - COMPLETE, - FAILED, - } - - private static State ipcStateToState(int state) { - switch (state) { - case 0: - return State.WAITING_RESPONSE; - case 1: - return State.RECEIVING_BYTES; - case 2: - return State.COMPLETE; - case 3: - return State.FAILED; - default: - throw new IllegalArgumentException("Unexpected state " + state); - } - } Navigation(INavigation impl) { mNavigationImpl = impl; } - public State getState() { + @NavigationState + public int getState() { ThreadCheck.ensureOnUiThread(); try { - return ipcStateToState(mNavigationImpl.getState()); + return mNavigationImpl.getState(); } catch (RemoteException e) { throw new APICallException(e); } @@ -95,10 +74,37 @@ * - same page history navigation */ public boolean isSameDocument() { + ThreadCheck.ensureOnUiThread(); try { return mNavigationImpl.isSameDocument(); } catch (RemoteException e) { throw new APICallException(e); } } + + /** + * Whether the navigation resulted in an error page (e.g. interstitial). Note that if an error + * page reloads, this will return true even though GetNetErrorCode will be kNoError. + */ + public boolean isErrorPage() { + ThreadCheck.ensureOnUiThread(); + try { + return mNavigationImpl.isErrorPage(); + } catch (RemoteException e) { + throw new APICallException(e); + } + } + + /** + * Return information about the error, if any, that was encountered while loading the page. + */ + @LoadError + public int getLoadError() { + ThreadCheck.ensureOnUiThread(); + try { + return mNavigationImpl.getLoadError(); + } catch (RemoteException e) { + throw new APICallException(e); + } + } }
diff --git a/weblayer/public/java/org/chromium/weblayer/NavigationState.java b/weblayer/public/java/org/chromium/weblayer/NavigationState.java new file mode 100644 index 0000000..1d0264a --- /dev/null +++ b/weblayer/public/java/org/chromium/weblayer/NavigationState.java
@@ -0,0 +1,26 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.weblayer; + +import androidx.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * @hide + */ +@IntDef({NavigationState.WAITING_RESPONSE, NavigationState.RECEIVING_BYTES, + NavigationState.COMPLETE, NavigationState.FAILED}) +@Retention(RetentionPolicy.SOURCE) +public @interface NavigationState { + int WAITING_RESPONSE = + org.chromium.weblayer_private.interfaces.NavigationState.WAITING_RESPONSE; + + int RECEIVING_BYTES = org.chromium.weblayer_private.interfaces.NavigationState.RECEIVING_BYTES; + int COMPLETE = org.chromium.weblayer_private.interfaces.NavigationState.COMPLETE; + + int FAILED = org.chromium.weblayer_private.interfaces.NavigationState.FAILED; +}
diff --git a/weblayer/public/navigation.h b/weblayer/public/navigation.h index b8a947e..61fac6c 100644 --- a/weblayer/public/navigation.h +++ b/weblayer/public/navigation.h
@@ -11,6 +11,17 @@ namespace weblayer { +// These types are sent over IPC and across different versions. Never remove +// or change the order. +// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.weblayer_private +// GENERATED_JAVA_CLASS_NAME_OVERRIDE: ImplNavigationState +enum class NavigationState { + kWaitingResponse = 0, + kReceivingBytes = 1, + kComplete = 2, + kFailed = 3, +}; + class Navigation { public: virtual ~Navigation() {} @@ -24,16 +35,7 @@ // there will be one entry in the list). virtual const std::vector<GURL>& GetRedirectChain() = 0; - // These types are sent over IPC and across different versions. Never remove - // or change the order. - enum State { - kWaitingResponse = 0, - kReceivingBytes = 1, - kComplete = 2, - kFailed = 3, - }; - - virtual State GetState() = 0; + virtual NavigationState GetState() = 0; // Whether the navigation happened without changing document. Examples of // same document navigations are: @@ -41,6 +43,26 @@ // * pushState/replaceState // * same page history navigation virtual bool IsSameDocument() = 0; + + // Whether the navigation resulted in an error page (e.g. interstitial). Note + // that if an error page reloads, this will return true even though + // GetNetErrorCode will be kNoError. + virtual bool IsErrorPage() = 0; + + // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.weblayer_private + // GENERATED_JAVA_CLASS_NAME_OVERRIDE: ImplLoadError + enum LoadError { + kNoError = 0, // Navigation completed successfully. + kHttpClientError = 1, // Server responded with 4xx status code. + kHttpServerError = 2, // Server responded with 5xx status code. + kSSLError = 3, // Certificate error. + kConnectivityError = 4, // Problem connecting to server. + kOtherError = 5, // An error not listed above occurred. + }; + + // Return information about the error, if any, that was encountered while + // loading the page. + virtual LoadError GetLoadError() = 0; }; } // namespace weblayer
diff --git a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java index a03b913..7cf69fe 100644 --- a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java +++ b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java
@@ -22,6 +22,7 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; +import org.chromium.weblayer.LoadError; import org.chromium.weblayer.Navigation; import org.chromium.weblayer.NavigationCallback; import org.chromium.weblayer.NavigationController; @@ -52,11 +53,13 @@ private Uri mUri; private boolean mIsSameDocument; private List<Uri> mRedirectChain; + private @LoadError int mLoadError; public void notifyCalled(Navigation navigation) { mUri = navigation.getUri(); mIsSameDocument = navigation.isSameDocument(); mRedirectChain = navigation.getRedirectChain(); + mLoadError = navigation.getLoadError(); notifyCalled(); } @@ -77,6 +80,13 @@ waitForCallback(currentCallCount); assertEquals(mRedirectChain, redirectChain); } + + public void assertCalledWith(int currentCallCount, String uri, @LoadError int loadError) + throws TimeoutException { + waitForCallback(currentCallCount); + assertEquals(mUri.toString(), uri); + assertEquals(mLoadError, loadError); + } } public static class NavigationCallbackValueRecorder { @@ -341,6 +351,22 @@ }); } + @Test + @SmallTest + public void testLoadError() throws Exception { + String url = mActivityTestRule.getTestDataURL("non_existent.html"); + + InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank"); + setNavigationCallback(activity); + + int curCompletedCount = mCallback.onCompletedCallback.getCallCount(); + + mActivityTestRule.navigateAndWait(url); + + mCallback.onCompletedCallback.assertCalledWith( + curCompletedCount, url, LoadError.HTTP_CLIENT_ERROR); + } + private void setNavigationCallback(InstrumentationActivity activity) { runOnUiThreadBlocking( ()
diff --git a/weblayer/shell/app/shell_main_params.cc b/weblayer/shell/app/shell_main_params.cc index 3524d87d..8a25b79 100644 --- a/weblayer/shell/app/shell_main_params.cc +++ b/weblayer/shell/app/shell_main_params.cc
@@ -31,6 +31,9 @@ GURL GetStartupURL() { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kNoInitialNavigation)) + return GURL(); + const base::CommandLine::StringVector& args = command_line->GetArgs(); #if defined(OS_ANDROID)
diff --git a/weblayer/shell/common/shell_switches.cc b/weblayer/shell/common/shell_switches.cc index feded8a..db313c6 100644 --- a/weblayer/shell/common/shell_switches.cc +++ b/weblayer/shell/common/shell_switches.cc
@@ -6,6 +6,9 @@ namespace switches { +// Stops new Shell objects from navigating to a default url. +const char kNoInitialNavigation[] = "no-initial-navigation"; + // Makes WebLayer Shell use the given path for its data directory. const char kWebLayerShellDataPath[] = "data-path";
diff --git a/weblayer/shell/common/shell_switches.h b/weblayer/shell/common/shell_switches.h index 26548d9..a7ab5e4 100644 --- a/weblayer/shell/common/shell_switches.h +++ b/weblayer/shell/common/shell_switches.h
@@ -7,6 +7,7 @@ namespace switches { +extern const char kNoInitialNavigation[]; extern const char kWebLayerShellDataPath[]; } // namespace switches
diff --git a/weblayer/test/BUILD.gn b/weblayer/test/BUILD.gn index 815e774..ea44f8a 100644 --- a/weblayer/test/BUILD.gn +++ b/weblayer/test/BUILD.gn
@@ -87,6 +87,7 @@ ] sources = [ + "../browser/navigation_browsertest.cc", "../browser/ssl_browsertest.cc", "../browser/webui/webui_browsertest.cc", "browsertests_main.cc",
diff --git a/weblayer/test/weblayer_browser_test.cc b/weblayer/test/weblayer_browser_test.cc index 415c1d17..04cbfa78 100644 --- a/weblayer/test/weblayer_browser_test.cc +++ b/weblayer/test/weblayer_browser_test.cc
@@ -7,6 +7,7 @@ #include "base/base_paths.h" #include "base/command_line.h" #include "weblayer/shell/browser/shell.h" +#include "weblayer/shell/common/shell_switches.h" namespace weblayer { @@ -18,6 +19,7 @@ void WebLayerBrowserTest::SetUp() { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + command_line->AppendSwitch(switches::kNoInitialNavigation); SetUpCommandLine(command_line); content::BrowserTestBase::SetUp(); }