diff --git a/.gitignore b/.gitignore index 2d2ec98..f01599cf 100644 --- a/.gitignore +++ b/.gitignore
@@ -61,7 +61,7 @@ /.settings/ /.vs/ # Visual Studio Code -/.vscode/ +.vscode/ /_out /android_emulator_sdk /ash/ash_unittests_run.xml
diff --git a/DEPS b/DEPS index a617575..fdb998db 100644 --- a/DEPS +++ b/DEPS
@@ -129,7 +129,7 @@ # 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': '69da7ad49b55a9085ff4e442b5d67ea110ac5566', + 'skia_revision': 'c7755d9470846024ad8108bc7b9b868e808258d6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -145,7 +145,7 @@ # 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': 'bd3af855ae74d9767eb68adcdd1a66c29dc1d81e', + 'swiftshader_revision': '484e08e0fae627f107df3458242e158741a42e96', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -196,7 +196,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': '9057b413d4b19b24786542b710e03cfa62bbb6af', + 'catapult_revision': '27980609ac44bfbce0fd4d752f7c1efd5f32d58a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -805,7 +805,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c5403d69e17c0cf99abb9eb10e827515afca499f', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c6dfce981f13e2699c827618d3f92d8cb0656aca', 'condition': 'checkout_linux', }, @@ -959,7 +959,7 @@ }, 'src/third_party/arcore-android-sdk/src': { - 'url': Var('chromium_git') + '/external/github.com/google-ar/arcore-android-sdk.git' + '@' + '6fcebcbf021b53ceb254e58cce6d5d4a4214819d', + 'url': Var('chromium_git') + '/external/github.com/google-ar/arcore-android-sdk.git' + '@' + '5b67d88f0b33edbfbe4902141ca44e750df9b6c2', 'condition': 'checkout_android', }, @@ -1172,7 +1172,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '3c836b671503ce665ee4a9e4fe79e8758866acfc', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'cc57bf714a300c5e0b6bc04f76ea058e50c38399', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1999,7 +1999,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_ar_core', - 'version': 'version:1.6.0-cr0', + 'version': 'version:1.8.0-cr0', }, ], 'condition': 'checkout_android',
diff --git a/ash/display/display_output_protection.cc b/ash/display/display_output_protection.cc index cd734f83..e676944 100644 --- a/ash/display/display_output_protection.cc +++ b/ash/display/display_output_protection.cc
@@ -24,11 +24,13 @@ display_configurator_->UnregisterContentProtectionClient(client_id_); } - uint64_t client_id() const { return client_id_; } + DisplayConfigurator::ContentProtectionClientId client_id() const { + return client_id_; + } private: - display::DisplayConfigurator* const display_configurator_; - const uint64_t client_id_; + DisplayConfigurator* const display_configurator_; + const DisplayConfigurator::ContentProtectionClientId client_id_; DISALLOW_COPY_AND_ASSIGN(BindingContext); }; @@ -49,7 +51,7 @@ void DisplayOutputProtection::QueryContentProtectionStatus( int64_t display_id, QueryContentProtectionStatusCallback callback) { - display_configurator_->QueryContentProtectionStatus( + display_configurator_->QueryContentProtection( bindings_.dispatch_context()->client_id(), display_id, std::move(callback)); } @@ -58,7 +60,7 @@ int64_t display_id, uint32_t desired_method_mask, SetContentProtectionCallback callback) { - display_configurator_->SetContentProtection( + display_configurator_->ApplyContentProtection( bindings_.dispatch_context()->client_id(), display_id, desired_method_mask, std::move(callback)); }
diff --git a/ash/kiosk_next/kiosk_next_shell_controller.cc b/ash/kiosk_next/kiosk_next_shell_controller.cc index 5ca69ca33..279be8a 100644 --- a/ash/kiosk_next/kiosk_next_shell_controller.cc +++ b/ash/kiosk_next/kiosk_next_shell_controller.cc
@@ -26,9 +26,16 @@ // static void KioskNextShellController::RegisterProfilePrefs( - PrefRegistrySimple* registry) { - registry->RegisterBooleanPref(prefs::kKioskNextShellEnabled, false, - PrefRegistry::PUBLIC); + PrefRegistrySimple* registry, + bool for_test) { + if (for_test) { + registry->RegisterBooleanPref(prefs::kKioskNextShellEnabled, false, + PrefRegistry::PUBLIC); + return; + } + // The registration has been moved to + // chromeos::Preferences::RegisterProfilePrefs to avoid race conditions. + registry->RegisterForeignPref(prefs::kKioskNextShellEnabled); } void KioskNextShellController::BindRequest(
diff --git a/ash/kiosk_next/kiosk_next_shell_controller.h b/ash/kiosk_next/kiosk_next_shell_controller.h index 3d0c072..7d3fd45 100644 --- a/ash/kiosk_next/kiosk_next_shell_controller.h +++ b/ash/kiosk_next/kiosk_next_shell_controller.h
@@ -30,7 +30,7 @@ ~KioskNextShellController() override; // Register prefs related to the Kiosk Next Shell. - static void RegisterProfilePrefs(PrefRegistrySimple* registry); + static void RegisterProfilePrefs(PrefRegistrySimple* registry, bool for_test); // Binds the mojom::KioskNextShellController interface to this object. void BindRequest(mojom::KioskNextShellControllerRequest request);
diff --git a/ash/kiosk_next/kiosk_next_shell_controller_unittest.cc b/ash/kiosk_next/kiosk_next_shell_controller_unittest.cc index 85a3e6d..99e0446 100644 --- a/ash/kiosk_next/kiosk_next_shell_controller_unittest.cc +++ b/ash/kiosk_next/kiosk_next_shell_controller_unittest.cc
@@ -58,29 +58,26 @@ } protected: - void LoginKioskNextUser() { + void LoginKioskNextUser() { LoginUser(true); } + + void LoginUser(bool enable_kiosk_next_shell) { TestSessionControllerClient* session_controller_client = GetSessionControllerClient(); // Create session for KioskNext user. session_controller_client->AddUserSession( kTestUserEmail, user_manager::USER_TYPE_REGULAR, - true /* enable_settings */, false /* provide_pref_service */); + true /* enable_settings */, true /* provide_pref_service */); - // Create a KioskNext User and register its preferences. - auto pref_service = std::make_unique<TestingPrefServiceSimple>(); + ash::SessionController* controller = Shell::Get()->session_controller(); - // Initialize the default preferences. - Shell::RegisterUserProfilePrefs(pref_service->registry(), - true /* for_test */); + PrefService* pref_service = controller->GetUserPrefServiceForUser( + AccountId::FromUserEmail(kTestUserEmail)); - // Set the user's KioskNextShell preference. - pref_service->SetUserPref(prefs::kKioskNextShellEnabled, - std::make_unique<base::Value>(true)); - - // Provide PrefService for test user. - Shell::Get()->session_controller()->ProvideUserPrefServiceForTest( - AccountId::FromUserEmail(kTestUserEmail), std::move(pref_service)); + if (enable_kiosk_next_shell) { + // Set the user's KioskNextShell preference. + pref_service->Set(prefs::kKioskNextShellEnabled, base::Value(true)); + } session_controller_client->SwitchActiveUser( AccountId::FromUserEmail(kTestUserEmail)); @@ -101,7 +98,7 @@ EXPECT_FALSE(GetKioskNextShellController()->IsEnabled()); // Login a regular user whose KioskNext pref has not been enabled. - SimulateNewUserFirstLogin("primary_user@test.com"); + LoginUser(false /* enable_kiosk_next_shell */); // KioskNextShell is not enabled for regular users by default. EXPECT_FALSE(GetKioskNextShellController()->IsEnabled());
diff --git a/ash/media/media_notification_item.cc b/ash/media/media_notification_item.cc index 4d17ccc7..67c796f 100644 --- a/ash/media/media_notification_item.cc +++ b/ash/media/media_notification_item.cc
@@ -8,6 +8,7 @@ #include "ash/media/media_notification_view.h" #include "ash/public/cpp/notification_utils.h" #include "base/bind.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string16.h" #include "base/time/time.h" #include "services/media_session/public/mojom/constants.mojom.h" @@ -32,6 +33,10 @@ } // namespace +// static +const char MediaNotificationItem::kUserActionHistogramName[] = + "Media.Notification.UserAction"; + MediaNotificationItem::MediaNotificationItem( const std::string& id, media_session::mojom::MediaControllerPtr controller, @@ -186,7 +191,11 @@ if (!button_id) return; - switch (static_cast<MediaSessionAction>(*button_id)) { + const MediaSessionAction action = static_cast<MediaSessionAction>(*button_id); + + UMA_HISTOGRAM_ENUMERATION(kUserActionHistogramName, action); + + switch (action) { case MediaSessionAction::kPreviousTrack: media_controller_ptr_->PreviousTrack(); break;
diff --git a/ash/media/media_notification_item.h b/ash/media/media_notification_item.h index 468cccb..944e2d5 100644 --- a/ash/media/media_notification_item.h +++ b/ash/media/media_notification_item.h
@@ -26,6 +26,9 @@ : public media_session::mojom::MediaControllerObserver, public media_session::mojom::MediaControllerImageObserver { public: + // The name of the histogram used when recording user actions. + static const char kUserActionHistogramName[]; + MediaNotificationItem(const std::string& id, media_session::mojom::MediaControllerPtr controller, media_session::mojom::MediaSessionInfoPtr session_info);
diff --git a/ash/media/media_notification_view_unittest.cc b/ash/media/media_notification_view_unittest.cc index 88a7c0e..0ec769bc 100644 --- a/ash/media/media_notification_view_unittest.cc +++ b/ash/media/media_notification_view_unittest.cc
@@ -20,6 +20,7 @@ #include "base/bind.h" #include "base/macros.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/unguessable_token.h" #include "services/media_session/public/cpp/test/test_media_controller.h" @@ -230,6 +231,12 @@ ui::EventTimeForNow(), 0, 0)); } + void ExpectHistogramActionRecorded(MediaSessionAction action) { + histogram_tester_.ExpectUniqueSample( + MediaNotificationItem::kUserActionHistogramName, + static_cast<base::HistogramBase::Sample>(action), 1); + } + private: std::unique_ptr<message_center::MessageView> CreateAndCaptureCustomView( const message_center::Notification& notification) { @@ -247,6 +254,8 @@ base::test::ScopedFeatureList scoped_feature_list_; + base::HistogramTester histogram_tester_; + std::set<MediaSessionAction> actions_; std::unique_ptr<TestMediaController> media_controller_; @@ -316,6 +325,7 @@ GetItem()->FlushForTesting(); EXPECT_EQ(1, media_controller()->next_track_count()); + ExpectHistogramActionRecorded(MediaSessionAction::kNextTrack); } TEST_F(MediaNotificationViewTest, PlayButtonClick) { @@ -327,6 +337,7 @@ GetItem()->FlushForTesting(); EXPECT_EQ(1, media_controller()->resume_count()); + ExpectHistogramActionRecorded(MediaSessionAction::kPlay); } TEST_F(MediaNotificationViewTest, PauseButtonClick) { @@ -345,6 +356,7 @@ GetItem()->FlushForTesting(); EXPECT_EQ(1, media_controller()->suspend_count()); + ExpectHistogramActionRecorded(MediaSessionAction::kPause); } TEST_F(MediaNotificationViewTest, PreviousTrackButtonClick) { @@ -356,6 +368,7 @@ GetItem()->FlushForTesting(); EXPECT_EQ(1, media_controller()->previous_track_count()); + ExpectHistogramActionRecorded(MediaSessionAction::kPreviousTrack); } TEST_F(MediaNotificationViewTest, SeekBackwardButtonClick) { @@ -367,6 +380,7 @@ GetItem()->FlushForTesting(); EXPECT_EQ(1, media_controller()->seek_backward_count()); + ExpectHistogramActionRecorded(MediaSessionAction::kSeekBackward); } TEST_F(MediaNotificationViewTest, SeekForwardButtonClick) { @@ -378,6 +392,7 @@ GetItem()->FlushForTesting(); EXPECT_EQ(1, media_controller()->seek_forward_count()); + ExpectHistogramActionRecorded(MediaSessionAction::kSeekForward); } TEST_F(MediaNotificationViewTest, ClickNotification) {
diff --git a/ash/shell.cc b/ash/shell.cc index 5a28ef66..0fd5af9 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -256,7 +256,7 @@ BluetoothPowerController::RegisterProfilePrefs(registry); CapsLockNotificationController::RegisterProfilePrefs(registry, for_test); DockedMagnifierController::RegisterProfilePrefs(registry, for_test); - KioskNextShellController::RegisterProfilePrefs(registry); + KioskNextShellController::RegisterProfilePrefs(registry, for_test); LoginScreenController::RegisterProfilePrefs(registry, for_test); LogoutButtonTray::RegisterProfilePrefs(registry); MessageCenterController::RegisterProfilePrefs(registry);
diff --git a/ash/wm/non_client_frame_controller.cc b/ash/wm/non_client_frame_controller.cc index 7d7bb5c..7ede688 100644 --- a/ash/wm/non_client_frame_controller.cc +++ b/ash/wm/non_client_frame_controller.cc
@@ -255,7 +255,6 @@ new WmNativeWidgetAura(widget_, DoesClientProvideFrame(properties)); window_ = native_widget->GetNativeView(); window_->SetProperty(kNonClientFrameControllerKey, this); - window_->SetProperty(kWidgetCreationTypeKey, WidgetCreationType::FOR_CLIENT); window_->AddObserver(this); params.native_widget = native_widget; aura::SetWindowType(window_, ws::mojom::WindowType::WINDOW);
diff --git a/ash/wm/top_level_window_factory_unittest.cc b/ash/wm/top_level_window_factory_unittest.cc index ce2cdfe..cdd9ebf 100644 --- a/ash/wm/top_level_window_factory_unittest.cc +++ b/ash/wm/top_level_window_factory_unittest.cc
@@ -108,8 +108,6 @@ ASSERT_TRUE(window->parent()); EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id()); EXPECT_EQ(bounds, window->bounds()); - EXPECT_EQ(WidgetCreationType::FOR_CLIENT, - window->GetProperty(kWidgetCreationTypeKey)); EXPECT_FALSE(window->IsVisible()); }
diff --git a/ash/wm/widget_finder.cc b/ash/wm/widget_finder.cc index 5989f32..8701c51 100644 --- a/ash/wm/widget_finder.cc +++ b/ash/wm/widget_finder.cc
@@ -4,17 +4,16 @@ #include "ash/wm/widget_finder.h" -#include "ash/wm/window_properties.h" +#include "services/ws/window_service.h" #include "ui/aura/window.h" #include "ui/views/widget/widget.h" namespace ash { views::Widget* GetInternalWidgetForWindow(aura::Window* window) { - return window->GetProperty(kWidgetCreationTypeKey) == - WidgetCreationType::INTERNAL - ? views::Widget::GetWidgetForNativeView(window) - : nullptr; + return ws::WindowService::IsProxyWindow(window) + ? nullptr + : views::Widget::GetWidgetForNativeView(window); } } // namespace ash
diff --git a/ash/wm/window_properties.cc b/ash/wm/window_properties.cc index 5be1ad3..99d5c66e 100644 --- a/ash/wm/window_properties.cc +++ b/ash/wm/window_properties.cc
@@ -8,16 +8,11 @@ #include "ui/gfx/geometry/rect.h" DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(ASH_EXPORT, ash::wm::WindowState*) -DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(ASH_EXPORT, ash::WidgetCreationType) namespace ash { DEFINE_UI_CLASS_PROPERTY_KEY(bool, kLockedToRootKey, false) -DEFINE_UI_CLASS_PROPERTY_KEY(WidgetCreationType, - kWidgetCreationTypeKey, - WidgetCreationType::INTERNAL) - DEFINE_UI_CLASS_PROPERTY_KEY(bool, kWindowIsJanky, false) DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(ash::wm::WindowState, kWindowStateKey, NULL)
diff --git a/ash/wm/window_properties.h b/ash/wm/window_properties.h index c243e56..3d7f88b 100644 --- a/ash/wm/window_properties.h +++ b/ash/wm/window_properties.h
@@ -19,26 +19,6 @@ class WindowState; } // namespace wm -// Used with kWidgetCreationType to indicate source of the widget creation. -// -// TODO: investigate removing this. If it's still needed, we can likely ask -// the window service if it has a remote client for the window rather than using -// a property. https://crbug.com/865616 -enum class WidgetCreationType { - // The widget was created internally, and not at the request of a client. - // For example, overview mode creates a number of widgets. These widgets are - // created with a type of INTERNAL. This is the default. - INTERNAL, - - // The widget was created for a client. In other words there is a client - // embedded in the aura::Window. For example, when Chrome creates a new - // browser window the window manager is asked to create the aura::Window. - // The window manager creates an aura::Window and a views::Widget to show - // the non-client frame decorations. In this case the creation type is - // FOR_CLIENT. - FOR_CLIENT, -}; - // Shell-specific window property keys; some keys are exported for use in tests. // Alphabetical sort. @@ -47,9 +27,6 @@ // bounds outside of its root window is set. ASH_EXPORT extern const aura::WindowProperty<bool>* const kLockedToRootKey; -ASH_EXPORT extern const aura::WindowProperty<WidgetCreationType>* const - kWidgetCreationTypeKey; - // Set to true if the window server tells us the window is janky (see // WindowManagerDelegate::OnWmClientJankinessChanged()). ASH_EXPORT extern const aura::WindowProperty<bool>* const kWindowIsJanky;
diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc index 9f19663..493252e9 100644 --- a/ash/wm/window_state.cc +++ b/ash/wm/window_state.cc
@@ -194,7 +194,8 @@ } void WindowState::SetDelegate(std::unique_ptr<WindowStateDelegate> delegate) { - DCHECK(!delegate_.get()); + DCHECK((!delegate_.get() && !!delegate.get()) || + (!!delegate_.get() && !delegate.get())); delegate_ = std::move(delegate); }
diff --git a/base/profiler/stack_sampler.h b/base/profiler/stack_sampler.h index 262e38d..a6f13d00 100644 --- a/base/profiler/stack_sampler.h +++ b/base/profiler/stack_sampler.h
@@ -13,6 +13,7 @@ namespace base { +class Unwinder; class ModuleCache; class ProfileBuilder; class StackSamplerTestDelegate; @@ -61,6 +62,10 @@ // The following functions are all called on the SamplingThread (not the // thread being sampled). + // Adds an auxiliary unwinder to handle additional, non-native-code unwind + // scenarios. + virtual void AddAuxUnwinder(Unwinder* unwinder) = 0; + // Records a set of frames and returns them. virtual void RecordStackFrames(StackBuffer* stackbuffer, ProfileBuilder* profile_builder) = 0;
diff --git a/base/profiler/stack_sampler_impl.cc b/base/profiler/stack_sampler_impl.cc index a1153c3..fffb59a1 100644 --- a/base/profiler/stack_sampler_impl.cc +++ b/base/profiler/stack_sampler_impl.cc
@@ -85,6 +85,10 @@ StackSamplerImpl::~StackSamplerImpl() = default; +void StackSamplerImpl::AddAuxUnwinder(Unwinder* unwinder) { + aux_unwinder_ = unwinder; +} + void StackSamplerImpl::RecordStackFrames(StackBuffer* stack_buffer, ProfileBuilder* profile_builder) { DCHECK(stack_buffer);
diff --git a/base/profiler/stack_sampler_impl.h b/base/profiler/stack_sampler_impl.h index 926c4a3..d7aaac1 100644 --- a/base/profiler/stack_sampler_impl.h +++ b/base/profiler/stack_sampler_impl.h
@@ -30,7 +30,8 @@ StackSamplerImpl(const StackSamplerImpl&) = delete; StackSamplerImpl& operator=(const StackSamplerImpl&) = delete; - // Records a set of frames and returns them. + // StackSampler: + void AddAuxUnwinder(Unwinder* unwinder) override; void RecordStackFrames(StackBuffer* stack_buffer, ProfileBuilder* profile_builder) override; @@ -45,6 +46,7 @@ const std::unique_ptr<ThreadDelegate> thread_delegate_; const std::unique_ptr<Unwinder> native_unwinder_; + Unwinder* aux_unwinder_ = nullptr; ModuleCache* const module_cache_; StackSamplerTestDelegate* const test_delegate_; };
diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc index f5687e7..0c7c1f4 100644 --- a/base/profiler/stack_sampling_profiler.cc +++ b/base/profiler/stack_sampling_profiler.cc
@@ -125,6 +125,10 @@ // stop the sampling. int Add(std::unique_ptr<CollectionContext> collection); + // Adds an auxiliary unwinder to be used for the collection, to handle + // additional, non-native-code unwind scenarios. + void AddAuxUnwinder(int collection_id, Unwinder* unwinder); + // Removes an active collection based on its collection id, forcing it to run // its callback if any data has been collected. This can be called externally // from any thread. @@ -174,6 +178,7 @@ // These methods are tasks that get posted to the internal message queue. void AddCollectionTask(std::unique_ptr<CollectionContext> collection); + void AddAuxUnwinderTask(int collection_id, Unwinder* unwinder); void RemoveCollectionTask(int collection_id); void RecordSampleTask(int collection_id); void ShutdownTask(int add_events); @@ -324,6 +329,18 @@ return collection_id; } +void StackSamplingProfiler::SamplingThread::AddAuxUnwinder(int collection_id, + Unwinder* unwinder) { + ThreadExecutionState state; + scoped_refptr<SingleThreadTaskRunner> task_runner = GetTaskRunner(&state); + if (state != RUNNING) + return; + DCHECK(task_runner); + task_runner->PostTask( + FROM_HERE, BindOnce(&SamplingThread::AddAuxUnwinderTask, Unretained(this), + collection_id, unwinder)); +} + void StackSamplingProfiler::SamplingThread::Remove(int collection_id) { // This is not to be run on the sampling thread. @@ -458,6 +475,18 @@ TimeDelta::FromSeconds(60)); } +void StackSamplingProfiler::SamplingThread::AddAuxUnwinderTask( + int collection_id, + Unwinder* unwinder) { + DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); + + auto loc = active_collections_.find(collection_id); + if (loc == active_collections_.end()) + return; + + loc->second->native_sampler->AddAuxUnwinder(unwinder); +} + void StackSamplingProfiler::SamplingThread::AddCollectionTask( std::unique_ptr<CollectionContext> collection) { DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); @@ -715,4 +744,9 @@ profiler_id_ = kNullProfilerId; } +void StackSamplingProfiler::AddAuxUnwinder(Unwinder* unwinder) { + SamplingThread::GetInstance()->AddAuxUnwinder(profiler_id_, + std::move(unwinder)); +} + } // namespace base
diff --git a/base/profiler/stack_sampling_profiler.h b/base/profiler/stack_sampling_profiler.h index 25779f3..71f8d0c5 100644 --- a/base/profiler/stack_sampling_profiler.h +++ b/base/profiler/stack_sampling_profiler.h
@@ -17,6 +17,7 @@ namespace base { +class Unwinder; class StackSampler; class StackSamplerTestDelegate; @@ -110,6 +111,10 @@ // are completed or the profiler object is destroyed, whichever occurs first. void Stop(); + // Adds an auxiliary unwinder to handle additional, non-native-code unwind + // scenarios. + void AddAuxUnwinder(Unwinder* unwinder); + // Test peer class. These functions are purely for internal testing of // StackSamplingProfiler; DO NOT USE within tests outside of this directory. // The functions are static because they interact with the sampling thread, a
diff --git a/cc/paint/image_provider.cc b/cc/paint/image_provider.cc index fa224ad5..e30c8bb 100644 --- a/cc/paint/image_provider.cc +++ b/cc/paint/image_provider.cc
@@ -17,27 +17,24 @@ DestructionCallback callback) : image_(std::move(image)), destruction_callback_(std::move(callback)) {} -ImageProvider::ScopedResult::ScopedResult(const PaintRecord* record, +ImageProvider::ScopedResult::ScopedResult(sk_sp<PaintRecord> record, DestructionCallback callback) - : record_(record), destruction_callback_(std::move(callback)) { + : record_(std::move(record)), destruction_callback_(std::move(callback)) { DCHECK(!destruction_callback_.is_null()); } ImageProvider::ScopedResult::ScopedResult(ScopedResult&& other) : image_(std::move(other.image_)), - record_(other.record_), - destruction_callback_(std::move(other.destruction_callback_)) { - other.record_ = nullptr; -} + record_(std::move(other.record_)), + destruction_callback_(std::move(other.destruction_callback_)) {} ImageProvider::ScopedResult& ImageProvider::ScopedResult::operator=( ScopedResult&& other) { DestroyDecode(); image_ = std::move(other.image_); - record_ = other.record_; + record_ = std::move(other.record_); destruction_callback_ = std::move(other.destruction_callback_); - other.record_ = nullptr; return *this; }
diff --git a/cc/paint/image_provider.h b/cc/paint/image_provider.h index 6ffd8978..2b5e5f707 100644 --- a/cc/paint/image_provider.h +++ b/cc/paint/image_provider.h
@@ -10,6 +10,7 @@ #include "cc/paint/decoded_draw_image.h" #include "cc/paint/draw_image.h" #include "cc/paint/paint_export.h" +#include "cc/paint/paint_op_buffer.h" #include <vector> @@ -27,7 +28,7 @@ ScopedResult(); explicit ScopedResult(DecodedDrawImage image); ScopedResult(DecodedDrawImage image, DestructionCallback callback); - ScopedResult(const PaintRecord* record, DestructionCallback callback); + ScopedResult(sk_sp<PaintRecord> record, DestructionCallback callback); ScopedResult(const ScopedResult&) = delete; ScopedResult(ScopedResult&& other); ~ScopedResult(); @@ -40,14 +41,14 @@ bool needs_unlock() const { return !destruction_callback_.is_null(); } const PaintRecord* paint_record() { DCHECK(record_); - return record_; + return record_.get(); } private: void DestroyDecode(); DecodedDrawImage image_; - const PaintRecord* record_ = nullptr; + sk_sp<PaintRecord> record_; DestructionCallback destruction_callback_; };
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc index 5d82c6e..39ffaff 100644 --- a/cc/paint/paint_op_buffer_unittest.cc +++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -2742,7 +2742,7 @@ quality_[i], true)); } - void SetRecord(PaintRecord* record) { record_ = record; } + void SetRecord(sk_sp<PaintRecord> record) { record_ = std::move(record); } private: std::vector<SkSize> src_rect_offset_; @@ -2750,7 +2750,7 @@ std::vector<SkFilterQuality> quality_; size_t index_ = 0; bool fail_all_decodes_ = false; - PaintRecord* record_; + sk_sp<PaintRecord> record_; }; TEST(PaintOpBufferTest, SkipsOpsOutsideClip) { @@ -2845,18 +2845,18 @@ } TEST(PaintOpBufferTest, RasterPaintWorkletImage1) { - PaintOpBuffer paint_worklet_buffer; + sk_sp<PaintOpBuffer> paint_worklet_buffer = sk_make_sp<PaintOpBuffer>(); PaintFlags noop_flags; SkRect savelayer_rect = SkRect::MakeXYWH(0, 0, 100, 100); - paint_worklet_buffer.push<TranslateOp>(8.0f, 8.0f); - paint_worklet_buffer.push<SaveLayerOp>(&savelayer_rect, &noop_flags); + paint_worklet_buffer->push<TranslateOp>(8.0f, 8.0f); + paint_worklet_buffer->push<SaveLayerOp>(&savelayer_rect, &noop_flags); PaintFlags draw_flags; draw_flags.setColor(0u); SkRect rect = SkRect::MakeXYWH(0, 0, 100, 100); - paint_worklet_buffer.push<DrawRectOp>(rect, draw_flags); + paint_worklet_buffer->push<DrawRectOp>(rect, draw_flags); MockImageProvider provider; - provider.SetRecord(&paint_worklet_buffer); + provider.SetRecord(paint_worklet_buffer); PaintOpBuffer blink_buffer; scoped_refptr<TestPaintWorkletInput> input = @@ -2878,20 +2878,20 @@ } TEST(PaintOpBufferTest, RasterPaintWorkletImage2) { - PaintOpBuffer paint_worklet_buffer; + sk_sp<PaintOpBuffer> paint_worklet_buffer = sk_make_sp<PaintOpBuffer>(); PaintFlags noop_flags; SkRect savelayer_rect = SkRect::MakeXYWH(0, 0, 10, 10); - paint_worklet_buffer.push<SaveLayerOp>(&savelayer_rect, &noop_flags); + paint_worklet_buffer->push<SaveLayerOp>(&savelayer_rect, &noop_flags); PaintFlags draw_flags; draw_flags.setFilterQuality(kLow_SkFilterQuality); PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10)); - paint_worklet_buffer.push<DrawImageOp>(paint_image, 0.0f, 0.0f, &draw_flags); + paint_worklet_buffer->push<DrawImageOp>(paint_image, 0.0f, 0.0f, &draw_flags); std::vector<SkSize> src_rect_offset = {SkSize::MakeEmpty()}; std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f)}; std::vector<SkFilterQuality> quality = {kHigh_SkFilterQuality}; MockImageProvider provider(src_rect_offset, scale_adjustment, quality); - provider.SetRecord(&paint_worklet_buffer); + provider.SetRecord(paint_worklet_buffer); PaintOpBuffer blink_buffer; scoped_refptr<TestPaintWorkletInput> input =
diff --git a/cc/raster/paint_worklet_image_provider.cc b/cc/raster/paint_worklet_image_provider.cc index f33424d..7312ba3 100644 --- a/cc/raster/paint_worklet_image_provider.cc +++ b/cc/raster/paint_worklet_image_provider.cc
@@ -25,9 +25,9 @@ ImageProvider::ScopedResult PaintWorkletImageProvider::GetPaintRecordResult( PaintWorkletInput* input) { - std::pair<PaintRecord*, base::OnceCallback<void()>> record_and_callback = - cache_->GetPaintRecordAndRef(input); - return ImageProvider::ScopedResult(record_and_callback.first, + std::pair<sk_sp<PaintRecord>, base::OnceCallback<void()>> + record_and_callback = cache_->GetPaintRecordAndRef(input); + return ImageProvider::ScopedResult(std::move(record_and_callback.first), std::move(record_and_callback.second)); }
diff --git a/cc/tiles/paint_worklet_image_cache.cc b/cc/tiles/paint_worklet_image_cache.cc index b955b08..7d6cc848 100644 --- a/cc/tiles/paint_worklet_image_cache.cc +++ b/cc/tiles/paint_worklet_image_cache.cc
@@ -5,6 +5,7 @@ #include "cc/tiles/paint_worklet_image_cache.h" #include "base/bind.h" +#include "base/bind_helpers.h" #include "cc/paint/paint_worklet_layer_painter.h" namespace cc { @@ -85,15 +86,13 @@ } } -std::pair<PaintRecord*, base::OnceCallback<void()>> +std::pair<sk_sp<PaintRecord>, base::OnceCallback<void()>> PaintWorkletImageCache::GetPaintRecordAndRef(PaintWorkletInput* input) { base::AutoLock hold(records_lock_); // If the |painter_| is null, then GetTaskForPaintWorkletImage will return a // null TileTask, and hence there will be no cache entry for this input. - if (!painter_) { - return std::make_pair(sk_make_sp<PaintOpBuffer>().get(), - base::OnceCallback<void()>()); - } + if (!painter_) + return std::make_pair(sk_make_sp<PaintOpBuffer>(), base::DoNothing::Once()); DCHECK(records_.find(input) != records_.end()); records_[input].used_ref_count++; records_[input].num_of_frames_not_accessed = 0u; @@ -103,7 +102,7 @@ auto callback = base::BindOnce(&PaintWorkletImageCache::DecrementCacheRefCount, base::Unretained(this), base::Unretained(input)); - return std::make_pair(records_[input].record.get(), std::move(callback)); + return std::make_pair(records_[input].record, std::move(callback)); } void PaintWorkletImageCache::SetNumOfFramesToPurgeCacheEntryForTest(
diff --git a/cc/tiles/paint_worklet_image_cache.h b/cc/tiles/paint_worklet_image_cache.h index e5ef233a..f9b976f3 100644 --- a/cc/tiles/paint_worklet_image_cache.h +++ b/cc/tiles/paint_worklet_image_cache.h
@@ -51,8 +51,8 @@ void NotifyDidPrepareTiles(); // Returns a callback to decrement the ref count for the corresponding entry. - std::pair<PaintRecord*, base::OnceCallback<void()>> GetPaintRecordAndRef( - PaintWorkletInput* input); + std::pair<sk_sp<PaintRecord>, base::OnceCallback<void()>> + GetPaintRecordAndRef(PaintWorkletInput* input); const base::flat_map<PaintWorkletInput*, PaintWorkletImageCacheValue>& GetRecordsForTest() {
diff --git a/cc/tiles/paint_worklet_image_cache_unittest.cc b/cc/tiles/paint_worklet_image_cache_unittest.cc index 4ee6b0d..4a26f40 100644 --- a/cc/tiles/paint_worklet_image_cache_unittest.cc +++ b/cc/tiles/paint_worklet_image_cache_unittest.cc
@@ -198,7 +198,7 @@ records[paint_image2.paint_worklet_input()].num_of_frames_not_accessed, 1u); - std::pair<PaintRecord*, base::OnceCallback<void()>> pair = + std::pair<sk_sp<PaintRecord>, base::OnceCallback<void()>> pair = cache.GetPaintRecordAndRef(paint_image1.paint_worklet_input()); // Run the callback to decrement the ref count. std::move(pair.second).Run(); @@ -257,5 +257,23 @@ } } +TEST(PaintWorkletImageCacheTest, TaskIsNullWhenPainterIsNull) { + TestPaintWorkletImageCache cache; + PaintImage paint_image = CreatePaintImage(100, 100); + scoped_refptr<TileTask> task = + GetTaskForPaintWorkletImage(paint_image, &cache); + EXPECT_EQ(task, nullptr); +} + +TEST(PaintWorkletImageCacheTest, RecordAndCallbackAreEmptyWhenPainterIsNull) { + TestPaintWorkletImageCache cache; + PaintImage paint_image = CreatePaintImage(100, 100); + std::pair<sk_sp<PaintRecord>, base::OnceCallback<void()>> result = + cache.GetPaintRecordAndRef(paint_image.paint_worklet_input()); + EXPECT_EQ(result.first->total_op_count(), 0u); + // This is an empty callback, running it should not crash. + std::move(result.second).Run(); +} + } // namespace } // namespace cc
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 048d0bd..0bec89c 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -1582,6 +1582,7 @@ if (is_chromeos) { public_deps += [ + "//chrome/browser/resources/chromeos:cellular_setup_resources", "//chrome/browser/resources/chromeos:multidevice_setup_resources", "//chrome/browser/resources/chromeos/chromevox", "//chrome/browser/resources/chromeos/select_to_speak:build",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 0d054c7..0d9abf1 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -397,6 +397,8 @@ "java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapState.java", "java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateController.java", "java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateInterface.java", + "java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslation.java", + "java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImpl.java", "java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java", "java/src/org/chromium/chrome/browser/contextualsearch/CtrSuppression.java", "java/src/org/chromium/chrome/browser/contextualsearch/DisableablePromoTapCounter.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index 1d68bf3..3650ab8 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -51,6 +51,7 @@ "junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchEntityHeuristicTest.java", "junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInternalStateTest.java", "junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionControllerTest.java", + "junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImplTest.java", "junit/src/org/chromium/chrome/browser/contextualsearch/SelectionClientManagerTest.java", "junit/src/org/chromium/chrome/browser/cookies/CanonicalCookieTest.java", "junit/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnableUnitTest.java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java index 4549443..291cf89 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
@@ -4,16 +4,20 @@ package org.chromium.chrome.browser.tasks.tab_management; +import static org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider.SYNTHETIC_TRIAL_POSTFIX; + import android.content.Context; import android.view.ViewGroup; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.ThemeColorProvider; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver; +import org.chromium.chrome.browser.metrics.UmaSessionStats; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModelFilterProvider; import org.chromium.chrome.browser.tabmodel.TabModelSelector; @@ -59,6 +63,11 @@ @Override public void initializeWithNative(ChromeActivity activity, BottomControlsCoordinator.BottomControlsVisibilityController visibilityController) { + if (ChromeFeatureList.isInitialized()) { + UmaSessionStats.registerSyntheticFieldTrial( + ChromeFeatureList.TAB_GROUPS_ANDROID + SYNTHETIC_TRIAL_POSTFIX, + "Downloaded_Enabled"); + } assert activity instanceof ChromeTabbedActivity; mActivity = activity; TabModelSelector tabModelSelector = activity.getTabModelSelector();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementModuleImpl.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementModuleImpl.java index 73c61ae..3c94a78 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementModuleImpl.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementModuleImpl.java
@@ -4,11 +4,15 @@ package org.chromium.chrome.browser.tasks.tab_management; +import static org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider.SYNTHETIC_TRIAL_POSTFIX; + import android.view.ViewGroup; import org.chromium.base.annotations.UsedByReflection; import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ThemeColorProvider; +import org.chromium.chrome.browser.metrics.UmaSessionStats; /** * Impl class that will resolve components for tab management. @@ -17,6 +21,11 @@ public class TabManagementModuleImpl implements TabManagementModule { @Override public GridTabSwitcher createGridTabSwitcher(ChromeActivity activity) { + if (ChromeFeatureList.isInitialized()) { + UmaSessionStats.registerSyntheticFieldTrial( + ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID + SYNTHETIC_TRIAL_POSTFIX, + "Downloaded_Enabled"); + } return new GridTabSwitcherCoordinator(activity, activity.getLifecycleDispatcher(), activity.getToolbarManager(), activity.getTabModelSelector(), activity.getTabContentManager(), activity.getCompositorViewHolder(),
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementModuleProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementModuleProvider.java index 17fcb67..718b195b 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementModuleProvider.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementModuleProvider.java
@@ -6,12 +6,16 @@ import android.support.annotation.Nullable; +import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.metrics.UmaSessionStats; import org.chromium.components.module_installer.ModuleInstaller; /** * Provider class for TabManagementModule. */ public class TabManagementModuleProvider { + public static final String SYNTHETIC_TRIAL_POSTFIX = "SyntheticTrial"; + private static final String TAB_MANAGEMENT_MODULE_IMPL_CLASS_NAME = "org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleImpl"; @@ -28,8 +32,28 @@ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException e) { ModuleInstaller.installDeferred("tab_ui"); + if (ChromeFeatureList.isInitialized()) { + UmaSessionStats.registerSyntheticFieldTrial( + ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID + SYNTHETIC_TRIAL_POSTFIX, + "DownloadAttempted"); + UmaSessionStats.registerSyntheticFieldTrial( + ChromeFeatureList.TAB_GROUPS_ANDROID + SYNTHETIC_TRIAL_POSTFIX, + "DownloadAttempted"); + } return null; } + if (ChromeFeatureList.isInitialized()) { + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID)) { + UmaSessionStats.registerSyntheticFieldTrial( + ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID + SYNTHETIC_TRIAL_POSTFIX, + "Downloaded_Control"); + } + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_GROUPS_ANDROID)) { + UmaSessionStats.registerSyntheticFieldTrial( + ChromeFeatureList.TAB_GROUPS_ANDROID + SYNTHETIC_TRIAL_POSTFIX, + "Downloaded_Control"); + } + } return tabManagementModule; } }
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 640ec33c5..bf56f45 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -182,7 +182,7 @@ the module installation will not automatically bring in DFM's manifest entries. --> <meta-data android:name="com.google.ar.core.min_apk_version" - android:value="181012000"/> + android:value="190310000"/> <activity android:name="com.google.ar.core.InstallActivity" android:configChanges="keyboardHidden|orientation|screenSize"
diff --git a/chrome/android/java/monochrome_public_apk.AndroidManifest.expected b/chrome/android/java/monochrome_public_apk.AndroidManifest.expected index f78d443..e872549 100644 --- a/chrome/android/java/monochrome_public_apk.AndroidManifest.expected +++ b/chrome/android/java/monochrome_public_apk.AndroidManifest.expected
@@ -1197,7 +1197,7 @@ android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/> <meta-data android:name="com.google.ar.core" android:value="optional"/> - <meta-data android:name="com.google.ar.core.min_apk_version" android:value="181012000"/> + <meta-data android:name="com.google.ar.core.min_apk_version" android:value="190310000"/> <meta-data android:name="com.samsung.android.sdk.multiwindow.enable" android:value="true"/> <meta-data android:name="com.samsung.android.sdk.multiwindow.penwindow.enable"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index c6c8935d..3485f71 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -209,6 +209,8 @@ public static final String CONTEXTUAL_SEARCH_SECOND_TAP = "ContextualSearchSecondTap"; public static final String CONTEXTUAL_SEARCH_TAP_DISABLE_OVERRIDE = "ContextualSearchTapDisableOverride"; + public static final String CONTEXTUAL_SEARCH_TRANSLATION_MODEL = + "ContextualSearchTranslationModel"; public static final String CONTEXTUAL_SEARCH_UNITY_INTEGRATION = "ContextualSearchUnityIntegration"; public static final String CONTEXTUAL_SUGGESTIONS_BUTTON = "ContextualSuggestionsButton"; @@ -219,6 +221,8 @@ public static final String DATA_SAVER_LITE_MODE_REBRANDING = "DataSaverLiteModeRebranding"; public static final String DELEGATE_OVERSCROLL_SWIPES = "DelegateOverscrollSwipes"; public static final String DONT_PREFETCH_LIBRARIES = "DontPrefetchLibraries"; + public static final String DOWNLOAD_LOCATION_SHOW_IMAGE_IN_GALLERY = + "DownloadLocationShowImageInGallery"; public static final String DOWNLOAD_HOME_SHOW_STORAGE_INFO = "DownloadHomeShowStorageInfo"; public static final String DOWNLOAD_PROGRESS_INFOBAR = "DownloadProgressInfoBar"; public static final String DOWNLOAD_HOME_V2 = "DownloadHomeV2"; @@ -228,6 +232,7 @@ public static final String DOWNLOAD_OFFLINE_CONTENT_PROVIDER = "UseDownloadOfflineContentProvider"; public static final String DOWNLOADS_LOCATION_CHANGE = "DownloadsLocationChange"; + public static final String DOWNLOAD_TAB_MANAGEMENT_MODULE = "DownloadTabManagementModule"; public static final String DRAW_VERTICALLY_EDGE_TO_EDGE = "DrawVerticallyEdgeToEdge"; public static final String EPHEMERAL_TAB = "EphemeralTab"; public static final String EXPERIMENTAL_APP_BANNERS = "ExperimentalAppBanners";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java index ad9e5822..45c5182 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -136,7 +136,7 @@ private ContextualSearchInternalStateController mInternalStateController; @VisibleForTesting - protected ContextualSearchTranslateController mTranslateController; + protected ContextualSearchTranslation mTranslateController; // The Overlay panel. private ContextualSearchPanel mSearchPanel; @@ -238,7 +238,8 @@ mSelectionController = new ContextualSearchSelectionController(activity, this); mNetworkCommunicator = this; mPolicy = new ContextualSearchPolicy(mSelectionController, mNetworkCommunicator); - mTranslateController = new ContextualSearchTranslateController(mPolicy, this); + mTranslateController = + ContextualSearchTranslateController.getContextualSearchTranslation(mPolicy, this); mInternalStateController = new ContextualSearchInternalStateController( mPolicy, getContextualSearchInternalStateHandler()); mInteractionRecorder = new ContextualSearchRankerLoggerImpl(); @@ -465,8 +466,7 @@ mShouldLoadDelayedSearch = false; } if (isTap && mPolicy.shouldPreviousTapResolve()) { - // Cache the native translate data, so JNI calls won't be made when time-critical. - mTranslateController.cacheNativeTranslateData(); + // For a resolving Tap we'll figure out translation need after the Resolve. } else if (!TextUtils.isEmpty(selection)) { boolean shouldPrefetch = mPolicy.shouldPrefetchSearchResult(); mSearchRequest = new ContextualSearchRequest(selection, shouldPrefetch);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateController.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateController.java index faba8f4..2f2427e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateController.java
@@ -9,6 +9,7 @@ import android.text.TextUtils; import org.chromium.base.ContextUtils; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.ui.UiUtils; import java.util.ArrayList; @@ -16,11 +17,10 @@ import java.util.List; import java.util.Locale; - /** * Controls how Translation One-box triggering is handled for the {@link ContextualSearchManager}. */ -public class ContextualSearchTranslateController { +public class ContextualSearchTranslateController implements ContextualSearchTranslation { private static final int LOCALE_MIN_LENGTH = 2; private final ContextualSearchPolicy mPolicy; @@ -30,19 +30,33 @@ private String mTranslateServiceTargetLanguage; private String mAcceptLanguages; - ContextualSearchTranslateController( + /** + * Constructs a translation implementation that determines when to trigger translations for + * Contextual Search requests. + * @param policy The {@link ContextualSearchPolicy} for determining the target language and + * whether translation is disabled. + * @param hostInterface A {@link ContextualSearchTranslateInterface} back to the host which + * provides native implementations of this interface. + */ + static public ContextualSearchTranslation getContextualSearchTranslation( + ContextualSearchPolicy policy, ContextualSearchTranslateInterface hostInterface) { + if (useChromeLanguageModel()) { + return new ContextualSearchTranslationImpl(policy); + } else { + return new ContextualSearchTranslateController(policy, hostInterface); + } + } + + /** Do not construct directly, call getContextualSearchTranslation static method. */ + protected ContextualSearchTranslateController( ContextualSearchPolicy policy, ContextualSearchTranslateInterface hostInterface) { mPolicy = policy; mHost = hostInterface; } - /** - * Force translation from the given language for the current search request, - * unless disabled by a Chrome Variation. Also log whenever conditions are right to translate. - * @param searchRequest The search request to force translation upon. - * @param sourceLanguage The language to translate from, or an empty string if not known. - */ - void forceTranslateIfNeeded(ContextualSearchRequest searchRequest, String sourceLanguage) { + @Override + public void forceTranslateIfNeeded( + ContextualSearchRequest searchRequest, String sourceLanguage) { if (mPolicy.isTranslationDisabled()) return; // Force translation if not disabled and server controlled or client logic says required. @@ -51,20 +65,12 @@ searchRequest.forceTranslation( sourceLanguage, mPolicy.bestTargetLanguage(getProficientLanguageList())); } - // Log that conditions were right for translation, even though it may be disabled - // for an experiment so we can compare with the counter factual data. - ContextualSearchUma.logTranslateOnebox(doForceTranslate); - // Log whether or not translate conditions are met ContextualSearchUma.logTranslateCondition(doForceTranslate); } - /** - * Force auto-detect translation for the current search request unless disabled by experiment. - * Also log that conditions are right to translate. - * @param searchRequest The search request to force translation upon. - */ - void forceAutoDetectTranslateUnlessDisabled(ContextualSearchRequest searchRequest) { + @Override + public void forceAutoDetectTranslateUnlessDisabled(ContextualSearchRequest searchRequest) { // Always trigger translation using auto-detect when we're not resolving, // unless disabled by policy. if (mPolicy.isTranslationDisabled()) return; @@ -75,27 +81,19 @@ searchRequest.forceAutoDetectTranslation( mPolicy.bestTargetLanguage(getProficientLanguageList())); } - // Log that conditions were right for translation, even though it may be disabled - // for an experiment so we can compare with the counter factual data. - ContextualSearchUma.logTranslateOnebox(true); } - /** - * Caches all the native translate language info, so we can avoid repeated JNI calls. - */ - void cacheNativeTranslateData() { - if (mPolicy.isTranslationDisabled()) return; - - getNativeTranslateServiceTargetLanguage(); - getNativeAcceptLanguages(); - } - - /** @return Whether the given {@code sourceLanguage} needs translation for the current user. */ - boolean needsTranslation(@Nullable String sourceLanguage) { + @Override + public boolean needsTranslation(@Nullable String sourceLanguage) { return !mPolicy.isTranslationDisabled() && !TextUtils.isEmpty(sourceLanguage) && mPolicy.needsTranslation(sourceLanguage, getReadableLanguages()); } + @Override + public String getTranslateServiceTargetLanguage() { + return getNativeTranslateServiceTargetLanguage(); + } + /** * Gets the list of readable languages for the current user, with the first * item in the list being the user's primary language (according to the Translate Service). @@ -182,6 +180,11 @@ return new Locale(trimmedLocale).getLanguage(); } + /** @return whether we should use the Chrome Language Model due to the feature being enabled. */ + static private boolean useChromeLanguageModel() { + return ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SEARCH_TRANSLATION_MODEL); + } + /** * @return The accept-languages string from the cache or from native code (when not cached). */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslation.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslation.java new file mode 100644 index 0000000..2f74c35 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslation.java
@@ -0,0 +1,41 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.contextualsearch; + +import android.support.annotation.Nullable; + +/** + * Provides an interface for forcing translation on a Contextual Search Request. + * When translation is forced, the request has additional parameters that force a one-box for the + * supplied source and destination languages. + * Methods support forcing translation on a request from a given source language, or forcing + * translation on a request using an auto-detection for whether the source and destination are + * different. + */ +public interface ContextualSearchTranslation { + /** + * Force translation from the given language for the given search request. + * Also log whenever conditions are right to translate. + * @param searchRequest The search request to force translation upon. + * @param sourceLanguage The language to translate from, or an empty string if not known. + */ + void forceTranslateIfNeeded(ContextualSearchRequest searchRequest, String sourceLanguage); + + /** + * Force auto-detect translation for the current search request. The language to translate from + * will be auto-detected, and some overtriggering is likely but not harmful (because a translate + * onebox is suppressed when the from/to languages match. + * @param searchRequest The search request to force translation upon. + */ + void forceAutoDetectTranslateUnlessDisabled(ContextualSearchRequest searchRequest); + + /** @return Whether the given {@code sourceLanguage} needs translation for the current user. */ + boolean needsTranslation(@Nullable String sourceLanguage); + + /** + * @return The best target language based on what the Translate Service knows about the user. + */ + String getTranslateServiceTargetLanguage(); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImpl.java new file mode 100644 index 0000000..24d622f --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImpl.java
@@ -0,0 +1,98 @@ +// 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.chrome.browser.contextualsearch; + +import android.support.annotation.Nullable; +import android.text.TextUtils; + +import org.chromium.chrome.browser.translate.TranslateBridge; + +import java.util.LinkedHashSet; + +/** + * Controls how Translation One-box triggering is handled for the {@link ContextualSearchManager}. + */ +public class ContextualSearchTranslationImpl implements ContextualSearchTranslation { + private final TranslateBridgeWrapper mTranslateBridgeWrapper; + private final ContextualSearchPolicy mPolicy; + /** + * Creates a {@link ContextualSearchTranslation} for updating {@link ContextualSearchRequest}s + * for translation. + */ + ContextualSearchTranslationImpl(ContextualSearchPolicy policy) { + mPolicy = policy; + mTranslateBridgeWrapper = new TranslateBridgeWrapper(); + } + + /** Constructor useful for testing, uses the given {@link TranslateBridgeWrapper}. */ + ContextualSearchTranslationImpl( + ContextualSearchPolicy policy, TranslateBridgeWrapper translateBridgeWrapper) { + mPolicy = policy; + mTranslateBridgeWrapper = translateBridgeWrapper; + } + + @Override + public void forceTranslateIfNeeded( + ContextualSearchRequest searchRequest, String sourceLanguage) { + if (needsTranslation(sourceLanguage)) { + searchRequest.forceTranslation(sourceLanguage, getTranslateServiceTargetLanguage()); + } + } + + @Override + public void forceAutoDetectTranslateUnlessDisabled(ContextualSearchRequest searchRequest) { + searchRequest.forceAutoDetectTranslation(getTranslateServiceTargetLanguage()); + } + + @Override + public boolean needsTranslation(@Nullable String sourceLanguage) { + if (TextUtils.isEmpty(sourceLanguage) || isBlockedLanguage(sourceLanguage) + || mPolicy.isTranslationDisabled()) + return false; + + LinkedHashSet<String> languages = mTranslateBridgeWrapper.getModelLanguages(); + for (String language : languages) { + if (language.equals(sourceLanguage)) return false; + } + return true; + } + + @Override + public String getTranslateServiceTargetLanguage() { + return mTranslateBridgeWrapper.getTargetLanguage(); + } + + /** @return whether the given {@code language} is blocked for translation. */ + private boolean isBlockedLanguage(String language) { + return mTranslateBridgeWrapper.isBlockedLanguage(language); + } + + /** + * Wraps our usage of the static methods in the {@link TranslateBridge} into a class that can be + * mocked for testing. + */ + static class TranslateBridgeWrapper { + /** @return whether the given string is blocked for translation. */ + public boolean isBlockedLanguage(String language) { + return TranslateBridge.isBlockedLanguage(language); + } + + /** + * @return The best target language based on what the Translate Service knows about the + * user. + */ + public String getTargetLanguage() { + return TranslateBridge.getTargetLanguage(); + } + + /** + * @return The {@link LinkedHashSet} of language code strings that the Chrome Language Model + * thinks the user knows, in order of most familiar to least familiar. + */ + public LinkedHashSet<String> getModelLanguages() { + return TranslateBridge.getModelLanguages(); + } + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java index 6ec6770..bad960bf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
@@ -1348,17 +1348,6 @@ } /** - * Logs that the conditions are right to force the translation one-box, and whether it - * was actually forced or not. - * @param didForceTranslate Whether the translation onebox was forced. - */ - public static void logTranslateOnebox(boolean didForceTranslate) { - int code = didForceTranslate ? ForceTranslate.DID_FORCE : ForceTranslate.WOULD_FORCE; - RecordHistogram.recordEnumeratedHistogram( - "Search.ContextualSearchShouldTranslate", code, ForceTranslate.NUM_ENTRIES); - } - - /** * Logs that whether or not the conditions are met to perform a translation. * @param isConditionMet Whether the translation conditions were met. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java index 848210d..ea13439 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
@@ -816,11 +816,21 @@ @VisibleForTesting void onStop(int actionSource) { + // MediaSessionCompat calls this sometimes when `mMediaNotificationInfo` + // is no longer available. It's unclear if it is a Support Library issue + // or something that isn't properly cleaned up but given that the + // crashes are rare and the fix is simple, null check was enough. + if (mMediaNotificationInfo == null) return; mMediaNotificationInfo.listener.onStop(actionSource); } @VisibleForTesting void onMediaSessionAction(int action) { + // MediaSessionCompat calls this sometimes when `mMediaNotificationInfo` + // is no longer available. It's unclear if it is a Support Library issue + // or something that isn't properly cleaned up but given that the + // crashes are rare and the fix is simple, null check was enough. + if (mMediaNotificationInfo == null) return; mMediaNotificationInfo.listener.onMediaSessionAction(action); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java index b433f07..37da76b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java
@@ -144,11 +144,6 @@ uiDelegate.getEventReporter().onMoreButtonClicked(this); switch (mCategoryInfo.getAdditionalAction()) { - case ContentSuggestionsAdditionalAction.VIEW_ALL: - // The action does not reach the backend, so we record it here. - SuggestionsMetrics.recordActionViewAll(); - mCategoryInfo.performViewAllAction(uiDelegate.getNavigationDelegate()); - return; case ContentSuggestionsAdditionalAction.FETCH: mParentSection.fetchSuggestions(onFailure, onNoNewSuggestions); return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java index 735ec94..7e24c073 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java
@@ -6,14 +6,12 @@ import android.support.annotation.Nullable; -import org.chromium.base.Log; import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.native_page.ContextMenuManager.ContextMenuItemId; import org.chromium.chrome.browser.ntp.snippets.CategoryInt; import org.chromium.chrome.browser.ntp.snippets.ContentSuggestionsCardLayout; import org.chromium.chrome.browser.ntp.snippets.KnownCategories; import org.chromium.chrome.browser.suggestions.ContentSuggestionsAdditionalAction; -import org.chromium.chrome.browser.suggestions.SuggestionsNavigationDelegate; /** * Contains meta information about a Category. Equivalent of the CategoryInfo class in @@ -112,36 +110,10 @@ public Boolean isContextMenuItemSupported(@ContextMenuItemId int menuItemId) { if (menuItemId == ContextMenuManager.ContextMenuItemId.REMOVE) return null; - if (mCategory == KnownCategories.DOWNLOADS) { - if (menuItemId == ContextMenuManager.ContextMenuItemId.OPEN_IN_INCOGNITO_TAB - || menuItemId == ContextMenuManager.ContextMenuItemId.SAVE_FOR_OFFLINE) { - return false; - } - } return true; } /** - * Performs the View All action for the provided category, navigating navigating to the view - * showing all the content. - */ - public void performViewAllAction(SuggestionsNavigationDelegate navigationDelegate) { - switch (mCategory) { - case KnownCategories.DOWNLOADS: - navigationDelegate.navigateToDownloadManager(); - break; - case KnownCategories.BOOKMARKS_DEPRECATED: - case KnownCategories.FOREIGN_TABS_DEPRECATED: - case KnownCategories.PHYSICAL_WEB_PAGES_DEPRECATED: - case KnownCategories.RECENT_TABS_DEPRECATED: - case KnownCategories.ARTICLES: - default: - Log.wtf(TAG, "'Empty State' action called for unsupported category: %d", mCategory); - break; - } - } - - /** * Whether the Category supports fetching more content. Only Articles supports this at this * time. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java index 8071496..7fc4b95 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java
@@ -13,7 +13,6 @@ import org.chromium.chrome.browser.suggestions.OfflinableSuggestion; import org.chromium.ui.modelutil.PropertyObservable; -import java.io.File; import java.util.Collection; import java.util.Collections; @@ -81,18 +80,6 @@ /** The thumbnail dominant color. */ private @ColorInt Integer mThumbnailDominantColor; - /** Whether the linked article represents an asset download. */ - private boolean mIsAssetDownload; - - /** The GUID of the asset download (only for asset download articles). */ - private String mAssetDownloadGuid; - - /** The path to the asset download (only for asset download articles). */ - private File mAssetDownloadFile; - - /** The mime type of the asset download (only for asset download articles). */ - private String mAssetDownloadMimeType; - /** The tab id of the corresponding tab (only for recent tab articles). */ private int mRecentTabId; @@ -202,71 +189,9 @@ return mCategory == KnownCategories.CONTEXTUAL; } - /** @return whether a snippet is either offline page or asset download. */ - public boolean isDownload() { - return mCategory == KnownCategories.DOWNLOADS; - } - - /** @return whether a snippet is asset download. */ - public boolean isAssetDownload() { - return mIsAssetDownload; - } - - /** - * @return the GUID of the asset download. May only be called if {@link #mIsAssetDownload} is - * {@code true} (which implies that this snippet belongs to the DOWNLOADS category). - */ - public String getAssetDownloadGuid() { - assert isDownload(); - assert mIsAssetDownload; - return mAssetDownloadGuid; - } - - /** - * @return the asset download path. May only be called if {@link #mIsAssetDownload} is - * {@code true} (which implies that this snippet belongs to the DOWNLOADS category). - */ - public File getAssetDownloadFile() { - assert isDownload(); - assert mIsAssetDownload; - return mAssetDownloadFile; - } - - /** - * @return the mime type of the asset download. May only be called if {@link #mIsAssetDownload} - * is {@code true} (which implies that this snippet belongs to the DOWNLOADS category). - */ - public String getAssetDownloadMimeType() { - assert isDownload(); - assert mIsAssetDownload; - return mAssetDownloadMimeType; - } - - /** - * Marks the article suggestion as an asset download with the given path and mime type. May only - * be called if this snippet belongs to DOWNLOADS category. - */ - public void setAssetDownloadData(String downloadGuid, String filePath, String mimeType) { - assert isDownload(); - mIsAssetDownload = true; - mAssetDownloadGuid = downloadGuid; - mAssetDownloadFile = new File(filePath); - mAssetDownloadMimeType = mimeType; - } - - /** - * Marks the article suggestion as an offline page download with the given id. May only - * be called if this snippet belongs to DOWNLOADS category. - */ - public void setOfflinePageDownloadData(long offlinePageId) { - assert isDownload(); - mIsAssetDownload = false; - setOfflinePageOfflineId(offlinePageId); - } - @Override public boolean requiresExactOfflinePage() { - return isDownload(); + return false; } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java index 8ce1dc3..c9bbb3a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
@@ -195,7 +195,7 @@ /** Updates the visibility of the card's offline badge by checking the bound article's info. */ private void refreshOfflineBadgeVisibility() { - boolean visible = mArticle.getOfflinePageOfflineId() != null || mArticle.isAssetDownload(); + boolean visible = mArticle.getOfflinePageOfflineId() != null; mSuggestionsBinder.updateOfflineBadgeVisibility(visible); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java index 97d3923..0f79667 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java
@@ -207,18 +207,6 @@ } @CalledByNative - private static void setAssetDownloadDataForSuggestion( - SnippetArticle suggestion, String downloadGuid, String filePath, String mimeType) { - suggestion.setAssetDownloadData(downloadGuid, filePath, mimeType); - } - - @CalledByNative - private static void setOfflinePageDownloadDataForSuggestion( - SnippetArticle suggestion, long offlinePageId) { - suggestion.setOfflinePageDownloadData(offlinePageId); - } - - @CalledByNative private static SuggestionsCategoryInfo createSuggestionsCategoryInfo(int category, String title, @ContentSuggestionsCardLayout int cardLayout, @ContentSuggestionsAdditionalAction int additionalAction, boolean showIfEmpty,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java index 768a5b51..a97b835 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java
@@ -6,12 +6,9 @@ import android.graphics.Bitmap; import android.os.SystemClock; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import org.chromium.base.Callback; import org.chromium.base.DiscardableReferencePool; -import org.chromium.base.Promise; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.favicon.LargeIconBridge; import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; @@ -29,7 +26,6 @@ * To fetch an image, the caller should create a request which is done in the following way: * - for favicons: {@link #makeFaviconRequest(SnippetArticle, int, Callback)} * - for article thumbnails: {@link #makeArticleThumbnailRequest(SnippetArticle, Callback)} - * - for article downloads: {@link #makeDownloadThumbnailRequest(SnippetArticle, int)} * - for large icons: {@link #makeLargeIconRequest(String, int, * LargeIconBridge.LargeIconCallback)} * @@ -59,22 +55,6 @@ } /** - * Creates a request for a thumbnail from a downloaded image. - * - * If there is an error while fetching the thumbnail, the callback will not be called. - * - * @param suggestion The suggestion for which we need a thumbnail. - * @param thumbnailSizePx The required size for the thumbnail. - * @return The request which will be used to fetch the thumbnail. - */ - public DownloadThumbnailRequest makeDownloadThumbnailRequest( - SnippetArticle suggestion, int thumbnailSizePx) { - assert !mIsDestroyed; - - return new DownloadThumbnailRequest(suggestion, thumbnailSizePx); - } - - /** * Creates a request for an article thumbnail. * * If there is an error while fetching the thumbnail, the callback will not be called. @@ -179,65 +159,4 @@ } return mLargeIconBridge; } - - /** - * Request for a download thumbnail. - * - * The request uses a {@link Promise<Bitmap>}, which will be fulfilled once the thumbnail is - * received. - * - * Cancellation of the request is available through {@link #cancel(), which will remove the - * request from the ThumbnailProvider queue}. - */ - public class DownloadThumbnailRequest implements ThumbnailProvider.ThumbnailRequest { - private final Promise<Bitmap> mThumbnailReceivedPromise; - private final SnippetArticle mSuggestion; - private final int mSize; - - /** - * @param suggestion The suggestion whose thumbnail will be fetched. - * @param size The required size for the thumbnail. - */ - DownloadThumbnailRequest(SnippetArticle suggestion, int size) { - mThumbnailReceivedPromise = new Promise<>(); - mSuggestion = suggestion; - mSize = size; - - getThumbnailProvider().getThumbnail(this); - } - - @Override - public @Nullable String getFilePath() { - return mSuggestion.getAssetDownloadFile().getAbsolutePath(); - } - - @Override - public @Nullable String getContentId() { - return mSuggestion.getAssetDownloadGuid(); - } - - @Override - public void onThumbnailRetrieved(@NonNull String contentId, @Nullable Bitmap thumbnail) { - mThumbnailReceivedPromise.fulfill(thumbnail); - } - - @Override - public int getIconSize() { - return mSize; - } - - public void cancel() { - if (mIsDestroyed) return; - getThumbnailProvider().cancelRetrieval(this); - } - - public Promise<Bitmap> getPromise() { - return mThumbnailReceivedPromise; - } - - @Override - public String getMimeType() { - return null; - } - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java index 22d3d0f..731d2c6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java
@@ -26,7 +26,6 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; -import org.chromium.base.Promise; import org.chromium.base.SysUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler; @@ -71,9 +70,6 @@ boolean mHasVideoBadge; boolean mHasOfflineBadge; - @Nullable - private ImageFetcher.DownloadThumbnailRequest mThumbnailRequest; - private SnippetArticle mSuggestion; /** @@ -209,9 +205,6 @@ } private void setThumbnail() { - // If there's still a pending thumbnail fetch, cancel it. - cancelThumbnailFetch(); - // mThumbnailView's visibility is modified in updateFieldsVisibility(). if (mThumbnailView.getVisibility() != View.VISIBLE) return; @@ -221,11 +214,6 @@ return; } - if (mSuggestion.isDownload()) { - setDownloadThumbnail(); - return; - } - // Temporarily set placeholder and then fetch the thumbnail from a provider. mThumbnailView.setBackground(null); if (mIsContextual) { @@ -246,42 +234,6 @@ mSuggestion, new FetchThumbnailCallback(mSuggestion, mThumbnailSize)); } - private void setDownloadThumbnail() { - assert mSuggestion.isDownload(); - if (!mSuggestion.isAssetDownload()) { - setThumbnailFromFileType(DownloadFilter.Type.PAGE); - return; - } - - @DownloadFilter.Type - int fileType = DownloadFilter.fromMimeType(mSuggestion.getAssetDownloadMimeType()); - if (fileType == DownloadFilter.Type.IMAGE) { - // For image downloads, attempt to fetch a thumbnail. - ImageFetcher.DownloadThumbnailRequest thumbnailRequest = - mImageFetcher.makeDownloadThumbnailRequest(mSuggestion, mThumbnailSize); - - Promise<Bitmap> thumbnailReceivedPromise = thumbnailRequest.getPromise(); - - if (thumbnailReceivedPromise.isFulfilled()) { - // If the thumbnail was cached, then it will be retrieved synchronously, the promise - // will be fulfilled and we can set the thumbnail immediately. - verifyBitmap(thumbnailReceivedPromise.getResult()); - setThumbnail(ThumbnailGradient.createDrawableWithGradientIfNeeded( - thumbnailReceivedPromise.getResult(), mCardContainerView.getResources())); - - return; - } - - mThumbnailRequest = thumbnailRequest; - - // Queue a callback to be called after the thumbnail is retrieved asynchronously. - thumbnailReceivedPromise.then(new FetchThumbnailCallback(mSuggestion, mThumbnailSize)); - } - - // Set a placeholder for the file type. - setThumbnailFromFileType(fileType); - } - private void setThumbnail(Drawable thumbnail) { assert thumbnail != null; @@ -318,13 +270,6 @@ mPublisherTextView.setVisibility(View.VISIBLE); } - private void cancelThumbnailFetch() { - if (mThumbnailRequest != null) { - mThumbnailRequest.cancel(); - mThumbnailRequest = null; - } - } - private void fadeThumbnailIn(Drawable thumbnail) { assert mThumbnailView.getDrawable() != null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsEventReporterBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsEventReporterBridge.java index 07f974c..c73cff5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsEventReporterBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsEventReporterBridge.java
@@ -4,10 +4,8 @@ package org.chromium.chrome.browser.suggestions; -import org.chromium.chrome.browser.ntp.NewTabPageUma; import org.chromium.chrome.browser.ntp.cards.ActionItem; import org.chromium.chrome.browser.ntp.snippets.CategoryInt; -import org.chromium.chrome.browser.ntp.snippets.KnownCategories; import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; /** @@ -57,14 +55,6 @@ @CategoryInt int category = actionItem.getCategory(); nativeOnMoreButtonClicked(category, actionItem.getPerSectionRank()); - switch (category) { - case KnownCategories.DOWNLOADS: - NewTabPageUma.recordAction(NewTabPageUma.ACTION_OPENED_DOWNLOADS_MANAGER); - break; - default: - // No action associated - break; - } } public static void onSuggestionTargetVisited(int category, long visitTimeMs) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java index a045366..b2b4f87 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java
@@ -67,10 +67,6 @@ // Effect/Purpose of the interactions. Most are recorded in |content_suggestions_metrics.h| - public static void recordActionViewAll() { - RecordUserAction.record("Suggestions.Category.ViewAll"); - } - /** * Records metrics for the visit to the provided content suggestion, such as the time spent on * the website, or if the user comes back to the starting point.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegate.java index 5df40a0..619843d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegate.java
@@ -4,12 +4,8 @@ package org.chromium.chrome.browser.suggestions; -import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeFeatureList; -import org.chromium.chrome.browser.bookmarks.BookmarkUtils; -import org.chromium.chrome.browser.download.DownloadMetrics; -import org.chromium.chrome.browser.download.DownloadUtils; import org.chromium.chrome.browser.native_page.NativePageHost; import org.chromium.chrome.browser.native_page.NativePageNavigationDelegateImpl; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; @@ -38,18 +34,6 @@ super(activity, profile, host, tabModelSelector); } - /** Opens the bookmarks page in the current tab. */ - public void navigateToBookmarks() { - RecordUserAction.record("MobileNTPSwitchToBookmarks"); - BookmarkUtils.showBookmarkManager(mActivity); - } - - /** Opens the Download Manager UI in the current tab. */ - public void navigateToDownloadManager() { - RecordUserAction.record("MobileNTPSwitchToDownloadManager"); - DownloadUtils.showDownloadManager(mActivity, mHost.getActiveTab()); - } - @Override public void navigateToHelpPage() { NewTabPageUma.recordAction(NewTabPageUma.ACTION_CLICKED_LEARN_MORE); @@ -80,23 +64,11 @@ NewTabPageUma.recordAction(NewTabPageUma.ACTION_OPENED_SNIPPET); } - if (article.isAssetDownload()) { - assert windowOpenDisposition == WindowOpenDisposition.CURRENT_TAB - || windowOpenDisposition == WindowOpenDisposition.NEW_WINDOW - || windowOpenDisposition == WindowOpenDisposition.NEW_BACKGROUND_TAB; - DownloadUtils.openFile(article.getAssetDownloadFile().getPath(), - article.getAssetDownloadMimeType(), article.getAssetDownloadGuid(), false, null, - null, DownloadMetrics.DownloadOpenSource.NEW_TAP_PAGE); - return; - } - - // We explicitly open an offline page only for offline page downloads or for prefetched - // offline pages when Data Reduction Proxy is enabled. For all other - // sections the URL is opened and it is up to Offline Pages whether to open its offline - // page (e.g. when offline). - if ((article.isDownload() && !article.isAssetDownload()) - || (DataReductionProxySettings.getInstance().isDataReductionProxyEnabled() - && article.isPrefetched())) { + // We explicitly open an offline page only for prefetched offline pages when Data Reduction + // Proxy is enabled. For all other sections the URL is opened and it is up to Offline Pages + // whether to open its offline page (e.g. when offline). + if (DataReductionProxySettings.getInstance().isDataReductionProxyEnabled() + && article.isPrefetched()) { assert article.getOfflinePageOfflineId() != null; assert windowOpenDisposition == WindowOpenDisposition.CURRENT_TAB || windowOpenDisposition == WindowOpenDisposition.NEW_WINDOW
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java index b3df252..1a11013 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java
@@ -4,9 +4,12 @@ package org.chromium.chrome.browser.translate; +import org.chromium.base.annotations.CalledByNative; import org.chromium.chrome.browser.tab.Tab; import org.chromium.content_public.browser.WebContents; +import java.util.LinkedHashSet; + /** * Bridge class that lets Android code access native code to execute translate on a tab. */ @@ -42,9 +45,42 @@ nativeSetPredefinedTargetLanguage(tab.getWebContents(), targetLanguage); } + /** + * @return The best target language based on what the Translate Service knows about the user. + */ + public static String getTargetLanguage() { + return nativeGetTargetLanguage(); + } + + /** @return whether the given string is blocked for translation. */ + public static boolean isBlockedLanguage(String language) { + return nativeIsBlockedLanguage(language); + } + + /** + * @return The ordered set of all languages that the user's knows, ordered by how well they know + * them with the most familiar listed first. + */ + public static LinkedHashSet<String> getModelLanguages() { + LinkedHashSet<String> set = new LinkedHashSet<String>(); + // Calls back through addModelLanguageToSet repeatedly. + nativeGetModelLanguages(set); + return set; + } + + /** Called by {@link #nativeGetModelLanguages} with the set to add to and the language to add.*/ + @CalledByNative + private static void addModelLanguageToSet( + LinkedHashSet<String> languages, String languageCode) { + languages.add(languageCode); + } + private static native void nativeManualTranslateWhenReady(WebContents webContents); private static native boolean nativeCanManuallyTranslate(WebContents webContents); private static native boolean nativeShouldShowManualTranslateIPH(WebContents webContents); private static native void nativeSetPredefinedTargetLanguage( WebContents webContents, String targetLanguage); + private static native String nativeGetTargetLanguage(); + private static native boolean nativeIsBlockedLanguage(String language); + private static native void nativeGetModelLanguages(LinkedHashSet<String> set); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java index 4696142..b895a2cb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
@@ -560,6 +560,11 @@ ChromePreferenceManager.getInstance().writeBoolean( ChromePreferenceManager.GRID_TAB_SWITCHER_ENABLED_KEY, !DeviceClassManager.enableAccessibilityLayout() + && (ChromeFeatureList.isEnabled( + ChromeFeatureList.DOWNLOAD_TAB_MANAGEMENT_MODULE) + || ChromeFeatureList.isEnabled( + ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID)) + && TabManagementModuleProvider.getTabManagementModule() != null && ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID)); } @@ -575,14 +580,18 @@ } // TODO(yusufo): AccessibilityLayout check should not be here and the flow should support // changing that setting while Chrome is alive. - return sIsGridTabSwitcherEnabled - && TabManagementModuleProvider.getTabManagementModule() != null; + return sIsGridTabSwitcherEnabled; } private static void cacheTabGroupsAndroidEnabled() { ChromePreferenceManager.getInstance().writeBoolean( ChromePreferenceManager.TAB_GROUPS_ANDROID_ENABLED_KEY, !DeviceClassManager.enableAccessibilityLayout() + && (ChromeFeatureList.isEnabled( + ChromeFeatureList.DOWNLOAD_TAB_MANAGEMENT_MODULE) + || ChromeFeatureList.isEnabled( + ChromeFeatureList.TAB_GROUPS_ANDROID)) + && TabManagementModuleProvider.getTabManagementModule() != null && ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_GROUPS_ANDROID)); } @@ -599,8 +608,7 @@ ChromePreferenceManager.TAB_GROUPS_ANDROID_ENABLED_KEY, false); } - return sIsTabGroupsAndroidEnabled - && TabManagementModuleProvider.getTabManagementModule() != null; + return sIsTabGroupsAndroidEnabled; } private static boolean isHighEndPhone() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java index 48276b6a..31f86ae 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -1503,14 +1503,16 @@ /** * Checks whether the sheet can be moved. It cannot be moved when the activity is in overview - * mode, when "find in page" is visible, or when the toolbar is hidden. + * mode, when "find in page" is visible, when the toolbar is in the animation to hide, or when + * the toolbar is hidden. */ protected boolean canMoveSheet() { if (mFindInPageView == null) mFindInPageView = findViewById(R.id.find_toolbar); boolean isFindInPageVisible = mFindInPageView != null && mFindInPageView.getVisibility() == View.VISIBLE; - return !isToolbarAndroidViewHidden() && !isFindInPageVisible; + return !isToolbarAndroidViewHidden() && !isFindInPageVisible + && mTargetState != SheetState.HIDDEN; } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java index 833100e..bb2549c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java
@@ -239,46 +239,6 @@ @Test @MediumTest @Feature({"ArticleSnippets", "RenderTest"}) - public void testDownloadSuggestion() throws IOException { - String downloadFilePath = - UrlUtils.getIsolatedTestFilePath("chrome/test/data/android/capybara.jpg"); - TestThreadUtils.runOnUiThreadBlocking(() -> { - SnippetArticle downloadSuggestion = new SnippetArticle(KnownCategories.DOWNLOADS, "id1", - "test_image.jpg", "example.com", "http://example.com", - mTimestamp, // Publish timestamp - 10f, // Score - mTimestamp, // Fetch timestamp - false, // Is video suggestion - null); // Thumbnail dominant color - downloadSuggestion.setAssetDownloadData("asdf", downloadFilePath, "image/jpeg"); - SuggestionsCategoryInfo downloadsCategory = new SuggestionsCategoryInfo( - KnownCategories.DOWNLOADS, "Downloads", ContentSuggestionsCardLayout.FULL_CARD, - ContentSuggestionsAdditionalAction.NONE, - /* show_if_empty = */ true, "No suggestions"); - - mSuggestion.onBindViewHolder(downloadSuggestion, downloadsCategory); - mContentView.addView(mSuggestion.itemView); - }); - - mRenderTestRule.render(mSuggestion.itemView, "download_snippet_placeholder"); - - InstrumentationRegistry.getInstrumentation().waitForIdleSync(); - List<ThumbnailRequest> requests = mThumbnailProvider.getRequests(); - Assert.assertEquals(1, requests.size()); - ThumbnailRequest request = requests.get(0); - Assert.assertEquals(downloadFilePath, request.getFilePath()); - - Bitmap thumbnail = BitmapFactory.decodeFile(downloadFilePath); - - TestThreadUtils.runOnUiThreadBlocking( - () -> { mThumbnailProvider.fulfillRequest(request, thumbnail); }); - - mRenderTestRule.render(mSuggestion.itemView, "download_snippet_thumbnail"); - } - - @Test - @MediumTest - @Feature({"ArticleSnippets", "RenderTest"}) public void testVideoSuggestion() throws IOException { SuggestionsCategoryInfo categoryInfo = new SuggestionsCategoryInfo(FULL_CATEGORY, "Section Title", ContentSuggestionsCardLayout.FULL_CARD,
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImplTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImplTest.java new file mode 100644 index 0000000..be264d3 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImplTest.java
@@ -0,0 +1,135 @@ +// 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.chrome.browser.contextualsearch; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import static org.chromium.chrome.browser.contextualsearch.ContextualSearchTranslationImpl.TranslateBridgeWrapper; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import org.chromium.base.test.util.Feature; + +import java.util.LinkedHashSet; + +/** + * Tests the {@link ContextualSearchTranslationImpl} class. + */ +@RunWith(BlockJUnit4ClassRunner.class) +public class ContextualSearchTranslationImplTest { + private static final String ENGLISH = "en"; + private static final String SPANISH = "es"; + private static final String GERMAN = "de"; + private static final LinkedHashSet<String> ENGLISH_AND_SPANISH; + static { + LinkedHashSet<String> langs = new LinkedHashSet<String>(); + langs.add(ENGLISH); + langs.add(SPANISH); + ENGLISH_AND_SPANISH = langs; + } + private static final LinkedHashSet<String> ENGLISH_SET; + static { + LinkedHashSet<String> langs = new LinkedHashSet<String>(); + langs.add(ENGLISH); + ENGLISH_SET = langs; + } + + @Mock + private TranslateBridgeWrapper mTranslateBridgeWrapperMock; + @Mock + private ContextualSearchRequest mRequest; + @Mock + private ContextualSearchPolicy mPolicy; + + private ContextualSearchTranslationImpl mImpl; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mImpl = new ContextualSearchTranslationImpl(mPolicy, mTranslateBridgeWrapperMock); + doReturn(false).when(mPolicy).isTranslationDisabled(); + } + + @Test + @Feature("TranslateUtilities") + public void testNeedsTranslationEmptyModelLanguages() { + doReturn(new LinkedHashSet<String>()).when(mTranslateBridgeWrapperMock).getModelLanguages(); + assertThat(mImpl.needsTranslation(ENGLISH), is(true)); + } + + @Test + @Feature("TranslateUtilities") + public void testNeedsTranslationUserModelLanguages() { + doReturn(ENGLISH_SET).when(mTranslateBridgeWrapperMock).getModelLanguages(); + assertThat(mImpl.needsTranslation(ENGLISH), is(false)); + } + + @Test + @Feature("TranslateUtilities") + public void testNeedsTranslationMultipleModelLanguages() { + doReturn(ENGLISH_AND_SPANISH).when(mTranslateBridgeWrapperMock).getModelLanguages(); + assertThat(mImpl.needsTranslation(ENGLISH), is(false)); + } + + @Test + @Feature("TranslateUtilities") + public void testNeedsTranslationOtherModelLanguage() { + doReturn(ENGLISH_AND_SPANISH).when(mTranslateBridgeWrapperMock).getModelLanguages(); + assertThat(mImpl.needsTranslation(GERMAN), is(true)); + } + + @Test + @Feature("TranslateUtilities") + public void testNeedsTranslationOtherBlocked() { + doReturn(ENGLISH_AND_SPANISH).when(mTranslateBridgeWrapperMock).getModelLanguages(); + doReturn(true).when(mTranslateBridgeWrapperMock).isBlockedLanguage(GERMAN); + assertThat(mImpl.needsTranslation(GERMAN), is(false)); + } + + @Test + @Feature("TranslateUtilities") + public void testTargetLanguage() { + doReturn(GERMAN).when(mTranslateBridgeWrapperMock).getTargetLanguage(); + assertThat(mImpl.getTranslateServiceTargetLanguage(), is(GERMAN)); + } + + @Test + @Feature("TranslateUtilities") + public void testForceTranslateIfNeededWhenNeeded() { + doReturn(ENGLISH_AND_SPANISH).when(mTranslateBridgeWrapperMock).getModelLanguages(); + doNothing().when(mRequest).forceTranslation(any(), any()); + when(mRequest.isTranslationForced()).thenReturn(true); + + mImpl.forceTranslateIfNeeded(mRequest, GERMAN); + + assertThat(mRequest.isTranslationForced(), is(true)); + verify(mTranslateBridgeWrapperMock).getModelLanguages(); + verify(mRequest).forceTranslation(GERMAN, null); + } + + @Test + @Feature("TranslateUtilities") + public void testForceTranslateIfNeededWhenNotNeeded() { + doReturn(ENGLISH_AND_SPANISH).when(mTranslateBridgeWrapperMock).getModelLanguages(); + + mImpl.forceTranslateIfNeeded(mRequest, ENGLISH); + + assertThat(mRequest.isTranslationForced(), is(false)); + verify(mTranslateBridgeWrapperMock).getModelLanguages(); + verify(mRequest, never()).forceTranslation(any(), any()); + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfoTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfoTest.java index 401302c..eab4c17 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfoTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfoTest.java
@@ -24,27 +24,6 @@ @Config(manifest = Config.NONE) public class SuggestionsCategoryInfoTest { @Test - public void testDownloadContextMenu() { - SuggestionsCategoryInfo categoryInfo = - new CategoryInfoBuilder(KnownCategories.DOWNLOADS).build(); - assertThat(categoryInfo.isContextMenuItemSupported( - ContextMenuManager.ContextMenuItemId.OPEN_IN_NEW_WINDOW), - is(true)); - assertThat(categoryInfo.isContextMenuItemSupported( - ContextMenuManager.ContextMenuItemId.OPEN_IN_NEW_TAB), - is(true)); - assertThat(categoryInfo.isContextMenuItemSupported( - ContextMenuManager.ContextMenuItemId.OPEN_IN_INCOGNITO_TAB), - is(false)); - assertThat(categoryInfo.isContextMenuItemSupported( - ContextMenuManager.ContextMenuItemId.SAVE_FOR_OFFLINE), - is(false)); - assertThat(categoryInfo.isContextMenuItemSupported( - ContextMenuManager.ContextMenuItemId.REMOVE), - nullValue()); - } - - @Test public void testArticleContextMenu() { SuggestionsCategoryInfo categoryInfo = new CategoryInfoBuilder(KnownCategories.ARTICLES).build();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java index 3527959..5e1d2b2 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
@@ -527,23 +527,6 @@ @Test @Feature({"Ntp"}) - public void testViewAllAction() { - // When all the actions are enabled, ViewAll always has the priority and is shown. - - // Spy so that VerifyAction can check methods being called. - SuggestionsCategoryInfo info = - spy(new CategoryInfoBuilder(TEST_CATEGORY_ID) - .withAction(ContentSuggestionsAdditionalAction.VIEW_ALL) - .showIfEmpty() - .build()); - SuggestionsSection section = createSection(info); - - assertTrue(section.getActionItemForTesting().isVisible()); - verifyAction(section, ContentSuggestionsAdditionalAction.VIEW_ALL); - } - - @Test - @Feature({"Ntp"}) public void testFetchAction() { // When only FetchMore is shown when enabled. @@ -1092,10 +1075,6 @@ section.getActionItemForTesting().performAction(mUiDelegate, null, null); } - verify(section.getCategoryInfo(), - (action == ContentSuggestionsAdditionalAction.VIEW_ALL ? times(1) : never())) - .performViewAllAction(mUiDelegate.getNavigationDelegate()); - // noinspection unchecked -- See https://crbug.com/740162 for rationale. verify(mUiDelegate.getSuggestionsSource(), (action == ContentSuggestionsAdditionalAction.FETCH ? times(1) : never()))
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/SuggestionsImageFetcherTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/SuggestionsImageFetcherTest.java index 3bb195b..2fe1d09 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/SuggestionsImageFetcherTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/SuggestionsImageFetcherTest.java
@@ -31,7 +31,6 @@ import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.suggestions.ImageFetcher.DownloadThumbnailRequest; import org.chromium.chrome.browser.widget.ThumbnailProvider; import org.chromium.chrome.test.support.DisableHistogramsRule; import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule; @@ -92,8 +91,7 @@ } @KnownCategories - int[] categoriesThatDontFetch = - new int[] {KnownCategories.DOWNLOADS, KnownCategories.READING_LIST}; + int[] categoriesThatDontFetch = new int[] {KnownCategories.READING_LIST}; for (@KnownCategories int category : categoriesThatDontFetch) { SnippetArticle suggestion = createDummySuggestion(category); imageFetcher.makeFaviconRequest(suggestion, mockCallback); @@ -104,21 +102,6 @@ } } - @Test - public void testDownloadThumbnailFetch() { - ImageFetcher imageFetcher = - new ImageFetcher(mSuggestionsSource, mock(Profile.class), mReferencePool); - - SnippetArticle suggestion = createDummySuggestion(KnownCategories.DOWNLOADS); - - DownloadThumbnailRequest request = - imageFetcher.makeDownloadThumbnailRequest(suggestion, IMAGE_SIZE_PX); - verify(mThumbnailProvider).getThumbnail(eq(request)); - - request.cancel(); - verify(mThumbnailProvider).cancelRetrieval(eq(request)); - } - @SuppressWarnings("unchecked") @Test public void testArticleThumbnailFetch() {
diff --git a/chrome/android/touchless/java/res/drawable/ic_apps_black_24dp.xml b/chrome/android/touchless/java/res/drawable/ic_apps_black_24dp.xml index 51d4fbf..5c228efc 100644 --- a/chrome/android/touchless/java/res/drawable/ic_apps_black_24dp.xml +++ b/chrome/android/touchless/java/res/drawable/ic_apps_black_24dp.xml
@@ -1,6 +1,3 @@ -<!-- 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. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:targetApi="21" @@ -9,6 +6,6 @@ android:viewportWidth="24.0" android:viewportHeight="24.0"> <path - android:fillColor="@color/default_icon_color_blue" + android:fillColor="#4267B2" android:pathData="M4,8h4L8,4L4,4v4zM10,20h4v-4h-4v4zM4,20h4v-4L4,16v4zM4,14h4v-4L4,10v4zM10,14h4v-4h-4v4zM16,4v4h4L20,4h-4zM10,8h4L14,4h-4v4zM16,14h4v-4h-4v4zM16,20h4v-4h-4v4z"/> </vector>
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsAdapter.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsAdapter.java index f4029cf..f0ebc57 100644 --- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsAdapter.java +++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsAdapter.java
@@ -98,9 +98,8 @@ private TextView mTitleView; /** - * @param model The main property model coming from {@link SiteSuggestionsCoordinator}. Contains - * properties for a list of suggestions, number of items, and current focused index. - * @param iconGenerator An icon generator for creating icons. + * @param model the main property model coming from {@link SiteSuggestionsCoordinator}. + * @param iconGenerator an icon generator for creating icons. * @param navigationDelegate delegate for navigation controls * @param contextMenuManager handles context menu creation * @param layoutManager the layout manager controlling this recyclerview and adapter @@ -130,7 +129,8 @@ @Override public int getItemViewType(int position) { - if (isAllAppsPosition(position)) return ViewType.ALL_APPS_TYPE; + int itemCount = mModel.get(ITEM_COUNT_KEY); + if (itemCount == 1 || position % itemCount == 0) return ViewType.ALL_APPS_TYPE; return ViewType.SUGGESTION_TYPE; } @@ -155,9 +155,9 @@ WindowOpenDisposition.CURRENT_TAB, UrlConstants.EXPLORE_URL)); } else if (holder.getItemViewType() == ViewType.SUGGESTION_TYPE) { // If site suggestion, attach context menu handler; clicks navigate to site url. + int itemCount = mModel.get(ITEM_COUNT_KEY); // Subtract 1 from position % MAX_TILES to account for "all apps" taking up one space. - PropertyModel item = - mModel.get(SUGGESTIONS_KEY).get(getModelPositionFromAdapterPosition(position)); + PropertyModel item = mModel.get(SUGGESTIONS_KEY).get((position % itemCount) - 1); // Only update the icon for icon updates. if (payload == SiteSuggestionModel.ICON_KEY) { tile.updateIcon(item.get(SiteSuggestionModel.ICON_KEY), @@ -185,12 +185,13 @@ if (propertyKey == CURRENT_INDEX_KEY) { // When the current index changes, we want to scroll to position and update the title. int position = mModel.get(CURRENT_INDEX_KEY); + int itemCount = mModel.get(ITEM_COUNT_KEY); mLayoutManager.scrollToPosition(position); - if (isAllAppsPosition(position)) { + if (itemCount == 1 || position % itemCount == 0) { mTitleView.setText(R.string.ntp_all_apps); } else { mTitleView.setText(mModel.get(SUGGESTIONS_KEY) - .get(getModelPositionFromAdapterPosition(position)) + .get(position % itemCount - 1) .get(SiteSuggestionModel.TITLE_KEY)); } } @@ -213,7 +214,7 @@ public void notifyItemRangeRemoved(int index, int count) { if (mModel.get(SUGGESTIONS_KEY).size() == 0) { // When we removed the last item in the model, we would go from infinite scroll - // back to non-scrolling. Notify RecyclerView to remove everything. + // back to non-scrolling. Notify Recyclerview to remove everything. super.notifyItemRangeRemoved(1, Integer.MAX_VALUE - 1); } else { // Otherwise we are already infinite-scrolling, so just tell recyclerview that @@ -224,21 +225,33 @@ @Override public void notifyItemRangeChanged(int index, int count, @Nullable PropertyKey payload) { - // When something has changed, assume everything has changed. - super.notifyItemRangeChanged(0, Integer.MAX_VALUE, payload); - } - - public void destroy() { - mModel.removeObserver(this); - mModel.get(SUGGESTIONS_KEY).removeObserver(this); - } - - private int getModelPositionFromAdapterPosition(int adapterPosition) { - return adapterPosition % mModel.get(ITEM_COUNT_KEY) - 1; - } - - private boolean isAllAppsPosition(int adapterPosition) { - return mModel.get(ITEM_COUNT_KEY) == 1 - || getModelPositionFromAdapterPosition(adapterPosition) < 0; + if (count > 1) { + // If more than 1 item was changed, then assume everything was changed. This should + // only happen if we are infinite-scrolling. + super.notifyItemRangeChanged(0, Integer.MAX_VALUE, payload); + } else if (mModel.get(SUGGESTIONS_KEY).size() == 0) { + // If itemCount is 1, then notify super. + // This should only happen if "All apps" icon has changed in some way and we aren't + // infinite-scrolling. + super.notifyItemRangeChanged(index, count, payload); + } else { + // Otherwise, count = 1 and we have an infinite list. We will only notify that items + // near the currently visible area has changed. + // beginIndex at the layoutManager's firstVisibleItemPosition, with buffer. + int beginIndex = + mLayoutManager.findFirstVisibleItemPosition() - mModel.get(ITEM_COUNT_KEY); + // endIndex at the lastVisibleItemPosition, with buffer. + int endIndex = + mLayoutManager.findLastVisibleItemPosition() + mModel.get(ITEM_COUNT_KEY); + // Find elements between begin and end such that (i % itemCount) - 1 == index. + // Subtract 1 because itemRangeChanged is called from the listObserver which does not + // have "All apps". However, i is calculated from layoutManager, which includes "All + // apps" + for (int i = beginIndex; i < endIndex; i++) { + if (i % mModel.get(ITEM_COUNT_KEY) - 1 == index) { + super.notifyItemRangeChanged(i, 1, payload); + } + } + } } }
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsCoordinator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsCoordinator.java index ece6b74b..5b6044e 100644 --- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsCoordinator.java +++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsCoordinator.java
@@ -35,7 +35,6 @@ new PropertyModel.WritableIntPropertyKey(); private SiteSuggestionsMediator mMediator; - private SiteSuggestionsAdapter mAdapterDelegate; SiteSuggestionsCoordinator(View parentView, Profile profile, SuggestionsNavigationDelegate navigationDelegate, ContextMenuManager contextMenuManager, @@ -57,13 +56,13 @@ LinearLayoutManager layoutManager = new SiteSuggestionsLayoutManager(context); RecyclerView recyclerView = suggestionsView.findViewById(R.id.most_likely_launcher_recycler); - mAdapterDelegate = new SiteSuggestionsAdapter(model, iconGenerator, navigationDelegate, - contextMenuManager, layoutManager, + SiteSuggestionsAdapter adapterDelegate = new SiteSuggestionsAdapter(model, iconGenerator, + navigationDelegate, contextMenuManager, layoutManager, suggestionsView.findViewById(R.id.most_likely_web_title_text)); RecyclerViewAdapter<SiteSuggestionsViewHolderFactory.SiteSuggestionsViewHolder, PropertyKey> adapter = new RecyclerViewAdapter<>( - mAdapterDelegate, new SiteSuggestionsViewHolderFactory()); + adapterDelegate, new SiteSuggestionsViewHolderFactory()); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(adapter); @@ -73,6 +72,5 @@ public void destroy() { mMediator.destroy(); - mAdapterDelegate.destroy(); } }
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java index 0b4d6a5b..9371076 100644 --- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java +++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java
@@ -71,7 +71,6 @@ protected Bitmap doInBackground() { return BitmapFactory.decodeFile(suggestion.whitelistIconPath); } - @Override protected void onPostExecute(Bitmap icon) { if (icon == null) makeIconRequest(siteSuggestion); @@ -83,7 +82,7 @@ // Total item count is 1 more than number of site suggestions to account for "all apps". mModel.set(SiteSuggestionsCoordinator.ITEM_COUNT_KEY, getItemCount() + 1); - // If we fetched site suggestions for the first time, set initial scrolled position. + // If we fetched site suggestions the first time, set initial scrolled position. // We don't want to set scrolled position if we've already set position before. if (siteSuggestions.size() > 0 && mModel.get(SiteSuggestionsCoordinator.CURRENT_INDEX_KEY) == 0) {
diff --git a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/NoTouchActivityTest.java b/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/NoTouchActivityTest.java index c2762491..7fab62a 100644 --- a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/NoTouchActivityTest.java +++ b/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/NoTouchActivityTest.java
@@ -80,7 +80,7 @@ mActivityTestRule.startMainActivityFromIntent(i, null); mActivity = mActivityTestRule.getActivity(); Assert.assertFalse(mActivity.getActivityTab().isNativePage()); - ThreadUtils.runOnUiThreadBlocking(() -> { + TestThreadUtils.runOnUiThreadBlocking(() -> { Assert.assertEquals("chrome://dino/", mActivity.getActivityTab().getWebContents().getLastCommittedUrl()); }); @@ -101,7 +101,7 @@ mActivityTestRule.startMainActivityFromIntent(i, null); mActivity = mActivityTestRule.getActivity(); Assert.assertFalse(mActivity.getActivityTab().isNativePage()); - ThreadUtils.runOnUiThreadBlocking(() -> { + TestThreadUtils.runOnUiThreadBlocking(() -> { Assert.assertEquals("chrome://dino/", mActivity.getActivityTab().getWebContents().getLastCommittedUrl()); });
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 772fb81f..e7cd1c8 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -2723,6 +2723,15 @@ <message name="IDS_NETWORK_UI_DEVICES" desc="Label for list of network devices, e.g. wifi or cellular"> Devices: </message> + <message name="IDS_NETWORK_UI_NO_CELLULAR_ACTIVATION_LABEL" desc="Label for section dealing with activating a cellular network SIM card."> + Cellular Activation + </message> + <message name="IDS_NETWORK_UI_OPEN_CELLULAR_ACTIVATION_BUTTON_TEXT" desc="Text for button which, when pressed, opens the cellular activation UI."> + Open Cellular Activation UI + </message> + <message name="IDS_NETWORK_UI_NO_CELLULAR_ERROR_TEXT" desc="Text displayed when the cellular activation UI cannot be opened because no cellular network exists."> + No cellular network exists + </message> <message name="IDS_DEVICE_LOG_LINK_TEXT" desc="Message preceeding link to chrome://device-log"> For network logs, see: <ph name="DEVICE_LOG_LINK"><a href="chrome://device-log">chrome://device-log</a></ph>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index d260a8b..69793ca 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1179,6 +1179,11 @@ chrome::android::kContextualSearchSimplifiedServer, kSimplifiedServerVariations, "ContextualSearchSimplifiedServer")}, + {"contextual-search-translation-model", + flag_descriptions::kContextualSearchTranslationModelName, + flag_descriptions::kContextualSearchTranslationModelDescription, + kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kContextualSearchTranslationModel)}, {"contextual-search-unity-integration", flag_descriptions::kContextualSearchUnityIntegrationName, flag_descriptions::kContextualSearchUnityIntegrationDescription, @@ -1597,18 +1602,6 @@ ENABLE_DISABLE_VALUE_TYPE(switches::kEnableZeroCopy, switches::kDisableZeroCopy)}, #if defined(OS_MACOSX) - {"bookmark-apps", flag_descriptions::kNewBookmarkAppsName, - flag_descriptions::kNewBookmarkAppsDescription, kOsMac, - FEATURE_VALUE_TYPE(features::kBookmarkApps)}, - {"disable-hosted-apps-in-windows", - flag_descriptions::kHostedAppsInWindowsName, - flag_descriptions::kHostedAppsInWindowsDescription, kOsMac, - ENABLE_DISABLE_VALUE_TYPE(switches::kEnableHostedAppsInWindows, - switches::kDisableHostedAppsInWindows)}, - {"create-app-windows-in-app", - flag_descriptions::kCreateAppWindowsInAppShimProcessName, - flag_descriptions::kCreateAppWindowsInAppShimProcessDescription, kOsMac, - FEATURE_VALUE_TYPE(features::kHostWindowsInAppShimProcess)}, {"disable-hosted-app-shim-creation", flag_descriptions::kHostedAppShimCreationName, flag_descriptions::kHostedAppShimCreationDescription, kOsMac,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index 6635f67..67701a2 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -122,14 +122,17 @@ &kContextualSearchSecondTap, &kContextualSearchSimplifiedServer, &kContextualSearchTapDisableOverride, + &kContextualSearchTranslationModel, &kContextualSearchUnityIntegration, &kCustomContextMenu, &kDelegateOverscrollSwipes, &kDontPrefetchLibraries, + &kDownloadLocationShowImageInGallery, &kDownloadProgressInfoBar, &kDownloadHomeV2, &kDownloadHomeShowStorageInfo, &kDownloadRename, + &kDownloadTabManagementModule, &kDrawVerticallyEdgeToEdge, &kEphemeralTab, &kExploreSites, @@ -340,6 +343,9 @@ const base::Feature kContextualSearchTapDisableOverride{ "ContextualSearchTapDisableOverride", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kContextualSearchTranslationModel{ + "ContextualSearchTranslationModel", base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kContextualSearchUnityIntegration{ "ContextualSearchUnityIntegration", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -358,6 +364,9 @@ const base::Feature kDownloadAutoResumptionThrottling{ "DownloadAutoResumptionThrottling", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kDownloadLocationShowImageInGallery{ + "DownloadLocationShowImageInGallery", base::FEATURE_ENABLED_BY_DEFAULT}; + const base::Feature kDownloadProgressInfoBar{"DownloadProgressInfoBar", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -370,6 +379,9 @@ const base::Feature kDownloadRename{"DownloadRename", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kDownloadTabManagementModule{ + "DownloadTabManagementModule", base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kEphemeralTab{"EphemeralTab", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h index 87ebb545..ec2067f1 100644 --- a/chrome/browser/android/chrome_feature_list.h +++ b/chrome/browser/android/chrome_feature_list.h
@@ -51,15 +51,18 @@ extern const base::Feature kContextualSearchSecondTap; extern const base::Feature kContextualSearchSimplifiedServer; extern const base::Feature kContextualSearchTapDisableOverride; +extern const base::Feature kContextualSearchTranslationModel; extern const base::Feature kContextualSearchUnityIntegration; extern const base::Feature kCustomContextMenu; extern const base::Feature kDelegateOverscrollSwipes; extern const base::Feature kDontPrefetchLibraries; extern const base::Feature kDownloadAutoResumptionThrottling; +extern const base::Feature kDownloadLocationShowImageInGallery; extern const base::Feature kDownloadProgressInfoBar; extern const base::Feature kDownloadHomeV2; extern const base::Feature kDownloadHomeShowStorageInfo; extern const base::Feature kDownloadRename; +extern const base::Feature kDownloadTabManagementModule; extern const base::Feature kDrawVerticallyEdgeToEdge; extern const base::Feature kEphemeralTab; extern const base::Feature kExploreSites;
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc index b9c9f22..46be73d 100644 --- a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc +++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
@@ -44,6 +44,7 @@ #include "url/gurl.h" using content::RenderFrameHost; +using language::LanguageModel; using unified_consent::UrlKeyedDataCollectionConsentHelper; namespace { @@ -422,10 +423,11 @@ // Gets the target language from the translate service using the user's profile. std::string ContextualSearchDelegate::GetTargetLanguage() { Profile* profile = ProfileManager::GetActiveUserProfile(); - PrefService* pref_service = profile->GetPrefs(); - language::LanguageModel* language_model = + LanguageModel* language_model = LanguageModelManagerFactory::GetForBrowserContext(profile) ->GetPrimaryModel(); + DCHECK(language_model); + PrefService* pref_service = profile->GetPrefs(); std::string result = TranslateService::GetTargetLanguage(pref_service, language_model); DCHECK(!result.empty());
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate.h b/chrome/browser/android/contextualsearch/contextual_search_delegate.h index 13d64af..386da81 100644 --- a/chrome/browser/android/contextualsearch/contextual_search_delegate.h +++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.h
@@ -68,6 +68,8 @@ content::WebContents* web_contents); // Gets the target language for translation purposes for this user. + // TODO(donnd): remove these language accessors once the transition to the + // Chrome Language Model is complete. std::string GetTargetLanguage(); // Returns the accept languages preference string.
diff --git a/chrome/browser/android/ntp/ntp_snippets_bridge.cc b/chrome/browser/android/ntp/ntp_snippets_bridge.cc index b6700d47..158a903 100644 --- a/chrome/browser/android/ntp/ntp_snippets_bridge.cc +++ b/chrome/browser/android/ntp/ntp_snippets_bridge.cc
@@ -77,24 +77,6 @@ suggestion.fetch_date().ToJavaTime(), suggestion.is_video_suggestion(), suggestion.optional_image_dominant_color().value_or(0)); - if (suggestion.id().category().IsKnownCategory( - KnownCategories::DOWNLOADS) && - suggestion.download_suggestion_extra() != nullptr) { - if (suggestion.download_suggestion_extra()->is_download_asset) { - Java_SnippetsBridge_setAssetDownloadDataForSuggestion( - env, java_suggestion, - ConvertUTF8ToJavaString( - env, suggestion.download_suggestion_extra()->download_guid), - ConvertUTF8ToJavaString(env, suggestion.download_suggestion_extra() - ->target_file_path.value()), - ConvertUTF8ToJavaString( - env, suggestion.download_suggestion_extra()->mime_type)); - } else { - Java_SnippetsBridge_setOfflinePageDownloadDataForSuggestion( - env, java_suggestion, - suggestion.download_suggestion_extra()->offline_page_id); - } - } } return result;
diff --git a/chrome/browser/android/vr/BUILD.gn b/chrome/browser/android/vr/BUILD.gn index b033f0e1..d748cc4 100644 --- a/chrome/browser/android/vr/BUILD.gn +++ b/chrome/browser/android/vr/BUILD.gn
@@ -87,11 +87,6 @@ "arcore_device/arcore_shim.cc", "arcore_device/arcore_shim.h", ] - - # TODO(https://crbug.com/936004): Remove this once arcore_c_api.h is - # -Wextra-semi clean. - configs -= [ "//build/config/compiler:chromium_code" ] - configs += [ "//build/config/compiler:no_chromium_code" ] } deps = [
diff --git a/chrome/browser/android/vr/arcore_device/arcore_impl.cc b/chrome/browser/android/vr/arcore_device/arcore_impl.cc index bb6c9f5..cb7585c 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_impl.cc +++ b/chrome/browser/android/vr/arcore_device/arcore_impl.cc
@@ -108,8 +108,11 @@ size_t num_elements = uvs.size(); DCHECK(num_elements % 2 == 0); std::vector<float> uvs_out(num_elements); - ArFrame_transformDisplayUvCoords(arcore_session_.get(), arcore_frame_.get(), - num_elements, &uvs[0], &uvs_out[0]); + + ArFrame_transformCoordinates2d( + arcore_session_.get(), arcore_frame_.get(), + AR_COORDINATES_2D_VIEW_NORMALIZED, num_elements / 2, &uvs[0], + AR_COORDINATES_2D_TEXTURE_NORMALIZED, &uvs_out[0]); return uvs_out; }
diff --git a/chrome/browser/android/vr/arcore_device/arcore_shim.cc b/chrome/browser/android/vr/arcore_device/arcore_shim.cc index 5ee88a84..eaf2fc5 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_shim.cc +++ b/chrome/browser/android/vr/arcore_device/arcore_shim.cc
@@ -12,40 +12,40 @@ namespace { // Run CALL macro for every function defined in the API. -#define FOR_EACH_API_FN \ - CALL(ArCamera_getDisplayOrientedPose) \ - CALL(ArCamera_getProjectionMatrix) \ - CALL(ArCamera_getTrackingState) \ - CALL(ArCamera_getViewMatrix) \ - CALL(ArConfig_create) \ - CALL(ArConfig_destroy) \ - CALL(ArFrame_acquireCamera) \ - CALL(ArFrame_create) \ - CALL(ArFrame_destroy) \ - CALL(ArFrame_hitTestRay) \ - CALL(ArFrame_transformDisplayUvCoords) \ - CALL(ArHitResult_create) \ - CALL(ArHitResult_destroy) \ - CALL(ArHitResult_getHitPose) \ - CALL(ArHitResultList_create) \ - CALL(ArHitResultList_destroy) \ - CALL(ArHitResultList_getItem) \ - CALL(ArHitResultList_getSize) \ - CALL(ArPose_create) \ - CALL(ArPose_destroy) \ - CALL(ArPose_getMatrix) \ - CALL(ArPose_getPoseRaw) \ - CALL(ArSession_configure) \ - CALL(ArSession_create) \ - CALL(ArSession_destroy) \ - CALL(ArSession_pause) \ - CALL(ArSession_resume) \ - CALL(ArSession_setCameraTextureName) \ - CALL(ArSession_setDisplayGeometry) \ - CALL(ArHitResult_acquireTrackable) \ - CALL(ArTrackable_getType) \ - CALL(ArTrackable_release) \ - CALL(ArPlane_isPoseInPolygon) \ +#define FOR_EACH_API_FN \ + CALL(ArCamera_getDisplayOrientedPose) \ + CALL(ArCamera_getProjectionMatrix) \ + CALL(ArCamera_getTrackingState) \ + CALL(ArCamera_getViewMatrix) \ + CALL(ArConfig_create) \ + CALL(ArConfig_destroy) \ + CALL(ArFrame_acquireCamera) \ + CALL(ArFrame_create) \ + CALL(ArFrame_destroy) \ + CALL(ArFrame_hitTestRay) \ + CALL(ArFrame_transformCoordinates2d) \ + CALL(ArHitResult_create) \ + CALL(ArHitResult_destroy) \ + CALL(ArHitResult_getHitPose) \ + CALL(ArHitResultList_create) \ + CALL(ArHitResultList_destroy) \ + CALL(ArHitResultList_getItem) \ + CALL(ArHitResultList_getSize) \ + CALL(ArPose_create) \ + CALL(ArPose_destroy) \ + CALL(ArPose_getMatrix) \ + CALL(ArPose_getPoseRaw) \ + CALL(ArSession_configure) \ + CALL(ArSession_create) \ + CALL(ArSession_destroy) \ + CALL(ArSession_pause) \ + CALL(ArSession_resume) \ + CALL(ArSession_setCameraTextureName) \ + CALL(ArSession_setDisplayGeometry) \ + CALL(ArHitResult_acquireTrackable) \ + CALL(ArTrackable_getType) \ + CALL(ArTrackable_release) \ + CALL(ArPlane_isPoseInPolygon) \ CALL(ArSession_update) #define CALL(fn) decltype(&fn) impl_##fn = nullptr; @@ -160,13 +160,16 @@ ray_direction_3, out_hit_results); } -void ArFrame_transformDisplayUvCoords(const ArSession* session, - const ArFrame* frame, - int32_t num_elements, - const float* uvs_in, - float* uvs_out) { - arcore_api->impl_ArFrame_transformDisplayUvCoords( - session, frame, num_elements, uvs_in, uvs_out); +void ArFrame_transformCoordinates2d(const ArSession* session, + const ArFrame* frame, + ArCoordinates2dType input_coordinates, + int32_t number_of_vertices, + const float* vertices_2d, + ArCoordinates2dType output_coordinates, + float* out_vertices_2d) { + arcore_api->impl_ArFrame_transformCoordinates2d( + session, frame, input_coordinates, number_of_vertices, vertices_2d, + output_coordinates, out_vertices_2d); } void ArHitResult_create(const ArSession* session,
diff --git a/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm b/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm index 83d13d1..1b8d8a3 100644 --- a/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm +++ b/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm
@@ -21,7 +21,6 @@ #include "base/run_loop.h" #include "base/strings/sys_string_conversions.h" #include "base/task/post_task.h" -#include "base/test/scoped_feature_list.h" #include "base/test/test_timeouts.h" #include "base/threading/thread_restrictions.h" #include "build/build_config.h" @@ -58,12 +57,6 @@ AppShimInteractiveTest() : auto_reset_(&g_app_shims_allow_update_and_launch_in_tests, true) {} - // testing::Test: - void SetUp() override { - scoped_feature_list_.InitAndEnableFeature(features::kBookmarkApps); - PlatformAppBrowserTest::SetUp(); - } - // Install a test app of |type| and reliably wait for its app shim to be // created on disk. Sets |shim_path_|. const extensions::Extension* InstallAppWithShim(AppType type, @@ -75,7 +68,6 @@ private: // Temporarily enable app shims. base::AutoReset<bool> auto_reset_; - base::test::ScopedFeatureList scoped_feature_list_; DISALLOW_COPY_AND_ASSIGN(AppShimInteractiveTest); };
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index d7ef52a..57996bb 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -2234,7 +2234,7 @@ // then launches the app window again. The process is repeated 3 times. // TODO(crbug.com/949923): The test is flaky (crash) on ChromeOS debug and ASan/LSan #if defined(OS_CHROMEOS) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER)) -#define MAYBE_CloseOnLoadcommit DEFINE_CloseOnLoadcommit +#define MAYBE_CloseOnLoadcommit DISABLED_CloseOnLoadcommit #else #define MAYBE_CloseOnLoadcommit CloseOnLoadcommit #endif
diff --git a/chrome/browser/apps/platform_apps/platform_app_launch.cc b/chrome/browser/apps/platform_apps/platform_app_launch.cc index 2fc86ba..34ac465 100644 --- a/chrome/browser/apps/platform_apps/platform_app_launch.cc +++ b/chrome/browser/apps/platform_apps/platform_app_launch.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/apps/platform_apps/platform_app_launch.h" -#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/launch_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/extensions/app_launch_params.h" @@ -44,12 +43,6 @@ extensions::LaunchContainer launch_container = extensions::GetLaunchContainer( extensions::ExtensionPrefs::Get(profile), app); - if (!extensions::util::IsNewBookmarkAppsEnabled() && - !extensions::HasPreferredLaunchContainer( - extensions::ExtensionPrefs::Get(profile), app)) { - launch_container = extensions::LAUNCH_CONTAINER_WINDOW; - } - *out_app = app; *out_launch_container = launch_container; return true;
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index bd231c5..62f138f 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -2383,6 +2383,7 @@ "input_method/input_method_engine_unittest.cc", "input_method/input_method_manager_impl_unittest.cc", "input_method/input_method_persistence_unittest.cc", + "kiosk_next_home/app_controller_service_unittest.cc", "locale_change_guard_unittest.cc", "lock_screen_apps/app_manager_impl_unittest.cc", "lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc",
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc b/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc index dcb02bc..223f31d 100644 --- a/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc
@@ -281,7 +281,8 @@ "Second paragraph*")); } -IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, FocusRingMovesWithMouse) { +// Flaky test. https://crbug.com/950049 +IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, DISABLED_FocusRingMovesWithMouse) { // Create a callback for the focus ring observer. base::RepeatingCallback<void()> callback = base::BindRepeating(&SelectToSpeakTest::OnFocusRingChanged, GetWeakPtr());
diff --git a/chrome/browser/chromeos/arc/process/arc_process.cc b/chrome/browser/chromeos/arc/process/arc_process.cc index 3b917c5..ab151f45 100644 --- a/chrome/browser/chromeos/arc/process/arc_process.cc +++ b/chrome/browser/chromeos/arc/process/arc_process.cc
@@ -40,7 +40,7 @@ ProcessState::FOREGROUND_SERVICE, ProcessState::BOUND_FOREGROUND_SERVICE, ProcessState::IMPORTANT_FOREGROUND, - ProcessState::IMPORTANT_FOREGROUND}); + ProcessState::IMPORTANT_BACKGROUND}); return *kProtectedBackgroundStates; } @@ -89,6 +89,8 @@ ArcProcess::ArcProcess(ArcProcess&& other) = default; ArcProcess& ArcProcess::operator=(ArcProcess&& other) = default; +// TODO(wvk): Use a simple switch/case instead of std::unordered_set lookup, +// it will likely be faster. bool ArcProcess::IsImportant() const { return ImportantStates().count(process_state()) == 1 || IsArcProtected(); }
diff --git a/chrome/browser/chromeos/display/output_protection_controller_ash.cc b/chrome/browser/chromeos/display/output_protection_controller_ash.cc index 13648a2..f55153ab 100644 --- a/chrome/browser/chromeos/display/output_protection_controller_ash.cc +++ b/chrome/browser/chromeos/display/output_protection_controller_ash.cc
@@ -7,29 +7,29 @@ #include "ash/shell.h" // mash-ok +namespace { + +display::DisplayConfigurator* configurator() { + return ash::Shell::Get()->display_configurator(); +} + +} // namespace + namespace chromeos { OutputProtectionControllerAsh::OutputProtectionControllerAsh() - : client_id_(ash::Shell::Get() - ->display_configurator() - ->RegisterContentProtectionClient()) {} + : client_id_(configurator()->RegisterContentProtectionClient()) {} OutputProtectionControllerAsh::~OutputProtectionControllerAsh() { DCHECK(thread_checker_.CalledOnValidThread()); - if (client_id_ != display::DisplayConfigurator::INVALID_CLIENT_ID) { - display::DisplayConfigurator* configurator = - ash::Shell::Get()->display_configurator(); - configurator->UnregisterContentProtectionClient(client_id_); - } + configurator()->UnregisterContentProtectionClient(client_id_); } void OutputProtectionControllerAsh::QueryStatus( int64_t display_id, const OutputProtectionDelegate::QueryStatusCallback& callback) { DCHECK(thread_checker_.CalledOnValidThread()); - display::DisplayConfigurator* configurator = - ash::Shell::Get()->display_configurator(); - configurator->QueryContentProtectionStatus(client_id_, display_id, callback); + configurator()->QueryContentProtection(client_id_, display_id, callback); } void OutputProtectionControllerAsh::SetProtection( @@ -37,10 +37,8 @@ uint32_t desired_method_mask, const OutputProtectionDelegate::SetProtectionCallback& callback) { DCHECK(thread_checker_.CalledOnValidThread()); - display::DisplayConfigurator* configurator = - ash::Shell::Get()->display_configurator(); - configurator->SetContentProtection(client_id_, display_id, - desired_method_mask, callback); + configurator()->ApplyContentProtection(client_id_, display_id, + desired_method_mask, callback); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/display/output_protection_controller_ash.h b/chrome/browser/chromeos/display/output_protection_controller_ash.h index d69c0e1..1ad6e5fc 100644 --- a/chrome/browser/chromeos/display/output_protection_controller_ash.h +++ b/chrome/browser/chromeos/display/output_protection_controller_ash.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "base/threading/thread_checker.h" #include "chrome/browser/chromeos/display/output_protection_delegate.h" +#include "ui/display/manager/display_configurator.h" namespace chromeos { @@ -28,7 +29,7 @@ const OutputProtectionDelegate::SetProtectionCallback& callback) override; private: - const uint64_t client_id_; + const display::DisplayConfigurator::ContentProtectionClientId client_id_; base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(OutputProtectionControllerAsh);
diff --git a/chrome/browser/chromeos/kiosk_next_home/app_controller_service.cc b/chrome/browser/chromeos/kiosk_next_home/app_controller_service.cc index c8540af..617a994 100644 --- a/chrome/browser/chromeos/kiosk_next_home/app_controller_service.cc +++ b/chrome/browser/chromeos/kiosk_next_home/app_controller_service.cc
@@ -98,10 +98,11 @@ mojom::AppController::GetArcAndroidIdCallback callback) { arc::GetAndroidId(base::BindOnce( [](mojom::AppController::GetArcAndroidIdCallback callback, bool success, - int64_t android_id) { - // We need the string version of the Android ID since the int64_t - // is too big for Javascript. - std::move(callback).Run(success, base::NumberToString(android_id)); + int64_t raw_android_id) { + // The bridge expects the Android id as a hex string. + std::string android_id = base::NumberToString(raw_android_id); + std::move(callback).Run( + success, base::HexEncode(android_id.data(), android_id.size())); }, std::move(callback))); }
diff --git a/chrome/browser/chromeos/kiosk_next_home/app_controller_service_unittest.cc b/chrome/browser/chromeos/kiosk_next_home/app_controller_service_unittest.cc new file mode 100644 index 0000000..8a0d5c9 --- /dev/null +++ b/chrome/browser/chromeos/kiosk_next_home/app_controller_service_unittest.cc
@@ -0,0 +1,330 @@ +// 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/chromeos/kiosk_next_home/app_controller_service.h" + +#include <map> +#include <memory> +#include <utility> +#include <vector> + +#include "base/test/bind_test_util.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" +#include "chrome/browser/ui/app_list/arc/arc_app_test.h" +#include "chrome/common/extensions/extension_constants.h" +#include "chrome/services/app_service/public/cpp/app_registry_cache.h" +#include "chrome/services/app_service/public/cpp/app_update.h" +#include "chrome/test/base/testing_profile.h" +#include "components/arc/test/fake_app_instance.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace kiosk_next_home { +namespace { + +// Fake activity that we use when seeding data to ARC. +constexpr char kFakeActivity[] = "test.kiosk_next_home.activity"; + +using apps::mojom::AppType; +using apps::mojom::OptionalBool; +using apps::mojom::Readiness; + +typedef std::map<std::string, mojom::AppPtr> AppMap; + +} // namespace + +class AppControllerServiceTest : public testing::Test { + protected: + void SetUp() override { + profile_ = std::make_unique<TestingProfile>(); + + arc_test_.SetUp(profile()); + proxy_ = apps::AppServiceProxy::Get(profile()); + + app_controller_service_ = AppControllerService::Get(profile()); + } + + void TearDown() override { arc_test_.TearDown(); } + + Profile* profile() { return profile_.get(); } + + std::string GetAppIdFromAndroidPackage(const std::string& package) { + return ArcAppListPrefs::GetAppId(package, kFakeActivity); + } + + void AddAndroidPackageToArc(const std::string& package) { + arc::mojom::AppInfo app_info; + app_info.package_name = package; + + // We are only interested in the package name that we already set above, + // but we need to send a full struct so ARC doesn't drop it. + app_info.name = "test_app_name"; + app_info.activity = kFakeActivity; + app_info.sticky = false; + app_info.notifications_enabled = false; + arc_test_.app_instance()->SendAppAdded(app_info); + } + + void AddAppDeltaToAppService(apps::mojom::AppPtr delta) { + std::vector<apps::mojom::AppPtr> deltas; + deltas.push_back(std::move(delta)); + proxy_->AppRegistryCache().OnApps(std::move(deltas)); + } + + // Gets all apps from the AppControllerService instance being tested and + // returns them in a map keyed by their |app_id|. + AppMap GetAppsFromController() { + AppMap apps; + app_controller_service_->GetApps(base::BindLambdaForTesting( + [&apps](std::vector<mojom::AppPtr> app_list) { + for (const auto& app : app_list) { + apps[app->app_id] = app.Clone(); + } + })); + return apps; + } + + // Expects the given apps to be returned by a call to + // AppControllerService::GetApps(). This function doesn't take into account + // the order of the returned apps. + void ExpectApps(const std::vector<mojom::App>& expected_apps) { + AppMap returned_apps_map = GetAppsFromController(); + + EXPECT_EQ(expected_apps.size(), returned_apps_map.size()) + << "AppServiceController::GetApps() returned wrong number of apps."; + + for (const auto& expected_app : expected_apps) { + auto returned_app_it = returned_apps_map.find(expected_app.app_id); + ASSERT_NE(returned_app_it, returned_apps_map.end()) + << "App with app_id " << expected_app.app_id + << " was not returned by the AppControllerService::GetApps() " + "call."; + + mojom::AppPtr& returned_app = returned_app_it->second; + + // Test equality of every single field to make tests failures more + // readable. + EXPECT_EQ(returned_app->app_id, expected_app.app_id); + EXPECT_EQ(returned_app->type, expected_app.type); + EXPECT_EQ(returned_app->display_name, expected_app.display_name); + EXPECT_EQ(returned_app->readiness, expected_app.readiness); + EXPECT_EQ(returned_app->android_package_name, + expected_app.android_package_name); + + // Catch all clause of equality. This will only be necessary if we add + // more fields that are not expected above. + EXPECT_TRUE(expected_app.Equals(*returned_app)); + } + } + + private: + content::TestBrowserThreadBundle test_browser_thread_bundle_; + std::unique_ptr<TestingProfile> profile_; + ArcAppTest arc_test_; + apps::AppServiceProxy* proxy_; + AppControllerService* app_controller_service_; +}; + +TEST_F(AppControllerServiceTest, AppIsFetchedCorrectly) { + std::string app_id = "fake_app_id"; + std::string display_name = "Fake app name"; + AppType app_type = AppType::kExtension; + Readiness readiness = Readiness::kReady; + + // Seeding data. + apps::mojom::App delta; + delta.app_id = app_id; + delta.name = display_name; + delta.app_type = app_type; + delta.readiness = readiness; + delta.show_in_launcher = OptionalBool::kTrue; + AddAppDeltaToAppService(delta.Clone()); + + mojom::App expected_app; + expected_app.android_package_name = ""; + expected_app.app_id = app_id; + expected_app.display_name = display_name; + expected_app.type = app_type; + expected_app.readiness = readiness; + + ExpectApps({expected_app}); +} + +TEST_F(AppControllerServiceTest, AndroidAppIsFetchedCorrectly) { + std::string android_package_name = "fake.app.package"; + std::string app_id = GetAppIdFromAndroidPackage(android_package_name); + std::string display_name = "Fake app name"; + AppType app_type = AppType::kArc; + Readiness readiness = Readiness::kReady; + + // Seeding data. + AddAndroidPackageToArc(android_package_name); + apps::mojom::App delta; + delta.app_id = app_id; + delta.name = display_name; + delta.app_type = app_type; + delta.readiness = readiness; + delta.show_in_launcher = OptionalBool::kTrue; + AddAppDeltaToAppService(delta.Clone()); + + mojom::App expected_app; + expected_app.android_package_name = android_package_name; + expected_app.app_id = app_id; + expected_app.display_name = display_name; + expected_app.type = app_type; + expected_app.readiness = readiness; + + ExpectApps({expected_app}); +} + +TEST_F(AppControllerServiceTest, AndroidAppWithMissingPackageFetchedCorrectly) { + std::string android_package_name = "fake.app.package"; + std::string app_id = GetAppIdFromAndroidPackage(android_package_name); + std::string display_name = "Fake app name"; + AppType app_type = AppType::kArc; + Readiness readiness = Readiness::kReady; + + // Seeding data. This time we intentionally don't seed the package to ARC. + apps::mojom::App delta; + delta.app_id = app_id; + delta.name = display_name; + delta.app_type = app_type; + delta.readiness = readiness; + delta.show_in_launcher = OptionalBool::kTrue; + AddAppDeltaToAppService(delta.Clone()); + + mojom::App expected_app; + // Since we don't seed information to ARC, we don't expect to receive a + // package here. In this case, expect an empty string (and not a crash :) + expected_app.android_package_name = ""; + expected_app.app_id = app_id; + expected_app.display_name = display_name; + expected_app.type = app_type; + expected_app.readiness = readiness; + + ExpectApps({expected_app}); +} + +TEST_F(AppControllerServiceTest, AppReadinessIsUpdated) { + std::string app_id = "fake_app_id"; + AppType app_type = AppType::kExtension; + Readiness readiness = Readiness::kUnknown; + + apps::mojom::App delta; + delta.app_id = app_id; + delta.app_type = app_type; + delta.readiness = readiness; + delta.show_in_launcher = OptionalBool::kTrue; + AddAppDeltaToAppService(delta.Clone()); + + mojom::App expected_app; + expected_app.app_id = app_id; + expected_app.type = app_type; + expected_app.readiness = readiness; + ExpectApps({expected_app}); + + // Now we change the readiness. + delta.readiness = Readiness::kReady; + AddAppDeltaToAppService(delta.Clone()); + + expected_app.readiness = Readiness::kReady; + ExpectApps({expected_app}); +} + +TEST_F(AppControllerServiceTest, AppDisplayNameIsUpdated) { + std::string app_id = "fake_app_id"; + AppType app_type = AppType::kExtension; + std::string display_name = "Initial App Name"; + + apps::mojom::App delta; + delta.app_id = app_id; + delta.app_type = app_type; + delta.name = display_name; + delta.show_in_launcher = OptionalBool::kTrue; + AddAppDeltaToAppService(delta.Clone()); + + mojom::App expected_app; + expected_app.app_id = app_id; + expected_app.type = app_type; + expected_app.display_name = display_name; + ExpectApps({expected_app}); + + // Now we change the name. + std::string new_display_name = "New App Name"; + delta.name = new_display_name; + AddAppDeltaToAppService(delta.Clone()); + + expected_app.display_name = new_display_name; + ExpectApps({expected_app}); +} + +TEST_F(AppControllerServiceTest, MultipleAppsAreFetchedCorrectly) { + // Seed the first app. + apps::mojom::App first_delta; + first_delta.app_id = "first_app"; + first_delta.app_type = AppType::kBuiltIn; + first_delta.show_in_launcher = OptionalBool::kTrue; + AddAppDeltaToAppService(first_delta.Clone()); + + mojom::App first_expected_app; + first_expected_app.app_id = "first_app"; + first_expected_app.type = AppType::kBuiltIn; + // Expect only the first app. + ExpectApps({first_expected_app}); + + // Seed second app. + apps::mojom::App second_delta; + second_delta.app_id = "second_app"; + second_delta.app_type = AppType::kBuiltIn; + second_delta.show_in_launcher = OptionalBool::kTrue; + AddAppDeltaToAppService(second_delta.Clone()); + + mojom::App second_expected_app; + second_expected_app.app_id = "second_app"; + second_expected_app.type = AppType::kBuiltIn; + // Expect both apps. + ExpectApps({first_expected_app, second_expected_app}); +} + +TEST_F(AppControllerServiceTest, AppsThatAreNotRelevantAreFiltered) { + // Seed an app that's allowed to be returned by the AppControllerService. + apps::mojom::App allowed_app_delta; + allowed_app_delta.app_id = "allowed_app"; + allowed_app_delta.app_type = AppType::kBuiltIn; + allowed_app_delta.show_in_launcher = OptionalBool::kTrue; + AddAppDeltaToAppService(allowed_app_delta.Clone()); + + apps::mojom::App first_blocked_app_delta; + first_blocked_app_delta.app_id = "first_blocked_app"; + first_blocked_app_delta.app_type = AppType::kBuiltIn; + first_blocked_app_delta.show_in_launcher = OptionalBool::kUnknown; + AddAppDeltaToAppService(first_blocked_app_delta.Clone()); + + apps::mojom::App second_blocked_app_delta; + second_blocked_app_delta.app_id = "second_blocked_app"; + second_blocked_app_delta.app_type = AppType::kBuiltIn; + second_blocked_app_delta.show_in_launcher = OptionalBool::kFalse; + AddAppDeltaToAppService(second_blocked_app_delta.Clone()); + + apps::mojom::App kiosk_next_app_delta; + kiosk_next_app_delta.app_id = extension_misc::kKioskNextHomeAppId; + kiosk_next_app_delta.app_type = AppType::kBuiltIn; + // Even though the Kiosk Next might be allowed in the launcher, we cannot + // return it. + kiosk_next_app_delta.show_in_launcher = OptionalBool::kTrue; + AddAppDeltaToAppService(kiosk_next_app_delta.Clone()); + + mojom::App allowed_app; + allowed_app.app_id = "allowed_app"; + allowed_app.type = AppType::kBuiltIn; + + // Expect only the allowed app, all the other ones were filtered. + ExpectApps({allowed_app}); +} + +} // namespace kiosk_next_home +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index ca003a2a..0e02efe 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -2157,9 +2157,6 @@ browser_creator.LaunchBrowser( *base::CommandLine::ForCurrentProcess(), profile, base::FilePath(), chrome::startup::IS_PROCESS_STARTUP, first_run); - } else { - LOG(WARNING) << "Browser hasn't been launched, should_launch_browser_" - << " is false. This is normal in some tests."; } if (HatsNotificationController::ShouldShowSurveyToProfile(profile))
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc index 0d6d9ff..eb4de186 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc +++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/threading/thread_task_runner_handle.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/login/existing_user_controller.h" #include "chrome/browser/chromeos/login/mojo_system_info_dispatcher.h" #include "chrome/browser/chromeos/login/screens/chrome_user_selection_screen.h" @@ -20,6 +21,7 @@ #include "chrome/browser/ui/ash/login_screen_client.h" #include "chrome/browser/ui/ash/wallpaper_controller_client.h" #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" +#include "chrome/common/pref_names.h" #include "chromeos/login/auth/user_context.h" #include "components/user_manager/user_names.h" @@ -200,6 +202,35 @@ return; } + // Check whether factory reset or debugging feature have been requested in + // prior session. Ideally this would be handled earlier in startup flow, but + // it's handled here, after mojo login display host is set up to avoid running + // the wizard with web UI based login display host, and possibly adding + // another way to land on web UI based sign-in screen. + // TODO(tbarzic): Reassess when https://crbug.com/943720 is fixed. + PrefService* local_state = g_browser_process->local_state(); + if (local_state->GetBoolean(prefs::kFactoryResetRequested)) { + StartWizard(OobeScreen::SCREEN_OOBE_RESET); + start_delayed_for_oobe_dialog_ = true; + return; + } + + if (local_state->GetBoolean(prefs::kDebuggingFeaturesRequested)) { + StartWizard(OobeScreen::SCREEN_OOBE_ENABLE_DEBUGGING); + start_delayed_for_oobe_dialog_ = true; + return; + } + + // If initial signin screen was delayed to show a OOBE dialog, make sure the + // dialog is hidden. + if (start_delayed_for_oobe_dialog_) { + dialog_->Hide(); + // Reset accelerator will not work properly if OOBE UI stays in reset + // dialog state, so make sure the curren dialog screen changes. + GetOobeUI()->GetGaiaScreenView()->ShowGaiaAsync(base::nullopt); + start_delayed_for_oobe_dialog_ = false; + } + signin_screen_started_ = true; existing_user_controller_ = std::make_unique<ExistingUserController>();
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.h b/chrome/browser/chromeos/login/ui/login_display_host_mojo.h index 5c8b37a..6219862 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.h +++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
@@ -164,6 +164,10 @@ // first OnStartSigninScreen and remains true afterward. bool signin_screen_started_ = false; + // Set if the signin screen initialization was delayed to show a OOBE dialog, + // for example to run reset or enable debugging wizard. + bool start_delayed_for_oobe_dialog_ = false; + base::WeakPtrFactory<LoginDisplayHostMojo> weak_factory_; DISALLOW_COPY_AND_ASSIGN(LoginDisplayHostMojo);
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index 0a449d9..71300c99b 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc
@@ -199,6 +199,10 @@ hardware_keyboard_id = "xkb:us::eng"; // only for testing. } + registry->RegisterBooleanPref(ash::prefs::kKioskNextShellEnabled, + false /* default_value */, + PrefRegistry::PUBLIC); + registry->RegisterBooleanPref(prefs::kPerformanceTracingEnabled, false); // This pref is device specific and must not be synced. @@ -591,6 +595,7 @@ pref_change_registrar_.Add(prefs::kResolveTimezoneByGeolocationMethod, callback); pref_change_registrar_.Add(prefs::kUse24HourClock, callback); + pref_change_registrar_.Add(prefs::kParentAccessCodeConfig, callback); for (auto* remap_pref : kLanguageRemapPrefs) pref_change_registrar_.Add(remap_pref, callback); } @@ -946,6 +951,20 @@ prefs::kUse24HourClock, value); } + if (pref_name == prefs::kParentAccessCodeConfig || + reason != REASON_PREF_CHANGED) { + const base::Value* value = + prefs_->GetDictionary(prefs::kParentAccessCodeConfig); + if (value && prefs_->IsManagedPreference(prefs::kParentAccessCodeConfig)) { + user_manager::known_user::SetPref(user_->GetAccountId(), + prefs::kKnownUserParentAccessCodeConfig, + value->Clone()); + } else { + user_manager::known_user::RemovePref( + user_->GetAccountId(), prefs::kKnownUserParentAccessCodeConfig); + } + } + for (auto* remap_pref : kLanguageRemapPrefs) { if (pref_name == remap_pref || reason != REASON_ACTIVE_USER_CHANGED) { const int value = prefs_->GetInteger(remap_pref);
diff --git a/chrome/browser/complex_tasks/task_tab_helper_unittest.cc b/chrome/browser/complex_tasks/task_tab_helper_unittest.cc index 47e3fdc5..5f56efc 100644 --- a/chrome/browser/complex_tasks/task_tab_helper_unittest.cc +++ b/chrome/browser/complex_tasks/task_tab_helper_unittest.cc
@@ -37,7 +37,8 @@ class TaskTabHelperUnitTest : public ChromeRenderViewHostTestHarness { protected: - const GURL URL = GURL("http://www.google.com"); + const std::string kSearchDomain = "http://www.google.com/"; + const GURL kSearchURL = GURL(kSearchDomain); const std::string from_default_search_engine_histogram = "Tabs.Tasks.HubAndSpokeNavigationUsage.FromDefaultSearchEngine"; const std::string from_form_submit_histogram = @@ -56,7 +57,7 @@ ChromeRenderViewHostTestHarness::SetUp(); MockTaskTabHelper::CreateForWebContents(web_contents()); task_tab_helper_ = MockTaskTabHelper::FromWebContents(web_contents()); - NavigateAndCommit(URL); + NavigateAndCommit(kSearchURL); ON_CALL(*task_tab_helper_, GetSpokeEntryHubType()) .WillByDefault(testing::Return(DEFAULT_SEARCH_ENGINE_HUB_TYPE)); @@ -74,7 +75,12 @@ void NavigateAndCommitNTimes(int times) { while (times--) { - NavigateAndCommit(URL); + static int unique_int = 0; + // Note: The URLs need to be different on each iteration. Otherwise, + // navigations will be treated as reloads and will not create a new + // NavigationEntry. + NavigateAndCommit( + GURL(kSearchDomain + base::NumberToString(++unique_int))); } } @@ -83,7 +89,7 @@ }; // Testing the reset counter logic -TEST_F(TaskTabHelperUnitTest, spokeCountShouldResetInNavigationEntryCommitted) { +TEST_F(TaskTabHelperUnitTest, SpokeCountShouldResetInNavigationEntryCommitted) { NavigateAndCommitNTimes(2); GoBackNTimes(1); NavigateAndCommitNTimes(1); @@ -95,7 +101,7 @@ } TEST_F(TaskTabHelperUnitTest, - spokeCountShouldNotResetInNavigationEntryCommitted) { + SpokeCountShouldNotResetInNavigationEntryCommitted) { NavigateAndCommitNTimes(2); GoBackNTimes(1); NavigateAndCommitNTimes(1); @@ -107,7 +113,7 @@ // Testing the recording TEST_F(TaskTabHelperUnitTest, - simpleRecordHubAndSpokeUsageFromDefaultSearchEngine) { + SimpleRecordHubAndSpokeUsageFromDefaultSearchEngine) { EXPECT_CALL(*task_tab_helper_, GetSpokeEntryHubType()) .WillOnce(testing::Return(DEFAULT_SEARCH_ENGINE_HUB_TYPE)); @@ -119,7 +125,7 @@ 1); } -TEST_F(TaskTabHelperUnitTest, simpleRecordHubAndSpokeUsageFromFormSubmit) { +TEST_F(TaskTabHelperUnitTest, SimpleRecordHubAndSpokeUsageFromFormSubmit) { EXPECT_CALL(*task_tab_helper_, GetSpokeEntryHubType()) .WillOnce(testing::Return(FORM_SUBMIT_HUB_TYPE)); @@ -130,7 +136,7 @@ histogram_tester_.ExpectBucketCount(from_form_submit_histogram, 2, 1); } -TEST_F(TaskTabHelperUnitTest, simpleRecordHubAndSpokeUsageFromOther) { +TEST_F(TaskTabHelperUnitTest, SimpleRecordHubAndSpokeUsageFromOther) { EXPECT_CALL(*task_tab_helper_, GetSpokeEntryHubType()) .WillOnce(testing::Return(OTHER_HUB_TYPE)); @@ -141,7 +147,7 @@ histogram_tester_.ExpectBucketCount(from_others_histogram, 2, 1); } -TEST_F(TaskTabHelperUnitTest, complexRecordHubAndSpokeUsage) { +TEST_F(TaskTabHelperUnitTest, ComplexRecordHubAndSpokeUsage) { { testing::InSequence s;
diff --git a/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc b/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc index e95bf82..f520395 100644 --- a/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc +++ b/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc
@@ -756,7 +756,7 @@ } IN_PROC_BROWSER_TEST_F(DataReductionProxyFallbackBrowsertest, - ProxyBlockedOnAuthError) { + DISABLED_ProxyBlockedOnAuthError) { base::HistogramTester histogram_tester; net::EmbeddedTestServer test_server; test_server.RegisterRequestHandler( @@ -774,7 +774,8 @@ // Tests that if using data reduction proxy results in redirect loop, then // the proxy is bypassed, and the request is fetched directly. -IN_PROC_BROWSER_TEST_F(DataReductionProxyFallbackBrowsertest, RedirectCycle) { +IN_PROC_BROWSER_TEST_F(DataReductionProxyFallbackBrowsertest, + DISABLED_RedirectCycle) { base::HistogramTester histogram_tester; net::EmbeddedTestServer test_server; test_server.RegisterRequestHandler(
diff --git a/chrome/browser/download/download_service_factory.cc b/chrome/browser/download/download_service_factory.cc index cd3f5bb..dafae7e 100644 --- a/chrome/browser/download/download_service_factory.cc +++ b/chrome/browser/download/download_service_factory.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_constants.h" #include "components/download/content/factory/download_service_factory_helper.h" +#include "components/download/content/factory/navigation_monitor_factory.h" #include "components/download/public/background_service/clients.h" #include "components/download/public/background_service/download_service.h" #include "components/download/public/background_service/features.h" @@ -59,6 +60,7 @@ : BrowserContextKeyedServiceFactory( "download::DownloadService", BrowserContextDependencyManager::GetInstance()) { + DependsOn(download::NavigationMonitorFactory::GetInstance()); DependsOn(leveldb_proto::ProtoDatabaseProviderFactory::GetInstance()); }
diff --git a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc index 1dcbd430..b961735 100644 --- a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc +++ b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
@@ -12,7 +12,6 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/extensions/chrome_extension_function_details.h" #include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/launch_util.h" #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/installable/installable_metrics.h" @@ -312,14 +311,6 @@ return std::unique_ptr<extensions::AppForLinkDelegate>(delegate); } -bool ChromeManagementAPIDelegate::CanHostedAppsOpenInWindows() const { - return extensions::util::CanHostedAppsOpenInWindows(); -} - -bool ChromeManagementAPIDelegate::IsNewBookmarkAppsEnabled() const { - return extensions::util::IsNewBookmarkAppsEnabled(); -} - void ChromeManagementAPIDelegate::EnableExtension( content::BrowserContext* context, const std::string& extension_id) const {
diff --git a/chrome/browser/extensions/api/management/chrome_management_api_delegate.h b/chrome/browser/extensions/api/management/chrome_management_api_delegate.h index eb53b3d..8146845 100644 --- a/chrome/browser/extensions/api/management/chrome_management_api_delegate.h +++ b/chrome/browser/extensions/api/management/chrome_management_api_delegate.h
@@ -46,8 +46,6 @@ content::BrowserContext* context, const std::string& title, const GURL& launch_url) const override; - bool CanHostedAppsOpenInWindows() const override; - bool IsNewBookmarkAppsEnabled() const override; void EnableExtension(content::BrowserContext* context, const std::string& extension_id) const override; void DisableExtension(
diff --git a/chrome/browser/extensions/api/management/management_apitest.cc b/chrome/browser/extensions/api/management/management_apitest.cc index cfea99a..425e774 100644 --- a/chrome/browser/extensions/api/management/management_apitest.cc +++ b/chrome/browser/extensions/api/management/management_apitest.cc
@@ -7,7 +7,6 @@ #include "build/build_config.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/launch_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" @@ -301,23 +300,11 @@ // If the ID changed, then the pref will not apply to the app. ASSERT_EQ(app_id, app_id_new); - unsigned expected_browser_count = 2; -#if defined(OS_MACOSX) - // Without the new Bookmark Apps, Mac has no way of making standalone browser - // windows for apps, so it will add to the tabstrip instead. - EXPECT_FALSE(extensions::util::IsNewBookmarkAppsEnabled()); - EXPECT_FALSE(extensions::util::CanHostedAppsOpenInWindows()); - expected_browser_count = 1; - ASSERT_EQ(2, browser()->tab_strip_model()->count()); -#endif // Find the app's browser. Opening in a new window will create // a new browser. - ASSERT_EQ(expected_browser_count, - chrome::GetBrowserCount(browser()->profile())); - if (expected_browser_count == 2) { - Browser* app_browser = FindOtherBrowser(browser()); - ASSERT_TRUE(app_browser->is_app()); - } + ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile())); + Browser* app_browser = FindOtherBrowser(browser()); + ASSERT_TRUE(app_browser->is_app()); } // Flaky on MacOS: crbug.com/915339
diff --git a/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc b/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc index d4506f84..f7f0ce9 100644 --- a/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc +++ b/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc
@@ -13,10 +13,10 @@ #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_service.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/shill/fake_shill_profile_client.h" -#include "chromeos/dbus/shill/fake_shill_service_client.h" #include "chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h" +#include "chromeos/dbus/shill/shill_clients.h" +#include "chromeos/dbus/shill/shill_profile_client.h" +#include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/network/network_configuration_handler.h" #include "chromeos/network/network_profile_handler.h" #include "content/public/browser/browser_context.h" @@ -122,17 +122,15 @@ void SetUpInProcessBrowserTestFixture() override { extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture(); + // Destroy the existing client and create a test specific fake client. It + // will be destroyed in ChromeBrowserMain. test_client_ = new TestShillThirdPartyVpnDriverClient(); - DBusThreadManager::GetSetterForTesting()->SetShillThirdPartyVpnDriverClient( - base::WrapUnique(test_client_)); } void AddNetworkProfileForUser() { - static_cast<FakeShillProfileClient*>( - DBusThreadManager::Get()->GetShillProfileClient()) - ->AddProfile( - kNetworkProfilePath, - chromeos::ProfileHelper::GetUserIdHashFromProfile(profile())); + ShillProfileClient::Get()->GetTestInterface()->AddProfile( + kNetworkProfilePath, + chromeos::ProfileHelper::GetUserIdHashFromProfile(profile())); content::RunAllPendingInMessageLoop(); } @@ -191,7 +189,7 @@ } protected: - TestShillThirdPartyVpnDriverClient* test_client_ = nullptr; + TestShillThirdPartyVpnDriverClient* test_client_ = nullptr; // Unowned VpnService* service_ = nullptr; std::string extension_id_; std::string service_path_; @@ -217,10 +215,8 @@ const std::string service_path = GetSingleServicePath(); std::string profile_path; base::DictionaryValue properties; - EXPECT_TRUE(DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->GetService(service_path, &profile_path, &properties)); + EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService( + service_path, &profile_path, &properties)); } IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, DestroyConfig) { @@ -231,17 +227,13 @@ const std::string service_path = GetSingleServicePath(); std::string profile_path; base::DictionaryValue properties; - EXPECT_TRUE(DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->GetService(service_path, &profile_path, &properties)); + EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService( + service_path, &profile_path, &properties)); EXPECT_TRUE(RunExtensionTest("destroyConfigSuccess")); EXPECT_FALSE(DoesConfigExist(kTestConfig)); - EXPECT_FALSE(DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->GetService(service_path, &profile_path, &properties)); + EXPECT_FALSE(ShillProfileClient::Get()->GetTestInterface()->GetService( + service_path, &profile_path, &properties)); } IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, DestroyConnectedConfig) { @@ -253,10 +245,8 @@ const std::string service_path = GetSingleServicePath(); std::string profile_path; base::DictionaryValue properties; - EXPECT_TRUE(DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->GetService(service_path, &profile_path, &properties)); + EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService( + service_path, &profile_path, &properties)); EXPECT_FALSE(IsConfigConnected()); const std::string object_path = shill::kObjectPathBase + GetKey(kTestConfig); @@ -268,10 +258,8 @@ EXPECT_TRUE(DestroyConfigForTest(kTestConfig)); EXPECT_FALSE(DoesConfigExist(kTestConfig)); - EXPECT_FALSE(DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->GetService(service_path, &profile_path, &properties)); + EXPECT_FALSE(ShillProfileClient::Get()->GetTestInterface()->GetService( + service_path, &profile_path, &properties)); extensions::ResultCatcher catcher; ASSERT_TRUE(catcher.GetNextResult()); @@ -285,10 +273,8 @@ const std::string service_path = GetSingleServicePath(); std::string profile_path; base::DictionaryValue properties; - EXPECT_TRUE(DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->GetService(service_path, &profile_path, &properties)); + EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService( + service_path, &profile_path, &properties)); EXPECT_FALSE(IsConfigConnected()); const std::string object_path = shill::kObjectPathBase + GetKey(kTestConfig); @@ -384,18 +370,14 @@ const std::string service_path = GetSingleServicePath(); std::string profile_path; base::DictionaryValue properties; - EXPECT_TRUE(DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->GetService(service_path, &profile_path, &properties)); + EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService( + service_path, &profile_path, &properties)); UninstallExtension(extension_id_); content::RunAllPendingInMessageLoop(); EXPECT_FALSE(DoesConfigExist(kTestConfig)); - EXPECT_FALSE(DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->GetService(service_path, &profile_path, &properties)); + EXPECT_FALSE(ShillProfileClient::Get()->GetTestInterface()->GetService( + service_path, &profile_path, &properties)); } IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, CreateDisable) { @@ -407,10 +389,8 @@ const std::string service_path = GetSingleServicePath(); std::string profile_path; base::DictionaryValue properties; - EXPECT_TRUE(DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->GetService(service_path, &profile_path, &properties)); + EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService( + service_path, &profile_path, &properties)); extensions::ExtensionService* extension_service = extensions::ExtensionSystem::Get(profile())->extension_service(); @@ -418,10 +398,8 @@ extension_id_, extensions::disable_reason::DISABLE_USER_ACTION); content::RunAllPendingInMessageLoop(); EXPECT_FALSE(DoesConfigExist(kTestConfig)); - EXPECT_FALSE(DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->GetService(service_path, &profile_path, &properties)); + EXPECT_FALSE(ShillProfileClient::Get()->GetTestInterface()->GetService( + service_path, &profile_path, &properties)); } IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, CreateBlacklist) { @@ -433,20 +411,16 @@ const std::string service_path = GetSingleServicePath(); std::string profile_path; base::DictionaryValue properties; - EXPECT_TRUE(DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->GetService(service_path, &profile_path, &properties)); + EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService( + service_path, &profile_path, &properties)); extensions::ExtensionService* extension_service = extensions::ExtensionSystem::Get(profile())->extension_service(); extension_service->BlacklistExtensionForTest(extension_id_); content::RunAllPendingInMessageLoop(); EXPECT_FALSE(DoesConfigExist(kTestConfig)); - EXPECT_FALSE(DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->GetService(service_path, &profile_path, &properties)); + EXPECT_FALSE(ShillProfileClient::Get()->GetTestInterface()->GetService( + service_path, &profile_path, &properties)); } } // namespace chromeos
diff --git a/chrome/browser/extensions/extension_util.cc b/chrome/browser/extensions/extension_util.cc index 401d622..b36d1916 100644 --- a/chrome/browser/extensions/extension_util.cc +++ b/chrome/browser/extensions/extension_util.cc
@@ -309,26 +309,6 @@ IDR_EXTENSION_DEFAULT_ICON); } -bool IsNewBookmarkAppsEnabled() { -#if defined(OS_MACOSX) - return base::FeatureList::IsEnabled(features::kBookmarkApps) || - base::FeatureList::IsEnabled(features::kAppBanners) || - banners::AppBannerManager::IsExperimentalAppBannersEnabled(); -#else - return true; -#endif -} - -bool CanHostedAppsOpenInWindows() { -#if defined(OS_MACOSX) - return base::CommandLine::ForCurrentProcess()->HasSwitch( - ::switches::kEnableHostedAppsInWindows) || - base::FeatureList::IsEnabled(features::kDesktopPWAWindowing); -#else - return true; -#endif -} - bool IsExtensionSupervised(const Extension* extension, Profile* profile) { return WasInstalledByCustodian(extension->id(), profile) && profile->IsSupervised();
diff --git a/chrome/browser/extensions/extension_util.h b/chrome/browser/extensions/extension_util.h index c395032..ec062ab 100644 --- a/chrome/browser/extensions/extension_util.h +++ b/chrome/browser/extensions/extension_util.h
@@ -102,16 +102,6 @@ const gfx::ImageSkia& GetDefaultExtensionIcon(); const gfx::ImageSkia& GetDefaultAppIcon(); -// Returns true if the bookmark apps feature is enabled. -// -// TODO(benwells): http://crbug.com/441128: Remove this entirely once the -// feature is stable. -bool IsNewBookmarkAppsEnabled(); - -// TODO(dominickn): http://crbug.com/517682: Remove this entirely once -// open in window is stable on Mac. -bool CanHostedAppsOpenInWindows(); - // Returns true for custodian-installed extensions in a supervised profile. bool IsExtensionSupervised(const Extension* extension, Profile* profile);
diff --git a/chrome/browser/extensions/launch_util.cc b/chrome/browser/extensions/launch_util.cc index c231fb56f..14d1653 100644 --- a/chrome/browser/extensions/launch_util.cc +++ b/chrome/browser/extensions/launch_util.cc
@@ -9,7 +9,6 @@ #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/extensions/extension_sync_service.h" -#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_applications/extensions/bookmark_app_util.h" #include "chrome/common/extensions/extension_constants.h" @@ -51,26 +50,11 @@ if (extension->is_hosted_app() && !BookmarkAppIsLocallyInstalled(prefs, extension)) { result = LAUNCH_TYPE_REGULAR; - } - -#if defined(OS_MACOSX) - // Disable opening as window on Mac if: - // 1. the extension isn't a platform app, AND - // 2. the intended result is open as window, AND - // 3. CanHostedAppsOpenInWindows() is false - if (!extension->is_platform_app() && result == LAUNCH_TYPE_WINDOW && - !extensions::util::CanHostedAppsOpenInWindows()) { + } else if (result == LAUNCH_TYPE_PINNED) { result = LAUNCH_TYPE_REGULAR; + } else if (result == LAUNCH_TYPE_FULLSCREEN) { + result = LAUNCH_TYPE_WINDOW; } -#else - if (extensions::util::IsNewBookmarkAppsEnabled()) { - if (result == LAUNCH_TYPE_PINNED) - result = LAUNCH_TYPE_REGULAR; - if (result == LAUNCH_TYPE_FULLSCREEN) - result = LAUNCH_TYPE_WINDOW; - } -#endif - return result; }
diff --git a/chrome/browser/extensions/tab_helper.cc b/chrome/browser/extensions/tab_helper.cc index 744e081..7eb0908a 100644 --- a/chrome/browser/extensions/tab_helper.cc +++ b/chrome/browser/extensions/tab_helper.cc
@@ -225,18 +225,13 @@ ExtensionRegistry* registry = ExtensionRegistry::Get(context); const ExtensionSet& enabled_extensions = registry->enabled_extensions(); - if (util::IsNewBookmarkAppsEnabled()) { - Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); - if (browser && browser->is_app()) { - const Extension* extension = registry->GetExtensionById( - web_app::GetAppIdFromApplicationName(browser->app_name()), - ExtensionRegistry::EVERYTHING); - if (extension && AppLaunchInfo::GetFullLaunchURL(extension).is_valid()) - SetExtensionApp(extension); - } else { - UpdateExtensionAppIcon( - enabled_extensions.GetExtensionOrAppByURL( - navigation_handle->GetURL())); + Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); + if (browser && browser->is_app()) { + const Extension* extension = registry->GetExtensionById( + web_app::GetAppIdFromApplicationName(browser->app_name()), + ExtensionRegistry::EVERYTHING); + if (extension && AppLaunchInfo::GetFullLaunchURL(extension).is_valid()) { + SetExtensionApp(extension); } } else { UpdateExtensionAppIcon(
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 8baab65..cbc127ce 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -417,6 +417,11 @@ "expiry_milestone": 78 }, { + "name": "contextual-search-translation-model", + "owners": [ "//chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/OWNERS" ], + "expiry_milestone": 77 + }, + { "name": "contextual-search-unity-integration", "owners": [ "//chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/OWNERS" ], "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 156682f..13ef88f 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -2300,6 +2300,12 @@ "Enables triggering on a second tap gesture even when Ranker would " "normally suppress that tap."; +const char kContextualSearchTranslationModelName[] = + "Contextual Search translation using the Chrome translate model."; +const char kContextualSearchTranslationModelDescription[] = + "Enables triggering translation in Contextual Search according to the " + "Chrome translation model semantics."; + const char kContextualSearchUnityIntegrationName[] = "Contextual Search integration with Unified Consent"; const char kContextualSearchUnityIntegrationDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 38e8643..b33d9be 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1375,6 +1375,9 @@ extern const char kContextualSearchSimplifiedServerName[]; extern const char kContextualSearchSimplifiedServerDescription[]; +extern const char kContextualSearchTranslationModelName[]; +extern const char kContextualSearchTranslationModelDescription[]; + extern const char kContextualSearchUnityIntegrationName[]; extern const char kContextualSearchUnityIntegrationDescription[];
diff --git a/chrome/browser/image_fetcher/image_fetcher_service_factory.cc b/chrome/browser/image_fetcher/image_fetcher_service_factory.cc index a5615a1..7024306 100644 --- a/chrome/browser/image_fetcher/image_fetcher_service_factory.cc +++ b/chrome/browser/image_fetcher/image_fetcher_service_factory.cc
@@ -22,6 +22,7 @@ #include "components/image_fetcher/core/image_fetcher_service.h" #include "components/keyed_service/core/simple_dependency_manager.h" #include "components/keyed_service/core/simple_factory_key.h" +#include "components/leveldb_proto/content/proto_database_provider_factory.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/storage_partition.h" @@ -58,7 +59,9 @@ ImageFetcherServiceFactory::ImageFetcherServiceFactory() : SimpleKeyedServiceFactory("ImageFetcherService", - SimpleDependencyManager::GetInstance()) {} + SimpleDependencyManager::GetInstance()) { + DependsOn(leveldb_proto::ProtoDatabaseProviderFactory::GetInstance()); +} ImageFetcherServiceFactory::~ImageFetcherServiceFactory() = default; @@ -73,6 +76,7 @@ base::DefaultClock* clock = base::DefaultClock::GetInstance(); auto metadata_store = std::make_unique<ImageMetadataStoreLevelDB>( + leveldb_proto::ProtoDatabaseProviderFactory::GetForKey(key, prefs), cache_path, task_runner, clock); auto data_store = std::make_unique<ImageDataStoreDisk>(cache_path, task_runner);
diff --git a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc index e7a055f..4b862f1 100644 --- a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc
@@ -28,8 +28,6 @@ content::NavigationHandle* navigation_handle, ukm::SourceId source_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!data_reduction_proxy::params::IsDataSaverSiteBreakdownUsingPLMEnabled()) - return STOP_OBSERVING; // This BrowserContext is valid for the lifetime of // DataReductionProxyMetricsObserver. BrowserContext is always valid and
diff --git a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc index f37e0d1..4e95d52 100644 --- a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc +++ b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc
@@ -60,11 +60,7 @@ protected: void SetUp() override { scoped_feature_list_.InitWithFeatures( - {data_reduction_proxy::features:: - kDataSaverSiteBreakdownUsingPageLoadMetrics, - previews::features::kClientLoFi, features::kLazyImageLoading}, - {}); - + {previews::features::kClientLoFi, features::kLazyImageLoading}, {}); InProcessBrowserTest::SetUp(); }
diff --git a/chrome/browser/resource_coordinator/lifecycle_unit.cc b/chrome/browser/resource_coordinator/lifecycle_unit.cc index ea80def9..2de2ff1 100644 --- a/chrome/browser/resource_coordinator/lifecycle_unit.cc +++ b/chrome/browser/resource_coordinator/lifecycle_unit.cc
@@ -17,12 +17,8 @@ LifecycleUnit::SortKey::SortKey(const SortKey& other) = default; bool LifecycleUnit::SortKey::operator<(const SortKey& other) const { - if (score.has_value()) { - DCHECK(other.score.has_value()); - if (score.value() != other.score.value()) - return score.value() < other.score.value(); - } - + if (score != other.score) + return score < other.score; return last_focused_time < other.last_focused_time; }
diff --git a/chrome/browser/resource_coordinator/lifecycle_unit.h b/chrome/browser/resource_coordinator/lifecycle_unit.h index 8ed3034..9fb0314 100644 --- a/chrome/browser/resource_coordinator/lifecycle_unit.h +++ b/chrome/browser/resource_coordinator/lifecycle_unit.h
@@ -60,7 +60,7 @@ // Abstract importance score calculated by the Tab Ranker where a higher // score suggests the tab is more likely to be reactivated. // kMaxScore if the LifecycleUnit is currently focused. - base::Optional<float> score; + float score = kMaxScore; // Last time at which the LifecycleUnit was focused. base::TimeTicks::Max() // if the LifecycleUnit is currently focused.
diff --git a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc index c7c4e15..3ef89aa 100644 --- a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc +++ b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc
@@ -82,11 +82,6 @@ LOG(WARNING) << "Set OOM score: " << output; } -bool IsNewProcessTypesEnabled() { - return base::FeatureList::IsEnabled(features::kNewProcessTypes) && - !base::FeatureList::IsEnabled(features::kTabRanker); -} - } // namespace // static @@ -98,14 +93,6 @@ return os << "FOCUSED_TAB"; case ProcessType::FOCUSED_APP: return os << "FOCUSED_APP"; - case ProcessType::IMPORTANT_APP: - return os << "IMPORTANT_APP"; - case ProcessType::BACKGROUND_APP: - return os << "BACKGROUND_APP"; - case ProcessType::BACKGROUND_TAB: - return os << "BACKGROUND_TAB"; - case ProcessType::PROTECTED_BACKGROUND_TAB: - return os << "PROTECTED_BACKGROUND_TAB"; case ProcessType::UNKNOWN_TYPE: return os << "UNKNOWN_TYPE"; case ProcessType::BACKGROUND: @@ -138,39 +125,13 @@ const TabManagerDelegate::Candidate& rhs) const { if (process_type() != rhs.process_type()) return process_type() < rhs.process_type(); - if (app() && rhs.app()) - return *app() < *rhs.app(); - if (lifecycle_unit() && rhs.lifecycle_unit()) - return lifecycle_unit_sort_key_ > rhs.lifecycle_unit_sort_key_; - // When NewProcessTypes feature is turned off and using old ProcessType - // categories, tabs and apps are in separate categories so this is an - // impossible case. Otherwise, tabs and apps are compared using last active - // time. - if ((lifecycle_unit() && rhs.app()) || (app() && rhs.lifecycle_unit())) - return GetLastActiveTime() < rhs.GetLastActiveTime(); - - NOTREACHED() << "Undefined comparison between apps and tabs: process_type=" - << process_type(); - return app(); -} - -TimeTicks TabManagerDelegate::Candidate::GetLastActiveTime() const { - if (app()) - return TimeTicks::FromUptimeMillis(app()->last_activity_time()); - if (lifecycle_unit()) - return lifecycle_unit()->GetLastFocusedTime(); - return TimeTicks(); + return lifecycle_unit_sort_key_ > rhs.lifecycle_unit_sort_key_; } ProcessType TabManagerDelegate::Candidate::GetProcessTypeInternal() const { - const bool use_new_proc_types = IsNewProcessTypesEnabled(); if (app()) { if (app()->is_focused()) return ProcessType::FOCUSED_APP; - if (!use_new_proc_types) { - return app()->IsImportant() ? ProcessType::IMPORTANT_APP - : ProcessType::BACKGROUND_APP; - } if (app()->IsBackgroundProtected()) return ProcessType::PROTECTED_BACKGROUND; if (app()->IsCached()) @@ -184,11 +145,9 @@ if (!lifecycle_unit()->CanDiscard( ::mojom::LifecycleUnitDiscardReason::PROACTIVE, &decision_details)) { - return use_new_proc_types ? ProcessType::PROTECTED_BACKGROUND - : ProcessType::PROTECTED_BACKGROUND_TAB; + return ProcessType::PROTECTED_BACKGROUND; } - return use_new_proc_types ? ProcessType::BACKGROUND - : ProcessType::BACKGROUND_TAB; + return ProcessType::BACKGROUND; } return ProcessType::UNKNOWN_TYPE; } @@ -633,20 +592,14 @@ const ProcessType process_type = it->process_type(); - // Never kill selected tab, foreground app, and important apps regardless of - // whether they're in the active window. Since the user experience would be - // bad. + // Never kill selected tab and foreground app regardless of whether they're + // in the active window. Since the user experience would be bad. if (it->app()) { if (process_type == ProcessType::FOCUSED_APP) { MEMORY_LOG(ERROR) << "Skipped killing focused app " << it->app()->process_name(); continue; } - if (process_type == ProcessType::IMPORTANT_APP) { - MEMORY_LOG(ERROR) << "Skipped killing important app " - << it->app()->process_name(); - continue; - } if (IsRecentlyKilledArcProcess(it->app()->process_name(), now)) { MEMORY_LOG(ERROR) << "Avoided killing " << it->app()->process_name() << " too often"; @@ -745,12 +698,11 @@ int range_middle = (chrome::kLowestRendererOomScore + chrome::kHighestRendererOomScore) / 2; - // Find some pivot point. For now (roughly) apps are in the first half and - // tabs are in the second half. + // Find some pivot point. FOCUSED_TAB, FOCUSED_APP, and PROTECTED_BACKGROUND + // processes are in the first half and BACKGROUND and CACHED_APP processes + // are in the second half. auto lower_priority_part = candidates.end(); - bool use_new_proc_types = IsNewProcessTypesEnabled(); - ProcessType pivot_type = use_new_proc_types ? ProcessType::BACKGROUND - : ProcessType::BACKGROUND_TAB; + ProcessType pivot_type = ProcessType::BACKGROUND; for (auto it = candidates.begin(); it != candidates.end(); ++it) { if (it->process_type() >= pivot_type) { lower_priority_part = it;
diff --git a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.h b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.h index 7715a81c..47a655f 100644 --- a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.h +++ b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.h
@@ -42,27 +42,14 @@ FOCUSED_TAB = 1, FOCUSED_APP = 2, - // Important apps are protected in two ways: 1) Chrome never kills them, and - // 2) the kernel is still allowed to kill them, but their OOM adjustment - // scores are better than BACKGROUND_TABs and BACKGROUND_APPs. - IMPORTANT_APP = 3, - - BACKGROUND_APP = 4, - PROTECTED_BACKGROUND_TAB = 5, - BACKGROUND_TAB = 6, - - // PROTECTED_BACKGROUND, BACKGROUND, and CACHED_APP are newer types - // that are used instead of the previous 4 types on systems where the - // TabRanker experiment is disabled. Processes previously in IMPORTANT_APP - // and PROTECTED_BACKGROUND_TAB are now in PROTECTED_BACKGROUND, processes - // previously in either BACKGROUND_APP or BACKGROUND_TAB are now BACKGROUND. - // CACHED_APP marks Android processes which are cached or empty. - // Currently these types are only used on systems where the NewProcessTypes - // feature is enabled. - PROTECTED_BACKGROUND = 7, - BACKGROUND = 8, - CACHED_APP = 9, - UNKNOWN_TYPE = 10, + // PROTECTED_BACKGROUND processes are those that are in the background but + // are more important than BACKGROUND processes because they may be disruptive + // to the user if killed. CACHED_APP marks Android processes which are cached + // or empty. + PROTECTED_BACKGROUND = 3, + BACKGROUND = 4, + CACHED_APP = 5, + UNKNOWN_TYPE = 6, }; // The Chrome OS TabManagerDelegate is responsible for keeping the @@ -123,7 +110,7 @@ FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest, CandidatesSortedWithFocusedAppAndTab); FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest, - CandidatesSortedWithNewProcessTypes); + CandidatesSortedWithTabRanker); FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest, DoNotKillRecentlyKilledArcProcesses); FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest, IsRecentlyKilledArcProcess); @@ -244,20 +231,44 @@ lifecycle_unit_sort_key_(lifecycle_unit_->GetSortKey()) { DCHECK(lifecycle_unit_); } - explicit Candidate(const arc::ArcProcess* app) : app_(app) { DCHECK(app_); } + + // Candidates are sorted by a pair of sort keys <TabRanker score, + // last_activity_time>. Apps are not scored by TabRanker, so their score + // is set to kMaxScore. When TabRanker is off, tabs also have a score of + // kMaxScore so this has the effect of sorting by last_activity_time only. + // But if TabRanker is on, kMaxScore guarantees all apps are sorted before + // tabs. + explicit Candidate(const arc::ArcProcess* app) + : lifecycle_unit_sort_key_( + LifecycleUnit::SortKey::kMaxScore, + base::TimeTicks::FromUptimeMillis(app->last_activity_time())), + app_(app) { + DCHECK(app_); + } // Move-only class. Candidate(Candidate&&) = default; Candidate& operator=(Candidate&& other); - // Higher priority first. + // Candidates are sorted higher priority first. They are first sorted into + // their respective ProcessTypes. + // LifecycleUnit::SortKey is used to compare processes within a ProcessType, + // using a combination of TabRanker reactivation score (for tabs only) and + // last focused time for all processes. When TabRanker is disabled, tabs are + // given a default score of kMaxScore. An ArcProcess (app) is always assigned + // kMaxScore. This means that when TabRanker is off, all processes have + // kMaxScore and are then compared by last focused time. + // When TabRanker is on, tabs have their own defined order so we can't compare + // apps to tabs, since we wouldn't have a comparator to satisfy transitivity. + // In this case, ARC processes are sorted before (higher priority than) tabs + // and compared by last focused time, while tabs are compared by their + // reactivation score. bool operator<(const Candidate& rhs) const; LifecycleUnit* lifecycle_unit() { return lifecycle_unit_; } const LifecycleUnit* lifecycle_unit() const { return lifecycle_unit_; } const arc::ArcProcess* app() const { return app_; } ProcessType process_type() const { return process_type_; } - base::TimeTicks GetLastActiveTime() const; private: // Derive process type for this candidate. Used to initialize |process_type_|.
diff --git a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc index 12baa93..290bda2 100644 --- a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc
@@ -41,11 +41,11 @@ arc_processes.emplace_back(1, 10, "focused", arc::mojom::ProcessState::TOP, kIsFocused, 100); arc_processes.emplace_back(2, 20, "visible1", arc::mojom::ProcessState::TOP, - kNotFocused, 200); + kNotFocused, 6000); arc_processes.emplace_back( - 3, 30, "service", arc::mojom::ProcessState::SERVICE, kNotFocused, 500); + 3, 30, "service", arc::mojom::ProcessState::SERVICE, kNotFocused, 2001); arc_processes.emplace_back(4, 40, "visible2", arc::mojom::ProcessState::TOP, - kNotFocused, 150); + kNotFocused, 5001); TestLifecycleUnit focused_lifecycle_unit(base::TimeTicks::Max()); TestLifecycleUnit protected_lifecycle_unit( @@ -77,11 +77,11 @@ // visible app 2, last_activity_time less than visible app 1. ASSERT_TRUE(candidates[3].app()); EXPECT_EQ("visible2", candidates[3].app()->process_name()); + EXPECT_EQ(candidates[4].lifecycle_unit(), &protected_lifecycle_unit); // background service. - ASSERT_TRUE(candidates[4].app()); - EXPECT_EQ("service", candidates[4].app()->process_name()); + ASSERT_TRUE(candidates[5].app()); + EXPECT_EQ("service", candidates[5].app()->process_name()); // protected LifecycleUnit - EXPECT_EQ(candidates[5].lifecycle_unit(), &protected_lifecycle_unit); // non-focused LifecycleUnits, sorted by last focused time. EXPECT_EQ(candidates[6].lifecycle_unit(), &other_non_focused_lifecycle_unit); EXPECT_EQ(candidates[7].lifecycle_unit(), &non_focused_lifecycle_unit); @@ -109,28 +109,29 @@ EXPECT_EQ("focused", candidates[1].app()->process_name()); } -TEST_F(TabManagerDelegateTest, CandidatesSortedWithNewProcessTypes) { +// Test to make sure old process types are active when TabRanker experiment +// is turned on. +TEST_F(TabManagerDelegateTest, CandidatesSortedWithTabRanker) { base::test::ScopedFeatureList feature_list; - feature_list.InitWithFeatures({features::kNewProcessTypes}, - {features::kTabRanker}); + feature_list.InitWithFeatures({features::kTabRanker}, {}); std::vector<arc::ArcProcess> arc_processes; arc_processes.emplace_back(1, 10, "focused", arc::mojom::ProcessState::TOP, - kIsFocused, 100); + kIsFocused, 99); arc_processes.emplace_back(2, 20, "visible1", arc::mojom::ProcessState::TOP, - kNotFocused, 200); + kNotFocused, 89); arc_processes.emplace_back( - 3, 30, "service", arc::mojom::ProcessState::SERVICE, kNotFocused, 500); - arc_processes.emplace_back(4, 40, "cached", - arc::mojom::ProcessState::CACHED_EMPTY, - kNotFocused, 150); + 3, 30, "service", arc::mojom::ProcessState::SERVICE, kNotFocused, 79); - TestLifecycleUnit focused_tab(base::TimeTicks::Max()); - TestLifecycleUnit protected_tab( - base::TimeTicks() + base::TimeDelta::FromSeconds(1), 0, false); - TestLifecycleUnit background_tab(base::TimeTicks() + - base::TimeDelta::FromSeconds(5)); - LifecycleUnitVector lifecycle_units{&focused_tab, &protected_tab, - &background_tab}; + TestLifecycleUnit tab1( + base::TimeTicks() + base::TimeDelta::FromMilliseconds(100), 4); + tab1.SetSortKey(LifecycleUnit::SortKey(10, tab1.GetLastFocusedTime())); + TestLifecycleUnit tab2( + base::TimeTicks() + base::TimeDelta::FromMilliseconds(90), 5); + tab2.SetSortKey(LifecycleUnit::SortKey(20, tab2.GetLastFocusedTime())); + TestLifecycleUnit tab3( + base::TimeTicks() + base::TimeDelta::FromMilliseconds(80), 6); + tab3.SetSortKey(LifecycleUnit::SortKey(30, tab3.GetLastFocusedTime())); + LifecycleUnitVector lifecycle_units{&tab1, &tab2, &tab3}; TabManagerDelegate::OptionalArcProcessList opt_arc_processes( std::move(arc_processes)); @@ -138,25 +139,23 @@ candidates = TabManagerDelegate::GetSortedCandidates(lifecycle_units, opt_arc_processes); - ASSERT_EQ(7U, candidates.size()); - EXPECT_EQ(&focused_tab, candidates[0].lifecycle_unit()); - EXPECT_EQ(ProcessType::FOCUSED_TAB, candidates[0].process_type()); + ASSERT_EQ(6U, candidates.size()); + ASSERT_TRUE(candidates[0].app()); + EXPECT_EQ("focused", candidates[0].app()->process_name()); + EXPECT_EQ(ProcessType::FOCUSED_APP, candidates[0].process_type()); ASSERT_TRUE(candidates[1].app()); - EXPECT_EQ("focused", candidates[1].app()->process_name()); - EXPECT_EQ(ProcessType::FOCUSED_APP, candidates[1].process_type()); + EXPECT_EQ("visible1", candidates[1].app()->process_name()); + EXPECT_EQ(ProcessType::PROTECTED_BACKGROUND, candidates[1].process_type()); ASSERT_TRUE(candidates[2].app()); - EXPECT_EQ("visible1", candidates[2].app()->process_name()); - EXPECT_EQ(ProcessType::PROTECTED_BACKGROUND, candidates[2].process_type()); - EXPECT_EQ(&protected_tab, candidates[3].lifecycle_unit()); - EXPECT_EQ(ProcessType::PROTECTED_BACKGROUND, candidates[3].process_type()); - ASSERT_TRUE(candidates[4].app()); - EXPECT_EQ("service", candidates[4].app()->process_name()); + EXPECT_EQ("service", candidates[2].app()->process_name()); + EXPECT_EQ(ProcessType::BACKGROUND, candidates[2].process_type()); + + EXPECT_EQ(&tab3, candidates[3].lifecycle_unit()); + EXPECT_EQ(ProcessType::BACKGROUND, candidates[3].process_type()); + EXPECT_EQ(&tab2, candidates[4].lifecycle_unit()); EXPECT_EQ(ProcessType::BACKGROUND, candidates[4].process_type()); - EXPECT_EQ(&background_tab, candidates[5].lifecycle_unit()); + EXPECT_EQ(&tab1, candidates[5].lifecycle_unit()); EXPECT_EQ(ProcessType::BACKGROUND, candidates[5].process_type()); - ASSERT_TRUE(candidates[6].app()); - EXPECT_EQ("cached", candidates[6].app()->process_name()); - EXPECT_EQ(ProcessType::CACHED_APP, candidates[6].process_type()); } class MockTabManagerDelegate : public TabManagerDelegate { @@ -288,16 +287,16 @@ // Sorted order (by GetSortedCandidates): // app "focused" pid: 10 - // app "persistent" pid: 50 - // app "persistent_ui" pid: 60 // app "visible1" pid: 20 // app "visible2" pid: 40 - // app "service" pid: 30 // tab3 pid: 12 // tab4 pid: 12 // tab1 pid: 11 // tab5 pid: 12 // tab2 pid: 11 + // app "persistent" pid: 50 + // app "persistent_ui" pid: 60 + // app "service" pid: 30 tab_manager_delegate.AdjustOomPrioritiesImpl(std::move(arc_processes)); auto& oom_score_map = tab_manager_delegate.oom_score_map_; @@ -312,13 +311,13 @@ // Higher priority part. EXPECT_EQ(300, oom_score_map[10]); - EXPECT_EQ(388, oom_score_map[20]); - EXPECT_EQ(475, oom_score_map[40]); - EXPECT_EQ(563, oom_score_map[30]); + EXPECT_EQ(417, oom_score_map[20]); + EXPECT_EQ(533, oom_score_map[40]); // Lower priority part. EXPECT_EQ(650, oom_score_map[12]); - EXPECT_EQ(720, oom_score_map[11]); + EXPECT_EQ(708, oom_score_map[11]); + EXPECT_EQ(767, oom_score_map[30]); } TEST_F(TabManagerDelegateTest, IsRecentlyKilledArcProcess) { @@ -435,26 +434,28 @@ // Sorted order (by GetSortedCandidates): // app "focused" pid: 10 nspid 1 - // app "persistent" pid: 60 nspid 6 + // app "not-visible" pid: 50 nspid 5 // app "visible1" pid: 20 nspid 2 // app "visible2" pid: 40 nspid 4 - // app "not-visible" pid: 50 nspid 5 - // app "service" pid: 30 nspid 3 // tab3 pid: 12 id 3 // tab4 pid: 12 id 4 // tab1 pid: 11 id 1 // tab5 pid: 12 id 5 // tab2 pid: 11 id 2 + // app "service" pid: 30 nspid 3 + // app "persistent" pid: 60 nspid 6 memory_stat->SetTargetMemoryToFreeKB(250000); + + // TODO(wvk) For now the estimation of freed memory for tabs is 0, but we + // probably want to fix it later by implementing + // TestLifecycleUnit::GetEstimatedMemoryFreedOnDiscardKB. // Entities to be killed. - memory_stat->SetProcessPss(11, 50000); - memory_stat->SetProcessPss(12, 30000); - memory_stat->SetProcessPss(30, 10000); - memory_stat->SetProcessPss(50, 60000); - // Should not be used. - memory_stat->SetProcessPss(60, 500000); - memory_stat->SetProcessPss(40, 50000); memory_stat->SetProcessPss(20, 30000); + memory_stat->SetProcessPss(30, 10000); + memory_stat->SetProcessPss(40, 50000); + memory_stat->SetProcessPss(50, 60000); + // Should not be killed. + memory_stat->SetProcessPss(60, 500000); memory_stat->SetProcessPss(10, 100000); tab_manager_delegate.LowMemoryKillImpl( @@ -465,10 +466,13 @@ auto killed_arc_processes = tab_manager_delegate.GetKilledArcProcesses(); auto killed_tabs = tab_manager_delegate.GetKilledTabs(); - // Killed apps and their nspid. - ASSERT_EQ(2U, killed_arc_processes.size()); + // Killed apps and their nspid. All of the apps (except the focused app + // and the app marked as persistent) should have been killed. + ASSERT_EQ(4U, killed_arc_processes.size()); EXPECT_EQ(3, killed_arc_processes[0]); - EXPECT_EQ(5, killed_arc_processes[1]); + EXPECT_EQ(4, killed_arc_processes[1]); + EXPECT_EQ(2, killed_arc_processes[2]); + EXPECT_EQ(5, killed_arc_processes[3]); // Killed tabs and their content id. // Note that process with pid 11 is counted twice and pid 12 is counted 3 // times. But so far I don't have a good way to estimate the memory freed @@ -483,9 +487,11 @@ // Check that killed apps are in the map. const TabManagerDelegate::KilledArcProcessesMap& processes_map = tab_manager_delegate.recently_killed_arc_processes_; - EXPECT_EQ(2U, processes_map.size()); + EXPECT_EQ(4U, processes_map.size()); EXPECT_EQ(1U, processes_map.count("service")); EXPECT_EQ(1U, processes_map.count("not-visible")); + EXPECT_EQ(1U, processes_map.count("visible1")); + EXPECT_EQ(1U, processes_map.count("visible2")); } } // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_manager_features.cc b/chrome/browser/resource_coordinator/tab_manager_features.cc index 0e1dd21..4293249 100644 --- a/chrome/browser/resource_coordinator/tab_manager_features.cc +++ b/chrome/browser/resource_coordinator/tab_manager_features.cc
@@ -54,13 +54,6 @@ // on last focused time. const base::Feature kTabRanker{"TabRanker", base::FEATURE_DISABLED_BY_DEFAULT}; -#if defined(OS_CHROMEOS) -// On ChromeOS, enables using new ProcessType enums that combine apps and tabs -// in the same categories. -const base::Feature kNewProcessTypes{ - "NewProcessTypes", base::FEATURE_DISABLED_BY_DEFAULT}; -#endif // defined(OS_CHROMEOS) - } // namespace features namespace resource_coordinator {
diff --git a/chrome/browser/resource_coordinator/tab_manager_features.h b/chrome/browser/resource_coordinator/tab_manager_features.h index 0599ef4..45748f06 100644 --- a/chrome/browser/resource_coordinator/tab_manager_features.h +++ b/chrome/browser/resource_coordinator/tab_manager_features.h
@@ -20,9 +20,6 @@ extern const base::Feature kStaggeredBackgroundTabOpening; extern const base::Feature kStaggeredBackgroundTabOpeningExperiment; extern const base::Feature kTabRanker; -#if defined(OS_CHROMEOS) -extern const base::Feature kNewProcessTypes; -#endif // defined(OS_CHROMEOS) } // namespace features
diff --git a/chrome/browser/resource_coordinator/tab_metrics_logger_unittest.cc b/chrome/browser/resource_coordinator/tab_metrics_logger_unittest.cc index 595b74c..b4b2d0a 100644 --- a/chrome/browser/resource_coordinator/tab_metrics_logger_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_metrics_logger_unittest.cc
@@ -179,7 +179,7 @@ // Tests navigation_entry_count. TEST_F(TabMetricsLoggerTest, GetNavigationEntryCount) { EXPECT_EQ(CurrentTabFeatures().navigation_entry_count, 1); - tab_activity_simulator_.Navigate(web_contents_, GURL(kChromiumUrl), + tab_activity_simulator_.Navigate(web_contents_, GURL(kExampleUrl), pg_metrics_.page_transition); EXPECT_EQ(CurrentTabFeatures().navigation_entry_count, 2); tab_activity_simulator_.Navigate(web_contents_, GURL(kChromiumUrl),
diff --git a/chrome/browser/resource_coordinator/test_lifecycle_unit.cc b/chrome/browser/resource_coordinator/test_lifecycle_unit.cc index 22885b7..51cdb4d 100644 --- a/chrome/browser/resource_coordinator/test_lifecycle_unit.cc +++ b/chrome/browser/resource_coordinator/test_lifecycle_unit.cc
@@ -15,6 +15,7 @@ : LifecycleUnitBase(nullptr, content::Visibility::VISIBLE, nullptr), last_focused_time_(last_focused_time), process_handle_(process_handle), + sort_key_(last_focused_time), can_discard_(can_discard) {} TestLifecycleUnit::TestLifecycleUnit(content::Visibility visibility, @@ -45,7 +46,7 @@ } LifecycleUnit::SortKey TestLifecycleUnit::GetSortKey() const { - return SortKey(last_focused_time_); + return sort_key_; } content::Visibility TestLifecycleUnit::GetVisibility() const {
diff --git a/chrome/browser/resource_coordinator/test_lifecycle_unit.h b/chrome/browser/resource_coordinator/test_lifecycle_unit.h index cde4b206..f9357a9 100644 --- a/chrome/browser/resource_coordinator/test_lifecycle_unit.h +++ b/chrome/browser/resource_coordinator/test_lifecycle_unit.h
@@ -29,6 +29,8 @@ last_focused_time_ = last_focused_time; } + void SetSortKey(LifecycleUnit::SortKey sort_key) { sort_key_ = sort_key; } + void SetTitle(base::StringPiece16 title) { title_ = title.as_string(); } // LifecycleUnit: @@ -53,6 +55,7 @@ base::string16 title_; base::TimeTicks last_focused_time_; base::ProcessHandle process_handle_; + LifecycleUnit::SortKey sort_key_; bool can_discard_ = true; DISALLOW_COPY_AND_ASSIGN(TestLifecycleUnit);
diff --git a/chrome/browser/resources/chromeos/BUILD.gn b/chrome/browser/resources/chromeos/BUILD.gn index 88dd640..941dfca 100644 --- a/chrome/browser/resources/chromeos/BUILD.gn +++ b/chrome/browser/resources/chromeos/BUILD.gn
@@ -8,6 +8,19 @@ assert(is_chromeos, "Only Chrome OS resources in //c/b/resources//chromeos.") +grit("cellular_setup_resources") { + source = "cellular_setup/cellular_setup_resources.grd" + + defines = chrome_grit_defines + outputs = [ + "grit/cellular_setup_resources.h", + "grit/cellular_setup_resources_map.cc", + "grit/cellular_setup_resources_map.h", + "cellular_setup_resources.pak", + ] + output_dir = "$root_gen_dir/chrome" +} + grit("multidevice_setup_resources") { source = "multidevice_setup/multidevice_setup_resources.grd"
diff --git a/chrome/browser/resources/chromeos/cellular_setup/OWNERS b/chrome/browser/resources/chromeos/cellular_setup/OWNERS new file mode 100644 index 0000000..75e2f312 --- /dev/null +++ b/chrome/browser/resources/chromeos/cellular_setup/OWNERS
@@ -0,0 +1,2 @@ +azeemarshad@chromium.org +khorimoto@chromium.org
diff --git a/chrome/browser/resources/chromeos/cellular_setup/cellular_setup_dialog.html b/chrome/browser/resources/chromeos/cellular_setup/cellular_setup_dialog.html new file mode 100644 index 0000000..8ec69bc --- /dev/null +++ b/chrome/browser/resources/chromeos/cellular_setup/cellular_setup_dialog.html
@@ -0,0 +1,23 @@ +<!doctype html> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> +<head> + <meta charset="utf8"> + <base href="chrome://cellular-setup"> + <style> + html, + body { + display: flex; + height: 100%; + justify-content: center; + margin: 0; + overflow: hidden; + width: 100%; + } + </style> +</head> +<body> + <link rel="import" href="i18n_setup.html"> + <!-- TODO(khorimoto): Replace button with actual content.--> + <button>$i18n{cancel}</button> +</body> +</html>
diff --git a/chrome/browser/resources/chromeos/cellular_setup/cellular_setup_resources.grd b/chrome/browser/resources/chromeos/cellular_setup/cellular_setup_resources.grd new file mode 100644 index 0000000..319dbda --- /dev/null +++ b/chrome/browser/resources/chromeos/cellular_setup/cellular_setup_resources.grd
@@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/cellular_setup_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="grit/cellular_setup_resources_map.cc" + type="resource_file_map_source" /> + <output filename="grit/cellular_setup_resources_map.h" + type="resource_map_header" /> + <output filename="cellular_setup_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <structures> + <structure name="IDR_CELLULAR_SETUP_I18N_SETUP_HTML" + file="i18n_setup.html" + type="chrome_html" /> + <structure name="IDR_CELLULAR_SETUP_CELLULAR_SETUP_DIALOG_HTML" + file="cellular_setup_dialog.html" + flattenhtml="true" + allowexternalscript="true" + type="chrome_html" /> + </structures> + </release> +</grit>
diff --git a/chrome/browser/resources/chromeos/cellular_setup/i18n_setup.html b/chrome/browser/resources/chromeos/cellular_setup/i18n_setup.html new file mode 100644 index 0000000..b1bc3de --- /dev/null +++ b/chrome/browser/resources/chromeos/cellular_setup/i18n_setup.html
@@ -0,0 +1,3 @@ +<link rel="import" href="chrome://resources/html/load_time_data.html"> + +<script src="strings.js"></script>
diff --git a/chrome/browser/resources/chromeos/network_ui/network_ui.html b/chrome/browser/resources/chromeos/network_ui/network_ui.html index c35eb276..29b8e18 100644 --- a/chrome/browser/resources/chromeos/network_ui/network_ui.html +++ b/chrome/browser/resources/chromeos/network_ui/network_ui.html
@@ -15,12 +15,26 @@ <script src="chrome://resources/js/util.js"></script> <script src="chrome://network/strings.js"></script> <script src="chrome://network/network_ui.js"></script> + + <style> + #cellular-error-text { + color: red; + } + </style> </head> <body> <div>$i18n{autoRefreshText}</div> <span>$i18nRaw{deviceLogLinkText}</span> + <div> + <h2>$i18n{cellularActivationLabel}</h2> + <paper-button raised class="colored" id="cellular-activation-button"> + $i18n{cellularActivationButtonText} + </paper-button> + <div id="cellular-error-text" hidden>$i18n{noCellularErrorText}</div> + </div> + <h2>$i18n{globalPolicyLabel}</h2> <div id="global-policy"></div>
diff --git a/chrome/browser/resources/chromeos/network_ui/network_ui.js b/chrome/browser/resources/chromeos/network_ui/network_ui.js index 067fe5b..06eb54d 100644 --- a/chrome/browser/resources/chromeos/network_ui/network_ui.js +++ b/chrome/browser/resources/chromeos/network_ui/network_ui.js
@@ -400,6 +400,23 @@ }; /** + * Callback invoked by Chrome after a openCellularActivationUi call. + * @param {boolean} didOpenActivationUi Whether the activation UI was actually + * opened. If this value is false, it means that no cellular network was + * available to be activated. + */ + var openCellularActivationUiResult = function(didOpenActivationUi) { + $('cellular-error-text').hidden = didOpenActivationUi; + }; + + /** + * Requests that the cellular activation UI be displayed. + */ + var openCellularActivationUi = function() { + chrome.send('openCellularActivationUi'); + }; + + /** * Requests an update of all network info. */ var requestNetworks = function() { @@ -446,6 +463,7 @@ {customItemName: 'Add WiFi', polymerIcon: 'cr:add', customData: 'WiFi'}, {customItemName: 'Add VPN', polymerIcon: 'cr:add', customData: 'VPN'} ]; + $('cellular-activation-button').onclick = openCellularActivationUi; $('refresh').onclick = requestNetworks; setRefresh(); requestNetworks(); @@ -458,6 +476,7 @@ return { getShillNetworkPropertiesResult: getShillNetworkPropertiesResult, - getShillDevicePropertiesResult: getShillDevicePropertiesResult + getShillDevicePropertiesResult: getShillDevicePropertiesResult, + openCellularActivationUiResult: openCellularActivationUiResult }; })();
diff --git a/chrome/browser/resources/discards/generate_graph_tab.py b/chrome/browser/resources/discards/generate_graph_tab.py index 528e1d8..4205e36 100644 --- a/chrome/browser/resources/discards/generate_graph_tab.py +++ b/chrome/browser/resources/discards/generate_graph_tab.py
@@ -30,7 +30,8 @@ html_doc = html_template.substitute({'javascript_file': js_file_contents}); # Construct the data: URL that contains the combined doc. - data_url = "data:text/html;base64,%s" % base64.b64encode(html_doc); + data_url = "data:text/html;base64,%s" % base64.b64encode( + html_doc.encode()).decode() # And finally stamp the the data URL into the output template. output = output_template.substitute({'data_url': data_url})
diff --git a/chrome/browser/resources/ntp4/apps_page.js b/chrome/browser/resources/ntp4/apps_page.js index 2336547..32bb497 100644 --- a/chrome/browser/resources/ntp4/apps_page.js +++ b/chrome/browser/resources/ntp4/apps_page.js
@@ -53,9 +53,7 @@ menu.appendChild(cr.ui.MenuItem.createSeparator()); this.launchRegularTab_ = this.appendMenuItem_('applaunchtyperegular'); this.launchPinnedTab_ = this.appendMenuItem_('applaunchtypepinned'); - if (loadTimeData.getBoolean('canHostedAppsOpenInWindows')) { - this.launchNewWindow_ = this.appendMenuItem_('applaunchtypewindow'); - } + this.launchNewWindow_ = this.appendMenuItem_('applaunchtypewindow'); this.launchFullscreen_ = this.appendMenuItem_('applaunchtypefullscreen'); const self = this; @@ -152,16 +150,11 @@ this.forAllLaunchTypes_(function(launchTypeButton, id) { launchTypeButton.disabled = false; launchTypeButton.checked = app.appData.launch_type == id; - // There are three cases when a launch type is hidden: + // There are two cases when a launch type is hidden: // 1. if the launch type can't be changed. - // 2. canHostedAppsOpenInWindows is false and type is launchTypeWindow - // 3. enableNewBookmarkApps is true and type is anything except - // launchTypeWindow + // 2. type is anything except launchTypeWindow launchTypeButton.hidden = !app.appData.mayChangeLaunchType || - (!loadTimeData.getBoolean('canHostedAppsOpenInWindows') && - launchTypeButton == launchTypeWindow) || - (loadTimeData.getBoolean('enableNewBookmarkApps') && - launchTypeButton != launchTypeWindow); + launchTypeButton != launchTypeWindow; if (!launchTypeButton.hidden) { hasLaunchType = true; } @@ -201,11 +194,9 @@ let targetLaunchType = pressed; // When bookmark apps are enabled, hosted apps can only toggle between // open as window and open as tab. - if (loadTimeData.getBoolean('enableNewBookmarkApps')) { - targetLaunchType = this.launchNewWindow_.checked ? - this.launchRegularTab_ : - this.launchNewWindow_; - } + targetLaunchType = this.launchNewWindow_.checked ? + this.launchRegularTab_ : + this.launchNewWindow_; this.forAllLaunchTypes_(function(launchTypeButton, id) { if (launchTypeButton == targetLaunchType) { chrome.send('setLaunchType', [app.appId, id]);
diff --git a/chrome/browser/resources/settings/autofill_page/payments_section.html b/chrome/browser/resources/settings/autofill_page/payments_section.html index 6113b3f..7e53d968 100644 --- a/chrome/browser/resources/settings/autofill_page/payments_section.html +++ b/chrome/browser/resources/settings/autofill_page/payments_section.html
@@ -69,7 +69,7 @@ </paper-button> </div> <div class="settings-box two-line" id="migrateCreditCards" - hidden$="[[!checkIfMigratable_(syncStatus, creditCards, + hidden$="[[!checkIfMigratable_(creditCards, prefs.autofill.credit_card_enabled.value)]]" on-click="onMigrateCreditCardsClick_" actionable> <div class="start">
diff --git a/chrome/browser/resources/settings/autofill_page/payments_section.js b/chrome/browser/resources/settings/autofill_page/payments_section.js index 0eca2bcf..03d51d2 100644 --- a/chrome/browser/resources/settings/autofill_page/payments_section.js +++ b/chrome/browser/resources/settings/autofill_page/payments_section.js
@@ -120,7 +120,10 @@ * An array of all saved credit cards. * @type {!Array<!PaymentsManager.CreditCardEntry>} */ - creditCards: Array, + creditCards: { + type: Array, + value: () => [], + }, /** * The model for any credit card related action menus or dialogs. @@ -135,12 +138,6 @@ migratableCreditCardsInfo_: String, /** - * The current sync status, supplied by SyncBrowserProxy. - * @type {?settings.SyncStatus} - */ - syncStatus: Object, - - /** * Whether migration local card on settings page is enabled. * @private */ @@ -151,66 +148,6 @@ }, readOnly: true, }, - - /** - * Whether user has a Google Payments account. - * @private - */ - hasGooglePaymentsAccount_: { - type: Boolean, - value: function() { - return loadTimeData.getBoolean('hasGooglePaymentsAccount'); - }, - readOnly: true, - }, - - /** - * Whether Autofill Upstream is enabled. - * @private - */ - upstreamEnabled_: { - type: Boolean, - value: function() { - return loadTimeData.getBoolean('upstreamEnabled'); - }, - readOnly: true, - }, - - /** - * Whether the user has a secondary sync passphrase. - * @private - */ - isUsingSecondaryPassphrase_: { - type: Boolean, - value: function() { - return loadTimeData.getBoolean('isUsingSecondaryPassphrase'); - }, - readOnly: true, - }, - - /** - * Whether the upload-to-google state is active. - * @private - */ - uploadToGoogleActive_: { - type: Boolean, - value: function() { - return loadTimeData.getBoolean('uploadToGoogleActive'); - }, - readOnly: true, - }, - - /** - * Whether the domain of the user's email is allowed. - * @private - */ - userEmailDomainAllowed_: { - type: Boolean, - value: function() { - return loadTimeData.getBoolean('userEmailDomainAllowed'); - }, - readOnly: true, - }, }, listeners: { @@ -238,9 +175,6 @@ */ setCreditCardsListener_: null, - /** @private {?settings.SyncBrowserProxy} */ - syncBrowserProxy_: null, - /** @override */ attached: function() { // Create listener function. @@ -262,12 +196,6 @@ this.paymentsManager_.addCreditCardListChangedListener( setCreditCardsListener); - this.syncBrowserProxy_ = settings.SyncBrowserProxyImpl.getInstance(); - this.syncBrowserProxy_.getSyncStatus().then( - this.handleSyncStatus_.bind(this)); - this.addWebUIListener( - 'sync-status-changed', this.handleSyncStatus_.bind(this)); - // Record that the user opened the payments settings. chrome.metricsPrivate.recordUserAction('AutofillCreditCardsViewed'); }, @@ -383,73 +311,22 @@ }, /** - * Handler for when the sync state is pushed from the browser. - * @param {?settings.SyncStatus} syncStatus - * @private - */ - handleSyncStatus_: function(syncStatus) { - this.syncStatus = syncStatus; - }, - - /** - * @param {!settings.SyncStatus} syncStatus * @param {!Array<!PaymentsManager.CreditCardEntry>} creditCards * @param {boolean} creditCardEnabled - * @return {boolean} Whether to show the migration button. True iff at - * least - * one valid local card, enable migration, signed-in & synced and credit - * card pref enabled. + * @return {boolean} Whether to show the migration button. * @private */ - checkIfMigratable_: function(syncStatus, creditCards, creditCardEnabled) { - if (syncStatus == undefined) { - return false; - } - - // If user not enable migration experimental flag, return false. + checkIfMigratable_: function(creditCards, creditCardEnabled) { + // If migration prerequisites are not met, return false. if (!this.migrationEnabled_) { return false; } - // If user does not have Google Payments Account, return false. - if (!this.hasGooglePaymentsAccount_) { - return false; - } - - // If the Autofill Upstream feature is not enabled, return false. - if (!this.upstreamEnabled_) { - return false; - } - - // Don't offer upload if user has a secondary passphrase. Users who have - // enabled a passphrase have chosen to not make their sync information - // accessible to Google. Since upload makes credit card data available - // to other Google systems, disable it for passphrase users. - if (this.isUsingSecondaryPassphrase_) { - return false; - } - - // If upload-to-Google state is not active, card cannot be saved to - // Google Payments. Return false. - if (!this.uploadToGoogleActive_) { - return false; - } - - // The domain of the user's email address is not allowed, return false. - if (!this.userEmailDomainAllowed_) { - return false; - } - // If credit card enabled pref is false, return false. if (!creditCardEnabled) { return false; } - // If user not signed-in and synced, return false. - if (!syncStatus.signedIn || !syncStatus.syncSystemEnabled) { - return false; - } - const numberOfMigratableCreditCard = creditCards.filter(card => card.metadata.isMigratable).length; // Check whether exist at least one local valid card for migration.
diff --git a/chrome/browser/resources/welcome/OWNERS b/chrome/browser/resources/welcome/OWNERS index bfe00f2..08ee1a9 100644 --- a/chrome/browser/resources/welcome/OWNERS +++ b/chrome/browser/resources/welcome/OWNERS
@@ -1,2 +1 @@ hcarmona@chromium.org -scottchen@chromium.org
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html index 1c8b099..70c4455 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html
@@ -13,15 +13,17 @@ } .email-logo { - content: -webkit-image-set( - url(../images/email_provider_1x.png) 1x, - url(../images/email_provider_2x.png) 2x); + content: url(../images/module_icons/email_light.svg); height: 38px; margin: auto; margin-bottom: 16px; width: 42px; } + :host-context([dark]) .email-logo { + content: url(../images/module_icons/email_dark.svg); + } + h1 { color: var(--cr-primary-text-color); font-size: 1.5rem;
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html index 51fc1c9..2cae5b1 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html
@@ -13,15 +13,17 @@ } .chrome-logo { - content: -webkit-image-set( - url(chrome://welcome/images/google_apps_1x.png) 1x, - url(chrome://welcome/images/google_apps_2x.png) 2x); + content: url(../images/module_icons/google_light.svg); height: 38px; margin: auto; margin-bottom: 16px; width: 42px; } + :host-context([dark]) .chrome-logo { + content: url(../images/module_icons/google_dark.svg); + } + h1 { color: var(--cr-primary-text-color); font-size: 1.5rem;
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/email_provider_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/email_provider_1x.png deleted file mode 100644 index 4ef0c29..0000000 --- a/chrome/browser/resources/welcome/onboarding_welcome/images/email_provider_1x.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/email_provider_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/email_provider_2x.png deleted file mode 100644 index 62b7614..0000000 --- a/chrome/browser/resources/welcome/onboarding_welcome/images/email_provider_2x.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/google_apps_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/google_apps_1x.png deleted file mode 100644 index adaff6c..0000000 --- a/chrome/browser/resources/welcome/onboarding_welcome/images/google_apps_1x.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/google_apps_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/google_apps_2x.png deleted file mode 100644 index eeccb7d..0000000 --- a/chrome/browser/resources/welcome/onboarding_welcome/images/google_apps_2x.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/email_dark.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/email_dark.svg new file mode 100644 index 0000000..f6eac4f --- /dev/null +++ b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/email_dark.svg
@@ -0,0 +1 @@ +<svg width="46" height="39" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-2 -2)" fill="none" fill-rule="evenodd"><circle fill="#90CFA3" cx="9.764" cy="38.785" r="2"/><path d="M34.998 27.443l11.433-.565a1.157 1.157 0 0 1 1.156 1.16 1.142 1.142 0 0 1-.127.514L42.284 38.58a1.174 1.174 0 0 1-1.977.163L34.05 29.28a1.144 1.144 0 0 1 .247-1.611c.203-.148.45-.227.701-.226z" fill="#EE675C" style="mix-blend-mode:screen"/><path d="M37.43 13.118H16.097a2.663 2.663 0 0 0-2.653 2.667l-.014 16c0 1.466 1.2 2.666 2.667 2.666H37.43c1.467 0 2.667-1.2 2.667-2.666v-16c0-1.467-1.2-2.667-2.667-2.667zm0 5.333l-10.666 6.667-10.667-6.667v-2.666l10.667 6.666 10.666-6.666v2.666z" fill="#8AB4F8" fill-rule="nonzero"/><path style="mix-blend-mode:multiply" d="M10.764 7.785h32v32h-32z"/><path d="M7.356 5.426c4.903-4.184 12.016-3.946 16.689.284.464.42 1.274 1.412-.187 2.658L7.085 22.678c-1.324 1.13-1.914.198-2.203-.255C1.42 16.985 2.38 9.671 7.356 5.426z" fill="#FDD663" style="mix-blend-mode:screen"/></g></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/email_light.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/email_light.svg new file mode 100644 index 0000000..bb7b52ab --- /dev/null +++ b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/email_light.svg
@@ -0,0 +1 @@ +<svg width="46" height="39" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-2 -2)" fill="none" fill-rule="evenodd"><circle fill="#31A753" cx="9.764" cy="38.785" r="2"/><path d="M34.998 27.443l11.433-.565a1.157 1.157 0 0 1 1.156 1.16 1.142 1.142 0 0 1-.127.514L42.284 38.58a1.174 1.174 0 0 1-1.977.163L34.05 29.28a1.144 1.144 0 0 1 .247-1.611c.203-.148.45-.227.701-.226z" fill="#E74133" style="mix-blend-mode:multiply"/><path d="M37.43 13.118H16.097a2.663 2.663 0 0 0-2.653 2.667l-.014 16c0 1.466 1.2 2.666 2.667 2.666H37.43c1.467 0 2.667-1.2 2.667-2.666v-16c0-1.467-1.2-2.667-2.667-2.667zm0 5.333l-10.666 6.667-10.667-6.667v-2.666l10.667 6.666 10.666-6.666v2.666z" fill="#1A73E8" fill-rule="nonzero"/><path style="mix-blend-mode:multiply" d="M10.764 7.785h32v32h-32z"/><path d="M7.356 5.426c4.903-4.184 12.016-3.946 16.689.284.464.42 1.274 1.412-.187 2.658L7.085 22.678c-1.324 1.13-1.914.198-2.203-.255C1.42 16.985 2.38 9.671 7.356 5.426z" fill="#FACF4C" style="mix-blend-mode:multiply"/></g></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/google_dark.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/google_dark.svg new file mode 100644 index 0000000..40991d56 --- /dev/null +++ b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/google_dark.svg
@@ -0,0 +1 @@ +<svg width="42" height="38" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-2 -2)" fill="none" fill-rule="evenodd"><path d="M31.235 26.057l11.432-.566a1.157 1.157 0 0 1 1.157 1.16 1.142 1.142 0 0 1-.128.515L38.52 37.192a1.174 1.174 0 0 1-1.977.163l-6.257-9.461a1.144 1.144 0 0 1 .247-1.612c.203-.148.45-.227.702-.225z" fill="#EE675C"/><path d="M23.239 25.28v-4.464h11.455c.171.756.306 1.464.306 2.46C35 30.128 30.313 35 23.25 35 16.484 35 11 29.624 11 23s5.483-12 12.239-12c3.304 0 6.07 1.188 8.187 3.132l-3.475 3.312c-.882-.816-2.411-1.788-4.712-1.788-4.051 0-7.356 3.3-7.356 7.344 0 4.044 3.305 7.344 7.356 7.344 4.687 0 6.413-3.18 6.73-5.064h-6.73z" fill="#8AB4F8" fill-rule="nonzero"/><path d="M7 7h32v32H7z"/><circle fill="#81C995" cx="10" cy="37.398" r="2"/><path d="M6.592 5.039c4.904-4.183 12.017-3.946 16.689.284.464.42 1.274 1.412-.187 2.658L6.321 22.291c-1.324 1.13-1.914.198-2.202-.254C.655 16.597 1.616 9.284 6.592 5.039z" fill="#FDD663" style="mix-blend-mode:screen"/></g></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/google_light.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/google_light.svg new file mode 100644 index 0000000..a0bed3b --- /dev/null +++ b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/google_light.svg
@@ -0,0 +1 @@ +<svg width="42" height="38" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-2 -2)" fill="none" fill-rule="evenodd"><path d="M31.235 26.057l11.432-.566a1.157 1.157 0 0 1 1.157 1.16 1.142 1.142 0 0 1-.128.515L38.52 37.192a1.174 1.174 0 0 1-1.977.163l-6.257-9.461a1.144 1.144 0 0 1 .247-1.612c.203-.148.45-.227.702-.225z" fill="#E74133"/><path d="M23.239 25.678v-4.464h11.455c.171.756.306 1.464.306 2.46 0 6.852-4.687 11.724-11.75 11.724-6.767 0-12.25-5.376-12.25-12s5.483-12 12.239-12c3.304 0 6.07 1.188 8.187 3.132l-3.475 3.312c-.882-.816-2.411-1.788-4.712-1.788-4.051 0-7.356 3.3-7.356 7.344 0 4.044 3.305 7.344 7.356 7.344 4.687 0 6.413-3.18 6.73-5.064h-6.73z" fill="#1A73E8" fill-rule="nonzero"/><path d="M7 7.398h32v32H7z"/><circle fill="#31A753" cx="10" cy="37.398" r="2"/><path d="M6.592 5.039c4.904-4.183 12.017-3.946 16.689.284.464.42 1.274 1.412-.187 2.658L6.321 22.291c-1.324 1.13-1.914.198-2.202-.254C.655 16.597 1.616 9.284 6.592 5.039z" fill="#FACF4C" style="mix-blend-mode:multiply"/></g></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/set_default_dark.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/set_default_dark.svg new file mode 100644 index 0000000..414dff5 --- /dev/null +++ b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/set_default_dark.svg
@@ -0,0 +1 @@ +<svg width="44" height="39" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path d="M14 3C7.929 3 3 7.929 3 14s4.929 11 11 11 11-4.929 11-11S20.071 3 14 3zm0-3c7.728 0 14 6.272 14 14s-6.272 14-14 14S0 21.728 0 14 6.272 0 14 0z" id="a"/><path d="M14 .667C21.36.667 27.333 6.64 27.333 14S21.36 27.333 14 27.333.667 21.36.667 14 6.64.667 14 .667zM3.333 14H9.2c4.543.029 6.562 2.308 6.058 6.836H10.65v3.293c1.054.349 2.18.538 3.35.538 5.887 0 10.667-4.78 10.667-10.667 0-.217-.007-.433-.02-.647-.876 1.32-2.203 1.98-3.98 1.98-2.85 0-4.275-1.222-4.275-3.665h-4.998c-.365-3.638.91-5.457 3.827-5.457 0-1.3.436-2.13 1.082-2.628A10.69 10.69 0 0 0 14 3.333C8.113 3.333 3.333 8.113 3.333 14z" id="c"/></defs><g transform="translate(-2 -2)" fill="none" fill-rule="evenodd"><path d="M33.235 28.659l11.432-.566a1.157 1.157 0 0 1 1.157 1.16 1.142 1.142 0 0 1-.128.515L40.52 39.794a1.174 1.174 0 0 1-1.977.163l-6.257-9.461a1.144 1.144 0 0 1 .247-1.612c.203-.148.45-.227.702-.225z" fill="#EE675C"/><g transform="translate(11 9)"><mask id="b" fill="#fff"><use xlink:href="#a"/></mask><use fill="#000" fill-rule="nonzero" xlink:href="#a"/><g mask="url(#b)" fill="#1A73E8"><path d="M-2-2h32v32H-2z"/></g><use fill="#8AB4F8" fill-rule="nonzero" xlink:href="#c"/></g><circle fill="#81C995" cx="9" cy="38.398" r="2"/><path d="M6.592 5.039c4.904-4.183 12.017-3.946 16.689.284.464.42 1.274 1.412-.187 2.658L6.321 22.291c-1.324 1.13-1.914.198-2.202-.254C.655 16.597 1.616 9.284 6.592 5.039z" fill="#FDDF8B" style="mix-blend-mode:screen"/></g></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/set_default_light.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/set_default_light.svg new file mode 100644 index 0000000..2a0c6eb --- /dev/null +++ b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/set_default_light.svg
@@ -0,0 +1 @@ +<svg width="44" height="39" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path d="M16 5C9.929 5 5 9.929 5 16s4.929 11 11 11 11-4.929 11-11S22.071 5 16 5zm0-3c7.728 0 14 6.272 14 14s-6.272 14-14 14S2 23.728 2 16 8.272 2 16 2z" id="a"/><path d="M16 2.667c7.36 0 13.333 5.973 13.333 13.333S23.36 29.333 16 29.333 2.667 23.36 2.667 16 8.64 2.667 16 2.667zM5.333 16H11.2c4.543.029 6.562 2.308 6.058 6.836H12.65v3.293c1.054.349 2.18.538 3.35.538 5.887 0 10.667-4.78 10.667-10.667 0-.217-.007-.433-.02-.647-.876 1.32-2.203 1.98-3.98 1.98-2.85 0-4.275-1.222-4.275-3.665h-4.998c-.365-3.638.91-5.457 3.827-5.457 0-1.3.436-2.13 1.082-2.628A10.69 10.69 0 0 0 16 5.333c-5.887 0-10.667 4.78-10.667 10.667z" id="c"/></defs><g transform="translate(-2 -2)" fill="none" fill-rule="evenodd"><path d="M33.235 28.659l11.432-.566a1.157 1.157 0 0 1 1.157 1.16 1.142 1.142 0 0 1-.128.515L40.52 39.794a1.174 1.174 0 0 1-1.977.163l-6.257-9.461a1.144 1.144 0 0 1 .247-1.612c.203-.148.45-.227.702-.225z" fill="#E74133"/><g transform="translate(9 7.398)"><mask id="b" fill="#fff"><use xlink:href="#a"/></mask><use fill="#000" fill-rule="nonzero" xlink:href="#a"/><g mask="url(#b)" fill="#1A73E8"><path d="M0 0h32v32H0z"/></g><mask id="d" fill="#fff"><use xlink:href="#c"/></mask><use fill="#000" fill-rule="nonzero" xlink:href="#c"/><g mask="url(#d)" fill="#1A73E8"><path d="M0 0h32v32H0z"/></g></g><circle fill="#31A753" cx="9" cy="38.398" r="2"/><path d="M6.592 5.039c4.904-4.183 12.017-3.946 16.689.284.464.42 1.274 1.412-.187 2.658L6.321 22.291c-1.324 1.13-1.914.198-2.202-.254C.655 16.597 1.616 9.284 6.592 5.039z" fill="#FACF4C" style="mix-blend-mode:multiply"/></g></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/wallpaper_dark.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/wallpaper_dark.svg new file mode 100644 index 0000000..45cfa17 --- /dev/null +++ b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/wallpaper_dark.svg
@@ -0,0 +1 @@ +<svg width="44" height="39" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-2 -2)" fill="none" fill-rule="evenodd"><path d="M33.235 28.659l11.432-.566a1.157 1.157 0 0 1 1.157 1.16 1.142 1.142 0 0 1-.128.515L40.52 39.794a1.174 1.174 0 0 1-1.977.163l-6.257-9.461a1.144 1.144 0 0 1 .247-1.612c.203-.148.45-.227.702-.225z" fill="#EE675C"/><circle fill="#31A753" cx="9" cy="38.398" r="2"/><path d="M9 7h32v32H9z"/><path d="M34.333 13.667v18.666H15.667V13.667h18.666zm0-2.667H15.667A2.675 2.675 0 0 0 13 13.667v18.666C13 33.8 14.2 35 15.667 35h18.666C35.8 35 37 33.8 37 32.333V13.667C37 12.2 35.8 11 34.333 11zm-6.48 11.813l-4 5.16L21 24.52l-4 5.147h16l-5.147-6.854z" fill="#8AB4F8" fill-rule="nonzero"/><path d="M6.592 5.039c4.904-4.183 12.017-3.946 16.689.284.464.42 1.274 1.412-.187 2.658L6.321 22.291c-1.324 1.13-1.914.198-2.202-.254C.655 16.597 1.616 9.284 6.592 5.039z" fill="#FDDB79" style="mix-blend-mode:screen"/></g></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/wallpaper_light.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/wallpaper_light.svg new file mode 100644 index 0000000..300ae22 --- /dev/null +++ b/chrome/browser/resources/welcome/onboarding_welcome/images/module_icons/wallpaper_light.svg
@@ -0,0 +1 @@ +<svg width="44" height="39" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-2 -2)" fill="none" fill-rule="evenodd"><path d="M33.235 28.659l11.432-.566a1.157 1.157 0 0 1 1.157 1.16 1.142 1.142 0 0 1-.128.515L40.52 39.794a1.174 1.174 0 0 1-1.977.163l-6.257-9.461a1.144 1.144 0 0 1 .247-1.612c.203-.148.45-.227.702-.225z" fill="#E74133"/><circle fill="#31A753" cx="9" cy="38.398" r="2"/><path d="M6.592 5.039c4.904-4.183 12.017-3.946 16.689.284.464.42 1.274 1.412-.187 2.658L6.321 22.291c-1.324 1.13-1.914.198-2.202-.254C.655 16.597 1.616 9.284 6.592 5.039z" fill="#FACF4C" style="mix-blend-mode:multiply"/><path d="M9 7h32v32H9z"/><path d="M34.333 13.667v18.666H15.667V13.667h18.666zm0-2.667H15.667A2.675 2.675 0 0 0 13 13.667v18.666C13 33.8 14.2 35 15.667 35h18.666C35.8 35 37 33.8 37 32.333V13.667C37 12.2 35.8 11 34.333 11zm-6.48 11.813l-4 5.16L21 24.52l-4 5.147h16l-5.147-6.854z" fill="#1A73E8" fill-rule="nonzero"/></g></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/ntp_background_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/ntp_background_1x.png deleted file mode 100644 index fdc3f4f..0000000 --- a/chrome/browser/resources/welcome/onboarding_welcome/images/ntp_background_1x.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/ntp_background_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/ntp_background_2x.png deleted file mode 100644 index a6e3139..0000000 --- a/chrome/browser/resources/welcome/onboarding_welcome/images/ntp_background_2x.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/set_as_default_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/set_as_default_1x.png deleted file mode 100644 index c6d2637..0000000 --- a/chrome/browser/resources/welcome/onboarding_welcome/images/set_as_default_1x.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/set_as_default_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/set_as_default_2x.png deleted file mode 100644 index b82f6201..0000000 --- a/chrome/browser/resources/welcome/onboarding_welcome/images/set_as_default_2x.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/ntp_background/nux_ntp_background.html b/chrome/browser/resources/welcome/onboarding_welcome/ntp_background/nux_ntp_background.html index 132f6c5..d8b7649 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/ntp_background/nux_ntp_background.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/ntp_background/nux_ntp_background.html
@@ -57,15 +57,17 @@ } .ntp-background-logo { - content: -webkit-image-set( - url(chrome://welcome/images/ntp_background_1x.png) 1x, - url(chrome://welcome/images/ntp_background_2x.png) 2x); + content: url(../images/module_icons/wallpaper_light.svg); height: 39px; margin: auto; margin-bottom: 16px; width: 44px; } + :host-context([dark]) .ntp-background-logo { + content: url(../images/module_icons/wallpaper_dark.svg); + } + h1 { color: var(--cr-primary-text-color); font-size: 1.5rem;
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd b/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd index 2f3f089..174bf93 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd +++ b/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd
@@ -15,103 +15,111 @@ <release seq="1"> <includes> <include name="IDR_NUX_EMAIL_AOL_1X" - file="images\aol_1x.png" + file="images/aol_1x.png" type="BINDATA"/> <include name="IDR_NUX_EMAIL_AOL_2X" - file="images\aol_2x.png" + file="images/aol_2x.png" type="BINDATA" /> <include name="IDR_NUX_EMAIL_GMAIL_1X" - file="images\gmail_1x.png" + file="images/gmail_1x.png" type="BINDATA" /> <include name="IDR_NUX_EMAIL_GMAIL_2X" - file="images\gmail_2x.png" + file="images/gmail_2x.png" type="BINDATA" /> <include name="IDR_NUX_EMAIL_ICLOUD_1X" - file="images\icloud_1x.png" + file="images/icloud_1x.png" type="BINDATA" /> <include name="IDR_NUX_EMAIL_ICLOUD_2X" - file="images\icloud_2x.png" + file="images/icloud_2x.png" type="BINDATA" /> <include name="IDR_NUX_EMAIL_OUTLOOK_1X" - file="images\outlook_1x.png" + file="images/outlook_1x.png" type="BINDATA" /> <include name="IDR_NUX_EMAIL_OUTLOOK_2X" - file="images\outlook_2x.png" - type="BINDATA" /> - <include name="IDR_NUX_EMAIL_PROVIDER_LOGO_1X" - file="images\email_provider_1x.png" - type="BINDATA" /> - <include name="IDR_NUX_EMAIL_PROVIDER_LOGO_2X" - file="images\email_provider_2x.png" + file="images/outlook_2x.png" type="BINDATA" /> <include name="IDR_NUX_EMAIL_YAHOO_1X" - file="images\yahoo_1x.png" + file="images/yahoo_1x.png" type="BINDATA" /> <include name="IDR_NUX_EMAIL_YAHOO_2X" - file="images\yahoo_2x.png" + file="images/yahoo_2x.png" type="BINDATA" /> <include name="IDR_NUX_GOOGLE_APPS_CHROME_STORE_1X" - file="images\chrome_store_1x.png" + file="images/chrome_store_1x.png" type="BINDATA" /> <include name="IDR_NUX_GOOGLE_APPS_CHROME_STORE_2X" - file="images\chrome_store_2x.png" - type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_LOGO_1X" - file="images\google_apps_1x.png" - type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_LOGO_2X" - file="images\google_apps_2x.png" + file="images/chrome_store_2x.png" type="BINDATA" /> <include name="IDR_NUX_GOOGLE_APPS_MAPS_1X" - file="images\maps_1x.png" + file="images/maps_1x.png" type="BINDATA" /> <include name="IDR_NUX_GOOGLE_APPS_MAPS_2X" - file="images\maps_2x.png" + file="images/maps_2x.png" type="BINDATA" /> <include name="IDR_NUX_GOOGLE_APPS_NEWS_1X" - file="images\news_1x.png" + file="images/news_1x.png" type="BINDATA" /> <include name="IDR_NUX_GOOGLE_APPS_NEWS_2X" - file="images\news_2x.png" + file="images/news_2x.png" type="BINDATA" /> <include name="IDR_NUX_GOOGLE_APPS_TRANSLATE_1X" - file="images\translate_1x.png" + file="images/translate_1x.png" type="BINDATA" /> <include name="IDR_NUX_GOOGLE_APPS_TRANSLATE_2X" - file="images\translate_2x.png" + file="images/translate_2x.png" type="BINDATA" /> <include name="IDR_NUX_GOOGLE_APPS_YOUTUBE_1X" - file="images\youtube_1x.png" + file="images/youtube_1x.png" type="BINDATA" /> <include name="IDR_NUX_GOOGLE_APPS_YOUTUBE_2X" - file="images\youtube_2x.png" + file="images/youtube_2x.png" type="BINDATA" /> - <include name="IDR_NUX_NTP_BACKGROUND_LOGO_1X" - file="images\ntp_background_1x.png" + <include name="IDR_NUX_MODULE_ICONS_EMAIL_DARK" + file="images/module_icons/email_dark.svg" + compress="gzip" type="BINDATA" /> - <include name="IDR_NUX_NTP_BACKGROUND_LOGO_2X" - file="images\ntp_background_2x.png" + <include name="IDR_NUX_MODULE_ICONS_EMAIL_LIGHT" + file="images/module_icons/email_light.svg" + compress="gzip" + type="BINDATA" /> + <include name="IDR_NUX_MODULE_ICONS_GOOGLE_DARK" + file="images/module_icons/google_dark.svg" + compress="gzip" + type="BINDATA" /> + <include name="IDR_NUX_MODULE_ICONS_GOOGLE_LIGHT" + file="images/module_icons/google_light.svg" + compress="gzip" + type="BINDATA" /> + <include name="IDR_NUX_MODULE_ICONS_SET_DEFAULT_DARK" + file="images/module_icons/set_default_dark.svg" + compress="gzip" + type="BINDATA" /> + <include name="IDR_NUX_MODULE_ICONS_SET_DEFAULT_LIGHT" + file="images/module_icons/set_default_light.svg" + compress="gzip" + type="BINDATA" /> + <include name="IDR_NUX_MODULE_ICONS_WALLPAPER_DARK" + file="images/module_icons/wallpaper_dark.svg" + compress="gzip" + type="BINDATA" /> + <include name="IDR_NUX_MODULE_ICONS_WALLPAPER_LIGHT" + file="images/module_icons/wallpaper_light.svg" + compress="gzip" type="BINDATA" /> <include name="IDR_NUX_NTP_BACKGROUND_THUMBNAIL_ART" - file="images\ntp_thumbnails\art.jpg" + file="images/ntp_thumbnails/art.jpg" type="BINDATA" /> <include name="IDR_NUX_NTP_BACKGROUND_THUMBNAIL_CITYSCAPE" - file="images\ntp_thumbnails\cityscape.jpg" + file="images/ntp_thumbnails/cityscape.jpg" type="BINDATA" /> <include name="IDR_NUX_NTP_BACKGROUND_THUMBNAIL_EARTH" - file="images\ntp_thumbnails\earth.jpg" + file="images/ntp_thumbnails/earth.jpg" type="BINDATA" /> <include name="IDR_NUX_NTP_BACKGROUND_THUMBNAIL_GEOMETRIC_SHAPES" - file="images\ntp_thumbnails\geometric_shapes.jpg" + file="images/ntp_thumbnails/geometric_shapes.jpg" type="BINDATA" /> <include name="IDR_NUX_NTP_BACKGROUND_THUMBNAIL_LANDSCAPE" - file="images\ntp_thumbnails\landscape.jpg" - type="BINDATA" /> - <include name="IDR_NUX_SET_AS_DEFAULT_LOGO_1X" - file="images\set_as_default_1x.png" - type="BINDATA" /> - <include name="IDR_NUX_SET_AS_DEFAULT_LOGO_2X" - file="images\set_as_default_2x.png" + file="images/ntp_thumbnails/landscape.jpg" type="BINDATA" /> <include name="IDR_NUX_SET_DEFAULT_DARK" file="images\set_default_dark.svg" @@ -122,31 +130,31 @@ compress="gzip" type="BINDATA" /> <include name="IDR_WELCOME_ONBOARDING_WELCOME_IMAGES_BACKGROUND_SVGS_BLUE_CIRCLE_SVG" - file="images\background_svgs\blue_circle.svg" + file="images/background_svgs/blue_circle.svg" compress="gzip" type="BINDATA" /> <include name="IDR_WELCOME_ONBOARDING_WELCOME_IMAGES_BACKGROUND_SVGS_GREEN_RECTANGLE_SVG" - file="images\background_svgs\green_rectangle.svg" + file="images/background_svgs/green_rectangle.svg" compress="gzip" type="BINDATA" /> <include name="IDR_WELCOME_ONBOARDING_WELCOME_IMAGES_BACKGROUND_SVGS_GREY_OVAL_SVG" - file="images\background_svgs\grey_oval.svg" + file="images/background_svgs/grey_oval.svg" compress="gzip" type="BINDATA" /> <include name="IDR_WELCOME_ONBOARDING_WELCOME_IMAGES_BACKGROUND_SVGS_GREY_ROUNDED_RECTANGLE_SVG" - file="images\background_svgs\grey_rounded_rectangle.svg" + file="images/background_svgs/grey_rounded_rectangle.svg" compress="gzip" type="BINDATA" /> <include name="IDR_WELCOME_ONBOARDING_WELCOME_IMAGES_BACKGROUND_SVGS_RED_TRIANGLE_SVG" - file="images\background_svgs\red_triangle.svg" + file="images/background_svgs/red_triangle.svg" compress="gzip" type="BINDATA" /> <include name="IDR_WELCOME_ONBOARDING_WELCOME_IMAGES_BACKGROUND_SVGS_YELLOW_DOTS_SVG" - file="images\background_svgs\yellow_dots.svg" + file="images/background_svgs/yellow_dots.svg" compress="gzip" type="BINDATA" /> <include name="IDR_WELCOME_ONBOARDING_WELCOME_IMAGES_BACKGROUND_SVGS_YELLOW_SEMICIRCLE_SVG" - file="images\background_svgs\yellow_semicircle.svg" + file="images/background_svgs/yellow_semicircle.svg" compress="gzip" type="BINDATA" /> </includes> @@ -182,67 +190,67 @@ compress="gzip" preprocess="true"/> <structure name="IDR_NUX_SHARED_APP_CHOOSER_HTML" - file="shared\app_chooser.html" + file="shared/app_chooser.html" compress="gzip" type="chrome_html" /> <structure name="IDR_NUX_SHARED_APP_CHOOSER_JS" - file="shared\app_chooser.js" + file="shared/app_chooser.js" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_ACTION_LINK_STYLE_JS" - file="shared\action_link_style.js" + file="shared/action_link_style.js" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_ACTION_LINK_STYLE_CSS_HTML" - file="shared\action_link_style_css.html" + file="shared/action_link_style_css.html" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_BOOKMARK_PROXY_HTML" - file="shared\bookmark_proxy.html" + file="shared/bookmark_proxy.html" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_BOOKMARK_PROXY_JS" - file="shared\bookmark_proxy.js" + file="shared/bookmark_proxy.js" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_CHOOSER_SHARED_CSS" - file="shared\chooser_shared_css.html" + file="shared/chooser_shared_css.html" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_I18N_SETUP_HTML" - file="shared\i18n_setup.html" + file="shared/i18n_setup.html" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_MODULE_METRICS_PROXY_HTML" - file="shared\module_metrics_proxy.html" + file="shared/module_metrics_proxy.html" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_MODULE_METRICS_PROXY_JS" - file="shared\module_metrics_proxy.js" + file="shared/module_metrics_proxy.js" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_NAVI_COLORS_CSS" - file="shared\navi_colors_css.html" + file="shared/navi_colors_css.html" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_ONBOARDING_BACKGROUND_HTML" - file="shared\onboarding_background.html" + file="shared/onboarding_background.html" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_ONBOARDING_BACKGROUND_JS" - file="shared\onboarding_background.js" + file="shared/onboarding_background.js" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_STEP_INDICATOR_HTML" - file="shared\step_indicator.html" + file="shared/step_indicator.html" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_STEP_INDICATOR_JS" - file="shared\step_indicator.js" + file="shared/step_indicator.js" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_SPLASH_PAGES_SHARED_CSS" - file="shared\splash_pages_shared_css.html" + file="shared/splash_pages_shared_css.html" compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SIGNIN_VIEW_HTML" @@ -301,73 +309,73 @@ <!-- NUX Email--> <structure name="IDR_EMAIL_APP_PROXY_HTML" - file="email\email_app_proxy.html" + file="email/email_app_proxy.html" compress="gzip" type="chrome_html" /> <structure name="IDR_EMAIL_APP_PROXY_JS" - file="email\email_app_proxy.js" + file="email/email_app_proxy.js" compress="gzip" type="chrome_html" /> <structure name="IDR_NUX_EMAIL_HTML" - file="email\nux_email.html" + file="email/nux_email.html" compress="gzip" type="chrome_html" /> <structure name="IDR_NUX_EMAIL_JS" - file="email\nux_email.js" + file="email/nux_email.js" compress="gzip" type="chrome_html" /> <!-- NUX Google apps--> <structure name="IDR_NUX_GOOGLE_APPS_HTML" - file="google_apps\nux_google_apps.html" + file="google_apps/nux_google_apps.html" compress="gzip" type="chrome_html" /> <structure name="IDR_NUX_GOOGLE_APPS_JS" - file="google_apps\nux_google_apps.js" + file="google_apps/nux_google_apps.js" compress="gzip" type="chrome_html" /> <structure name="IDR_GOOGLE_APP_PROXY_HTML" - file="google_apps\google_app_proxy.html" + file="google_apps/google_app_proxy.html" compress="gzip" type="chrome_html" /> <structure name="IDR_GOOGLE_APP_PROXY_JS" - file="google_apps\google_app_proxy.js" + file="google_apps/google_app_proxy.js" compress="gzip" type="chrome_html" /> <structure name="IDR_NUX_SET_AS_DEFAULT_HTML" - file="set_as_default\nux_set_as_default.html" + file="set_as_default/nux_set_as_default.html" type="chrome_html" compress="gzip" preprocess="true"/> <structure name="IDR_NUX_SET_AS_DEFAULT_JS" - file="set_as_default\nux_set_as_default.js" + file="set_as_default/nux_set_as_default.js" type="chrome_html" compress="gzip" preprocess="true"/> <structure name="IDR_NUX_SET_AS_DEFAULT_PROXY_HTML" - file="set_as_default\nux_set_as_default_proxy.html" + file="set_as_default/nux_set_as_default_proxy.html" compress="gzip" type="chrome_html" /> <structure name="IDR_NUX_SET_AS_DEFAULT_PROXY_JS" - file="set_as_default\nux_set_as_default_proxy.js" + file="set_as_default/nux_set_as_default_proxy.js" compress="gzip" type="chrome_html" /> <!-- NUX NTP background--> <structure name="IDR_NUX_NTP_BACKGROUND_HTML" - file="ntp_background\nux_ntp_background.html" + file="ntp_background/nux_ntp_background.html" compress="gzip" type="chrome_html" /> <structure name="IDR_NUX_NTP_BACKGROUND_JS" - file="ntp_background\nux_ntp_background.js" + file="ntp_background/nux_ntp_background.js" compress="gzip" type="chrome_html" /> <structure name="IDR_NUX_NTP_BACKGROUND_PROXY_HTML" - file="ntp_background\ntp_background_proxy.html" + file="ntp_background/ntp_background_proxy.html" compress="gzip" type="chrome_html" /> <structure name="IDR_NUX_NTP_BACKGROUND_PROXY_JS" - file="ntp_background\ntp_background_proxy.js" + file="ntp_background/ntp_background_proxy.js" compress="gzip" type="chrome_html" /> </structures>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html index 303d6e2..aca9698 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
@@ -21,15 +21,17 @@ } .logo { - content: -webkit-image-set( - url(../images/set_as_default_1x.png) 1x, - url(../images/set_as_default_2x.png) 2x); + content: url(../images/module_icons/set_default_light.svg); display: inline-block; height: 38px; margin-bottom: 16px; width: 42px; } + :host-context([dark]) .logo { + content: url(../images/module_icons/set_default_dark.svg); + } + .illustration { content: url(../images/set_default_light.svg); margin: auto;
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_service_browsertest.cc b/chrome/browser/safe_browsing/download_protection/download_protection_service_browsertest.cc new file mode 100644 index 0000000..9d399e2 --- /dev/null +++ b/chrome/browser/safe_browsing/download_protection/download_protection_service_browsertest.cc
@@ -0,0 +1,121 @@ +// 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/files/file_path.h" +#include "base/path_service.h" +#include "base/run_loop.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/safe_browsing/proto/csd.pb.h" +#include "components/safe_browsing/web_ui/safe_browsing_ui.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/download_manager.h" +#include "content/public/browser/site_instance.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/download_test_observer.h" +#include "crypto/sha2.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/window_open_disposition.h" + +namespace safe_browsing { + +class DownloadProtectionServiceBrowserTest : public InProcessBrowserTest { + protected: + base::FilePath GetTestDataDirectory() { + base::FilePath test_file_directory; + base::PathService::Get(chrome::DIR_TEST_DATA, &test_file_directory); + return test_file_directory; + } + + void DownloadAndWait(GURL url) { + content::DownloadManager* download_manager = + content::BrowserContext::GetDownloadManager(browser()->profile()); + content::DownloadTestObserverTerminal observer( + download_manager, 1, + content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_IGNORE); + + // This call will block until the navigation completes, but will not wait + // for the download to finish. + ui_test_utils::NavigateToURLWithDisposition( + browser(), url, WindowOpenDisposition::CURRENT_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + + observer.WaitForFinished(); + } + + // The hash of 10 A's, followed by a newline. Was generated as follows: + // echo "AAAAAAAAAA" > a.zip + // sha256sum a.zip + static const uint8_t kAZipDigest[]; + + // The hash of 9 B's, followed by a newline. Was generated as follows: + // echo "BBBBBBBBB" > a.zip + // sha256sum a.zip + static const uint8_t kBZipDigest[]; +}; + +const uint8_t DownloadProtectionServiceBrowserTest::kAZipDigest[] = { + 0x70, 0x5d, 0x29, 0x0c, 0x12, 0x89, 0x59, 0x01, 0xf8, 0x09, 0xf6, + 0xc2, 0xfe, 0x77, 0x2a, 0x94, 0xdb, 0x51, 0x81, 0xd7, 0x26, 0x46, + 0x4d, 0x84, 0x06, 0x82, 0x10, 0x6f, 0x4a, 0x93, 0x4b, 0x87}; + +const uint8_t DownloadProtectionServiceBrowserTest::kBZipDigest[] = { + 0x94, 0x1e, 0x17, 0x3f, 0x62, 0xbc, 0x04, 0x50, 0x6f, 0xeb, 0xb5, + 0xe2, 0x8c, 0x38, 0x6c, 0xb2, 0x11, 0x91, 0xf3, 0x77, 0xa7, 0x2c, + 0x11, 0x92, 0xe0, 0x25, 0xb0, 0xe5, 0xc7, 0x70, 0x3b, 0x23}; + +IN_PROC_BROWSER_TEST_F(DownloadProtectionServiceBrowserTest, VerifyZipHash) { + embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory()); + ASSERT_TRUE(embedded_test_server()->Start()); + + WebUIInfoSingleton::GetInstance()->AddListenerForTesting(); + + GURL url = embedded_test_server()->GetURL( + "/safe_browsing/download_protection/zipfile_two_archives.zip"); + DownloadAndWait(url); + + const std::vector<std::unique_ptr<ClientDownloadRequest>>& requests = + WebUIInfoSingleton::GetInstance()->client_download_requests_sent(); + + ASSERT_EQ(1u, requests.size()); + ASSERT_EQ(2, requests[0]->archived_binary_size()); + + EXPECT_EQ("a.zip", requests[0]->archived_binary(0).file_basename()); + EXPECT_EQ(std::string(kAZipDigest, kAZipDigest + crypto::kSHA256Length), + requests[0]->archived_binary(0).digests().sha256()); + + EXPECT_EQ("b.zip", requests[0]->archived_binary(1).file_basename()); + EXPECT_EQ(std::string(kBZipDigest, kBZipDigest + crypto::kSHA256Length), + requests[0]->archived_binary(1).digests().sha256()); +} + +IN_PROC_BROWSER_TEST_F(DownloadProtectionServiceBrowserTest, VerifyRarHash) { + embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory()); + ASSERT_TRUE(embedded_test_server()->Start()); + + WebUIInfoSingleton::GetInstance()->AddListenerForTesting(); + + GURL url = + embedded_test_server()->GetURL("/safe_browsing/rar/has_two_archives.rar"); + DownloadAndWait(url); + + const std::vector<std::unique_ptr<ClientDownloadRequest>>& requests = + WebUIInfoSingleton::GetInstance()->client_download_requests_sent(); + + ASSERT_EQ(1u, requests.size()); + ASSERT_EQ(2, requests[0]->archived_binary_size()); + + EXPECT_EQ("a.zip", requests[0]->archived_binary(0).file_basename()); + EXPECT_EQ(std::string(kAZipDigest, kAZipDigest + crypto::kSHA256Length), + requests[0]->archived_binary(0).digests().sha256()); + + EXPECT_EQ("b.zip", requests[0]->archived_binary(1).file_basename()); + EXPECT_EQ(std::string(kBZipDigest, kBZipDigest + crypto::kSHA256Length), + requests[0]->archived_binary(1).digests().sha256()); +} + +} // namespace safe_browsing
diff --git a/chrome/browser/translate/android/translate_bridge.cc b/chrome/browser/translate/android/translate_bridge.cc index a0f41d3..f9ca78e 100644 --- a/chrome/browser/translate/android/translate_bridge.cc +++ b/chrome/browser/translate/android/translate_bridge.cc
@@ -3,9 +3,14 @@ // found in the LICENSE file. #include "base/android/jni_string.h" +#include "chrome/browser/language/language_model_manager_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/translate/chrome_translate_client.h" +#include "chrome/browser/translate/translate_service.h" +#include "components/language/core/browser/language_model.h" +#include "components/language/core/browser/language_model_manager.h" #include "components/language/core/common/language_experiments.h" -#include "components/translate/content/browser/content_translate_driver.h" #include "components/translate/core/browser/translate_manager.h" #include "components/translate/core/browser/translate_prefs.h" #include "content/public/browser/web_contents.h" @@ -73,3 +78,55 @@ DCHECK(client); client->SetPredefinedTargetLanguage(translate_language); } + +// Returns the preferred target language to translate into for this user. +static base::android::ScopedJavaLocalRef<jstring> +JNI_TranslateBridge_GetTargetLanguage(JNIEnv* env) { + Profile* profile = ProfileManager::GetActiveUserProfile(); + language::LanguageModel* language_model = + LanguageModelManagerFactory::GetForBrowserContext(profile) + ->GetPrimaryModel(); + DCHECK(language_model); + PrefService* pref_service = profile->GetPrefs(); + std::string target_language = + TranslateService::GetTargetLanguage(pref_service, language_model); + DCHECK(!target_language.empty()); + base::android::ScopedJavaLocalRef<jstring> j_target_language = + base::android::ConvertUTF8ToJavaString(env, target_language); + return j_target_language; +} + +// Determines whether the given language is blocked for translation. +static jboolean JNI_TranslateBridge_IsBlockedLanguage( + JNIEnv* env, + const base::android::JavaParamRef<jstring>& j_language_string) { + std::string language_we_might_block = + ConvertJavaStringToUTF8(env, j_language_string); + Profile* profile = ProfileManager::GetActiveUserProfile(); + PrefService* pref_service = profile->GetPrefs(); + std::unique_ptr<translate::TranslatePrefs> translate_prefs = + ChromeTranslateClient::CreateTranslatePrefs(pref_service); + DCHECK(translate_prefs); + return translate_prefs->IsBlockedLanguage(language_we_might_block); +} + +// Gets all the model languages and calls back to the Java +// TranslateBridge#addModelLanguageToSet once for each language. +static void JNI_TranslateBridge_GetModelLanguages( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& set) { + Profile* profile = ProfileManager::GetActiveUserProfile(); + language::LanguageModel* language_model = + LanguageModelManagerFactory::GetForBrowserContext(profile) + ->GetPrimaryModel(); + DCHECK(language_model); + std::string model_languages; + std::vector<language::LanguageModel::LanguageDetails> languageDetails = + language_model->GetLanguages(); + DCHECK(!languageDetails.empty()); + for (const auto& details : languageDetails) { + Java_TranslateBridge_addModelLanguageToSet( + env, set, + base::android::ConvertUTF8ToJavaString(env, details.lang_code)); + } +}
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index dcc5061..3de926fc 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1550,6 +1550,16 @@ "webui/chromeos/bluetooth_dialog_localized_strings_provider.h", "webui/chromeos/bluetooth_pairing_dialog.cc", "webui/chromeos/bluetooth_pairing_dialog.h", + "webui/chromeos/cellular_setup/cellular_setup_dialog.cc", + "webui/chromeos/cellular_setup/cellular_setup_dialog.h", + "webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.cc", + "webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.h", + "webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc", + "webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.h", + "webui/chromeos/cellular_setup/mobile_setup_dialog.cc", + "webui/chromeos/cellular_setup/mobile_setup_dialog.h", + "webui/chromeos/cellular_setup/mobile_setup_ui.cc", + "webui/chromeos/cellular_setup/mobile_setup_ui.h", "webui/chromeos/certificate_manager_dialog_ui.cc", "webui/chromeos/certificate_manager_dialog_ui.h", "webui/chromeos/cryptohome_ui.cc", @@ -1684,10 +1694,6 @@ "webui/chromeos/login/welcome_screen_handler.h", "webui/chromeos/login/wrong_hwid_screen_handler.cc", "webui/chromeos/login/wrong_hwid_screen_handler.h", - "webui/chromeos/mobile_setup_dialog.cc", - "webui/chromeos/mobile_setup_dialog.h", - "webui/chromeos/mobile_setup_ui.cc", - "webui/chromeos/mobile_setup_ui.h", "webui/chromeos/multidevice_setup/multidevice_setup_dialog.cc", "webui/chromeos/multidevice_setup/multidevice_setup_dialog.h", "webui/chromeos/multidevice_setup/multidevice_setup_handler.cc", @@ -2631,8 +2637,6 @@ "views/location_bar/location_bar_bubble_delegate_view.h", "views/location_bar/location_bar_layout.cc", "views/location_bar/location_bar_layout.h", - "views/location_bar/location_bar_separator_view.cc", - "views/location_bar/location_bar_separator_view.h", "views/location_bar/location_bar_view.cc", "views/location_bar/location_bar_view.h", "views/location_bar/location_icon_view.cc",
diff --git a/chrome/browser/ui/app_list/extension_app_context_menu.cc b/chrome/browser/ui/app_list/extension_app_context_menu.cc index 89df9b0..1c5513f 100644 --- a/chrome/browser/ui/app_list/extension_app_context_menu.cc +++ b/chrome/browser/ui/app_list/extension_app_context_menu.cc
@@ -7,7 +7,6 @@ #include "ash/public/cpp/app_menu_constants.h" #include "base/bind.h" #include "chrome/browser/extensions/context_menu_matcher.h" -#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/menu_manager.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/profiles/profile.h" @@ -54,11 +53,7 @@ // If --enable-new-bookmark-apps is enabled, then only check if // USE_LAUNCH_TYPE_WINDOW is checked, as USE_LAUNCH_TYPE_PINNED (i.e. open // as pinned tab) and fullscreen-by-default windows do not exist. - bool launch_in_window = - extensions::util::IsNewBookmarkAppsEnabled() - ? IsCommandIdChecked(ash::USE_LAUNCH_TYPE_WINDOW) - : !(IsCommandIdChecked(ash::USE_LAUNCH_TYPE_PINNED) || - IsCommandIdChecked(ash::USE_LAUNCH_TYPE_REGULAR)); + bool launch_in_window = IsCommandIdChecked(ash::USE_LAUNCH_TYPE_WINDOW); return launch_in_window ? IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW : IDS_APP_LIST_CONTEXT_MENU_NEW_TAB; } @@ -115,7 +110,7 @@ if (controller()->CanDoShowAppInfoFlow()) { AddContextMenuOption(menu_model, ash::SHOW_APP_INFO, IDS_APP_CONTEXT_MENU_SHOW_INFO); - } + } } } @@ -189,17 +184,13 @@ controller()->DoShowAppInfoFlow(profile(), app_id()); } else if (command_id >= ash::USE_LAUNCH_TYPE_COMMAND_START && command_id < ash::USE_LAUNCH_TYPE_COMMAND_END) { - extensions::LaunchType launch_type = static_cast<extensions::LaunchType>( - command_id - ash::USE_LAUNCH_TYPE_COMMAND_START); - // When bookmark apps are enabled, hosted apps can only toggle between - // LAUNCH_TYPE_WINDOW and LAUNCH_TYPE_REGULAR. - if (extensions::util::IsNewBookmarkAppsEnabled()) { - launch_type = (controller()->GetExtensionLaunchType(profile(), - app_id()) == - extensions::LAUNCH_TYPE_WINDOW) - ? extensions::LAUNCH_TYPE_REGULAR - : extensions::LAUNCH_TYPE_WINDOW; - } + // Hosted apps can only toggle between LAUNCH_TYPE_WINDOW and + // LAUNCH_TYPE_REGULAR. + extensions::LaunchType launch_type = + (controller()->GetExtensionLaunchType(profile(), app_id()) == + extensions::LAUNCH_TYPE_WINDOW) + ? extensions::LAUNCH_TYPE_REGULAR + : extensions::LAUNCH_TYPE_WINDOW; controller()->SetExtensionLaunchType(profile(), app_id(), launch_type); } else if (command_id == ash::OPTIONS) { controller()->ShowOptionsPage(profile(), app_id());
diff --git a/chrome/browser/ui/ash/kiosk_next_shell_client_browsertest.cc b/chrome/browser/ui/ash/kiosk_next_shell_client_browsertest.cc index f87920a..f5be1eca 100644 --- a/chrome/browser/ui/ash/kiosk_next_shell_client_browsertest.cc +++ b/chrome/browser/ui/ash/kiosk_next_shell_client_browsertest.cc
@@ -17,10 +17,12 @@ #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/extensions/component_loader.h" #include "chrome/browser/ui/ash/kiosk_next_shell_client.h" +#include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" #include "chrome/common/extensions/extension_constants.h" #include "components/prefs/pref_service.h" #include "components/user_manager/user.h" +#include "components/user_manager/user_manager.h" #include "content/public/browser/notification_service.h" #include "content/public/test/test_utils.h" #include "extensions/browser/app_window/app_window.h" @@ -96,6 +98,19 @@ EXPECT_TRUE(waiter.WaitForShownWithTimeout(TestTimeouts::action_timeout())); } +IN_PROC_BROWSER_TEST_F(KioskNextShellClientTest, PRE_BrowserNotLaunched) { + LoginAndEnableKioskNextShellPref(); +} + +// Ensures that browser is not launched when feature is enabled and prefs allow. +IN_PROC_BROWSER_TEST_F(KioskNextShellClientTest, BrowserNotLaunched) { + extensions::ComponentLoader::EnableBackgroundExtensionsForTesting(); + Login("username"); + Profile* profile = ProfileHelper::Get()->GetProfileByUser( + user_manager::UserManager::Get()->GetActiveUser()); + EXPECT_EQ(0u, chrome::GetBrowserCount(profile)); +} + // Checks that the Kiosk Next Home window does not launch in sign-in when // its pref is disabled. IN_PROC_BROWSER_TEST_F(KioskNextShellClientTest, KioskNextShellNotLaunched) {
diff --git a/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc index 73bd4c5e..454b57d 100644 --- a/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc
@@ -123,14 +123,11 @@ SetLaunchType(extensions::LAUNCH_TYPE_REGULAR); break; case ash::LAUNCH_TYPE_WINDOW: { - extensions::LaunchType launch_type = extensions::LAUNCH_TYPE_WINDOW; - // With bookmark apps enabled, hosted apps can only toggle between - // LAUNCH_WINDOW and LAUNCH_REGULAR. - if (extensions::util::IsNewBookmarkAppsEnabled()) { - launch_type = GetLaunchType() == extensions::LAUNCH_TYPE_WINDOW - ? extensions::LAUNCH_TYPE_REGULAR - : extensions::LAUNCH_TYPE_WINDOW; - } + // Hosted apps can only toggle between LAUNCH_WINDOW and LAUNCH_REGULAR. + extensions::LaunchType launch_type = + GetLaunchType() == extensions::LAUNCH_TYPE_WINDOW + ? extensions::LAUNCH_TYPE_REGULAR + : extensions::LAUNCH_TYPE_WINDOW; SetLaunchType(launch_type); break; }
diff --git a/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc b/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc index 4b28e031..bdbba5e 100644 --- a/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc +++ b/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc
@@ -75,14 +75,12 @@ // Bookmark app windows should match their launch url extension despite // their web extents. - if (extensions::util::IsNewBookmarkAppsEnabled()) { - for (const auto& i : extensions) { - if (i.get()->from_bookmark() && - extensions::IsInNavigationScopeForLaunchUrl( - extensions::AppLaunchInfo::GetLaunchWebURL(i.get()), url) && - !extensions::LaunchesInWindow(profile, i.get())) { - return i.get(); - } + for (const auto& i : extensions) { + if (i.get()->from_bookmark() && + extensions::IsInNavigationScopeForLaunchUrl( + extensions::AppLaunchInfo::GetLaunchWebURL(i.get()), url) && + !extensions::LaunchesInWindow(profile, i.get())) { + return i.get(); } } return nullptr;
diff --git a/chrome/browser/ui/ash/network/network_connect_delegate_chromeos.cc b/chrome/browser/ui/ash/network/network_connect_delegate_chromeos.cc index 0c054a32..79da39cb 100644 --- a/chrome/browser/ui/ash/network/network_connect_delegate_chromeos.cc +++ b/chrome/browser/ui/ash/network/network_connect_delegate_chromeos.cc
@@ -8,7 +8,7 @@ #include "chrome/browser/ui/ash/network/enrollment_dialog_view.h" #include "chrome/browser/ui/ash/network/network_state_notifier.h" #include "chrome/browser/ui/ash/system_tray_client.h" -#include "chrome/browser/ui/webui/chromeos/mobile_setup_dialog.h" +#include "chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.h" namespace { @@ -50,7 +50,7 @@ const std::string& network_id) { if (!IsUIAvailable()) return; - chromeos::MobileSetupDialog::ShowByNetworkId(network_id); + chromeos::cellular_setup::OpenCellularSetupDialog(network_id); } void NetworkConnectDelegateChromeOS::ShowNetworkConnectError(
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index aed3350..03d5f11 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -34,7 +34,6 @@ #include "chrome/browser/devtools/devtools_window_testing.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/first_run/first_run.h" #include "chrome/browser/lifetime/application_lifetime.h" @@ -1216,19 +1215,14 @@ chrome::startup::IS_FIRST_RUN : chrome::startup::IS_NOT_FIRST_RUN; StartupBrowserCreatorImpl launch(base::FilePath(), command_line, first_run); - bool new_bookmark_apps_enabled = extensions::util::IsNewBookmarkAppsEnabled(); - - // If the new bookmark app flow is enabled, the app should open as an tab. - // Otherwise the app should open as an app window. - EXPECT_EQ(!new_bookmark_apps_enabled, - launch.OpenApplicationWindow(browser()->profile())); - EXPECT_EQ(new_bookmark_apps_enabled, - launch.OpenApplicationTab(browser()->profile())); + // The app should open as a tab. + EXPECT_FALSE(launch.OpenApplicationWindow(browser()->profile())); + EXPECT_TRUE(launch.OpenApplicationTab(browser()->profile())); // Check that a the number of browsers and tabs is correct. unsigned int expected_browsers = 1; int expected_tabs = 1; - new_bookmark_apps_enabled ? expected_tabs++ : expected_browsers++; + expected_tabs++; EXPECT_EQ(expected_browsers, chrome::GetBrowserCount(browser()->profile())); EXPECT_EQ(expected_tabs, browser()->tab_strip_model()->count());
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index fac29c30..409fb26 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/defaults.h" #include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/profiles/profile.h" @@ -934,10 +933,8 @@ UpdateShowSyncState(true); // Navigation commands - command_updater_.UpdateCommandEnabled( - IDC_HOME, - normal_window || - (extensions::util::IsNewBookmarkAppsEnabled() && browser_->is_app())); + command_updater_.UpdateCommandEnabled(IDC_HOME, + normal_window || browser_->is_app()); const bool is_experimental_hosted_app = extensions::HostedAppBrowserController::IsForExperimentalHostedAppBrowser(
diff --git a/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm b/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm index 791746d5..d1a5e13 100644 --- a/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm +++ b/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm
@@ -12,7 +12,6 @@ #import "base/mac/scoped_objc_class_swizzler.h" #include "base/macros.h" #include "base/strings/sys_string_conversions.h" -#include "base/test/scoped_feature_list.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h" #include "chrome/browser/apps/platform_apps/app_browsertest_util.h" @@ -43,12 +42,6 @@ hosted_app_(nullptr), initial_menu_item_count_(0) {} - // testing::Test: - void SetUp() override { - scoped_feature_list_.InitAndEnableFeature(features::kBookmarkApps); - PlatformAppBrowserTest::SetUp(); - } - // Start testing apps and wait for them to launch. |flags| is a bitmask of // AvailableApps. void SetUpApps(int flags) { @@ -136,8 +129,6 @@ NSUInteger initial_menu_item_count_; private: - base::test::ScopedFeatureList scoped_feature_list_; - DISALLOW_COPY_AND_ASSIGN(AppShimMenuControllerBrowserTest); };
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc index 4776c0f5..4be0617 100644 --- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc +++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -282,9 +282,6 @@ enabled_features.push_back(features::kDesktopPWAWindowing); } else { disabled_features.push_back(features::kDesktopPWAWindowing); -#if defined(OS_MACOSX) - enabled_features.push_back(features::kBookmarkApps); -#endif } auto& features = use_custom_tab_flag ? enabled_features : disabled_features;
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.cc b/chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.cc index 3d5d03aa..9600709 100644 --- a/chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.cc +++ b/chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.cc
@@ -38,7 +38,6 @@ } void ChromeOmniboxEditController::OnInputInProgress(bool in_progress) { - GetLocationBarModel()->set_input_in_progress(in_progress); UpdateWithoutTabRestore(); }
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc index fc57da6b..1aa0191 100644 --- a/chrome/browser/ui/startup/startup_browser_creator.cc +++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -69,8 +69,11 @@ #include "printing/buildflags/buildflags.h" #if defined(OS_CHROMEOS) +#include "ash/public/cpp/ash_features.h" +#include "ash/public/cpp/ash_pref_names.h" #include "chrome/browser/chromeos/app_mode/app_launch_utils.h" #include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chromeos/constants/chromeos_switches.h" #include "chromeos/cryptohome/cryptohome_parameters.h" @@ -277,6 +280,27 @@ #endif // !defined(OS_CHROMEOS) } +bool IsSilentLaunchEnabled(const base::CommandLine& command_line, + const Profile* profile) { + // Note: This check should have been done in ProcessCmdLineImpl() + // before calling this function. However chromeos/login/login_utils.cc + // calls this function directly (see comments there) so it has to be checked + // again. + bool silent_launch = command_line.HasSwitch(switches::kSilentLaunch); + +#if defined(CHROMEOS) + DCHECK(!chromeos::ProfileHelper::IsSigninProfile(profile)); + if (base::FeatureList::IsEnabled(ash::features::kKioskNextShell)) { + const PrefService* prefs = profile->GetPrefs(); + if (prefs->GetBoolean(ash::prefs::kKioskNextShellEnabled)) { + silent_launch = true; + } + } +#endif + + return silent_launch; +} + } // namespace StartupBrowserCreator::StartupBrowserCreator() @@ -336,13 +360,7 @@ profile = profile->GetOffTheRecordProfile(); #endif - // Note: This check should have been done in ProcessCmdLineImpl() - // before calling this function. However chromeos/login/login_utils.cc - // calls this function directly (see comments there) so it has to be checked - // again. - const bool silent_launch = command_line.HasSwitch(switches::kSilentLaunch); - - if (!silent_launch) { + if (!IsSilentLaunchEnabled(command_line, profile)) { StartupBrowserCreatorImpl lwp(cur_dir, command_line, this, is_first_run); const std::vector<GURL> urls_to_launch = GetURLsFromCommandLine(command_line, cur_dir, profile);
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc index 0881e5ff..2cb6b925 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -22,7 +22,6 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/launch_util.h" #include "chrome/browser/first_run/first_run.h" #include "chrome/browser/infobars/infobar_service.h" @@ -403,11 +402,9 @@ EXPECT_EQ(2, tab_strip->count()); EXPECT_EQ(tab_strip->GetActiveWebContents(), tab_strip->GetWebContentsAt(1)); - // If new bookmark apps are enabled, it should be a standard tabbed window, - // not an app window; otherwise the reverse should be true. - bool new_bookmark_apps_enabled = extensions::util::IsNewBookmarkAppsEnabled(); - EXPECT_EQ(!new_bookmark_apps_enabled, browser()->is_app()); - EXPECT_EQ(new_bookmark_apps_enabled, browser()->is_type_tabbed()); + // It should be a standard tabbed window, not an app window. + EXPECT_FALSE(browser()->is_app()); + EXPECT_TRUE(browser()->is_type_tabbed()); } IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTest, OpenAppShortcutWindowPref) {
diff --git a/chrome/browser/ui/thumbnails/thumbnail_page_event_adapter.cc b/chrome/browser/ui/thumbnails/thumbnail_page_event_adapter.cc index 1dfa7ce..3af5260 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_page_event_adapter.cc +++ b/chrome/browser/ui/thumbnails/thumbnail_page_event_adapter.cc
@@ -77,6 +77,11 @@ observer.PageLoadStarted(); } +void ThumbnailPageEventAdapter::DidFirstVisuallyNonEmptyPaint() { + for (auto& observer : observers_) + observer.PagePainted(); +} + void ThumbnailPageEventAdapter::DidFinishLoad( content::RenderFrameHost* render_frame_host, const GURL& validated_url) {
diff --git a/chrome/browser/ui/thumbnails/thumbnail_page_event_adapter.h b/chrome/browser/ui/thumbnails/thumbnail_page_event_adapter.h index 7df0da26..4314772 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_page_event_adapter.h +++ b/chrome/browser/ui/thumbnails/thumbnail_page_event_adapter.h
@@ -41,6 +41,7 @@ void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; void DocumentAvailableInMainFrame() override; + void DidFirstVisuallyNonEmptyPaint() override; void DidFinishLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url) override; void DidFailLoad(content::RenderFrameHost* render_frame_host,
diff --git a/chrome/browser/ui/thumbnails/thumbnail_page_observer.h b/chrome/browser/ui/thumbnails/thumbnail_page_observer.h index 2255ee3..70c03a2b 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_page_observer.h +++ b/chrome/browser/ui/thumbnails/thumbnail_page_observer.h
@@ -32,6 +32,9 @@ // Called when the page/tab's visibility changes. virtual void VisibilityChanged(bool visible) = 0; + // Called when the page is painted for the first time. + virtual void PagePainted() = 0; + // Called when a page begins to load. virtual void PageLoadStarted() = 0;
diff --git a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc index 21185ea..5665176 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc +++ b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc
@@ -62,6 +62,10 @@ web_contents()->GetVisibleURL()); } +void ThumbnailTabHelper::PagePainted() { + page_painted_ = true; +} + void ThumbnailTabHelper::PageLoadFinished() { TransitionLoadingState(LoadingState::kLoadFinished, web_contents()->GetVisibleURL()); @@ -73,9 +77,7 @@ // tab did when the user last visited it. const bool was_visible = view_is_visible_; view_is_visible_ = visible; - if (!was_visible && visible) { - last_visible_start_time_ = base::TimeTicks::Now(); - } else if (was_visible && !visible) { + if (was_visible && !visible) { StartThumbnailCapture(); } } @@ -97,11 +99,9 @@ if (web_contents()->GetVisibleURL().is_empty()) return; - // Don't capture pages that have been visible for a short time (e.g. during a - // tab scrub). - base::TimeTicks start_time = base::TimeTicks::Now(); - constexpr base::TimeDelta kMinVisibleTime = base::TimeDelta::FromSeconds(2); - if (start_time - last_visible_start_time_ < kMinVisibleTime) + // Don't capture pages that have not been loading and visible long enough to + // actually paint. + if (!page_painted_) return; content::RenderWidgetHostView* const source_view = @@ -128,7 +128,7 @@ source_view->CopyFromSurface( copy_info.copy_rect, copy_info.target_size, base::BindOnce(&ThumbnailTabHelper::ProcessCapturedThumbnail, - weak_factory_.GetWeakPtr(), start_time)); + weak_factory_.GetWeakPtr(), base::TimeTicks::Now())); } void ThumbnailTabHelper::ProcessCapturedThumbnail( @@ -176,6 +176,7 @@ if (!is_similar_url) { current_url_ = url; ClearThumbnail(); + page_painted_ = false; loading_state_ = state; } else { loading_state_ = std::max(loading_state_, state);
diff --git a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h index b540367..d55098d 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h +++ b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h
@@ -26,6 +26,7 @@ // ThumbnailWebContentsObserver: void TopLevelNavigationStarted(const GURL& url) override; void TopLevelNavigationEnded(const GURL& url) override; + void PagePainted() override; void PageLoadStarted() override; void PageLoadFinished() override; void VisibilityChanged(bool visible) override; @@ -62,8 +63,7 @@ // VisibilityChanged() for more information. bool view_is_visible_; // set in constructor - // When the page last became visible. - base::TimeTicks last_visible_start_time_; + bool page_painted_ = false; LoadingState loading_state_ = LoadingState::kNone; GURL current_url_;
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc index ea6d9c8..316e5b0 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.cc +++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -206,9 +206,7 @@ // - Option to enable profiling. void ToolsMenuModel::Build(Browser* browser) { AddItemWithStringId(IDC_SAVE_PAGE, IDS_SAVE_PAGE); - - if (extensions::util::IsNewBookmarkAppsEnabled()) - AddItemWithStringId(IDC_CREATE_SHORTCUT, IDS_ADD_TO_OS_LAUNCH_SURFACE); + AddItemWithStringId(IDC_CREATE_SHORTCUT, IDS_ADD_TO_OS_LAUNCH_SURFACE); AddSeparator(ui::NORMAL_SEPARATOR); AddItemWithStringId(IDC_CLEAR_BROWSING_DATA, IDS_CLEAR_BROWSING_DATA); @@ -766,8 +764,7 @@ AddItemWithStringId(IDC_FIND, IDS_FIND); - if (extensions::util::IsNewBookmarkAppsEnabled() && - banners::AppBannerManager::IsExperimentalAppBannersEnabled()) { + if (banners::AppBannerManager::IsExperimentalAppBannersEnabled()) { const extensions::Extension* pwa = base::FeatureList::IsEnabled(features::kDesktopPWAWindowing) ? extensions::util::GetPwaForSecureActiveTab(browser_)
diff --git a/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc b/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc index 1ed3931..1c53b55 100644 --- a/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc +++ b/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc
@@ -468,10 +468,19 @@ EXPECT_EQ(0, back_model->GetItemCount()); EXPECT_FALSE(back_model->ItemHasCommand(1)); + // Note: Multiple navigations to the same URL in a row have to be + // renderer-initiated. If they were browser-initiated, the + // NavigationController would treat them as reloads. LoadURLAndUpdateState("http://www.a.com/1", "A B"); - LoadURLAndUpdateState("http://www.a.com/1", "A & B"); + NavigationSimulator::NavigateAndCommitFromDocument(GURL("http://www.a.com/1"), + main_rfh()); + web_contents()->UpdateTitleForEntry(controller().GetLastCommittedEntry(), + base::UTF8ToUTF16("A & B")); LoadURLAndUpdateState("http://www.a.com/2", "A && B"); - LoadURLAndUpdateState("http://www.a.com/2", "A &&& B"); + NavigationSimulator::NavigateAndCommitFromDocument(GURL("http://www.a.com/2"), + main_rfh()); + web_contents()->UpdateTitleForEntry(controller().GetLastCommittedEntry(), + base::UTF8ToUTF16("A &&& B")); LoadURLAndUpdateState("http://www.a.com/3", ""); EXPECT_EQ(6, back_model->GetItemCount());
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_browsertest.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_browsertest.cc index d8891a2..3c670af 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_browsertest.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_browsertest.cc
@@ -15,11 +15,6 @@ #include "chrome/browser/ui/test/test_browser_dialog.h" #include "chrome/test/base/testing_profile.h" -#if defined(OS_MACOSX) -#include "base/command_line.h" -#include "chrome/common/chrome_switches.h" -#endif - class AppInfoDialogBrowserTest : public DialogBrowserTest { public: AppInfoDialogBrowserTest() {} @@ -40,13 +35,6 @@ void TearDownOnMainThread() override { extension_environment_ = nullptr; } -#if defined(OS_MACOSX) - // content::BrowserTestBase: - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitch(switches::kEnableAppInfoDialogMac); - } -#endif - private: std::unique_ptr<extensions::TestExtensionEnvironment> extension_environment_; scoped_refptr<const extensions::Extension> extension_;
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc index 97e3deb..2493308 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
@@ -12,9 +12,7 @@ #include "base/callback_forward.h" #include "base/logging.h" #include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" #include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/launch_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" @@ -60,47 +58,14 @@ }; LaunchOptionsComboboxModel::LaunchOptionsComboboxModel() { - if (extensions::util::IsNewBookmarkAppsEnabled()) { - // When bookmark apps are enabled, hosted apps can only toggle between - // LAUNCH_TYPE_WINDOW and LAUNCH_TYPE_REGULAR. - // TODO(sashab): Use a checkbox for this choice instead of combobox. - launch_types_.push_back(extensions::LAUNCH_TYPE_REGULAR); - launch_type_messages_.push_back( - l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_TAB)); - - if (extensions::util::CanHostedAppsOpenInWindows()) { - launch_types_.push_back(extensions::LAUNCH_TYPE_WINDOW); - launch_type_messages_.push_back( - l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_WINDOW)); - } - } else { - launch_types_.push_back(extensions::LAUNCH_TYPE_REGULAR); - launch_type_messages_.push_back( - l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_REGULAR)); - - launch_types_.push_back(extensions::LAUNCH_TYPE_PINNED); - launch_type_messages_.push_back( - l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_PINNED)); - - if (extensions::util::CanHostedAppsOpenInWindows()) { - launch_types_.push_back(extensions::LAUNCH_TYPE_WINDOW); - launch_type_messages_.push_back( - l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_WINDOW)); - } -#if defined(OS_MACOSX) - // Mac does not support standalone web app browser windows or maximize - // unless the new bookmark apps system is enabled. - launch_types_.push_back(extensions::LAUNCH_TYPE_FULLSCREEN); - launch_type_messages_.push_back( - l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_FULLSCREEN)); -#else - // Even though the launch type is Full Screen, it is more accurately - // described as Maximized in non-Mac OSs. - launch_types_.push_back(extensions::LAUNCH_TYPE_FULLSCREEN); - launch_type_messages_.push_back( - l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED)); -#endif - } + // Hosted apps can only toggle between LAUNCH_TYPE_WINDOW and + // LAUNCH_TYPE_REGULAR. + launch_types_.push_back(extensions::LAUNCH_TYPE_REGULAR); + launch_type_messages_.push_back( + l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_TAB)); + launch_types_.push_back(extensions::LAUNCH_TYPE_WINDOW); + launch_type_messages_.push_back( + l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_WINDOW)); } LaunchOptionsComboboxModel::~LaunchOptionsComboboxModel() { @@ -162,8 +127,6 @@ DISTANCE_RELATED_CONTROL_VERTICAL_SMALL))); if (!app_->description().empty()) { - // TODO(sashab): Clip the app's description to 4 lines, and use Label's - // built-in elide behavior to add ellipses at the end: crbug.com/358053 const size_t max_length = 400; base::string16 text = base::UTF8ToUTF16(app_->description()); if (text.length() > max_length) {
diff --git a/chrome/browser/ui/views/extensions/bookmark_app_confirmation_view.cc b/chrome/browser/ui/views/extensions/bookmark_app_confirmation_view.cc index eef0c6a..51f29db9 100644 --- a/chrome/browser/ui/views/extensions/bookmark_app_confirmation_view.cc +++ b/chrome/browser/ui/views/extensions/bookmark_app_confirmation_view.cc
@@ -12,7 +12,6 @@ #include "base/strings/string16.h" #include "base/strings/string_util.h" #include "build/build_config.h" -#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/extensions/web_app_info_image_source.h" #include "chrome/common/chrome_features.h" @@ -87,17 +86,12 @@ layout->AddPaddingRow( views::GridLayout::kFixedSize, layout_provider->GetDistanceMetric(DISTANCE_CONTROL_LIST_VERTICAL)); - - // When CanHostedAppsOpenInWindows() returns false, do not show the open as - // window checkbox to avoid confusing users. - if (extensions::util::CanHostedAppsOpenInWindows()) { - open_as_window_checkbox_ = new views::Checkbox( - l10n_util::GetStringUTF16(IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_WINDOW)); - open_as_window_checkbox_->SetChecked(web_app_info_.open_as_window); - layout->StartRow(views::GridLayout::kFixedSize, kColumnSetId); - layout->SkipColumns(1); - layout->AddView(open_as_window_checkbox_); - } + open_as_window_checkbox_ = new views::Checkbox( + l10n_util::GetStringUTF16(IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_WINDOW)); + open_as_window_checkbox_->SetChecked(web_app_info_.open_as_window); + layout->StartRow(views::GridLayout::kFixedSize, kColumnSetId); + layout->SkipColumns(1); + layout->AddView(open_as_window_checkbox_); title_tf_->SelectAll(true); chrome::RecordDialogCreation(
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc index 83883887..de8f1d0 100644 --- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc +++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
@@ -8,10 +8,8 @@ #include <memory> #include <utility> -#include "base/time/time.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/omnibox/omnibox_theme.h" -#include "chrome/browser/ui/views/location_bar/location_bar_separator_view.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/material_design/material_design_controller.h" @@ -46,6 +44,10 @@ // or label. constexpr int kIconLabelBubbleSpaceBesideSeparator = 8; +// The length of the separator's fade animation. These values are empirical. +constexpr int kIconLabelBubbleFadeInDurationMs = 250; +constexpr int kIconLabelBubbleFadeOutDurationMs = 175; + // The type of tweening for the animation. const gfx::Tween::Type kIconLabelBubbleTweenType = gfx::Tween::EASE_IN_OUT; @@ -56,14 +58,77 @@ const double kIconLabelBubbleOpenTimeFraction = 0.2; } // namespace +////////////////////////////////////////////////////////////////// +// SeparatorView class + +IconLabelBubbleView::SeparatorView::SeparatorView(IconLabelBubbleView* owner) { + DCHECK(owner); + owner_ = owner; + + SetPaintToLayer(); + layer()->SetFillsBoundsOpaquely(false); +} + +void IconLabelBubbleView::SeparatorView::OnPaint(gfx::Canvas* canvas) { + const SkColor background_color = owner_->GetParentBackgroundColor(); + const SkColor separator_color = + SkColorSetA(color_utils::GetColorWithMaxContrast(background_color), 0x69); + const float x = GetLocalBounds().right() - + owner_->GetEndPaddingWithSeparator() - + 1.0f / canvas->image_scale(); + canvas->DrawLine(gfx::PointF(x, GetLocalBounds().y()), + gfx::PointF(x, GetLocalBounds().bottom()), separator_color); +} + +void IconLabelBubbleView::SeparatorView::UpdateOpacity() { + if (!visible()) + return; + + // When using focus rings are visible we should hide the separator instantly + // when the IconLabelBubbleView is focused. Otherwise we should follow the + // inkdrop. + if (owner_->focus_ring() && owner_->HasFocus()) { + layer()->SetOpacity(0.0f); + return; + } + + views::InkDrop* ink_drop = owner_->GetInkDrop(); + DCHECK(ink_drop); + + // If an inkdrop highlight or ripple is animating in or visible, the + // separator should fade out. + views::InkDropState state = ink_drop->GetTargetInkDropState(); + float opacity = 0.0f; + float duration = kIconLabelBubbleFadeOutDurationMs; + if (!ink_drop->IsHighlightFadingInOrVisible() && + (state == views::InkDropState::HIDDEN || + state == views::InkDropState::ACTION_TRIGGERED || + state == views::InkDropState::DEACTIVATED)) { + opacity = 1.0f; + duration = kIconLabelBubbleFadeInDurationMs; + } + + if (disable_animation_for_test_) { + layer()->SetOpacity(opacity); + } else { + ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator()); + animation.SetTransitionDuration( + base::TimeDelta::FromMilliseconds(duration)); + animation.SetTweenType(gfx::Tween::Type::EASE_IN); + layer()->SetOpacity(opacity); + } +} + +////////////////////////////////////////////////////////////////// +// IconLabelBubbleView class + IconLabelBubbleView::IconLabelBubbleView(const gfx::FontList& font_list) : LabelButton(nullptr, base::string16()), - separator_view_(new LocationBarSeparatorView()) { + separator_view_(new SeparatorView(this)) { SetFontList(font_list); SetHorizontalAlignment(gfx::ALIGN_LEFT); - separator_view_->SetBackgroundColor(GetParentBackgroundColor()); - UpdateSeparator(); + separator_view_->SetVisible(ShouldShowSeparator()); AddChildView(separator_view_); set_ink_drop_visible_opacity( @@ -84,7 +149,7 @@ IconLabelBubbleView::~IconLabelBubbleView() {} void IconLabelBubbleView::InkDropAnimationStarted() { - UpdateSeparator(); + separator_view_->UpdateOpacity(); } void IconLabelBubbleView::InkDropRippleAnimationEnded( @@ -99,7 +164,8 @@ void IconLabelBubbleView::SetLabel(const base::string16& label_text) { SetAccessibleName(label_text); label()->SetText(label_text); - UpdateSeparator(); + separator_view_->SetVisible(ShouldShowSeparator()); + separator_view_->UpdateOpacity(); } void IconLabelBubbleView::SetImage(const gfx::ImageSkia& image_skia) { @@ -188,17 +254,17 @@ GetWidthBetweenIconAndSeparator()); label()->SetBounds(label_x, 0, label_width, height()); - const int icon_end = label()->text().empty() ? image()->bounds().right() - : label()->bounds().right(); - // The separator should be the same height as the icons. - const gfx::Size separator_size(kIconLabelBubbleSeparatorWidth, - GetLayoutConstant(LOCATION_BAR_ICON_SIZE)); - const int separator_x = icon_end + GetWidthBetweenIconAndSeparator(); - const int separator_y = (height() - separator_size.height()) / 2; - const gfx::Rect separator_bounds(gfx::Point(separator_x, separator_y), - separator_size); - separator_view_->SetBoundsRect(separator_bounds); + const int separator_height = GetLayoutConstant(LOCATION_BAR_ICON_SIZE); + gfx::Rect separator_bounds(label()->bounds()); + separator_bounds.Inset(0, (separator_bounds.height() - separator_height) / 2); + + float separator_width = + GetWidthBetweenIconAndSeparator() + GetEndPaddingWithSeparator(); + int separator_x = label()->text().empty() ? image()->bounds().right() + : label()->bounds().right(); + separator_view_->SetBounds(separator_x, separator_bounds.y(), separator_width, + separator_height); UpdateHighlightPath(); } @@ -213,7 +279,6 @@ LabelButton::OnNativeThemeChanged(native_theme); SetEnabledTextColors(GetTextColor()); label()->SetBackgroundColor(GetParentBackgroundColor()); - separator_view_->SetBackgroundColor(GetParentBackgroundColor()); SchedulePaint(); } @@ -244,12 +309,12 @@ } void IconLabelBubbleView::OnFocus() { - UpdateSeparator(); + separator_view_->UpdateOpacity(); LabelButton::OnFocus(); } void IconLabelBubbleView::OnBlur() { - UpdateSeparator(); + separator_view_->UpdateOpacity(); LabelButton::OnBlur(); } @@ -445,34 +510,3 @@ focus_ring()->SchedulePaint(); } } - -void IconLabelBubbleView::UpdateSeparator() { - if (!ShouldShowSeparator()) { - separator_view_->SetVisible(false); - return; - } - - separator_view_->SetVisible(true); - - // When using focus rings, we should hide the separator instantly upon - // focus. Otherwise we should follow the inkdrop. - if (focus_ring() && HasFocus()) { - separator_view_->Hide(); - return; - } - - views::InkDrop* const ink_drop = GetInkDrop(); - DCHECK(ink_drop); - - // If an inkdrop highlight or ripple is animating in or visible, the - // separator should fade out. - const views::InkDropState state = ink_drop->GetTargetInkDropState(); - if (!ink_drop->IsHighlightFadingInOrVisible() && - (state == views::InkDropState::HIDDEN || - state == views::InkDropState::ACTION_TRIGGERED || - state == views::InkDropState::DEACTIVATED)) { - separator_view_->FadeIn(); - } else { - separator_view_->FadeOut(); - } -}
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h index 3e09f4a..53ec4df 100644 --- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h +++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
@@ -35,8 +35,6 @@ class ImageView; } -class LocationBarSeparatorView; - // View used to draw a bubble, containing an icon and a label. We use this as a // base for the classes that handle the location icon (including the EV bubble), // tab-to-search UI, and content settings. @@ -46,6 +44,30 @@ public: static constexpr int kTrailingPaddingPreMd = 2; + // A view that draws the separator. + class SeparatorView : public views::View { + public: + explicit SeparatorView(IconLabelBubbleView* owner); + + // views::View: + void OnPaint(gfx::Canvas* canvas) override; + + // Updates the opacity based on the ink drop's state. + void UpdateOpacity(); + + void set_disable_animation_for_test(bool disable_animation_for_test) { + disable_animation_for_test_ = disable_animation_for_test; + } + + private: + // Weak. + IconLabelBubbleView* owner_; + + bool disable_animation_for_test_ = false; + + DISALLOW_COPY_AND_ASSIGN(SeparatorView); + }; + explicit IconLabelBubbleView(const gfx::FontList& font_list); ~IconLabelBubbleView() override; @@ -67,7 +89,7 @@ SkColor GetParentBackgroundColor() const; // Exposed for testing. - LocationBarSeparatorView* separator_view() const { return separator_view_; } + SeparatorView* separator_view() const { return separator_view_; } // Exposed for testing. bool is_animating_label() const { return slide_animation_.is_animating(); } @@ -199,10 +221,8 @@ // bounds and the separator visibility. void UpdateHighlightPath(); - void UpdateSeparator(); - // The contents of the bubble. - LocationBarSeparatorView* separator_view_; + SeparatorView* separator_view_; // The padding of the element that will be displayed after |this|. This value // is relevant for calculating the amount of space to reserve after the
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc index 9fde86a..45a899d2 100644 --- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc +++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc
@@ -7,7 +7,6 @@ #include "base/optional.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/layout_constants.h" -#include "chrome/browser/ui/views/location_bar/location_bar_separator_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_view.h" #include "chrome/test/views/chrome_views_test_base.h" #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/ui/views/location_bar/location_bar_separator_view.cc b/chrome/browser/ui/views/location_bar/location_bar_separator_view.cc deleted file mode 100644 index ec44799..0000000 --- a/chrome/browser/ui/views/location_bar/location_bar_separator_view.cc +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/location_bar/location_bar_separator_view.h" - -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_animator.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/animation/tween.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/color_utils.h" -#include "ui/gfx/geometry/point_f.h" - -namespace { - -// These values are empirical. -constexpr base::TimeDelta kLocationBarSeparatorFadeInDuration = - base::TimeDelta::FromMilliseconds(250); -constexpr base::TimeDelta kLocationBarSeparatorFadeOutDuration = - base::TimeDelta::FromMilliseconds(175); - -} // namespace - -LocationBarSeparatorView::LocationBarSeparatorView() { - SetPaintToLayer(); - layer()->SetFillsBoundsOpaquely(false); -} - -void LocationBarSeparatorView::OnPaint(gfx::Canvas* canvas) { - DCHECK_NE(gfx::kPlaceholderColor, background_color_); - const SkColor separator_color = SkColorSetA( - color_utils::GetColorWithMaxContrast(background_color_), 0x69); - const float x = 1.f - 1.f / canvas->image_scale(); - canvas->DrawLine(gfx::PointF(x, GetLocalBounds().y()), - gfx::PointF(x, GetLocalBounds().bottom()), separator_color); -} - -void LocationBarSeparatorView::Show() { - layer()->SetOpacity(0.0f); -} - -void LocationBarSeparatorView::Hide() { - layer()->SetOpacity(1.0f); -} - -void LocationBarSeparatorView::FadeIn() { - FadeTo(1.0f, kLocationBarSeparatorFadeInDuration); -} - -void LocationBarSeparatorView::FadeOut() { - FadeTo(0.0f, kLocationBarSeparatorFadeOutDuration); -} - -void LocationBarSeparatorView::FadeTo(float opacity, base::TimeDelta duration) { - if (disable_animation_for_test_) { - layer()->SetOpacity(opacity); - } else { - ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator()); - animation.SetTransitionDuration(duration); - animation.SetTweenType(gfx::Tween::Type::EASE_IN); - layer()->SetOpacity(opacity); - } -}
diff --git a/chrome/browser/ui/views/location_bar/location_bar_separator_view.h b/chrome/browser/ui/views/location_bar/location_bar_separator_view.h deleted file mode 100644 index 800d233..0000000 --- a/chrome/browser/ui/views/location_bar/location_bar_separator_view.h +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_LOCATION_BAR_SEPARATOR_VIEW_H_ -#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_LOCATION_BAR_SEPARATOR_VIEW_H_ - -#include "base/time/time.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/color_palette.h" -#include "ui/views/view.h" - -namespace gfx { -class Canvas; -} - -class LocationBarSeparatorView : public views::View { - public: - LocationBarSeparatorView(); - - void SetBackgroundColor(SkColor color) { background_color_ = color; } - - // Show or hide immediately. - void Show(); - void Hide(); - - // Animate in or out. - void FadeIn(); - void FadeOut(); - - // views::View: - void OnPaint(gfx::Canvas* canvas) override; - - void set_disable_animation_for_test(bool disable_animation_for_test) { - disable_animation_for_test_ = disable_animation_for_test; - } - - private: - void FadeTo(float opacity, base::TimeDelta duration); - - SkColor background_color_ = gfx::kPlaceholderColor; - bool disable_animation_for_test_ = false; - - DISALLOW_COPY_AND_ASSIGN(LocationBarSeparatorView); -}; - -#endif // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_LOCATION_BAR_SEPARATOR_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index 59b844af..93ec4cb 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -698,8 +698,7 @@ } content::WebContents* LocationBarView::GetContentSettingWebContents() { - return GetLocationBarModel()->input_in_progress() ? nullptr - : GetWebContents(); + return IsLocationBarUserInputInProgress() ? nullptr : GetWebContents(); } ContentSettingBubbleModelDelegate* @@ -1012,7 +1011,7 @@ if (star_view_) { star_view_->SetVisible(browser_defaults::bookmarks_enabled && !is_popup_mode_ && - !GetLocationBarModel()->input_in_progress() && + !IsLocationBarUserInputInProgress() && edit_bookmarks_enabled_.GetValue() && !IsBookmarkStarHiddenByExtension()); } @@ -1149,7 +1148,7 @@ void LocationBarView::OnChanged() { location_icon_view_->Update(/*suppress_animations=*/false); - clear_all_button_->SetVisible(GetLocationBarModel()->input_in_progress() && + clear_all_button_->SetVisible(IsLocationBarUserInputInProgress() && !omnibox_view_->text().empty() && IsVirtualKeyboardVisible(GetWidget())); Layout();
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index 6650e23a..3d740c7 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -18,7 +18,6 @@ #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/browser_features.h" #include "chrome/browser/command_updater.h" -#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/media/router/media_router_feature.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/themes/theme_properties.h" @@ -839,7 +838,6 @@ void ToolbarView::UpdateHomeButtonVisibility() { const bool show_home_button = - show_home_button_.GetValue() || - (browser_->is_app() && extensions::util::IsNewBookmarkAppsEnabled()); + show_home_button_.GetValue() || browser_->is_app(); home_->SetVisible(show_home_button); }
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index 56cb558..89c6ea0 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -151,6 +151,8 @@ #include "chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.h" #include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h" #include "chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.h" +#include "chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.h" +#include "chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_ui.h" #include "chrome/browser/ui/webui/chromeos/certificate_manager_dialog_ui.h" #include "chrome/browser/ui/webui/chromeos/cryptohome_ui.h" #include "chrome/browser/ui/webui/chromeos/drive_internals_ui.h" @@ -158,7 +160,6 @@ #include "chrome/browser/ui/webui/chromeos/internet_config_dialog.h" #include "chrome/browser/ui/webui/chromeos/internet_detail_dialog.h" #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" -#include "chrome/browser/ui/webui/chromeos/mobile_setup_ui.h" #include "chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h" #include "chrome/browser/ui/webui/chromeos/network_ui.h" #include "chrome/browser/ui/webui/chromeos/power_ui.h" @@ -499,6 +500,8 @@ return &NewWebUI<chromeos::AccountManagerWelcomeUI>; if (url.host_piece() == chrome::kChromeUIBluetoothPairingHost) return &NewWebUI<chromeos::BluetoothPairingDialogUI>; + if (url.host_piece() == chrome::kChromeUICellularSetupHost) + return &NewWebUI<chromeos::cellular_setup::CellularSetupDialogUI>; if (url.host_piece() == chrome::kChromeUICertificateManagerHost) return &NewWebUI<chromeos::CertificateManagerDialogUI>; if (url.host_piece() == chrome::kChromeUICryptohomeHost) @@ -508,7 +511,7 @@ if (url.host_piece() == chrome::kChromeUIFirstRunHost) return &NewWebUI<chromeos::FirstRunUI>; if (url.host_piece() == chrome::kChromeUIMobileSetupHost) - return &NewWebUI<chromeos::MobileSetupUI>; + return &NewWebUI<chromeos::cellular_setup::MobileSetupUI>; if (url.host_piece() == chrome::kChromeUIMultiDeviceSetupHost) return &NewWebUI<chromeos::multidevice_setup::MultiDeviceSetupDialogUI>; if (url.host_piece() == chrome::kChromeUINetworkHost)
diff --git a/chrome/browser/ui/webui/chromeos/cellular_setup/OWNERS b/chrome/browser/ui/webui/chromeos/cellular_setup/OWNERS new file mode 100644 index 0000000..e26edaf --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/cellular_setup/OWNERS
@@ -0,0 +1,2 @@ +khorimoto@chromium.org +tbarzic@chromium.org
diff --git a/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.cc b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.cc new file mode 100644 index 0000000..6dbe658 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.cc
@@ -0,0 +1,99 @@ +// 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 "chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/browser_dialogs.h" +#include "chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.h" +#include "chrome/common/url_constants.h" +#include "chrome/grit/cellular_setup_resources.h" +#include "chrome/grit/cellular_setup_resources_map.h" +#include "content/public/browser/web_ui_data_source.h" +#include "ui/aura/window.h" + +namespace chromeos { + +namespace cellular_setup { + +namespace { + +// TODO(azeemarshad): Determine the exact height and width of the dialog. The +// current mocks are unclear, so these are just a guess. +constexpr int kDialogHeightPx = 850; +constexpr int kDialogWidthPx = 650; + +CellularSetupDialog* dialog_instance = nullptr; + +} // namespace + +// static +void CellularSetupDialog::ShowDialog(const std::string& cellular_network_guid) { + if (dialog_instance) { + dialog_instance->dialog_window()->Focus(); + return; + } + + dialog_instance = new CellularSetupDialog(); + + // Note: chrome::ShowWebDialog() is used instead of + // dialog_instance->ShowSystemDialog() because it provides the dialog to + // ability to switch to full-screen in tablet mode. + chrome::ShowWebDialog(nullptr /* parent */, + ProfileManager::GetActiveUserProfile(), + dialog_instance); +} + +CellularSetupDialog::CellularSetupDialog() + : SystemWebDialogDelegate(GURL(chrome::kChromeUICellularSetupUrl), + base::string16()) {} + +CellularSetupDialog::~CellularSetupDialog() = default; + +void CellularSetupDialog::GetDialogSize(gfx::Size* size) const { + size->SetSize(kDialogWidthPx, kDialogHeightPx); +} + +bool CellularSetupDialog::CanResizeDialog() const { + return false; +} + +void CellularSetupDialog::OnDialogClosed(const std::string& json_retval) { + DCHECK(this == dialog_instance); + dialog_instance = nullptr; + + // Note: The call below deletes |this|, so there is no further need to keep + // track of the pointer. + SystemWebDialogDelegate::OnDialogClosed(json_retval); +} + +CellularSetupDialogUI::CellularSetupDialogUI(content::WebUI* web_ui) + : ui::MojoWebDialogUI(web_ui) { + content::WebUIDataSource* source = + content::WebUIDataSource::Create(chrome::kChromeUICellularSetupHost); + + chromeos::cellular_setup::AddLocalizedStrings(source); + source->SetJsonPath("strings.js"); + source->SetDefaultResource(IDR_CELLULAR_SETUP_CELLULAR_SETUP_DIALOG_HTML); + + // Note: The |kCellularSetupResourcesSize| and |kCellularSetupResources| + // fields are defined in the generated file + // chrome/grit/cellular_setup_resources_map.h. + for (size_t i = 0; i < kCellularSetupResourcesSize; ++i) { + source->AddResourcePath(kCellularSetupResources[i].name, + kCellularSetupResources[i].value); + } + + content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source); + + // TODO(khorimoto): Add Mojo bindings to this WebUI so that Mojo calls can + // occur in JavaScript. +} + +CellularSetupDialogUI::~CellularSetupDialogUI() = default; + +} // namespace cellular_setup + +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.h b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.h new file mode 100644 index 0000000..164c12f --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.h
@@ -0,0 +1,48 @@ +// 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_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_CELLULAR_SETUP_DIALOG_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_CELLULAR_SETUP_DIALOG_H_ + +#include "base/macros.h" +#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h" +#include "ui/web_dialogs/web_dialog_ui.h" + +namespace chromeos { + +namespace cellular_setup { + +// Dialog which displays the cellular setup flow which allows users to +// activate their un-activated SIM cards. This dialog is only used when the +// kUpdatedCellularActivationUi flag is enabled; see go/cros-cellular-design. +class CellularSetupDialog : public SystemWebDialogDelegate { + protected: + CellularSetupDialog(); + ~CellularSetupDialog() override; + + // ui::WebDialogDelegate + void GetDialogSize(gfx::Size* size) const override; + bool CanResizeDialog() const override; + void OnDialogClosed(const std::string& json_retval) override; + + private: + friend void OpenCellularSetupDialog(const std::string& cellular_network_guid); + static void ShowDialog(const std::string& cellular_network_guid); + + DISALLOW_COPY_AND_ASSIGN(CellularSetupDialog); +}; + +class CellularSetupDialogUI : public ui::MojoWebDialogUI { + public: + explicit CellularSetupDialogUI(content::WebUI* web_ui); + ~CellularSetupDialogUI() override; + + DISALLOW_COPY_AND_ASSIGN(CellularSetupDialogUI); +}; + +} // namespace cellular_setup + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_CELLULAR_SETUP_DIALOG_H_
diff --git a/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.cc b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.cc new file mode 100644 index 0000000..a95ee83 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.cc
@@ -0,0 +1,27 @@ +// 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/ui/webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.h" + +#include "base/feature_list.h" +#include "chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.h" +#include "chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_dialog.h" +#include "chromeos/constants/chromeos_features.h" + +namespace chromeos { + +namespace cellular_setup { + +void OpenCellularSetupDialog(const std::string& cellular_network_guid) { + if (base::FeatureList::IsEnabled( + chromeos::features::kUpdatedCellularActivationUi)) { + CellularSetupDialog::ShowDialog(cellular_network_guid); + } else { + MobileSetupDialog::ShowByNetworkId(cellular_network_guid); + } +} + +} // namespace cellular_setup + +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.h b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.h new file mode 100644 index 0000000..e8477d8 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.h
@@ -0,0 +1,24 @@ +// 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_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_CELLULAR_SETUP_DIALOG_LAUNCHER_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_CELLULAR_SETUP_DIALOG_LAUNCHER_H_ + +#include <string> + +namespace chromeos { + +namespace cellular_setup { + +// Opens the cellular setup dialog for the cellular network with the provided +// GUID; if the dialog is already open, this function focuses it. Note that this +// function may open a different dialog depending on whether the +// kUpdatedCellularActivationUi flag is enabled. +void OpenCellularSetupDialog(const std::string& cellular_network_guid); + +} // namespace cellular_setup + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_CELLULAR_SETUP_DIALOG_LAUNCHER_H_
diff --git a/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc new file mode 100644 index 0000000..c8112a8 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc
@@ -0,0 +1,38 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.h" + +#include "base/stl_util.h" +#include "chrome/browser/ui/webui/localized_string.h" +#include "components/login/localized_values_builder.h" +#include "components/strings/grit/components_strings.h" +#include "content/public/browser/web_ui_data_source.h" + +namespace chromeos { + +namespace cellular_setup { + +namespace { + +// TODO(azeemarshad): Add localized strings for cellular setup flow. +constexpr LocalizedString kLocalizedStringsWithoutPlaceholders[] = { + {"cancel", IDS_CANCEL}, +}; + +} // namespace + +void AddLocalizedStrings(content::WebUIDataSource* html_source) { + AddLocalizedStringsBulk(html_source, kLocalizedStringsWithoutPlaceholders, + base::size(kLocalizedStringsWithoutPlaceholders)); +} + +void AddLocalizedValuesToBuilder(::login::LocalizedValuesBuilder* builder) { + for (const auto& entry : kLocalizedStringsWithoutPlaceholders) + builder->Add(entry.name, entry.id); +} + +} // namespace cellular_setup + +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.h b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.h new file mode 100644 index 0000000..6ab522f --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.h
@@ -0,0 +1,30 @@ +// 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_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_CELLULAR_SETUP_LOCALIZED_STRINGS_PROVIDER_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_CELLULAR_SETUP_LOCALIZED_STRINGS_PROVIDER_H_ + +namespace login { +class LocalizedValuesBuilder; +} + +namespace content { +class WebUIDataSource; +} + +namespace chromeos { + +namespace cellular_setup { + +// Adds the strings needed for the cellular setup flow to |html_source|. +void AddLocalizedStrings(content::WebUIDataSource* html_source); + +// Same as AddLocalizedStrings() but for a LocalizedValuesBuilder. +void AddLocalizedValuesToBuilder(::login::LocalizedValuesBuilder* builder); + +} // namespace cellular_setup + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_CELLULAR_SETUP_LOCALIZED_STRINGS_PROVIDER_H_
diff --git a/chrome/browser/ui/webui/chromeos/mobile_setup_dialog.cc b/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_dialog.cc similarity index 95% rename from chrome/browser/ui/webui/chromeos/mobile_setup_dialog.cc rename to chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_dialog.cc index eaa3962..542665cb 100644 --- a/chrome/browser/ui/webui/chromeos/mobile_setup_dialog.cc +++ b/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_dialog.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/webui/chromeos/mobile_setup_dialog.h" +#include "chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_dialog.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/chromeos/mobile/mobile_activator.h" @@ -21,6 +21,8 @@ namespace chromeos { +namespace cellular_setup { + namespace { constexpr int kMobileSetupDialogWidth = 850; @@ -98,4 +100,6 @@ l10n_util::GetStringUTF16(IDS_MOBILE_CANCEL_ACTIVATION)); } +} // namespace cellular_setup + } // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/mobile_setup_dialog.h b/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_dialog.h similarity index 61% rename from chrome/browser/ui/webui/chromeos/mobile_setup_dialog.h rename to chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_dialog.h index 8243bf7..4739b83 100644 --- a/chrome/browser/ui/webui/chromeos/mobile_setup_dialog.h +++ b/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_dialog.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_MOBILE_SETUP_DIALOG_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_MOBILE_SETUP_DIALOG_H_ +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_MOBILE_SETUP_DIALOG_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_MOBILE_SETUP_DIALOG_H_ #include "base/macros.h" #include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h" @@ -12,10 +12,12 @@ class NetworkState; -class MobileSetupDialog : public SystemWebDialogDelegate { - public: - static void ShowByNetworkId(const std::string& network_id); +namespace cellular_setup { +// Dialog used for cellular activation flow when the +// kUpdatedCellularActivationUi flag is disabled. +// DEPRECATED: Being replaced by new UI; see https://crbug.com/778021. +class MobileSetupDialog : public SystemWebDialogDelegate { protected: explicit MobileSetupDialog(const NetworkState& network); ~MobileSetupDialog() override; @@ -27,9 +29,15 @@ void OnCloseContents(content::WebContents* source, bool* out_close_dialog) override; + private: + friend void OpenCellularSetupDialog(const std::string& cellular_network_guid); + static void ShowByNetworkId(const std::string& network_id); + DISALLOW_COPY_AND_ASSIGN(MobileSetupDialog); }; +} // namespace cellular_setup + } // namespace chromeos -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_MOBILE_SETUP_DIALOG_H_ +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_MOBILE_SETUP_DIALOG_H_
diff --git a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc b/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_ui.cc similarity index 99% rename from chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc rename to chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_ui.cc index 8fb50f2e..060cab4 100644 --- a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc +++ b/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_ui.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/webui/chromeos/mobile_setup_ui.h" +#include "chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_ui.h" #include <stddef.h> @@ -46,6 +46,8 @@ namespace chromeos { +namespace cellular_setup { + namespace { // Host page JS API function names. @@ -604,4 +606,6 @@ MobileSetupUI::~MobileSetupUI() = default; +} // namespace cellular_setup + } // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.h b/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_ui.h similarity index 60% rename from chrome/browser/ui/webui/chromeos/mobile_setup_ui.h rename to chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_ui.h index 8334f11..a9d6fcc 100644 --- a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.h +++ b/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_ui.h
@@ -2,16 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_MOBILE_SETUP_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_MOBILE_SETUP_UI_H_ +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_MOBILE_SETUP_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_MOBILE_SETUP_UI_H_ #include "base/macros.h" #include "ui/web_dialogs/web_dialog_ui.h" namespace chromeos { +namespace cellular_setup { + // A custom WebUI that defines datasource for mobile setup registration page // that is used in Chrome OS activate modem and perform plan subscription tasks. +// This WebUI is being replaced and is only shown when the +// kUpdatedCellularActivationUi flag is disabled; see go/cros-cellular-design. class MobileSetupUI : public ui::WebDialogUI { public: explicit MobileSetupUI(content::WebUI* web_ui); @@ -21,6 +25,8 @@ DISALLOW_COPY_AND_ASSIGN(MobileSetupUI); }; +} // namespace cellular_setup + } // namespace chromeos -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_MOBILE_SETUP_UI_H_ +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_CELLULAR_SETUP_MOBILE_SETUP_UI_H_
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.cc b/chrome/browser/ui/webui/chromeos/network_ui.cc index 7494e78..1513366c 100644 --- a/chrome/browser/ui/webui/chromeos/network_ui.cc +++ b/chrome/browser/ui/webui/chromeos/network_ui.cc
@@ -14,6 +14,7 @@ #include "base/strings/stringprintf.h" #include "base/values.h" #include "chrome/browser/extensions/tab_helper.h" +#include "chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.h" #include "chrome/browser/ui/webui/chromeos/internet_config_dialog.h" #include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h" #include "chrome/common/url_constants.h" @@ -37,8 +38,10 @@ namespace { +constexpr char kAddNetwork[] = "addNetwork"; constexpr char kGetNetworkProperties[] = "getShillNetworkProperties"; constexpr char kGetDeviceProperties[] = "getShillDeviceProperties"; +constexpr char kOpenCellularActivationUi[] = "openCellularActivationUi"; bool GetServicePathFromGuid(const std::string& guid, std::string* service_path) { @@ -84,6 +87,10 @@ // WebUIMessageHandler implementation. void RegisterMessages() override { web_ui()->RegisterMessageCallback( + kAddNetwork, + base::BindRepeating(&NetworkConfigMessageHandler::AddNetwork, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( kGetNetworkProperties, base::BindRepeating( &NetworkConfigMessageHandler::GetShillNetworkProperties, @@ -94,9 +101,10 @@ &NetworkConfigMessageHandler::GetShillDeviceProperties, base::Unretained(this))); web_ui()->RegisterMessageCallback( - "addNetwork", - base::BindRepeating(&NetworkConfigMessageHandler::AddNetwork, - base::Unretained(this))); + kOpenCellularActivationUi, + base::BindRepeating( + &NetworkConfigMessageHandler::OpenCellularActivationUi, + base::Unretained(this))); } private: @@ -165,6 +173,19 @@ weak_ptr_factory_.GetWeakPtr(), type, kGetDeviceProperties)); } + void OpenCellularActivationUi(const base::ListValue* arg_list) { + const NetworkState* cellular_network = + NetworkHandler::Get()->network_state_handler()->FirstNetworkByType( + NetworkTypePattern::Cellular()); + if (cellular_network) + cellular_setup::OpenCellularSetupDialog(cellular_network->guid()); + + AllowJavascript(); + CallJavascriptFunction( + base::StringPrintf("NetworkUI.%sResult", kOpenCellularActivationUi), + base::Value(cellular_network != nullptr)); + } + void GetShillDevicePropertiesSuccess( const std::string& device_path, const base::DictionaryValue& dictionary) { @@ -263,6 +284,17 @@ l10n_util::GetStringUTF16(IDS_NETWORK_UI_FAVORITE_NETWORKS)); localized_strings->SetString( "devicesLabel", l10n_util::GetStringUTF16(IDS_NETWORK_UI_DEVICES)); + + localized_strings->SetString( + "cellularActivationLabel", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NO_CELLULAR_ACTIVATION_LABEL)); + localized_strings->SetString( + "cellularActivationButtonText", + l10n_util::GetStringUTF16( + IDS_NETWORK_UI_OPEN_CELLULAR_ACTIVATION_BUTTON_TEXT)); + localized_strings->SetString( + "noCellularErrorText", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NO_CELLULAR_ERROR_TEXT)); } NetworkUI::NetworkUI(content::WebUI* web_ui)
diff --git a/chrome/browser/ui/webui/management_ui_handler.cc b/chrome/browser/ui/webui/management_ui_handler.cc index 3565d325..d289c26 100644 --- a/chrome/browser/ui/webui/management_ui_handler.cc +++ b/chrome/browser/ui/webui/management_ui_handler.cc
@@ -134,10 +134,19 @@ std::string GetAccountDomain(Profile* profile) { auto username = profile->GetProfileUserName(); size_t email_separator_pos = username.find('@'); - auto is_email = email_separator_pos != username.npos && + bool is_email = email_separator_pos != std::string::npos && email_separator_pos < username.length() - 1; - return is_email ? gaia::ExtractDomainName(std::move(username)) - : std::string(); + + if (!is_email) + return std::string(); + + const std::string domain = gaia::ExtractDomainName(std::move(username)); + + auto consumer_domain_pos = domain.find("gmail.com"); + if (consumer_domain_pos == std::string::npos) + consumer_domain_pos = domain.find("googlemail.com"); + + return consumer_domain_pos == std::string::npos ? domain : std::string(); } #if !defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/management_ui_handler_unittest.cc b/chrome/browser/ui/webui/management_ui_handler_unittest.cc index 36a2abb..212d62f 100644 --- a/chrome/browser/ui/webui/management_ui_handler_unittest.cc +++ b/chrome/browser/ui/webui/management_ui_handler_unittest.cc
@@ -150,6 +150,32 @@ } TEST_F(ManagementUIHandlerTests, + ManagementContextualSourceUpdateManagedConsumerDomain) { + TestingProfile::Builder builder; + builder.SetProfileName("managed@gmail.com"); + auto profile = builder.Build(); + + base::string16 extensions_installed; + base::string16 browser_management_notice; + base::string16 title; + ContextualManagementSourceUpdate extracted{ + &extensions_installed, &browser_management_notice, &title}; + + handler_.SetManagedForTesting(true); + auto data = handler_.GetDataSourceUpdate(profile.get()); + ExtractContextualSourceUpdate(data.get(), extracted); + + EXPECT_EQ(data->DictSize(), 3u); + EXPECT_EQ(extensions_installed, + l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED)); + EXPECT_EQ(browser_management_notice, + l10n_util::GetStringFUTF16( + IDS_MANAGEMENT_BROWSER_NOTICE, + base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))); + EXPECT_EQ(title, l10n_util::GetStringUTF16(IDS_MANAGEMENT_TITLE)); +} + +TEST_F(ManagementUIHandlerTests, ManagementContextualSourceUpdateUnmanagedKnownDomain) { TestingProfile::Builder builder; builder.SetProfileName("managed@manager.com"); @@ -178,6 +204,33 @@ } TEST_F(ManagementUIHandlerTests, + ManagementContextualSourceUpdateUnmanagedCustomerDomain) { + TestingProfile::Builder builder; + builder.SetProfileName("managed@googlemail.com"); + auto profile = builder.Build(); + + base::string16 extensions_installed; + base::string16 browser_management_notice; + base::string16 title; + ContextualManagementSourceUpdate extracted{ + &extensions_installed, &browser_management_notice, &title}; + + handler_.SetManagedForTesting(false); + + auto data = handler_.GetDataSourceUpdate(profile.get()); + ExtractContextualSourceUpdate(data.get(), extracted); + + EXPECT_EQ(data->DictSize(), 3u); + EXPECT_EQ(extensions_installed, + l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED)); + EXPECT_EQ(browser_management_notice, + l10n_util::GetStringFUTF16( + IDS_MANAGEMENT_NOT_MANAGED_NOTICE, + base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))); + EXPECT_EQ(title, l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_TITLE)); +} + +TEST_F(ManagementUIHandlerTests, ManagementContextualSourceUpdateManagedKnownDomain) { TestingProfile::Builder builder; builder.SetProfileName("managed@manager.com");
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc index 78c46d6..17e7580 100644 --- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc +++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -17,7 +17,6 @@ #include "chrome/browser/browser_features.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/themes/theme_properties.h" @@ -455,12 +454,6 @@ load_time_data.SetBoolean("showWebStoreIcon", !prefs->GetBoolean(prefs::kHideWebStoreIcon)); - load_time_data.SetBoolean("enableNewBookmarkApps", - extensions::util::IsNewBookmarkAppsEnabled()); - - load_time_data.SetBoolean("canHostedAppsOpenInWindows", - extensions::util::CanHostedAppsOpenInWindows()); - load_time_data.SetBoolean("canShowAppInfoDialog", CanShowAppInfoDialog());
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 907b6e67..50f3c74 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -30,9 +30,11 @@ #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/locale_settings.h" +#include "components/autofill/core/browser/autofill_experiments.h" #include "components/autofill/core/browser/payments/payments_service_url.h" #include "components/autofill/core/browser/payments/payments_util.h" #include "components/autofill/core/browser/personal_data_manager.h" +#include "components/autofill/core/browser/sync_utils.h" #include "components/autofill/core/common/autofill_constants.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_payments_features.h" @@ -1560,37 +1562,6 @@ autofill::payments::GetManageInstrumentsUrl().spec()); html_source->AddString("paymentMethodsLearnMoreURL", chrome::kPaymentMethodsLearnMoreURL); - html_source->AddBoolean( - "migrationEnabled", - autofill::features::GetLocalCardMigrationExperimentalFlag() == - autofill::features::LocalCardMigrationExperimentalFlag:: - kMigrationIncludeSettingsPage); - html_source->AddBoolean( - "upstreamEnabled", - base::FeatureList::IsEnabled(autofill::features::kAutofillUpstream)); - - autofill::PersonalDataManager* personal_data_manager_ = - autofill::PersonalDataManagerFactory::GetForProfile(profile); - html_source->AddBoolean( - "hasGooglePaymentsAccount", - autofill::payments::GetBillingCustomerId(personal_data_manager_) != 0); - - syncer::SyncService* sync_service = - ProfileSyncServiceFactory::GetForProfile(profile); - if (sync_service && sync_service->CanSyncFeatureStart() && - sync_service->GetPreferredDataTypes().Has(syncer::AUTOFILL_PROFILE)) { - html_source->AddBoolean( - "isUsingSecondaryPassphrase", - sync_service->GetUserSettings()->IsUsingSecondaryPassphrase()); - html_source->AddBoolean( - "uploadToGoogleActive", - syncer::GetUploadToGoogleState( - sync_service, syncer::ModelType::AUTOFILL_WALLET_DATA) == - syncer::UploadState::ACTIVE); - } else { - html_source->AddBoolean("isUsingSecondaryPassphrase", false); - html_source->AddBoolean("uploadToGoogleActive", false); - } bool is_guest_mode = false; #if defined(OS_CHROMEOS) @@ -1599,24 +1570,14 @@ #else // !defined(OS_CHROMEOS) is_guest_mode = profile->IsOffTheRecord(); #endif // defined(OS_CHROMEOS) - - if (is_guest_mode) { - html_source->AddBoolean("userEmailDomainAllowed", false); - } else { - const std::string& user_email = - personal_data_manager_->GetAccountInfoForPaymentsServer().email; - if (user_email.empty()) { - html_source->AddBoolean("userEmailDomainAllowed", false); - } else { - std::string domain = gaia::ExtractDomainName(user_email); - html_source->AddBoolean( - "userEmailDomainAllowed", - base::FeatureList::IsEnabled( - autofill::features::kAutofillUpstreamAllowAllEmailDomains) || - (domain == "googlemail.com" || domain == "gmail.com" || - domain == "google.com" || domain == "chromium.org")); - } - } + html_source->AddBoolean( + "migrationEnabled", + !is_guest_mode && + autofill::IsCreditCardMigrationEnabled( + autofill::PersonalDataManagerFactory::GetForProfile(profile), + profile->GetPrefs(), + ProfileSyncServiceFactory::GetForProfile(profile), + /*is_test_mode=*/false)); AddLocalizedStringsBulk(html_source, kLocalizedStrings, base::size(kLocalizedStrings));
diff --git a/chrome/browser/ui/webui/welcome/OWNERS b/chrome/browser/ui/webui/welcome/OWNERS index c497ef2..a0bd3ec 100644 --- a/chrome/browser/ui/webui/welcome/OWNERS +++ b/chrome/browser/ui/webui/welcome/OWNERS
@@ -1,4 +1,3 @@ hcarmona@chromium.org -scottchen@chromium.org # COMPONENT: UI>Browser>FirstRun
diff --git a/chrome/browser/ui/webui/welcome/welcome_ui_unittest.cc b/chrome/browser/ui/webui/welcome/welcome_ui_unittest.cc index dc45f0d..9f8592e 100644 --- a/chrome/browser/ui/webui/welcome/welcome_ui_unittest.cc +++ b/chrome/browser/ui/webui/welcome/welcome_ui_unittest.cc
@@ -19,7 +19,7 @@ EXPECT_TRUE(TestWelcomeUI::IsGzipped("returning-user")); // Images are intentionally not gzipped. - EXPECT_FALSE(TestWelcomeUI::IsGzipped("images/set_as_default_1x.png")); + EXPECT_FALSE(TestWelcomeUI::IsGzipped("images/youtube_1x.png")); // This is a dynamic path that fetches from the network and should not be // considered gzipped.
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn index a813b89..d4859f7b 100644 --- a/chrome/browser/vr/BUILD.gn +++ b/chrome/browser/vr/BUILD.gn
@@ -679,6 +679,7 @@ "//chrome/test:browser_tests_runner", "//chrome/test:test_support", "//chrome/test:test_support_ui", + "//device/base", "//device/vr:vr", "//device/vr/buildflags:buildflags", "//device/vr/public/mojom:mojom",
diff --git a/chrome/browser/vr/test/webxr_vr_browser_test.h b/chrome/browser/vr/test/webxr_vr_browser_test.h index 644ce4c..80bbf99c 100644 --- a/chrome/browser/vr/test/webxr_vr_browser_test.h +++ b/chrome/browser/vr/test/webxr_vr_browser_test.h
@@ -11,6 +11,7 @@ #include "chrome/common/chrome_features.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" +#include "device/base/features.h" #include "device/vr/buildflags/buildflags.h" #if defined(OS_WIN) @@ -53,6 +54,25 @@ } }; +// WebXrOrientationSensorDevice is only defined when the enable_vr flag is set. +#if BUILDFLAG(ENABLE_VR) +class WebXrVrBrowserTestSensorless : public WebXrVrBrowserTestBase { + public: + WebXrVrBrowserTestSensorless() { + enable_features_.push_back(features::kWebXr); + disable_features_.push_back(device::kWebXrOrientationSensorDevice); + +#if BUILDFLAG(ENABLE_WINDOWS_MR) + disable_features_.push_back(features::kWindowsMixedReality); +#endif + +#if defined(OS_WIN) + disable_features_.push_back(service_manager::features::kXRSandbox); +#endif + } +}; +#endif + // OpenVR feature only defined on Windows. #ifdef OS_WIN // Test class with standard features enabled: WebXR and OpenVR.
diff --git a/chrome/browser/vr/test/xr_browser_test.cc b/chrome/browser/vr/test/xr_browser_test.cc index ae2ea5e..23d7fda 100644 --- a/chrome/browser/vr/test/xr_browser_test.cc +++ b/chrome/browser/vr/test/xr_browser_test.cc
@@ -103,13 +103,13 @@ } // Set the environment variable to use the mock OpenVR client. - EXPECT_TRUE( + ASSERT_TRUE( env_->SetVar(kVrOverrideEnvVar, MakeExecutableRelative(kVrOverrideVal))) << "Failed to set OpenVR mock client location environment variable"; - EXPECT_TRUE(env_->SetVar(kVrConfigPathEnvVar, + ASSERT_TRUE(env_->SetVar(kVrConfigPathEnvVar, MakeExecutableRelative(kVrConfigPathVal))) << "Failed to set OpenVR config location environment variable"; - EXPECT_TRUE( + ASSERT_TRUE( env_->SetVar(kVrLogPathEnvVar, MakeExecutableRelative(kVrLogPathVal))) << "Failed to set OpenVR log location environment variable"; @@ -155,7 +155,7 @@ void XrBrowserTestBase::LoadUrlAndAwaitInitialization(const GURL& url) { ui_test_utils::NavigateToURL(browser(), url); - EXPECT_TRUE(PollJavaScriptBoolean("isInitializationComplete()", + ASSERT_TRUE(PollJavaScriptBoolean("isInitializationComplete()", kPollTimeoutMedium, GetCurrentWebContents())) << "Timed out waiting for JavaScript test initialization."; @@ -164,7 +164,7 @@ void XrBrowserTestBase::RunJavaScriptOrFail( const std::string& js_expression, content::WebContents* web_contents) { - EXPECT_TRUE(content::ExecuteScript(web_contents, js_expression)) + ASSERT_TRUE(content::ExecuteScript(web_contents, js_expression)) << "Failed to run given JavaScript: " << js_expression; } @@ -215,7 +215,7 @@ const std::string& bool_expression, const base::TimeDelta& timeout, content::WebContents* web_contents) { - EXPECT_TRUE(PollJavaScriptBoolean(bool_expression, timeout, web_contents)) + ASSERT_TRUE(PollJavaScriptBoolean(bool_expression, timeout, web_contents)) << "Timed out polling JavaScript boolean expression: " << bool_expression; } @@ -267,7 +267,7 @@ // code to do so. bool code_available = RunJavaScriptAndExtractBoolOrFail( "typeof javascriptDone !== 'undefined'", web_contents); - EXPECT_TRUE(code_available) << "Attempted to wait on a JavaScript test step " + ASSERT_TRUE(code_available) << "Attempted to wait on a JavaScript test step " << "without the code to do so. You either forgot " << "to import webxr_e2e.js or " << "are incorrectly using a C++ function.";
diff --git a/chrome/browser/vr/test/xr_browser_test.h b/chrome/browser/vr/test/xr_browser_test.h index dc9160c..683be2c5 100644 --- a/chrome/browser/vr/test/xr_browser_test.h +++ b/chrome/browser/vr/test/xr_browser_test.h
@@ -84,7 +84,7 @@ void LoadUrlAndAwaitInitialization(const GURL& url); // Convenience function for ensuring the given JavaScript runs successfully - // without having to always surround in EXPECT_TRUE. + // without having to always surround in ASSERT_TRUE. void RunJavaScriptOrFail(const std::string& js_expression, content::WebContents* web_contents);
diff --git a/chrome/browser/vr/webxr_vr_frame_pose_browser_test.cc b/chrome/browser/vr/webxr_vr_frame_pose_browser_test.cc index 2334652..526af32 100644 --- a/chrome/browser/vr/webxr_vr_frame_pose_browser_test.cc +++ b/chrome/browser/vr/webxr_vr_frame_pose_browser_test.cc
@@ -98,7 +98,7 @@ wait_loop_ = nullptr; } - EXPECT_TRUE(!!last_immersive_frame_data) + ASSERT_TRUE(!!last_immersive_frame_data) << "Frame submitted without any frame data provided"; // We expect a waitGetPoses, then 2 submits (one for each eye), so after 2 @@ -171,7 +171,7 @@ t->EnterSessionWithUserGestureOrFail(); // Wait for JavaScript to submit at least one frame. - EXPECT_TRUE( + ASSERT_TRUE( t->PollJavaScriptBoolean("hasPresentedFrame", t->kPollTimeoutShort)) << "No frame submitted"; @@ -202,27 +202,27 @@ // Validate that each frame is only seen once for each eye. DLOG(ERROR) << "Frame id: " << frame_id; if (data->eye == device_test::mojom::Eye::LEFT) { - EXPECT_TRUE(seen_left.find(frame_id) == seen_left.end()) + ASSERT_TRUE(seen_left.find(frame_id) == seen_left.end()) << "Frame for left eye submitted more than once"; seen_left.insert(frame_id); } else { - EXPECT_TRUE(seen_right.find(frame_id) == seen_right.end()) + ASSERT_TRUE(seen_right.find(frame_id) == seen_right.end()) << "Frame for right eye submitted more than once"; seen_right.insert(frame_id); } // Validate that frames arrive in order. - EXPECT_TRUE(frame_id >= max_frame_id) << "Frame received out of order"; + ASSERT_TRUE(frame_id >= max_frame_id) << "Frame received out of order"; max_frame_id = std::max(frame_id, max_frame_id); // Validate that the JavaScript-side cache of frames contains our submitted // frame. - EXPECT_TRUE(t->RunJavaScriptAndExtractBoolOrFail( + ASSERT_TRUE(t->RunJavaScriptAndExtractBoolOrFail( base::StringPrintf("checkFrameOccurred(%d)", frame_id))) << "JavaScript-side frame cache does not contain submitted frame"; // Validate that the JavaScript-side cache of frames has the correct pose. - EXPECT_TRUE(t->RunJavaScriptAndExtractBoolOrFail(base::StringPrintf( + ASSERT_TRUE(t->RunJavaScriptAndExtractBoolOrFail(base::StringPrintf( "checkFramePose(%d, %s)", frame_id, GetPoseAsString(frame).c_str()))) << "JavaScript-side frame cache has incorrect pose"; }
diff --git a/chrome/browser/vr/webxr_vr_pixel_browser_test.cc b/chrome/browser/vr/webxr_vr_pixel_browser_test.cc index a452c46..8d92634 100644 --- a/chrome/browser/vr/webxr_vr_pixel_browser_test.cc +++ b/chrome/browser/vr/webxr_vr_pixel_browser_test.cc
@@ -66,7 +66,7 @@ t->EnterSessionWithUserGestureOrFail(); // Wait for JavaScript to submit at least one frame. - EXPECT_TRUE( + ASSERT_TRUE( t->PollJavaScriptBoolean("hasPresentedFrame", t->kPollTimeoutMedium)) << "No frame submitted";
diff --git a/chrome/browser/vr/webxr_vr_spatial_tracking_test.cc b/chrome/browser/vr/webxr_vr_spatial_tracking_test.cc index 145578f..041990b 100644 --- a/chrome/browser/vr/webxr_vr_spatial_tracking_test.cc +++ b/chrome/browser/vr/webxr_vr_spatial_tracking_test.cc
@@ -19,4 +19,13 @@ WaitOnJavaScriptStep(); EndTest(); } + +#if BUILDFLAG(ENABLE_VR) +IN_PROC_BROWSER_TEST_F(WebXrVrBrowserTestSensorless, TestSensorlessRejections) { + LoadUrlAndAwaitInitialization( + GetFileUrlForHtmlTestFile("test_stationary_reference_space_rejects")); + WaitOnJavaScriptStep(); + EndTest(); +} +#endif } // namespace vr
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index 803db7cc..f54552a 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -150,6 +150,7 @@ if (is_chromeos) { sources += [ "$root_gen_dir/ash/public/cpp/resources/ash_public_unscaled_resources.pak", + "$root_gen_dir/chrome/cellular_setup_resources.pak", "$root_gen_dir/chrome/multidevice_setup_resources.pak", "$root_gen_dir/chromeos/chromeos_resources.pak", "$root_gen_dir/third_party/ink/ink_resources.pak", @@ -157,6 +158,7 @@ ] deps += [ "//ash/public/cpp/resources:ash_public_unscaled_resources", + "//chrome/browser/resources/chromeos:cellular_setup_resources", "//chrome/browser/resources/chromeos:multidevice_setup_resources", "//chromeos/resources", "//third_party/ink:ink_resources",
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 43b7382..b61a480 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -110,12 +110,6 @@ const base::Feature kBlockPromptsIfIgnoredOften{ "BlockPromptsIfIgnoredOften", base::FEATURE_DISABLED_BY_DEFAULT}; -#if defined(OS_MACOSX) -// Enables the new bookmark app system (e.g. Add To Applications on Mac). -const base::Feature kBookmarkApps{"BookmarkAppsMac", - base::FEATURE_ENABLED_BY_DEFAULT}; -#endif - // Fixes for browser hang bugs are deployed in a field trial in order to measure // their impact. See crbug.com/478209. const base::Feature kBrowserHangFixesExperiment{
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index cc03713..9406822 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -70,10 +70,6 @@ COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kBlockPromptsIfIgnoredOften; -#if defined(OS_MACOSX) -COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kBookmarkApps; -#endif - COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kBrowserHangFixesExperiment;
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 775e7716..97e786f 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -786,33 +786,16 @@ // Prevents Chrome from quitting when Chrome Apps are open. const char kAppsKeepChromeAliveInTests[] = "apps-keep-chrome-alive-in-tests"; -// Disable the toolkit-views App Info dialog for Mac. -const char kDisableAppInfoDialogMac[] = "disable-app-info-dialog-mac"; - // Disables app shim creation for hosted apps on Mac. const char kDisableHostedAppShimCreation[] = "disable-hosted-app-shim-creation"; -// Prevents hosted apps from being opened in windows on Mac. -const char kDisableHostedAppsInWindows[] = "disable-hosted-apps-in-windows"; - -// Disables use of toolkit-views based native app windows. -const char kDisableMacViewsNativeAppWindows[] = - "disable-mac-views-native-app-windows"; - // Enable user metrics from within the installer. const char kEnableUserMetrics[] = "enable-user-metrics"; -// Enable the toolkit-views App Info dialog for Mac. This is accessible from -// chrome://apps and chrome://extensions and is already enabled on non-mac. -const char kEnableAppInfoDialogMac[] = "enable-app-info-dialog-mac"; - // Enables the fullscreen toolbar to reveal itself for tab strip changes. const char kEnableFullscreenToolbarReveal[] = "enable-fullscreen-toolbar-reveal"; -// Allows hosted apps to be opened in windows on Mac. -const char kEnableHostedAppsInWindows[] = "enable-hosted-apps-in-windows"; - // Shows a notification when quitting Chrome with hosted apps running. Default // behavior is to also quit all hosted apps. const char kHostedAppQuitNotification[] = "enable-hosted-app-quit-notification";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index b5d6a55..0c44a8c 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -240,13 +240,8 @@ #if defined(OS_MACOSX) extern const char kAppsKeepChromeAliveInTests[]; -extern const char kDisableAppInfoDialogMac[]; extern const char kDisableHostedAppShimCreation[]; -extern const char kDisableHostedAppsInWindows[]; -extern const char kDisableMacViewsNativeAppWindows[]; -extern const char kEnableAppInfoDialogMac[]; extern const char kEnableFullscreenToolbarReveal[]; -extern const char kEnableHostedAppsInWindows[]; extern const char kEnableUserMetrics[]; extern const char kHostedAppQuitNotification[]; extern const char kMetricsClientID[];
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 4f1495f..d805619 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -1977,6 +1977,12 @@ "auto_screen_brightness.metrics.supported_als_user_adjustment_count"; const char kAutoScreenBrightnessMetricsUnsupportedAlsUserAdjustmentCount[] = "auto_screen_brightness.metrics.unsupported_als_user_adjustment_count"; + +// Dictionary pref containing the configuration used to verify Parent Access +// Code. The data is sent through the ParentAccessCodeConfig policy, which is +// set for child users only, and kept on the known user storage. +const char kKnownUserParentAccessCodeConfig[] = + "child_user.parent_access_code.config"; #endif // defined(OS_CHROMEOS) // Whether there is a Flash version installed that supports clearing LSO data.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 6ea8b24cc..403842e 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -655,6 +655,7 @@ extern const char kAutoScreenBrightnessMetricsSupportedAlsUserAdjustmentCount[]; extern const char kAutoScreenBrightnessMetricsUnsupportedAlsUserAdjustmentCount[]; +extern const char kKnownUserParentAccessCodeConfig[]; #endif // defined(OS_CHROMEOS) extern const char kClearPluginLSODataEnabled[];
diff --git a/chrome/common/thread_profiler.cc b/chrome/common/thread_profiler.cc index 74372d49..f77b3f2 100644 --- a/chrome/common/thread_profiler.cc +++ b/chrome/common/thread_profiler.cc
@@ -158,6 +158,13 @@ ScheduleNextPeriodicCollection(); } +void ThreadProfiler::AddAuxUnwinder(std::unique_ptr<base::Unwinder> unwinder) { + aux_unwinder_ = std::move(unwinder); + startup_profiler_->AddAuxUnwinder(aux_unwinder_.get()); + if (periodic_profiler_) + periodic_profiler_->AddAuxUnwinder(aux_unwinder_.get()); +} + // static void ThreadProfiler::StartOnChildThread(CallStackProfileParams::Thread thread) { if (!StackSamplingConfiguration::Get()->IsProfilerEnabledForCurrentProcess()) @@ -274,6 +281,8 @@ base::BindOnce(&ThreadProfiler::OnPeriodicCollectionCompleted, owning_thread_task_runner_, weak_factory_.GetWeakPtr()))); + if (aux_unwinder_) + periodic_profiler_->AddAuxUnwinder(aux_unwinder_.get()); periodic_profiler_->Start(); }
diff --git a/chrome/common/thread_profiler.h b/chrome/common/thread_profiler.h index 5a3de1f..16edefe 100644 --- a/chrome/common/thread_profiler.h +++ b/chrome/common/thread_profiler.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/profiler/stack_sampling_profiler.h" +#include "base/profiler/unwinder.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread.h" #include "base/threading/thread_checker.h" @@ -66,6 +67,11 @@ void SetMainThreadTaskRunner( scoped_refptr<base::SingleThreadTaskRunner> task_runner); + // Adds an auxiliary unwinder to supply to the StackSamplingProfiler to handle + // additional, non-native-code unwind scenarios. Currently used to support + // unwinding V8 JavaScript frames. + void AddAuxUnwinder(std::unique_ptr<base::Unwinder> unwinder); + // Creates a profiler for a child thread and immediately starts it. This // should be called from a task posted on the child thread immediately after // thread start. The thread will be profiled until exit. @@ -118,6 +124,8 @@ std::unique_ptr<WorkIdRecorder> work_id_recorder_; + std::unique_ptr<base::Unwinder> aux_unwinder_; + std::unique_ptr<base::StackSamplingProfiler> startup_profiler_; std::unique_ptr<base::StackSamplingProfiler> periodic_profiler_;
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index cf6f7dd..9c301c7 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -191,6 +191,8 @@ const char kChromeUIActivationMessageHost[] = "activationmessage"; const char kChromeUIBluetoothPairingHost[] = "bluetooth-pairing"; const char kChromeUIBluetoothPairingURL[] = "chrome://bluetooth-pairing/"; +const char kChromeUICellularSetupHost[] = "cellular-setup"; +const char kChromeUICellularSetupUrl[] = "chrome://cellular-setup"; const char kChromeUICertificateManagerDialogURL[] = "chrome://certificate-manager/"; const char kChromeUICertificateManagerHost[] = "certificate-manager";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 1a06412..acd86f9 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -189,6 +189,8 @@ extern const char kChromeUIActivationMessageHost[]; extern const char kChromeUIBluetoothPairingHost[]; extern const char kChromeUIBluetoothPairingURL[]; +extern const char kChromeUICellularSetupHost[]; +extern const char kChromeUICellularSetupUrl[]; extern const char kChromeUICertificateManagerDialogURL[]; extern const char kChromeUICertificateManagerHost[]; extern const char kChromeUICryptohomeHost[];
diff --git a/chrome/renderer/url_loader_throttle_provider_impl.cc b/chrome/renderer/url_loader_throttle_provider_impl.cc index 4374489..f124847 100644 --- a/chrome/renderer/url_loader_throttle_provider_impl.cc +++ b/chrome/renderer/url_loader_throttle_provider_impl.cc
@@ -178,7 +178,8 @@ // Don't add them for frame requests. bool is_frame_resource = content::IsResourceTypeFrame(resource_type); - DCHECK(!is_frame_resource || IsTypeFrame()); + DCHECK(!is_frame_resource || + type_ == content::URLLoaderThrottleProviderType::kFrame); if (data_reduction_proxy_manager_) { throttles.push_back( @@ -191,28 +192,15 @@ base::FeatureList::IsEnabled( safe_browsing::kCheckByURLLoaderThrottle)) && !is_frame_resource) { - if (safe_browsing_info_) { - scoped_refptr<base::SingleThreadTaskRunner> task_runner = - base::ThreadTaskRunnerHandle::Get(); - if (IsTypeFrame()) { - DCHECK(content::RenderThread::IsMainThread()); - content::RenderFrame* render_frame = - content::RenderFrame::FromRoutingID(render_frame_id); - if (render_frame) { - task_runner = - render_frame->GetTaskRunner(blink::TaskType::kInternalDefault); - } - } - safe_browsing_.Bind(std::move(safe_browsing_info_), - std::move(task_runner)); - } + if (safe_browsing_info_) + safe_browsing_.Bind(std::move(safe_browsing_info_)); throttles.push_back( std::make_unique<safe_browsing::RendererURLLoaderThrottle>( safe_browsing_.get(), render_frame_id)); } - if (IsTypeFrame() && !is_frame_resource) { - DCHECK(content::RenderThread::IsMainThread()); + if (type_ == content::URLLoaderThrottleProviderType::kFrame && + !is_frame_resource) { content::RenderFrame* render_frame = content::RenderFrame::FromRoutingID(render_frame_id); auto* prerender_helper = @@ -239,7 +227,8 @@ } #if BUILDFLAG(ENABLE_EXTENSIONS) - if (network_service_enabled && IsTypeFrame() && + if (network_service_enabled && + type_ == content::URLLoaderThrottleProviderType::kFrame && resource_type == content::RESOURCE_TYPE_OBJECT) { content::RenderFrame* render_frame = content::RenderFrame::FromRoutingID(render_frame_id); @@ -303,7 +292,3 @@ extension_throttle_manager_->SetOnline(is_online); #endif } - -bool URLLoaderThrottleProviderImpl::IsTypeFrame() const { - return type_ == content::URLLoaderThrottleProviderType::kFrame; -}
diff --git a/chrome/renderer/url_loader_throttle_provider_impl.h b/chrome/renderer/url_loader_throttle_provider_impl.h index f3ec637..f2b78d68 100644 --- a/chrome/renderer/url_loader_throttle_provider_impl.h +++ b/chrome/renderer/url_loader_throttle_provider_impl.h
@@ -48,11 +48,6 @@ // general use. URLLoaderThrottleProviderImpl(const URLLoaderThrottleProviderImpl& other); - // Reports whether the provider type is frame or not. When this is true, the - // member functions are called on the main thread. Otherwise, they are called - // on worker threads. - bool IsTypeFrame() const; - std::unique_ptr<subresource_filter::AdDelayThrottle::Factory> ad_delay_factory_;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index f8e14bc..3978031 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -868,6 +868,7 @@ "../browser/resource_coordinator/tab_activity_watcher_browsertest.cc", "../browser/resource_coordinator/tab_manager_browsertest.cc", "../browser/safe_browsing/chrome_cleaner/reporter_runner_browsertest_win.cc", + "../browser/safe_browsing/download_protection/download_protection_service_browsertest.cc", "../browser/safe_browsing/test_safe_browsing_database_helper.cc", "../browser/safe_browsing/test_safe_browsing_database_helper.h", "../browser/safe_json_parser_browsertest.cc",
diff --git a/chrome/test/data/safe_browsing/download_protection/zipfile_two_archives.zip b/chrome/test/data/safe_browsing/download_protection/zipfile_two_archives.zip new file mode 100644 index 0000000..d7af463 --- /dev/null +++ b/chrome/test/data/safe_browsing/download_protection/zipfile_two_archives.zip Binary files differ
diff --git a/chrome/test/data/safe_browsing/rar/has_two_archives.rar b/chrome/test/data/safe_browsing/rar/has_two_archives.rar new file mode 100644 index 0000000..416bd852 --- /dev/null +++ b/chrome/test/data/safe_browsing/rar/has_two_archives.rar Binary files differ
diff --git a/chrome/test/data/webui/settings/payments_section_test.js b/chrome/test/data/webui/settings/payments_section_test.js index ccb978b..4e2397d 100644 --- a/chrome/test/data/webui/settings/payments_section_test.js +++ b/chrome/test/data/webui/settings/payments_section_test.js
@@ -19,20 +19,10 @@ }); suite('PaymentsSection', function() { - /** @type {settings.SyncBrowserProxy} */ - let syncBrowserProxy = null; - setup(function() { - syncBrowserProxy = new TestSyncBrowserProxy(); - settings.SyncBrowserProxyImpl.instance_ = syncBrowserProxy; PolymerTest.clearBody(); loadTimeData.overrideValues({ migrationEnabled: true, - hasGooglePaymentsAccount: true, - upstreamEnabled: true, - isUsingSecondaryPassphrase: false, - uploadToGoogleActive: true, - userEmailDomainAllowed: true, }); }); @@ -409,8 +399,7 @@ }); test('verifyMigrationButtonNotShownIfMigrationNotEnabled', function() { - // Mock the Google Payments account. Disable the migration experimental - // flag. Won't show migration button. + // Mock prerequisites are not met. loadTimeData.overrideValues({migrationEnabled: false}); // Add one migratable credit card. @@ -419,196 +408,31 @@ const section = createPaymentsSection( [creditCard], {credit_card_enabled: {value: true}}); - // Simulate Signed-in and Synced status. - sync_test_util.simulateSyncStatus({ - signedIn: true, - syncSystemEnabled: true, - }); - - // All migration requirements are met but migration experimental flag is - // not enabled, verify migration button is hidden. assertTrue(section.$$('#migrateCreditCards').hidden); }); - test('verifyMigrationButtonNotShownIfNotSignedIn', function() { + test('verifyMigrationButtonNotShownIfCreditCardDisabled', function() { // Add one migratable credit card. const creditCard = FakeDataMaker.creditCardEntry(); creditCard.metadata.isMigratable = true; + // Mock credit card save toggle is turned off by users. const section = createPaymentsSection( - [creditCard], {credit_card_enabled: {value: true}}); + [creditCard], {credit_card_enabled: {value: false}}); - // Simulate not Signed-in status. Won't show migration button. - sync_test_util.simulateSyncStatus({ - signedIn: false, - syncSystemEnabled: true, - }); - - // All migration requirements are met but not signed in, verify migration - // button is hidden. assertTrue(section.$$('#migrateCreditCards').hidden); }); - test('verifyMigrationButtonNotShownIfNotSynced', function() { + test('verifyMigrationButtonNotShownIfNoCardIsMigratable', function() { // Add one migratable credit card. const creditCard = FakeDataMaker.creditCardEntry(); - creditCard.metadata.isMigratable = true; - const section = createPaymentsSection( - [creditCard], {credit_card_enabled: {value: true}}); - - // Simulate not Synced status. Won't show migration button. - sync_test_util.simulateSyncStatus({ - signedIn: true, - syncSystemEnabled: false, - }); - - // All migration requirements are met but not Synced, verify migration - // button is hidden. - assertTrue(section.$$('#migrateCreditCards').hidden); - }); - - test('verifyMigrationButtonNotShownIfNoMigratableCard', function() { - // Add one credit card but not migratable. Won't show migration button. - const creditCard = FakeDataMaker.creditCardEntry(); + // Mock credit card is not valid. creditCard.metadata.isMigratable = false; const section = createPaymentsSection( [creditCard], {credit_card_enabled: {value: true}}); - // Simulate Signed-in and Synced status. - sync_test_util.simulateSyncStatus({ - signedIn: true, - syncSystemEnabled: true, - }); - - // All migration requirements are met but no migratable credi card, verify - // migration button is hidden. assertTrue(section.$$('#migrateCreditCards').hidden); }); - test('verifyMigrationButtonNotShownWhenCreditCardDisabled', function() { - // Add one migratable credit card. - const creditCard = FakeDataMaker.creditCardEntry(); - creditCard.metadata.isMigratable = true; - const section = createPaymentsSection( - [creditCard], {credit_card_enabled: {value: false}}); - - // Simulate Signed-in and Synced status. - sync_test_util.simulateSyncStatus({ - signedIn: true, - syncSystemEnabled: true, - }); - - // All migration requirements are met but credit card is disable, verify - // migration button is hidden. - assertTrue(section.$$('#migrateCreditCards').hidden); - }); - - test('verifyMigrationButtonNotShownIfNoGooglePaymentsAccount', function() { - // Mocks no Google payments account. Won't show migration button. - loadTimeData.overrideValues({hasGooglePaymentsAccount: false}); - - // Add one migratable credit card. - const creditCard = FakeDataMaker.creditCardEntry(); - creditCard.metadata.isMigratable = true; - const section = createPaymentsSection( - [creditCard], {credit_card_enabled: {value: true}}); - - // Simulate Signed-in and Synced status. - sync_test_util.simulateSyncStatus({ - signedIn: true, - syncSystemEnabled: true, - }); - - // All migration requirements are met but no Google Payments account, - // verify migration button is hidden. - assertTrue(section.$$('#migrateCreditCards').hidden); - }); - - test('verifyMigrationButtonNotShownIfAutofillUpstreamDisabled', function() { - loadTimeData.overrideValues({upstreamEnabled: false}); - - // Add one migratable credit card. - const creditCard = FakeDataMaker.creditCardEntry(); - creditCard.metadata.isMigratable = true; - const section = createPaymentsSection( - [creditCard], {credit_card_enabled: {value: true}}); - - // Simulate Signed-in and Synced status. - sync_test_util.simulateSyncStatus({ - signedIn: true, - syncSystemEnabled: true, - }); - - // All migration requirements are met but Autofill Upstream is disabled, - // verify migration button is hidden. - assertTrue(section.$$('#migrateCreditCards').hidden); - }); - - test( - 'verifyMigrationButtonNotShownIfUserHasSecondaryPassphrase', - function() { - loadTimeData.overrideValues({isUsingSecondaryPassphrase: true}); - - // Add one migratable credit card. - const creditCard = FakeDataMaker.creditCardEntry(); - creditCard.metadata.isMigratable = true; - const section = createPaymentsSection( - [creditCard], {credit_card_enabled: {value: true}}); - - // Simulate Signed-in and Synced status. - sync_test_util.simulateSyncStatus({ - signedIn: true, - syncSystemEnabled: true, - }); - - // All migration requirements are met but the user has a secondary - // passphrase, verify migration button is hidden. - assertTrue(section.$$('#migrateCreditCards').hidden); - }); - - test( - 'verifyMigrationButtonNotShownIfUploadToGoogleStateIsInactive', - function() { - loadTimeData.overrideValues({uploadToGoogleActive: false}); - - // Add one migratable credit card. - const creditCard = FakeDataMaker.creditCardEntry(); - creditCard.metadata.isMigratable = true; - const section = createPaymentsSection( - [creditCard], {credit_card_enabled: {value: true}}); - - // Simulate Signed-in and Synced status. - sync_test_util.simulateSyncStatus({ - signedIn: true, - syncSystemEnabled: true, - }); - - // All migration requirements are met but upload to Google is - // inactive, verify migration button is hidden. - assertTrue(section.$$('#migrateCreditCards').hidden); - }); - - test( - 'verifyMigrationButtonNotShownIfUserEmailDomainIsNotAllowed', - function() { - loadTimeData.overrideValues({userEmailDomainAllowed: false}); - - // Add one migratable credit card. - const creditCard = FakeDataMaker.creditCardEntry(); - creditCard.metadata.isMigratable = true; - const section = createPaymentsSection( - [creditCard], {credit_card_enabled: {value: true}}); - - // Simulate Signed-in and Synced status. - sync_test_util.simulateSyncStatus({ - signedIn: true, - syncSystemEnabled: true, - }); - - // All migration requirements are met but the user's email domain is - // not allowed, verify migration button is hidden. - assertTrue(section.$$('#migrateCreditCards').hidden); - }); - test('verifyMigrationButtonShown', function() { // Add one migratable credit card. const creditCard = FakeDataMaker.creditCardEntry(); @@ -616,13 +440,6 @@ const section = createPaymentsSection( [creditCard], {credit_card_enabled: {value: true}}); - // Simulate Signed-in and Synced status. - sync_test_util.simulateSyncStatus({ - signedIn: true, - syncSystemEnabled: true, - }); - - // All migration requirements are met, verify migration button is shown. assertFalse(section.$$('#migrateCreditCards').hidden); }); });
diff --git a/chrome/test/data/xr/e2e_test_files/html/test_stationary_reference_space_rejects.html b/chrome/test/data/xr/e2e_test_files/html/test_stationary_reference_space_rejects.html new file mode 100644 index 0000000..12cf99a --- /dev/null +++ b/chrome/test/data/xr/e2e_test_files/html/test_stationary_reference_space_rejects.html
@@ -0,0 +1,28 @@ +<!doctype html> +<!-- +Tests that a request for a stationary reference space is rejected. +--> +<html> + <head> + <link rel="stylesheet" type="text/css" href="../resources/webxr_e2e.css"> + </head> + <body> + <script src="../../../../../../third_party/blink/web_tests/resources/testharness.js"></script> + <script src="../resources/webxr_e2e.js"></script> + <script> + let session_ = null; + navigator.xr.requestSession() + .then((xrSession) => { + session_ = xrSession; + return xrSession.requestReferenceSpace({ type: 'stationary', subtype: 'floor-level'}); + }) + .then((refSpace) => { + assert_unreached("Should not be able to get a stationary reference space"); + }, (err) => { + assert_not_equals(session_, null, "Ensure session was created"); + assert_equals(err.name, "NotSupportedError", "Ensure we got the right error"); + done(); + }); + </script> + </body> +</html>
diff --git a/chrome/test/mini_installer/test_chrome_with_chromedriver.py b/chrome/test/mini_installer/test_chrome_with_chromedriver.py index b492bb4..fd8fd80 100644 --- a/chrome/test/mini_installer/test_chrome_with_chromedriver.py +++ b/chrome/test/mini_installer/test_chrome_with_chromedriver.py
@@ -45,13 +45,13 @@ @contextlib.contextmanager def CreateChromedriver(args): - """Create a webdriver object ad close it after.""" + """Create a webdriver object and close it after.""" def DeleteWithRetry(path, func): # There seems to be a race condition on the bots that causes the paths - # to not delete because they are being used. This allows up to 2 seconds + # to not delete because they are being used. This allows up to 4 seconds # to delete - for _ in xrange(4): + for _ in xrange(8): try: return func(path) except WindowsError: @@ -129,18 +129,17 @@ target = os.path.join(args.output_dir, os.path.basename(log_file)) shutil.copyfile(log_file, target) logging.error('Saved Chrome log to %s', target) - DeleteWithRetry(log_file, os.remove) + try: + DeleteWithRetry(log_file, os.remove) + except WindowsError: + # Don't fail the test if the log file couldn't be deleted. + logging.exception('Failed to delete log file %s' % log_file) if report_count: raise Exception('Failing test due to %s crash reports found' % report_count) def main(): - # DISABLING - # https://crbug.com/949727 - # DISABLING - return 0 - """Main entry point.""" parser = parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn index 8f5ff9e..9a62e07 100644 --- a/chromeos/dbus/BUILD.gn +++ b/chromeos/dbus/BUILD.gn
@@ -158,6 +158,8 @@ "shill/modem_messaging_client.h", "shill/shill_client_helper.cc", "shill/shill_client_helper.h", + "shill/shill_clients.cc", + "shill/shill_clients.h", "shill/shill_device_client.cc", "shill/shill_device_client.h", "shill/shill_ipconfig_client.cc",
diff --git a/chromeos/dbus/README.md b/chromeos/dbus/README.md index e664e10f..48bb688b 100644 --- a/chromeos/dbus/README.md +++ b/chromeos/dbus/README.md
@@ -41,6 +41,15 @@ (Many existing clients provide additional test functionality in the fake implementation, however this complicates tests and the fake implementation). +## Shill clients + +Shill clients will eventually only be available to Chrome. As such, the +DBusThreadManager::GetShill*Client() methods have been left intact for now. +However, the clients are no longer owned by DBusClientsCommon so that they can +be initialized independent of DBusThreadManager. + +New code should prefer Shill*Client::Get() over the DBusThreadManager accessors. + ## Older clients that have been removed: * Amplifier (`amplifier_client.cc`)
diff --git a/chromeos/dbus/dbus_clients_common.cc b/chromeos/dbus/dbus_clients_common.cc index 1a628086..6367250e 100644 --- a/chromeos/dbus/dbus_clients_common.cc +++ b/chromeos/dbus/dbus_clients_common.cc
@@ -4,30 +4,10 @@ #include "chromeos/dbus/dbus_clients_common.h" -#include "base/command_line.h" -#include "chromeos/dbus/constants/dbus_switches.h" #include "chromeos/dbus/cras_audio_client.h" #include "chromeos/dbus/dbus_client_implementation_type.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_cras_audio_client.h" -#include "chromeos/dbus/shill/fake_gsm_sms_client.h" -#include "chromeos/dbus/shill/fake_modem_messaging_client.h" -#include "chromeos/dbus/shill/fake_shill_device_client.h" -#include "chromeos/dbus/shill/fake_shill_ipconfig_client.h" -#include "chromeos/dbus/shill/fake_shill_manager_client.h" -#include "chromeos/dbus/shill/fake_shill_profile_client.h" -#include "chromeos/dbus/shill/fake_shill_service_client.h" -#include "chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h" -#include "chromeos/dbus/shill/fake_sms_client.h" -#include "chromeos/dbus/shill/gsm_sms_client.h" -#include "chromeos/dbus/shill/modem_messaging_client.h" -#include "chromeos/dbus/shill/shill_device_client.h" -#include "chromeos/dbus/shill/shill_ipconfig_client.h" -#include "chromeos/dbus/shill/shill_manager_client.h" -#include "chromeos/dbus/shill/shill_profile_client.h" -#include "chromeos/dbus/shill/shill_service_client.h" -#include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h" -#include "chromeos/dbus/shill/sms_client.h" namespace chromeos { @@ -36,44 +16,6 @@ cras_audio_client_.reset(CrasAudioClient::Create()); else cras_audio_client_.reset(new FakeCrasAudioClient); - - if (use_real_clients) { - shill_manager_client_.reset(ShillManagerClient::Create()); - shill_device_client_.reset(ShillDeviceClient::Create()); - shill_ipconfig_client_.reset(ShillIPConfigClient::Create()); - shill_service_client_.reset(ShillServiceClient::Create()); - shill_profile_client_.reset(ShillProfileClient::Create()); - shill_third_party_vpn_driver_client_.reset( - ShillThirdPartyVpnDriverClient::Create()); - } else { - shill_manager_client_.reset(new FakeShillManagerClient); - shill_device_client_.reset(new FakeShillDeviceClient); - shill_ipconfig_client_.reset(new FakeShillIPConfigClient); - shill_service_client_.reset(new FakeShillServiceClient); - shill_profile_client_.reset(new FakeShillProfileClient); - shill_third_party_vpn_driver_client_.reset( - new FakeShillThirdPartyVpnDriverClient); - } - - if (use_real_clients) { - gsm_sms_client_.reset(GsmSMSClient::Create()); - } else { - FakeGsmSMSClient* gsm_sms_client = new FakeGsmSMSClient(); - gsm_sms_client->set_sms_test_message_switch_present( - base::CommandLine::ForCurrentProcess()->HasSwitch( - chromeos::switches::kSmsTestMessages)); - gsm_sms_client_.reset(gsm_sms_client); - } - - if (use_real_clients) - modem_messaging_client_.reset(ModemMessagingClient::Create()); - else - modem_messaging_client_.reset(new FakeModemMessagingClient); - - if (use_real_clients) - sms_client_.reset(SMSClient::Create()); - else - sms_client_.reset(new FakeSMSClient); } DBusClientsCommon::~DBusClientsCommon() = default; @@ -82,20 +24,6 @@ DCHECK(DBusThreadManager::IsInitialized()); cras_audio_client_->Init(system_bus); - gsm_sms_client_->Init(system_bus); - modem_messaging_client_->Init(system_bus); - shill_device_client_->Init(system_bus); - shill_ipconfig_client_->Init(system_bus); - shill_manager_client_->Init(system_bus); - shill_service_client_->Init(system_bus); - shill_profile_client_->Init(system_bus); - shill_third_party_vpn_driver_client_->Init(system_bus); - sms_client_->Init(system_bus); - - ShillManagerClient::TestInterface* manager = - shill_manager_client_->GetTestInterface(); - if (manager) - manager->SetupDefaultEnvironment(); } } // namespace chromeos
diff --git a/chromeos/dbus/dbus_clients_common.h b/chromeos/dbus/dbus_clients_common.h index bbbe6d1..f8d26ce 100644 --- a/chromeos/dbus/dbus_clients_common.h +++ b/chromeos/dbus/dbus_clients_common.h
@@ -17,15 +17,6 @@ namespace chromeos { class CrasAudioClient; -class GsmSMSClient; -class ModemMessagingClient; -class ShillDeviceClient; -class ShillIPConfigClient; -class ShillManagerClient; -class ShillProfileClient; -class ShillServiceClient; -class ShillThirdPartyVpnDriverClient; -class SMSClient; // D-Bus clients used in multiple processes (e.g. ash, browser, mus). class COMPONENT_EXPORT(CHROMEOS_DBUS) DBusClientsCommon { @@ -43,16 +34,6 @@ friend class DBusThreadManagerSetter; std::unique_ptr<CrasAudioClient> cras_audio_client_; - std::unique_ptr<GsmSMSClient> gsm_sms_client_; - std::unique_ptr<ModemMessagingClient> modem_messaging_client_; - std::unique_ptr<ShillDeviceClient> shill_device_client_; - std::unique_ptr<ShillIPConfigClient> shill_ipconfig_client_; - std::unique_ptr<ShillManagerClient> shill_manager_client_; - std::unique_ptr<ShillServiceClient> shill_service_client_; - std::unique_ptr<ShillProfileClient> shill_profile_client_; - std::unique_ptr<ShillThirdPartyVpnDriverClient> - shill_third_party_vpn_driver_client_; - std::unique_ptr<SMSClient> sms_client_; DISALLOW_COPY_AND_ASSIGN(DBusClientsCommon); };
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc index 15846c2..de4e5cd4 100644 --- a/chromeos/dbus/dbus_thread_manager.cc +++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -32,6 +32,7 @@ #include "chromeos/dbus/seneschal_client.h" #include "chromeos/dbus/shill/gsm_sms_client.h" #include "chromeos/dbus/shill/modem_messaging_client.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/dbus/shill/shill_device_client.h" #include "chromeos/dbus/shill/shill_ipconfig_client.h" #include "chromeos/dbus/shill/shill_manager_client.h" @@ -166,32 +167,32 @@ } ShillDeviceClient* DBusThreadManager::GetShillDeviceClient() { - return clients_common_->shill_device_client_.get(); + return ShillDeviceClient::Get(); } ShillIPConfigClient* DBusThreadManager::GetShillIPConfigClient() { - return clients_common_->shill_ipconfig_client_.get(); + return ShillIPConfigClient::Get(); } ShillManagerClient* DBusThreadManager::GetShillManagerClient() { - return clients_common_->shill_manager_client_.get(); + return ShillManagerClient::Get(); } ShillServiceClient* DBusThreadManager::GetShillServiceClient() { - return clients_common_->shill_service_client_.get(); + return ShillServiceClient::Get(); } ShillProfileClient* DBusThreadManager::GetShillProfileClient() { - return clients_common_->shill_profile_client_.get(); + return ShillProfileClient::Get(); } ShillThirdPartyVpnDriverClient* DBusThreadManager::GetShillThirdPartyVpnDriverClient() { - return clients_common_->shill_third_party_vpn_driver_client_.get(); + return ShillThirdPartyVpnDriverClient::Get(); } GsmSMSClient* DBusThreadManager::GetGsmSMSClient() { - return clients_common_->gsm_sms_client_.get(); + return GsmSMSClient::Get(); } ImageBurnerClient* DBusThreadManager::GetImageBurnerClient() { @@ -210,7 +211,7 @@ } ModemMessagingClient* DBusThreadManager::GetModemMessagingClient() { - return clients_common_->modem_messaging_client_.get(); + return ModemMessagingClient::Get(); } OobeConfigurationClient* DBusThreadManager::GetOobeConfigurationClient() { @@ -232,7 +233,7 @@ } SMSClient* DBusThreadManager::GetSMSClient() { - return clients_common_->sms_client_.get(); + return SMSClient::Get(); } UpdateEngineClient* DBusThreadManager::GetUpdateEngineClient() { @@ -251,6 +252,14 @@ DCHECK(g_dbus_thread_manager); clients_common_->Initialize(GetSystemBus()); + + // TODO(stevenjb): Move these to dbus_helper.cc in src/chrome and any tests + // that require Shill clients. https://crbug.com/948390. + if (use_real_clients_) + shill_clients::Initialize(GetSystemBus()); + else + shill_clients::InitializeFakes(); + if (clients_browser_) clients_browser_->Initialize(GetSystemBus()); @@ -309,6 +318,10 @@ void DBusThreadManager::Shutdown() { // Ensure that we only shutdown DBusThreadManager once. CHECK(g_dbus_thread_manager); + + // TODO(stevenjb): Remove. https://crbug.com/948390. + shill_clients::Shutdown(); + DBusThreadManager* dbus_thread_manager = g_dbus_thread_manager; g_dbus_thread_manager = nullptr; g_using_dbus_thread_manager_for_testing = false; @@ -369,43 +382,6 @@ std::move(client); } -void DBusThreadManagerSetter::SetShillDeviceClient( - std::unique_ptr<ShillDeviceClient> client) { - DBusThreadManager::Get()->clients_common_->shill_device_client_ = - std::move(client); -} - -void DBusThreadManagerSetter::SetShillIPConfigClient( - std::unique_ptr<ShillIPConfigClient> client) { - DBusThreadManager::Get()->clients_common_->shill_ipconfig_client_ = - std::move(client); -} - -void DBusThreadManagerSetter::SetShillManagerClient( - std::unique_ptr<ShillManagerClient> client) { - DBusThreadManager::Get()->clients_common_->shill_manager_client_ = - std::move(client); -} - -void DBusThreadManagerSetter::SetShillServiceClient( - std::unique_ptr<ShillServiceClient> client) { - DBusThreadManager::Get()->clients_common_->shill_service_client_ = - std::move(client); -} - -void DBusThreadManagerSetter::SetShillProfileClient( - std::unique_ptr<ShillProfileClient> client) { - DBusThreadManager::Get()->clients_common_->shill_profile_client_ = - std::move(client); -} - -void DBusThreadManagerSetter::SetShillThirdPartyVpnDriverClient( - std::unique_ptr<ShillThirdPartyVpnDriverClient> client) { - DBusThreadManager::Get() - ->clients_common_->shill_third_party_vpn_driver_client_ = - std::move(client); -} - void DBusThreadManagerSetter::SetImageBurnerClient( std::unique_ptr<ImageBurnerClient> client) { DBusThreadManager::Get()->clients_browser_->image_burner_client_ =
diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h index 63ff079e8..b5efc2e 100644 --- a/chromeos/dbus/dbus_thread_manager.h +++ b/chromeos/dbus/dbus_thread_manager.h
@@ -128,24 +128,27 @@ DebugDaemonClient* GetDebugDaemonClient(); DiagnosticsdClient* GetDiagnosticsdClient(); EasyUnlockClient* GetEasyUnlockClient(); - GsmSMSClient* GetGsmSMSClient(); ImageBurnerClient* GetImageBurnerClient(); ImageLoaderClient* GetImageLoaderClient(); LorgnetteManagerClient* GetLorgnetteManagerClient(); - ModemMessagingClient* GetModemMessagingClient(); OobeConfigurationClient* GetOobeConfigurationClient(); RuntimeProbeClient* GetRuntimeProbeClient(); SeneschalClient* GetSeneschalClient(); + SmbProviderClient* GetSmbProviderClient(); + UpdateEngineClient* GetUpdateEngineClient(); + VirtualFileProviderClient* GetVirtualFileProviderClient(); + + // DEPRECATED, DO NOT USE. The static getter for each of these classes should + // be used instead. TODO(stevenjb): Remove. https://crbug.com/948390. + GsmSMSClient* GetGsmSMSClient(); + ModemMessagingClient* GetModemMessagingClient(); + SMSClient* GetSMSClient(); ShillDeviceClient* GetShillDeviceClient(); ShillIPConfigClient* GetShillIPConfigClient(); ShillManagerClient* GetShillManagerClient(); ShillProfileClient* GetShillProfileClient(); ShillServiceClient* GetShillServiceClient(); ShillThirdPartyVpnDriverClient* GetShillThirdPartyVpnDriverClient(); - SmbProviderClient* GetSmbProviderClient(); - SMSClient* GetSMSClient(); - UpdateEngineClient* GetUpdateEngineClient(); - VirtualFileProviderClient* GetVirtualFileProviderClient(); private: friend class DBusThreadManagerSetter; @@ -188,13 +191,6 @@ void SetImageLoaderClient(std::unique_ptr<ImageLoaderClient> client); void SetSeneschalClient(std::unique_ptr<SeneschalClient> client); void SetRuntimeProbeClient(std::unique_ptr<RuntimeProbeClient> client); - void SetShillDeviceClient(std::unique_ptr<ShillDeviceClient> client); - void SetShillIPConfigClient(std::unique_ptr<ShillIPConfigClient> client); - void SetShillManagerClient(std::unique_ptr<ShillManagerClient> client); - void SetShillServiceClient(std::unique_ptr<ShillServiceClient> client); - void SetShillProfileClient(std::unique_ptr<ShillProfileClient> client); - void SetShillThirdPartyVpnDriverClient( - std::unique_ptr<ShillThirdPartyVpnDriverClient> client); void SetSmbProviderClient(std::unique_ptr<SmbProviderClient> client); void SetUpdateEngineClient(std::unique_ptr<UpdateEngineClient> client);
diff --git a/chromeos/dbus/shill/fake_gsm_sms_client.cc b/chromeos/dbus/shill/fake_gsm_sms_client.cc index 5b3ad438..77301505 100644 --- a/chromeos/dbus/shill/fake_gsm_sms_client.cc +++ b/chromeos/dbus/shill/fake_gsm_sms_client.cc
@@ -2,22 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <stdint.h> +#include "chromeos/dbus/shill/fake_gsm_sms_client.h" +#include <stdint.h> #include <memory> #include <utility> #include "base/bind.h" +#include "base/command_line.h" #include "base/location.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "chromeos/dbus/shill/fake_gsm_sms_client.h" +#include "chromeos/dbus/constants/dbus_switches.h" namespace chromeos { FakeGsmSMSClient::FakeGsmSMSClient() : test_index_(-1), - sms_test_message_switch_present_(false), + sms_test_message_switch_present_( + base::CommandLine::ForCurrentProcess()->HasSwitch( + chromeos::switches::kSmsTestMessages)), weak_ptr_factory_(this) { test_messages_.push_back("Test Message 0"); test_messages_.push_back("Test Message 1"); @@ -32,8 +36,6 @@ FakeGsmSMSClient::~FakeGsmSMSClient() = default; -void FakeGsmSMSClient::Init(dbus::Bus* bus) {} - void FakeGsmSMSClient::SetSmsReceivedHandler( const std::string& service_name, const dbus::ObjectPath& object_path,
diff --git a/chromeos/dbus/shill/fake_gsm_sms_client.h b/chromeos/dbus/shill/fake_gsm_sms_client.h index 12d46a4..7d86470 100644 --- a/chromeos/dbus/shill/fake_gsm_sms_client.h +++ b/chromeos/dbus/shill/fake_gsm_sms_client.h
@@ -25,7 +25,6 @@ ~FakeGsmSMSClient() override; // GsmSMSClient overrides - void Init(dbus::Bus* bus) override; void SetSmsReceivedHandler(const std::string& service_name, const dbus::ObjectPath& object_path, const SmsReceivedHandler& handler) override; @@ -45,12 +44,6 @@ void RequestUpdate(const std::string& service_name, const dbus::ObjectPath& object_path) override; - // Sets if the command line switch for test is present. RequestUpdate() - // changes its behavior depending on the switch. - void set_sms_test_message_switch_present(bool is_present) { - sms_test_message_switch_present_ = is_present; - } - private: void PushTestMessageChain(); void PushTestMessageDelayed();
diff --git a/chromeos/dbus/shill/fake_modem_messaging_client.cc b/chromeos/dbus/shill/fake_modem_messaging_client.cc index c9d66e9..926236f 100644 --- a/chromeos/dbus/shill/fake_modem_messaging_client.cc +++ b/chromeos/dbus/shill/fake_modem_messaging_client.cc
@@ -17,8 +17,6 @@ FakeModemMessagingClient::FakeModemMessagingClient() = default; FakeModemMessagingClient::~FakeModemMessagingClient() = default; -void FakeModemMessagingClient::Init(dbus::Bus* bus) {} - void FakeModemMessagingClient::SetSmsReceivedHandler( const std::string& service_name, const dbus::ObjectPath& object_path,
diff --git a/chromeos/dbus/shill/fake_modem_messaging_client.h b/chromeos/dbus/shill/fake_modem_messaging_client.h index 5dce655b..9cb26299 100644 --- a/chromeos/dbus/shill/fake_modem_messaging_client.h +++ b/chromeos/dbus/shill/fake_modem_messaging_client.h
@@ -21,7 +21,6 @@ FakeModemMessagingClient(); ~FakeModemMessagingClient() override; - void Init(dbus::Bus* bus) override; void SetSmsReceivedHandler(const std::string& service_name, const dbus::ObjectPath& object_path, const SmsReceivedHandler& handler) override;
diff --git a/chromeos/dbus/shill/fake_shill_device_client.cc b/chromeos/dbus/shill/fake_shill_device_client.cc index a3ef2f4..4bf5009 100644 --- a/chromeos/dbus/shill/fake_shill_device_client.cc +++ b/chromeos/dbus/shill/fake_shill_device_client.cc
@@ -16,7 +16,6 @@ #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "chromeos/dbus/shill/shill_property_changed_observer.h" #include "dbus/bus.h" @@ -73,8 +72,6 @@ // ShillDeviceClient overrides. -void FakeShillDeviceClient::Init(dbus::Bus* bus) {} - void FakeShillDeviceClient::AddPropertyChangedObserver( const dbus::ObjectPath& device_path, ShillPropertyChangedObserver* observer) { @@ -114,7 +111,7 @@ const base::Closure& callback, const ErrorCallback& error_callback, bool notify_changed) { - base::DictionaryValue* device_properties = NULL; + base::DictionaryValue* device_properties = nullptr; if (!stub_devices_.GetDictionaryWithoutPathExpansion(device_path.value(), &device_properties)) { PostNotFoundError(error_callback); @@ -133,13 +130,13 @@ void FakeShillDeviceClient::ClearProperty(const dbus::ObjectPath& device_path, const std::string& name, VoidDBusMethodCallback callback) { - base::DictionaryValue* device_properties = NULL; + base::DictionaryValue* device_properties = nullptr; if (!stub_devices_.GetDictionaryWithoutPathExpansion(device_path.value(), &device_properties)) { PostVoidCallback(std::move(callback), false); return; } - device_properties->RemoveWithoutPathExpansion(name, NULL); + device_properties->RemoveWithoutPathExpansion(name, nullptr); PostVoidCallback(std::move(callback), true); } @@ -428,10 +425,7 @@ void FakeShillDeviceClient::AddDevice(const std::string& device_path, const std::string& type, const std::string& name) { - DBusThreadManager::Get() - ->GetShillManagerClient() - ->GetTestInterface() - ->AddDevice(device_path); + ShillManagerClient::Get()->GetTestInterface()->AddDevice(device_path); base::Value* properties = GetDeviceProperties(device_path); properties->SetKey(shill::kTypeProperty, base::Value(type)); @@ -446,20 +440,12 @@ } void FakeShillDeviceClient::RemoveDevice(const std::string& device_path) { - DBusThreadManager::Get() - ->GetShillManagerClient() - ->GetTestInterface() - ->RemoveDevice(device_path); - - stub_devices_.RemoveWithoutPathExpansion(device_path, NULL); + ShillManagerClient::Get()->GetTestInterface()->RemoveDevice(device_path); + stub_devices_.RemoveWithoutPathExpansion(device_path, nullptr); } void FakeShillDeviceClient::ClearDevices() { - DBusThreadManager::Get() - ->GetShillManagerClient() - ->GetTestInterface() - ->ClearDevices(); - + ShillManagerClient::Get()->GetTestInterface()->ClearDevices(); stub_devices_.Clear(); } @@ -478,7 +464,7 @@ const std::string& type) { for (base::DictionaryValue::Iterator iter(stub_devices_); !iter.IsAtEnd(); iter.Advance()) { - const base::DictionaryValue* properties = NULL; + const base::DictionaryValue* properties = nullptr; if (!iter.value().GetAsDictionary(&properties)) continue; std::string prop_type; @@ -653,7 +639,7 @@ void FakeShillDeviceClient::PassStubDeviceProperties( const dbus::ObjectPath& device_path, const DictionaryValueCallback& callback) const { - const base::DictionaryValue* device_properties = NULL; + const base::DictionaryValue* device_properties = nullptr; if (!stub_devices_.GetDictionaryWithoutPathExpansion(device_path.value(), &device_properties)) { base::DictionaryValue empty_dictionary; @@ -673,13 +659,13 @@ void FakeShillDeviceClient::NotifyObserversPropertyChanged( const dbus::ObjectPath& device_path, const std::string& property) { - base::DictionaryValue* dict = NULL; + base::DictionaryValue* dict = nullptr; std::string path = device_path.value(); if (!stub_devices_.GetDictionaryWithoutPathExpansion(path, &dict)) { LOG(ERROR) << "Notify for unknown device: " << path; return; } - base::Value* value = NULL; + base::Value* value = nullptr; if (!dict->GetWithoutPathExpansion(property, &value)) { LOG(ERROR) << "Notify for unknown property: " << path << " : " << property; return;
diff --git a/chromeos/dbus/shill/fake_shill_device_client.h b/chromeos/dbus/shill/fake_shill_device_client.h index 1e658f76..f2ee167 100644 --- a/chromeos/dbus/shill/fake_shill_device_client.h +++ b/chromeos/dbus/shill/fake_shill_device_client.h
@@ -27,7 +27,6 @@ ~FakeShillDeviceClient() override; // ShillDeviceClient overrides - void Init(dbus::Bus* bus) override; void AddPropertyChangedObserver( const dbus::ObjectPath& device_path, ShillPropertyChangedObserver* observer) override;
diff --git a/chromeos/dbus/shill/fake_shill_ipconfig_client.cc b/chromeos/dbus/shill/fake_shill_ipconfig_client.cc index 652f34015..57a8b6f 100644 --- a/chromeos/dbus/shill/fake_shill_ipconfig_client.cc +++ b/chromeos/dbus/shill/fake_shill_ipconfig_client.cc
@@ -27,8 +27,6 @@ FakeShillIPConfigClient::~FakeShillIPConfigClient() = default; -void FakeShillIPConfigClient::Init(dbus::Bus* bus) {} - void FakeShillIPConfigClient::AddPropertyChangedObserver( const dbus::ObjectPath& ipconfig_path, ShillPropertyChangedObserver* observer) {} @@ -43,7 +41,7 @@ void FakeShillIPConfigClient::GetProperties( const dbus::ObjectPath& ipconfig_path, const DictionaryValueCallback& callback) { - const base::DictionaryValue* dict = NULL; + const base::DictionaryValue* dict = nullptr; if (!ipconfigs_.GetDictionaryWithoutPathExpansion(ipconfig_path.value(), &dict)) return;
diff --git a/chromeos/dbus/shill/fake_shill_ipconfig_client.h b/chromeos/dbus/shill/fake_shill_ipconfig_client.h index dd210429..7d332bb 100644 --- a/chromeos/dbus/shill/fake_shill_ipconfig_client.h +++ b/chromeos/dbus/shill/fake_shill_ipconfig_client.h
@@ -22,7 +22,6 @@ ~FakeShillIPConfigClient() override; // ShillIPConfigClient overrides - void Init(dbus::Bus* bus) override; void AddPropertyChangedObserver( const dbus::ObjectPath& ipconfig_path, ShillPropertyChangedObserver* observer) override;
diff --git a/chromeos/dbus/shill/fake_shill_manager_client.cc b/chromeos/dbus/shill/fake_shill_manager_client.cc index c25967f..6c8aa4d0b 100644 --- a/chromeos/dbus/shill/fake_shill_manager_client.cc +++ b/chromeos/dbus/shill/fake_shill_manager_client.cc
@@ -20,7 +20,6 @@ #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "chromeos/dbus/constants/dbus_switches.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/fake_shill_device_client.h" #include "chromeos/dbus/shill/shill_device_client.h" #include "chromeos/dbus/shill/shill_ipconfig_client.h" @@ -186,11 +185,8 @@ } void UpdatePortaledWifiState(const std::string& service_path) { - DBusThreadManager::Get() - ->GetShillServiceClient() - ->GetTestInterface() - ->SetServiceProperty(service_path, shill::kStateProperty, - base::Value(shill::kStatePortal)); + ShillServiceClient::Get()->GetTestInterface()->SetServiceProperty( + service_path, shill::kStateProperty, base::Value(shill::kStatePortal)); } bool IsCellularTechnology(const std::string& type) { @@ -209,10 +205,8 @@ void SetInitialDeviceProperty(const std::string& device_path, const std::string& name, const base::Value& value) { - DBusThreadManager::Get() - ->GetShillDeviceClient() - ->GetTestInterface() - ->SetDeviceProperty(device_path, name, value, /*notify_changed=*/false); + ShillDeviceClient::Get()->GetTestInterface()->SetDeviceProperty( + device_path, name, value, /*notify_changed=*/false); } const char kPathKey[] = "path"; @@ -241,8 +235,6 @@ // ShillManagerClient overrides. -void FakeShillManagerClient::Init(dbus::Bus* bus) {} - void FakeShillManagerClient::AddPropertyChangedObserver( ShillPropertyChangedObserver* observer) { observer_list_.AddObserver(observer); @@ -285,7 +277,7 @@ // For Stub purposes, default to a Wifi scan. std::string device_type = type.empty() ? shill::kTypeWifi : type; ShillDeviceClient::TestInterface* device_client = - DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface(); + ShillDeviceClient::Get()->GetTestInterface(); std::string device_path = device_client->GetDevicePathForType(device_type); if (!device_path.empty()) { device_client->SetDeviceProperty(device_path, shill::kScanningProperty, @@ -345,7 +337,7 @@ const ObjectPathCallback& callback, const ErrorCallback& error_callback) { ShillServiceClient::TestInterface* service_client = - DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); + ShillServiceClient::Get()->GetTestInterface(); std::string guid; std::string type; @@ -394,8 +386,7 @@ merged_properties->GetStringWithoutPathExpansion(shill::kProfileProperty, &profile_path); if (!profile_path.empty()) { - auto* profile_client = - DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface(); + auto* profile_client = ShillProfileClient::Get()->GetTestInterface(); if (!profile_client->UpdateService(profile_path, service_path)) profile_client->AddService(profile_path, service_path); } @@ -431,8 +422,8 @@ return; } - DBusThreadManager::Get()->GetShillServiceClient()->Connect( - dbus::ObjectPath(best_service_), callback, error_callback); + ShillServiceClient::Get()->Connect(dbus::ObjectPath(best_service_), callback, + error_callback); } ShillManagerClient::TestInterface* FakeShillManagerClient::GetTestInterface() { @@ -586,10 +577,9 @@ std::vector<base::Value> complete_dict_list; for (const base::Value& value : complete_path_list->GetList()) { std::string service_path = value.GetString(); - const base::Value* properties = DBusThreadManager::Get() - ->GetShillServiceClient() - ->GetTestInterface() - ->GetServiceProperties(service_path); + const base::Value* properties = + ShillServiceClient::Get()->GetTestInterface()->GetServiceProperties( + service_path); if (!properties) { LOG(ERROR) << "Properties not found for service: " << service_path; continue; @@ -673,18 +663,17 @@ if (!base::ThreadTaskRunnerHandle::IsSet()) return; - DBusThreadManager* dbus_manager = DBusThreadManager::Get(); ShillServiceClient::TestInterface* services = - dbus_manager->GetShillServiceClient()->GetTestInterface(); + ShillServiceClient::Get()->GetTestInterface(); DCHECK(services); ShillProfileClient::TestInterface* profiles = - dbus_manager->GetShillProfileClient()->GetTestInterface(); + ShillProfileClient::Get()->GetTestInterface(); DCHECK(profiles); ShillDeviceClient::TestInterface* devices = - dbus_manager->GetShillDeviceClient()->GetTestInterface(); + ShillDeviceClient::Get()->GetTestInterface(); DCHECK(devices); ShillIPConfigClient::TestInterface* ip_configs = - dbus_manager->GetShillIPConfigClient()->GetTestInterface(); + ShillIPConfigClient::Get()->GetTestInterface(); DCHECK(ip_configs); const std::string shared_profile = ShillProfileClient::GetSharedProfilePath(); @@ -736,10 +725,8 @@ // Wifi if (s_tdls_busy_count != 0) { - DBusThreadManager::Get() - ->GetShillDeviceClient() - ->GetTestInterface() - ->SetTDLSBusyCount(s_tdls_busy_count); + ShillDeviceClient::Get()->GetTestInterface()->SetTDLSBusyCount( + s_tdls_busy_count); } state = GetInitialStateForType(shill::kTypeWifi, &enabled); @@ -1091,7 +1078,7 @@ const base::ListValue* service_list; if (stub_properties_.GetListWithoutPathExpansion(property, &service_list)) { ShillServiceClient::TestInterface* service_client = - DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); + ShillServiceClient::Get()->GetTestInterface(); for (base::ListValue::const_iterator iter = service_list->begin(); iter != service_list->end(); ++iter) { std::string service_path; @@ -1115,11 +1102,9 @@ void FakeShillManagerClient::ScanCompleted(const std::string& device_path, const base::Closure& callback) { if (!device_path.empty()) { - DBusThreadManager::Get() - ->GetShillDeviceClient() - ->GetTestInterface() - ->SetDeviceProperty(device_path, shill::kScanningProperty, - base::Value(false), /*notify_changed=*/true); + ShillDeviceClient::Get()->GetTestInterface()->SetDeviceProperty( + device_path, shill::kScanningProperty, base::Value(false), + /*notify_changed=*/true); } VLOG(1) << "ScanCompleted"; CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
diff --git a/chromeos/dbus/shill/fake_shill_manager_client.h b/chromeos/dbus/shill/fake_shill_manager_client.h index 71c90b8..703b1da 100644 --- a/chromeos/dbus/shill/fake_shill_manager_client.h +++ b/chromeos/dbus/shill/fake_shill_manager_client.h
@@ -28,7 +28,6 @@ ~FakeShillManagerClient() override; // ShillManagerClient overrides - void Init(dbus::Bus* bus) override; void AddPropertyChangedObserver( ShillPropertyChangedObserver* observer) override; void RemovePropertyChangedObserver(
diff --git a/chromeos/dbus/shill/fake_shill_profile_client.cc b/chromeos/dbus/shill/fake_shill_profile_client.cc index 3cd86cf9..7e0dc1b0a 100644 --- a/chromeos/dbus/shill/fake_shill_profile_client.cc +++ b/chromeos/dbus/shill/fake_shill_profile_client.cc
@@ -14,7 +14,6 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_property_changed_observer.h" #include "chromeos/dbus/shill/shill_service_client.h" #include "dbus/bus.h" @@ -45,8 +44,6 @@ FakeShillProfileClient::~FakeShillProfileClient() = default; -void FakeShillProfileClient::Init(dbus::Bus* bus) {} - void FakeShillProfileClient::AddPropertyChangedObserver( const dbus::ObjectPath& profile_path, ShillPropertyChangedObserver* observer) {} @@ -88,7 +85,7 @@ if (!profile) return; - base::DictionaryValue* entry = NULL; + base::DictionaryValue* entry = nullptr; profile->entries.GetDictionaryWithoutPathExpansion(entry_path, &entry); if (!entry) { error_callback.Run("Error.InvalidProfileEntry", "Invalid profile entry"); @@ -108,17 +105,14 @@ if (!profile) return; - if (!profile->entries.RemoveWithoutPathExpansion(entry_path, NULL)) { + if (!profile->entries.RemoveWithoutPathExpansion(entry_path, nullptr)) { error_callback.Run("Error.InvalidProfileEntry", entry_path); return; } base::Value profile_path_value(""); - DBusThreadManager::Get() - ->GetShillServiceClient() - ->GetTestInterface() - ->SetServiceProperty(entry_path, shill::kProfileProperty, - profile_path_value); + ShillServiceClient::Get()->GetTestInterface()->SetServiceProperty( + entry_path, shill::kProfileProperty, profile_path_value); base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); } @@ -142,10 +136,7 @@ profile->path = profile_path; profiles_.emplace_back(std::move(profile)); - DBusThreadManager::Get() - ->GetShillManagerClient() - ->GetTestInterface() - ->AddProfile(profile_path); + ShillManagerClient::Get()->GetTestInterface()->AddProfile(profile_path); } void FakeShillProfileClient::AddEntry(const std::string& profile_path, @@ -155,10 +146,8 @@ GetProfile(dbus::ObjectPath(profile_path), ErrorCallback()); DCHECK(profile); profile->entries.SetKey(entry_path, properties.Clone()); - DBusThreadManager::Get() - ->GetShillManagerClient() - ->GetTestInterface() - ->AddManagerService(entry_path, true); + ShillManagerClient::Get()->GetTestInterface()->AddManagerService(entry_path, + true); } bool FakeShillProfileClient::AddService(const std::string& profile_path, @@ -197,7 +186,7 @@ const std::string& service_path, ProfileProperties* profile) { ShillServiceClient::TestInterface* service_test = - DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); + ShillServiceClient::Get()->GetTestInterface(); const base::DictionaryValue* service_properties = service_test->GetServiceProperties(service_path); if (!service_properties) {
diff --git a/chromeos/dbus/shill/fake_shill_profile_client.h b/chromeos/dbus/shill/fake_shill_profile_client.h index bd5b73f..71400f7 100644 --- a/chromeos/dbus/shill/fake_shill_profile_client.h +++ b/chromeos/dbus/shill/fake_shill_profile_client.h
@@ -25,7 +25,6 @@ ~FakeShillProfileClient() override; // ShillProfileClient overrides - void Init(dbus::Bus* bus) override; void AddPropertyChangedObserver( const dbus::ObjectPath& profile_path, ShillPropertyChangedObserver* observer) override;
diff --git a/chromeos/dbus/shill/fake_shill_service_client.cc b/chromeos/dbus/shill/fake_shill_service_client.cc index e8348bb..4fc8536 100644 --- a/chromeos/dbus/shill/fake_shill_service_client.cc +++ b/chromeos/dbus/shill/fake_shill_service_client.cc
@@ -38,17 +38,11 @@ } void CallSortManagerServices() { - DBusThreadManager::Get() - ->GetShillManagerClient() - ->GetTestInterface() - ->SortManagerServices(true); + ShillManagerClient::Get()->GetTestInterface()->SortManagerServices(true); } int GetInteractiveDelay() { - return DBusThreadManager::Get() - ->GetShillManagerClient() - ->GetTestInterface() - ->GetInteractiveDelay(); + return ShillManagerClient::Get()->GetTestInterface()->GetInteractiveDelay(); } } // namespace @@ -59,8 +53,6 @@ // ShillServiceClient overrides. -void FakeShillServiceClient::Init(dbus::Bus* bus) {} - void FakeShillServiceClient::AddPropertyChangedObserver( const dbus::ObjectPath& service_path, ShillPropertyChangedObserver* observer) { @@ -261,7 +253,7 @@ const dbus::ObjectPath& service_path, const DictionaryValueCallback& callback) { ShillProfileClient::TestInterface* profile_client = - DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface(); + ShillProfileClient::Get()->GetTestInterface(); std::vector<std::string> profiles; profile_client->GetProfilePathsContainingService(service_path.value(), &profiles); @@ -311,10 +303,8 @@ if (!ipconfig_path.empty()) properties->SetKey(shill::kIPConfigProperty, base::Value(ipconfig_path)); - DBusThreadManager::Get() - ->GetShillManagerClient() - ->GetTestInterface() - ->AddManagerService(service_path, true); + ShillManagerClient::Get()->GetTestInterface()->AddManagerService(service_path, + true); } base::DictionaryValue* FakeShillServiceClient::SetServiceProperties( @@ -335,10 +325,8 @@ if (guid_to_set.empty()) { std::string profile_path; base::DictionaryValue profile_properties; - if (DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->GetService(service_path, &profile_path, &profile_properties)) { + if (ShillProfileClient::Get()->GetTestInterface()->GetService( + service_path, &profile_path, &profile_properties)) { profile_properties.GetStringWithoutPathExpansion(shill::kGuidProperty, &guid_to_set); } @@ -350,10 +338,8 @@ properties->SetKey(shill::kWifiHexSsid, base::Value(base::HexEncode(name.c_str(), name.size()))); properties->SetKey(shill::kNameProperty, base::Value(name)); - std::string device_path = DBusThreadManager::Get() - ->GetShillDeviceClient() - ->GetTestInterface() - ->GetDevicePathForType(type); + std::string device_path = + ShillDeviceClient::Get()->GetTestInterface()->GetDevicePathForType(type); properties->SetKey(shill::kDeviceProperty, base::Value(device_path)); properties->SetKey(shill::kTypeProperty, base::Value(type)); properties->SetKey(shill::kStateProperty, base::Value(state)); @@ -374,10 +360,8 @@ void FakeShillServiceClient::RemoveService(const std::string& service_path) { stub_services_.RemoveWithoutPathExpansion(service_path, nullptr); connect_behavior_.erase(service_path); - DBusThreadManager::Get() - ->GetShillManagerClient() - ->GetTestInterface() - ->RemoveManagerService(service_path); + ShillManagerClient::Get()->GetTestInterface()->RemoveManagerService( + service_path); } bool FakeShillServiceClient::SetServiceProperty(const std::string& service_path, @@ -443,7 +427,7 @@ // Add or update the profile entry. ShillProfileClient::TestInterface* profile_test = - DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface(); + ShillProfileClient::Get()->GetTestInterface(); if (property == shill::kProfileProperty) { std::string profile_path; if (value.GetAsString(&profile_path)) { @@ -465,10 +449,8 @@ if (property == shill::kStateProperty) { std::string state; value.GetAsString(&state); - DBusThreadManager::Get() - ->GetShillManagerClient() - ->GetTestInterface() - ->ServiceStateChanged(service_path, state); + ShillManagerClient::Get()->GetTestInterface()->ServiceStateChanged( + service_path, state); } // If the State or Visibility changes, the sort order of service lists may @@ -496,11 +478,7 @@ } void FakeShillServiceClient::ClearServices() { - DBusThreadManager::Get() - ->GetShillManagerClient() - ->GetTestInterface() - ->ClearManagerServices(); - + ShillManagerClient::Get()->GetTestInterface()->ClearManagerServices(); stub_services_.Clear(); connect_behavior_.clear(); }
diff --git a/chromeos/dbus/shill/fake_shill_service_client.h b/chromeos/dbus/shill/fake_shill_service_client.h index 5688a51f..084d487 100644 --- a/chromeos/dbus/shill/fake_shill_service_client.h +++ b/chromeos/dbus/shill/fake_shill_service_client.h
@@ -28,7 +28,6 @@ ~FakeShillServiceClient() override; // ShillServiceClient overrides - void Init(dbus::Bus* bus) override; void AddPropertyChangedObserver( const dbus::ObjectPath& service_path, ShillPropertyChangedObserver* observer) override;
diff --git a/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.cc b/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.cc index 13aca81..944d5be 100644 --- a/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.cc +++ b/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.cc
@@ -21,8 +21,6 @@ FakeShillThirdPartyVpnDriverClient::~FakeShillThirdPartyVpnDriverClient() = default; -void FakeShillThirdPartyVpnDriverClient::Init(dbus::Bus* bus) {} - void FakeShillThirdPartyVpnDriverClient::AddShillThirdPartyVpnObserver( const std::string& object_path_value, ShillThirdPartyVpnObserver* observer) {
diff --git a/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h b/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h index a7290c8..a70730f 100644 --- a/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h +++ b/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h
@@ -29,7 +29,6 @@ ~FakeShillThirdPartyVpnDriverClient() override; // ShillThirdPartyVpnDriverClient overrides - void Init(dbus::Bus* bus) override; void AddShillThirdPartyVpnObserver( const std::string& object_path_value, ShillThirdPartyVpnObserver* observer) override;
diff --git a/chromeos/dbus/shill/fake_sms_client.cc b/chromeos/dbus/shill/fake_sms_client.cc index e132965..3575f84 100644 --- a/chromeos/dbus/shill/fake_sms_client.cc +++ b/chromeos/dbus/shill/fake_sms_client.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chromeos/dbus/shill/fake_sms_client.h" + #include <string> #include "base/bind.h" @@ -13,7 +15,6 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "chromeos/dbus/constants/dbus_switches.h" -#include "chromeos/dbus/shill/fake_sms_client.h" #include "dbus/object_path.h" namespace chromeos { @@ -22,8 +23,6 @@ FakeSMSClient::~FakeSMSClient() = default; -void FakeSMSClient::Init(dbus::Bus* bus) {} - void FakeSMSClient::GetAll(const std::string& service_name, const dbus::ObjectPath& object_path, GetAllCallback callback) {
diff --git a/chromeos/dbus/shill/fake_sms_client.h b/chromeos/dbus/shill/fake_sms_client.h index 748dfd7..54a32b2b 100644 --- a/chromeos/dbus/shill/fake_sms_client.h +++ b/chromeos/dbus/shill/fake_sms_client.h
@@ -18,7 +18,6 @@ ~FakeSMSClient() override; // SMSClient overrides. - void Init(dbus::Bus* bus) override; void GetAll(const std::string& service_name, const dbus::ObjectPath& object_path, GetAllCallback callback) override;
diff --git a/chromeos/dbus/shill/gsm_sms_client.cc b/chromeos/dbus/shill/gsm_sms_client.cc index f4bc4c8..8d49a31 100644 --- a/chromeos/dbus/shill/gsm_sms_client.cc +++ b/chromeos/dbus/shill/gsm_sms_client.cc
@@ -1,10 +1,10 @@ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + #include "chromeos/dbus/shill/gsm_sms_client.h" #include <stdint.h> - #include <map> #include <memory> #include <utility> @@ -15,6 +15,8 @@ #include "base/memory/weak_ptr.h" #include "base/strings/stringprintf.h" #include "base/values.h" +#include "chromeos/dbus/shill/fake_gsm_sms_client.h" +#include "chromeos/dbus/shill/fake_sms_client.h" #include "dbus/bus.h" #include "dbus/message.h" #include "dbus/object_proxy.h" @@ -25,6 +27,8 @@ namespace { +GsmSMSClient* g_instance = nullptr; + // A class actually making method calls for SMS services, used by // GsmSMSClientImpl. class SMSProxy { @@ -161,7 +165,8 @@ // The GsmSMSClient implementation. class GsmSMSClientImpl : public GsmSMSClient { public: - GsmSMSClientImpl() : bus_(NULL) {} + explicit GsmSMSClientImpl(dbus::Bus* bus) : bus_(bus) {} + ~GsmSMSClientImpl() override = default; // GsmSMSClient override. void SetSmsReceivedHandler(const std::string& service_name, @@ -203,9 +208,6 @@ void RequestUpdate(const std::string& service_name, const dbus::ObjectPath& object_path) override {} - protected: - void Init(dbus::Bus* bus) override { bus_ = bus; } - private: using ProxyMap = std::map<std::pair<std::string, std::string>, std::unique_ptr<SMSProxy>>; @@ -237,13 +239,36 @@ //////////////////////////////////////////////////////////////////////////////// // GsmSMSClient -GsmSMSClient::GsmSMSClient() = default; +GsmSMSClient::GsmSMSClient() { + DCHECK(!g_instance); + g_instance = this; +} -GsmSMSClient::~GsmSMSClient() = default; +GsmSMSClient::~GsmSMSClient() { + DCHECK_EQ(this, g_instance); + g_instance = nullptr; +} // static -GsmSMSClient* GsmSMSClient::Create() { - return new GsmSMSClientImpl(); +void GsmSMSClient::Initialize(dbus::Bus* bus) { + DCHECK(bus); + new GsmSMSClientImpl(bus); +} + +// static +void GsmSMSClient::InitializeFake() { + new FakeGsmSMSClient; +} + +// static +void GsmSMSClient::Shutdown() { + DCHECK(g_instance); + delete g_instance; +} + +// static +GsmSMSClient* GsmSMSClient::Get() { + return g_instance; } } // namespace chromeos
diff --git a/chromeos/dbus/shill/gsm_sms_client.h b/chromeos/dbus/shill/gsm_sms_client.h index a4a95f3..05aee39 100644 --- a/chromeos/dbus/shill/gsm_sms_client.h +++ b/chromeos/dbus/shill/gsm_sms_client.h
@@ -12,7 +12,6 @@ #include "base/callback.h" #include "base/component_export.h" #include "base/macros.h" -#include "chromeos/dbus/dbus_client.h" #include "chromeos/dbus/dbus_method_call_status.h" namespace base { @@ -21,8 +20,9 @@ } // namespace base namespace dbus { +class Bus; class ObjectPath; -} +} // namespace dbus namespace chromeos { @@ -30,16 +30,22 @@ // org.freedesktop.ModemManager.Modem.Gsm.SMS service. // All methods should be called from the origin thread (UI thread) which // initializes the DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) GsmSMSClient : public DBusClient { +class COMPONENT_EXPORT(CHROMEOS_DBUS) GsmSMSClient { public: typedef base::Callback<void(uint32_t index, bool complete)> SmsReceivedHandler; - ~GsmSMSClient() override; + // Creates and initializes the global instance. |bus| must not be null. + static void Initialize(dbus::Bus* bus); - // Factory function, creates a new instance and returns ownership. - // For normal usage, access the singleton via DBusThreadManager::Get(). - static GsmSMSClient* Create(); + // Creates the global instance with a fake implementation. + static void InitializeFake(); + + // Destroys the global instance which must have been initialized. + static void Shutdown(); + + // Returns the global instance if initialized. May return null. + static GsmSMSClient* Get(); // Sets SmsReceived signal handler. virtual void SetSmsReceivedHandler(const std::string& service_name, @@ -75,8 +81,9 @@ protected: friend class GsmSMSClientTest; - // Create() should be used instead. + // Initialize/Shutdown should be used instead. GsmSMSClient(); + virtual ~GsmSMSClient(); private: DISALLOW_COPY_AND_ASSIGN(GsmSMSClient);
diff --git a/chromeos/dbus/shill/gsm_sms_client_unittest.cc b/chromeos/dbus/shill/gsm_sms_client_unittest.cc index b8adc98..70b707f9 100644 --- a/chromeos/dbus/shill/gsm_sms_client_unittest.cc +++ b/chromeos/dbus/shill/gsm_sms_client_unittest.cc
@@ -78,11 +78,14 @@ EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return()); // Create a client with the mock bus. - client_.reset(GsmSMSClient::Create()); - client_->Init(mock_bus_.get()); + GsmSMSClient::Initialize(mock_bus_.get()); + client_ = GsmSMSClient::Get(); } - void TearDown() override { mock_bus_->ShutdownAndBlock(); } + void TearDown() override { + mock_bus_->ShutdownAndBlock(); + GsmSMSClient::Shutdown(); + } // Handles Delete method call. void OnDelete(dbus::MethodCall* method_call, @@ -133,8 +136,7 @@ } protected: - // The client to be tested. - std::unique_ptr<GsmSMSClient> client_; + GsmSMSClient* client_ = nullptr; // Unowned convenience pointer. // A message loop to emulate asynchronous behavior. base::MessageLoop message_loop_; // The mock bus.
diff --git a/chromeos/dbus/shill/modem_messaging_client.cc b/chromeos/dbus/shill/modem_messaging_client.cc index 61ef07e..3379155 100644 --- a/chromeos/dbus/shill/modem_messaging_client.cc +++ b/chromeos/dbus/shill/modem_messaging_client.cc
@@ -1,6 +1,7 @@ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + #include "chromeos/dbus/shill/modem_messaging_client.h" #include <map> @@ -11,6 +12,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/values.h" +#include "chromeos/dbus/shill/fake_modem_messaging_client.h" #include "dbus/bus.h" #include "dbus/message.h" #include "dbus/object_proxy.h" @@ -20,6 +22,8 @@ namespace { +ModemMessagingClient* g_instance = nullptr; + // A class which makes method calls for SMS services via the // org.freedesktop.ModemManager1.Messaging object. class ModemMessagingProxy { @@ -133,7 +137,8 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS) ModemMessagingClientImpl : public ModemMessagingClient { public: - ModemMessagingClientImpl() : bus_(NULL) {} + explicit ModemMessagingClientImpl(dbus::Bus* bus) : bus_(bus) {} + ~ModemMessagingClientImpl() override = default; void SetSmsReceivedHandler(const std::string& service_name, const dbus::ObjectPath& object_path, @@ -159,9 +164,6 @@ GetProxy(service_name, object_path)->List(std::move(callback)); } - protected: - void Init(dbus::Bus* bus) override { bus_ = bus; } - private: using ProxyMap = std::map<std::pair<std::string, std::string>, std::unique_ptr<ModemMessagingProxy>>; @@ -193,13 +195,36 @@ //////////////////////////////////////////////////////////////////////////////// // ModemMessagingClient -ModemMessagingClient::ModemMessagingClient() = default; +ModemMessagingClient::ModemMessagingClient() { + DCHECK(!g_instance); + g_instance = this; +} -ModemMessagingClient::~ModemMessagingClient() = default; +ModemMessagingClient::~ModemMessagingClient() { + DCHECK_EQ(this, g_instance); + g_instance = nullptr; +} // static -ModemMessagingClient* ModemMessagingClient::Create() { - return new ModemMessagingClientImpl(); +void ModemMessagingClient::Initialize(dbus::Bus* bus) { + DCHECK(bus); + new ModemMessagingClientImpl(bus); +} + +// static +void ModemMessagingClient::InitializeFake() { + new FakeModemMessagingClient(); +} + +// static +void ModemMessagingClient::Shutdown() { + DCHECK(g_instance); + delete g_instance; +} + +// static +ModemMessagingClient* ModemMessagingClient::Get() { + return g_instance; } } // namespace chromeos
diff --git a/chromeos/dbus/shill/modem_messaging_client.h b/chromeos/dbus/shill/modem_messaging_client.h index 264f81ad..b089be41 100644 --- a/chromeos/dbus/shill/modem_messaging_client.h +++ b/chromeos/dbus/shill/modem_messaging_client.h
@@ -15,8 +15,9 @@ #include "chromeos/dbus/dbus_method_call_status.h" namespace dbus { +class Bus; class ObjectPath; -} +} // namespace dbus namespace chromeos { @@ -24,17 +25,23 @@ // org.freedesktop.ModemManager1.Modem.Messaging service. All methods // should be called from the origin thread (UI thread) which // initializes the DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ModemMessagingClient : public DBusClient { +class COMPONENT_EXPORT(CHROMEOS_DBUS) ModemMessagingClient { public: typedef base::Callback<void(const dbus::ObjectPath& message_path, bool complete)> SmsReceivedHandler; - ~ModemMessagingClient() override; + // Creates and initializes the global instance. |bus| must not be null. + static void Initialize(dbus::Bus* bus); - // Factory function, creates a new instance and returns ownership. - // For normal usage, access the singleton via DBusThreadManager::Get(). - static ModemMessagingClient* Create(); + // Creates the global instance with a fake implementation. + static void InitializeFake(); + + // Destroys the global instance which must have been initialized. + static void Shutdown(); + + // Returns the global instance if initialized. May return null. + static ModemMessagingClient* Get(); // Sets SmsReceived signal handler. virtual void SetSmsReceivedHandler(const std::string& service_name, @@ -60,8 +67,9 @@ protected: friend class ModemMessagingClientTest; - // Create() should be used instead. + // Initialize/Shutdown should be used instead. ModemMessagingClient(); + virtual ~ModemMessagingClient(); private: DISALLOW_COPY_AND_ASSIGN(ModemMessagingClient);
diff --git a/chromeos/dbus/shill/modem_messaging_client_unittest.cc b/chromeos/dbus/shill/modem_messaging_client_unittest.cc index 9c0dace..0444546 100644 --- a/chromeos/dbus/shill/modem_messaging_client_unittest.cc +++ b/chromeos/dbus/shill/modem_messaging_client_unittest.cc
@@ -77,11 +77,14 @@ EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return()); // Create a client with the mock bus. - client_.reset(ModemMessagingClient::Create()); - client_->Init(mock_bus_.get()); + ModemMessagingClient::Initialize(mock_bus_.get()); + client_ = ModemMessagingClient::Get(); } - void TearDown() override { mock_bus_->ShutdownAndBlock(); } + void TearDown() override { + mock_bus_->ShutdownAndBlock(); + ModemMessagingClient::Shutdown(); + } // Handles Delete method call. void OnDelete(dbus::MethodCall* method_call, @@ -115,8 +118,7 @@ } protected: - // The client to be tested. - std::unique_ptr<ModemMessagingClient> client_; + ModemMessagingClient* client_ = nullptr; // Unowned convenience pointer. // A message loop to emulate asynchronous behavior. base::MessageLoop message_loop_; // The mock bus.
diff --git a/chromeos/dbus/shill/shill_clients.cc b/chromeos/dbus/shill/shill_clients.cc new file mode 100644 index 0000000..d17dc38 --- /dev/null +++ b/chromeos/dbus/shill/shill_clients.cc
@@ -0,0 +1,60 @@ +// 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/dbus/shill/shill_clients.h" + +#include "chromeos/dbus/shill/gsm_sms_client.h" +#include "chromeos/dbus/shill/modem_messaging_client.h" +#include "chromeos/dbus/shill/shill_device_client.h" +#include "chromeos/dbus/shill/shill_ipconfig_client.h" +#include "chromeos/dbus/shill/shill_manager_client.h" +#include "chromeos/dbus/shill/shill_profile_client.h" +#include "chromeos/dbus/shill/shill_service_client.h" +#include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h" +#include "chromeos/dbus/shill/sms_client.h" + +namespace chromeos { +namespace shill_clients { + +void Initialize(dbus::Bus* system_bus) { + DCHECK(system_bus); + GsmSMSClient::Initialize(system_bus); + ModemMessagingClient::Initialize(system_bus); + SMSClient::Initialize(system_bus); + ShillDeviceClient::Initialize(system_bus); + ShillIPConfigClient::Initialize(system_bus); + ShillManagerClient::Initialize(system_bus); + ShillProfileClient::Initialize(system_bus); + ShillServiceClient::Initialize(system_bus); + ShillThirdPartyVpnDriverClient::Initialize(system_bus); +} + +void InitializeFakes() { + GsmSMSClient::InitializeFake(); + ModemMessagingClient::InitializeFake(); + SMSClient::InitializeFake(); + ShillDeviceClient::InitializeFake(); + ShillIPConfigClient::InitializeFake(); + ShillManagerClient::InitializeFake(); + ShillProfileClient::InitializeFake(); + ShillServiceClient::InitializeFake(); + ShillThirdPartyVpnDriverClient::InitializeFake(); + + ShillManagerClient::Get()->GetTestInterface()->SetupDefaultEnvironment(); +} + +void Shutdown() { + ShillThirdPartyVpnDriverClient::Shutdown(); + ShillServiceClient::Shutdown(); + ShillProfileClient::Shutdown(); + ShillManagerClient::Shutdown(); + ShillIPConfigClient::Shutdown(); + ShillDeviceClient::Shutdown(); + SMSClient::Shutdown(); + ModemMessagingClient::Shutdown(); + GsmSMSClient::Shutdown(); +} + +} // namespace shill_clients +} // namespace chromeos
diff --git a/chromeos/dbus/shill/shill_clients.h b/chromeos/dbus/shill/shill_clients.h new file mode 100644 index 0000000..aca7564 --- /dev/null +++ b/chromeos/dbus/shill/shill_clients.h
@@ -0,0 +1,29 @@ +// 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_DBUS_SHILL_SHILL_CLIENTS_H_ +#define CHROMEOS_DBUS_SHILL_SHILL_CLIENTS_H_ + +#include "base/component_export.h" + +namespace dbus { +class Bus; +} + +namespace chromeos { +namespace shill_clients { + +// Initialize Shill and modemmanager related dbus clients. +COMPONENT_EXPORT(CHROMEOS_DBUS) void Initialize(dbus::Bus* system_bus); + +// Initialize fake Shill and modemmanager related dbus clients. +COMPONENT_EXPORT(CHROMEOS_DBUS) void InitializeFakes(); + +// Shut down Shill and modemmanager related dbus clients. +COMPONENT_EXPORT(CHROMEOS_DBUS) void Shutdown(); + +} // namespace shill_clients +} // namespace chromeos + +#endif // CHROMEOS_DBUS_SHILL_SHILL_CLIENTS_H_
diff --git a/chromeos/dbus/shill/shill_device_client.cc b/chromeos/dbus/shill/shill_device_client.cc index 9688128..b1acca8f 100644 --- a/chromeos/dbus/shill/shill_device_client.cc +++ b/chromeos/dbus/shill/shill_device_client.cc
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/stl_util.h" #include "base/values.h" +#include "chromeos/dbus/shill/fake_shill_device_client.h" #include "chromeos/dbus/shill/shill_property_changed_observer.h" #include "dbus/bus.h" #include "dbus/message.h" @@ -24,10 +25,12 @@ namespace { +ShillDeviceClient* g_instance = nullptr; + // The ShillDeviceClient implementation. class ShillDeviceClientImpl : public ShillDeviceClient { public: - ShillDeviceClientImpl() : bus_(NULL) {} + explicit ShillDeviceClientImpl(dbus::Bus* bus) : bus_(bus) {} ~ShillDeviceClientImpl() override { for (HelperMap::iterator iter = helpers_.begin(); iter != helpers_.end(); @@ -36,7 +39,7 @@ // seem to imply that it does happen sometimes. Adding CHECKs here // so we can determine more accurately where the problem lies. // See: http://crbug.com/170541 - CHECK(iter->second) << "NULL Helper found in helper list."; + CHECK(iter->second) << "null Helper found in helper list."; delete iter->second; } helpers_.clear(); @@ -270,10 +273,7 @@ error_callback); } - TestInterface* GetTestInterface() override { return NULL; } - - protected: - void Init(dbus::Bus* bus) override { bus_ = bus; } + TestInterface* GetTestInterface() override { return nullptr; } private: typedef std::map<std::string, ShillClientHelper*> HelperMap; @@ -282,7 +282,7 @@ ShillClientHelper* GetHelper(const dbus::ObjectPath& device_path) { HelperMap::iterator it = helpers_.find(device_path.value()); if (it != helpers_.end()) { - CHECK(it->second) << "Found a NULL helper in the list."; + CHECK(it->second) << "Found a null helper in the list."; return it->second; } @@ -304,13 +304,36 @@ } // namespace -ShillDeviceClient::ShillDeviceClient() = default; +ShillDeviceClient::ShillDeviceClient() { + DCHECK(!g_instance); + g_instance = this; +} -ShillDeviceClient::~ShillDeviceClient() = default; +ShillDeviceClient::~ShillDeviceClient() { + DCHECK_EQ(this, g_instance); + g_instance = nullptr; +} // static -ShillDeviceClient* ShillDeviceClient::Create() { - return new ShillDeviceClientImpl(); +void ShillDeviceClient::Initialize(dbus::Bus* bus) { + DCHECK(bus); + new ShillDeviceClientImpl(bus); +} + +// static +void ShillDeviceClient::InitializeFake() { + new FakeShillDeviceClient(); +} + +// static +void ShillDeviceClient::Shutdown() { + DCHECK(g_instance); + delete g_instance; +} + +// static +ShillDeviceClient* ShillDeviceClient::Get() { + return g_instance; } } // namespace chromeos
diff --git a/chromeos/dbus/shill/shill_device_client.h b/chromeos/dbus/shill/shill_device_client.h index cd22975a..c4f1b03d 100644 --- a/chromeos/dbus/shill/shill_device_client.h +++ b/chromeos/dbus/shill/shill_device_client.h
@@ -11,25 +11,19 @@ #include "base/callback.h" #include "base/component_export.h" #include "base/macros.h" -#include "chromeos/dbus/dbus_client.h" #include "chromeos/dbus/shill/shill_client_helper.h" namespace base { - class Value; - } // namespace base namespace dbus { - +class Bus; class ObjectPath; - } // namespace dbus namespace net { - class IPEndPoint; - } // namespace net namespace chromeos { @@ -39,7 +33,7 @@ // ShillDeviceClient is used to communicate with the Shill Device service. // All methods should be called from the origin thread which initializes the // DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillDeviceClient : public DBusClient { +class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillDeviceClient { public: typedef ShillClientHelper::PropertyChangedHandler PropertyChangedHandler; typedef ShillClientHelper::DictionaryValueCallback DictionaryValueCallback; @@ -73,11 +67,17 @@ virtual ~TestInterface() {} }; - ~ShillDeviceClient() override; + // Creates and initializes the global instance. |bus| must not be null. + static void Initialize(dbus::Bus* bus); - // Factory function, creates a new instance which is owned by the caller. - // For normal usage, access the singleton via DBusThreadManager::Get(). - static ShillDeviceClient* Create(); + // Creates the global instance with a fake implementation. + static void InitializeFake(); + + // Destroys the global instance which must have been initialized. + static void Shutdown(); + + // Returns the global instance if initialized. May return null. + static ShillDeviceClient* Get(); // Adds a property changed |observer| for the device at |device_path|. virtual void AddPropertyChangedObserver( @@ -209,14 +209,15 @@ const base::Closure& callback, const ErrorCallback& error_callback) = 0; - // Returns an interface for testing (stub only), or returns NULL. + // Returns an interface for testing (stub only), or returns null. virtual TestInterface* GetTestInterface() = 0; protected: friend class ShillDeviceClientTest; - // Create() should be used instead. + // Initialize/Shutdown should be used instead. ShillDeviceClient(); + virtual ~ShillDeviceClient(); private: DISALLOW_COPY_AND_ASSIGN(ShillDeviceClient);
diff --git a/chromeos/dbus/shill/shill_device_client_unittest.cc b/chromeos/dbus/shill/shill_device_client_unittest.cc index 58fd0e1..1e192292 100644 --- a/chromeos/dbus/shill/shill_device_client_unittest.cc +++ b/chromeos/dbus/shill/shill_device_client_unittest.cc
@@ -62,14 +62,19 @@ void SetUp() override { ShillClientUnittestBase::SetUp(); // Create a client with the mock bus. - client_.reset(ShillDeviceClient::Create()); - client_->Init(mock_bus_.get()); + ShillDeviceClient::Initialize(mock_bus_.get()); + client_ = ShillDeviceClient::Get(); // Run the message loop to run the signal connection result callback. base::RunLoop().RunUntilIdle(); } + void TearDown() override { + ShillDeviceClient::Shutdown(); + ShillClientUnittestBase::TearDown(); + } + protected: - std::unique_ptr<ShillDeviceClient> client_; + ShillDeviceClient* client_ = nullptr; // Unowned convenience pointer. }; TEST_F(ShillDeviceClientTest, PropertyChanged) {
diff --git a/chromeos/dbus/shill/shill_ipconfig_client.cc b/chromeos/dbus/shill/shill_ipconfig_client.cc index a540a27..0070297 100644 --- a/chromeos/dbus/shill/shill_ipconfig_client.cc +++ b/chromeos/dbus/shill/shill_ipconfig_client.cc
@@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/macros.h" #include "base/values.h" +#include "chromeos/dbus/shill/fake_shill_ipconfig_client.h" #include "chromeos/dbus/shill/shill_property_changed_observer.h" #include "dbus/bus.h" #include "dbus/message.h" @@ -23,10 +24,13 @@ namespace { +ShillIPConfigClient* g_instance = nullptr; + // The ShillIPConfigClient implementation. class ShillIPConfigClientImpl : public ShillIPConfigClient { public: - ShillIPConfigClientImpl(); + explicit ShillIPConfigClientImpl(dbus::Bus* bus) : bus_(bus) {} + ~ShillIPConfigClientImpl() override = default; //////////////////////////////////// // ShillIPConfigClient overrides. @@ -56,9 +60,6 @@ VoidDBusMethodCallback callback) override; ShillIPConfigClient::TestInterface* GetTestInterface() override; - protected: - void Init(dbus::Bus* bus) override { bus_ = bus; } - private: using HelperMap = std::map<std::string, std::unique_ptr<ShillClientHelper>>; @@ -85,8 +86,6 @@ DISALLOW_COPY_AND_ASSIGN(ShillIPConfigClientImpl); }; -ShillIPConfigClientImpl::ShillIPConfigClientImpl() : bus_(NULL) {} - void ShillIPConfigClientImpl::GetProperties( const dbus::ObjectPath& ipconfig_path, const DictionaryValueCallback& callback) { @@ -113,11 +112,11 @@ // IPConfig supports writing basic type and string array properties. switch (value.type()) { case base::Value::Type::LIST: { - const base::ListValue* list_value = NULL; + const base::ListValue* list_value = nullptr; value.GetAsList(&list_value); - dbus::MessageWriter variant_writer(NULL); + dbus::MessageWriter variant_writer(nullptr); writer.OpenVariant("as", &variant_writer); - dbus::MessageWriter array_writer(NULL); + dbus::MessageWriter array_writer(nullptr); variant_writer.OpenArray("s", &array_writer); for (base::ListValue::const_iterator it = list_value->begin(); it != list_value->end(); ++it) { @@ -162,18 +161,41 @@ ShillIPConfigClient::TestInterface* ShillIPConfigClientImpl::GetTestInterface() { - return NULL; + return nullptr; } } // namespace -ShillIPConfigClient::ShillIPConfigClient() = default; +ShillIPConfigClient::ShillIPConfigClient() { + DCHECK(!g_instance); + g_instance = this; +} -ShillIPConfigClient::~ShillIPConfigClient() = default; +ShillIPConfigClient::~ShillIPConfigClient() { + DCHECK_EQ(this, g_instance); + g_instance = nullptr; +} // static -ShillIPConfigClient* ShillIPConfigClient::Create() { - return new ShillIPConfigClientImpl(); +void ShillIPConfigClient::Initialize(dbus::Bus* bus) { + DCHECK(bus); + new ShillIPConfigClientImpl(bus); +} + +// static +void ShillIPConfigClient::InitializeFake() { + new FakeShillIPConfigClient(); +} + +// static +void ShillIPConfigClient::Shutdown() { + DCHECK(g_instance); + delete g_instance; +} + +// static +ShillIPConfigClient* ShillIPConfigClient::Get() { + return g_instance; } } // namespace chromeos
diff --git a/chromeos/dbus/shill/shill_ipconfig_client.h b/chromeos/dbus/shill/shill_ipconfig_client.h index 9d01d8f..272545d 100644 --- a/chromeos/dbus/shill/shill_ipconfig_client.h +++ b/chromeos/dbus/shill/shill_ipconfig_client.h
@@ -10,20 +10,16 @@ #include "base/callback.h" #include "base/component_export.h" #include "base/macros.h" -#include "chromeos/dbus/dbus_client.h" #include "chromeos/dbus/shill/shill_client_helper.h" namespace base { - class Value; class DictionaryValue; - } // namespace base namespace dbus { - +class Bus; class ObjectPath; - } // namespace dbus namespace chromeos { @@ -33,7 +29,7 @@ // ShillIPConfigClient is used to communicate with the Shill IPConfig // service. All methods should be called from the origin thread which // initializes the DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillIPConfigClient : public DBusClient { +class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillIPConfigClient { public: typedef ShillClientHelper::PropertyChangedHandler PropertyChangedHandler; typedef ShillClientHelper::DictionaryValueCallback DictionaryValueCallback; @@ -48,7 +44,17 @@ virtual ~TestInterface() {} }; - ~ShillIPConfigClient() override; + // Creates and initializes the global instance. |bus| must not be null. + static void Initialize(dbus::Bus* bus); + + // Creates the global instance with a fake implementation. + static void InitializeFake(); + + // Destroys the global instance which must have been initialized. + static void Shutdown(); + + // Returns the global instance if initialized. May return null. + static ShillIPConfigClient* Get(); // Factory function, creates a new instance which is owned by the caller. // For normal usage, access the singleton via DBusThreadManager::Get(). @@ -92,14 +98,15 @@ virtual void Remove(const dbus::ObjectPath& ipconfig_path, VoidDBusMethodCallback callback) = 0; - // Returns an interface for testing (stub only), or returns NULL. + // Returns an interface for testing (stub only), or returns null. virtual ShillIPConfigClient::TestInterface* GetTestInterface() = 0; protected: friend class ShillIPConfigClientTest; - // Create() should be used instead. + // Initialize/Shutdown should be used instead. ShillIPConfigClient(); + virtual ~ShillIPConfigClient(); private: DISALLOW_COPY_AND_ASSIGN(ShillIPConfigClient);
diff --git a/chromeos/dbus/shill/shill_ipconfig_client_unittest.cc b/chromeos/dbus/shill/shill_ipconfig_client_unittest.cc index 05f1c37..274c4d0 100644 --- a/chromeos/dbus/shill/shill_ipconfig_client_unittest.cc +++ b/chromeos/dbus/shill/shill_ipconfig_client_unittest.cc
@@ -36,14 +36,19 @@ void SetUp() override { ShillClientUnittestBase::SetUp(); // Create a client with the mock bus. - client_.reset(ShillIPConfigClient::Create()); - client_->Init(mock_bus_.get()); + ShillIPConfigClient::Initialize(mock_bus_.get()); + client_ = ShillIPConfigClient::Get(); // Run the message loop to run the signal connection result callback. base::RunLoop().RunUntilIdle(); } + void TearDown() override { + ShillIPConfigClient::Shutdown(); + ShillClientUnittestBase::TearDown(); + } + protected: - std::unique_ptr<ShillIPConfigClient> client_; + ShillIPConfigClient* client_ = nullptr; // Unowned convenience pointer. }; TEST_F(ShillIPConfigClientTest, PropertyChanged) {
diff --git a/chromeos/dbus/shill/shill_manager_client.cc b/chromeos/dbus/shill/shill_manager_client.cc index e2c8f14..bb05c859 100644 --- a/chromeos/dbus/shill/shill_manager_client.cc +++ b/chromeos/dbus/shill/shill_manager_client.cc
@@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/values.h" +#include "chromeos/dbus/shill/fake_shill_manager_client.h" #include "chromeos/dbus/shill/shill_property_changed_observer.h" #include "dbus/bus.h" #include "dbus/message.h" @@ -23,10 +24,13 @@ namespace { +ShillManagerClient* g_instance = nullptr; + // The ShillManagerClient implementation. class ShillManagerClientImpl : public ShillManagerClient { public: - ShillManagerClientImpl() : proxy_(NULL) {} + ShillManagerClientImpl() = default; + ~ShillManagerClientImpl() override = default; //////////////////////////////////// // ShillManagerClient overrides. @@ -157,10 +161,9 @@ error_callback); } - TestInterface* GetTestInterface() override { return NULL; } + TestInterface* GetTestInterface() override { return nullptr; } - protected: - void Init(dbus::Bus* bus) override { + void Init(dbus::Bus* bus) { proxy_ = bus->GetObjectProxy(shill::kFlimflamServiceName, dbus::ObjectPath(shill::kFlimflamServicePath)); helper_.reset(new ShillClientHelper(proxy_)); @@ -168,7 +171,7 @@ } private: - dbus::ObjectProxy* proxy_; + dbus::ObjectProxy* proxy_ = nullptr; std::unique_ptr<ShillClientHelper> helper_; DISALLOW_COPY_AND_ASSIGN(ShillManagerClientImpl); @@ -176,13 +179,36 @@ } // namespace -ShillManagerClient::ShillManagerClient() = default; +ShillManagerClient::ShillManagerClient() { + DCHECK(!g_instance); + g_instance = this; +} -ShillManagerClient::~ShillManagerClient() = default; +ShillManagerClient::~ShillManagerClient() { + DCHECK_EQ(this, g_instance); + g_instance = nullptr; +} // static -ShillManagerClient* ShillManagerClient::Create() { - return new ShillManagerClientImpl(); +void ShillManagerClient::Initialize(dbus::Bus* bus) { + DCHECK(bus); + (new ShillManagerClientImpl)->Init(bus); +} + +// static +void ShillManagerClient::InitializeFake() { + new FakeShillManagerClient(); +} + +// static +void ShillManagerClient::Shutdown() { + DCHECK(g_instance); + delete g_instance; +} + +// static +ShillManagerClient* ShillManagerClient::Get() { + return g_instance; } } // namespace chromeos
diff --git a/chromeos/dbus/shill/shill_manager_client.h b/chromeos/dbus/shill/shill_manager_client.h index 2839ecf..02900c0 100644 --- a/chromeos/dbus/shill/shill_manager_client.h +++ b/chromeos/dbus/shill/shill_manager_client.h
@@ -9,13 +9,13 @@ #include "base/component_export.h" #include "base/macros.h" -#include "chromeos/dbus/dbus_client.h" #include "chromeos/dbus/dbus_method_call_status.h" #include "chromeos/dbus/shill/shill_client_helper.h" namespace dbus { +class Bus; class ObjectPath; -} +} // namespace dbus namespace chromeos { @@ -24,7 +24,7 @@ // ShillManagerClient is used to communicate with the Shill Manager // service. All methods should be called from the origin thread which // initializes the DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillManagerClient : public DBusClient { +class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillManagerClient { public: typedef ShillClientHelper::PropertyChangedHandler PropertyChangedHandler; typedef ShillClientHelper::DictionaryValueCallback DictionaryValueCallback; @@ -107,11 +107,17 @@ virtual ~TestInterface() {} }; - ~ShillManagerClient() override; + // Creates and initializes the global instance. |bus| must not be null. + static void Initialize(dbus::Bus* bus); - // Factory function, creates a new instance which is owned by the caller. - // For normal usage, access the singleton via DBusThreadManager::Get(). - static ShillManagerClient* Create(); + // Creates the global instance with a fake implementation. + static void InitializeFake(); + + // Destroys the global instance which must have been initialized. + static void Shutdown(); + + // Returns the global instance if initialized. May return null. + static ShillManagerClient* Get(); // Adds a property changed |observer|. virtual void AddPropertyChangedObserver( @@ -187,14 +193,15 @@ const base::Closure& callback, const ErrorCallback& error_callback) = 0; - // Returns an interface for testing (stub only), or returns NULL. + // Returns an interface for testing (stub only), or returns null. virtual TestInterface* GetTestInterface() = 0; protected: friend class ShillManagerClientTest; - // Create() should be used instead. + // Initialize/Shutdown should be used instead. ShillManagerClient(); + virtual ~ShillManagerClient(); private: DISALLOW_COPY_AND_ASSIGN(ShillManagerClient);
diff --git a/chromeos/dbus/shill/shill_manager_client_unittest.cc b/chromeos/dbus/shill/shill_manager_client_unittest.cc index ec0f8cb..eefd987 100644 --- a/chromeos/dbus/shill/shill_manager_client_unittest.cc +++ b/chromeos/dbus/shill/shill_manager_client_unittest.cc
@@ -54,14 +54,19 @@ void SetUp() override { ShillClientUnittestBase::SetUp(); // Create a client with the mock bus. - client_.reset(ShillManagerClient::Create()); - client_->Init(mock_bus_.get()); + ShillManagerClient::Initialize(mock_bus_.get()); + client_ = ShillManagerClient::Get(); // Run the message loop to run the signal connection result callback. base::RunLoop().RunUntilIdle(); } + void TearDown() override { + ShillManagerClient::Shutdown(); + ShillClientUnittestBase::TearDown(); + } + protected: - std::unique_ptr<ShillManagerClient> client_; + ShillManagerClient* client_ = nullptr; // Unowned convenience pointer. }; TEST_F(ShillManagerClientTest, PropertyChanged) {
diff --git a/chromeos/dbus/shill/shill_profile_client.cc b/chromeos/dbus/shill/shill_profile_client.cc index 759dcda7..170c422 100644 --- a/chromeos/dbus/shill/shill_profile_client.cc +++ b/chromeos/dbus/shill/shill_profile_client.cc
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/values.h" #include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/fake_shill_profile_client.h" #include "chromeos/dbus/shill/shill_property_changed_observer.h" #include "dbus/bus.h" #include "dbus/message.h" @@ -25,9 +26,12 @@ const char kSharedProfilePath[] = "/profile/default"; +ShillProfileClient* g_instance = nullptr; + class ShillProfileClientImpl : public ShillProfileClient { public: - ShillProfileClientImpl(); + explicit ShillProfileClientImpl(dbus::Bus* bus) : bus_(bus) {} + ~ShillProfileClientImpl() override = default; void AddPropertyChangedObserver( const dbus::ObjectPath& profile_path, @@ -53,10 +57,7 @@ const base::Closure& callback, const ErrorCallback& error_callback) override; - TestInterface* GetTestInterface() override { return NULL; } - - protected: - void Init(dbus::Bus* bus) override { bus_ = bus; } + TestInterface* GetTestInterface() override { return nullptr; } private: using HelperMap = std::map<std::string, std::unique_ptr<ShillClientHelper>>; @@ -70,8 +71,6 @@ DISALLOW_COPY_AND_ASSIGN(ShillProfileClientImpl); }; -ShillProfileClientImpl::ShillProfileClientImpl() : bus_(NULL) {} - ShillClientHelper* ShillProfileClientImpl::GetHelper( const dbus::ObjectPath& profile_path) { HelperMap::const_iterator it = helpers_.find(profile_path.value()); @@ -128,13 +127,36 @@ } // namespace -ShillProfileClient::ShillProfileClient() = default; +ShillProfileClient::ShillProfileClient() { + DCHECK(!g_instance); + g_instance = this; +} -ShillProfileClient::~ShillProfileClient() = default; +ShillProfileClient::~ShillProfileClient() { + DCHECK_EQ(this, g_instance); + g_instance = nullptr; +} // static -ShillProfileClient* ShillProfileClient::Create() { - return new ShillProfileClientImpl(); +void ShillProfileClient::Initialize(dbus::Bus* bus) { + DCHECK(bus); + new ShillProfileClientImpl(bus); +} + +// static +void ShillProfileClient::InitializeFake() { + new FakeShillProfileClient(); +} + +// static +void ShillProfileClient::Shutdown() { + DCHECK(g_instance); + delete g_instance; +} + +// static +ShillProfileClient* ShillProfileClient::Get() { + return g_instance; } // static
diff --git a/chromeos/dbus/shill/shill_profile_client.h b/chromeos/dbus/shill/shill_profile_client.h index d9a8a69..b75a452 100644 --- a/chromeos/dbus/shill/shill_profile_client.h +++ b/chromeos/dbus/shill/shill_profile_client.h
@@ -11,19 +11,15 @@ #include "base/callback.h" #include "base/component_export.h" #include "base/macros.h" -#include "chromeos/dbus/dbus_client.h" #include "chromeos/dbus/shill/shill_client_helper.h" namespace base { - class DictionaryValue; - } // namespace base namespace dbus { - +class Bus; class ObjectPath; - } // namespace dbus namespace chromeos { @@ -33,7 +29,7 @@ // ShillProfileClient is used to communicate with the Shill Profile // service. All methods should be called from the origin thread which // initializes the DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillProfileClient : public DBusClient { +class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillProfileClient { public: typedef ShillClientHelper::PropertyChangedHandler PropertyChangedHandler; typedef ShillClientHelper::DictionaryValueCallbackWithoutStatus @@ -97,11 +93,17 @@ virtual ~TestInterface() {} }; - ~ShillProfileClient() override; + // Creates and initializes the global instance. |bus| must not be null. + static void Initialize(dbus::Bus* bus); - // Factory function, creates a new instance which is owned by the caller. - // For normal usage, access the singleton via DBusThreadManager::Get(). - static ShillProfileClient* Create(); + // Creates the global instance with a fake implementation. + static void InitializeFake(); + + // Destroys the global instance which must have been initialized. + static void Shutdown(); + + // Returns the global instance if initialized. May return null. + static ShillProfileClient* Get(); // Returns the shared profile path. static std::string GetSharedProfilePath(); @@ -137,14 +139,15 @@ const base::Closure& callback, const ErrorCallback& error_callback) = 0; - // Returns an interface for testing (stub only), or returns NULL. + // Returns an interface for testing (stub only), or returns null. virtual TestInterface* GetTestInterface() = 0; protected: friend class ShillProfileClientTest; - // Create() should be used instead. + // Initialize/Shutdown should be used instead. ShillProfileClient(); + virtual ~ShillProfileClient(); private: DISALLOW_COPY_AND_ASSIGN(ShillProfileClient);
diff --git a/chromeos/dbus/shill/shill_profile_client_unittest.cc b/chromeos/dbus/shill/shill_profile_client_unittest.cc index 30384b8..8c71ca2 100644 --- a/chromeos/dbus/shill/shill_profile_client_unittest.cc +++ b/chromeos/dbus/shill/shill_profile_client_unittest.cc
@@ -45,14 +45,19 @@ void SetUp() override { ShillClientUnittestBase::SetUp(); // Create a client with the mock bus. - client_.reset(ShillProfileClient::Create()); - client_->Init(mock_bus_.get()); + ShillProfileClient::Initialize(mock_bus_.get()); + client_ = ShillProfileClient::Get(); // Run the message loop to run the signal connection result callback. base::RunLoop().RunUntilIdle(); } + void TearDown() override { + ShillProfileClient::Shutdown(); + ShillClientUnittestBase::TearDown(); + } + protected: - std::unique_ptr<ShillProfileClient> client_; + ShillProfileClient* client_ = nullptr; // Unowned convenience pointer. }; TEST_F(ShillProfileClientTest, PropertyChanged) {
diff --git a/chromeos/dbus/shill/shill_service_client.cc b/chromeos/dbus/shill/shill_service_client.cc index 1feb4f65..bb0833693 100644 --- a/chromeos/dbus/shill/shill_service_client.cc +++ b/chromeos/dbus/shill/shill_service_client.cc
@@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "base/stl_util.h" #include "base/values.h" +#include "chromeos/dbus/shill/fake_shill_service_client.h" #include "chromeos/dbus/shill/shill_property_changed_observer.h" #include "components/device_event_log/device_event_log.h" #include "dbus/bus.h" @@ -29,6 +30,8 @@ #define DBUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject" #endif +ShillServiceClient* g_instance = nullptr; + // Error callback for GetProperties. void OnGetDictionaryError( const std::string& method_name, @@ -55,7 +58,8 @@ // The ShillServiceClient implementation. class ShillServiceClientImpl : public ShillServiceClient { public: - ShillServiceClientImpl() : bus_(NULL), weak_ptr_factory_(this) {} + explicit ShillServiceClientImpl(dbus::Bus* bus) + : bus_(bus), weak_ptr_factory_(this) {} ~ShillServiceClientImpl() override { for (HelperMap::iterator iter = helpers_.begin(); iter != helpers_.end(); @@ -213,12 +217,9 @@ } ShillServiceClient::TestInterface* GetTestInterface() override { - return NULL; + return nullptr; } - protected: - void Init(dbus::Bus* bus) override { bus_ = bus; } - private: typedef std::map<std::string, ShillClientHelper*> HelperMap; @@ -270,13 +271,36 @@ } // namespace -ShillServiceClient::ShillServiceClient() = default; +ShillServiceClient::ShillServiceClient() { + DCHECK(!g_instance); + g_instance = this; +} -ShillServiceClient::~ShillServiceClient() = default; +ShillServiceClient::~ShillServiceClient() { + DCHECK_EQ(this, g_instance); + g_instance = nullptr; +} // static -ShillServiceClient* ShillServiceClient::Create() { - return new ShillServiceClientImpl(); +void ShillServiceClient::Initialize(dbus::Bus* bus) { + DCHECK(bus); + new ShillServiceClientImpl(bus); +} + +// static +void ShillServiceClient::InitializeFake() { + new FakeShillServiceClient(); +} + +// static +void ShillServiceClient::Shutdown() { + DCHECK(g_instance); + delete g_instance; +} + +// static +ShillServiceClient* ShillServiceClient::Get() { + return g_instance; } } // namespace chromeos
diff --git a/chromeos/dbus/shill/shill_service_client.h b/chromeos/dbus/shill/shill_service_client.h index c0d6ef7b..c3a4658 100644 --- a/chromeos/dbus/shill/shill_service_client.h +++ b/chromeos/dbus/shill/shill_service_client.h
@@ -11,20 +11,16 @@ #include "base/callback.h" #include "base/component_export.h" #include "base/macros.h" -#include "chromeos/dbus/dbus_client.h" #include "chromeos/dbus/shill/shill_client_helper.h" namespace base { - class Value; class DictionaryValue; - } // namespace base namespace dbus { - +class Bus; class ObjectPath; - } // namespace dbus namespace chromeos { @@ -33,7 +29,7 @@ // service. // All methods should be called from the origin thread which initializes the // DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillServiceClient : public DBusClient { +class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillServiceClient { public: typedef ShillClientHelper::PropertyChangedHandler PropertyChangedHandler; typedef ShillClientHelper::DictionaryValueCallback DictionaryValueCallback; @@ -76,7 +72,7 @@ const std::string& property, const base::Value& value) = 0; - // Returns properties for |service_path| or NULL if no Service matches. + // Returns properties for |service_path| or null if no Service matches. virtual const base::DictionaryValue* GetServiceProperties( const std::string& service_path) const = 0; @@ -89,11 +85,18 @@ protected: virtual ~TestInterface() {} }; - ~ShillServiceClient() override; - // Factory function, creates a new instance which is owned by the caller. - // For normal usage, access the singleton via DBusThreadManager::Get(). - static ShillServiceClient* Create(); + // Creates and initializes the global instance. |bus| must not be null. + static void Initialize(dbus::Bus* bus); + + // Creates the global instance with a fake implementation. + static void InitializeFake(); + + // Destroys the global instance which must have been initialized. + static void Shutdown(); + + // Returns the global instance if initialized. May return null. + static ShillServiceClient* Get(); // Adds a property changed |observer| to the service at |service_path|. virtual void AddPropertyChangedObserver( @@ -177,14 +180,15 @@ const dbus::ObjectPath& service_path, const DictionaryValueCallback& callback) = 0; - // Returns an interface for testing (stub only), or returns NULL. + // Returns an interface for testing (stub only), or returns null. virtual TestInterface* GetTestInterface() = 0; protected: friend class ShillServiceClientTest; - // Create() should be used instead. + // Initialize/Shutdown should be used instead. ShillServiceClient(); + virtual ~ShillServiceClient(); private: DISALLOW_COPY_AND_ASSIGN(ShillServiceClient);
diff --git a/chromeos/dbus/shill/shill_service_client_unittest.cc b/chromeos/dbus/shill/shill_service_client_unittest.cc index d8c6f9e..5027ac0c 100644 --- a/chromeos/dbus/shill/shill_service_client_unittest.cc +++ b/chromeos/dbus/shill/shill_service_client_unittest.cc
@@ -36,14 +36,19 @@ void SetUp() override { ShillClientUnittestBase::SetUp(); // Create a client with the mock bus. - client_.reset(ShillServiceClient::Create()); - client_->Init(mock_bus_.get()); + ShillServiceClient::Initialize(mock_bus_.get()); + client_ = ShillServiceClient::Get(); // Run the message loop to run the signal connection result callback. base::RunLoop().RunUntilIdle(); } + void TearDown() override { + ShillServiceClient::Shutdown(); + ShillClientUnittestBase::TearDown(); + } + protected: - std::unique_ptr<ShillServiceClient> client_; + ShillServiceClient* client_ = nullptr; // Unowned convenience pointer. }; TEST_F(ShillServiceClientTest, PropertyChanged) {
diff --git a/chromeos/dbus/shill/shill_third_party_vpn_driver_client.cc b/chromeos/dbus/shill/shill_third_party_vpn_driver_client.cc index ebfc703..b540adf 100644 --- a/chromeos/dbus/shill/shill_third_party_vpn_driver_client.cc +++ b/chromeos/dbus/shill/shill_third_party_vpn_driver_client.cc
@@ -13,6 +13,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/stl_util.h" +#include "chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h" #include "chromeos/dbus/shill/shill_third_party_vpn_observer.h" #include "dbus/bus.h" #include "dbus/message.h" @@ -34,11 +35,13 @@ shill::kDnsServersParameterThirdPartyVpn, shill::kReconnectParameterThirdPartyVpn}; +ShillThirdPartyVpnDriverClient* g_instance = nullptr; + // The ShillThirdPartyVpnDriverClient implementation. class ShillThirdPartyVpnDriverClientImpl : public ShillThirdPartyVpnDriverClient { public: - ShillThirdPartyVpnDriverClientImpl(); + explicit ShillThirdPartyVpnDriverClientImpl(dbus::Bus* bus); ~ShillThirdPartyVpnDriverClientImpl() override; // ShillThirdPartyVpnDriverClient overrides @@ -67,12 +70,7 @@ const base::Closure& callback, const ShillClientHelper::ErrorCallback& error_callback) override; - protected: - void Init(dbus::Bus* bus) override { bus_ = bus; } - - ShillThirdPartyVpnDriverClient::TestInterface* GetTestInterface() override { - return nullptr; - } + TestInterface* GetTestInterface() override { return nullptr; } private: class HelperInfo { @@ -132,8 +130,9 @@ dbus::ObjectProxy* object_proxy) : helper_(object_proxy), observer_(nullptr), weak_ptr_factory_(this) {} -ShillThirdPartyVpnDriverClientImpl::ShillThirdPartyVpnDriverClientImpl() - : bus_(nullptr) { +ShillThirdPartyVpnDriverClientImpl::ShillThirdPartyVpnDriverClientImpl( + dbus::Bus* bus) + : bus_(bus) { for (uint32_t i = 0; i < base::size(kSetParametersKeyList); ++i) { valid_keys_.insert(kSetParametersKeyList[i]); } @@ -334,13 +333,38 @@ } // namespace -ShillThirdPartyVpnDriverClient::ShillThirdPartyVpnDriverClient() = default; +ShillThirdPartyVpnDriverClient::ShillThirdPartyVpnDriverClient() { + DCHECK(!g_instance); + g_instance = this; +} -ShillThirdPartyVpnDriverClient::~ShillThirdPartyVpnDriverClient() = default; +ShillThirdPartyVpnDriverClient::~ShillThirdPartyVpnDriverClient() { + DCHECK_EQ(this, g_instance); + g_instance = nullptr; +} // static -ShillThirdPartyVpnDriverClient* ShillThirdPartyVpnDriverClient::Create() { - return new ShillThirdPartyVpnDriverClientImpl(); +void ShillThirdPartyVpnDriverClient::Initialize(dbus::Bus* bus) { + DCHECK(bus); + new ShillThirdPartyVpnDriverClientImpl(bus); +} + +// static +void ShillThirdPartyVpnDriverClient::InitializeFake() { + // If a browser test creates a custom fake, don't override it. + if (!FakeShillThirdPartyVpnDriverClient::Get()) + new FakeShillThirdPartyVpnDriverClient(); +} + +// static +void ShillThirdPartyVpnDriverClient::Shutdown() { + DCHECK(g_instance); + delete g_instance; +} + +// static +ShillThirdPartyVpnDriverClient* ShillThirdPartyVpnDriverClient::Get() { + return g_instance; } } // namespace chromeos
diff --git a/chromeos/dbus/shill/shill_third_party_vpn_driver_client.h b/chromeos/dbus/shill/shill_third_party_vpn_driver_client.h index 5d8af6d..89814686 100644 --- a/chromeos/dbus/shill/shill_third_party_vpn_driver_client.h +++ b/chromeos/dbus/shill/shill_third_party_vpn_driver_client.h
@@ -12,9 +12,16 @@ #include "base/callback.h" #include "base/component_export.h" #include "base/macros.h" -#include "chromeos/dbus/dbus_client.h" #include "chromeos/dbus/shill/shill_client_helper.h" +namespace base { +class DictionaryValue; +} // namespace base + +namespace dbus { +class Bus; +} // namespace dbus + namespace chromeos { class ShillThirdPartyVpnObserver; @@ -23,8 +30,7 @@ // ThirdPartyVpnDriver service. // All methods should be called from the origin thread which initializes the // DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillThirdPartyVpnDriverClient - : public DBusClient { +class COMPONENT_EXPORT(CHROMEOS_DBUS) ShillThirdPartyVpnDriverClient { public: class TestInterface { public: @@ -37,11 +43,18 @@ virtual ~TestInterface() {} }; - ~ShillThirdPartyVpnDriverClient() override; + // Creates and initializes the global instance. |bus| must not be null. + static void Initialize(dbus::Bus* bus); - // Factory function, creates a new instance which is owned by the caller. - // For normal usage, access the singleton via DBusThreadManager::Get(). - static ShillThirdPartyVpnDriverClient* Create(); + // Creates the global instance with a fake implementation if not already + // created (e.g. in a browser test setup), otherwise does nothing. + static void InitializeFake(); + + // Destroys the global instance which must have been initialized. + static void Shutdown(); + + // Returns the global instance if initialized. May return null. + static ShillThirdPartyVpnDriverClient* Get(); // Adds an |observer| for the third party vpn driver at |object_path_value|. virtual void AddShillThirdPartyVpnObserver( @@ -83,8 +96,9 @@ protected: friend class ShillThirdPartyVpnDriverClientTest; - // Create() should be used instead. + // Initialize/Shutdown should be used instead. ShillThirdPartyVpnDriverClient(); + virtual ~ShillThirdPartyVpnDriverClient(); private: DISALLOW_COPY_AND_ASSIGN(ShillThirdPartyVpnDriverClient);
diff --git a/chromeos/dbus/shill/shill_third_party_vpn_driver_client_unittest.cc b/chromeos/dbus/shill/shill_third_party_vpn_driver_client_unittest.cc index 6e30887..4185581 100644 --- a/chromeos/dbus/shill/shill_third_party_vpn_driver_client_unittest.cc +++ b/chromeos/dbus/shill/shill_third_party_vpn_driver_client_unittest.cc
@@ -43,12 +43,17 @@ ShillClientUnittestBase::SetUp(); // Create a client with the mock bus. - client_.reset(ShillThirdPartyVpnDriverClient::Create()); - client_->Init(mock_bus_.get()); + ShillThirdPartyVpnDriverClient::Initialize(mock_bus_.get()); + client_ = ShillThirdPartyVpnDriverClient::Get(); // Run the message loop to run the signal connection result callback. base::RunLoop().RunUntilIdle(); } + void TearDown() override { + ShillThirdPartyVpnDriverClient::Shutdown(); + ShillClientUnittestBase::TearDown(); + } + MOCK_METHOD0(MockSuccess, void()); MOCK_METHOD1(MockSuccessWithWarning, void(const std::string& warning)); static void Failure(const std::string& error_name, @@ -57,7 +62,7 @@ } protected: - std::unique_ptr<ShillThirdPartyVpnDriverClient> client_; + ShillThirdPartyVpnDriverClient* client_ = nullptr; // Unowned }; TEST_F(ShillThirdPartyVpnDriverClientTest, PlatformSignal) {
diff --git a/chromeos/dbus/shill/sms_client.cc b/chromeos/dbus/shill/sms_client.cc index ff4d131..f1188815 100644 --- a/chromeos/dbus/shill/sms_client.cc +++ b/chromeos/dbus/shill/sms_client.cc
@@ -1,6 +1,7 @@ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + #include "chromeos/dbus/shill/sms_client.h" #include <map> @@ -15,6 +16,7 @@ #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" +#include "chromeos/dbus/shill/fake_sms_client.h" #include "dbus/bus.h" #include "dbus/message.h" #include "dbus/object_proxy.h" @@ -29,6 +31,8 @@ // See "enum MMSMSState" definition in ModemManager. constexpr uint32_t kSMSStateReceived = 3; // MM_SMS_STATE_RECEIVED +SMSClient* g_instance = nullptr; + class SMSReceiveHandler { public: SMSReceiveHandler(dbus::ObjectProxy* object_proxy, @@ -101,8 +105,7 @@ // DBusThreadManager instance. class SMSClientImpl : public SMSClient { public: - SMSClientImpl() : bus_(NULL), weak_ptr_factory_(this) {} - + explicit SMSClientImpl(dbus::Bus* bus) : bus_(bus), weak_ptr_factory_(this) {} ~SMSClientImpl() override = default; // Calls GetAll method. |callback| is called after the method call succeeds. @@ -116,9 +119,6 @@ std::move(callback))); } - protected: - void Init(dbus::Bus* bus) override { bus_ = bus; } - private: void OnSMSReceived(const dbus::ObjectPath& object_path, GetAllCallback callback, @@ -150,13 +150,36 @@ const char SMSClient::kSMSPropertyText[] = "Text"; const char SMSClient::kSMSPropertyTimestamp[] = "Timestamp"; -SMSClient::SMSClient() = default; +SMSClient::SMSClient() { + DCHECK(!g_instance); + g_instance = this; +} -SMSClient::~SMSClient() = default; +SMSClient::~SMSClient() { + DCHECK_EQ(this, g_instance); + g_instance = nullptr; +} // static -SMSClient* SMSClient::Create() { - return new SMSClientImpl(); +void SMSClient::Initialize(dbus::Bus* bus) { + DCHECK(bus); + new SMSClientImpl(bus); +} + +// static +void SMSClient::InitializeFake() { + new FakeSMSClient(); +} + +// static +void SMSClient::Shutdown() { + DCHECK(g_instance); + delete g_instance; +} + +// static +SMSClient* SMSClient::Get() { + return g_instance; } } // namespace chromeos
diff --git a/chromeos/dbus/shill/sms_client.h b/chromeos/dbus/shill/sms_client.h index 478691fe..de50158 100644 --- a/chromeos/dbus/shill/sms_client.h +++ b/chromeos/dbus/shill/sms_client.h
@@ -13,8 +13,9 @@ #include "chromeos/dbus/dbus_client.h" namespace base { +class Bus; class DictionaryValue; -} +} // namespace base namespace dbus { class ObjectPath; @@ -26,7 +27,7 @@ // org.freedesktop.ModemManager1.SMS service. All methods should be // called from the origin thread (UI thread) which initializes the // DBusThreadManager instance. -class COMPONENT_EXPORT(CHROMEOS_DBUS) SMSClient : public DBusClient { +class COMPONENT_EXPORT(CHROMEOS_DBUS) SMSClient { public: using GetAllCallback = base::OnceCallback<void(const base::DictionaryValue& sms)>; @@ -36,11 +37,17 @@ static const char kSMSPropertyText[]; static const char kSMSPropertyTimestamp[]; - ~SMSClient() override; + // Creates and initializes the global instance. |bus| must not be null. + static void Initialize(dbus::Bus* bus); - // Factory function, creates a new instance and returns ownership. - // For normal usage, access the singleton via DBusThreadManager::Get(). - static SMSClient* Create(); + // Creates the global instance with a fake implementation. + static void InitializeFake(); + + // Destroys the global instance which must have been initialized. + static void Shutdown(); + + // Returns the global instance if initialized. May return null. + static SMSClient* Get(); // Calls GetAll method. |callback| is called after the method call succeeds. virtual void GetAll(const std::string& service_name, @@ -48,8 +55,9 @@ GetAllCallback callback) = 0; protected: - // Create() should be used instead. + // Initialize/Shutdown should be used instead. SMSClient(); + virtual ~SMSClient(); private: DISALLOW_COPY_AND_ASSIGN(SMSClient);
diff --git a/chromeos/geolocation/simple_geolocation_unittest.cc b/chromeos/geolocation/simple_geolocation_unittest.cc index 7dc23e7..81ef9ca6 100644 --- a/chromeos/geolocation/simple_geolocation_unittest.cc +++ b/chromeos/geolocation/simple_geolocation_unittest.cc
@@ -10,7 +10,7 @@ #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "chromeos/geolocation/simple_geolocation_provider.h" #include "chromeos/geolocation/simple_geolocation_request_test_monitor.h" @@ -273,8 +273,7 @@ } TEST_F(SimpleGeolocationTest, NoWiFi) { - // This initializes DBusThreadManager and markes it "for tests only". - DBusThreadManager::GetSetterForTesting(); + shill_clients::InitializeFakes(); NetworkHandler::Initialize(); WirelessTestMonitor requests_monitor; @@ -301,7 +300,7 @@ EXPECT_EQ(1U, url_factory.attempts()); NetworkHandler::Shutdown(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } // Test sending of WiFi Access points and Cell Towers. @@ -313,11 +312,9 @@ ~SimpleGeolocationWirelessTest() override = default; void SetUp() override { - // This initializes DBusThreadManager and markes it "for tests only". - DBusThreadManager::GetSetterForTesting(); + shill_clients::InitializeFakes(); // Get the test interface for manager / device. - manager_test_ = - DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface(); + manager_test_ = ShillManagerClient::Get()->GetTestInterface(); ASSERT_TRUE(manager_test_); geolocation_handler_.reset(new GeolocationHandler()); geolocation_handler_->Init(); @@ -326,7 +323,7 @@ void TearDown() override { geolocation_handler_.reset(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } bool GetWifiAccessPoints() {
diff --git a/chromeos/network/auto_connect_handler.cc b/chromeos/network/auto_connect_handler.cc index e75109a..ad31e7e 100644 --- a/chromeos/network/auto_connect_handler.cc +++ b/chromeos/network/auto_connect_handler.cc
@@ -12,7 +12,6 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/network/device_state.h" @@ -401,7 +400,7 @@ NET_LOG(EVENT) << "ConnectToBestServices [" << AutoConnectReasonsToString(auto_connect_reasons_) << "]"; - DBusThreadManager::Get()->GetShillManagerClient()->ConnectToBestServices( + ShillManagerClient::Get()->ConnectToBestServices( base::Bind(&AutoConnectHandler::NotifyAutoConnectInitiated, weak_ptr_factory_.GetWeakPtr(), auto_connect_reasons_), base::Bind(&network_handler::ShillErrorCallbackFunction,
diff --git a/chromeos/network/client_cert_resolver.cc b/chromeos/network/client_cert_resolver.cc index 5a07452..e142d9c 100644 --- a/chromeos/network/client_cert_resolver.cc +++ b/chromeos/network/client_cert_resolver.cc
@@ -20,7 +20,6 @@ #include "base/stl_util.h" #include "base/task/post_task.h" #include "base/time/clock.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/network/certificate_helper.h" #include "chromeos/network/managed_network_configuration_handler.h" @@ -723,7 +722,7 @@ client_cert::SetEmptyShillProperties(match.cert_config_type, &shill_properties); } - DBusThreadManager::Get()->GetShillServiceClient()->SetProperties( + ShillServiceClient::Get()->SetProperties( dbus::ObjectPath(match.service_path), shill_properties, base::DoNothing(), base::BindRepeating(&LogError, match.service_path)); network_state_handler_->RequestUpdateForNetwork(match.service_path);
diff --git a/chromeos/network/client_cert_resolver_unittest.cc b/chromeos/network/client_cert_resolver_unittest.cc index 341d5bc..99e37416 100644 --- a/chromeos/network/client_cert_resolver_unittest.cc +++ b/chromeos/network/client_cert_resolver_unittest.cc
@@ -21,7 +21,7 @@ #include "base/test/scoped_task_environment.h" #include "base/test/simple_test_clock.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "chromeos/dbus/shill/shill_profile_client.h" #include "chromeos/dbus/shill/shill_service_client.h" @@ -113,11 +113,9 @@ test_system_nsscertdb_->SetSystemSlot( crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_system_nssdb_.slot()))); - DBusThreadManager::Initialize(); - service_test_ = - DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); - profile_test_ = - DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface(); + shill_clients::InitializeFakes(); + service_test_ = ShillServiceClient::Get()->GetTestInterface(); + profile_test_ = ShillProfileClient::Get()->GetTestInterface(); profile_test_->AddProfile(kUserProfilePath, kUserHash); scoped_task_environment_.RunUntilIdle(); service_test_->ClearServices(); @@ -140,7 +138,7 @@ network_profile_handler_.reset(); network_state_handler_.reset(); NetworkCertLoader::Shutdown(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } protected: @@ -260,10 +258,8 @@ base::Value("invalid id")); profile_test_->AddService(kUserProfilePath, kWifiStub); - DBusThreadManager::Get() - ->GetShillManagerClient() - ->GetTestInterface() - ->AddManagerService(kWifiStub, true); + ShillManagerClient::Get()->GetTestInterface()->AddManagerService(kWifiStub, + true); } // Sets up a policy with a certificate pattern that matches any client cert
diff --git a/chromeos/network/fast_transition_observer_unittest.cc b/chromeos/network/fast_transition_observer_unittest.cc index 3ae70ea..dea7de6 100644 --- a/chromeos/network/fast_transition_observer_unittest.cc +++ b/chromeos/network/fast_transition_observer_unittest.cc
@@ -6,7 +6,7 @@ #include "base/message_loop/message_loop.h" #include "chromeos/constants/chromeos_pref_names.h" -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "chromeos/network/fast_transition_observer.h" #include "chromeos/network/network_state_handler.h" @@ -21,7 +21,7 @@ class FastTransitionObserverTest : public ::testing::Test { public: FastTransitionObserverTest() { - DBusThreadManager::Initialize(); + shill_clients::InitializeFakes(); network_state_handler_ = NetworkStateHandler::InitializeForTest(); NetworkHandler::Initialize(); local_state_ = std::make_unique<TestingPrefServiceSimple>(); @@ -36,14 +36,13 @@ local_state_.reset(); network_state_handler_.reset(); NetworkHandler::Shutdown(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } TestingPrefServiceSimple* local_state() { return local_state_.get(); } bool GetFastTransitionStatus() { - return DBusThreadManager::Get() - ->GetShillManagerClient() + return ShillManagerClient::Get() ->GetTestInterface() ->GetFastTransitionStatus(); }
diff --git a/chromeos/network/geolocation_handler.cc b/chromeos/network/geolocation_handler.cc index c6e562ec..f4ea4bb8 100644 --- a/chromeos/network/geolocation_handler.cc +++ b/chromeos/network/geolocation_handler.cc
@@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -31,19 +30,15 @@ : cellular_enabled_(false), wifi_enabled_(false), weak_ptr_factory_(this) {} GeolocationHandler::~GeolocationHandler() { - ShillManagerClient* manager_client = - DBusThreadManager::Get()->GetShillManagerClient(); - if (manager_client) - manager_client->RemovePropertyChangedObserver(this); + if (ShillManagerClient::Get()) + ShillManagerClient::Get()->RemovePropertyChangedObserver(this); } void GeolocationHandler::Init() { - ShillManagerClient* manager_client = - DBusThreadManager::Get()->GetShillManagerClient(); - manager_client->GetProperties( + ShillManagerClient::Get()->GetProperties( base::Bind(&GeolocationHandler::ManagerPropertiesCallback, weak_ptr_factory_.GetWeakPtr())); - manager_client->AddPropertyChangedObserver(this); + ShillManagerClient::Get()->AddPropertyChangedObserver(this); } bool GeolocationHandler::GetWifiAccessPoints( @@ -134,7 +129,7 @@ } void GeolocationHandler::RequestGeolocationObjects() { - DBusThreadManager::Get()->GetShillManagerClient()->GetNetworksForGeolocation( + ShillManagerClient::Get()->GetNetworksForGeolocation( base::Bind(&GeolocationHandler::GeolocationCallback, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chromeos/network/geolocation_handler_unittest.cc b/chromeos/network/geolocation_handler_unittest.cc index b0cc696..9b16d75 100644 --- a/chromeos/network/geolocation_handler_unittest.cc +++ b/chromeos/network/geolocation_handler_unittest.cc
@@ -12,7 +12,7 @@ #include "base/strings/stringprintf.h" #include "base/test/scoped_task_environment.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -28,11 +28,9 @@ ~GeolocationHandlerTest() override = default; void SetUp() override { - // Initialize DBusThreadManager with a stub implementation. - DBusThreadManager::Initialize(); + shill_clients::InitializeFakes(); // Get the test interface for manager / device. - manager_test_ = - DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface(); + manager_test_ = ShillManagerClient::Get()->GetTestInterface(); ASSERT_TRUE(manager_test_); geolocation_handler_.reset(new GeolocationHandler()); geolocation_handler_->Init(); @@ -41,7 +39,7 @@ void TearDown() override { geolocation_handler_.reset(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } bool GetWifiAccessPoints() {
diff --git a/chromeos/network/managed_network_configuration_handler_unittest.cc b/chromeos/network/managed_network_configuration_handler_unittest.cc index 395ee4e..a77a81cd 100644 --- a/chromeos/network/managed_network_configuration_handler_unittest.cc +++ b/chromeos/network/managed_network_configuration_handler_unittest.cc
@@ -13,9 +13,9 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/shill/fake_shill_profile_client.h" -#include "chromeos/dbus/shill/fake_shill_service_client.h" +#include "chromeos/dbus/shill/shill_clients.h" +#include "chromeos/dbus/shill/shill_profile_client.h" +#include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/network/managed_network_configuration_handler_impl.h" #include "chromeos/network/mock_network_state_handler.h" #include "chromeos/network/network_configuration_handler.h" @@ -88,7 +88,7 @@ class ManagedNetworkConfigurationHandlerTest : public testing::Test { public: ManagedNetworkConfigurationHandlerTest() { - DBusThreadManager::Initialize(); + shill_clients::InitializeFakes(); network_state_handler_ = MockNetworkStateHandler::InitializeForTest(); network_profile_handler_ = std::make_unique<TestNetworkProfileHandler>(); @@ -115,7 +115,7 @@ network_configuration_handler_.reset(); network_profile_handler_.reset(); network_state_handler_.reset(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } TestNetworkPolicyObserver* policy_observer() { return &policy_observer_; } @@ -124,14 +124,12 @@ return managed_network_configuration_handler_.get(); } - FakeShillServiceClient* GetShillServiceClient() { - return static_cast<FakeShillServiceClient*>( - DBusThreadManager::Get()->GetShillServiceClient()); + ShillServiceClient::TestInterface* GetShillServiceClient() { + return ShillServiceClient::Get()->GetTestInterface(); } - FakeShillProfileClient* GetShillProfileClient() { - return static_cast<FakeShillProfileClient*>( - DBusThreadManager::Get()->GetShillProfileClient()); + ShillProfileClient::TestInterface* GetShillProfileClient() { + return ShillProfileClient::Get()->GetTestInterface(); } void InitializeStandardProfiles() {
diff --git a/chromeos/network/network_activation_handler.cc b/chromeos/network/network_activation_handler.cc index 2e53320..fd28870a 100644 --- a/chromeos/network/network_activation_handler.cc +++ b/chromeos/network/network_activation_handler.cc
@@ -6,7 +6,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/network/network_event_log.h" #include "chromeos/network/network_handler.h" @@ -43,13 +42,12 @@ const base::Closure& success_callback, const network_handler::ErrorCallback& error_callback) { NET_LOG_USER("Activation Request", service_path + ": '" + carrier + "'"); - DBusThreadManager::Get()->GetShillServiceClient()->ActivateCellularModem( - dbus::ObjectPath(service_path), - carrier, - base::Bind(&NetworkActivationHandler::HandleShillSuccess, - AsWeakPtr(), service_path, success_callback), - base::Bind(&network_handler::ShillErrorCallbackFunction, - kErrorShillError, service_path, error_callback)); + ShillServiceClient::Get()->ActivateCellularModem( + dbus::ObjectPath(service_path), carrier, + base::Bind(&NetworkActivationHandler::HandleShillSuccess, AsWeakPtr(), + service_path, success_callback), + base::Bind(&network_handler::ShillErrorCallbackFunction, kErrorShillError, + service_path, error_callback)); } void NetworkActivationHandler::CallShillCompleteActivation( @@ -57,12 +55,12 @@ const base::Closure& success_callback, const network_handler::ErrorCallback& error_callback) { NET_LOG_USER("CompleteActivation Request", service_path); - DBusThreadManager::Get()->GetShillServiceClient()->CompleteCellularActivation( + ShillServiceClient::Get()->CompleteCellularActivation( dbus::ObjectPath(service_path), - base::Bind(&NetworkActivationHandler::HandleShillSuccess, - AsWeakPtr(), service_path, success_callback), - base::Bind(&network_handler::ShillErrorCallbackFunction, - kErrorShillError, service_path, error_callback)); + base::Bind(&NetworkActivationHandler::HandleShillSuccess, AsWeakPtr(), + service_path, success_callback), + base::Bind(&network_handler::ShillErrorCallbackFunction, kErrorShillError, + service_path, error_callback)); } void NetworkActivationHandler::HandleShillSuccess(
diff --git a/chromeos/network/network_cert_migrator.cc b/chromeos/network/network_cert_migrator.cc index a0a199d..879cde1 100644 --- a/chromeos/network/network_cert_migrator.cc +++ b/chromeos/network/network_cert_migrator.cc
@@ -12,7 +12,6 @@ #include "base/bind_helpers.h" #include "base/location.h" #include "base/metrics/histogram_macros.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/network/client_cert_util.h" #include "chromeos/network/network_handler_callbacks.h" @@ -62,12 +61,11 @@ continue; } - DBusThreadManager::Get()->GetShillServiceClient()->GetProperties( + ShillServiceClient::Get()->GetProperties( dbus::ObjectPath(service_path), base::Bind(&network_handler::GetPropertiesCallback, base::Bind(&MigrationTask::MigrateNetwork, this), - network_handler::ErrorCallback(), - service_path)); + network_handler::ErrorCallback(), service_path)); } } @@ -145,7 +143,7 @@ void SendPropertiesToShill(const std::string& service_path, const base::DictionaryValue& properties) { - DBusThreadManager::Get()->GetShillServiceClient()->SetProperties( + ShillServiceClient::Get()->SetProperties( dbus::ObjectPath(service_path), properties, base::DoNothing(), base::Bind(&LogError, service_path)); }
diff --git a/chromeos/network/network_cert_migrator_unittest.cc b/chromeos/network/network_cert_migrator_unittest.cc index 324969fb..adcf648 100644 --- a/chromeos/network/network_cert_migrator_unittest.cc +++ b/chromeos/network/network_cert_migrator_unittest.cc
@@ -12,7 +12,7 @@ #include "base/macros.h" #include "base/strings/string_number_conversions.h" #include "base/test/scoped_task_environment.h" -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/dbus/shill/shill_profile_client.h" #include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/network/network_cert_loader.h" @@ -64,13 +64,10 @@ test_system_nsscertdb_->SetSystemSlot( crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_system_nssdb_.slot()))); - DBusThreadManager::Initialize(); - service_test_ = - DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); - DBusThreadManager::Get() - ->GetShillProfileClient() - ->GetTestInterface() - ->AddProfile(kUserShillProfile, "" /* userhash */); + shill_clients::InitializeFakes(); + service_test_ = ShillServiceClient::Get()->GetTestInterface(); + ShillProfileClient::Get()->GetTestInterface()->AddProfile( + kUserShillProfile, "" /* userhash */); scoped_task_environment_.RunUntilIdle(); service_test_->ClearServices(); scoped_task_environment_.RunUntilIdle(); @@ -83,7 +80,7 @@ network_cert_migrator_.reset(); network_state_handler_.reset(); NetworkCertLoader::Shutdown(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } protected:
diff --git a/chromeos/network/network_configuration_handler.cc b/chromeos/network/network_configuration_handler.cc index b594fcb..bb5fae5 100644 --- a/chromeos/network/network_configuration_handler.cc +++ b/chromeos/network/network_configuration_handler.cc
@@ -18,7 +18,6 @@ #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "chromeos/dbus/shill/shill_profile_client.h" #include "chromeos/dbus/shill/shill_service_client.h" @@ -118,12 +117,10 @@ } void Run() { - DBusThreadManager::Get() - ->GetShillServiceClient() - ->GetLoadableProfileEntries( - dbus::ObjectPath(service_path_), - base::Bind(&ProfileEntryDeleter::GetProfileEntriesToDeleteCallback, - weak_ptr_factory_.GetWeakPtr())); + ShillServiceClient::Get()->GetLoadableProfileEntries( + dbus::ObjectPath(service_path_), + base::Bind(&ProfileEntryDeleter::GetProfileEntriesToDeleteCallback, + weak_ptr_factory_.GetWeakPtr())); } private: @@ -166,7 +163,7 @@ NET_LOG(DEBUG) << "Delete Profile Entry: " << profile_path << ": " << entry_path; profile_delete_entries_[profile_path] = entry_path; - DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry( + ShillProfileClient::Get()->DeleteEntry( dbus::ObjectPath(profile_path), entry_path, base::Bind(&ProfileEntryDeleter::ProfileEntryDeletedCallback, weak_ptr_factory_.GetWeakPtr(), profile_path, entry_path), @@ -258,7 +255,7 @@ callback.Run(service_path, dictionary); return; } - DBusThreadManager::Get()->GetShillServiceClient()->GetProperties( + ShillServiceClient::Get()->GetProperties( dbus::ObjectPath(service_path), base::Bind(&NetworkConfigurationHandler::GetPropertiesCallback, weak_ptr_factory_.GetWeakPtr(), callback, error_callback, @@ -297,7 +294,7 @@ std::unique_ptr<base::DictionaryValue> properties_copy( properties_to_set->DeepCopy()); - DBusThreadManager::Get()->GetShillServiceClient()->SetProperties( + ShillServiceClient::Get()->SetProperties( dbus::ObjectPath(service_path), *properties_to_set, base::Bind(&NetworkConfigurationHandler::SetPropertiesSuccessCallback, weak_ptr_factory_.GetWeakPtr(), service_path, @@ -326,7 +323,7 @@ iter != names.end(); ++iter) { NET_LOG(DEBUG) << "ClearProperty: " << service_path << "." << *iter; } - DBusThreadManager::Get()->GetShillServiceClient()->ClearProperties( + ShillServiceClient::Get()->ClearProperties( dbus::ObjectPath(service_path), names, base::Bind(&NetworkConfigurationHandler::ClearPropertiesSuccessCallback, weak_ptr_factory_.GetWeakPtr(), service_path, names, callback), @@ -338,8 +335,7 @@ const base::DictionaryValue& shill_properties, const network_handler::ServiceResultCallback& callback, const network_handler::ErrorCallback& error_callback) { - ShillManagerClient* manager = - DBusThreadManager::Get()->GetShillManagerClient(); + ShillManagerClient* manager = ShillManagerClient::Get(); std::string type; shill_properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type); DCHECK(!type.empty()); @@ -437,7 +433,7 @@ NET_LOG(USER) << "SetNetworkProfile: " << service_path << ": " << profile_path; base::Value profile_path_value(profile_path); - DBusThreadManager::Get()->GetShillServiceClient()->SetProperty( + ShillServiceClient::Get()->SetProperty( dbus::ObjectPath(service_path), shill::kProfileProperty, profile_path_value, base::Bind(&NetworkConfigurationHandler::SetNetworkProfileCompleted, @@ -453,7 +449,7 @@ const base::Closure& callback, const network_handler::ErrorCallback& error_callback) { NET_LOG(USER) << "SetManagerProperty: " << property_name << ": " << value; - DBusThreadManager::Get()->GetShillManagerClient()->SetProperty( + ShillManagerClient::Get()->SetProperty( property_name, value, callback, base::Bind(&ManagerSetPropertiesErrorCallback, error_callback)); }
diff --git a/chromeos/network/network_configuration_handler_unittest.cc b/chromeos/network/network_configuration_handler_unittest.cc index f32719b..9689665 100644 --- a/chromeos/network/network_configuration_handler_unittest.cc +++ b/chromeos/network/network_configuration_handler_unittest.cc
@@ -18,9 +18,10 @@ #include "base/stl_util.h" #include "base/strings/string_piece.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/shill/fake_shill_profile_client.h" -#include "chromeos/dbus/shill/fake_shill_service_client.h" +#include "chromeos/dbus/shill/shill_clients.h" +#include "chromeos/dbus/shill/shill_manager_client.h" +#include "chromeos/dbus/shill/shill_profile_client.h" +#include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/network/network_configuration_handler.h" #include "chromeos/network/network_configuration_observer.h" #include "chromeos/network/network_profile_handler.h" @@ -146,7 +147,7 @@ class NetworkConfigurationHandlerTest : public testing::Test { public: NetworkConfigurationHandlerTest() { - DBusThreadManager::Initialize(); + shill_clients::InitializeFakes(); network_state_handler_ = NetworkStateHandler::InitializeForTest(); // Note: NetworkConfigurationHandler's contructor is private, so @@ -169,7 +170,7 @@ network_configuration_handler_.reset(); network_state_handler_.reset(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } void SuccessCallback(const std::string& callback_name) { @@ -258,7 +259,7 @@ const std::string& key, std::string* result) { ShillServiceClient::TestInterface* service_test = - DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); + ShillServiceClient::Get()->GetTestInterface(); const base::DictionaryValue* properties = service_test->GetServiceProperties(service_path); if (!properties) @@ -296,14 +297,12 @@ return true; } - FakeShillServiceClient* GetShillServiceClient() { - return static_cast<FakeShillServiceClient*>( - DBusThreadManager::Get()->GetShillServiceClient()); + ShillServiceClient::TestInterface* GetShillServiceClient() { + return ShillServiceClient::Get()->GetTestInterface(); } - FakeShillProfileClient* GetShillProfileClient() { - return static_cast<FakeShillProfileClient*>( - DBusThreadManager::Get()->GetShillProfileClient()); + ShillProfileClient::TestInterface* GetShillProfileClient() { + return ShillProfileClient::Get()->GetTestInterface(); } std::unique_ptr<NetworkStateHandler> network_state_handler_; @@ -676,7 +675,7 @@ shill::kAlwaysOnVpnPackageProperty, base::Value(vpn_package), base::DoNothing(), base::Bind(&ErrorCallback)); - DBusThreadManager::Get()->GetShillManagerClient()->GetProperties( + ShillManagerClient::Get()->GetProperties( Bind(&NetworkConfigurationHandlerTest::ManagerGetPropertiesCallback, base::Unretained(this), "ManagerGetProperties")); base::RunLoop().RunUntilIdle();
diff --git a/chromeos/network/network_connect_unittest.cc b/chromeos/network/network_connect_unittest.cc index fb4f2f7..d6365df 100644 --- a/chromeos/network/network_connect_unittest.cc +++ b/chromeos/network/network_connect_unittest.cc
@@ -10,7 +10,7 @@ #include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "base/test/scoped_task_environment.h" -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/dbus/shill/shill_device_client.h" #include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/login/login_state/login_state.h" @@ -92,7 +92,7 @@ void SetUp() override { testing::Test::SetUp(); - DBusThreadManager::Initialize(); + shill_clients::InitializeFakes(); LoginState::Initialize(); SetupDefaultShillState(); NetworkHandler::Initialize(); @@ -113,15 +113,14 @@ mock_delegate_.reset(); LoginState::Shutdown(); NetworkHandler::Shutdown(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); testing::Test::TearDown(); } protected: void SetupDefaultShillState() { base::RunLoop().RunUntilIdle(); - device_test_ = - DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface(); + device_test_ = ShillDeviceClient::Get()->GetTestInterface(); device_test_->ClearDevices(); device_test_->AddDevice("/device/stub_wifi_device1", shill::kTypeWifi, "stub_wifi_device1"); @@ -131,8 +130,7 @@ kCellular1DevicePath, shill::kTechnologyFamilyProperty, base::Value(shill::kNetworkTechnologyGsm), /*notify_changed=*/true); - service_test_ = - DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); + service_test_ = ShillServiceClient::Get()->GetTestInterface(); service_test_->ClearServices(); const bool add_to_visible = true;
diff --git a/chromeos/network/network_connection_handler.cc b/chromeos/network/network_connection_handler.cc index 4ee7ca1..d7df369 100644 --- a/chromeos/network/network_connection_handler.cc +++ b/chromeos/network/network_connection_handler.cc
@@ -11,7 +11,6 @@ #include "base/strings/string_number_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/network/client_cert_resolver.h"
diff --git a/chromeos/network/network_connection_handler_impl.cc b/chromeos/network/network_connection_handler_impl.cc index 6cc346e..a9ad926 100644 --- a/chromeos/network/network_connection_handler_impl.cc +++ b/chromeos/network/network_connection_handler_impl.cc
@@ -12,7 +12,6 @@ #include "base/strings/string_number_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/network/client_cert_resolver.h" @@ -678,7 +677,7 @@ const std::string& service_path) { NET_LOG_EVENT("Sending Connect Request to Shill", service_path); network_state_handler_->ClearLastErrorForNetwork(service_path); - DBusThreadManager::Get()->GetShillServiceClient()->Connect( + ShillServiceClient::Get()->Connect( dbus::ObjectPath(service_path), base::Bind(&NetworkConnectionHandlerImpl::HandleShillConnectSuccess, AsWeakPtr(), service_path), @@ -843,7 +842,7 @@ const base::Closure& success_callback, const network_handler::ErrorCallback& error_callback) { NET_LOG_USER("Disconnect Request", service_path); - DBusThreadManager::Get()->GetShillServiceClient()->Disconnect( + ShillServiceClient::Get()->Disconnect( dbus::ObjectPath(service_path), base::Bind(&NetworkConnectionHandlerImpl::HandleShillDisconnectSuccess, AsWeakPtr(), service_path, success_callback),
diff --git a/chromeos/network/network_device_handler_impl.cc b/chromeos/network/network_device_handler_impl.cc index 84e8533d..533c25f 100644 --- a/chromeos/network/network_device_handler_impl.cc +++ b/chromeos/network/network_device_handler_impl.cc
@@ -21,7 +21,6 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_device_client.h" #include "chromeos/dbus/shill/shill_ipconfig_client.h" #include "chromeos/network/device_state.h" @@ -97,7 +96,7 @@ std::string ipconfig_path; if (!ip_configs->GetString(i, &ipconfig_path)) continue; - DBusThreadManager::Get()->GetShillIPConfigClient()->Refresh( + ShillIPConfigClient::Get()->Refresh( dbus::ObjectPath(ipconfig_path), base::BindOnce(&IPConfigRefreshCallback, ipconfig_path)); } @@ -116,7 +115,7 @@ const base::Closure& callback, const network_handler::ErrorCallback& error_callback) { NET_LOG(USER) << "Device.SetProperty: " << property_name << " = " << value; - DBusThreadManager::Get()->GetShillDeviceClient()->SetProperty( + ShillDeviceClient::Get()->SetProperty( dbus::ObjectPath(device_path), property_name, value, callback, base::Bind(&HandleShillCallFailure, device_path, error_callback)); } @@ -184,7 +183,7 @@ new_params.ip_or_mac_address = params.ip_or_mac_address; base::TimeDelta request_delay; - if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface()) + if (!ShillDeviceClient::Get()->GetTestInterface()) request_delay = base::TimeDelta::FromMilliseconds(request_delay_ms); base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( @@ -212,7 +211,7 @@ << device_path; const int64_t kReRequestDelayMs = 1000; base::TimeDelta request_delay; - if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface()) + if (!ShillDeviceClient::Get()->GetTestInterface()) request_delay = base::TimeDelta::FromMilliseconds(kReRequestDelayMs); base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( @@ -249,7 +248,7 @@ LOG(ERROR) << "TDLS: " << params.operation; NET_LOG(EVENT) << "CallPerformTDLSOperation: " << params.operation << ": " << device_path; - DBusThreadManager::Get()->GetShillDeviceClient()->PerformTDLSOperation( + ShillDeviceClient::Get()->PerformTDLSOperation( dbus::ObjectPath(device_path), params.operation, params.ip_or_mac_address, base::Bind(&TDLSSuccessCallback, device_path, params, callback, error_callback), @@ -268,7 +267,7 @@ const std::string& device_path, const network_handler::DictionaryResultCallback& callback, const network_handler::ErrorCallback& error_callback) const { - DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties( + ShillDeviceClient::Get()->GetProperties( dbus::ObjectPath(device_path), base::Bind(&network_handler::GetPropertiesCallback, callback, error_callback, device_path)); @@ -314,7 +313,7 @@ const network_handler::ErrorCallback& error_callback) { NET_LOG(USER) << "Device.RegisterCellularNetwork: " << device_path << " Id: " << network_id; - DBusThreadManager::Get()->GetShillDeviceClient()->Register( + ShillDeviceClient::Get()->Register( dbus::ObjectPath(device_path), network_id, callback, base::Bind(&HandleShillCallFailure, device_path, error_callback)); } @@ -326,7 +325,7 @@ const network_handler::ErrorCallback& error_callback) { NET_LOG(USER) << "Device.SetCarrier: " << device_path << " carrier: " << carrier; - DBusThreadManager::Get()->GetShillDeviceClient()->SetCarrier( + ShillDeviceClient::Get()->SetCarrier( dbus::ObjectPath(device_path), carrier, callback, base::Bind(&HandleShillCallFailure, device_path, error_callback)); } @@ -338,7 +337,7 @@ const base::Closure& callback, const network_handler::ErrorCallback& error_callback) { NET_LOG(USER) << "Device.RequirePin: " << device_path << ": " << require_pin; - DBusThreadManager::Get()->GetShillDeviceClient()->RequirePin( + ShillDeviceClient::Get()->RequirePin( dbus::ObjectPath(device_path), pin, require_pin, callback, base::Bind(&HandleShillCallFailure, device_path, error_callback)); } @@ -349,7 +348,7 @@ const base::Closure& callback, const network_handler::ErrorCallback& error_callback) { NET_LOG(USER) << "Device.EnterPin: " << device_path; - DBusThreadManager::Get()->GetShillDeviceClient()->EnterPin( + ShillDeviceClient::Get()->EnterPin( dbus::ObjectPath(device_path), pin, callback, base::Bind(&HandleShillCallFailure, device_path, error_callback)); } @@ -361,7 +360,7 @@ const base::Closure& callback, const network_handler::ErrorCallback& error_callback) { NET_LOG(USER) << "Device.UnblockPin: " << device_path; - DBusThreadManager::Get()->GetShillDeviceClient()->UnblockPin( + ShillDeviceClient::Get()->UnblockPin( dbus::ObjectPath(device_path), puk, new_pin, callback, base::Bind(&HandleShillCallFailure, device_path, error_callback)); } @@ -373,7 +372,7 @@ const base::Closure& callback, const network_handler::ErrorCallback& error_callback) { NET_LOG(USER) << "Device.ChangePin: " << device_path; - DBusThreadManager::Get()->GetShillDeviceClient()->ChangePin( + ShillDeviceClient::Get()->ChangePin( dbus::ObjectPath(device_path), old_pin, new_pin, callback, base::Bind(&HandleShillCallFailure, device_path, error_callback)); } @@ -431,7 +430,7 @@ return; NET_LOG(USER) << "Device.AddWakeOnWifi: " << device_state->path(); - DBusThreadManager::Get()->GetShillDeviceClient()->AddWakeOnPacketConnection( + ShillDeviceClient::Get()->AddWakeOnPacketConnection( dbus::ObjectPath(device_state->path()), ip_endpoint, callback, base::Bind(&HandleShillCallFailure, device_state->path(), error_callback)); @@ -447,7 +446,7 @@ NET_LOG(USER) << "Device.AddWifiWakeOnPacketOfTypes: " << device_state->path() << " Types: " << base::JoinString(types, " "); - DBusThreadManager::Get()->GetShillDeviceClient()->AddWakeOnPacketOfTypes( + ShillDeviceClient::Get()->AddWakeOnPacketOfTypes( dbus::ObjectPath(device_state->path()), types, callback, base::Bind(&HandleShillCallFailure, device_state->path(), error_callback)); @@ -462,12 +461,10 @@ return; NET_LOG(USER) << "Device.RemoveWakeOnWifi: " << device_state->path(); - DBusThreadManager::Get() - ->GetShillDeviceClient() - ->RemoveWakeOnPacketConnection( - dbus::ObjectPath(device_state->path()), ip_endpoint, callback, - base::Bind(&HandleShillCallFailure, device_state->path(), - error_callback)); + ShillDeviceClient::Get()->RemoveWakeOnPacketConnection( + dbus::ObjectPath(device_state->path()), ip_endpoint, callback, + base::Bind(&HandleShillCallFailure, device_state->path(), + error_callback)); } void NetworkDeviceHandlerImpl::RemoveWifiWakeOnPacketOfTypes( @@ -481,7 +478,7 @@ NET_LOG(USER) << "Device.RemoveWifiWakeOnPacketOfTypes: " << device_state->path() << " Types: " << base::JoinString(types, " "); - DBusThreadManager::Get()->GetShillDeviceClient()->RemoveWakeOnPacketOfTypes( + ShillDeviceClient::Get()->RemoveWakeOnPacketOfTypes( dbus::ObjectPath(device_state->path()), types, callback, base::Bind(&HandleShillCallFailure, device_state->path(), error_callback)); @@ -495,12 +492,10 @@ return; NET_LOG(USER) << "Device.RemoveAllWakeOnWifi: " << device_state->path(); - DBusThreadManager::Get() - ->GetShillDeviceClient() - ->RemoveAllWakeOnPacketConnections( - dbus::ObjectPath(device_state->path()), callback, - base::Bind(&HandleShillCallFailure, device_state->path(), - error_callback)); + ShillDeviceClient::Get()->RemoveAllWakeOnPacketConnections( + dbus::ObjectPath(device_state->path()), callback, + base::Bind(&HandleShillCallFailure, device_state->path(), + error_callback)); } void NetworkDeviceHandlerImpl::DeviceListChanged() {
diff --git a/chromeos/network/network_device_handler_unittest.cc b/chromeos/network/network_device_handler_unittest.cc index aa7eafd..fe11cd5 100644 --- a/chromeos/network/network_device_handler_unittest.cc +++ b/chromeos/network/network_device_handler_unittest.cc
@@ -11,7 +11,8 @@ #include "base/values.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/fake_shill_device_client.h" -#include "chromeos/dbus/shill/fake_shill_manager_client.h" +#include "chromeos/dbus/shill/shill_clients.h" +#include "chromeos/dbus/shill/shill_manager_client.h" #include "chromeos/network/network_device_handler_impl.h" #include "chromeos/network/network_state_handler.h" #include "testing/gtest/include/gtest/gtest.h" @@ -38,9 +39,9 @@ ~NetworkDeviceHandlerTest() override = default; void SetUp() override { - fake_device_client_ = new FakeShillDeviceClient; - DBusThreadManager::GetSetterForTesting()->SetShillDeviceClient( - std::unique_ptr<ShillDeviceClient>(fake_device_client_)); + shill_clients::InitializeFakes(); + fake_device_client_ = ShillDeviceClient::Get(); + fake_device_client_->GetTestInterface()->ClearDevices(); success_callback_ = base::Bind(&NetworkDeviceHandlerTest::SuccessCallback, base::Unretained(this)); @@ -78,7 +79,7 @@ network_state_handler_->Shutdown(); network_device_handler_.reset(); network_state_handler_.reset(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } void ErrorCallback(const std::string& error_name, @@ -105,7 +106,7 @@ protected: base::test::ScopedTaskEnvironment scoped_task_environment_; std::string result_; - FakeShillDeviceClient* fake_device_client_ = nullptr; + ShillDeviceClient* fake_device_client_ = nullptr; std::unique_ptr<NetworkDeviceHandler> network_device_handler_; std::unique_ptr<NetworkStateHandler> network_state_handler_; base::Closure success_callback_; @@ -374,7 +375,8 @@ const char kNewPin[] = "1234"; const char kIncorrectPin[] = "9999"; - fake_device_client_->SetSimLocked(kDefaultCellularDevicePath, true); + fake_device_client_->GetTestInterface()->SetSimLocked( + kDefaultCellularDevicePath, true); // Test that the success callback gets called. network_device_handler_->ChangePin(
diff --git a/chromeos/network/network_profile_handler.cc b/chromeos/network/network_profile_handler.cc index 82713e72..b83d51b2 100644 --- a/chromeos/network/network_profile_handler.cc +++ b/chromeos/network/network_profile_handler.cc
@@ -11,7 +11,6 @@ #include "base/bind.h" #include "base/strings/string_util.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "chromeos/dbus/shill/shill_profile_client.h" #include "chromeos/network/network_profile_observer.h" @@ -127,11 +126,10 @@ pending_profile_creations_.insert(*it); VLOG(2) << "Requesting properties of profile path " << *it << "."; - DBusThreadManager::Get()->GetShillProfileClient()->GetProperties( + ShillProfileClient::Get()->GetProperties( dbus::ObjectPath(*it), base::Bind(&NetworkProfileHandler::GetProfilePropertiesCallback, - weak_ptr_factory_.GetWeakPtr(), - *it), + weak_ptr_factory_.GetWeakPtr(), *it), base::Bind(&LogProfileRequestError, *it)); } } @@ -209,18 +207,16 @@ } void NetworkProfileHandler::Init() { - DBusThreadManager::Get()->GetShillManagerClient()-> - AddPropertyChangedObserver(this); + ShillManagerClient::Get()->AddPropertyChangedObserver(this); // Request the initial profile list. - DBusThreadManager::Get()->GetShillManagerClient()->GetProperties( + ShillManagerClient::Get()->GetProperties( base::Bind(&NetworkProfileHandler::GetManagerPropertiesCallback, weak_ptr_factory_.GetWeakPtr())); } NetworkProfileHandler::~NetworkProfileHandler() { - DBusThreadManager::Get()->GetShillManagerClient()-> - RemovePropertyChangedObserver(this); + ShillManagerClient::Get()->RemovePropertyChangedObserver(this); } } // namespace chromeos
diff --git a/chromeos/network/network_sms_handler.cc b/chromeos/network/network_sms_handler.cc index 355e4b5..7ec3656 100644 --- a/chromeos/network/network_sms_handler.cc +++ b/chromeos/network/network_sms_handler.cc
@@ -15,7 +15,6 @@ #include "base/containers/circular_deque.h" #include "base/macros.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/gsm_sms_client.h" #include "chromeos/dbus/shill/modem_messaging_client.h" #include "chromeos/dbus/shill/shill_device_client.h" @@ -88,13 +87,13 @@ deleting_messages_(false), weak_ptr_factory_(this) { // Set the handler for received Sms messaages. - DBusThreadManager::Get()->GetGsmSMSClient()->SetSmsReceivedHandler( + GsmSMSClient::Get()->SetSmsReceivedHandler( service_name_, object_path_, base::Bind(&ModemManagerNetworkSmsDeviceHandler::SmsReceivedCallback, weak_ptr_factory_.GetWeakPtr())); // List the existing messages. - DBusThreadManager::Get()->GetGsmSMSClient()->List( + GsmSMSClient::Get()->List( service_name_, object_path_, base::BindOnce( &NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler::ListCallback, @@ -102,8 +101,7 @@ } void NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler::RequestUpdate() { - DBusThreadManager::Get()->GetGsmSMSClient()->RequestUpdate( - service_name_, object_path_); + GsmSMSClient::Get()->RequestUpdate(service_name_, object_path_); } void NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler::ListCallback( @@ -136,7 +134,7 @@ deleting_messages_ = true; uint32_t index = delete_queue_.back(); delete_queue_.pop_back(); - DBusThreadManager::Get()->GetGsmSMSClient()->Delete( + GsmSMSClient::Get()->Delete( service_name_, object_path_, index, base::BindOnce(&NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler:: DeleteCallback, @@ -155,7 +153,7 @@ // Only handle complete messages. if (!complete) return; - DBusThreadManager::Get()->GetGsmSMSClient()->Get( + GsmSMSClient::Get()->Get( service_name_, object_path_, index, base::BindOnce( &NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler::GetCallback, @@ -225,15 +223,14 @@ retrieving_messages_(false), weak_ptr_factory_(this) { // Set the handler for received Sms messaages. - DBusThreadManager::Get()->GetModemMessagingClient()->SetSmsReceivedHandler( + ModemMessagingClient::Get()->SetSmsReceivedHandler( service_name_, object_path_, - base::Bind( - &NetworkSmsHandler:: - ModemManager1NetworkSmsDeviceHandler::SmsReceivedCallback, - weak_ptr_factory_.GetWeakPtr())); + base::Bind(&NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler:: + SmsReceivedCallback, + weak_ptr_factory_.GetWeakPtr())); // List the existing messages. - DBusThreadManager::Get()->GetModemMessagingClient()->List( + ModemMessagingClient::Get()->List( service_name_, object_path_, base::BindOnce(&NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler:: ListCallback, @@ -243,7 +240,7 @@ void NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::RequestUpdate() { // Calling List using the service "AddSMS" causes the stub // implementation to deliver new sms messages. - DBusThreadManager::Get()->GetModemMessagingClient()->List( + ModemMessagingClient::Get()->List( std::string("AddSMS"), dbus::ObjectPath("/"), base::BindOnce(&NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler:: ListCallback, @@ -277,7 +274,7 @@ deleting_messages_ = true; dbus::ObjectPath sms_path = std::move(delete_queue_.back()); delete_queue_.pop_back(); - DBusThreadManager::Get()->GetModemMessagingClient()->Delete( + ModemMessagingClient::Get()->Delete( service_name_, object_path_, sms_path, base::BindOnce(&NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler:: DeleteCallback, @@ -303,7 +300,7 @@ retrieving_messages_ = true; dbus::ObjectPath sms_path = retrieval_queue_.front(); retrieval_queue_.pop_front(); - DBusThreadManager::Get()->GetSMSClient()->GetAll( + SMSClient::Get()->GetAll( service_name_, sms_path, base::BindOnce( &NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::GetCallback, @@ -358,17 +355,15 @@ } NetworkSmsHandler::~NetworkSmsHandler() { - DBusThreadManager::Get()->GetShillManagerClient()-> - RemovePropertyChangedObserver(this); + ShillManagerClient::Get()->RemovePropertyChangedObserver(this); } void NetworkSmsHandler::Init() { // Add as an observer here so that new devices added after this call are // recognized. - DBusThreadManager::Get()->GetShillManagerClient()->AddPropertyChangedObserver( - this); + ShillManagerClient::Get()->AddPropertyChangedObserver(this); // Request network manager properties so that we can get the list of devices. - DBusThreadManager::Get()->GetShillManagerClient()->GetProperties( + ShillManagerClient::Get()->GetProperties( base::Bind(&NetworkSmsHandler::ManagerPropertiesCallback, weak_ptr_factory_.GetWeakPtr())); } @@ -449,11 +444,10 @@ if (!device_path.empty()) { // Request device properties. VLOG(1) << "GetDeviceProperties: " << device_path; - DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties( + ShillDeviceClient::Get()->GetProperties( dbus::ObjectPath(device_path), base::Bind(&NetworkSmsHandler::DevicePropertiesCallback, - weak_ptr_factory_.GetWeakPtr(), - device_path)); + weak_ptr_factory_.GetWeakPtr(), device_path)); } } }
diff --git a/chromeos/network/network_sms_handler_unittest.cc b/chromeos/network/network_sms_handler_unittest.cc index d515c12..b1dd9b0 100644 --- a/chromeos/network/network_sms_handler_unittest.cc +++ b/chromeos/network/network_sms_handler_unittest.cc
@@ -12,7 +12,7 @@ #include "base/run_loop.h" #include "base/test/scoped_task_environment.h" #include "chromeos/constants/chromeos_switches.h" -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/dbus/shill/shill_device_client.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -62,10 +62,9 @@ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); command_line->AppendSwitch(chromeos::switches::kSmsTestMessages); - // Initialize DBusThreadManager with a stub implementation. - DBusThreadManager::Initialize(); + shill_clients::InitializeFakes(); ShillDeviceClient::TestInterface* device_test = - DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface(); + ShillDeviceClient::Get()->GetTestInterface(); ASSERT_TRUE(device_test); device_test->AddDevice("/org/freedesktop/ModemManager1/stub/0", shill::kTypeCellular, @@ -86,7 +85,7 @@ void TearDown() override { network_sms_handler_->RemoveObserver(test_observer_.get()); network_sms_handler_.reset(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } protected:
diff --git a/chromeos/network/network_state_handler_unittest.cc b/chromeos/network/network_state_handler_unittest.cc index b816a33..3989cc5e 100644 --- a/chromeos/network/network_state_handler_unittest.cc +++ b/chromeos/network/network_state_handler_unittest.cc
@@ -21,7 +21,7 @@ #include "base/test/scoped_task_environment.h" #include "base/values.h" #include "chromeos/constants/chromeos_switches.h" -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/dbus/shill/shill_device_client.h" #include "chromeos/dbus/shill/shill_ipconfig_client.h" #include "chromeos/dbus/shill/shill_manager_client.h" @@ -101,11 +101,9 @@ void NetworkListChanged() override { NetworkStateHandler::NetworkStateList networks; - handler_->GetNetworkListByType(chromeos::NetworkTypePattern::Default(), - false /* configured_only */, - false /* visible_only */, - 0 /* no limit */, - &networks); + handler_->GetNetworkListByType( + chromeos::NetworkTypePattern::Default(), false /* configured_only */, + false /* visible_only */, 0 /* no limit */, &networks); network_count_ = networks.size(); ++network_list_changed_count_; } @@ -262,8 +260,7 @@ ~NetworkStateHandlerTest() override = default; void SetUp() override { - // Initialize DBusThreadManager with a stub implementation. - DBusThreadManager::Initialize(); + shill_clients::InitializeFakes(); SetupDefaultShillState(); network_state_handler_.reset(new NetworkStateHandler); test_observer_.reset(new TestObserver(network_state_handler_.get())); @@ -278,7 +275,7 @@ network_state_handler_->Shutdown(); test_observer_.reset(); network_state_handler_.reset(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } protected: @@ -293,48 +290,32 @@ void SetupDefaultShillState() { base::RunLoop().RunUntilIdle(); // Process any pending updates - device_test_ = - DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface(); + device_test_ = ShillDeviceClient::Get()->GetTestInterface(); ASSERT_TRUE(device_test_); device_test_->ClearDevices(); - device_test_->AddDevice(kShillManagerClientStubWifiDevice, - shill::kTypeWifi, "stub_wifi_device1"); + device_test_->AddDevice(kShillManagerClientStubWifiDevice, shill::kTypeWifi, + "stub_wifi_device1"); device_test_->AddDevice(kShillManagerClientStubCellularDevice, shill::kTypeCellular, "stub_cellular_device1"); - manager_test_ = - DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface(); + manager_test_ = ShillManagerClient::Get()->GetTestInterface(); ASSERT_TRUE(manager_test_); - profile_test_ = - DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface(); + profile_test_ = ShillProfileClient::Get()->GetTestInterface(); ASSERT_TRUE(profile_test_); profile_test_->ClearProfiles(); - service_test_ = - DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); + service_test_ = ShillServiceClient::Get()->GetTestInterface(); ASSERT_TRUE(service_test_); service_test_->ClearServices(); - AddService(kShillManagerClientStubDefaultService, - "eth1_guid", - "eth1", - shill::kTypeEthernet, - shill::kStateOnline); - AddService(kShillManagerClientStubDefaultWifi, - "wifi1_guid", - "wifi1", - shill::kTypeWifi, - shill::kStateOnline); - AddService(kShillManagerClientStubWifi2, - "wifi2_guid", - "wifi2", - shill::kTypeWifi, - shill::kStateIdle); - AddService(kShillManagerClientStubCellular, - "cellular1_guid", - "cellular1", - shill::kTypeCellular, - shill::kStateIdle); + AddService(kShillManagerClientStubDefaultService, "eth1_guid", "eth1", + shill::kTypeEthernet, shill::kStateOnline); + AddService(kShillManagerClientStubDefaultWifi, "wifi1_guid", "wifi1", + shill::kTypeWifi, shill::kStateOnline); + AddService(kShillManagerClientStubWifi2, "wifi2_guid", "wifi2", + shill::kTypeWifi, shill::kStateIdle); + AddService(kShillManagerClientStubCellular, "cellular1_guid", "cellular1", + shill::kTypeCellular, shill::kStateIdle); } void UpdateManagerProperties() { base::RunLoop().RunUntilIdle(); } @@ -342,9 +323,9 @@ void SetServiceProperty(const std::string& service_path, const std::string& key, const base::Value& value) { - DBusThreadManager::Get()->GetShillServiceClient()->SetProperty( - dbus::ObjectPath(service_path), key, value, base::DoNothing(), - base::Bind(&ErrorCallbackFunction)); + ShillServiceClient::Get()->SetProperty(dbus::ObjectPath(service_path), key, + value, base::DoNothing(), + base::Bind(&ErrorCallbackFunction)); } void SetProperties(NetworkState* network, const base::Value& properties) { @@ -393,14 +374,17 @@ EXPECT_EQ(kShillManagerClientStubDefaultService, network_state_handler_->DefaultNetwork()->path()); EXPECT_EQ(kShillManagerClientStubDefaultService, - network_state_handler_->ConnectedNetworkByType( - NetworkTypePattern::Ethernet())->path()); - EXPECT_EQ(kShillManagerClientStubDefaultWifi, - network_state_handler_->ConnectedNetworkByType( - NetworkTypePattern::WiFi())->path()); - EXPECT_EQ(kShillManagerClientStubCellular, - network_state_handler_->FirstNetworkByType( - NetworkTypePattern::Mobile())->path()); + network_state_handler_ + ->ConnectedNetworkByType(NetworkTypePattern::Ethernet()) + ->path()); + EXPECT_EQ( + kShillManagerClientStubDefaultWifi, + network_state_handler_->ConnectedNetworkByType(NetworkTypePattern::WiFi()) + ->path()); + EXPECT_EQ( + kShillManagerClientStubCellular, + network_state_handler_->FirstNetworkByType(NetworkTypePattern::Mobile()) + ->path()); EXPECT_EQ( kShillManagerClientStubCellular, network_state_handler_->FirstNetworkByType(NetworkTypePattern::Cellular()) @@ -458,12 +442,9 @@ // Add a non-visible network to the profile. const std::string profile = "/profile/profile1"; const std::string wifi_favorite_path = "/service/wifi_faviorite"; - service_test_->AddService(wifi_favorite_path, - "wifi_faviorite_guid", - "wifi_faviorite", - shill::kTypeWifi, - shill::kStateIdle, - false /* add_to_visible */); + service_test_->AddService(wifi_favorite_path, "wifi_faviorite_guid", + "wifi_faviorite", shill::kTypeWifi, + shill::kStateIdle, false /* add_to_visible */); profile_test_->AddProfile(profile, "" /* userhash */); EXPECT_TRUE(profile_test_->AddService(profile, wifi_favorite_path)); UpdateManagerProperties(); @@ -484,19 +465,15 @@ // Get all networks. NetworkStateHandler::NetworkStateList networks; - network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(), - false /* configured_only */, - false /* visible_only */, - 0 /* no limit */, - &networks); + network_state_handler_->GetNetworkListByType( + NetworkTypePattern::Default(), false /* configured_only */, + false /* visible_only */, 0 /* no limit */, &networks); EXPECT_EQ(kNumShillManagerClientStubImplServices + kNumTetherNetworks + 1, networks.size()); // Limit number of results, including only Tether networks. - network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(), - false /* configured_only */, - false /* visible_only */, - 2 /* limit */, - &networks); + network_state_handler_->GetNetworkListByType( + NetworkTypePattern::Default(), false /* configured_only */, + false /* visible_only */, 2 /* limit */, &networks); EXPECT_EQ(2u, networks.size()); // Limit number of results, including more than only Tether networks. network_state_handler_->GetNetworkListByType( @@ -509,29 +486,23 @@ false /* visible_only */, 0 /* no limit */, &networks); EXPECT_EQ(2u, networks.size()); // Get all wifi networks. - network_state_handler_->GetNetworkListByType(NetworkTypePattern::WiFi(), - false /* configured_only */, - false /* visible_only */, - 0 /* no limit */, - &networks); + network_state_handler_->GetNetworkListByType( + NetworkTypePattern::WiFi(), false /* configured_only */, + false /* visible_only */, 0 /* no limit */, &networks); EXPECT_EQ(3u, networks.size()); // Get visible networks. - network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(), - false /* configured_only */, - true /* visible_only */, - 0 /* no limit */, - &networks); + network_state_handler_->GetNetworkListByType( + NetworkTypePattern::Default(), false /* configured_only */, + true /* visible_only */, 0 /* no limit */, &networks); EXPECT_EQ(kNumShillManagerClientStubImplServices + kNumTetherNetworks, networks.size()); network_state_handler_->GetVisibleNetworkList(&networks); EXPECT_EQ(kNumShillManagerClientStubImplServices + kNumTetherNetworks, networks.size()); // Get configured (profile) networks. - network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(), - true /* configured_only */, - false /* visible_only */, - 0 /* no limit */, - &networks); + network_state_handler_->GetNetworkListByType( + NetworkTypePattern::Default(), true /* configured_only */, + false /* visible_only */, 0 /* no limit */, &networks); EXPECT_EQ(kNumTetherNetworks + 1u, networks.size()); } @@ -710,12 +681,12 @@ // Set up two additional visible networks. const std::string wifi3 = "/service/wifi3"; const std::string wifi4 = "/service/wifi4"; - service_test_->SetServiceProperties( - wifi3, "wifi3_guid", "wifi3", - shill::kTypeWifi, shill::kStateIdle, true /* visible */); - service_test_->SetServiceProperties( - wifi4, "wifi4_guid", "wifi4", - shill::kTypeWifi, shill::kStateIdle, true /* visible */); + service_test_->SetServiceProperties(wifi3, "wifi3_guid", "wifi3", + shill::kTypeWifi, shill::kStateIdle, + true /* visible */); + service_test_->SetServiceProperties(wifi4, "wifi4_guid", "wifi4", + shill::kTypeWifi, shill::kStateIdle, + true /* visible */); // Add the services to the Manager. Only notify when the second service is // added. manager_test_->AddManagerService(wifi3, false); @@ -736,12 +707,9 @@ // Add a non-visible network to the profile. const std::string profile = "/profile/profile1"; const std::string wifi_favorite_path = "/service/wifi_faviorite"; - service_test_->AddService(wifi_favorite_path, - "wifi_faviorite_guid", - "wifi_faviorite", - shill::kTypeWifi, - shill::kStateIdle, - false /* add_to_visible */); + service_test_->AddService(wifi_favorite_path, "wifi_faviorite_guid", + "wifi_faviorite", shill::kTypeWifi, + shill::kStateIdle, false /* add_to_visible */); base::RunLoop().RunUntilIdle(); EXPECT_EQ(kNumShillManagerClientStubImplServices + 1, test_observer_->network_count()); @@ -1601,7 +1569,7 @@ // Change a network state. base::Value connection_state_idle_value(shill::kStateIdle); service_test_->SetServiceProperty(eth1, shill::kStateProperty, - connection_state_idle_value); + connection_state_idle_value); base::RunLoop().RunUntilIdle(); EXPECT_EQ(shill::kStateIdle, test_observer_->NetworkConnectionStateForService(eth1)); @@ -1609,7 +1577,7 @@ // Confirm that changing the connection state to the same value does *not* // signal the observer. service_test_->SetServiceProperty(eth1, shill::kStateProperty, - connection_state_idle_value); + connection_state_idle_value); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, test_observer_->ConnectionStateChangesForService(eth1)); } @@ -1821,12 +1789,12 @@ TEST_F(NetworkStateHandlerTest, RequestUpdate) { // Request an update for kShillManagerClientStubDefaultWifi. EXPECT_EQ(1, test_observer_->PropertyUpdatesForService( - kShillManagerClientStubDefaultWifi)); + kShillManagerClientStubDefaultWifi)); network_state_handler_->RequestUpdateForNetwork( kShillManagerClientStubDefaultWifi); base::RunLoop().RunUntilIdle(); EXPECT_EQ(2, test_observer_->PropertyUpdatesForService( - kShillManagerClientStubDefaultWifi)); + kShillManagerClientStubDefaultWifi)); } TEST_F(NetworkStateHandlerTest, RequestScan) { @@ -1938,13 +1906,13 @@ TEST_F(NetworkStateHandlerTest, IPConfigChanged) { test_observer_->reset_updates(); EXPECT_EQ(0, test_observer_->PropertyUpdatesForDevice( - kShillManagerClientStubWifiDevice)); + kShillManagerClientStubWifiDevice)); EXPECT_EQ(0, test_observer_->PropertyUpdatesForService( - kShillManagerClientStubDefaultWifi)); + kShillManagerClientStubDefaultWifi)); // Change IPConfigs property. ShillIPConfigClient::TestInterface* ip_config_test = - DBusThreadManager::Get()->GetShillIPConfigClient()->GetTestInterface(); + ShillIPConfigClient::Get()->GetTestInterface(); const std::string kIPConfigPath = "test_ip_config"; base::DictionaryValue ip_config_properties; ip_config_test->AddIPConfig(kIPConfigPath, ip_config_properties); @@ -1958,9 +1926,9 @@ base::Value(kIPConfigPath)); UpdateManagerProperties(); EXPECT_EQ(1, test_observer_->PropertyUpdatesForDevice( - kShillManagerClientStubWifiDevice)); + kShillManagerClientStubWifiDevice)); EXPECT_EQ(1, test_observer_->PropertyUpdatesForService( - kShillManagerClientStubDefaultWifi)); + kShillManagerClientStubDefaultWifi)); } TEST_F(NetworkStateHandlerTest, UpdateGuid) {
diff --git a/chromeos/network/network_state_test_helper.cc b/chromeos/network/network_state_test_helper.cc index 8246d8d..f96e80d 100644 --- a/chromeos/network/network_state_test_helper.cc +++ b/chromeos/network/network_state_test_helper.cc
@@ -7,7 +7,7 @@ #include "base/bind.h" #include "base/json/json_reader.h" #include "base/run_loop.h" -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/network/network_state_handler.h" #include "chromeos/network/onc/onc_utils.h" #include "dbus/object_path.h" @@ -28,20 +28,14 @@ NetworkStateTestHelper::NetworkStateTestHelper( bool use_default_devices_and_services) : weak_ptr_factory_(this) { - if (!DBusThreadManager::IsInitialized()) { - DBusThreadManager::Initialize(); - dbus_thread_manager_initialized_ = true; + if (!ShillManagerClient::Get()) { + shill_clients::InitializeFakes(); + shill_clients_initialized_ = true; } - DBusThreadManager* dbus_thread_manager = DBusThreadManager::Get(); - - manager_test_ = - dbus_thread_manager->GetShillManagerClient()->GetTestInterface(); - profile_test_ = - dbus_thread_manager->GetShillProfileClient()->GetTestInterface(); - device_test_ = - dbus_thread_manager->GetShillDeviceClient()->GetTestInterface(); - service_test_ = - dbus_thread_manager->GetShillServiceClient()->GetTestInterface(); + manager_test_ = ShillManagerClient::Get()->GetTestInterface(); + profile_test_ = ShillProfileClient::Get()->GetTestInterface(); + device_test_ = ShillDeviceClient::Get()->GetTestInterface(); + service_test_ = ShillServiceClient::Get()->GetTestInterface(); profile_test_->AddProfile("shared_profile_path", std::string() /* shared profile */); @@ -56,8 +50,8 @@ NetworkStateTestHelper::~NetworkStateTestHelper() { ShutdownNetworkState(); - if (dbus_thread_manager_initialized_) - DBusThreadManager::Shutdown(); + if (shill_clients_initialized_) + shill_clients::Shutdown(); } void NetworkStateTestHelper::ShutdownNetworkState() { @@ -107,7 +101,7 @@ // |last_created_service_path| will be set before it is returned. In // error cases, ConfigureCallback() will not run, resulting in "" being // returned from this function. - DBusThreadManager::Get()->GetShillManagerClient()->ConfigureService( + ShillManagerClient::Get()->ConfigureService( *shill_json_dict, base::Bind(&NetworkStateTestHelper::ConfigureCallback, weak_ptr_factory_.GetWeakPtr()),
diff --git a/chromeos/network/network_state_test_helper.h b/chromeos/network/network_state_test_helper.h index 0036865..0f22c197 100644 --- a/chromeos/network/network_state_test_helper.h +++ b/chromeos/network/network_state_test_helper.h
@@ -78,7 +78,7 @@ private: void ConfigureCallback(const dbus::ObjectPath& result); - bool dbus_thread_manager_initialized_ = false; + bool shill_clients_initialized_ = false; std::string last_created_service_path_; ShillManagerClient::TestInterface* manager_test_;
diff --git a/chromeos/network/policy_applicator.cc b/chromeos/network/policy_applicator.cc index 0f98682..748cda1 100644 --- a/chromeos/network/policy_applicator.cc +++ b/chromeos/network/policy_applicator.cc
@@ -12,7 +12,6 @@ #include "base/location.h" #include "base/logging.h" #include "base/memory/ptr_util.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_profile_client.h" #include "chromeos/network/network_type_pattern.h" #include "chromeos/network/network_ui_data.h" @@ -69,7 +68,7 @@ } void PolicyApplicator::Run() { - DBusThreadManager::Get()->GetShillProfileClient()->GetProperties( + ShillProfileClient::Get()->GetProperties( dbus::ObjectPath(profile_.path), base::Bind(&PolicyApplicator::GetProfilePropertiesCallback, weak_ptr_factory_.GetWeakPtr()), @@ -110,15 +109,12 @@ continue; pending_get_entry_calls_.insert(entry); - DBusThreadManager::Get()->GetShillProfileClient()->GetEntry( - dbus::ObjectPath(profile_.path), - entry, + ShillProfileClient::Get()->GetEntry( + dbus::ObjectPath(profile_.path), entry, base::Bind(&PolicyApplicator::GetEntryCallback, - weak_ptr_factory_.GetWeakPtr(), - entry), + weak_ptr_factory_.GetWeakPtr(), entry), base::Bind(&PolicyApplicator::GetEntryError, - weak_ptr_factory_.GetWeakPtr(), - entry)); + weak_ptr_factory_.GetWeakPtr(), entry)); } if (pending_get_entry_calls_.empty()) { ApplyRemainingPolicies(); @@ -276,7 +272,7 @@ } void PolicyApplicator::DeleteEntry(const std::string& entry) { - DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry( + ShillProfileClient::Get()->DeleteEntry( dbus::ObjectPath(profile_.path), entry, base::DoNothing(), base::Bind(&LogErrorMessage, FROM_HERE)); }
diff --git a/chromeos/network/proxy/proxy_config_handler.cc b/chromeos/network/proxy/proxy_config_handler.cc index 71b73545..aeeff88 100644 --- a/chromeos/network/proxy/proxy_config_handler.cc +++ b/chromeos/network/proxy/proxy_config_handler.cc
@@ -11,7 +11,6 @@ #include "base/json/json_writer.h" #include "base/logging.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/network/network_handler_callbacks.h" #include "chromeos/network/network_profile.h" @@ -96,16 +95,13 @@ void SetProxyConfigForNetwork(const ProxyConfigDictionary& proxy_config, const NetworkState& network) { - chromeos::ShillServiceClient* shill_service_client = - DBusThreadManager::Get()->GetShillServiceClient(); - // The user's proxy setting is not stored in the Chrome preference yet. We // still rely on Shill storing it. ProxyPrefs::ProxyMode mode; if (!proxy_config.GetMode(&mode) || mode == ProxyPrefs::MODE_DIRECT) { // Return empty string for direct mode for portal check to work correctly. // TODO(pneubeck): Consider removing this legacy code. - shill_service_client->ClearProperty( + ShillServiceClient::Get()->ClearProperty( dbus::ObjectPath(network.path()), shill::kProxyConfigProperty, base::Bind(&NotifyNetworkStateHandler, network.path()), base::Bind(&network_handler::ShillErrorCallbackFunction, @@ -114,7 +110,7 @@ } else { std::string proxy_config_str; base::JSONWriter::Write(proxy_config.GetDictionary(), &proxy_config_str); - shill_service_client->SetProperty( + ShillServiceClient::Get()->SetProperty( dbus::ObjectPath(network.path()), shill::kProxyConfigProperty, base::Value(proxy_config_str), base::Bind(&NotifyNetworkStateHandler, network.path()),
diff --git a/chromeos/network/proxy/proxy_config_service_impl_unittest.cc b/chromeos/network/proxy/proxy_config_service_impl_unittest.cc index 646128a..ae0d0e7 100644 --- a/chromeos/network/proxy/proxy_config_service_impl_unittest.cc +++ b/chromeos/network/proxy/proxy_config_service_impl_unittest.cc
@@ -9,7 +9,7 @@ #include "base/test/scoped_task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/network/network_handler.h" #include "components/prefs/pref_service.h" #include "components/prefs/testing_pref_service.h" @@ -48,14 +48,14 @@ class ProxyConfigServiceImplTest : public testing::Test { void SetUp() override { - DBusThreadManager::Initialize(); + shill_clients::InitializeFakes(); chromeos::NetworkHandler::Initialize(); base::RunLoop().RunUntilIdle(); } void TearDown() override { chromeos::NetworkHandler::Shutdown(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } protected:
diff --git a/chromeos/network/proxy/ui_proxy_config_service_unittest.cc b/chromeos/network/proxy/ui_proxy_config_service_unittest.cc index 4339901..c6675a0a 100644 --- a/chromeos/network/proxy/ui_proxy_config_service_unittest.cc +++ b/chromeos/network/proxy/ui_proxy_config_service_unittest.cc
@@ -13,7 +13,7 @@ #include "base/strings/string_util.h" #include "base/test/scoped_task_environment.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/dbus/shill/shill_manager_client.h" #include "chromeos/network/network_handler.h" #include "chromeos/network/onc/onc_utils.h" @@ -107,7 +107,7 @@ } void SetUp() override { - DBusThreadManager::Initialize(); + shill_clients::InitializeFakes(); NetworkHandler::Initialize(); ConfigureService(kTestUserWifiConfig); ConfigureService(kTestSharedWifiConfig); @@ -116,7 +116,7 @@ void TearDown() override { NetworkHandler::Shutdown(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } ~UIProxyConfigServiceTest() override = default; @@ -126,7 +126,7 @@ base::DictionaryValue::From( onc::ReadDictionaryFromJson(shill_json_string)); ASSERT_TRUE(shill_json_dict); - DBusThreadManager::Get()->GetShillManagerClient()->ConfigureService( + ShillManagerClient::Get()->ConfigureService( *shill_json_dict, base::DoNothing(), base::Bind([](const std::string& name, const std::string& msg) {})); base::RunLoop().RunUntilIdle();
diff --git a/chromeos/network/shill_property_handler.cc b/chromeos/network/shill_property_handler.cc index 4478a85..208db9f 100644 --- a/chromeos/network/shill_property_handler.cc +++ b/chromeos/network/shill_property_handler.cc
@@ -15,7 +15,6 @@ #include "base/macros.h" #include "base/strings/string_util.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill/shill_device_client.h" #include "chromeos/dbus/shill/shill_ipconfig_client.h" #include "chromeos/dbus/shill/shill_manager_client.h" @@ -63,14 +62,12 @@ : type_(type), path_(path), handler_(handler) { if (type_ == ManagedState::MANAGED_TYPE_NETWORK) { DVLOG(2) << "ShillPropertyObserver: Network: " << path; - DBusThreadManager::Get() - ->GetShillServiceClient() - ->AddPropertyChangedObserver(dbus::ObjectPath(path_), this); + ShillServiceClient::Get()->AddPropertyChangedObserver( + dbus::ObjectPath(path_), this); } else if (type_ == ManagedState::MANAGED_TYPE_DEVICE) { DVLOG(2) << "ShillPropertyObserver: Device: " << path; - DBusThreadManager::Get() - ->GetShillDeviceClient() - ->AddPropertyChangedObserver(dbus::ObjectPath(path_), this); + ShillDeviceClient::Get()->AddPropertyChangedObserver( + dbus::ObjectPath(path_), this); } else { NOTREACHED(); } @@ -78,13 +75,11 @@ ~ShillPropertyObserver() override { if (type_ == ManagedState::MANAGED_TYPE_NETWORK) { - DBusThreadManager::Get() - ->GetShillServiceClient() - ->RemovePropertyChangedObserver(dbus::ObjectPath(path_), this); + ShillServiceClient::Get()->RemovePropertyChangedObserver( + dbus::ObjectPath(path_), this); } else if (type_ == ManagedState::MANAGED_TYPE_DEVICE) { - DBusThreadManager::Get() - ->GetShillDeviceClient() - ->RemovePropertyChangedObserver(dbus::ObjectPath(path_), this); + ShillDeviceClient::Get()->RemovePropertyChangedObserver( + dbus::ObjectPath(path_), this); } else { NOTREACHED(); } @@ -108,12 +103,11 @@ // ShillPropertyHandler ShillPropertyHandler::ShillPropertyHandler(Listener* listener) - : listener_(listener), - shill_manager_(DBusThreadManager::Get()->GetShillManagerClient()) {} + : listener_(listener), shill_manager_(ShillManagerClient::Get()) {} ShillPropertyHandler::~ShillPropertyHandler() { // Delete network service observers. - CHECK(shill_manager_ == DBusThreadManager::Get()->GetShillManagerClient()); + CHECK(shill_manager_ == ShillManagerClient::Get()); shill_manager_->RemovePropertyChangedObserver(this); } @@ -278,12 +272,12 @@ << " For: " << path; pending_updates_[type].insert(path); if (type == ManagedState::MANAGED_TYPE_NETWORK) { - DBusThreadManager::Get()->GetShillServiceClient()->GetProperties( + ShillServiceClient::Get()->GetProperties( dbus::ObjectPath(path), base::Bind(&ShillPropertyHandler::GetPropertiesCallback, AsWeakPtr(), type, path)); } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { - DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties( + ShillDeviceClient::Get()->GetProperties( dbus::ObjectPath(path), base::Bind(&ShillPropertyHandler::GetPropertiesCallback, AsWeakPtr(), type, path)); @@ -564,7 +558,7 @@ NET_LOG(ERROR) << "Invalid IPConfig: " << path; return; } - DBusThreadManager::Get()->GetShillIPConfigClient()->GetProperties( + ShillIPConfigClient::Get()->GetProperties( dbus::ObjectPath(ip_config_path), base::Bind(&ShillPropertyHandler::GetIPConfigCallback, AsWeakPtr(), type, path, ip_config_path));
diff --git a/chromeos/network/shill_property_handler_unittest.cc b/chromeos/network/shill_property_handler_unittest.cc index d4f77717..78b5fce 100644 --- a/chromeos/network/shill_property_handler_unittest.cc +++ b/chromeos/network/shill_property_handler_unittest.cc
@@ -17,7 +17,7 @@ #include "base/run_loop.h" #include "base/test/scoped_task_environment.h" #include "base/values.h" -#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill/shill_clients.h" #include "chromeos/dbus/shill/shill_device_client.h" #include "chromeos/dbus/shill/shill_ipconfig_client.h" #include "chromeos/dbus/shill/shill_manager_client.h" @@ -168,21 +168,16 @@ ~ShillPropertyHandlerTest() override = default; void SetUp() override { - // Initialize DBusThreadManager with a stub implementation. - DBusThreadManager::Initialize(); + shill_clients::InitializeFakes(); // Get the test interface for manager / device / service and clear the // default stub properties. - manager_test_ = - DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface(); + manager_test_ = ShillManagerClient::Get()->GetTestInterface(); ASSERT_TRUE(manager_test_); - device_test_ = - DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface(); + device_test_ = ShillDeviceClient::Get()->GetTestInterface(); ASSERT_TRUE(device_test_); - service_test_ = - DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); + service_test_ = ShillServiceClient::Get()->GetTestInterface(); ASSERT_TRUE(service_test_); - profile_test_ = - DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface(); + profile_test_ = ShillProfileClient::Get()->GetTestInterface(); ASSERT_TRUE(profile_test_); SetupShillPropertyHandler(); base::RunLoop().RunUntilIdle(); @@ -191,7 +186,7 @@ void TearDown() override { shill_property_handler_.reset(); listener_.reset(); - DBusThreadManager::Shutdown(); + shill_clients::Shutdown(); } void AddDevice(const std::string& type, const std::string& id) { @@ -328,7 +323,7 @@ // Enable the technology. listener_->reset_list_updates(); - DBusThreadManager::Get()->GetShillManagerClient()->EnableTechnology( + ShillManagerClient::Get()->EnableTechnology( shill::kTypeWifi, base::DoNothing(), base::Bind(&ErrorCallbackFunction)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, listener_->technology_list_updates()); @@ -380,7 +375,7 @@ shill::kServiceCompleteListProperty)[kTestServicePath]); // Change a property. base::Value scan_interval(3); - DBusThreadManager::Get()->GetShillServiceClient()->SetProperty( + ShillServiceClient::Get()->SetProperty( dbus::ObjectPath(kTestServicePath), shill::kScanIntervalProperty, scan_interval, base::DoNothing(), base::Bind(&ErrorCallbackFunction)); base::RunLoop().RunUntilIdle(); @@ -391,7 +386,7 @@ // Set the state of the service to Connected. This will trigger a service list // update. listener_->reset_list_updates(); - DBusThreadManager::Get()->GetShillServiceClient()->SetProperty( + ShillServiceClient::Get()->SetProperty( dbus::ObjectPath(kTestServicePath), shill::kStateProperty, base::Value(shill::kStateReady), base::DoNothing(), base::Bind(&ErrorCallbackFunction)); @@ -415,23 +410,23 @@ const std::string kTestIPConfigPath("test_ip_config_path"); base::Value ip_address("192.168.1.1"); - DBusThreadManager::Get()->GetShillIPConfigClient()->SetProperty( - dbus::ObjectPath(kTestIPConfigPath), shill::kAddressProperty, ip_address, - EmptyVoidDBusMethodCallback()); + ShillIPConfigClient::Get()->SetProperty(dbus::ObjectPath(kTestIPConfigPath), + shill::kAddressProperty, ip_address, + EmptyVoidDBusMethodCallback()); base::ListValue dns_servers; dns_servers.AppendString("192.168.1.100"); dns_servers.AppendString("192.168.1.101"); - DBusThreadManager::Get()->GetShillIPConfigClient()->SetProperty( + ShillIPConfigClient::Get()->SetProperty( dbus::ObjectPath(kTestIPConfigPath), shill::kNameServersProperty, dns_servers, EmptyVoidDBusMethodCallback()); base::Value prefixlen(8); - DBusThreadManager::Get()->GetShillIPConfigClient()->SetProperty( - dbus::ObjectPath(kTestIPConfigPath), shill::kPrefixlenProperty, prefixlen, - EmptyVoidDBusMethodCallback()); + ShillIPConfigClient::Get()->SetProperty(dbus::ObjectPath(kTestIPConfigPath), + shill::kPrefixlenProperty, prefixlen, + EmptyVoidDBusMethodCallback()); base::Value gateway("192.0.0.1"); - DBusThreadManager::Get()->GetShillIPConfigClient()->SetProperty( - dbus::ObjectPath(kTestIPConfigPath), shill::kGatewayProperty, gateway, - EmptyVoidDBusMethodCallback()); + ShillIPConfigClient::Get()->SetProperty(dbus::ObjectPath(kTestIPConfigPath), + shill::kGatewayProperty, gateway, + EmptyVoidDBusMethodCallback()); base::RunLoop().RunUntilIdle(); // Add a service with an empty ipconfig and then update @@ -442,7 +437,7 @@ // This is the initial property update. EXPECT_EQ(1, listener_->initial_property_updates( shill::kServiceCompleteListProperty)[kTestServicePath1]); - DBusThreadManager::Get()->GetShillServiceClient()->SetProperty( + ShillServiceClient::Get()->SetProperty( dbus::ObjectPath(kTestServicePath1), shill::kIPConfigProperty, base::Value(kTestIPConfigPath), base::DoNothing(), base::Bind(&ErrorCallbackFunction));
diff --git a/components/README b/components/README deleted file mode 100644 index a5053b2c..0000000 --- a/components/README +++ /dev/null
@@ -1,56 +0,0 @@ -This directory is for features that are intended for reuse. Example use cases: -- features that are shared by Chrome on iOS and other Chrome platforms (since - the iOS port doesn't use src/chrome) -- features that are shared between multiple embedders of content (e.g., Android - WebView and Chrome) -- features that are shared between Blink and the browser process - * Note: It is also possible to place code shared between Blink and the - browser process into //third_party/blink/common. The distinction comes - down to (a) whether Blink is the owner of the code in question or a consumer - of it and (b) whether the code in question is shared by Chrome on iOS as - well. If the code is conceptually its own cross-process feature with Blink - as a consumer, then //components can make sense. If it's conceptually - Blink code, then third_party/blink/common likely makes more sense. (In the - so-far hypothetical case where it's conceptually Blink code that is shared - by iOS, raise the question on chromium-dev@, where the right folks will see - it). - -In general, if some code is used by a directory "foo" and things above "foo" in -the dependency tree, the code should probably live in "foo". - -By default, components can depend only on the lower layers of the Chromium -codebase (e.g. base/, net/, etc.). Individual components may additionally allow -dependencies on the content API and IPC; however, if such a component is used -by Chrome for iOS (which does not use the content API or IPC), the component -will have to be in the form of a layered component -(http://www.chromium.org/developers/design-documents/layered-components-design). - -Components that have bits of code that need to live in different -processes (e.g. some code in the browser process, some in the renderer -process, etc.) should separate the code into different subdirectories. -Hence for a component named 'foo' you might end up with a structure -like the following (assuming that foo is not used by iOS and thus does not -need to be a layered component): - -components/foo - DEPS, OWNERS, foo.gypi -components/foo/browser - code that needs the browser process -components/foo/common - for e.g. IPC constants and such -components/foo/renderer - code that needs renderer process - -These subdirectories should have DEPS files with the relevant -restrictions in place, i.e. only components/*/browser should -be allowed to #include from content/public/browser. - -Note that there may also be an 'android' subdir, with a Java source -code structure underneath it where the package name is -org.chromium.components.foo, and with subdirs after 'foo' -to illustrate process, e.g. 'browser' or 'renderer': - -components/foo/android/OWNERS, DEPS -components/foo/android/java/src/org/chromium/components/foo/browser/ -components/foo/android/javatests/src/org/chromium/components/foo/browser/ - -Code in a component should be placed in a namespace corresponding to -the name of the component; e.g. for a component living in -//components/foo, code in that component should be in the foo:: -namespace.
diff --git a/components/README.md b/components/README.md new file mode 100644 index 0000000..ea3b0eb --- /dev/null +++ b/components/README.md
@@ -0,0 +1,104 @@ +# About //components + +This directory is meant to house features or subsystems that are used in more +than one part of the Chromium codebase. + +## Example use cases: + + * Features that are shared by Chrome on iOS (`//ios/chrome`) and Chrome on + other platforms (`//chrome`). + * Note: `//ios` doesn't depend on `//chrome`. + * Features that are shared between multiple embedders of content. For example, + `//chrome` and `//android_webview`. + * Features that are shared between Blink and the browser process. + * Note: It is also possible to place code shared between Blink and the + browser process into `//third_party/blink/common`. The distinction comes + down to (a) whether Blink is the owner of the code in question or a + consumer of it and (b) whether the code in question is shared by Chrome + on iOS as well. If the code is conceptually its own cross-process + feature with Blink as a consumer, then `//components` can make sense. If + it's conceptually Blink code, then `//third_party/blink/common` likely + makes more sense. (In the so-far hypothetical case where it's + conceptually Blink code that is shared by iOS, raise the question on + chromium-dev@, where the right folks will see it). + +## Guidelines for adding a new component + + * You will be added to an OWNERS file under `//components/{your component}` + and be responsible for maintaining your addition. + * A `//components/OWNER` must approve of the location of your code. + * Code must be needed in at least 2 places in Chrome that don't have a "higher + layered" directory that could facilitate sharing (e.g. `//content/common`, + `//chrome/utility`, etc.). + +## Dependencies of a component + +Components **cannot** depend on the higher layers of the Chromium codebase: + + * `//android_webview` + * `//chrome` + * `//chromecast` + * `//headless` + * `//ios/chrome` + * `//content/shell` + +Components **can** depend on the lower layers of the Chromium codebase: + + * `//base` + * `//gpu` + * `//mojo` + * `//net` + * `//ui` + +Components **can** depend on each other. This must be made explicit in the +`DEPS` file of the component. + +Components **can** depend on `//content/public` and `//ipc`. This must be made +explicit in the `DEPS` file of the component. If such a component is used by +Chrome for iOS (which does not use content or IPC), the component will have to +be in the form of a [layered +component](http://www.chromium.org/developers/design-documents/layered-components-design). + +`//chrome`, `//ios/chrome`, `//content` and `//ios/web` **can** depend on +individual components. The dependency might have to be made explicit in the +`DEPS` file of the higher layer (e.g. in `//content/browser/DEPS`). Circular +dependencies are not allowed: if `//content` depends on a component, then that +component cannot depend on `//content/public`, directly or indirectly. + +## Structure of a component + +As mentioned above, components that depend on `//content/public` or `//ipc` +might have to be in the form of a [layered +component](http://www.chromium.org/developers/design-documents/layered-components-design). + +Components that have bits of code that need to live in different processes (e.g. +some code in the browser process, some in the renderer process, etc.) should +separate the code into different subdirectories. Hence for a component named +'foo' you might end up with a structure like the following (assuming that foo is +not used by iOS and thus does not need to be a layered component): + + * `components/foo` - DEPS, OWNERS, BUILD.gn + * `components/foo/browser` - code that needs the browser process + * `components/foo/common` - for e.g. Mojo interfaces and such + * `components/foo/renderer` - code that needs renderer process + +These subdirectories should have DEPS files with the relevant restrictions in +place, i.e. only `components/foo/browser` should be allowed to #include from +`content/public/browser`. + +Note that there may also be an `android` subdir, with a Java source code +structure underneath it where the package name is org.chromium.components.foo, +and with subdirs after 'foo' to illustrate process, e.g. 'browser' or +'renderer': + + * `components/foo/android/OWNERS`, `DEPS` + * `components/foo/android/java/src/org/chromium/components/foo/browser/` + * `components/foo/android/javatests/src/org/chromium/components/foo/browser/` + +Code in a component should be placed in a namespace corresponding to the name of +the component; e.g. for a component living in `//components/foo`, code in that +component should be in the `foo::` namespace. + +## How does this differ from //base/util? + +See the explanation in [//base/util/README.md](https://chromium.googlesource.com/chromium/src/+/HEAD/base/util/README.md#how-does-this-differ-from-components).
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 406d655..d8d463f 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -487,7 +487,6 @@ testonly = true sources = [ "address_combobox_model_unittest.cc", - "address_contact_form_label_formatter_unittest.cc", "address_email_form_label_formatter_unittest.cc", "address_field_unittest.cc", "address_form_label_formatter_unittest.cc",
diff --git a/components/autofill/core/browser/label_formatter.cc b/components/autofill/core/browser/label_formatter.cc index 263df91..689e250 100644 --- a/components/autofill/core/browser/label_formatter.cc +++ b/components/autofill/core/browser/label_formatter.cc
@@ -76,8 +76,7 @@ switch (groups) { case kName | kAddress | kEmail | kPhone: - return std::make_unique<AddressContactFormLabelFormatter>( - app_locale, focused_field_type, field_types); + return nullptr; case kName | kAddress | kPhone: return std::make_unique<AddressPhoneFormLabelFormatter>( app_locale, focused_field_type, field_types);
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 657e7864..7c1dab2 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -36,6 +36,8 @@ #include "components/autofill/core/browser/country_data.h" #include "components/autofill/core/browser/country_names.h" #include "components/autofill/core/browser/form_structure.h" +#include "components/autofill/core/browser/label_formatter.h" +#include "components/autofill/core/browser/label_formatter_utils.h" #include "components/autofill/core/browser/personal_data_manager_observer.h" #include "components/autofill/core/browser/phone_number.h" #include "components/autofill/core/browser/phone_number_i18n.h" @@ -1160,20 +1162,23 @@ matched_profiles, suggestions, &unique_matched_profiles); + std::unique_ptr<LabelFormatter> formatter = + base::FeatureList::IsEnabled( + autofill::features::kAutofillUseImprovedLabelDisambiguation) + ? LabelFormatter::Create(app_locale_, type.GetStorableType(), + field_types) + : nullptr; + // Generate disambiguating labels based on the list of matches. std::vector<base::string16> labels; - AutofillProfile::CreateInferredLabels(unique_matched_profiles, &field_types, - type.GetStorableType(), 1, app_locale_, - &labels); - DCHECK_EQ(unique_suggestions.size(), labels.size()); - for (size_t i = 0; i < labels.size(); i++) { - // A suggestion's label has one line of disambiguating information to show - // to the user. However, when the two-line suggestion display experiment is - // enabled on desktop, label is replaced by additional label. - unique_suggestions[i].label = labels[i]; - unique_suggestions[i].additional_label = labels[i]; + if (formatter) { + labels = formatter->GetLabels(unique_matched_profiles); + } else { + AutofillProfile::CreateInferredLabels(unique_matched_profiles, &field_types, + type.GetStorableType(), 1, + app_locale_, &labels); } - + suggestion_selection::PrepareSuggestions(labels, &unique_suggestions); return unique_suggestions; }
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc index e362a13..f761fcc 100644 --- a/components/autofill/core/browser/personal_data_manager_unittest.cc +++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -38,6 +38,7 @@ #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_structure.h" +#include "components/autofill/core/browser/label_formatter_test_utils.h" #include "components/autofill/core/browser/personal_data_manager_observer.h" #include "components/autofill/core/browser/suggestion_selection.h" #include "components/autofill/core/browser/sync_utils.h" @@ -2547,6 +2548,116 @@ EXPECT_EQ(0U, personal_data_->GetProfiles().size()); } +TEST_F(PersonalDataManagerTest, + GetProfileSuggestionsWithImprovedLabelDisambiguationForContactForm) { + AutofillProfile profile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "", + "401 Merrimack St", "", "Lowell", "MA", "01852", "US", + "19786744120"); + AddProfileToPersonalDataManager(profile); + + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillUseImprovedLabelDisambiguation}, + /*disabled_features=*/{}); + + EXPECT_THAT( + personal_data_->GetProfileSuggestions( + AutofillType(NAME_FIRST), base::string16(), false, + std::vector<ServerFieldType>{NAME_FIRST, NAME_LAST, EMAIL_ADDRESS, + PHONE_HOME_WHOLE_NUMBER}), + ElementsAre(AllOf( + testing::Field( + &Suggestion::label, + FormatExpectedLabel("(978) 674-4120", "hoa.pham@comcast.net")), + testing::Field( + &Suggestion::additional_label, + FormatExpectedLabel("(978) 674-4120", "hoa.pham@comcast.net"))))); +} + +TEST_F(PersonalDataManagerTest, + GetProfileSuggestionsWithImprovedLabelDisambiguationForAddressForm) { + AutofillProfile profile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "", + "401 Merrimack St", "", "Lowell", "MA", "01852", "US", + "19786744120"); + AddProfileToPersonalDataManager(profile); + + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillUseImprovedLabelDisambiguation}, + /*disabled_features=*/{}); + + EXPECT_THAT(personal_data_->GetProfileSuggestions( + AutofillType(NAME_FULL), base::string16(), false, + std::vector<ServerFieldType>{ + NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_CITY, + ADDRESS_HOME_STATE, ADDRESS_HOME_ZIP}), + ElementsAre(AllOf( + testing::Field( + &Suggestion::label, + base::ASCIIToUTF16("401 Merrimack St, Lowell, MA 01852")), + testing::Field(&Suggestion::additional_label, + base::ASCIIToUTF16( + "401 Merrimack St, Lowell, MA 01852"))))); +} + +TEST_F( + PersonalDataManagerTest, + GetProfileSuggestionsWithImprovedLabelDisambiguationForAddressPhoneForm) { + AutofillProfile profile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "", + "401 Merrimack St", "", "Lowell", "MA", "01852", "US", + "19786744120"); + AddProfileToPersonalDataManager(profile); + + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillUseImprovedLabelDisambiguation}, + /*disabled_features=*/{}); + + EXPECT_THAT( + personal_data_->GetProfileSuggestions( + AutofillType(NAME_FULL), base::string16(), false, + std::vector<ServerFieldType>{NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, + PHONE_HOME_WHOLE_NUMBER}), + ElementsAre(AllOf( + testing::Field( + &Suggestion::label, + FormatExpectedLabel("(978) 674-4120", "401 Merrimack St")), + testing::Field( + &Suggestion::additional_label, + FormatExpectedLabel("(978) 674-4120", "401 Merrimack St"))))); +} + +TEST_F( + PersonalDataManagerTest, + GetProfileSuggestionsWithImprovedLabelDisambiguationForAddressEmailForm) { + AutofillProfile profile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "", + "401 Merrimack St", "", "Lowell", "MA", "01852", "US", + "19786744120"); + AddProfileToPersonalDataManager(profile); + + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillUseImprovedLabelDisambiguation}, + /*disabled_features=*/{}); + + EXPECT_THAT( + personal_data_->GetProfileSuggestions( + AutofillType(NAME_FULL), base::string16(), false, + std::vector<ServerFieldType>{NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, + EMAIL_ADDRESS}), + ElementsAre(AllOf( + testing::Field( + &Suggestion::label, + FormatExpectedLabel("401 Merrimack St", "hoa.pham@comcast.net")), + testing::Field(&Suggestion::additional_label, + FormatExpectedLabel("401 Merrimack St", + "hoa.pham@comcast.net"))))); +} + TEST_F(PersonalDataManagerTest, IsKnownCard_MatchesMaskedServerCard) { // Add a masked server card. std::vector<CreditCard> server_cards;
diff --git a/components/autofill/core/browser/suggestion_selection.cc b/components/autofill/core/browser/suggestion_selection.cc index 516899d..10d93bd 100644 --- a/components/autofill/core/browser/suggestion_selection.cc +++ b/components/autofill/core/browser/suggestion_selection.cc
@@ -233,5 +233,15 @@ num_profiles_supressed); } +void PrepareSuggestions(const std::vector<base::string16>& labels, + std::vector<Suggestion>* suggestions) { + DCHECK_EQ(suggestions->size(), labels.size()); + + for (size_t i = 0; i < labels.size(); ++i) { + (*suggestions)[i].additional_label = base::string16(labels[i]); + (*suggestions)[i].label = base::string16(labels[i]); + } +} + } // namespace suggestion_selection } // namespace autofill
diff --git a/components/autofill/core/browser/suggestion_selection.h b/components/autofill/core/browser/suggestion_selection.h index 0e6909e..067538b 100644 --- a/components/autofill/core/browser/suggestion_selection.h +++ b/components/autofill/core/browser/suggestion_selection.h
@@ -59,6 +59,12 @@ base::Time min_last_used, std::vector<AutofillProfile*>* profiles); +// Prepares a collection of Suggestions to show to the user. Adds |labels| to +// their corresponding |suggestions|. A label corresponds to the suggestion with +// the same index. +void PrepareSuggestions(const std::vector<base::string16>& labels, + std::vector<Suggestion>* suggestions); + } // namespace suggestion_selection } // namespace autofill
diff --git a/components/country_codes/OWNERS b/components/country_codes/OWNERS index 76dd81a..fc3fe26 100644 --- a/components/country_codes/OWNERS +++ b/components/country_codes/OWNERS
@@ -1,5 +1,4 @@ jdonnelly@chromium.org -scottchen@chromium.org pkasting@chromium.org # COMPONENT: Internals>Core
diff --git a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc b/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc index 67db6a6..5006226 100644 --- a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc +++ b/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
@@ -5,6 +5,7 @@ #include "components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h" #include "base/bind.h" +#include "base/metrics/histogram_macros.h" #include "components/data_reduction_proxy/content/common/header_util.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" @@ -20,6 +21,17 @@ namespace data_reduction_proxy { +namespace { +void RecordQuicProxyStatus(const net::ProxyServer& proxy_server) { + if (proxy_server.is_https() || proxy_server.is_quic()) { + RecordQuicProxyStatus(IsQuicProxy(proxy_server) + ? QUIC_PROXY_STATUS_AVAILABLE + : QUIC_PROXY_NOT_SUPPORTED); + } +} + +} // namespace + DataReductionProxyURLLoaderThrottle::DataReductionProxyURLLoaderThrottle( const net::HttpRequestHeaders& post_cache_headers, DataReductionProxyThrottleManager* manager) @@ -78,6 +90,7 @@ before_will_process_response_received_ = true; MaybeRetry(proxy_server, response_head.headers.get(), net::OK, defer); + RecordQuicProxyStatus(proxy_server); } void DataReductionProxyURLLoaderThrottle::MaybeRetry(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc index 1ce2d3f..c382847 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc
@@ -57,8 +57,6 @@ : data_reduction_proxy_io_data_(data_reduction_proxy_io_data), data_use_ascriber_(data_use_ascriber) { DCHECK(data_reduction_proxy_io_data_); - if (!data_reduction_proxy::params::IsDataSaverSiteBreakdownUsingPLMEnabled()) - data_use_ascriber_->AddObserver(this); } DataReductionProxyDataUseObserver::~DataReductionProxyDataUseObserver() {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc index 367c0b73..99a7bd7 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc
@@ -15,6 +15,7 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" #include "net/base/host_port_pair.h" @@ -26,12 +27,6 @@ namespace data_reduction_proxy { -namespace { - -static const char kDataReductionCoreProxy[] = "proxy.googlezip.net"; - -} // namespace - DataReductionProxyDelegate::DataReductionProxyDelegate( DataReductionProxyConfig* config, const DataReductionProxyConfigurator* configurator, @@ -204,18 +199,7 @@ bool DataReductionProxyDelegate::SupportsQUIC( const net::ProxyServer& proxy_server) const { DCHECK(thread_checker_.CalledOnValidThread()); - // Enable QUIC for whitelisted proxies. - return params::IsQuicEnabledForNonCoreProxies() || - proxy_server == - net::ProxyServer(net::ProxyServer::SCHEME_HTTPS, - net::HostPortPair(kDataReductionCoreProxy, 443)); -} - -void DataReductionProxyDelegate::RecordQuicProxyStatus( - QuicProxyStatus status) const { - DCHECK(thread_checker_.CalledOnValidThread()); - UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.Quic.ProxyStatus", status, - QUIC_PROXY_STATUS_BOUNDARY); + return IsQuicProxy(proxy_server); } } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h index 14ba5fa..8f5e0c4 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h
@@ -56,20 +56,7 @@ // Returns true if |proxy_server| supports QUIC. virtual bool SupportsQUIC(const net::ProxyServer& proxy_server) const; - // Availability status of data reduction QUIC proxy. - // Protected so that the enum values are accessible for testing. - enum QuicProxyStatus { - QUIC_PROXY_STATUS_AVAILABLE, - QUIC_PROXY_NOT_SUPPORTED, - QUIC_PROXY_STATUS_MARKED_AS_BROKEN, - QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL, - QUIC_PROXY_STATUS_BOUNDARY - }; - private: - // Records the availability status of data reduction proxy. - void RecordQuicProxyStatus(QuicProxyStatus status) const; - // Checks if the first proxy server in |result| supports QUIC and if so // adds an alternative proxy configuration to |result|. void GetAlternativeProxy(const GURL& url,
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc index fc1049e..c38b9c9 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
@@ -33,6 +33,7 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers_test_utils.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" @@ -104,27 +105,19 @@ if (expect_alternative_proxy_server && !broken) { histogram_tester.ExpectUniqueSample( "DataReductionProxy.Quic.ProxyStatus", - TestDataReductionProxyDelegate::QuicProxyStatus:: - QUIC_PROXY_STATUS_AVAILABLE, - 1); + QuicProxyStatus::QUIC_PROXY_STATUS_AVAILABLE, 1); } else if (!supports_quic && !broken) { histogram_tester.ExpectUniqueSample( "DataReductionProxy.Quic.ProxyStatus", - TestDataReductionProxyDelegate::QuicProxyStatus:: - QUIC_PROXY_NOT_SUPPORTED, - 1); + QuicProxyStatus::QUIC_PROXY_NOT_SUPPORTED, 1); } else { ASSERT_TRUE(broken); histogram_tester.ExpectUniqueSample( "DataReductionProxy.Quic.ProxyStatus", - TestDataReductionProxyDelegate::QuicProxyStatus:: - QUIC_PROXY_STATUS_MARKED_AS_BROKEN, - 1); + QuicProxyStatus::QUIC_PROXY_STATUS_MARKED_AS_BROKEN, 1); } } - using DataReductionProxyDelegate::QuicProxyStatus; - private: const bool proxy_supports_quic_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc index fcfad73..67a939a 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
@@ -575,8 +575,7 @@ request), request.traffic_annotation().unique_id_hash_code); - if (params::IsDataSaverSiteBreakdownUsingPLMEnabled() && - data_reduction_proxy_io_data_ && + if (data_reduction_proxy_io_data_ && data_reduction_proxy_io_data_->resource_type_provider() && data_reduction_proxy_io_data_->resource_type_provider() ->IsNonContentInitiatedRequest(request)) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc index 394055d..82a6bfa 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -1999,10 +1999,6 @@ "Via: 1.1 Chrome-Compression-Proxy\r\n" "\r\n"; - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - data_reduction_proxy::features:: - kDataSaverSiteBreakdownUsingPageLoadMetrics); Init(USE_INSECURE_PROXY); EnableDataUsageReporting(); auto test_resource_type_provider =
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.cc index 6ffe2d4..4bdb409 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.cc
@@ -27,6 +27,8 @@ namespace { +static const char kDataReductionCoreProxy[] = "proxy.googlezip.net"; + // Returns the Data Reduction Proxy servers in |proxy_type_info| that should be // marked bad according to |data_reduction_proxy_info|. std::vector<net::ProxyServer> GetProxiesToMarkBad( @@ -293,4 +295,17 @@ return true; } +bool IsQuicProxy(const net::ProxyServer& proxy_server) { + // Enable QUIC for whitelisted proxies. + return params::IsQuicEnabledForNonCoreProxies() || + proxy_server == + net::ProxyServer(net::ProxyServer::SCHEME_HTTPS, + net::HostPortPair(kDataReductionCoreProxy, 443)); +} + +void RecordQuicProxyStatus(QuicProxyStatus status) { + UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.Quic.ProxyStatus", status, + QUIC_PROXY_STATUS_BOUNDARY); +} + } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h index d87153bb..b3ba446 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h
@@ -15,6 +15,15 @@ struct DataReductionProxyTypeInfo; +// Availability status of data reduction QUIC proxy. +enum QuicProxyStatus { + QUIC_PROXY_STATUS_AVAILABLE, + QUIC_PROXY_NOT_SUPPORTED, + QUIC_PROXY_STATUS_MARKED_AS_BROKEN, + QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL, + QUIC_PROXY_STATUS_BOUNDARY +}; + // Records a data reduction proxy bypass event as a "BlockType" if // |bypass_all| is true and as a "BypassType" otherwise. Records the event as // "Primary" if |is_primary| is true and "Fallback" otherwise. @@ -110,6 +119,11 @@ base::TimeTicks t, base::TimeDelta* retry_delay); +// Returns true if the proxy supports QUIC. +bool IsQuicProxy(const net::ProxyServer& proxy_server); + +void RecordQuicProxyStatus(QuicProxyStatus status); + } // namespace data_reduction_proxy #endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_BYPASS_PROTOCOL_H_
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc index 5762b9f9..87d7321 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc
@@ -31,12 +31,6 @@ const base::Feature kDogfood{"DataReductionProxyDogfood", base::FEATURE_DISABLED_BY_DEFAULT}; -// Enables recording of the site-breakdown metrics using the page load metrics -// harness, and disables the observer for data use ascriber. -const base::Feature kDataSaverSiteBreakdownUsingPageLoadMetrics{ - "DataSaverSiteBreakdownUsingPageLoadMetrics", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Enables data reduction proxy when network service is enabled. const base::Feature kDataReductionProxyEnabledWithNetworkService{ "DataReductionProxyEnabledWithNetworkService",
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.h index 830d096..3212c6f2 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.h +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.h
@@ -13,7 +13,6 @@ extern const base::Feature kDataReductionProxyDecidesTransform; extern const base::Feature kDataReductionProxyLowMemoryDevicePromo; extern const base::Feature kDogfood; -extern const base::Feature kDataSaverSiteBreakdownUsingPageLoadMetrics; extern const base::Feature kDataReductionProxyEnabledWithNetworkService; extern const base::Feature kDataSaverUseOnDeviceSafeBrowsing;
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc index a13dd24..c309efe 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
@@ -362,12 +362,6 @@ return GURL(secure_proxy_check_url); } -bool IsDataSaverSiteBreakdownUsingPLMEnabled() { - return base::FeatureList::IsEnabled( - data_reduction_proxy::features:: - kDataSaverSiteBreakdownUsingPageLoadMetrics); -} - bool IsEnabledWithNetworkService() { return base::FeatureList::IsEnabled( data_reduction_proxy::features::
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h index 4143ded..8b7bb88 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
@@ -137,10 +137,6 @@ // unsuccessful. bool IsWhitelistedHttpResponseCodeForProbes(int http_response_code); -// Returns if site-breakdown metrics should be recorded using the page load -// metrics harness. -bool IsDataSaverSiteBreakdownUsingPLMEnabled(); - // Returns whether network service is enabled and data reduction proxy should be // used. bool IsEnabledWithNetworkService();
diff --git a/components/download/internal/background_service/controller_impl.cc b/components/download/internal/background_service/controller_impl.cc index 3c76cce..2177e6a8 100644 --- a/components/download/internal/background_service/controller_impl.cc +++ b/components/download/internal/background_service/controller_impl.cc
@@ -134,6 +134,7 @@ } ControllerImpl::~ControllerImpl() { + navigation_monitor_->SetObserver(nullptr); base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( this); }
diff --git a/components/download/internal/background_service/navigation_monitor_impl_unittests.cc b/components/download/internal/background_service/navigation_monitor_impl_unittests.cc index 0b23cef..19fb4dd 100644 --- a/components/download/internal/background_service/navigation_monitor_impl_unittests.cc +++ b/components/download/internal/background_service/navigation_monitor_impl_unittests.cc
@@ -97,6 +97,15 @@ DISALLOW_COPY_AND_ASSIGN(NavigationMonitorImplTest); }; +TEST_F(NavigationMonitorImplTest, NoObserver) { + SendNavigationEventAt(NavigationEvent::START_NAVIGATION, 5); + + observer_->VerifyNavigationStateAt(false, 0); + observer_->VerifyNavigationStateAt(false, 10); + observer_->VerifyNavigationStateAt(false, 100); + WaitUntilDone(); +} + TEST_F(NavigationMonitorImplTest, NavigationTimeout) { navigation_monitor_->SetObserver(observer_.get()); SendNavigationEventAt(NavigationEvent::START_NAVIGATION, 5);
diff --git a/components/download/internal/common/download_path_reservation_tracker.cc b/components/download/internal/common/download_path_reservation_tracker.cc index b5eccbd..5c02e27 100644 --- a/components/download/internal/common/download_path_reservation_tracker.cc +++ b/components/download/internal/common/download_path_reservation_tracker.cc
@@ -252,13 +252,18 @@ PathValidationResult ValidatePathAndResolveConflicts( const CreateReservationInfo& info, base::FilePath* target_path) { - // Check writability of the suggested path. If we can't write to it, default - // to the user's Documents directory. We'll prompt them in this case. No - // further amendments are made to the filename since the user is going to be - // prompted. + // Check writability of the suggested path. If we can't write to it, use + // the |default_download_path| if it is not empty or |fallback_directory|. + // We'll prompt them in this case. No further amendments are made to the + // filename since the user is going to be prompted. if (!IsPathWritable(info, *target_path)) { DVLOG(1) << "Unable to write to path \"" << target_path->value() << "\""; - *target_path = info.fallback_directory.Append(target_path->BaseName()); + if (!info.default_download_path.empty() && + target_path->DirName() != info.default_download_path) { + *target_path = info.default_download_path.Append(target_path->BaseName()); + } else { + *target_path = info.fallback_directory.Append(target_path->BaseName()); + } return PathValidationResult::PATH_NOT_WRITABLE; }
diff --git a/components/download/internal/common/download_path_reservation_tracker_unittest.cc b/components/download/internal/common/download_path_reservation_tracker_unittest.cc index d9d8745..acdffd42 100644 --- a/components/download/internal/common/download_path_reservation_tracker_unittest.cc +++ b/components/download/internal/common/download_path_reservation_tracker_unittest.cc
@@ -530,11 +530,23 @@ bool create_directory = false; CallGetReservedPath(item.get(), path, create_directory, conflict_action, &reserved_path, &result); - // Verification fails. + // Verification fails. If |dir| is the same as the default download dir, + // fallback_dir should be used. EXPECT_EQ(PathValidationResult::PATH_NOT_WRITABLE, result); EXPECT_EQ(path.BaseName().value(), reserved_path.BaseName().value()); EXPECT_EQ(fallback_dir.value(), reserved_path.DirName().value()); + + // Change the default download dir to something else. + base::FilePath default_download_path = + GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo/foo.txt")); + set_default_download_path(default_download_path); + CallGetReservedPath(item.get(), path, create_directory, conflict_action, + &reserved_path, &result); + EXPECT_EQ(PathValidationResult::PATH_NOT_WRITABLE, result); + EXPECT_EQ(path.BaseName().value(), reserved_path.BaseName().value()); + EXPECT_EQ(default_download_path.value(), reserved_path.DirName().value()); } + SetDownloadItemState(item.get(), DownloadItem::COMPLETE); }
diff --git a/components/download/quarantine/quarantine_features_win.cc b/components/download/quarantine/quarantine_features_win.cc index 7418593..6c67f2e1 100644 --- a/components/download/quarantine/quarantine_features_win.cc +++ b/components/download/quarantine/quarantine_features_win.cc
@@ -6,11 +6,6 @@ namespace download { -// When manually setting the Zone Identifier, this feature controls whether the -// HostUrl and ReferrerUrl values are set. -const base::Feature kAugmentedZoneIdentifier{"AugmentedZoneIdentifier", - base::FEATURE_DISABLED_BY_DEFAULT}; - // This feature controls whether the InvokeAttachmentServices function will be // called. Has no effect on machines that are domain-joined, where the function // is always called.
diff --git a/components/download/quarantine/quarantine_features_win.h b/components/download/quarantine/quarantine_features_win.h index b7db680..7363a0f4 100644 --- a/components/download/quarantine/quarantine_features_win.h +++ b/components/download/quarantine/quarantine_features_win.h
@@ -9,8 +9,6 @@ namespace download { -extern const base::Feature kAugmentedZoneIdentifier; - extern const base::Feature kInvokeAttachmentServices; } // namespace download
diff --git a/components/download/quarantine/quarantine_win.cc b/components/download/quarantine/quarantine_win.cc index 59701ee..eaf6370 100644 --- a/components/download/quarantine/quarantine_win.cc +++ b/components/download/quarantine/quarantine_win.cc
@@ -29,6 +29,7 @@ #include "base/threading/scoped_blocking_call.h" #include "base/win/scoped_handle.h" #include "base/win/win_util.h" +#include "base/win/windows_version.h" #include "components/download/quarantine/common_win.h" #include "components/download/quarantine/quarantine_features_win.h" #include "url/gurl.h" @@ -47,9 +48,8 @@ // streams are not supported, like a file on a FAT32 filesystem. This function // does not invoke Windows Attachment Execution Services. // -// If the AugmentedZoneIdentifier feature is enabled, the ReferrerUrl and -// HostUrl values are set according to the behavior of the IAttachmentExecute -// interface on Windows 10. +// On Windows 10 or higher, the ReferrerUrl and HostUrl values are set according +// to the behavior of the IAttachmentExecute interface. // // |full_path| is the path to the downloaded file. QuarantineFileResult SetInternetZoneIdentifierDirectly( @@ -68,7 +68,7 @@ static const char kHostUrlFormat[] = "HostUrl=%s\r\n"; std::string identifier = "[ZoneTransfer]\r\nZoneId=3\r\n"; - if (base::FeatureList::IsEnabled(kAugmentedZoneIdentifier)) { + if (base::win::GetVersion() >= base::win::VERSION_WIN10) { // Match what the InvokeAttachmentServices() function will output, including // the order of the values. if (IsValidUrlForAttachmentServices(referrer_url)) {
diff --git a/components/download/quarantine/quarantine_win_unittest.cc b/components/download/quarantine/quarantine_win_unittest.cc index c0e6283b..0c663a9 100644 --- a/components/download/quarantine/quarantine_win_unittest.cc +++ b/components/download/quarantine/quarantine_win_unittest.cc
@@ -30,8 +30,6 @@ const char kDummyReferrerUrl[] = "https://example.com/referrer"; const char kDummyClientGuid[] = "A1B69307-8FA2-4B6F-9181-EA06051A48A7"; -const char kMotwForInternetZone[] = "[ZoneTransfer]\r\nZoneId=3\r\n"; - const char* const kUntrustedURLs[] = { "http://example.com/foo", "https://example.com/foo", @@ -116,6 +114,7 @@ // Sets the internet Zone.Identifier alternate data stream for |file_path|. bool AddInternetZoneIdentifierDirectly(const base::FilePath& file_path) { + static const char kMotwForInternetZone[] = "[ZoneTransfer]\r\nZoneId=3\r\n"; return base::WriteFile(GetZoneIdentifierStreamPath(file_path), kMotwForInternetZone, base::size(kMotwForInternetZone)) == @@ -289,7 +288,10 @@ std::string zone_identifier; ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier)); - EXPECT_STREQ(zone_identifier.c_str(), kMotwForInternetZone); + // The actual assigned zone could be anything and the contents of the zone + // identifier depends on the version of Windows. So only testing that there is + // a zone annotation. + EXPECT_FALSE(zone_identifier.empty()); } // If there is no client GUID supplied to the QuarantineFile() call, then rather @@ -307,7 +309,10 @@ std::string zone_identifier; ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier)); - EXPECT_STREQ(zone_identifier.c_str(), kMotwForInternetZone); + // The actual assigned zone could be anything and the contents of the zone + // identifier depends on the version of Windows. So only testing that there is + // a zone annotation. + EXPECT_FALSE(zone_identifier.empty()); } // URLs longer than INTERNET_MAX_URL_LENGTH are known to break URLMon. Such a @@ -325,142 +330,10 @@ std::string zone_identifier; ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier)); - EXPECT_STREQ(zone_identifier.c_str(), kMotwForInternetZone); -} - -// On domain-joined machines, the IAttachmentExecute code path is taken, and the -// output depends on the Windows version. -TEST_F(QuarantineWinTest, EnterpriseUserZoneIdentifier) { - base::win::ScopedDomainStateForTesting scoped_domain(true); - - base::FilePath test_file = GetTempDir().AppendASCII("foo.exe"); - ASSERT_TRUE(CreateFile(test_file)); - - EXPECT_EQ(QuarantineFileResult::OK, - QuarantineFile(test_file, GURL(kDummySourceUrl), - GURL(kDummyReferrerUrl), kDummyClientGuid)); - - std::string zone_identifier; - ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier)); - - std::string expected = kMotwForInternetZone; - // On Win10, the MotW now contains the HostUrl and ReferrerUrl values. - if (base::win::GetVersion() >= base::win::VERSION_WIN10) { - expected.append(base::StringPrintf("ReferrerUrl=%s\r\nHostUrl=%s\r\n", - kDummyReferrerUrl, kDummySourceUrl)); - } - - EXPECT_EQ(zone_identifier, expected); -} - -// When the InvokeAttachmentServices is disabled, the fallback code path that -// manually sets the MotW is always invoked. The original fallback code only -// sets the ZoneId value. -TEST_F(QuarantineWinTest, DisableInvokeAttachmentServices) { - base::win::ScopedDomainStateForTesting scoped_domain(false); - - base::test::ScopedFeatureList scoped_feature_list_; - scoped_feature_list_.InitWithFeatures( - // Enabled features. - {}, - // Disabled features. - {kInvokeAttachmentServices}); - - base::FilePath test_file = GetTempDir().AppendASCII("foo.exe"); - ASSERT_TRUE(CreateFile(test_file)); - - EXPECT_EQ(QuarantineFileResult::OK, - QuarantineFile(test_file, GURL(kDummySourceUrl), - GURL(kDummyReferrerUrl), kDummyClientGuid)); - - std::string zone_identifier; - ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier)); - - EXPECT_STREQ(zone_identifier.c_str(), kMotwForInternetZone); -} - -// Tests the expected MotW when the AugmentedZoneIdentifier feature is enabled. -TEST_F(QuarantineWinTest, AugmentedZoneIdentifier) { - base::win::ScopedDomainStateForTesting scoped_domain(false); - - base::test::ScopedFeatureList scoped_feature_list_; - scoped_feature_list_.InitWithFeatures( - // Enabled features. - {kAugmentedZoneIdentifier}, - // Disabled features. - {kInvokeAttachmentServices}); - - base::FilePath test_file = GetTempDir().AppendASCII("foo.exe"); - ASSERT_TRUE(CreateFile(test_file)); - - EXPECT_EQ(QuarantineFileResult::OK, - QuarantineFile(test_file, GURL(kDummySourceUrl), - GURL(kDummyReferrerUrl), kDummyClientGuid)); - - std::string zone_identifier; - ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier)); - - std::string expected = kMotwForInternetZone; - expected.append(base::StringPrintf("ReferrerUrl=%s\r\nHostUrl=%s\r\n", - kDummyReferrerUrl, kDummySourceUrl)); - EXPECT_EQ(zone_identifier, expected); -} - -// Tests the expected MotW when the AugmentedZoneIdentifier feature is enabled -// and no referrer is provided to the QuarantineFile() function. -TEST_F(QuarantineWinTest, AugmentedZoneIdentifierNoReferrer) { - base::win::ScopedDomainStateForTesting scoped_domain(false); - - base::test::ScopedFeatureList scoped_feature_list_; - scoped_feature_list_.InitWithFeatures( - // Enabled features. - {kAugmentedZoneIdentifier}, - // Disabled features. - {kInvokeAttachmentServices}); - - base::FilePath test_file = GetTempDir().AppendASCII("foo.exe"); - ASSERT_TRUE(CreateFile(test_file)); - - EXPECT_EQ(QuarantineFileResult::OK, - QuarantineFile(test_file, GURL(kDummySourceUrl), GURL(), - kDummyClientGuid)); - - std::string zone_identifier; - ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier)); - - std::string expected = kMotwForInternetZone; - expected.append(base::StringPrintf("HostUrl=%s\r\n", kDummySourceUrl)); - - EXPECT_EQ(zone_identifier, expected); -} - -// Tests the expected MotW when the AugmentedZoneIdentifier feature is enabled -// and no source is provided to the QuarantineFile() function. -TEST_F(QuarantineWinTest, AugmentedZoneIdentifierNoSource) { - base::win::ScopedDomainStateForTesting scoped_domain(false); - - base::test::ScopedFeatureList scoped_feature_list_; - scoped_feature_list_.InitWithFeatures( - // Enabled features. - {kAugmentedZoneIdentifier}, - // Disabled features. - {kInvokeAttachmentServices}); - - base::FilePath test_file = GetTempDir().AppendASCII("foo.exe"); - ASSERT_TRUE(CreateFile(test_file)); - - EXPECT_EQ(QuarantineFileResult::OK, - QuarantineFile(test_file, GURL(), GURL(kDummyReferrerUrl), - kDummyClientGuid)); - - std::string zone_identifier; - ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier)); - - std::string expected = kMotwForInternetZone; - expected.append(base::StringPrintf("ReferrerUrl=%s\r\nHostUrl=%s\r\n", - kDummyReferrerUrl, "about:internet")); - - EXPECT_EQ(zone_identifier, expected); + // The actual assigned zone could be anything and the contents of the zone + // identifier depends on the version of Windows. So only testing that there is + // a zone annotation. + EXPECT_FALSE(zone_identifier.empty()); } TEST_F(QuarantineWinTest, TrustedSite) {
diff --git a/components/exo/client_controlled_shell_surface.cc b/components/exo/client_controlled_shell_surface.cc index afc35b88..61881c8 100644 --- a/components/exo/client_controlled_shell_surface.cc +++ b/components/exo/client_controlled_shell_surface.cc
@@ -308,6 +308,10 @@ } ClientControlledShellSurface::~ClientControlledShellSurface() { + // Reset the window delegate here so that we won't try to do any dragging + // operation on a to-be-destroyed window. |widget_| can be nullptr in tests. + if (GetWidget()) + GetWindowState()->SetDelegate(nullptr); wide_frame_.reset(); display::Screen::GetScreen()->RemoveObserver(this); }
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc index eab34b4..cc21e3cf 100644 --- a/components/exo/client_controlled_shell_surface_unittest.cc +++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -1090,6 +1090,80 @@ namespace { +// This class is only meant to used by CloseWindowWhenDraggingTest. +// When a ClientControlledShellSurface is destroyed, its natvie window will be +// hidden first and at that time its window delegate should have been properly +// reset. +class ShellSurfaceWindowObserver : public aura::WindowObserver { + public: + explicit ShellSurfaceWindowObserver(aura::Window* window) + : window_(window), + has_delegate_(ash::wm::GetWindowState(window)->HasDelegate()) { + window_->AddObserver(this); + } + ~ShellSurfaceWindowObserver() override { + if (window_) { + window_->RemoveObserver(this); + window_ = nullptr; + } + } + + bool has_delegate() const { return has_delegate_; } + + // aura::WindowObserver: + void OnWindowVisibilityChanged(aura::Window* window, bool visible) override { + DCHECK_EQ(window_, window); + + if (!visible) { + has_delegate_ = ash::wm::GetWindowState(window_)->HasDelegate(); + window_->RemoveObserver(this); + window_ = nullptr; + } + } + + private: + aura::Window* window_; + bool has_delegate_; + + DISALLOW_COPY_AND_ASSIGN(ShellSurfaceWindowObserver); +}; + +} // namespace + +// Test that when a shell surface is destroyed during its dragging, its window +// delegate should be reset properly. +TEST_F(ClientControlledShellSurfaceTest, CloseWindowWhenDraggingTest) { + gfx::Size buffer_size(256, 256); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface()); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get()); + + const gfx::Rect original_bounds(0, 0, 256, 256); + shell_surface->SetGeometry(original_bounds); + shell_surface->set_client_controlled_move_resize(false); + surface->Attach(buffer.get()); + surface->Commit(); + + // Press on the edge of the window and start dragging. + gfx::Point touch_location(256, 150); + ui::test::EventGenerator* event_generator = GetEventGenerator(); + event_generator->MoveTouch(touch_location); + event_generator->PressTouch(); + + aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); + EXPECT_TRUE(ash::wm::GetWindowState(window)->is_dragged()); + auto observer = std::make_unique<ShellSurfaceWindowObserver>(window); + EXPECT_TRUE(observer->has_delegate()); + + // Destroy the window. + shell_surface.reset(); + EXPECT_FALSE(observer->has_delegate()); +} + +namespace { + class ClientControlledShellSurfaceDragTest : public test::ExoTestBase { public: ClientControlledShellSurfaceDragTest() = default;
diff --git a/components/image_fetcher/core/cache/image_cache_unittest.cc b/components/image_fetcher/core/cache/image_cache_unittest.cc index 4802da6..bb57342 100644 --- a/components/image_fetcher/core/cache/image_cache_unittest.cc +++ b/components/image_fetcher/core/cache/image_cache_unittest.cc
@@ -52,8 +52,8 @@ auto db = std::make_unique<FakeDB<CachedImageMetadataProto>>(&db_store_); db_ = db.get(); - auto metadata_store = std::make_unique<ImageMetadataStoreLevelDB>( - base::FilePath(), std::move(db), &clock_); + auto metadata_store = + std::make_unique<ImageMetadataStoreLevelDB>(std::move(db), &clock_); metadata_store_ = metadata_store.get(); auto data_store = std::make_unique<ImageDataStoreDisk>( @@ -68,7 +68,7 @@ void InitializeImageCache() { image_cache_->MaybeStartInitialization(); - db()->InitCallback(true); + db()->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); RunUntilIdle(); ASSERT_TRUE(metadata_store()->IsInitialized()); } @@ -213,7 +213,7 @@ ASSERT_FALSE(IsCacheInitialized()); image_cache()->SaveImage(kImageUrl, kImageData); - db()->InitCallback(true); + db()->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); RunUntilIdle(); ASSERT_TRUE(IsCacheInitialized());
diff --git a/components/image_fetcher/core/cache/image_metadata_store_leveldb.cc b/components/image_fetcher/core/cache/image_metadata_store_leveldb.cc index d9f438f..11a669b 100644 --- a/components/image_fetcher/core/cache/image_metadata_store_leveldb.cc +++ b/components/image_fetcher/core/cache/image_metadata_store_leveldb.cc
@@ -33,12 +33,6 @@ return time.since_origin().InMicroseconds(); } -// Statistics are logged to UMA with this string as part of histogram name. They -// can all be found under LevelDB.*.ImageDatabase. Changing this needs to -// synchronize with histograms.xml, AND will also become incompatible with older -// browsers still reporting the previous values. -const char kImageDatabaseUMAClientName[] = "CachedImageFetcherDatabase"; - // The folder where the data will be stored on disk. const char kImageDatabaseFolder[] = "cached_image_fetcher_images"; @@ -62,23 +56,23 @@ leveldb_proto::ProtoDatabase<CachedImageMetadataProto>::KeyEntryVector; ImageMetadataStoreLevelDB::ImageMetadataStoreLevelDB( + leveldb_proto::ProtoDatabaseProvider* proto_database_provider, const base::FilePath& database_dir, scoped_refptr<base::SequencedTaskRunner> task_runner, base::Clock* clock) : ImageMetadataStoreLevelDB( - database_dir, - leveldb_proto::ProtoDatabaseProvider::CreateUniqueDB< - CachedImageMetadataProto>(task_runner), + proto_database_provider->GetDB<CachedImageMetadataProto>( + leveldb_proto::ProtoDbType::CACHED_IMAGE_METADATA_STORE, + database_dir.AppendASCII(kImageDatabaseFolder), + task_runner), clock) {} ImageMetadataStoreLevelDB::ImageMetadataStoreLevelDB( - const base::FilePath& database_dir, std::unique_ptr<leveldb_proto::ProtoDatabase<CachedImageMetadataProto>> database, base::Clock* clock) : estimated_size_(0), initialization_status_(InitializationStatus::UNINITIALIZED), - database_dir_(database_dir), database_(std::move(database)), clock_(clock), weak_ptr_factory_(this) {} @@ -93,9 +87,8 @@ options.write_buffer_size = kDatabaseWriteBufferSizeBytes; } - base::FilePath image_dir = database_dir_.AppendASCII(kImageDatabaseFolder); database_->Init( - kImageDatabaseUMAClientName, image_dir, options, + options, base::BindOnce(&ImageMetadataStoreLevelDB::OnDatabaseInitialized, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } @@ -188,9 +181,10 @@ void ImageMetadataStoreLevelDB::OnDatabaseInitialized( base::OnceClosure callback, - bool success) { - initialization_status_ = success ? InitializationStatus::INITIALIZED - : InitializationStatus::INIT_FAILURE; + leveldb_proto::Enums::InitStatus status) { + initialization_status_ = status == leveldb_proto::Enums::InitStatus::kOK + ? InitializationStatus::INITIALIZED + : InitializationStatus::INIT_FAILURE; std::move(callback).Run(); }
diff --git a/components/image_fetcher/core/cache/image_metadata_store_leveldb.h b/components/image_fetcher/core/cache/image_metadata_store_leveldb.h index 0a751bc..e5189a8d 100644 --- a/components/image_fetcher/core/cache/image_metadata_store_leveldb.h +++ b/components/image_fetcher/core/cache/image_metadata_store_leveldb.h
@@ -20,6 +20,10 @@ class SequencedTaskRunner; } // namespace base +namespace leveldb_proto { +class ProtoDatabaseProvider; +} // namespace leveldb_proto + namespace image_fetcher { class CachedImageMetadataProto; @@ -27,16 +31,16 @@ // Stores image metadata in leveldb. class ImageMetadataStoreLevelDB : public ImageMetadataStore { public: - // Initializes the database with |database_dir|. + // Initializes the database with |proto_database_provider|. ImageMetadataStoreLevelDB( + leveldb_proto::ProtoDatabaseProvider* proto_database_provider, const base::FilePath& database_dir, scoped_refptr<base::SequencedTaskRunner> task_runner, base::Clock* clock); - // Initializes the database with |database_dir|. Creates storage using the - // given |image_database| for local storage. Useful for testing. + // Creates storage using the given |database| for local storage. Useful for + // testing. ImageMetadataStoreLevelDB( - const base::FilePath& database_dir, std::unique_ptr<leveldb_proto::ProtoDatabase<CachedImageMetadataProto>> database, base::Clock* clock); @@ -62,7 +66,8 @@ KeysCallback callback) override; private: - void OnDatabaseInitialized(base::OnceClosure callback, bool success); + void OnDatabaseInitialized(base::OnceClosure callback, + leveldb_proto::Enums::InitStatus status); void OnImageUpdated(bool success); void UpdateImageMetadataImpl( bool success, @@ -82,7 +87,6 @@ int estimated_size_; InitializationStatus initialization_status_; - base::FilePath database_dir_; std::unique_ptr<leveldb_proto::ProtoDatabase<CachedImageMetadataProto>> database_; // Clock is owned by the service that creates this object.
diff --git a/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc b/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc index d6971df1..52d68dfeb 100644 --- a/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc +++ b/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc
@@ -47,8 +47,8 @@ // Setup the fake db and the class under test. auto db = std::make_unique<FakeDB<CachedImageMetadataProto>>(&db_store_); db_ = db.get(); - metadata_store_ = std::make_unique<ImageMetadataStoreLevelDB>( - base::FilePath(), std::move(db), clock_.get()); + metadata_store_ = std::make_unique<ImageMetadataStoreLevelDB>(std::move(db), + clock_.get()); } void InitializeDatabase() { @@ -56,7 +56,7 @@ metadata_store()->Initialize(base::BindOnce( &CachedImageFetcherImageMetadataStoreLevelDBTest::OnInitialized, base::Unretained(this))); - db()->InitCallback(true); + db()->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); RunUntilIdle(); }
diff --git a/components/image_fetcher/core/cached_image_fetcher_unittest.cc b/components/image_fetcher/core/cached_image_fetcher_unittest.cc index a4e8251..2c92f1b 100644 --- a/components/image_fetcher/core/cached_image_fetcher_unittest.cc +++ b/components/image_fetcher/core/cached_image_fetcher_unittest.cc
@@ -83,8 +83,8 @@ std::make_unique<FakeDB<CachedImageMetadataProto>>(&metadata_store_); db_ = db.get(); - auto metadata_store = std::make_unique<ImageMetadataStoreLevelDB>( - base::FilePath(), std::move(db), &clock_); + auto metadata_store = + std::make_unique<ImageMetadataStoreLevelDB>(std::move(db), &clock_); auto data_store = std::make_unique<ImageDataStoreDisk>( data_dir_.GetPath(), base::SequencedTaskRunnerHandle::Get()); @@ -95,7 +95,7 @@ // Use an initial request to start the cache up. image_cache_->SaveImage(kImageUrl.spec(), kImageData); RunUntilIdle(); - db_->InitCallback(true); + db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); image_cache_->DeleteImage(kImageUrl.spec()); RunUntilIdle();
diff --git a/components/leveldb_proto/public/shared_proto_database_client_list.cc b/components/leveldb_proto/public/shared_proto_database_client_list.cc index 6623e266..2c515675 100644 --- a/components/leveldb_proto/public/shared_proto_database_client_list.cc +++ b/components/leveldb_proto/public/shared_proto_database_client_list.cc
@@ -41,6 +41,8 @@ return "UsageStatsTokenMapping"; case ProtoDbType::DOM_DISTILLER_STORE: return "DomDistillerStore"; + case ProtoDbType::CACHED_IMAGE_METADATA_STORE: + return "CachedImageFetcherDatabase"; case ProtoDbType::LAST: NOTREACHED(); break; @@ -73,4 +75,4 @@ kProtoDBSharedMigration, kDBNameParamPrefix + name, false); } -} // namespace leveldb_proto \ No newline at end of file +} // namespace leveldb_proto
diff --git a/components/leveldb_proto/public/shared_proto_database_client_list.h b/components/leveldb_proto/public/shared_proto_database_client_list.h index 5b7b9211..c5d3434a 100644 --- a/components/leveldb_proto/public/shared_proto_database_client_list.h +++ b/components/leveldb_proto/public/shared_proto_database_client_list.h
@@ -27,6 +27,7 @@ USAGE_STATS_TOKEN_MAPPING = 7, DOM_DISTILLER_STORE = 8, DOWNLOAD_STORE = 9, + CACHED_IMAGE_METADATA_STORE = 10, LAST, }; @@ -55,4 +56,4 @@ } // namespace leveldb_proto -#endif // COMPONENTS_LEVELDB_PROTO_PUBLIC_SHARED_PROTO_DATABASE_CLIENT_LIST_H_ \ No newline at end of file +#endif // COMPONENTS_LEVELDB_PROTO_PUBLIC_SHARED_PROTO_DATABASE_CLIENT_LIST_H_
diff --git a/components/ntp_snippets/category.h b/components/ntp_snippets/category.h index a59a489..882cce3 100644 --- a/components/ntp_snippets/category.h +++ b/components/ntp_snippets/category.h
@@ -23,7 +23,7 @@ RECENT_TABS_DEPRECATED, // Pages downloaded by the user for offline consumption. - DOWNLOADS, + DOWNLOADS_DEPRECATED, // Recently used bookmarks. BOOKMARKS_DEPRECATED,
diff --git a/components/ntp_snippets/category_rankers/click_based_category_ranker_unittest.cc b/components/ntp_snippets/category_rankers/click_based_category_ranker_unittest.cc index baf37ec..8b80ec3 100644 --- a/components/ntp_snippets/category_rankers/click_based_category_ranker_unittest.cc +++ b/components/ntp_snippets/category_rankers/click_based_category_ranker_unittest.cc
@@ -113,7 +113,7 @@ TEST_F(ClickBasedCategoryRankerTest, ShouldSortLocalCategoriesBeforeRemote) { const Category remote_category = AddUnusedRemoteCategory(); const Category local_category = - Category::FromKnownCategory(KnownCategories::DOWNLOADS); + Category::FromKnownCategory(KnownCategories::READING_LIST); EXPECT_TRUE(CompareCategories(local_category, remote_category)); EXPECT_FALSE(CompareCategories(remote_category, local_category)); } @@ -124,7 +124,7 @@ EXPECT_FALSE(CompareCategories(remote_category, remote_category)); const Category local_category = - Category::FromKnownCategory(KnownCategories::DOWNLOADS); + Category::FromKnownCategory(KnownCategories::READING_LIST); EXPECT_FALSE(CompareCategories(local_category, local_category)); } @@ -428,29 +428,6 @@ EXPECT_TRUE(CompareCategories(first, second)); } -TEST_F(ClickBasedCategoryRankerTest, - ShouldReduceLastCategoryClicksWhenDismissed) { - Category first = AddUnusedRemoteCategory(); - Category second = AddUnusedRemoteCategory(); - - ASSERT_TRUE(CompareCategories(first, second)); - - NotifyOnSuggestionOpened(/*times=*/1, second); - - // This should reduce the click count back to 0. - NotifyOnCategoryDismissed(second); - - // Try to move the second category up assuming that the previous click is - // still there. - NotifyOnSuggestionOpened( - /*times=*/ClickBasedCategoryRanker::GetPassingMargin() - 1, second); - - EXPECT_TRUE(CompareCategories(first, second)); - - NotifyOnSuggestionOpened(/*times=*/1, second); - EXPECT_FALSE(CompareCategories(first, second)); -} - TEST_F(ClickBasedCategoryRankerTest, ShouldRestoreDefaultOrderOnClearHistory) { std::vector<KnownCategories> default_order = ConstantCategoryRanker::GetKnownCategoriesDefaultOrder(); @@ -639,7 +616,7 @@ ShouldNotChangeRemainingOrderWhenInsertingBeforeCategory) { std::vector<KnownCategories> default_order = ConstantCategoryRanker::GetKnownCategoriesDefaultOrder(); - Category anchor = Category::FromKnownCategory(default_order[2]); + Category anchor = Category::FromKnownCategory(default_order[0]); Category inserted = GetUnusedRemoteCategory(); ranker()->InsertCategoryBeforeIfNecessary(inserted, anchor); @@ -657,9 +634,7 @@ ConstantCategoryRanker::GetKnownCategoriesDefaultOrder(); Category first = Category::FromKnownCategory(default_order[0]); Category second = Category::FromKnownCategory(default_order[1]); - Category third = Category::FromKnownCategory(default_order[2]); ASSERT_TRUE(CompareCategories(first, second)); - ASSERT_TRUE(CompareCategories(second, third)); Category first_before = GetUnusedRemoteCategory(); ranker()->InsertCategoryBeforeIfNecessary(first_before, second); @@ -677,7 +652,6 @@ EXPECT_TRUE(CompareCategories(second_before, second)); EXPECT_TRUE(CompareCategories(second, second_after)); EXPECT_TRUE(CompareCategories(second_after, first_after)); - EXPECT_TRUE(CompareCategories(first_after, third)); } TEST_F(ClickBasedCategoryRankerTest, @@ -776,7 +750,7 @@ ShouldNotChangeRemainingOrderWhenInsertingAfterCategory) { std::vector<KnownCategories> default_order = ConstantCategoryRanker::GetKnownCategoriesDefaultOrder(); - Category anchor = Category::FromKnownCategory(default_order[2]); + Category anchor = Category::FromKnownCategory(default_order[0]); Category inserted = GetUnusedRemoteCategory(); ranker()->InsertCategoryAfterIfNecessary(inserted, anchor);
diff --git a/components/ntp_snippets/category_rankers/constant_category_ranker.cc b/components/ntp_snippets/category_rankers/constant_category_ranker.cc index b42aa5d..6ddd284 100644 --- a/components/ntp_snippets/category_rankers/constant_category_ranker.cc +++ b/components/ntp_snippets/category_rankers/constant_category_ranker.cc
@@ -17,7 +17,6 @@ // ContentSuggestionsService. constexpr KnownCategories kKnownCategoriesDefaultOrder[] = { KnownCategories::READING_LIST, - KnownCategories::DOWNLOADS, KnownCategories::ARTICLES, }; } // namespace
diff --git a/components/ntp_snippets/category_rankers/constant_category_ranker_unittest.cc b/components/ntp_snippets/category_rankers/constant_category_ranker_unittest.cc index 5f99d5d7..bd0421b 100644 --- a/components/ntp_snippets/category_rankers/constant_category_ranker_unittest.cc +++ b/components/ntp_snippets/category_rankers/constant_category_ranker_unittest.cc
@@ -62,7 +62,7 @@ TEST_F(ConstantCategoryRankerTest, ShouldSortLocalCategoriesBeforeRemote) { const Category remote_category = AddUnusedRemoteCategory(); const Category local_category = - Category::FromKnownCategory(KnownCategories::DOWNLOADS); + Category::FromKnownCategory(KnownCategories::READING_LIST); EXPECT_TRUE(CompareCategories(local_category, remote_category)); EXPECT_FALSE(CompareCategories(remote_category, local_category)); } @@ -72,7 +72,7 @@ EXPECT_FALSE(CompareCategories(remote_category, remote_category)); const Category local_category = - Category::FromKnownCategory(KnownCategories::DOWNLOADS); + Category::FromKnownCategory(KnownCategories::READING_LIST); EXPECT_FALSE(CompareCategories(local_category, local_category)); }
diff --git a/components/ntp_snippets/category_unittest.cc b/components/ntp_snippets/category_unittest.cc index a03034f1..f75c792 100644 --- a/components/ntp_snippets/category_unittest.cc +++ b/components/ntp_snippets/category_unittest.cc
@@ -9,13 +9,6 @@ namespace ntp_snippets { -TEST(CategoryTest, FromKnownCategoryShouldReturnSameCategoryForSameInput) { - const KnownCategories known_category = KnownCategories::DOWNLOADS; - Category first = Category::FromKnownCategory(known_category); - Category second = Category::FromKnownCategory(known_category); - EXPECT_EQ(first, second); -} - TEST(CategoryTest, ShouldIdentifyValidIDValues) { EXPECT_TRUE( Category::IsValidIDValue(static_cast<int>(KnownCategories::ARTICLES))); @@ -39,7 +32,7 @@ TEST(CategoryFactoryTest, FromIDValueShouldReturnSameKnownCategory) { Category known_category = - Category::FromKnownCategory(KnownCategories::DOWNLOADS); + Category::FromKnownCategory(KnownCategories::READING_LIST); Category known_category_by_id = Category::FromIDValue(known_category.id()); EXPECT_EQ(known_category, known_category_by_id); }
diff --git a/components/ntp_snippets/content_suggestion.cc b/components/ntp_snippets/content_suggestion.cc index 5dd75b9..036efc4 100644 --- a/components/ntp_snippets/content_suggestion.cc +++ b/components/ntp_snippets/content_suggestion.cc
@@ -8,13 +8,6 @@ namespace ntp_snippets { -DownloadSuggestionExtra::DownloadSuggestionExtra() = default; - -DownloadSuggestionExtra::DownloadSuggestionExtra( - const DownloadSuggestionExtra& other) = default; - -DownloadSuggestionExtra::~DownloadSuggestionExtra() = default; - bool ContentSuggestion::ID::operator==(const ID& rhs) const { return category_ == rhs.category_ && id_within_category_ == rhs.id_within_category_; @@ -51,12 +44,6 @@ return favicon_url.GetWithEmptyPath(); } -void ContentSuggestion::set_download_suggestion_extra( - std::unique_ptr<DownloadSuggestionExtra> download_suggestion_extra) { - DCHECK(id_.category().IsKnownCategory(KnownCategories::DOWNLOADS)); - download_suggestion_extra_ = std::move(download_suggestion_extra); -} - void ContentSuggestion::set_reading_list_suggestion_extra( std::unique_ptr<ReadingListSuggestionExtra> reading_list_suggestion_extra) { DCHECK(id_.category().IsKnownCategory(KnownCategories::READING_LIST));
diff --git a/components/ntp_snippets/content_suggestion.h b/components/ntp_snippets/content_suggestion.h index 8d19ec3d..63971207 100644 --- a/components/ntp_snippets/content_suggestion.h +++ b/components/ntp_snippets/content_suggestion.h
@@ -19,27 +19,6 @@ namespace ntp_snippets { -// DownloadSuggestionExtra contains additional data which is only available for -// download suggestions. -struct DownloadSuggestionExtra { - DownloadSuggestionExtra(); - DownloadSuggestionExtra(const DownloadSuggestionExtra&); - ~DownloadSuggestionExtra(); - - // The GUID for the downloaded file. - std::string download_guid; - // The file path of the downloaded file once download completes. - base::FilePath target_file_path; - // The effective MIME type of downloaded content. - std::string mime_type; - // Underlying offline page identifier. - int64_t offline_page_id = 0; - // Whether or not the download suggestion is a downloaded asset. - // When this is true, |offline_page_id| is ignored, otherwise - // |target_file_path| and |mime_type| are ignored. - bool is_download_asset = false; -}; - // ReadingListSuggestionExtra contains additional data which is only available // for Reading List suggestions. struct ReadingListSuggestionExtra { @@ -153,15 +132,6 @@ float score() const { return score_; } void set_score(float score) { score_ = score; } - // Extra information for download suggestions. Only available for DOWNLOADS - // suggestions (i.e., if the associated category has the - // KnownCategories::DOWNLOADS id). - DownloadSuggestionExtra* download_suggestion_extra() const { - return download_suggestion_extra_.get(); - } - void set_download_suggestion_extra( - std::unique_ptr<DownloadSuggestionExtra> download_suggestion_extra); - // Extra information for reading list suggestions. Only available for // KnownCategories::READING_LIST suggestions. ReadingListSuggestionExtra* reading_list_suggestion_extra() const { @@ -204,7 +174,6 @@ base::Time publish_date_; base::string16 publisher_name_; float score_; - std::unique_ptr<DownloadSuggestionExtra> download_suggestion_extra_; std::unique_ptr<ReadingListSuggestionExtra> reading_list_suggestion_extra_; std::unique_ptr<NotificationExtra> notification_extra_;
diff --git a/components/ntp_snippets/content_suggestions_metrics.cc b/components/ntp_snippets/content_suggestions_metrics.cc index 113a3a2..b55533e 100644 --- a/components/ntp_snippets/content_suggestions_metrics.cc +++ b/components/ntp_snippets/content_suggestions_metrics.cc
@@ -82,7 +82,7 @@ enum class HistogramCategories { EXPERIMENTAL, RECENT_TABS_DEPRECATED, - DOWNLOADS, + DOWNLOADS_DEPRECATED, BOOKMARKS_DEPRECATED, PHYSICAL_WEB_PAGES_DEPRECATED, FOREIGN_TABS_DEPRECATED, @@ -104,18 +104,18 @@ // listed here. auto known_category = static_cast<KnownCategories>(category.id()); switch (known_category) { - case KnownCategories::DOWNLOADS: - return HistogramCategories::DOWNLOADS; - case KnownCategories::BOOKMARKS_DEPRECATED: - return HistogramCategories::BOOKMARKS_DEPRECATED; - case KnownCategories::FOREIGN_TABS_DEPRECATED: - return HistogramCategories::FOREIGN_TABS_DEPRECATED; case KnownCategories::ARTICLES: return HistogramCategories::ARTICLES; case KnownCategories::READING_LIST: return HistogramCategories::READING_LIST; case KnownCategories::CONTEXTUAL: return HistogramCategories::CONTEXTUAL; + case KnownCategories::BOOKMARKS_DEPRECATED: + return HistogramCategories::BOOKMARKS_DEPRECATED; + case KnownCategories::DOWNLOADS_DEPRECATED: + return HistogramCategories::DOWNLOADS_DEPRECATED; + case KnownCategories::FOREIGN_TABS_DEPRECATED: + return HistogramCategories::FOREIGN_TABS_DEPRECATED; case KnownCategories::RECENT_TABS_DEPRECATED: case KnownCategories::PHYSICAL_WEB_PAGES_DEPRECATED: case KnownCategories::LOCAL_CATEGORIES_COUNT: @@ -132,8 +132,6 @@ std::string GetCategorySuffix(Category category) { HistogramCategories histogram_category = GetHistogramCategory(category); switch (histogram_category) { - case HistogramCategories::DOWNLOADS: - return "Downloads"; case HistogramCategories::ARTICLES: return "Articles"; case HistogramCategories::EXPERIMENTAL: @@ -143,6 +141,7 @@ case HistogramCategories::CONTEXTUAL: return "Contextual"; case HistogramCategories::BOOKMARKS_DEPRECATED: + case HistogramCategories::DOWNLOADS_DEPRECATED: case HistogramCategories::FOREIGN_TABS_DEPRECATED: case HistogramCategories::RECENT_TABS_DEPRECATED: case HistogramCategories::PHYSICAL_WEB_PAGES_DEPRECATED:
diff --git a/components/ntp_snippets/content_suggestions_metrics_unittest.cc b/components/ntp_snippets/content_suggestions_metrics_unittest.cc index 82bb90939..d1f3bba 100644 --- a/components/ntp_snippets/content_suggestions_metrics_unittest.cc +++ b/components/ntp_snippets/content_suggestions_metrics_unittest.cc
@@ -112,17 +112,13 @@ base::HistogramTester histogram_tester; OnPageShown(std::vector<Category>( {Category::FromKnownCategory(KnownCategories::ARTICLES), - Category::FromKnownCategory(KnownCategories::DOWNLOADS)}), + Category::FromKnownCategory(KnownCategories::READING_LIST)}), /*suggestions_per_category=*/{10, 5}, /*is_category_visible=*/{true, true}); EXPECT_THAT( histogram_tester.GetAllSamples( "NewTabPage.ContentSuggestions.CountOnNtpOpenedIfVisible.Articles"), ElementsAre(base::Bucket(/*min=*/10, /*count=*/1))); - EXPECT_THAT( - histogram_tester.GetAllSamples( - "NewTabPage.ContentSuggestions.CountOnNtpOpenedIfVisible.Downloads"), - ElementsAre(base::Bucket(/*min=*/5, /*count=*/1))); EXPECT_THAT(histogram_tester.GetAllSamples( "NewTabPage.ContentSuggestions.CountOnNtpOpenedIfVisible"), ElementsAre(base::Bucket(/*min=*/15, /*count=*/1)));
diff --git a/components/ntp_snippets/content_suggestions_service_unittest.cc b/components/ntp_snippets/content_suggestions_service_unittest.cc index 4cb6d0e..5fcd6a0 100644 --- a/components/ntp_snippets/content_suggestions_service_unittest.cc +++ b/components/ntp_snippets/content_suggestions_service_unittest.cc
@@ -211,19 +211,14 @@ Eq(ContentSuggestionsService::State::ENABLED)); Category articles_category = Category::FromKnownCategory(KnownCategories::ARTICLES); - Category offline_pages_category = - Category::FromKnownCategory(KnownCategories::DOWNLOADS); ASSERT_THAT(providers(), IsEmpty()); EXPECT_THAT(service()->GetCategories(), IsEmpty()); EXPECT_THAT(service()->GetCategoryStatus(articles_category), Eq(CategoryStatus::NOT_PROVIDED)); - EXPECT_THAT(service()->GetCategoryStatus(offline_pages_category), - Eq(CategoryStatus::NOT_PROVIDED)); MockContentSuggestionsProvider* provider1 = MakeRegisteredMockProvider(articles_category); provider1->FireCategoryStatusChangedWithCurrentStatus(articles_category); - EXPECT_THAT(providers().count(offline_pages_category), Eq(0ul)); ASSERT_THAT(providers().count(articles_category), Eq(1ul)); EXPECT_THAT(providers().at(articles_category), Eq(provider1)); EXPECT_THAT(providers().size(), Eq(1ul)); @@ -231,37 +226,16 @@ UnorderedElementsAre(articles_category)); EXPECT_THAT(service()->GetCategoryStatus(articles_category), Eq(CategoryStatus::AVAILABLE)); - EXPECT_THAT(service()->GetCategoryStatus(offline_pages_category), - Eq(CategoryStatus::NOT_PROVIDED)); - - MockContentSuggestionsProvider* provider2 = - MakeRegisteredMockProvider(offline_pages_category); - provider2->FireCategoryStatusChangedWithCurrentStatus(offline_pages_category); - ASSERT_THAT(providers().count(offline_pages_category), Eq(1ul)); - EXPECT_THAT(providers().at(articles_category), Eq(provider1)); - ASSERT_THAT(providers().count(articles_category), Eq(1ul)); - EXPECT_THAT(providers().at(offline_pages_category), Eq(provider2)); - EXPECT_THAT(providers().size(), Eq(2ul)); - EXPECT_THAT(service()->GetCategories(), - UnorderedElementsAre(offline_pages_category, articles_category)); - EXPECT_THAT(service()->GetCategoryStatus(articles_category), - Eq(CategoryStatus::AVAILABLE)); - EXPECT_THAT(service()->GetCategoryStatus(offline_pages_category), - Eq(CategoryStatus::AVAILABLE)); } TEST_F(ContentSuggestionsServiceDisabledTest, ShouldDoNothingWhenDisabled) { Category articles_category = Category::FromKnownCategory(KnownCategories::ARTICLES); - Category offline_pages_category = - Category::FromKnownCategory(KnownCategories::DOWNLOADS); EXPECT_THAT(service()->state(), Eq(ContentSuggestionsService::State::DISABLED)); EXPECT_THAT(providers(), IsEmpty()); EXPECT_THAT(service()->GetCategoryStatus(articles_category), Eq(CategoryStatus::ALL_SUGGESTIONS_EXPLICITLY_DISABLED)); - EXPECT_THAT(service()->GetCategoryStatus(offline_pages_category), - Eq(CategoryStatus::ALL_SUGGESTIONS_EXPLICITLY_DISABLED)); EXPECT_THAT(service()->GetCategories(), IsEmpty()); EXPECT_THAT(service()->GetSuggestionsForCategory(articles_category), IsEmpty()); @@ -270,19 +244,14 @@ TEST_F(ContentSuggestionsServiceTest, ShouldRedirectFetchSuggestionImage) { Category articles_category = Category::FromKnownCategory(KnownCategories::ARTICLES); - Category offline_pages_category = - Category::FromKnownCategory(KnownCategories::DOWNLOADS); MockContentSuggestionsProvider* provider1 = MakeRegisteredMockProvider(articles_category); - MockContentSuggestionsProvider* provider2 = - MakeRegisteredMockProvider(offline_pages_category); provider1->FireSuggestionsChanged(articles_category, CreateSuggestions(articles_category, {1})); ContentSuggestion::ID suggestion_id(articles_category, "1"); EXPECT_CALL(*provider1, FetchSuggestionImageMock(suggestion_id, _)); - EXPECT_CALL(*provider2, FetchSuggestionImageMock(_, _)).Times(0); service()->FetchSuggestionImage( suggestion_id, base::BindOnce(&ContentSuggestionsServiceTest::OnImageFetched, @@ -305,25 +274,6 @@ run_loop.Run(); } -TEST_F(ContentSuggestionsServiceTest, ShouldRedirectDismissSuggestion) { - Category articles_category = - Category::FromKnownCategory(KnownCategories::ARTICLES); - Category offline_pages_category = - Category::FromKnownCategory(KnownCategories::DOWNLOADS); - MockContentSuggestionsProvider* provider1 = - MakeRegisteredMockProvider(articles_category); - MockContentSuggestionsProvider* provider2 = - MakeRegisteredMockProvider(offline_pages_category); - - provider2->FireSuggestionsChanged( - offline_pages_category, CreateSuggestions(offline_pages_category, {11})); - ContentSuggestion::ID suggestion_id(offline_pages_category, "11"); - - EXPECT_CALL(*provider1, DismissSuggestion(_)).Times(0); - EXPECT_CALL(*provider2, DismissSuggestion(suggestion_id)); - service()->DismissSuggestion(suggestion_id); -} - TEST_F(ContentSuggestionsServiceTest, ShouldRedirectSuggestionInvalidated) { Category articles_category = Category::FromKnownCategory(KnownCategories::ARTICLES); @@ -358,20 +308,13 @@ TEST_F(ContentSuggestionsServiceTest, ShouldForwardSuggestions) { Category articles_category = Category::FromKnownCategory(KnownCategories::ARTICLES); - Category offline_pages_category = - Category::FromKnownCategory(KnownCategories::DOWNLOADS); // Create and register providers MockContentSuggestionsProvider* provider1 = MakeRegisteredMockProvider(articles_category); provider1->FireCategoryStatusChangedWithCurrentStatus(articles_category); - MockContentSuggestionsProvider* provider2 = - MakeRegisteredMockProvider(offline_pages_category); - provider2->FireCategoryStatusChangedWithCurrentStatus(offline_pages_category); ASSERT_THAT(providers().count(articles_category), Eq(1ul)); EXPECT_THAT(providers().at(articles_category), Eq(provider1)); - ASSERT_THAT(providers().count(offline_pages_category), Eq(1ul)); - EXPECT_THAT(providers().at(offline_pages_category), Eq(provider2)); // Create and register observer MockServiceObserver observer; @@ -389,15 +332,6 @@ provider1->FireSuggestionsChanged( articles_category, CreateSuggestions(articles_category, {1, 2})); ExpectThatSuggestionsAre(articles_category, {1, 2}); - ExpectThatSuggestionsAre(offline_pages_category, std::vector<int>()); - Mock::VerifyAndClearExpectations(&observer); - - // Send suggestions 13 and 14 - EXPECT_CALL(observer, OnNewSuggestions(offline_pages_category)); - provider2->FireSuggestionsChanged( - offline_pages_category, CreateSuggestions(articles_category, {13, 14})); - ExpectThatSuggestionsAre(articles_category, {1, 2}); - ExpectThatSuggestionsAre(offline_pages_category, {13, 14}); Mock::VerifyAndClearExpectations(&observer); // Send suggestion 1 only @@ -405,21 +339,6 @@ provider1->FireSuggestionsChanged(articles_category, CreateSuggestions(articles_category, {1})); ExpectThatSuggestionsAre(articles_category, {1}); - ExpectThatSuggestionsAre(offline_pages_category, {13, 14}); - Mock::VerifyAndClearExpectations(&observer); - - // provider2 reports BOOKMARKS as unavailable - EXPECT_CALL(observer, OnCategoryStatusChanged( - offline_pages_category, - CategoryStatus::CATEGORY_EXPLICITLY_DISABLED)); - provider2->FireCategoryStatusChanged( - offline_pages_category, CategoryStatus::CATEGORY_EXPLICITLY_DISABLED); - EXPECT_THAT(service()->GetCategoryStatus(articles_category), - Eq(CategoryStatus::AVAILABLE)); - EXPECT_THAT(service()->GetCategoryStatus(offline_pages_category), - Eq(CategoryStatus::CATEGORY_EXPLICITLY_DISABLED)); - ExpectThatSuggestionsAre(articles_category, {1}); - ExpectThatSuggestionsAre(offline_pages_category, std::vector<int>()); Mock::VerifyAndClearExpectations(&observer); // Shutdown the service @@ -431,13 +350,15 @@ TEST_F(ContentSuggestionsServiceTest, ShouldNotReturnCategoryInfoForNonexistentCategory) { - Category category = Category::FromKnownCategory(KnownCategories::DOWNLOADS); + Category category = + Category::FromKnownCategory(KnownCategories::READING_LIST); base::Optional<CategoryInfo> result = service()->GetCategoryInfo(category); EXPECT_FALSE(result.has_value()); } TEST_F(ContentSuggestionsServiceTest, ShouldReturnCategoryInfo) { - Category category = Category::FromKnownCategory(KnownCategories::DOWNLOADS); + Category category = + Category::FromKnownCategory(KnownCategories::READING_LIST); MockContentSuggestionsProvider* provider = MakeRegisteredMockProvider(category); provider->FireCategoryStatusChangedWithCurrentStatus(category); @@ -452,7 +373,8 @@ TEST_F(ContentSuggestionsServiceTest, ShouldRegisterNewCategoryOnNewSuggestions) { - Category category = Category::FromKnownCategory(KnownCategories::DOWNLOADS); + Category category = + Category::FromKnownCategory(KnownCategories::READING_LIST); MockContentSuggestionsProvider* provider = MakeRegisteredMockProvider(category); provider->FireCategoryStatusChangedWithCurrentStatus(category); @@ -488,7 +410,8 @@ TEST_F(ContentSuggestionsServiceTest, ShouldRegisterNewCategoryOnCategoryStatusChanged) { - Category category = Category::FromKnownCategory(KnownCategories::DOWNLOADS); + Category category = + Category::FromKnownCategory(KnownCategories::READING_LIST); MockContentSuggestionsProvider* provider = MakeRegisteredMockProvider(category); provider->FireCategoryStatusChangedWithCurrentStatus(category); @@ -518,7 +441,8 @@ } TEST_F(ContentSuggestionsServiceTest, ShouldRemoveCategoryWhenNotProvided) { - Category category = Category::FromKnownCategory(KnownCategories::DOWNLOADS); + Category category = + Category::FromKnownCategory(KnownCategories::READING_LIST); MockContentSuggestionsProvider* provider = MakeRegisteredMockProvider(category); MockServiceObserver observer; @@ -540,17 +464,6 @@ service()->RemoveObserver(&observer); } -TEST_F(ContentSuggestionsServiceTest, ShouldForwardClearHistoryToProviders) { - Category category = Category::FromKnownCategory(KnownCategories::DOWNLOADS); - MockContentSuggestionsProvider* provider = - MakeRegisteredMockProvider(category); - base::Time begin = base::Time::FromTimeT(123); - base::Time end = base::Time::FromTimeT(456); - EXPECT_CALL(*provider, ClearHistory(begin, end, _)); - base::Callback<bool(const GURL& url)> filter; - service()->ClearHistory(begin, end, filter); -} - TEST_F(ContentSuggestionsServiceTest, ShouldForwardClearHistoryToCategoryRanker) { auto mock_ranker = std::make_unique<MockCategoryRanker>(); @@ -567,86 +480,6 @@ service()->ClearHistory(begin, end, filter); } -TEST_F(ContentSuggestionsServiceTest, ShouldForwardDeleteAllHistoryURLs) { - StrictMock<MockServiceObserver> observer; - service()->AddObserver(&observer); - EXPECT_CALL(observer, OnFullRefreshRequired()); - - Category category = Category::FromKnownCategory(KnownCategories::DOWNLOADS); - MockContentSuggestionsProvider* provider = - MakeRegisteredMockProvider(category); - EXPECT_CALL(*provider, ClearHistory(base::Time(), base::Time::Max(), _)); - static_cast<history::HistoryServiceObserver*>(service())->OnURLsDeleted( - /*history_service=*/nullptr, history::DeletionInfo::ForAllHistory()); - - service()->RemoveObserver(&observer); -} - -TEST_F(ContentSuggestionsServiceTest, ShouldIgnoreExpiredURLDeletions) { - Category category = Category::FromKnownCategory(KnownCategories::DOWNLOADS); - MakeRegisteredMockProvider(category); - // Create an observer to make sure OnFullRefresh() does not get triggered. - StrictMock<MockServiceObserver> observer; - service()->AddObserver(&observer); - - static_cast<history::HistoryServiceObserver*>(service())->OnURLsDeleted( - /*history_service=*/nullptr, - history::DeletionInfo(history::DeletionTimeRange::AllTime(), - /*expired=*/true, history::URLRows(), - /*favicon_urls=*/std::set<GURL>(), - /*restrict_urls=*/base::nullopt)); - static_cast<history::HistoryServiceObserver*>(service())->OnURLsDeleted( - /*history_service=*/nullptr, - history::DeletionInfo(history::DeletionTimeRange::Invalid(), - /*expired=*/true, - {history::URLRow(GURL("http://google.com")), - history::URLRow(GURL("http://maps.google.com"))}, - /*favicon_urls=*/std::set<GURL>(), - /*restrict_urls=*/base::nullopt)); - - service()->RemoveObserver(&observer); -} - -TEST_F(ContentSuggestionsServiceTest, ShouldIgnoreEmptyURLDeletions) { - Category category = Category::FromKnownCategory(KnownCategories::DOWNLOADS); - MakeRegisteredMockProvider(category); - static_cast<history::HistoryServiceObserver*>(service())->OnURLsDeleted( - /*history_service=*/nullptr, history::DeletionInfo::ForUrls({}, {})); -} - -TEST_F(ContentSuggestionsServiceTest, - ShouldNotClearHistoryOnSingleURLDeletion) { - Category category = Category::FromKnownCategory(KnownCategories::DOWNLOADS); - MakeRegisteredMockProvider(category); - // Single URLs should not trigger - static_cast<history::HistoryServiceObserver*>(service())->OnURLsDeleted( - /*history_service=*/nullptr, - history::DeletionInfo::ForUrls( - {history::URLRow(GURL("http://google.com"))}, - /*favicon_urls=*/std::set<GURL>())); -} - -TEST_F(ContentSuggestionsServiceTest, - ShouldClearHistoryForMultipleURLDeletion) { - StrictMock<MockServiceObserver> observer; - service()->AddObserver(&observer); - EXPECT_CALL(observer, OnFullRefreshRequired()); - - Category category = Category::FromKnownCategory(KnownCategories::DOWNLOADS); - MockContentSuggestionsProvider* provider = - MakeRegisteredMockProvider(category); - EXPECT_CALL(*provider, ClearHistory(base::Time(), base::Time::Max(), _)); - - static_cast<history::HistoryServiceObserver*>(service())->OnURLsDeleted( - /*history_service=*/nullptr, - history::DeletionInfo::ForUrls( - {history::URLRow(GURL("http://google.com")), - history::URLRow(GURL("http://youtube.com"))}, - /*favicon_urls=*/std::set<GURL>())); - - service()->RemoveObserver(&observer); -} - TEST_F(ContentSuggestionsServiceTest, ShouldForwardFetch) { Category category = Category::FromKnownCategory(KnownCategories::ARTICLES); std::set<std::string> known_suggestions;
diff --git a/components/ntp_snippets/remote/remote_suggestion_unittest.cc b/components/ntp_snippets/remote/remote_suggestion_unittest.cc index d7437fbb..be203fc 100644 --- a/components/ntp_snippets/remote/remote_suggestion_unittest.cc +++ b/components/ntp_snippets/remote/remote_suggestion_unittest.cc
@@ -282,7 +282,6 @@ EXPECT_THAT(sugg.score(), Eq(9001)); EXPECT_THAT(sugg.salient_image_url(), Eq(GURL("http://localhost/foobar.jpg"))); - EXPECT_THAT(sugg.download_suggestion_extra(), IsNull()); EXPECT_THAT(sugg.notification_extra(), IsNull()); EXPECT_THAT(sugg.fetch_date(), Eq(fetch_date)); } @@ -306,7 +305,6 @@ EXPECT_THAT(sugg.publish_date().ToJavaTime(), Eq(1467284497000)); EXPECT_THAT(sugg.publisher_name(), Eq(base::UTF8ToUTF16("Foo News"))); EXPECT_THAT(sugg.score(), Eq(9001)); - EXPECT_THAT(sugg.download_suggestion_extra(), IsNull()); ASSERT_THAT(sugg.notification_extra(), NotNull()); EXPECT_THAT(sugg.notification_extra()->deadline.ToJavaTime(), Eq(1467291697000));
diff --git a/components/omnibox/browser/location_bar_model.h b/components/omnibox/browser/location_bar_model.h index 42af21c..544026f 100644 --- a/components/omnibox/browser/location_bar_model.h +++ b/components/omnibox/browser/location_bar_model.h
@@ -18,9 +18,9 @@ struct VectorIcon; } -// This class is the model used by the toolbar, location bar and autocomplete -// edit. It populates its states from the current navigation entry retrieved -// from the navigation controller returned by GetNavigationController(). +// This class provides information about the current navigation entry. +// Its methods always return data related to the current page, and does not +// account for the state of the omnibox, which is tracked by OmniboxEditModel. class LocationBarModel { public: virtual ~LocationBarModel() = default; @@ -41,9 +41,7 @@ // Returns the URL of the current navigation entry. virtual GURL GetURL() const = 0; - // Returns the security level that the toolbar should display. This reflects - // the underlying state of the page without regard to any user edits that may - // be in progress in the omnibox. + // Returns the security level that the toolbar should display. virtual security_state::SecurityLevel GetSecurityLevel() const = 0; // Returns true if the toolbar should display the search terms. When this @@ -56,20 +54,14 @@ // Returns the id of the icon to show to the left of the address, based on the // current URL. When search term replacement is active, this returns a search - // icon. This always shows the icon based on the current page's security - // state, and doesn't account for user editing, or show any specialized icons - // for input in progress. See OmniboxView::GetIcon() for those. + // icon. virtual const gfx::VectorIcon& GetVectorIcon() const = 0; // Returns text for the omnibox secure verbose chip, displayed next to the - // security icon on certain platforms. Always returns the text corresponding - // to the currently displayed page, irrespective of any user input in - // progress or displayed suggestions. + // security icon on certain platforms. virtual base::string16 GetSecureDisplayText() const = 0; - // Returns text describing the security state for accessibility. Always - // returns the text corresponding to the currently displayed page, - // irrespective of any user input in progress or displayed suggestions. + // Returns text describing the security state for accessibility. virtual base::string16 GetSecureAccessibilityText() const = 0; // Returns whether the URL for the current navigation entry should be @@ -80,18 +72,10 @@ // previously-downloaded content. virtual bool IsOfflinePage() const = 0; - // Whether the text in the omnibox is currently being edited. - void set_input_in_progress(bool input_in_progress) { - input_in_progress_ = input_in_progress; - } - bool input_in_progress() const { return input_in_progress_; } - protected: - LocationBarModel() : input_in_progress_(false) {} + LocationBarModel() = default; private: - bool input_in_progress_; - DISALLOW_COPY_AND_ASSIGN(LocationBarModel); };
diff --git a/components/safe_browsing/web_ui/safe_browsing_ui.cc b/components/safe_browsing/web_ui/safe_browsing_ui.cc index 60f878fd..340eca0 100644 --- a/components/safe_browsing/web_ui/safe_browsing_ui.cc +++ b/components/safe_browsing/web_ui/safe_browsing_ui.cc
@@ -59,12 +59,13 @@ // static bool WebUIInfoSingleton::HasListener() { - return !GetInstance()->webui_instances_.empty(); + return GetInstance()->has_test_listener_ || + !GetInstance()->webui_instances_.empty(); } void WebUIInfoSingleton::AddToClientDownloadRequestsSent( std::unique_ptr<ClientDownloadRequest> client_download_request) { - if (webui_instances_.empty()) + if (!HasListener()) return; for (auto* webui_listener : webui_instances_) @@ -80,7 +81,7 @@ void WebUIInfoSingleton::AddToClientDownloadResponsesReceived( std::unique_ptr<ClientDownloadResponse> client_download_response) { - if (webui_instances_.empty()) + if (!HasListener()) return; for (auto* webui_listener : webui_instances_) @@ -97,7 +98,7 @@ void WebUIInfoSingleton::AddToCSBRRsSent( std::unique_ptr<ClientSafeBrowsingReportRequest> csbrr) { - if (webui_instances_.empty()) + if (!HasListener()) return; for (auto* webui_listener : webui_instances_) @@ -112,7 +113,7 @@ void WebUIInfoSingleton::AddToPGEvents( const sync_pb::UserEventSpecifics& event) { - if (webui_instances_.empty()) + if (!HasListener()) return; for (auto* webui_listener : webui_instances_) @@ -127,7 +128,7 @@ int WebUIInfoSingleton::AddToPGPings( const LoginReputationClientRequest& request) { - if (webui_instances_.empty()) + if (!HasListener()) return -1; for (auto* webui_listener : webui_instances_) @@ -141,7 +142,7 @@ void WebUIInfoSingleton::AddToPGResponses( int token, const LoginReputationClientResponse& response) { - if (webui_instances_.empty()) + if (!HasListener()) return; for (auto* webui_listener : webui_instances_) @@ -156,7 +157,7 @@ } void WebUIInfoSingleton::LogMessage(const std::string& message) { - if (webui_instances_.empty()) + if (!HasListener()) return; base::Time timestamp = base::Time::Now(); @@ -176,7 +177,7 @@ void WebUIInfoSingleton::UnregisterWebUIInstance(SafeBrowsingUIHandler* webui) { base::Erase(webui_instances_, webui); - if (webui_instances_.empty()) { + if (!HasListener()) { ClearCSBRRsSent(); ClearClientDownloadRequestsSent(); ClearClientDownloadResponsesReceived();
diff --git a/components/safe_browsing/web_ui/safe_browsing_ui.h b/components/safe_browsing/web_ui/safe_browsing_ui.h index dcd3e82..23d4515 100644 --- a/components/safe_browsing/web_ui/safe_browsing_ui.h +++ b/components/safe_browsing/web_ui/safe_browsing_ui.h
@@ -251,6 +251,8 @@ return log_messages_; } + void AddListenerForTesting() { has_test_listener_ = true; } + private: WebUIInfoSingleton(); ~WebUIInfoSingleton(); @@ -301,6 +303,9 @@ // The current referrer chain provider, if any. Can be nullptr. ReferrerChainProvider* referrer_chain_provider_ = nullptr; + // Whether there is a test listener. + bool has_test_listener_ = false; + DISALLOW_COPY_AND_ASSIGN(WebUIInfoSingleton); };
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java index 1f34b1a..5009bcc 100644 --- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java +++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java
@@ -251,7 +251,12 @@ @Override public boolean hasFeatures(Account account, String[] features) { - final AccountHolder accountHolder = getAccountHolder(account); + @Nullable + AccountHolder accountHolder = tryGetAccountHolder(account); + if (accountHolder == null) { + // Features status is queried asynchronously, so the account could have been removed. + return false; + } Set<String> accountFeatures = accountHolder.getFeatures(); boolean hasAllFeatures = true; for (String feature : features) {
diff --git a/components/tracing/common/stack_sampler_android.cc b/components/tracing/common/stack_sampler_android.cc index 01a69dd..9cb2349 100644 --- a/components/tracing/common/stack_sampler_android.cc +++ b/components/tracing/common/stack_sampler_android.cc
@@ -17,6 +17,10 @@ StackSamplerAndroid::~StackSamplerAndroid() = default; +// Unimplemented. StackSamplerAndroid needs to be implemented in terms of +// base::StackSamplerImpl to make use of this. +void StackSamplerAndroid::AddAuxUnwinder(base::Unwinder* unwinder) {} + void StackSamplerAndroid::RecordStackFrames( StackBuffer* stack_buffer, base::ProfileBuilder* profile_builder) {
diff --git a/components/tracing/common/stack_sampler_android.h b/components/tracing/common/stack_sampler_android.h index 1022f3c..c8e6a6f64 100644 --- a/components/tracing/common/stack_sampler_android.h +++ b/components/tracing/common/stack_sampler_android.h
@@ -24,7 +24,8 @@ StackSamplerAndroid(const StackSamplerAndroid&) = delete; StackSamplerAndroid& operator=(const StackSamplerAndroid&) = delete; - // StackSamplingProfiler::StackSampler: + // StackSampler: + void AddAuxUnwinder(base::Unwinder* unwinder) override; void RecordStackFrames(StackBuffer* stack_buffer, base::ProfileBuilder* profile_builder) override;
diff --git a/components/tracing/common/trace_startup_config.cc b/components/tracing/common/trace_startup_config.cc index 47b396f..a8f1051 100644 --- a/components/tracing/common/trace_startup_config.cc +++ b/components/tracing/common/trace_startup_config.cc
@@ -80,13 +80,14 @@ return trace_config; } -TraceStartupConfig::TraceStartupConfig() - : is_enabled_(false), - is_enabled_from_background_tracing_(false), - trace_config_(base::trace_event::TraceConfig()), - startup_duration_(0), - should_trace_to_result_file_(false), - finished_writing_to_file_(false) { +TraceStartupConfig::TraceStartupConfig() { + auto* command_line = base::CommandLine::ForCurrentProcess(); + if (!command_line->HasSwitch(switches::kDisablePerfetto) && + command_line->GetSwitchValueASCII(switches::kTraceStartupOwner) == + "devtools") { + session_owner_ = SessionOwner::kDevToolsTracingHandler; + } + if (EnableFromCommandLine()) { DCHECK(IsEnabled()); } else if (EnableFromConfigFile()) { @@ -115,7 +116,8 @@ } bool TraceStartupConfig::IsTracingStartupForDuration() const { - return IsEnabled() && startup_duration_ > 0; + return IsEnabled() && startup_duration_ > 0 && + session_owner_ == SessionOwner::kTracingController; } base::trace_event::TraceConfig TraceStartupConfig::GetTraceConfig() const { @@ -157,6 +159,20 @@ #endif } +TraceStartupConfig::SessionOwner TraceStartupConfig::GetSessionOwner() const { + DCHECK(IsEnabled()); + return session_owner_; +} + +bool TraceStartupConfig::AttemptAdoptBySessionOwner(SessionOwner owner) { + if (IsEnabled() && GetSessionOwner() == owner && !session_adopted_) { + // The session can only be adopted once. + session_adopted_ = true; + return true; + } + return false; +} + bool TraceStartupConfig::EnableFromCommandLine() { auto* command_line = base::CommandLine::ForCurrentProcess();
diff --git a/components/tracing/common/trace_startup_config.h b/components/tracing/common/trace_startup_config.h index 675ce3e..bc132ab 100644 --- a/components/tracing/common/trace_startup_config.h +++ b/components/tracing/common/trace_startup_config.h
@@ -76,6 +76,8 @@ // TracingControllerAndroid::GenerateTracingFilePath. class TRACING_EXPORT TraceStartupConfig { public: + enum class SessionOwner { kTracingController, kDevToolsTracingHandler }; + static TraceStartupConfig* GetInstance(); // Default minimum startup trace config with enough events to debug issues. @@ -119,6 +121,13 @@ return finished_writing_to_file_; } + SessionOwner GetSessionOwner() const; + + // Called by a potential session owner to determine if it should take + // ownership of the startup tracing session and begin tracing. Returns |true| + // if the passed |owner| should adopt the session. + bool AttemptAdoptBySessionOwner(SessionOwner owner); + private: // This allows constructor and destructor to be private and usable only // by the Singleton class. @@ -136,13 +145,15 @@ bool ParseTraceConfigFileContent(const std::string& content); - bool is_enabled_; - bool is_enabled_from_background_tracing_; + bool is_enabled_ = false; + bool is_enabled_from_background_tracing_ = false; base::trace_event::TraceConfig trace_config_; - int startup_duration_; - bool should_trace_to_result_file_; + int startup_duration_ = 0; + bool should_trace_to_result_file_ = false; base::FilePath result_file_; - bool finished_writing_to_file_; + bool finished_writing_to_file_ = false; + SessionOwner session_owner_ = SessionOwner::kTracingController; + bool session_adopted_ = false; DISALLOW_COPY_AND_ASSIGN(TraceStartupConfig); };
diff --git a/components/tracing/common/tracing_switches.cc b/components/tracing/common/tracing_switches.cc index 3899cf20..26125bf 100644 --- a/components/tracing/common/tracing_switches.cc +++ b/components/tracing/common/tracing_switches.cc
@@ -54,6 +54,18 @@ // "record-until-full" mode will be used. const char kTraceStartupRecordMode[] = "trace-startup-record-mode"; +// Specifies the coordinator of the startup tracing session. If the legacy +// tracing backend is used instead of perfetto, providing this flag is not +// necessary. Valid values: 'controller', 'devtools'. Defaults to 'controller'. +// +// If 'controller' is specified, the session is controlled and stopped via the +// TracingController (e.g. to implement the timeout). +// +// If 'devtools' is specified, the startup tracing session will be owned by +// DevTools and thus can be controlled (i.e. stopped) via the DevTools Tracing +// domain on the first session connected to the browser endpoint. +const char kTraceStartupOwner[] = "trace-startup-owner"; + // Disables the perfetto tracing backend. We need a separate command line // argument from the kTracingPerfettoBackend feature, because feature flags are // parsed too late during startup for early startup tracing support.
diff --git a/components/tracing/common/tracing_switches.h b/components/tracing/common/tracing_switches.h index d81c6d0..4bc094be 100644 --- a/components/tracing/common/tracing_switches.h +++ b/components/tracing/common/tracing_switches.h
@@ -17,6 +17,7 @@ TRACING_EXPORT extern const char kTraceStartupDuration[]; TRACING_EXPORT extern const char kTraceStartupFile[]; TRACING_EXPORT extern const char kTraceStartupRecordMode[]; +TRACING_EXPORT extern const char kTraceStartupOwner[]; TRACING_EXPORT extern const char kDisablePerfetto[]; TRACING_EXPORT extern const char kPerfettoDisableInterning[]; TRACING_EXPORT extern const char kPerfettoOutputFile[];
diff --git a/components/user_manager/known_user.cc b/components/user_manager/known_user.cc index 8501c20..52c554b 100644 --- a/components/user_manager/known_user.cc +++ b/components/user_manager/known_user.cc
@@ -25,7 +25,8 @@ // placed in this list. const char kKnownUsers[] = "KnownUsers"; -// Known user preferences keys (stored in Local State). +// Known user preferences keys (stored in Local State). All keys should be +// listed in kReservedKeys below. // Key of canonical e-mail value. const char kCanonicalEmail[] = "email"; @@ -65,6 +66,20 @@ // from the local state on logout. const char kIsEphemeral[] = "is_ephemeral"; +// List containing all the known user preferences keys. +const char* kReservedKeys[] = {kCanonicalEmail, + kGAIAIdKey, + kObjGuidKey, + kAccountTypeKey, + kUsingSAMLKey, + kDeviceId, + kGAPSCookie, + kReauthReasonKey, + kGaiaIdMigration, + kMinimalMigrationAttempted, + kProfileRequiresPolicy, + kIsEphemeral}; + PrefService* GetLocalState() { if (!UserManager::IsInitialized()) return nullptr; @@ -206,13 +221,6 @@ void SetStringPref(const AccountId& account_id, const std::string& path, const std::string& in_value) { - PrefService* local_state = GetLocalState(); - - // Local State may not be initialized in tests. - if (!local_state) - return; - - ListPrefUpdate update(local_state, kKnownUsers); base::DictionaryValue dict; dict.SetString(path, in_value); UpdatePrefs(account_id, dict, false); @@ -231,13 +239,6 @@ void SetBooleanPref(const AccountId& account_id, const std::string& path, const bool in_value) { - PrefService* local_state = GetLocalState(); - - // Local State may not be initialized in tests. - if (!local_state) - return; - - ListPrefUpdate update(local_state, kKnownUsers); base::DictionaryValue dict; dict.SetBoolean(path, in_value); UpdatePrefs(account_id, dict, false); @@ -255,18 +256,47 @@ void SetIntegerPref(const AccountId& account_id, const std::string& path, const int in_value) { - PrefService* local_state = GetLocalState(); - - // Local State may not be initialized in tests. - if (!local_state) - return; - - ListPrefUpdate update(local_state, kKnownUsers); base::DictionaryValue dict; dict.SetInteger(path, in_value); UpdatePrefs(account_id, dict, false); } +bool GetPref(const AccountId& account_id, + const std::string& path, + const base::Value** out_value) { + const base::DictionaryValue* user_pref_dict = nullptr; + if (!FindPrefs(account_id, &user_pref_dict)) + return false; + + *out_value = user_pref_dict->FindPath(path); + return *out_value != nullptr; +} + +void SetPref(const AccountId& account_id, + const std::string& path, + base::Value in_value) { + base::DictionaryValue dict; + dict.SetPath(path, std::move(in_value)); + UpdatePrefs(account_id, dict, false); +} + +void RemovePref(const AccountId& account_id, const std::string& path) { + // Prevent removing keys that are used internally. + for (const std::string& key : kReservedKeys) + CHECK_NE(path, key); + + const base::DictionaryValue* user_pref_dict = nullptr; + if (!FindPrefs(account_id, &user_pref_dict)) + return; + + base::Value updated_user_pref = user_pref_dict->Clone(); + base::DictionaryValue* updated_user_pref_dict; + updated_user_pref.GetAsDictionary(&updated_user_pref_dict); + + updated_user_pref_dict->RemovePath(path); + UpdatePrefs(account_id, *updated_user_pref_dict, true); +} + AccountId GetAccountId(const std::string& user_email, const std::string& id, const AccountType& account_type) {
diff --git a/components/user_manager/known_user.h b/components/user_manager/known_user.h index a76f7faa..1c65bf88 100644 --- a/components/user_manager/known_user.h +++ b/components/user_manager/known_user.h
@@ -16,6 +16,7 @@ namespace base { class DictionaryValue; +class Value; } namespace user_manager { @@ -68,6 +69,21 @@ const std::string& path, const int in_value); +// Returns true if |account_id| preference by |path| does exist, +// fills in |out_value|. Otherwise returns false. +bool USER_MANAGER_EXPORT GetPref(const AccountId& account_id, + const std::string& path, + const base::Value** out_value); + +// Updates user's identified by |account_id| value preference |path|. +void USER_MANAGER_EXPORT SetPref(const AccountId& account_id, + const std::string& path, + base::Value in_value); + +// Removes user's identified by |account_id| preference |path|. +void USER_MANAGER_EXPORT RemovePref(const AccountId& account_id, + const std::string& path); + // Returns the list of known AccountIds. std::vector<AccountId> USER_MANAGER_EXPORT GetKnownAccountIds();
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc index abdfcd6f..ea93536a 100644 --- a/components/viz/service/display/renderer_pixeltest.cc +++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -1111,6 +1111,8 @@ cc::FuzzyPixelOffByOneComparator(true))); } +// TODO(crbug.com/924369): SkiaRenderer should not ignore the color matrix on +// the OutputSurface. TYPED_TEST(GLOnlyRendererPixelTest, SolidColorWithTemperature) { gfx::Rect rect(this->device_viewport_size_); @@ -1137,6 +1139,8 @@ cc::FuzzyPixelOffByOneComparator(true))); } +// TODO(crbug.com/924369): SkiaRenderer should not ignore the color matrix on +// the OutputSurface. TYPED_TEST(GLOnlyRendererPixelTest, SolidColorWithTemperature_NonRootRenderPass) { // Create a root and a child passes with two different solid color quads. @@ -1179,7 +1183,7 @@ cc::FuzzyPixelOffByOneComparator(true))); } -TYPED_TEST(GLOnlyRendererPixelTest, +TYPED_TEST(GLCapableRendererPixelTest, PremultipliedTextureWithBackgroundAndVertexOpacity) { gfx::Rect rect(this->device_viewport_size_); @@ -4247,7 +4251,7 @@ cc::FuzzyPixelOffByOneComparator(true))); } -TYPED_TEST(GLOnlyRendererPixelTest, TileQuadClamping) { +TYPED_TEST(GLCapableRendererPixelTest, TileQuadClamping) { gfx::Rect viewport(this->device_viewport_size_); bool swizzle_contents = true; bool contents_premultiplied = true; @@ -4371,7 +4375,7 @@ } } -TYPED_TEST(GLOnlyRendererPixelTest, RoundedCornerSimpleTextureDrawQuad) { +TYPED_TEST(GLCapableRendererPixelTest, RoundedCornerSimpleTextureDrawQuad) { gfx::Rect viewport_rect(this->device_viewport_size_); constexpr int kInset = 20; constexpr int kCornerRadius = 20; @@ -4424,10 +4428,22 @@ RenderPassList pass_list; pass_list.push_back(std::move(root_pass)); - EXPECT_TRUE(this->RunPixelTest( - &pass_list, - base::FilePath(FILE_PATH_LITERAL("rounded_corner_simple.png")), - cc::ExactPixelComparator(true))); + if (std::is_same<TypeParam, GLRenderer>() || + std::is_same<TypeParam, cc::GLRendererWithExpandedViewport>()) { + // GL Renderer should have an exact match as that is the reference point. + EXPECT_TRUE(this->RunPixelTest( + &pass_list, + base::FilePath(FILE_PATH_LITERAL("rounded_corner_simple.png")), + cc::ExactPixelComparator(true))); + } else { + // SkiaRenderer uses skia rrect to create rounded corner clip. This results + // in a different corner path due to a different anti aliasing approach than + // the fragment shader in gl renderer. + EXPECT_TRUE(this->RunPixelTest( + &pass_list, + base::FilePath(FILE_PATH_LITERAL("rounded_corner_simple.png")), + cc::FuzzyPixelComparator(true, 0.6f, 0.f, 255.f, 255, 0))); + } } // This draws a render pass with 2 solid color quads one of which has a rounded
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc b/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc index 6b3c548..61a11a4e 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc
@@ -500,17 +500,7 @@ "with display usage."; return nullptr; } - if (!sk_surface_) { - // Create a dummy sk surface to make SharedImage happy. - // TODO(penghuang): remove the dummy sk surface when BeginReadAccess() - // doesn't need pass in a sk surface. - auto image_info = - SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kPremul_SkAlphaType); - sk_surface_ = SkSurface::MakeRenderTarget( - gr_context(), SkBudgeted::kNo, image_info, 0 /* sampleCount */, - kBottomLeft_GrSurfaceOrigin, nullptr /* surfaceProps */); - } - auto promise_texture = representation->BeginReadAccess(sk_surface_.get()); + auto promise_texture = representation->BeginReadAccess(); if (!promise_texture) { DLOG(ERROR) << "Failed to begin read access for SharedImageRepresentationSkia";
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 91e70c5..7416ad1 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -679,8 +679,7 @@ *shared_image_out = std::move(shared_image); } if (*shared_image_out) { - auto promise_texture = - (*shared_image_out)->BeginReadAccess(output_sk_surface()); + auto promise_texture = (*shared_image_out)->BeginReadAccess(); DLOG_IF(ERROR, !promise_texture) << "Failed to begin read access for SharedImageRepresentationSkia"; return promise_texture;
diff --git a/content/DEPS b/content/DEPS index b010e3e..c33d096 100644 --- a/content/DEPS +++ b/content/DEPS
@@ -16,7 +16,7 @@ "-components", # Content can depend on components that are: - # 1) related to the implementation of the web platform + # 1) related to the implementation of the web platform, or, # 2) shared code between third_party/blink and content # It should not depend on chrome features or implementation details, i.e. the # original components/ directories which was code split out from chrome/ to be
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 9168181a..ff63c8a 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -303,11 +303,6 @@ } #endif // defined(USE_GLIB) -void OnStoppedStartupTracing(const base::FilePath& trace_file) { - VLOG(0) << "Completed startup tracing to " << trace_file.value(); - tracing::TraceStartupConfig::GetInstance()->OnTraceToResultFileFinished(); -} - // Tell compiler not to inline this function so it's possible to tell what // thread was unresponsive by inspecting the callstack. NOINLINE void ResetThread_IO( @@ -1203,10 +1198,6 @@ #endif } -void BrowserMainLoop::StopStartupTracingTimer() { - startup_trace_timer_.Stop(); -} - void BrowserMainLoop::InitializeMainThread() { TRACE_EVENT0("startup", "BrowserMainLoop::InitializeMainThread"); base::PlatformThread::SetName("CrBrowserMain"); @@ -1617,25 +1608,9 @@ // Start startup tracing through TracingController's interface. TraceLog has // been enabled in content_main_runner where threads are not available. Now We // need to start tracing for all other tracing agents, which require threads. - auto* trace_startup_config = tracing::TraceStartupConfig::GetInstance(); - if (trace_startup_config->IsEnabled()) { - // This checks kTraceConfigFile switch. - TracingController::GetInstance()->StartTracing( - trace_startup_config->GetTraceConfig(), - TracingController::StartTracingDoneCallback()); - } else if (parsed_command_line_.HasSwitch(switches::kTraceToConsole)) { - TracingController::GetInstance()->StartTracing( - tracing::GetConfigForTraceToConsole(), - TracingController::StartTracingDoneCallback()); - } - // Start tracing to a file for certain duration if needed. Only do this after - // starting the main message loop to avoid calling - // MessagePumpForUI::ScheduleWork() before MessagePumpForUI::Start() as it - // will crash the browser. - if (trace_startup_config->IsTracingStartupForDuration()) { - TRACE_EVENT0("startup", "BrowserMainLoop::InitStartupTracingForDuration"); - InitStartupTracingForDuration(); - } + // We can only do this after starting the main message loop to avoid calling + // MessagePumpForUI::ScheduleWork() before MessagePumpForUI::Start(). + TracingControllerImpl::GetInstance()->StartStartupTracingIfNeeded(); if (parts_) { parts_->ServiceManagerConnectionStarted( @@ -1647,46 +1622,6 @@ #endif } -base::FilePath BrowserMainLoop::GetStartupTraceFileName() const { - base::FilePath trace_file; - - trace_file = tracing::TraceStartupConfig::GetInstance()->GetResultFile(); - if (trace_file.empty()) { -#if defined(OS_ANDROID) - TracingControllerAndroid::GenerateTracingFilePath(&trace_file); -#else - // Default to saving the startup trace into the current dir. - trace_file = base::FilePath().AppendASCII("chrometrace.log"); -#endif - } - - return trace_file; -} - -void BrowserMainLoop::InitStartupTracingForDuration() { - DCHECK(tracing::TraceStartupConfig::GetInstance() - ->IsTracingStartupForDuration()); - - startup_trace_file_ = GetStartupTraceFileName(); - - startup_trace_timer_.Start( - FROM_HERE, - base::TimeDelta::FromSeconds( - tracing::TraceStartupConfig::GetInstance()->GetStartupDuration()), - this, &BrowserMainLoop::EndStartupTracing); -} - -void BrowserMainLoop::EndStartupTracing() { - // Do nothing if startup tracing is already stopped. - if (!tracing::TraceStartupConfig::GetInstance()->IsEnabled()) - return; - - TracingController::GetInstance()->StopTracing( - TracingController::CreateFileEndpoint( - startup_trace_file_, - base::Bind(OnStoppedStartupTracing, startup_trace_file_))); -} - void BrowserMainLoop::InitializeAudio() { DCHECK(!audio_manager_);
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h index 24cca0cf..d7939ebb 100644 --- a/content/browser/browser_main_loop.h +++ b/content/browser/browser_main_loop.h
@@ -12,7 +12,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/task/task_scheduler/task_scheduler.h" -#include "base/timer/timer.h" #include "build/build_config.h" #include "content/browser/browser_process_sub_thread.h" #include "content/public/browser/browser_main_runner.h" @@ -33,7 +32,6 @@ namespace base { class CommandLine; -class FilePath; class HighResolutionTimerManager; class MemoryPressureMonitor; class PowerMonitor; @@ -196,12 +194,6 @@ } midi::MidiService* midi_service() const { return midi_service_.get(); } - base::FilePath GetStartupTraceFileName() const; - - const base::FilePath& startup_trace_file() const { - return startup_trace_file_; - } - // Returns the task runner for tasks that that are critical to producing a new // CompositorFrame on resize. On Mac this will be the task runner provided by // WindowResizeHelperMac, on other platforms it will just be the thread task @@ -239,8 +231,6 @@ void GetCompositingModeReporter( viz::mojom::CompositingModeReporterRequest request); - void StopStartupTracingTimer(); - #if defined(OS_MACOSX) && !defined(OS_IOS) media::DeviceMonitorMac* device_monitor_mac() const { return device_monitor_mac_.get(); @@ -271,8 +261,6 @@ void MainMessageLoopRun(); void InitializeMojo(); - void InitStartupTracingForDuration(); - void EndStartupTracing(); void InitializeAudio(); @@ -295,7 +283,6 @@ // PostCreateThreads() // BrowserThreadsStarted() // InitializeMojo() - // InitStartupTracingForDuration() // PreMainMessageLoopRun() // Members initialized on construction --------------------------------------- @@ -335,12 +322,6 @@ std::unique_ptr<ScreenOrientationDelegate> screen_orientation_delegate_; #endif - // Members initialized in |InitStartupTracingForDuration()| ------------------ - base::FilePath startup_trace_file_; - - // This timer initiates trace file saving. - base::OneShotTimer startup_trace_timer_; - // Members initialized in |Init()| ------------------------------------------- // Destroy |parts_| before |main_message_loop_| (required) and before other // classes constructed in content (but after |main_thread_|).
diff --git a/content/browser/browser_main_runner_impl.cc b/content/browser/browser_main_runner_impl.cc index bfc7649..db743ae 100644 --- a/content/browser/browser_main_runner_impl.cc +++ b/content/browser/browser_main_runner_impl.cc
@@ -25,6 +25,7 @@ #include "content/browser/browser_main_loop.h" #include "content/browser/browser_shutdown_profile_dumper.h" #include "content/browser/notification_service_impl.h" +#include "content/browser/tracing/tracing_controller_impl.h" #include "content/common/content_switches_internal.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" @@ -180,26 +181,9 @@ main_loop_->PreShutdown(); - // If startup tracing has not been finished yet, replace it's dumper - // with special version, which would save trace file on exit (i.e. - // startup tracing becomes a version of shutdown tracing). - // There are two cases: - // 1. Startup duration is not reached. - // 2. Or if the trace should be saved to file for --trace-config-file flag. - std::unique_ptr<BrowserShutdownProfileDumper> startup_profiler; - if (tracing::TraceStartupConfig::GetInstance() - ->IsTracingStartupForDuration()) { - main_loop_->StopStartupTracingTimer(); - if (main_loop_->startup_trace_file() != - base::FilePath().AppendASCII("none")) { - startup_profiler.reset( - new BrowserShutdownProfileDumper(main_loop_->startup_trace_file())); - } - } else if (tracing::TraceStartupConfig::GetInstance() - ->ShouldTraceToResultFile()) { - base::FilePath result_file = main_loop_->GetStartupTraceFileName(); - startup_profiler.reset(new BrowserShutdownProfileDumper(result_file)); - } + // Finalize the startup tracing session if it is still active. + std::unique_ptr<BrowserShutdownProfileDumper> startup_profiler = + TracingControllerImpl::GetInstance()->FinalizeStartupTracingIfNeeded(); // The shutdown tracing got enabled in AttemptUserExit earlier, but someone // needs to write the result to disc. For that a dumper needs to get created
diff --git a/content/browser/devtools/protocol/tracing_handler.cc b/content/browser/devtools/protocol/tracing_handler.cc index 6b4d0e6..326069bf 100644 --- a/content/browser/devtools/protocol/tracing_handler.cc +++ b/content/browser/devtools/protocol/tracing_handler.cc
@@ -24,6 +24,7 @@ #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/trace_event_impl.h" #include "base/trace_event/tracing_agent.h" +#include "build/build_config.h" #include "components/tracing/common/trace_startup_config.h" #include "content/browser/devtools/devtools_agent_host_impl.h" #include "content/browser/devtools/devtools_frame_trace_recorder.h" @@ -41,7 +42,10 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h" +#include "services/tracing/public/cpp/perfetto/perfetto_config.h" +#include "services/tracing/public/cpp/tracing_features.h" #include "services/tracing/public/mojom/constants.mojom.h" +#include "services/tracing/public/mojom/perfetto_service.mojom.h" #ifdef OS_ANDROID #include "content/browser/renderer_host/compositor_impl_android.h" @@ -122,7 +126,7 @@ } private: - ~DevToolsTraceEndpointProxy() override {} + ~DevToolsTraceEndpointProxy() override = default; base::WeakPtr<TracingHandler> tracing_handler_; }; @@ -160,7 +164,7 @@ } private: - ~DevToolsStreamEndpoint() override {} + ~DevToolsStreamEndpoint() override = default; scoped_refptr<DevToolsStreamFile> stream_; base::WeakPtr<TracingHandler> tracing_handler_; @@ -208,8 +212,270 @@ } } +// We currently don't support concurrent tracing sessions, but are planning to. +// For the time being, we're using this flag as a workaround to prevent devtools +// users from accidentally starting two concurrent sessions. +// TODO(eseckler): Remove once we add support for concurrent sessions to the +// perfetto backend. +static bool g_any_agent_tracing = false; + } // namespace +class TracingHandler::TracingSession { + public: + TracingSession() = default; + virtual ~TracingSession() = default; + + virtual void EnableTracing( + const base::trace_event::TraceConfig& chrome_config, + base::OnceClosure on_recording_enabled_callback) = 0; + virtual void AdoptStartupTracingSession() = 0; + virtual void ChangeTraceConfig( + const base::trace_event::TraceConfig& chrome_config) = 0; + virtual void DisableTracing( + bool use_proto_format, + const std::string& agent_label, + const scoped_refptr<TracingController::TraceDataEndpoint>& endpoint) = 0; + virtual void GetBufferUsage( + base::OnceCallback<void(float percent_full, + size_t approximate_event_count)> + on_buffer_usage_callback) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(TracingSession); +}; + +class TracingHandler::LegacyTracingSession + : public TracingHandler::TracingSession { + public: + void EnableTracing(const base::trace_event::TraceConfig& chrome_config, + base::OnceClosure on_recording_enabled_callback) override { + DCHECK(!TracingController::GetInstance()->IsTracing()); + TracingController::GetInstance()->StartTracing( + chrome_config, std::move(on_recording_enabled_callback)); + } + + void AdoptStartupTracingSession() override { + // Nothing to do for legacy tracing here (tracing is already active). + DCHECK(TracingController::GetInstance()->IsTracing()); + } + + void ChangeTraceConfig( + const base::trace_event::TraceConfig& chrome_config) override { + TracingController::GetInstance()->StartTracing( + chrome_config, TracingController::StartTracingDoneCallback()); + } + + void DisableTracing(bool use_proto_format, + const std::string& agent_label, + const scoped_refptr<TracingController::TraceDataEndpoint>& + endpoint) override { + DCHECK(!use_proto_format); + TracingController::GetInstance()->StopTracing(endpoint, agent_label); + } + + void GetBufferUsage(base::OnceCallback<void(float percent_full, + size_t approximate_event_count)> + on_buffer_usage_callback) override { + TracingController::GetInstance()->GetTraceBufferUsage( + std::move(on_buffer_usage_callback)); + } +}; + +class TracingHandler::PerfettoTracingSession + : public TracingHandler::TracingSession, + public tracing::mojom::TracingSession, + public mojo::DataPipeDrainer::Client { + public: + ~PerfettoTracingSession() override { +#if DCHECK_IS_ON() + DCHECK(!tracing_active_); +#endif + } + + // TracingHandler::TracingSession implementation: + void EnableTracing(const base::trace_event::TraceConfig& chrome_config, + base::OnceClosure on_recording_enabled_callback) override { +#if DCHECK_IS_ON() + DCHECK(!tracing_active_); + tracing_active_ = true; +#endif + ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( + tracing::mojom::kServiceName, &consumer_host_); + + perfetto::TraceConfig perfetto_config = + CreatePerfettoConfiguration(chrome_config); + + tracing::mojom::TracingSessionPtr tracing_session; + binding_.Bind(mojo::MakeRequest(&tracing_session)); + binding_.set_connection_error_handler( + base::BindOnce(&PerfettoTracingSession::OnTracingSessionEnded, + base::Unretained(this))); + + on_recording_enabled_callback_ = std::move(on_recording_enabled_callback); + consumer_host_->EnableTracing(std::move(tracing_session), + std::move(perfetto_config)); + } + + void AdoptStartupTracingSession() override { + // Start a perfetto tracing session, which will claim startup tracing data. + DCHECK(!TracingController::GetInstance()->IsTracing()); + waiting_for_startup_tracing_enabled_ = true; + EnableTracing( + tracing::TraceStartupConfig::GetInstance()->GetTraceConfig(), + base::BindOnce(&PerfettoTracingSession::OnStartupTracingEnabled, + base::Unretained(this))); + } + + void ChangeTraceConfig( + const base::trace_event::TraceConfig& chrome_config) override { + auto perfetto_config = CreatePerfettoConfiguration(chrome_config); + consumer_host_->ChangeTraceConfig(perfetto_config); + } + + void DisableTracing(bool use_proto_format, + const std::string& agent_label, + const scoped_refptr<TracingController::TraceDataEndpoint>& + endpoint) override { + if (waiting_for_startup_tracing_enabled_) { + pending_disable_tracing_task_ = base::BindOnce( + &PerfettoTracingSession::DisableTracing, base::Unretained(this), + use_proto_format, agent_label, endpoint); + return; + } + use_proto_format_ = use_proto_format; + agent_label_ = agent_label; + endpoint_ = endpoint; +#if DCHECK_IS_ON() + tracing_active_ = false; +#endif + + if (!use_proto_format_) { + mojo::DataPipe data_pipe; + drainer_ = std::make_unique<mojo::DataPipeDrainer>( + this, std::move(data_pipe.consumer_handle)); + consumer_host_->DisableTracingAndEmitJson( + agent_label_, std::move(data_pipe.producer_handle), + base::BindOnce(&PerfettoTracingSession::OnReadBuffersComplete, + base::Unretained(this))); + } else { + // The host will close the TracingSession connection, calling + // OnTracingSessionEnded(), once tracing was disabled. + consumer_host_->DisableTracing(); + } + } + + void GetBufferUsage(base::OnceCallback<void(float percent_full, + size_t approximate_event_count)> + on_buffer_usage_callback) override { + DCHECK(on_buffer_usage_callback); + consumer_host_->RequestBufferUsage(base::BindOnce( + &PerfettoTracingSession::OnBufferUsage, base::Unretained(this), + std::move(on_buffer_usage_callback))); + } + + void OnBufferUsage(base::OnceCallback<void(float percent_full, + size_t approximate_event_count)> + on_buffer_usage_callback, + bool success, + float percent_full) { + if (!success) { + std::move(on_buffer_usage_callback).Run(0.0f, 0); + return; + } + std::move(on_buffer_usage_callback).Run(percent_full, 0); + } + + // tracing::mojom::TracingSession implementation: + void OnTracingEnabled() override { + if (on_recording_enabled_callback_) { + std::move(on_recording_enabled_callback_).Run(); + } + } + + private: + perfetto::TraceConfig CreatePerfettoConfiguration( + const base::trace_event::TraceConfig& chrome_config) { +#if DCHECK_IS_ON() + base::trace_event::TraceConfig processfilter_stripped_config(chrome_config); + processfilter_stripped_config.SetProcessFilterConfig( + base::trace_event::TraceConfig::ProcessFilterConfig()); + + // Ensure that the process filter is the only thing that gets changed + // in a configuration during a tracing session. + DCHECK((last_config_for_perfetto_.ToString() == + base::trace_event::TraceConfig().ToString()) || + (last_config_for_perfetto_.ToString() == + processfilter_stripped_config.ToString())); + last_config_for_perfetto_ = std::move(processfilter_stripped_config); +#endif + + return tracing::GetDefaultPerfettoConfig(chrome_config); + } + + void OnStartupTracingEnabled() { + waiting_for_startup_tracing_enabled_ = false; + if (pending_disable_tracing_task_) + std::move(pending_disable_tracing_task_).Run(); + } + + void OnTracingSessionEnded() { + // If we're converting to JSON, we will receive the data via + // ConsumerHost::DisableTracingAndEmitJson(). + if (!use_proto_format_) + return; + + DCHECK(agent_label_.empty()); + mojo::DataPipe data_pipe; + drainer_ = std::make_unique<mojo::DataPipeDrainer>( + this, std::move(data_pipe.consumer_handle)); + consumer_host_->ReadBuffers( + std::move(data_pipe.producer_handle), + base::BindOnce(&PerfettoTracingSession::OnReadBuffersComplete, + base::Unretained(this))); + } + + // mojo::DataPipeDrainer::Client implementation: + void OnDataAvailable(const void* data, size_t num_bytes) override { + auto data_string = std::make_unique<std::string>( + reinterpret_cast<const char*>(data), num_bytes); + endpoint_->ReceiveTraceChunk(std::move(data_string)); + } + + void OnDataComplete() override { + data_complete_ = true; + MaybeTraceComplete(); + } + + void OnReadBuffersComplete() { + read_buffers_complete_ = true; + MaybeTraceComplete(); + } + + void MaybeTraceComplete() { + if (read_buffers_complete_ && data_complete_) + endpoint_->ReceiveTraceFinalContents(nullptr); + } + + mojo::Binding<tracing::mojom::TracingSession> binding_{this}; + tracing::mojom::ConsumerHostPtr consumer_host_; + + bool use_proto_format_; + std::string agent_label_; + base::OnceClosure on_recording_enabled_callback_; + base::OnceClosure pending_disable_tracing_task_; + bool waiting_for_startup_tracing_enabled_ = false; + scoped_refptr<TracingController::TraceDataEndpoint> endpoint_; + std::unique_ptr<mojo::DataPipeDrainer> drainer_; + bool data_complete_ = false; + bool read_buffers_complete_ = false; + +#if DCHECK_IS_ON() + bool tracing_active_ = false; + base::trace_event::TraceConfig last_config_for_perfetto_; +#endif +}; + TracingHandler::TracingHandler(FrameTreeNode* frame_tree_node_, DevToolsIOContext* io_context, bool use_binary_protocol) @@ -233,6 +499,20 @@ std::make_unique<DevToolsVideoConsumer>(base::BindRepeating( &TracingHandler::OnFrameFromVideoConsumer, base::Unretained(this))); } + + auto* startup_config = tracing::TraceStartupConfig::GetInstance(); + // Check if we should adopt the startup tracing session. Only the first + // session connected to the browser endpoint can own it. + if (frame_tree_node_ != nullptr || + !startup_config->AttemptAdoptBySessionOwner( + tracing::TraceStartupConfig::SessionOwner::kDevToolsTracingHandler)) { + return; + } + + DCHECK(tracing::TracingUsesPerfettoBackend()); + session_ = std::make_unique<PerfettoTracingSession>(); + session_->AdoptStartupTracingSession(); + g_any_agent_tracing = true; } TracingHandler::~TracingHandler() = default; @@ -257,7 +537,7 @@ } Response TracingHandler::Disable() { - if (did_initiate_recording_) + if (session_) StopTracing(nullptr, ""); return Response::OK(); } @@ -297,6 +577,7 @@ DCHECK(!trace_data_buffer_state_.in_string); DCHECK(!trace_data_buffer_state_.slashed); + session_.reset(); frontend_->TracingComplete(); } @@ -359,16 +640,20 @@ } void TracingHandler::OnTraceToStreamComplete(const std::string& stream_handle) { + session_.reset(); + std::string stream_format = (proto_format_ ? Tracing::StreamFormatEnum::Proto + : Tracing::StreamFormatEnum::Json); std::string stream_compression = (gzip_compression_ ? Tracing::StreamCompressionEnum::Gzip : Tracing::StreamCompressionEnum::None); - frontend_->TracingComplete(stream_handle, stream_compression); + frontend_->TracingComplete(stream_handle, stream_format, stream_compression); } void TracingHandler::Start(Maybe<std::string> categories, Maybe<std::string> options, Maybe<double> buffer_usage_reporting_interval, Maybe<std::string> transfer_mode, + Maybe<std::string> transfer_format, Maybe<std::string> transfer_compression, Maybe<Tracing::TraceConfig> config, std::unique_ptr<StartCallback> callback) { @@ -376,13 +661,29 @@ Tracing::Start::TransferModeEnum::ReturnAsStream; bool gzip_compression = transfer_compression.fromMaybe("") == Tracing::StreamCompressionEnum::Gzip; + bool proto_format = + transfer_format.fromMaybe("") == Tracing::StreamFormatEnum::Proto; + + if (proto_format && !tracing::TracingUsesPerfettoBackend()) { + callback->sendFailure(Response::Error( + "Proto format is only supported with the perfetto backend.")); + return; + } + + if (proto_format && !return_as_stream) { + callback->sendFailure(Response::Error( + "Proto format is only supported when using stream transfer mode.")); + return; + } + if (IsTracing()) { if (!did_initiate_recording_ && IsStartupTracingActive()) { // If tracing is already running because it was initiated by startup - // tracing, honor the transfer mode update, as that's the only way + // tracing, honor the transfer mode/format update, as that's the only way // for the client to communicate it. return_as_stream_ = return_as_stream; gzip_compression_ = gzip_compression; + proto_format_ = proto_format; } callback->sendFailure(Response::Error("Tracing is already started")); return; @@ -398,6 +699,7 @@ did_initiate_recording_ = true; return_as_stream_ = return_as_stream; gzip_compression_ = gzip_compression; + proto_format_ = proto_format; buffer_usage_reporting_interval_ = buffer_usage_reporting_interval.fromMaybe(0); @@ -439,10 +741,16 @@ SetupProcessFilter(gpu_pid, nullptr); - TracingController::GetInstance()->StartTracing( + if (tracing::TracingUsesPerfettoBackend()) { + session_ = std::make_unique<PerfettoTracingSession>(); + } else { + session_ = std::make_unique<LegacyTracingSession>(); + } + session_->EnableTracing( trace_config_, base::BindOnce(&TracingHandler::OnRecordingEnabled, weak_factory_.GetWeakPtr(), std::move(callback))); + g_any_agent_tracing = true; } void TracingHandler::SetupProcessFilter( @@ -492,15 +800,21 @@ trace_config_.SetProcessFilterConfig( base::trace_event::TraceConfig::ProcessFilterConfig( included_process_ids)); - TracingController::GetInstance()->StartTracing( - trace_config_, TracingController::StartTracingDoneCallback()); + session_->ChangeTraceConfig(trace_config_); } Response TracingHandler::End() { // Startup tracing triggered by --trace-config-file is a special case, where // tracing is started automatically upon browser startup and can be stopped // via DevTools. - if (!did_initiate_recording_ && !IsStartupTracingActive()) + // TODO(eseckler): Remove this when we remove the legacy tracing backend. + if (!tracing::TracingUsesPerfettoBackend() && IsStartupTracingActive()) { + DCHECK(!session_ && !did_initiate_recording_); + session_ = std::make_unique<LegacyTracingSession>(); + session_->AdoptStartupTracingSession(); + } + + if (!session_) return Response::Error("Tracing is not started"); scoped_refptr<TracingController::TraceDataEndpoint> endpoint; @@ -526,6 +840,7 @@ void TracingHandler::GetCategories( std::unique_ptr<GetCategoriesCallback> callback) { + // TODO(eseckler): Support this via the perfetto service too. TracingController::GetInstance()->GetCategories( base::BindOnce(&TracingHandler::OnCategoriesReceived, weak_factory_.GetWeakPtr(), std::move(callback))); @@ -638,24 +953,29 @@ buffer_usage_poll_timer_.reset(new base::RepeatingTimer()); buffer_usage_poll_timer_->Start( FROM_HERE, interval, - base::Bind(base::IgnoreResult(&TracingController::GetTraceBufferUsage), - base::Unretained(TracingController::GetInstance()), - base::Bind(&TracingHandler::OnBufferUsage, - weak_factory_.GetWeakPtr()))); + base::BindRepeating(&TracingHandler::UpdateBufferUsage, + weak_factory_.GetWeakPtr())); +} + +void TracingHandler::UpdateBufferUsage() { + session_->GetBufferUsage(base::BindOnce(&TracingHandler::OnBufferUsage, + weak_factory_.GetWeakPtr())); } void TracingHandler::StopTracing( const scoped_refptr<TracingController::TraceDataEndpoint>& endpoint, const std::string& agent_label) { + DCHECK(session_); buffer_usage_poll_timer_.reset(); - TracingController::GetInstance()->StopTracing(endpoint, agent_label); + session_->DisableTracing(proto_format_, agent_label, endpoint); did_initiate_recording_ = false; + g_any_agent_tracing = false; if (video_consumer_) video_consumer_->StopCapture(); } bool TracingHandler::IsTracing() const { - return TracingController::GetInstance()->IsTracing(); + return TracingController::GetInstance()->IsTracing() || g_any_agent_tracing; } void TracingHandler::EmitFrameTree() { @@ -693,8 +1013,7 @@ SetupProcessFilter(base::kNullProcessId, navigation_handle->GetRenderFrameHost()); - TracingController::GetInstance()->StartTracing( - trace_config_, TracingController::StartTracingDoneCallback()); + session_->ChangeTraceConfig(trace_config_); } void TracingHandler::FrameDeleted(RenderFrameHostImpl* frame_host) {
diff --git a/content/browser/devtools/protocol/tracing_handler.h b/content/browser/devtools/protocol/tracing_handler.h index 5c05b31..2584945 100644 --- a/content/browser/devtools/protocol/tracing_handler.h +++ b/content/browser/devtools/protocol/tracing_handler.h
@@ -67,6 +67,7 @@ Maybe<std::string> options, Maybe<double> buffer_usage_reporting_interval, Maybe<std::string> transfer_mode, + Maybe<std::string> transfer_format, Maybe<std::string> transfer_compression, Maybe<Tracing::TraceConfig> config, std::unique_ptr<StartCallback> callback) override; @@ -83,6 +84,10 @@ private: friend class TracingHandlerTest; + class TracingSession; + class LegacyTracingSession; + class PerfettoTracingSession; + struct TraceDataBufferState { public: std::string data; @@ -108,6 +113,7 @@ const std::string& trace_fragment); void SetupTimer(double usage_reporting_interval); + void UpdateBufferUsage(); void StopTracing( const scoped_refptr<TracingController::TraceDataEndpoint>& endpoint, const std::string& agent_label); @@ -133,11 +139,13 @@ bool did_initiate_recording_; bool return_as_stream_; bool gzip_compression_; + bool proto_format_; double buffer_usage_reporting_interval_; TraceDataBufferState trace_data_buffer_state_; std::unique_ptr<DevToolsVideoConsumer> video_consumer_; int number_of_screenshots_from_video_consumer_ = 0; base::trace_event::TraceConfig trace_config_; + std::unique_ptr<TracingSession> session_; base::WeakPtrFactory<TracingHandler> weak_factory_; FRIEND_TEST_ALL_PREFIXES(TracingHandlerTest,
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc index 889191d..5eb56c0 100644 --- a/content/browser/frame_host/navigation_controller_impl_unittest.cc +++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -732,14 +732,12 @@ const GURL url1("http://foo1"); - controller.LoadURL( - url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); - int entry_id = controller.GetPendingEntry()->GetUniqueID(); + auto navigation1 = + NavigationSimulator::CreateBrowserInitiated(url1, contents()); + navigation1->Start(); EXPECT_EQ(0U, navigation_entry_changed_counter_); EXPECT_EQ(0U, navigation_list_pruned_counter_); - main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigateWithTransition( - entry_id, true, url1, ui::PAGE_TRANSITION_TYPED); + navigation1->Commit(); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -750,12 +748,10 @@ const std::string new_extra_headers("Foo: Bar\nBar: Baz"); controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, new_extra_headers); - entry_id = controller.GetPendingEntry()->GetUniqueID(); + auto navigation2 = NavigationSimulator::CreateFromPending(contents()); EXPECT_EQ(0U, navigation_entry_changed_counter_); EXPECT_EQ(0U, navigation_list_pruned_counter_); - main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigateWithTransition( - entry_id, false, url1, ui::PAGE_TRANSITION_TYPED); + navigation2->Commit(); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -1988,29 +1984,22 @@ EXPECT_EQ(nullptr, controller_impl().GetPendingEntry()); // Start a load of the same page again. - controller.LoadURL( - url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + auto navigation1 = + NavigationSimulatorImpl::CreateBrowserInitiated(url1, contents()); + navigation1->ReadyToCommit(); int entry_id1 = controller.GetPendingEntry()->GetUniqueID(); - // Immediately start loading a different page... - controller.LoadURL( - url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + // Before it can commit, start loading a different page... + auto navigation2 = + NavigationSimulator::CreateBrowserInitiated(url2, contents()); + navigation2->ReadyToCommit(); int entry_id2 = controller.GetPendingEntry()->GetUniqueID(); EXPECT_NE(entry_id1, entry_id2); // ... and now the renderer sends a commit for the first navigation. - FrameHostMsg_DidCommitProvisionalLoad_Params params; - params.nav_entry_id = entry_id1; - params.intended_as_new_entry = true; - params.did_create_new_entry = false; - params.url = url1; - params.transition = ui::PAGE_TRANSITION_TYPED; - params.page_state = PageState::CreateFromURL(url1); - LoadCommittedDetailsObserver observer(contents()); - - main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigateWithParams(¶ms, false); + navigation1->set_intended_as_new_entry(true); + navigation1->Commit(); EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, observer.navigation_type()); }
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index e42edef..1d9c1f5 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -5095,20 +5095,23 @@ // MHTML subframes can supply URLs at commit time that do not match the // process lock. For example, it can be either "cid:..." or arbitrary URL at // which the frame was at the time of generating the MHTML - // (e.g. "http://localhost"). In such cases, don't verify the URL, but allow + // (e.g. "http://localhost"). In such cases, don't verify the URL, but require // the URL to commit in the process of the main frame. - // TODO(creis): We should also ensure that such MHTML subframes do not commit - // in OOPIFs in a process based on the subframe URL, since MHTML should not - // allow such cases to occur. However, we are currently seeing cases where - // that is happening. Investigate in https://crbug.com/948246. if (!frame_tree_node()->IsMainFrame()) { - bool is_in_mhtml = frame_tree_node_->frame_tree() - ->root() - ->current_frame_host() - ->is_mhtml_document(); - if (is_in_mhtml && - IsSameSiteInstance(frame_tree_node()->parent()->current_frame_host())) { - return true; + RenderFrameHostImpl* main_frame = + frame_tree_node()->frame_tree()->GetMainFrame(); + if (main_frame->is_mhtml_document()) { + if (IsSameSiteInstance(main_frame)) + return true; + + // If an MHTML subframe commits in a different process (even one that + // appears correct for the subframe's URL), then we aren't correctly + // loading it from the archive and should kill the renderer. + base::debug::SetCrashKeyString( + base::debug::AllocateCrashKeyString( + "oopif_in_mhtml_page", base::debug::CrashKeySize::Size32), + is_mhtml_document() ? "is_mhtml_doc" : "not_mhtml_doc"); + return false; } }
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc index 64bb4b9..8ffc145 100644 --- a/content/browser/renderer_host/input/input_router_impl.cc +++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -55,12 +55,22 @@ } } -ui::WebScopedInputEvent ScaleEvent(const WebInputEvent& event, double scale) { +std::unique_ptr<InputEvent> ScaleEvent(const WebInputEvent& event, + double scale, + const ui::LatencyInfo latency_info) { std::unique_ptr<blink::WebInputEvent> event_in_viewport = ui::ScaleWebInputEvent(event, scale); - if (event_in_viewport) - return ui::WebScopedInputEvent(event_in_viewport.release()); - return ui::WebInputEventTraits::Clone(event); + if (event_in_viewport) { + ui::LatencyInfo scaled_latency_info(latency_info); + scaled_latency_info.set_scroll_update_delta( + latency_info.scroll_update_delta() * scale); + return std::make_unique<InputEvent>( + ui::WebScopedInputEvent(event_in_viewport.release()), + scaled_latency_info); + } + + return std::make_unique<InputEvent>(ui::WebInputEventTraits::Clone(event), + latency_info); } } // namespace @@ -520,8 +530,8 @@ return; } - std::unique_ptr<InputEvent> event = std::make_unique<InputEvent>( - ScaleEvent(input_event, device_scale_factor_), latency_info); + std::unique_ptr<InputEvent> event = + ScaleEvent(input_event, device_scale_factor_, latency_info); if (WebInputEventTraits::ShouldBlockEventStream(input_event)) { TRACE_EVENT_INSTANT0("input", "InputEventSentBlocking", TRACE_EVENT_SCOPE_THREAD);
diff --git a/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc b/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc index 33662f3c..fd04742 100644 --- a/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc +++ b/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
@@ -1204,115 +1204,4 @@ EXPECT_TRUE(HistogramSizeEq("Event.Latency.EndToEnd.TouchpadPinch", 1)); } -TEST_F(RenderWidgetHostLatencyTrackerTest, TestScrollUpdateAverageLag) { - // Simulate a simple situation that events at every 10ms and start at t=15ms, - // frame swaps at every 10ms too and start at t=20ms. - base::TimeTicks event_time = - base::TimeTicks() + base::TimeDelta::FromMilliseconds(5); - base::TimeTicks frame_time = - base::TimeTicks() + base::TimeDelta::FromMilliseconds(10); - { - // ScrollBegin - SyntheticWebTouchEvent touch; - touch.PressPoint(0, 0); - ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH); - - touch_latency.set_scroll_update_delta(10); - event_time += base::TimeDelta::FromMilliseconds(10); // 15ms - touch_latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, - event_time, 1); - touch_latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, event_time, - 1); - - frame_time += base::TimeDelta::FromMilliseconds(10); // 20ms - AddFakeComponentsWithTimeStamp(*tracker(), &touch_latency, frame_time); - AddRenderingScheduledComponent(&touch_latency, - false /* rendering_on_main */, frame_time); - tracker()->OnInputEvent(touch, &touch_latency); - tracker()->OnInputEventAck(touch, &touch_latency, - INPUT_EVENT_ACK_STATE_NOT_CONSUMED); - viz_tracker()->OnGpuSwapBuffersCompleted(touch_latency); - } - // Send 101 ScrollUpdate events to verify that there is 1 AverageLag record - // per 1 second. - const int kUpdates = 101; - for (int i = 0; i < kUpdates; i++) { - // ScrollUpdate - SyntheticWebTouchEvent touch; - touch.PressPoint(0, 0); - ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH); - - const int sign = (i < kUpdates / 2) ? 1 : -1; - touch_latency.set_scroll_update_delta(sign * 10); - event_time += base::TimeDelta::FromMilliseconds(10); - touch_latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, event_time, - 1); - touch_latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, event_time, - 1); - - frame_time += base::TimeDelta::FromMilliseconds(10); - AddFakeComponentsWithTimeStamp(*tracker(), &touch_latency, frame_time); - AddRenderingScheduledComponent(&touch_latency, false /*rendering_on_main*/, - frame_time); - tracker()->OnInputEvent(touch, &touch_latency); - tracker()->OnInputEventAck(touch, &touch_latency, - INPUT_EVENT_ACK_STATE_NOT_CONSUMED); - viz_tracker()->OnGpuSwapBuffersCompleted(touch_latency); - } - // ScrollBegin report_time is at 20ms, so the next ScrollUpdate report_time is - // at 1020ms. The last event_time that finish this report should be later than - // 1020ms. - EXPECT_EQ(event_time, - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1025)); - EXPECT_EQ(frame_time, - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1030)); - - // ScrollBegin AverageLag are the area between the event original component - // (time=15ms, delta=10px) to the frame swap time (time=20ms, expect finger - // position at delta=15px). The AverageLag scaled to 1 second is - // (5ms*10px+5ms*5px/2)/5ms = 12.5px. - EXPECT_THAT(histogram_tester().GetAllSamples( - "Event.Latency.ScrollBegin.Touch.AverageLag"), - ElementsAre(Bucket(12, 1))); - // This ScrollUpdate AverageLag are calculated as the finger uniformly scroll - // 10px each frame. For each frame, the Lag on the last frame start is 5px, - // and Lag on this frame swap is 15px, so the AverageLag in 1 second is 10px. - EXPECT_THAT(histogram_tester().GetAllSamples( - "Event.Latency.ScrollUpdate.Touch.AverageLag"), - ElementsAre(Bucket(10, 1))); - ResetHistograms(); - - { - // Send another ScrollBegin to end the unfinished ScrollUpdate report. - SyntheticWebTouchEvent touch; - touch.PressPoint(0, 0); - ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH); - - event_time += base::TimeDelta::FromMilliseconds(10); - touch_latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, - event_time, 1); - touch_latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, event_time, - 1); - - frame_time += base::TimeDelta::FromMilliseconds(10); - AddFakeComponentsWithTimeStamp(*tracker(), &touch_latency, frame_time); - AddRenderingScheduledComponent(&touch_latency, - false /* rendering_on_main */, frame_time); - tracker()->OnInputEvent(touch, &touch_latency); - tracker()->OnInputEventAck(touch, &touch_latency, - INPUT_EVENT_ACK_STATE_NOT_CONSUMED); - viz_tracker()->OnGpuSwapBuffersCompleted(touch_latency); - } - // The last frame's lag is 8.75px and truncated to 8. - EXPECT_THAT(histogram_tester().GetAllSamples( - "Event.Latency.ScrollUpdate.Touch.AverageLag"), - ElementsAre(Bucket(8, 1))); -} - } // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index e465d41..cf7d6a6 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2976,6 +2976,7 @@ switches::kEnableAccessibilityObjectModel, switches::kEnableAutomation, switches::kEnableExperimentalAccessibilityLanguageDetection, + switches::kEnableExperimentalAccessibilityLabelsDebugging, switches::kEnableExperimentalWebPlatformFeatures, switches::kEnableGPUClientLogging, switches::kEnableGpuClientTracing,
diff --git a/content/browser/tracing/startup_tracing_browsertest.cc b/content/browser/tracing/startup_tracing_browsertest.cc index cba2622..2bda794 100644 --- a/content/browser/tracing/startup_tracing_browsertest.cc +++ b/content/browser/tracing/startup_tracing_browsertest.cc
@@ -74,8 +74,9 @@ std::string trace; base::ScopedAllowBlockingForTesting allow_blocking; ASSERT_TRUE(base::ReadFileToString(temp_file_path_, &trace)); - EXPECT_TRUE(trace.find("BrowserMainLoop::InitStartupTracingForDuration") != - std::string::npos); + EXPECT_TRUE( + trace.find("TracingControllerImpl::InitStartupTracingForDuration") != + std::string::npos); } } // namespace content
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index 9c739f7..2b0e315 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -21,6 +21,9 @@ #include "base/values.h" #include "build/build_config.h" #include "components/tracing/common/trace_startup_config.h" +#include "components/tracing/common/trace_to_console.h" +#include "components/tracing/common/tracing_switches.h" +#include "content/browser/browser_shutdown_profile_dumper.h" #include "content/browser/gpu/gpu_data_manager_impl.h" #include "content/browser/tracing/file_tracing_provider_impl.h" #include "content/browser/tracing/perfetto_file_tracer.h" @@ -57,6 +60,7 @@ #if defined(OS_ANDROID) #include "base/debug/elf_reader.h" +#include "content/browser/android/tracing_controller_android.h" // Symbol with virtual address of the start of ELF header of the current binary. extern char __ehdr_start; @@ -137,6 +141,11 @@ } #endif +void OnStoppedStartupTracing(const base::FilePath& trace_file) { + VLOG(0) << "Completed startup tracing to " << trace_file.value(); + tracing::TraceStartupConfig::GetInstance()->OnTraceToResultFileFinished(); +} + } // namespace TracingController* TracingController::GetInstance() { @@ -382,6 +391,83 @@ return true; } +void TracingControllerImpl::StartStartupTracingIfNeeded() { + auto* trace_startup_config = tracing::TraceStartupConfig::GetInstance(); + if (trace_startup_config->AttemptAdoptBySessionOwner( + tracing::TraceStartupConfig::SessionOwner::kTracingController)) { + StartTracing(trace_startup_config->GetTraceConfig(), + StartTracingDoneCallback()); + } else if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kTraceToConsole)) { + StartTracing(tracing::GetConfigForTraceToConsole(), + StartTracingDoneCallback()); + } + + if (trace_startup_config->IsTracingStartupForDuration()) { + TRACE_EVENT0("startup", + "TracingControllerImpl::InitStartupTracingForDuration"); + InitStartupTracingForDuration(); + } +} + +base::FilePath TracingControllerImpl::GetStartupTraceFileName() const { + base::FilePath trace_file; + + trace_file = tracing::TraceStartupConfig::GetInstance()->GetResultFile(); + if (trace_file.empty()) { +#if defined(OS_ANDROID) + TracingControllerAndroid::GenerateTracingFilePath(&trace_file); +#else + // Default to saving the startup trace into the current dir. + trace_file = base::FilePath().AppendASCII("chrometrace.log"); +#endif + } + + return trace_file; +} + +void TracingControllerImpl::InitStartupTracingForDuration() { + DCHECK(tracing::TraceStartupConfig::GetInstance() + ->IsTracingStartupForDuration()); + + startup_trace_file_ = GetStartupTraceFileName(); + + startup_trace_timer_.Start( + FROM_HERE, + base::TimeDelta::FromSeconds( + tracing::TraceStartupConfig::GetInstance()->GetStartupDuration()), + this, &TracingControllerImpl::EndStartupTracing); +} + +void TracingControllerImpl::EndStartupTracing() { + // Do nothing if startup tracing is already stopped. + if (!tracing::TraceStartupConfig::GetInstance()->IsEnabled()) + return; + + StopTracing(CreateFileEndpoint( + startup_trace_file_, + base::BindRepeating(OnStoppedStartupTracing, startup_trace_file_))); +} + +std::unique_ptr<BrowserShutdownProfileDumper> +TracingControllerImpl::FinalizeStartupTracingIfNeeded() { + // There are two cases: + // 1. Startup duration is not reached. + // 2. Or if the trace should be saved to file for --trace-config-file flag. + if (startup_trace_timer_.IsRunning()) { + startup_trace_timer_.Stop(); + if (startup_trace_file_ != base::FilePath().AppendASCII("none")) { + return std::make_unique<BrowserShutdownProfileDumper>( + startup_trace_file_); + } + } else if (tracing::TraceStartupConfig::GetInstance() + ->ShouldTraceToResultFile()) { + return std::make_unique<BrowserShutdownProfileDumper>( + GetStartupTraceFileName()); + } + return nullptr; +} + bool TracingControllerImpl::StopTracing( const scoped_refptr<TraceDataEndpoint>& trace_data_endpoint) { return StopTracing(std::move(trace_data_endpoint), "");
diff --git a/content/browser/tracing/tracing_controller_impl.h b/content/browser/tracing/tracing_controller_impl.h index 832446a..acbad2f 100644 --- a/content/browser/tracing/tracing_controller_impl.h +++ b/content/browser/tracing/tracing_controller_impl.h
@@ -12,6 +12,7 @@ #include "base/callback_forward.h" #include "base/memory/ref_counted.h" +#include "base/timer/timer.h" #include "content/common/content_export.h" #include "content/public/browser/tracing_controller.h" #include "mojo/public/cpp/system/data_pipe_drainer.h" @@ -71,6 +72,21 @@ CONTENT_EXPORT void SetTracingDelegateForTesting( std::unique_ptr<TracingDelegate> delegate); + // If command line flags specify startup tracing options, adopts the startup + // tracing session and relays it to all tracing agents. Note that the local + // TraceLog has already been enabled at this point by + // tracing::EnableStartupTracingIfNeeded(), before threads were available. + // Requires browser threads to have started and a started main message loop. + void StartStartupTracingIfNeeded(); + + // Should be called before browser main loop shutdown. If startup tracing is + // tracing to a file and is still active, this stops the duration timer if it + // exists and returns a BrowserShutdownProfileDumper that will finalize the + // trace file upon its destruction (i.e. startup tracing becomes a version of + // shutdown tracing). + std::unique_ptr<BrowserShutdownProfileDumper> + FinalizeStartupTracingIfNeeded(); + private: friend std::default_delete<TracingControllerImpl>; @@ -88,6 +104,10 @@ void CompleteFlush(); + void InitStartupTracingForDuration(); + void EndStartupTracing(); + base::FilePath GetStartupTraceFileName() const; + std::unique_ptr<PerfettoFileTracer> perfetto_file_tracer_; tracing::mojom::CoordinatorPtr coordinator_; std::vector<std::unique_ptr<tracing::BaseAgent>> agents_; @@ -100,6 +120,10 @@ bool is_data_complete_ = false; bool is_metadata_available_ = false; + base::FilePath startup_trace_file_; + // This timer initiates trace file saving. + base::OneShotTimer startup_trace_timer_; + DISALLOW_COPY_AND_ASSIGN(TracingControllerImpl); };
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc index 159c1b6..1c0e46c 100644 --- a/content/renderer/accessibility/blink_ax_tree_source.cc +++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -39,6 +39,7 @@ #include "third_party/blink/public/web/web_plugin.h" #include "third_party/blink/public/web/web_plugin_container.h" #include "third_party/blink/public/web/web_view.h" +#include "ui/accessibility/accessibility_switches.h" #include "ui/accessibility/ax_enum_util.h" #include "ui/accessibility/ax_role_properties.h" #include "ui/gfx/geometry/vector2d_f.h" @@ -268,7 +269,11 @@ BlinkAXTreeSource::BlinkAXTreeSource(RenderFrameImpl* render_frame, ui::AXMode mode) - : render_frame_(render_frame), accessibility_mode_(mode), frozen_(false) {} + : render_frame_(render_frame), accessibility_mode_(mode), frozen_(false) { + image_annotation_debugging_ = + base::CommandLine::ForCurrentProcess()->HasSwitch( + ::switches::kEnableExperimentalAccessibilityLabelsDebugging); +} BlinkAXTreeSource::~BlinkAXTreeSource() { } @@ -1132,8 +1137,17 @@ ax::mojom::NameFrom name_from; blink::WebVector<WebAXObject> name_objects; blink::WebString web_name = src.GetName(name_from, name_objects); - if (name_from == ax::mojom::NameFrom::kAttributeExplicitlyEmpty || - !web_name.IsEmpty()) { + + // When visual debugging is enabled, the "title" attribute is set to a + // string beginning with a "%". We need to ignore such strings when + // subsequently deciding whether an image should be annotated or not. + bool has_debug_title = + image_annotation_debugging_ && + base::StartsWith(web_name.Utf8(), "%", base::CompareCase::SENSITIVE); + + if ((name_from == ax::mojom::NameFrom::kAttributeExplicitlyEmpty || + !web_name.IsEmpty()) && + !has_debug_title) { dst->SetImageAnnotationStatus( ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation); return; @@ -1143,7 +1157,8 @@ // it if it already has text other than whitespace. if (!base::ContainsOnlyChars( dst->GetStringAttribute(ax::mojom::StringAttribute::kName), - base::kWhitespaceASCII)) { + base::kWhitespaceASCII) && + !has_debug_title) { dst->SetImageAnnotationStatus( ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation); return;
diff --git a/content/renderer/accessibility/blink_ax_tree_source.h b/content/renderer/accessibility/blink_ax_tree_source.h index 8f635658..49dfc266 100644 --- a/content/renderer/accessibility/blink_ax_tree_source.h +++ b/content/renderer/accessibility/blink_ax_tree_source.h
@@ -149,6 +149,10 @@ AXImageAnnotator* image_annotator_ = nullptr; + // Whether we should highlight annotation results visually on the page + // for debugging. + bool image_annotation_debugging_ = false; + // These are updated when calling |Freeze|. bool frozen_ = false; blink::WebDocument document_;
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc index 0039583..30f04d2 100644 --- a/content/renderer/accessibility/render_accessibility_impl.cc +++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -34,6 +34,7 @@ #include "third_party/blink/public/web/web_settings.h" #include "third_party/blink/public/web/web_user_gesture_indicator.h" #include "third_party/blink/public/web/web_view.h" +#include "ui/accessibility/accessibility_switches.h" #include "ui/accessibility/ax_enum_util.h" #include "ui/accessibility/ax_event.h" #include "ui/accessibility/ax_node.h" @@ -159,6 +160,10 @@ HandleAXEvent(WebAXObject::FromWebDocument(document), ax::mojom::Event::kLayoutComplete); } + + image_annotation_debugging_ = + base::CommandLine::ForCurrentProcess()->HasSwitch( + ::switches::kEnableExperimentalAccessibilityLabelsDebugging); } RenderAccessibilityImpl::~RenderAccessibilityImpl() = default; @@ -172,6 +177,7 @@ void RenderAccessibilityImpl::DidCommitProvisionalLoad( bool is_same_document_navigation, ui::PageTransition transition) { + has_injected_stylesheet_ = false; // Remove the image annotator if the page is loading and it was added for // the one-shot image annotation (i.e. AXMode for image annotation is not // set). @@ -455,7 +461,7 @@ TRACE_EVENT0("accessibility", "RenderAccessibilityImpl::SendPendingAccessibilityEvents"); - const WebDocument& document = GetMainDocument(); + WebDocument document = GetMainDocument(); if (document.IsNull()) return; @@ -593,6 +599,12 @@ if (had_layout_complete_messages) SendLocationChanges(); + + if (had_load_complete_messages) + has_injected_stylesheet_ = false; + + if (image_annotation_debugging_) + AddImageAnnotationDebuggingAttributes(bundle.updates); } void RenderAccessibilityImpl::SendLocationChanges() { @@ -1089,4 +1101,74 @@ } } +void RenderAccessibilityImpl::AddImageAnnotationDebuggingAttributes( + const std::vector<AXContentTreeUpdate>& updates) { + DCHECK(image_annotation_debugging_); + + for (auto& update : updates) { + for (auto& node : update.nodes) { + if (!node.HasIntAttribute( + ax::mojom::IntAttribute::kImageAnnotationStatus)) + continue; + + ax::mojom::ImageAnnotationStatus status = node.GetImageAnnotationStatus(); + bool should_set_attributes = false; + switch (status) { + case ax::mojom::ImageAnnotationStatus::kNone: + case ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation: + case ax::mojom::ImageAnnotationStatus::kEligibleForAnnotation: + break; + case ax::mojom::ImageAnnotationStatus::kAnnotationPending: + case ax::mojom::ImageAnnotationStatus::kAnnotationAdult: + case ax::mojom::ImageAnnotationStatus::kAnnotationEmpty: + case ax::mojom::ImageAnnotationStatus::kAnnotationProcessFailed: + case ax::mojom::ImageAnnotationStatus::kAnnotationSucceeded: + should_set_attributes = true; + break; + } + + if (!should_set_attributes) + continue; + + WebDocument document = GetMainDocument(); + if (document.IsNull()) + continue; + WebAXObject obj = WebAXObject::FromWebDocumentByID(document, node.id); + if (obj.IsDetached()) + continue; + + if (!has_injected_stylesheet_) { + document.InsertStyleSheet( + "[imageannotation=annotationPending] { outline: 3px solid #9ff; } " + "[imageannotation=annotationSucceeded] { outline: 3px solid #3c3; " + "} " + "[imageannotation=annotationEmpty] { outline: 3px solid #ee6; } " + "[imageannotation=annotationAdult] { outline: 3px solid #f90; } " + "[imageannotation=annotationProcessFailed] { outline: 3px solid " + "#c00; } "); + has_injected_stylesheet_ = true; + } + + WebNode web_node = obj.GetNode(); + if (web_node.IsNull() || !web_node.IsElementNode()) + continue; + + WebElement element = web_node.To<WebElement>(); + std::string status_str = ui::ToString(status); + if (element.GetAttribute("imageannotation").Utf8() != status_str) + element.SetAttribute("imageannotation", + blink::WebString::FromUTF8(status_str)); + + std::string title = "%" + status_str; + std::string annotation = + node.GetStringAttribute(ax::mojom::StringAttribute::kImageAnnotation); + if (!annotation.empty()) + title = title + ": " + annotation; + if (element.GetAttribute("title").Utf8() != title) { + element.SetAttribute("title", blink::WebString::FromUTF8(title)); + } + } + } +} + } // namespace content
diff --git a/content/renderer/accessibility/render_accessibility_impl.h b/content/renderer/accessibility/render_accessibility_impl.h index 29a3ed5..aa86c84 100644 --- a/content/renderer/accessibility/render_accessibility_impl.h +++ b/content/renderer/accessibility/render_accessibility_impl.h
@@ -159,6 +159,8 @@ ax::mojom::EventFrom GetEventFrom(); void ScheduleSendAccessibilityEventsIfNeeded(); void RecordImageMetrics(AXContentTreeUpdate* update); + void AddImageAnnotationDebuggingAttributes( + const std::vector<AXContentTreeUpdate>& updates); // The RenderFrameImpl that owns us. RenderFrameImpl* render_frame_; @@ -216,6 +218,14 @@ // Token to send with event messages so we know when they're acknowledged. int ack_token_; + // Whether or not we've injected a stylesheet in this document + // (only when debugging flags are enabled, never under normal circumstances). + bool has_injected_stylesheet_ = false; + + // Whether we should highlight annotation results visually on the page + // for debugging. + bool image_annotation_debugging_ = false; + // So we can queue up tasks to be executed later. base::WeakPtrFactory<RenderAccessibilityImpl> weak_factory_;
diff --git a/content/renderer/compositor/layer_tree_view.cc b/content/renderer/compositor/layer_tree_view.cc index 98e9d3db..22ea28e 100644 --- a/content/renderer/compositor/layer_tree_view.cc +++ b/content/renderer/compositor/layer_tree_view.cc
@@ -235,10 +235,6 @@ return layer_tree_host_->GetSettings().enable_surface_synchronization; } -void LayerTreeView::SetNeedsForcedRedraw() { - layer_tree_host_->SetNeedsCommitWithForcedRedraw(); -} - std::unique_ptr<cc::SwapPromiseMonitor> LayerTreeView::CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) { return std::make_unique<cc::LatencyInfoSwapPromiseMonitor>( @@ -333,14 +329,6 @@ return layer_tree_host_->have_scroll_event_handlers(); } -bool LayerTreeView::CompositeIsSynchronous() const { - if (!compositor_thread_) { - DCHECK(!layer_tree_host_->GetSettings().single_thread_proxy_scheduler); - return true; - } - return false; -} - void LayerTreeView::SetLayerTreeFrameSink( std::unique_ptr<cc::LayerTreeFrameSink> layer_tree_frame_sink) { if (!layer_tree_frame_sink) { @@ -350,26 +338,6 @@ layer_tree_host_->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink)); } -void LayerTreeView::SynchronouslyComposite(bool raster) { - DCHECK(CompositeIsSynchronous()); - if (!layer_tree_host_->IsVisible()) - return; - - if (in_synchronous_compositor_update_) { - // Web tests can use a nested message loop to pump frames while inside a - // frame, but the compositor does not support this. In this case, we only - // run blink's lifecycle updates. - delegate_->BeginMainFrame(base::TimeTicks::Now()); - delegate_->UpdateVisualState(); - return; - } - - DCHECK(!in_synchronous_compositor_update_); - base::AutoReset<bool> inside_composite(&in_synchronous_compositor_update_, - true); - layer_tree_host_->Composite(base::TimeTicks::Now(), raster); -} - std::unique_ptr<cc::ScopedDeferMainFrameUpdate> LayerTreeView::DeferMainFrameUpdate() { return layer_tree_host_->DeferMainFrameUpdate(); @@ -404,40 +372,6 @@ layer_tree_host_->SetBrowserControlsShownRatio(ratio); } -void LayerTreeView::RequestDecode(const cc::PaintImage& image, - base::OnceCallback<void(bool)> callback) { - layer_tree_host_->QueueImageDecode(image, std::move(callback)); - - // If we're compositing synchronously, the SetNeedsCommit call which will be - // issued by |layer_tree_host_| is not going to cause a commit, due to the - // fact that this would make web tests slow and cause flakiness. However, - // in this case we actually need a commit to transfer the decode requests to - // the impl side. So, force a commit to happen. - if (CompositeIsSynchronous()) { - const bool raster = true; - layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()->PostTask( - FROM_HERE, base::BindOnce(&LayerTreeView::SynchronouslyComposite, - weak_factory_.GetWeakPtr(), raster)); - } -} - -void LayerTreeView::RequestPresentationCallback(base::OnceClosure callback) { - layer_tree_host_->RequestPresentationTimeForNextFrame(base::BindOnce( - [](base::OnceClosure callback, - const gfx::PresentationFeedback& feedback) { - std::move(callback).Run(); - }, - std::move(callback))); - SetNeedsForcedRedraw(); - if (CompositeIsSynchronous()) { - main_thread_->PostTask( - FROM_HERE, base::BindOnce(&LayerTreeView::SynchronouslyComposite, - weak_factory_.GetWeakPtr(), /*raster=*/true)); - } else { - layer_tree_host_->SetNeedsCommit(); - } -} - void LayerTreeView::SetOverscrollBehavior( const cc::OverscrollBehavior& behavior) { layer_tree_host_->SetOverscrollBehavior(behavior);
diff --git a/content/renderer/compositor/layer_tree_view.h b/content/renderer/compositor/layer_tree_view.h index 5853ec0d..d629a203 100644 --- a/content/renderer/compositor/layer_tree_view.h +++ b/content/renderer/compositor/layer_tree_view.h
@@ -89,9 +89,6 @@ // WebWidgetClient::ScheduleAnimate() instead, or they can bypass test // overrides. void SetNeedsBeginFrame(); - // Like SetNeedsRedraw but forces the frame to be drawn, without early-outs. - // Redraw will be forced after the next commit - void SetNeedsForcedRedraw(); // Calling CreateLatencyInfoSwapPromiseMonitor() to get a scoped // LatencyInfoSwapPromiseMonitor. During the life time of the // LatencyInfoSwapPromiseMonitor, if SetNeedsCommit() or @@ -155,9 +152,6 @@ float bottom_height, bool shrink) override; void SetBrowserControlsShownRatio(float) override; - void RequestDecode(const cc::PaintImage& image, - base::OnceCallback<void(bool)> callback) override; - void RequestPresentationCallback(base::OnceClosure callback) override; void SetOverscrollBehavior(const cc::OverscrollBehavior&) override; @@ -201,11 +195,6 @@ const cc::LayerTreeSettings& GetLayerTreeSettings() const; - // Performs a composite including a main frame and all lifecycle stages, - // immediately and synchronously. Should only be called in testing, when - // CompositeIsSynchronous() is true. - void SynchronouslyComposite(bool raster); - // Sets the RenderFrameMetadataObserver, which is sent to the compositor // thread for binding. void SetRenderFrameObserver( @@ -217,18 +206,12 @@ cc::LayerTreeHost* layer_tree_host() { return layer_tree_host_.get(); } - // Exposed for the WebTest harness to query. - bool CompositeIsSynchronousForTesting() const { - return CompositeIsSynchronous(); - } - protected: friend class RenderViewImplScaleFactorTest; private: void SetLayerTreeFrameSink( std::unique_ptr<cc::LayerTreeFrameSink> layer_tree_frame_sink); - bool CompositeIsSynchronous() const; LayerTreeViewDelegate* const delegate_; const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; @@ -240,8 +223,6 @@ bool layer_tree_frame_sink_request_failed_while_invisible_ = false; - bool in_synchronous_compositor_update_ = false; - viz::FrameSinkId frame_sink_id_; base::circular_deque< std::pair<uint32_t,
diff --git a/content/renderer/compositor/layer_tree_view_unittest.cc b/content/renderer/compositor/layer_tree_view_unittest.cc index 431243c..7085950 100644 --- a/content/renderer/compositor/layer_tree_view_unittest.cc +++ b/content/renderer/compositor/layer_tree_view_unittest.cc
@@ -423,7 +423,8 @@ std::move(callback).Run(); }, run_loop.QuitClosure(), &swap_time)); - layer_tree_view_.SynchronouslyComposite(/*raster=*/true); + layer_tree_view_.layer_tree_host()->Composite(base::TimeTicks::Now(), + /*raster=*/true); // The swap time notify comes as a posted task. run_loop.Run(); return swap_time;
diff --git a/content/renderer/media/stream/apply_constraints_processor.h b/content/renderer/media/stream/apply_constraints_processor.h index 1907819..ce34c656 100644 --- a/content/renderer/media/stream/apply_constraints_processor.h +++ b/content/renderer/media/stream/apply_constraints_processor.h
@@ -14,11 +14,11 @@ #include "media/capture/video_capture_types.h" #include "third_party/blink/public/mojom/mediastream/media_devices.mojom.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h" +#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h" #include "third_party/blink/public/web/web_apply_constraints_request.h" namespace blink { class MediaStreamAudioSource; -class MediaStreamVideoSource; class MediaStreamVideoTrack; class WebString; }
diff --git a/content/renderer/media/stream/media_stream_video_source_unittest.cc b/content/renderer/media/stream/media_stream_video_source_unittest.cc index 21baf254..700a34b 100644 --- a/content/renderer/media/stream/media_stream_video_source_unittest.cc +++ b/content/renderer/media/stream/media_stream_video_source_unittest.cc
@@ -21,7 +21,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h" -#include "third_party/blink/public/web/modules/mediastream/video_track_adapter.h" +#include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h" #include "third_party/blink/public/web/web_heap.h" using ::testing::_;
diff --git a/content/renderer/media/stream/media_stream_video_track_unittest.cc b/content/renderer/media/stream/media_stream_video_track_unittest.cc index 425e1a8..e457c65c 100644 --- a/content/renderer/media/stream/media_stream_video_track_unittest.cc +++ b/content/renderer/media/stream/media_stream_video_track_unittest.cc
@@ -19,7 +19,7 @@ #include "media/base/video_frame.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h" -#include "third_party/blink/public/web/modules/mediastream/video_track_adapter.h" +#include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h" #include "third_party/blink/public/web/web_heap.h" namespace content {
diff --git a/content/renderer/media/stream/mock_media_stream_registry.cc b/content/renderer/media/stream/mock_media_stream_registry.cc index a5353084..2a694349 100644 --- a/content/renderer/media/stream/mock_media_stream_registry.cc +++ b/content/renderer/media/stream/mock_media_stream_registry.cc
@@ -15,7 +15,7 @@ #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_vector.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h" -#include "third_party/blink/public/web/modules/mediastream/video_track_adapter.h" +#include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h" namespace content {
diff --git a/content/renderer/media/stream/user_media_client_impl_unittest.cc b/content/renderer/media/stream/user_media_client_impl_unittest.cc index ceb994f..b91aac6 100644 --- a/content/renderer/media/stream/user_media_client_impl_unittest.cc +++ b/content/renderer/media/stream/user_media_client_impl_unittest.cc
@@ -37,6 +37,7 @@ #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_vector.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h" +#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h" #include "third_party/blink/public/web/web_heap.h" using testing::_;
diff --git a/content/renderer/media/stream/video_track_adapter_unittest.cc b/content/renderer/media/stream/video_track_adapter_unittest.cc index a65018d9..1fae622 100644 --- a/content/renderer/media/stream/video_track_adapter_unittest.cc +++ b/content/renderer/media/stream/video_track_adapter_unittest.cc
@@ -8,6 +8,7 @@ #include "media/base/limits.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h" namespace content {
diff --git a/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc b/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc index 3b32fea..fccb236 100644 --- a/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc +++ b/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc
@@ -11,7 +11,7 @@ #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" -#include "third_party/blink/public/web/modules/mediastream/video_track_adapter.h" +#include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h" namespace content { namespace {
diff --git a/content/renderer/pepper/pepper_websocket_host.cc b/content/renderer/pepper/pepper_websocket_host.cc index b0aa5db..7765b00 100644 --- a/content/renderer/pepper/pepper_websocket_host.cc +++ b/content/renderer/pepper/pepper_websocket_host.cc
@@ -209,7 +209,8 @@ return PP_ERROR_BADARGUMENT; if (gurl.has_ref()) return PP_ERROR_BADARGUMENT; - if (!net::IsPortAllowedForScheme(gurl.EffectiveIntPort(), gurl.scheme())) + if (!net::IsPortAllowedForScheme(gurl.EffectiveIntPort(), + gurl.scheme_piece())) return PP_ERROR_BADARGUMENT; WebURL web_url(gurl);
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index ba98cf96..155a72f 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -977,11 +977,7 @@ void RenderWidget::RequestPresentation(PresentationTimeCallback callback) { layer_tree_view_->layer_tree_host()->RequestPresentationTimeForNextFrame( std::move(callback)); - layer_tree_view_->SetNeedsForcedRedraw(); - - // Need this since single thread mode doesn't have a scheduler so the above - // call won't cause us to generate a new frame. - ScheduleAnimation(); + layer_tree_view_->layer_tree_host()->SetNeedsCommitWithForcedRedraw(); } void RenderWidget::DidPresentForceDrawFrame( @@ -2837,8 +2833,8 @@ *result = int_value; return true; } else { - LOG(WARNING) << "Failed to parse switch " << switch_string << ": " - << string_value; + DLOG(WARNING) << "Failed to parse switch " << switch_string << ": " + << string_value; return false; } }; @@ -3321,6 +3317,12 @@ target_offset, use_anchor, new_page_scale, duration); } +void RenderWidget::RequestDecode(const cc::PaintImage& image, + base::OnceCallback<void(bool)> callback) { + layer_tree_view_->layer_tree_host()->QueueImageDecode(image, + std::move(callback)); +} + void RenderWidget::RequestUnbufferedInputEvents() { if (input_event_queue_) input_event_queue_->RequestUnbufferedInputEvents();
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index 98957193..fdb822b 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -446,6 +446,8 @@ bool use_anchor, float new_page_scale, double duration_sec) override; + void RequestDecode(const cc::PaintImage& image, + base::OnceCallback<void(bool)> callback) override; // Override point to obtain that the current input method state and caret // position. @@ -634,11 +636,18 @@ // to the user. using PresentationTimeCallback = base::OnceCallback<void(const gfx::PresentationFeedback&)>; - void RequestPresentation(PresentationTimeCallback callback); + virtual void RequestPresentation(PresentationTimeCallback callback); // RenderWidget IPC message handler that can be overridden by subclasses. virtual void OnSynchronizeVisualProperties(const VisualProperties& params); + bool in_synchronous_composite_for_testing() const { + return in_synchronous_composite_for_testing_; + } + void set_in_synchronous_composite_for_testing(bool in) { + in_synchronous_composite_for_testing_ = in; + } + // Called by Create() functions and subclasses to finish initialization. // |show_callback| will be invoked once WebWidgetClient::Show() occurs, and // should be null if Show() won't be triggered for this widget. @@ -983,6 +992,9 @@ // process, without the use of this mode, however it would be overridden by // the browser if they disagree. bool synchronous_resize_mode_for_testing_ = false; + // In web tests, synchronous composites should not be nested inside another + // composite, and this bool is used to guard against that. + bool in_synchronous_composite_for_testing_ = false; // Stores information about the current text input. blink::WebTextInputInfo text_input_info_;
diff --git a/content/renderer/renderer_main_platform_delegate_mac.mm b/content/renderer/renderer_main_platform_delegate_mac.mm index d6e9a70..e59ac93 100644 --- a/content/renderer/renderer_main_platform_delegate_mac.mm +++ b/content/renderer/renderer_main_platform_delegate_mac.mm
@@ -4,24 +4,11 @@ #include "content/renderer/renderer_main_platform_delegate.h" -#include <Carbon/Carbon.h> #import <Cocoa/Cocoa.h> -#include <objc/runtime.h> -#include <stdint.h> -#include "base/bind.h" -#include "base/callback.h" -#include "base/command_line.h" #include "base/logging.h" -#include "base/mac/mac_util.h" -#include "base/mac/scoped_cftyperef.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/sys_string_conversions.h" -#include "content/public/common/content_switches.h" -#include "content/public/common/sandbox_init.h" #include "sandbox/mac/seatbelt.h" #include "sandbox/mac/system_services.h" -#include "services/service_manager/sandbox/mac/sandbox_mac.h" extern "C" { CGError CGSSetDenyWindowServerConnections(bool); @@ -44,81 +31,6 @@ sandbox::DisableLaunchServices(); } -// You are about to read a pretty disgusting hack. In a static initializer, -// CoreFoundation decides to connect with cfprefsd(8) using Mach IPC. There is -// no public way to close this Mach port after-the-fact, nor a way to stop it -// from happening since it is done pre-main in dyld. But the address of the -// CFMachPort can be found in the run loop's string description. Below, that -// address is parsed, cast, and then used to invalidate the Mach port to -// disable communication with cfprefsd. -void DisconnectCFNotificationCenter() { - base::ScopedCFTypeRef<CFStringRef> run_loop_description( - CFCopyDescription(CFRunLoopGetCurrent())); - const CFIndex length = CFStringGetLength(run_loop_description); - for (CFIndex i = 0; i < length; ) { - // Find the start of a CFMachPort run loop source, which looks like this, - // without new lines: - // 1 : <CFRunLoopSource 0x7d16ea90 [0xa160af80]>{signalled = No, - // valid = Yes, order = 0, context = - // <CFMachPort 0x7d16fe00 [0xa160af80]>{valid = Yes, port = 3a0f, - // source = 0x7d16ea90, callout = - // _ZL14MessageHandlerP12__CFMachPortPvlS1_ (0x96df59c2), context = - // <CFMachPort context 0x1475b>}} - CFRange run_loop_source_context_range; - if (!CFStringFindWithOptions(run_loop_description, - CFSTR(", context = <CFMachPort "), CFRangeMake(i, length - i), - 0, &run_loop_source_context_range)) { - break; - } - i = run_loop_source_context_range.location + - run_loop_source_context_range.length; - - // The address of the CFMachPort is the first hexadecimal address after the - // CF type name. - CFRange port_address_range = CFRangeMake(i, 0); - for (CFIndex j = port_address_range.location; j < length; ++j) { - UniChar c = CFStringGetCharacterAtIndex(run_loop_description, j); - if (c == ' ') - break; - ++port_address_range.length; - } - - base::ScopedCFTypeRef<CFStringRef> port_address_string( - CFStringCreateWithSubstring(NULL, run_loop_description, - port_address_range)); - if (!port_address_string) - continue; - - // Convert the string to an address. - std::string port_address_std_string = - base::SysCFStringRefToUTF8(port_address_string); - uint64_t port_address = 0; - if (!base::HexStringToUInt64(port_address_std_string, &port_address)) - continue; - - // Cast the address to an object. - CFMachPortRef mach_port = reinterpret_cast<CFMachPortRef>(port_address); - if (CFGetTypeID(mach_port) != CFMachPortGetTypeID()) - continue; - - // Verify that this is the Mach port that needs to be disconnected by the - // name of its callout function. Example description (no new lines): - // <CFMachPort 0x7d16fe00 [0xa160af80]>{valid = Yes, port = 3a0f, source = - // 0x7d16ea90, callout = __CFXNotificationReceiveFromServer (0x96df59c2), - // context = <CFMachPort context 0x1475b>} - base::ScopedCFTypeRef<CFStringRef> port_description( - CFCopyDescription(mach_port)); - if (CFStringFindWithOptions(port_description, - CFSTR(", callout = __CFXNotificationReceiveFromServer ("), - CFRangeMake(0, CFStringGetLength(port_description)), - 0, - NULL)) { - CFMachPortInvalidate(mach_port); - return; - } - } -} - } // namespace RendererMainPlatformDelegate::RendererMainPlatformDelegate( @@ -143,23 +55,18 @@ } bool RendererMainPlatformDelegate::EnableSandbox() { - bool sandbox_initialized = sandbox::Seatbelt::IsSandboxed(); + // The sandbox is enabled as part of process launching, so assert that it has + // been initialized. + CHECK(sandbox::Seatbelt::IsSandboxed()); - // If the sandbox is already engaged, just disable system services. - if (sandbox_initialized) { - DisableSystemServices(); - } else { - sandbox_initialized = - InitializeSandbox(base::BindOnce(&DisableSystemServices)); - } + // Inform various system services that they should not attempt to acquire + // resources that will be blocked by the sandbox. + DisableSystemServices(); - // The sandbox is now engaged. Make sure that the renderer has not connected - // itself to Cocoa. + // Make sure that the renderer has not connected itself to Cocoa. CHECK(NSApp == nil); - DisconnectCFNotificationCenter(); - - return sandbox_initialized; + return true; } } // namespace content
diff --git a/content/shell/renderer/web_test/blink_test_runner.cc b/content/shell/renderer/web_test/blink_test_runner.cc index d0cf619..e256bcd 100644 --- a/content/shell/renderer/web_test/blink_test_runner.cc +++ b/content/shell/renderer/web_test/blink_test_runner.cc
@@ -461,6 +461,14 @@ // that this returns a value indicating if we should defer the pixel dump to // the browser instead. We want to switch all tests to use this for pixel // dumps. + // TODO(danakj): When not printing, this call doesn't do anything useful + // except cause the full viewport to be damaged and insert a presentation + // callback. Since we already get a callback from the browser side when the + // pixel capture is done, this callback seems redundant and probably this only + // really was needed for causing damage. Now WebWidgetTestProxy does that + // damage itself when a RequestPresentationForPixelDump() is performed so we + // could probably stop doing CaptureLocalLayoutDump() at all when not printing + // and not wait for the callback. bool browser_should_capture_pixels = CaptureLocalPixelsDump(); // Add the current selection rect to the dump result, if requested. @@ -526,9 +534,8 @@ waiting_for_pixels_dump_result_ = true; bool browser_should_capture_pixels = interfaces->TestRunner()->DumpPixelsAsync( - render_view()->GetWebView()->MainFrame()->ToWebLocalFrame(), - base::BindOnce(&BlinkTestRunner::OnPixelsDumpCompleted, - base::Unretained(this))); + render_view(), base::BindOnce(&BlinkTestRunner::OnPixelsDumpCompleted, + base::Unretained(this))); // If the browser should capture pixels, then we shouldn't be waiting for dump // results.
diff --git a/content/shell/test_runner/test_runner.cc b/content/shell/test_runner/test_runner.cc index f39aaea..535e4ca3 100644 --- a/content/shell/test_runner/test_runner.cc +++ b/content/shell/test_runner/test_runner.cc
@@ -1663,8 +1663,11 @@ } bool TestRunner::DumpPixelsAsync( - blink::WebLocalFrame* frame, + content::RenderView* render_view, base::OnceCallback<void(const SkBitmap&)> callback) { + auto* view_proxy = static_cast<WebViewTestProxy*>(render_view); + CHECK(view_proxy->GetWebView()->MainFrame()); + if (web_test_runtime_flags_.dump_drag_image()) { if (drag_image_.isNull()) { // This means the test called dumpDragImage but did not initiate a drag. @@ -1683,22 +1686,27 @@ // If we need to do a display compositor pixel dump, then delegate that to the // browser by returning true. Note that printing case can be handled here. if (!web_test_runtime_flags_.is_printing()) { - frame->View()->MainFrameWidget()->RequestPresentationCallbackForTesting( - base::BindOnce( - [](base::OnceCallback<void(const SkBitmap&)> callback) { - SkBitmap bitmap; - bitmap.allocN32Pixels(1, 1); - bitmap.eraseColor(0); - std::move(callback).Run(bitmap); - }, - std::move(callback))); + auto* widget_proxy = + static_cast<WebWidgetTestProxy*>(view_proxy->GetWidget()); + widget_proxy->RequestPresentationForPixelDump(base::BindOnce( + [](base::OnceCallback<void(const SkBitmap&)> callback, + const gfx::PresentationFeedback& feedback) { + // Generate a 1x1 black bitmap. + SkBitmap bitmap; + bitmap.allocN32Pixels(1, 1); + bitmap.eraseColor(0); + std::move(callback).Run(bitmap); + }, + std::move(callback))); return true; } - auto* target_frame = frame; + blink::WebLocalFrame* frame = + view_proxy->GetWebView()->MainFrame()->ToWebLocalFrame(); + blink::WebLocalFrame* target_frame = frame; std::string frame_name = web_test_runtime_flags_.printing_frame(); if (!frame_name.empty()) { - auto* frame_to_print = + blink::WebFrame* frame_to_print = frame->FindFrameByName(blink::WebString::FromUTF8(frame_name)); if (frame_to_print && frame_to_print->IsWebLocalFrame()) target_frame = frame_to_print->ToWebLocalFrame();
diff --git a/content/shell/test_runner/test_runner.h b/content/shell/test_runner/test_runner.h index 49f1bd3a..fdea070 100644 --- a/content/shell/test_runner/test_runner.h +++ b/content/shell/test_runner/test_runner.h
@@ -41,7 +41,6 @@ } namespace test_runner { - class MockContentSettingsClient; class MockScreenOrientationClient; class SpellCheckClient; @@ -88,7 +87,7 @@ std::string DumpLayout(blink::WebLocalFrame* frame) override; bool ShouldDumpSelectionRect() const override; bool DumpPixelsAsync( - blink::WebLocalFrame* frame, + content::RenderView* render_view, base::OnceCallback<void(const SkBitmap&)> callback) override; void ReplicateWebTestRuntimeFlagsChanges( const base::DictionaryValue& changed_values) override;
diff --git a/content/shell/test_runner/test_runner_for_specific_view.cc b/content/shell/test_runner/test_runner_for_specific_view.cc index 2a36e84..0308305 100644 --- a/content/shell/test_runner/test_runner_for_specific_view.cc +++ b/content/shell/test_runner/test_runner_for_specific_view.cc
@@ -227,7 +227,7 @@ << "testRuner.capturePixelsAsyncThen from an OOPIF"; web_view_test_proxy_->test_interfaces()->GetTestRunner()->DumpPixelsAsync( - web_view()->MainFrame()->ToWebLocalFrame(), + web_view_test_proxy_, base::BindOnce(&TestRunnerForSpecificView::CapturePixelsCallback, weak_factory_.GetWeakPtr(), std::move(persistent_callback)));
diff --git a/content/shell/test_runner/web_test_runner.h b/content/shell/test_runner/web_test_runner.h index bbf2f2c..86c1a81 100644 --- a/content/shell/test_runner/web_test_runner.h +++ b/content/shell/test_runner/web_test_runner.h
@@ -23,6 +23,10 @@ class WebView; } +namespace content { +class RenderView; +} + namespace test_runner { class WebTestRunner { @@ -56,13 +60,15 @@ // pixels. virtual bool ShouldDumpSelectionRect() const = 0; - // Snapshots image of |web_view| using the mode requested by the current test - // and calls |callback| with the result. Caller needs to ensure that - // |web_view| stays alive until |callback| is called. + // Snapshots the content of |render_view| using the mode requested by the + // current test and calls |callback| with the result. Caller needs to ensure + // that |render_view| stays alive until |callback| is called. // Returns false if the request to capture pixels was processed locally, and - // true if the pixels need to be captured in the browser process instead.. + // true if the pixels need to be captured in the browser process instead. In + // that case the |callback| is still called once the pixels are captures but + // the SkBitmap contained within is not useful. virtual bool DumpPixelsAsync( - blink::WebLocalFrame* frame, + content::RenderView* render_view, base::OnceCallback<void(const SkBitmap&)> callback) = 0; // Replicates changes to web test runtime flags
diff --git a/content/shell/test_runner/web_widget_test_proxy.cc b/content/shell/test_runner/web_widget_test_proxy.cc index d18921a..d2d56e6 100644 --- a/content/shell/test_runner/web_widget_test_proxy.cc +++ b/content/shell/test_runner/web_widget_test_proxy.cc
@@ -4,6 +4,7 @@ #include "content/shell/test_runner/web_widget_test_proxy.h" +#include "content/renderer/compositor/compositor_dependencies.h" #include "content/renderer/compositor/layer_tree_view.h" #include "content/renderer/input/widget_input_handler_manager.h" #include "content/shell/test_runner/test_interfaces.h" @@ -21,21 +22,70 @@ WebWidgetTestProxy::~WebWidgetTestProxy() = default; -void WebWidgetTestProxy::ScheduleAnimation() { - if (!GetTestRunner()->TestIsRunning()) - return; +void WebWidgetTestProxy::RequestDecode( + const cc::PaintImage& image, + base::OnceCallback<void(bool)> callback) { + RenderWidget::RequestDecode(image, std::move(callback)); + // In web tests the request does not actually cause a commit, because the + // compositor is scheduled by the test runner to avoid flakiness. So for this + // case we must request a main frame the way blink would. + // + // Pass true for |do_raster| to ensure the compositor is actually run, rather + // than just doing the main frame animate step. + if (GetTestRunner()->TestIsRunning()) + ScheduleAnimationInternal(/*do_raster=*/true); +} + +void WebWidgetTestProxy::RequestPresentation( + PresentationTimeCallback callback) { + RenderWidget::RequestPresentation(std::move(callback)); + + // Single threaded web tests must explicitly schedule commits. + // + // Pass true for |do_raster| to ensure the compositor is actually run, rather + // than just doing the main frame animate step. That way we know it will + // submit a frame and later trigger the presentation callback in order to make + // progress in the test. + if (GetTestRunner()->TestIsRunning()) + ScheduleAnimationInternal(/*do_raster=*/true); +} + +void WebWidgetTestProxy::RequestPresentationForPixelDump( + PresentationTimeCallback callback) { + RenderWidget::RequestPresentation(std::move(callback)); + + // Like WebWidgetTestProxy::RequestPresentation, except: + // We don't check TestIsRunning() here because this path is used to get a + // callback at end of each test, which can race with TestIsRunning(). + // + // TestIsRunning() races with the presentation request because the first comes + // from various signals including IPC messages, while the second comes from a + // IPC message on a different mojo channel. + ScheduleAnimationInternal(/*do_raster=*/true); +} + +void WebWidgetTestProxy::ScheduleAnimation() { + if (GetTestRunner()->TestIsRunning()) + ScheduleAnimationInternal(GetTestRunner()->animation_requires_raster()); +} + +void WebWidgetTestProxy::ScheduleAnimationInternal(bool do_raster) { // When using threaded compositing, have the RenderWidget schedule a request // for a frame, as we use the compositor's scheduler. Otherwise the testing // WebWidgetClient schedules it. // Note that for WebWidgetTestProxy the RenderWidget is subclassed to override // the WebWidgetClient, so we must call up to the base class RenderWidget // explicitly here to jump out of the test harness as intended. - if (!RenderWidget::layer_tree_view()->CompositeIsSynchronousForTesting()) { + if (RenderWidget::compositor_deps()->GetCompositorImplThreadTaskRunner()) { RenderWidget::ScheduleAnimation(); return; } + // If an animation already scheduled we'll make it composite, otherwise we'll + // schedule another animation step with composite now. + composite_requested_ |= do_raster; + if (!animation_scheduled_) { animation_scheduled_ = true; GetWebViewTestProxy()->delegate()->PostDelayedTask( @@ -110,8 +160,48 @@ widget_input_handler_manager()->InvokeInputProcessedCallback(); } +TestRunnerForSpecificView* WebWidgetTestProxy::GetViewTestRunner() { + return GetWebViewTestProxy()->view_test_runner(); +} + +TestRunner* WebWidgetTestProxy::GetTestRunner() { + return GetWebViewTestProxy()->test_interfaces()->GetTestRunner(); +} + +static void DoComposite(content::RenderWidget* widget, bool do_raster) { + if (!widget->layer_tree_view()->layer_tree_host()->IsVisible()) + return; + + if (widget->in_synchronous_composite_for_testing()) { + // Web tests can use a nested message loop to pump frames while inside a + // frame, but the compositor does not support this. In this case, we only + // run blink's lifecycle updates. + widget->BeginMainFrame(base::TimeTicks::Now()); + widget->UpdateVisualState(); + return; + } + + // Ensure that there is damage so that the compositor submits, and the display + // compositor draws this frame. + if (do_raster) { + content::LayerTreeView* layer_tree_view = widget->layer_tree_view(); + layer_tree_view->layer_tree_host()->SetNeedsCommitWithForcedRedraw(); + } + + widget->set_in_synchronous_composite_for_testing(true); + widget->layer_tree_view()->layer_tree_host()->Composite( + base::TimeTicks::Now(), do_raster); + widget->set_in_synchronous_composite_for_testing(false); +} + void WebWidgetTestProxy::SynchronouslyComposite(bool do_raster) { - layer_tree_view()->SynchronouslyComposite(do_raster); + DCHECK(!compositor_deps()->GetCompositorImplThreadTaskRunner()); + DCHECK(!layer_tree_view() + ->layer_tree_host() + ->GetSettings() + .single_thread_proxy_scheduler); + + DoComposite(this, do_raster); // If the RenderWidget is for the main frame, we also composite the current // PagePopup afterward. @@ -124,23 +214,12 @@ if (blink::WebPagePopup* popup = view->GetPagePopup()) { auto* popup_render_widget = static_cast<RenderWidget*>(popup->GetClientForTesting()); - popup_render_widget->layer_tree_view()->SynchronouslyComposite(do_raster); + DoComposite(popup_render_widget, do_raster); } } } -TestRunnerForSpecificView* WebWidgetTestProxy::GetViewTestRunner() { - return GetWebViewTestProxy()->view_test_runner(); -} - -TestRunner* WebWidgetTestProxy::GetTestRunner() { - return GetWebViewTestProxy()->test_interfaces()->GetTestRunner(); -} - void WebWidgetTestProxy::AnimateNow() { - if (!animation_scheduled_) - return; - // For child local roots, it's possible that the backing WebWidget gets // closed between the ScheduleAnimation() call and this execution // leading to a nullptr. This happens because child local roots are @@ -156,10 +235,10 @@ if (!GetWebWidget()) return; + bool do_raster = composite_requested_; animation_scheduled_ = false; - CHECK(GetTestRunner()); - bool animation_requires_raster = GetTestRunner()->animation_requires_raster(); - SynchronouslyComposite(animation_requires_raster); + composite_requested_ = false; + SynchronouslyComposite(do_raster); } } // namespace test_runner
diff --git a/content/shell/test_runner/web_widget_test_proxy.h b/content/shell/test_runner/web_widget_test_proxy.h index 9fef1da8..61da7cd3 100644 --- a/content/shell/test_runner/web_widget_test_proxy.h +++ b/content/shell/test_runner/web_widget_test_proxy.h
@@ -57,6 +57,11 @@ explicit WebWidgetTestProxy(Args&&... args) : RenderWidget(std::forward<Args>(args)...) {} + // RenderWidget overrides. + void RequestDecode(const cc::PaintImage& image, + base::OnceCallback<void(bool)> callback) override; + void RequestPresentation(PresentationTimeCallback callback) override; + // WebWidgetClient implementation. void ScheduleAnimation() override; bool RequestPointerLock() override; @@ -82,6 +87,13 @@ void EndSyntheticGestures(); + // Triggers a full composite, and always submits a new frame to the display + // compositor. The |callback| will be run when the display compositor has + // presented that frame as part of its global scene. + void RequestPresentationForPixelDump(PresentationTimeCallback callback); + // When |do_raster| is false, only a main frame animation step is performed, + // but when true, a full composite is performed and a frame submitted to the + // display compositor if there is any damage. void SynchronouslyComposite(bool do_raster); private: @@ -91,12 +103,19 @@ TestRunnerForSpecificView* GetViewTestRunner(); TestRunner* GetTestRunner(); + void ScheduleAnimationInternal(bool do_raster); void AnimateNow(); EventSender event_sender_{this}; // For collapsing multiple simulated ScheduleAnimation() calls. bool animation_scheduled_ = false; + // When true, the scheduled AnimateNow() will perform a full composite. + // Otherwise, it will only perform the animation step, which calls out to + // blink, for performance reasons. See setAnimationRequiresRaster() in + // https://chromium.googlesource.com/chromium/src/+/master/docs/testing/writing_web_tests.md + // for details on the optimization. + bool composite_requested_ = false; base::WeakPtrFactory<WebWidgetTestProxy> weak_factory_{this};
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 6f0c240..14bd749 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -94,10 +94,9 @@ self.Skip('conformance2/rendering/texture-switch-performance.html', bug=735483) + # TODO(shrekshao): Remove after updating this test case. self.Fail('conformance2/rendering/depth-stencil-feedback-loop.html', bug=660844) # WebGL 2.0.1 - self.Fail('conformance/rendering/rendering-sampling-feedback-loop.html', - bug=660844) # WebGL 2.0.1 # Nvidia bugs fixed in latest driver # TODO(http://crbug.com/887241): Upgrade the drivers on the bots. @@ -348,6 +347,8 @@ # Passthrough command decoder self.Fail('conformance/misc/webgl-specific-stencil-settings.html', ['passthrough'], bug=844349) + self.Fail('conformance/rendering/rendering-sampling-feedback-loop.html', + ['passthrough'], bug=660844) # WebGL 2.0.1 # Passthrough command decoder / OpenGL self.Fail('conformance2/misc/uninitialized-test-2.html',
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 5674a3d..012a33ff 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -107,10 +107,6 @@ self.Fail('conformance/extensions/webgl-draw-buffers.html', bug=927908) - # Need to add detection of feedback loops with multiple render targets. - self.Fail('conformance/rendering/rendering-sampling-feedback-loop.html', - bug=660844) - # Need to implement new error semantics # https://github.com/KhronosGroup/WebGL/pull/2607 self.Fail('conformance/extensions/' + @@ -147,6 +143,9 @@ self.Fail('conformance/textures/canvas/' + 'tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html', ['passthrough', 'opengl'], bug=2952) # angle bug ID + # Need to add detection of feedback loops with multiple render targets. + self.Fail('conformance/rendering/rendering-sampling-feedback-loop.html', + ['passthrough'], bug=660844) # Intel graphics driver issue. Passed on 25.20.100.6471 self.Fail('conformance/glsl/constructors/glsl-construct-mat2.html', @@ -314,6 +313,9 @@ ['win', 'd3d9'], bug=617148) self.Skip('conformance/glsl/misc/large-loop-compile.html', ['win', 'd3d9'], bug=674572) + # Test needs GL_EXT_draw_buffers which is not supported + self.Skip('conformance/rendering/rendering-sampling-feedback-loop.html', + ['win', 'd3d9', 'no_passthrough']) # WIN / OpenGL / NVIDIA failures self.Fail('conformance/limits/gl-max-texture-dimensions.html', @@ -792,6 +794,9 @@ ['android', ('qualcomm', 'Adreno (TM) 418')], bug=610951) self.Flaky('conformance/limits/gl-max-texture-dimensions.html', ['android', ('qualcomm', 'Adreno (TM) 418'), 'passthrough'], bug=914631) + # Test needs GL_EXT_draw_buffers which is not supported + self.Skip('conformance/rendering/rendering-sampling-feedback-loop.html', + ['android', ('qualcomm', 'Adreno (TM) 418'), 'no_passthrough']) # Nexus 6 (Adreno 420) and 6P (Adreno 430) self.Fail('conformance/context/' +
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc index f495c7e..f37f0f7 100644 --- a/content/test/navigation_simulator_impl.cc +++ b/content/test/navigation_simulator_impl.cc
@@ -295,8 +295,6 @@ static_cast<WebContentsImpl*>(contents), test_frame_host)); simulator->frame_tree_node_ = frame_tree_node; simulator->InitializeFromStartedRequest(request); - simulator->set_did_create_new_entry( - contents->GetController().GetPendingEntryIndex() == -1); return simulator; } @@ -1175,10 +1173,22 @@ if (ui::PageTransitionCoreTypeIs(transition_, ui::PAGE_TRANSITION_AUTO_SUBFRAME)) return false; - if (reload_type_ != ReloadType::NONE) + if (reload_type_ != ReloadType::NONE || + (request_ && FrameMsg_Navigate_Type::IsReload( + request_->common_params().navigation_type))) { return false; - if (session_history_offset_) + } + if (session_history_offset_ || + (request_ && FrameMsg_Navigate_Type::IsHistory( + request_->common_params().navigation_type))) { return false; + } + if (request_ && (request_->common_params().navigation_type == + FrameMsg_Navigate_Type::RESTORE || + request_->common_params().navigation_type == + FrameMsg_Navigate_Type::RESTORE_WITH_POST)) { + return false; + } return true; } @@ -1218,6 +1228,9 @@ params->did_create_new_entry = DidCreateNewEntry(); params->should_replace_current_entry = should_replace_current_entry_; + if (intended_as_new_entry_.has_value()) + params->intended_as_new_entry = intended_as_new_entry_.value(); + if (failed_navigation) { // Note: Error pages must commit in a unique origin. So it is left unset. params->url_is_unreachable = true;
diff --git a/content/test/navigation_simulator_impl.h b/content/test/navigation_simulator_impl.h index 7f3f621..6c4cfff9 100644 --- a/content/test/navigation_simulator_impl.h +++ b/content/test/navigation_simulator_impl.h
@@ -120,6 +120,12 @@ should_replace_current_entry_ = should_replace_current_entry; } + // Manually force the value of intended_as_new_entry flag in DidCommit*Params + // to |intended_as_new_entry|. + void set_intended_as_new_entry(bool intended_as_new_entry) { + intended_as_new_entry_ = intended_as_new_entry; + } + void set_http_connection_info(net::HttpResponseInfo::ConnectionInfo info) { http_connection_info_ = info; } @@ -272,8 +278,9 @@ NavigationController::LoadURLParams* load_url_params_; bool history_list_was_cleared_ = false; - base::Optional<bool> did_create_new_entry_; bool should_replace_current_entry_ = false; + base::Optional<bool> did_create_new_entry_; + base::Optional<bool> intended_as_new_entry_; // These are used to sanity check the content/public/ API calls emitted as // part of the navigation.
diff --git a/device/vr/windows/compositor_base.cc b/device/vr/windows/compositor_base.cc index d4e0807..992804a 100644 --- a/device/vr/windows/compositor_base.cc +++ b/device/vr/windows/compositor_base.cc
@@ -138,6 +138,7 @@ presentation_binding_.Close(); frame_data_binding_.Close(); gamepad_provider_.Close(); + overlay_binding_.Close(); StopRuntime(); }
diff --git a/docs/security/permissions-for-powerful-web-platform-features.md b/docs/security/permissions-for-powerful-web-platform-features.md new file mode 100644 index 0000000..cb42175 --- /dev/null +++ b/docs/security/permissions-for-powerful-web-platform-features.md
@@ -0,0 +1,388 @@ +# Controlling Access to Powerful Web Platform Features + +_Author: [dominickn@chromium.org](mailto:dominickn@chromium.org)_ +_Contributors: [rorymcclelland@chromium.org](mailto:rorymcclelland@chromium.org)_ + +# Overview + +[Fugu](https://blog.chromium.org/2018/11/our-commitment-to-more-capable-web.html) + is a renewed effort to bring + [powerful new capabilities](https://bugs.chromium.org/p/chromium/issues/list?can=2&q=Proj%3DFugu+&colspec=ID+Pri+M+Stars+ReleaseBlock+Component+Status+Owner+Summary+OS+Modified&x=m&y=releaseblock&cells=ids) +to the web -- e.g. filesystem read/write access. Allowing users to control +which sites are able to access such APIs is crucial for maintaining the +security and privacy properties of the web. The impact of restrictions on the +developer ergonomics and user utility of the API and the web platform overall +must also be considered. + +This document explores approaches to guarding powerful APIs, e.g. using +[installed web app state](https://developers.google.com/web/progressive-web-apps/) +or some other proxy for high user +[engagement](https://www.chromium.org/developers/design-documents/site-engagement). +The following general principles summarise the overall approach of the +Chromium project to evaluating how powerful new features should be controlled +on the web: + ++ __Access to powerful APIs__ should be available to the entire web platform + of secure contexts, with control managed exclusively by choosers, prompts, + or other user consent UX at time-of-use. ++ __API-specific restrictions__ on the scope of access may also be used to + guard against potential abuse (e.g. constraints on available directories / + files, no access without a currently open foreground tab). ++ Usage of powerful APIs should be clearly __disclosed__ to users, ideally + using a central hub that offers users __control__ over what sites can use + which capabilities. ++ Installing a web app is associated with __persistence__, and thus + persistent and/or background access to powerful APIs may only be granted + (possibly subject to additional requirements) to installed web apps. + Non-installed sites may still request and be granted permission to use + powerful APIs, but should not have their access persisted. ++ Installation or engagement alone __should not act as a vote of trust__ for + either granting access or enabling the ability to ask for access to + powerful APIs. ++ Separately, efforts should be made to __curtail the existing persistency__ + on the web platform outside of installed web apps, e.g. time-limiting + permission grants, more aggressively expiring cookies, and restricting + background task execution. + +The remainder of this document explains the reasoning behind these principles, +and summarises why alternative proposals were not taken up. + +# Definition of Terms + ++ [__Powerful Web Platform APIs__](https://www.chromium.org/Home/chromium-security/prefer-secure-origins-for-powerful-new-features) + are capabilities which carry inherent security or privacy risks when used, + but also provide users of web apps with significant utility. A canonical + example is native file system access (i.e. allowing web sites to directly + read and write from certain locations on the user's device). Many such + capabilities already exist on the web in every browser (e.g. access to + camera and microphone hardware), while new capabilities are under constant + development. ++ [__Installation__](https://www.w3.org/TR/appmanifest/#installable-web-applications) + is the process where a web site may be elevated to run with a more native + UX treatment on a given platform and device. It is usually tied with being + granted a presence in the platform launcher (e.g. the desktop). ++ [__Progressive Web Apps__](https://developers.google.com/web/progressive-web-apps/) + (PWAs) are web sites which are designed to be installable. ++ [__Engagement__](https://www.chromium.org/developers/design-documents/site-engagement) + is a mechanism for measuring how much users interact with a site. Higher + engagement may be a signal that the user derives significant utility from + a site. + + +# Principles for Access to Powerful APIs + +This section outlines the general principles that the Chromium team believes +are critical when designing access to powerful new web platform APIs. These +principles will be considered when evaluating how new APIs are designed. + +## Control and Transparency + ++ Users must be able to see when the powerful APIs in use, and what sites + are using them. ++ Users may revoke access to powerful APIs at any time, and preferably, + the revocation UI should be intuitive to locate based on how permission is + granted and/or disclosed to the user. ++ The principle of least privilege should apply as broadly as possible: + users should not have to grant access to more resources than necessary to + achieve their goals. + +## User Ergonomics + ++ The web platform should be fully functional without requiring + installation. ++ Sites must not be able to easily socially-engineer the user into + granting permissions they wouldn't otherwise want to. ++ As much as is practical, users should not be bombarded with permission + prompts, as this leads to decision fatigue. + +## Developer Predictability + ++ Developers must be able to know when they can and cannot access + powerful APIs. ++ Access mechanisms should be cross-browser compatible. + +# Proposal + +### Baseline: secure contexts, top-level frames, user gesture + +Minimally, all new powerful APIs must only be available in +[secure contexts](https://www.chromium.org/Home/chromium-security/deprecating-powerful-features-on-insecure-origins). +Ideally, availability is restricted to top-level frames and requires a user +gesture to trigger. When a webpage is running in a secure context in +a top-level frame with an active user gesture, we call this situation +a __baseline context__. + +[Browser extensions](https://developer.chrome.com/extensions) are also +included as a baseline context, as they can already make use of web platform +APIs (subject to the same access checks as web sites). + +The +[permission delegation](https://docs.google.com/document/d/1x5QejvpyQ71LPWhMLsaM1lWCfSsBsSQ8Dap9kJ6uLv0/preview?ts=5b857603#heading=h.ib6rctasbt3y) +mechanism may be used to extend privileges to iframes on a page if it makes +sense for a powerful capability to be delegated in this way. + +### The entire web platform may access new powerful APIs + +In general, any baseline context may access powerful APIs, regardless of its +windowing state (in the tabbed browser or in a standalone app window), +installation state (installed or not), or user engagement (highly interacted +with or not). This avoids the __fragmentation of the web__ into different, +sometimes unpredictable states, and encourages careful consideration of new +API surfaces such that they are exposed in a way that is safe for the web at +large. + +### Session-based access is granted by direct user consent + +In general, access to powerful APIs must be mediated by direct, informed user +consent while the requesting site is open in a foreground tab via mechanisms +which may include: + ++ choosers ++ prompts + +These mechanisms must clearly disclose the origin of the request, and follow +Chromium's +[guidelines on displaying URLs](https://chromium.googlesource.com/chromium/src/+/master/docs/security/url_display_guidelines/url_display_guidelines.md). +Implementations may be tested using tools such as +[Trickuri](https://github.com/chromium/trickuri). + +As much as possible, APIs should avoid a "double prompt", e.g. a permission +prompt requesting access to the file system, followed by a chooser to pick the +file/directory to access. There is little security or privacy benefit to such +a double prompt, and it detrimentally affects user and developer ergonomics. + +There are cases where double prompts are unavoidable, e.g. a web site may +request access to contact information, and if the user grants access, the +browser may need to request OS-level permission to service the request. + +In some cases, Chromium may implicitly grant access to an API if it is not +particularly dangerous or does not make sense to guard behind a permission +consent. An example of this is the +[Badging API](https://github.com/WICG/badging/blob/master/explainer.md), which +only works for installed web apps, and results in a subtle badging effect on +the installed app icon that is not invasive or privacy-sensitive. These cases +should be relatively rare considering the powerful APIs that are covered by +this document. + +The scope of access to APIs follows the web's same-origin model. + +### Persistent and/or background access is restricted to installed apps + +The only definite capability granted by installation is __persistence__. By +installing, the user has explicitly indicated that they want the web app to +have a persistent presence on their system. + +New powerful APIs should exclusively use session-based permissions for web +sites that are not installed. In particular, there should be no access while +the site is not open in a tab, and access cannot be requested from a +non-foreground tab. When the site is closed or navigated away from, it loses +any granted access to powerful APIs it had, and must re-ask for access the +next time the user visits. + +Installed web sites _may_ instead receive a permanent grant, which is removed +when the site is uninstalled. In this way, installed web sites _may_ be +granted the ability to access capabilities in the background, depending on the +particular details of each capability. It also avoids overloading the +installation decision with consequences that users may not expect. + +Persistency for installed web sites may have other requirements, but +non-installed sites may never receive persistent grants to access powerful new +APIs. + +Some powerful APIs act as a proxy for persistence (e.g. a web site with +permission to write files to disk). We distinguish persistence via a currently +granted capability from __persistent access to the capability itself__; it is +the latter privilege which is granted by being installed. + +### Disclose access and provide obvious user controls + +It should be obvious to users when sites are using powerful APIs, and they +should be given the tools needed to effectively manage and revoke access when +necessary. + +### Improve permissions and installation UX to avoid decision fatigue + +Removing persistent access from the drive-by web may drive up +[decision fatigue](https://en.wikipedia.org/wiki/Decision_fatigue) due to +overprompting. However, we anticipate that many of these capabilities will +have relatively niche applications that the drive-by web should not commonly +access. + +Repeated granting of access to powerful APIs can be used as a signal for +installation. For instance, after two successful powerful permission grants, +Chromium could present the user with the option to install the app on the +third permission request. + +### Administrator policies may override prompts and enforce persistence + +Powerful new capabilities may be paired with +[Chromium policies](https://www.chromium.org/administrators/policy-list-3) +which permit administrators to enforce persisted access to capabilities +without prompts. Capabilities may also be restricted or blocked by such +policies. This is in line with how many existing permissions have admin policy +overrides. + +### Explore ways of curtailing the lifetime of existing persistence + +Currently, web sites which are not installed have access to significant +persistence mechanisms: + ++ all existing permissions have their decisions persisted indefinitely ++ cookie and local storage lifetime may be indefinite + +To better align the existing web to the proposal presented here, we suggest a +parallel effort to apply new lifetime limits on existing persistence +mechanisms. For example, some of the following measures could be explored: + ++ forget any granted permissions if the site has not been visited in X weeks + + this could be challenging to apply for some capabilities such as push + notifications, where there is a use case for a site being able to send + informative notifications without ever needing to be opened. ++ ignore cookie Max-Age headers for non-installed sites, and erase cookies + when the associated URL is no longer in browser history. ++ restrict durable/persistent storage to installed apps. ++ limit the storage quota available to sites unless they are installed (and + conversely, raise storage quota limits for installed sites). ++ restrict what Service Workers may do in the background unless they control + a site that is installed. + +# Case Study -- Native File System Access + +We describe a high level case study based on the principles in this document +for granting a web site access to a) read any file in a certain directory; b) +write files to a directory. + +## Granting access + ++ The user must give direct consent via a file picker. ++ The browser should disclose that access to the chosen file or directory + will be granted to the web site. ++ A non-installed site will trigger the picker each page load that the API + to read or write to a directory is invoked. ++ An installed site will have its access to reading or writing persisted. + +## Additional considerations for writing to a directory + ++ Existing Downloads UI and protections (e.g. malicious file scanning) + could be employed to ensure sites cannot use writing to a directory as a + bypass. ++ Where such scanning isn't accessible, confirmation prompts for opening + dangerous files in the Downloads UI may be employed instead to ensure the + user knows if a potentially malicious file type is being stored. ++ Non-installed sites may have additional restrictions on which folders + are available to choose (e.g. only allowing the user's Downloads directory, + or excluding the user's Documents directory). + +# Alternatives Considered + +## Guard API Access Behind Installation + +Apps on any desktop or mobile platform require installation to run, and when +installed, apps are automatically granted many privileges. We could extend +this concept to the web by restricting powerful APIs like native file system +access only to installed web apps. That is, the drive-by web could not even +ask for permission to access an API -- the site would need to be installed. + +A key argument for using installation in this manner is that some APIs are +simply so powerful that the drive-by web should not be able to ask for them. +However, this document takes the position that installation alone as a +restriction is undesirable. + +### Pros: + ++ This is a simple model that is both user controllable and + developer-accessible (via installation APIs such as + [beforeinstallpromptevent](https://developers.google.com/web/fundamentals/app-install-banners/)). ++ Installation is already synonymous with some amount of elevated privilege + on most platforms. + +### Cons: + ++ Fragments the web platform into installed and not installed, with + different APIs available depending on installed state. ++ Disempowers the drive-by web, and undermines the "try-before-you-buy" + ability that the web affords today. Users may also not be willing to + install a site from which they cannot ascertain any benefit. ++ Forces users to install a site to use it, even if they don't want to + install. ++ May encourage web sites to prompt users on every visit to install the PWA + to get access to powerful features. ++ Creates confusing scenarios when web apps are running in tabs: + + If a web app is installed but the user opens the site in a + tab, does it get access to the capability or not? + + What about if the web app starts off in a standalone window, but + the user reparents it into a tab? Or if a user sets an installed app to + open in a tab? ++ Platforms where installation grants privilege all incur additional + friction during installation that the web currently does not exhibit. + Examples include: + + requiring something to be downloaded, + + requiring a confirmation prompt, installer, or some explicit + privilege or grant during installation, + + requiring an explicit display of permissions that are implicitly + granted. ++ The implicit granting of privilege by installation has proven to be a + security and privacy challenge on many platforms, e.g. Android native apps + can access many + [powerful features](https://developer.android.com/guide/topics/permissions/overview#normal-dangerous) + with no permission prompt and without user recourse to revoke access. ++ The amount of friction generated by PWA installation over the drive-by + web is unclear, and gating APIs behind installation increases the + incentive for tricking users into installing. + +### Security considerations: + +Restricting APIs to installed web apps is not a meaningful security improvement +for users for several reasons: + ++ While it eliminates the drive-by web as an attack surface, per-API + security mitigations (e.g. restricting which directories are accessible + for reading and writing) would still be necessary to protect users of + installed web apps. ++ The effectiveness of installation as a gate on access to powerful APIs + weakens as the installed web app model becomes more successful. ++ Developers are incentivised to ask for installation to utilise powerful + capabilities, contributing to the erosion of installation as an effective + security mitigation. ++ Per-API permission requests would still be necessary in the installed + state, making installation effectively equivalent to an implicit permission + grant to ask for permission to access powerful features. We should simply + ask users directly if they wish to grant permission, rather than use such a + two-tiered requirement. + +## Guard API Access Behind Engagement + +This is a more general concept than installation: that continual, significant +usage of a web site should allow that site to access more powerful APIs. + +### Pros: + ++ Continual usage of a web site can be taken as a signal of trust + +### Cons: + ++ Engagement is not standardised or exposed to the web platform, making + it a highly unpredictable and unergonomic mechanism of controlling access. + + Standardisation and a web-exposed API would both be requirements for + using engagement in this way. Chromium's current engagement + implementation is local-only and not web-exposed. There are serious + privacy questions about exposing such data to the web. ++ Solving the first-run problem is non-trivial: engagement requires usage + to accumulate, but there are apps which legitimately require access to a + powerful API immediately to function (e.g. an editor -> files, or a + weather site -> location). + +### Security considerations: + ++ There is no real evidence to support the implicit assumption under + this model that continual usage of a web site correlates with user consent + to access powerful features. + + Consider users who frequently use some web site for which location + data is useful, but denies that site persistent, background access to + geolocation permission. + + A proportion of web traffic goes to sites which users may interact + with frequently, but may not necessarily want to grant powerful + capabilities. + +Similar to installation, the Chromium team does not regard engagement as a +robust way of controlling access to APIs.
diff --git a/extensions/browser/api/management/management_api.cc b/extensions/browser/api/management/management_api.cc index 651f5744..0a131a33 100644 --- a/extensions/browser/api/management/management_api.cc +++ b/extensions/browser/api/management/management_api.cc
@@ -82,15 +82,7 @@ } launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB); - - // TODO(dominickn): remove check when hosted apps can open in windows on Mac. - if (delegate->CanHostedAppsOpenInWindows()) - launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW); - - if (!delegate->IsNewBookmarkAppsEnabled()) { - launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB); - launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_FULL_SCREEN); - } + launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW); return launch_type_list; }
diff --git a/extensions/browser/api/management/management_api_delegate.h b/extensions/browser/api/management/management_api_delegate.h index 13a46e5..3136455 100644 --- a/extensions/browser/api/management/management_api_delegate.h +++ b/extensions/browser/api/management/management_api_delegate.h
@@ -54,14 +54,6 @@ const Extension* extension, content::BrowserContext* context) const = 0; - // Forwards the call to extensions::util::IsNewBookmarkAppsEnabled in - // chrome. - virtual bool IsNewBookmarkAppsEnabled() const = 0; - - // Forwards the call to extensions::util::CanHostedAppsOpenInWindows in - // chrome. - virtual bool CanHostedAppsOpenInWindows() const = 0; - // Forwards the call to AppLaunchInfo::GetFullLaunchURL in chrome. virtual GURL GetFullLaunchURL(const Extension* extension) const = 0;
diff --git a/gpu/command_buffer/service/external_vk_image_skia_representation.cc b/gpu/command_buffer/service/external_vk_image_skia_representation.cc index 9650cd99..4f3c162 100644 --- a/gpu/command_buffer/service/external_vk_image_skia_representation.cc +++ b/gpu/command_buffer/service/external_vk_image_skia_representation.cc
@@ -47,7 +47,8 @@ GrContext* gr_context, int final_msaa_count, const SkSurfaceProps& surface_props) { - DCHECK(!surface_) << "Previous access hasn't ended yet"; + DCHECK_EQ(access_mode_, kNone) << "Previous access hasn't ended yet"; + DCHECK(!surface_); auto promise_texture = BeginAccess(false /* readonly */); if (!promise_texture) @@ -58,38 +59,42 @@ gr_context, promise_texture->backendTexture(), kTopLeft_GrSurfaceOrigin, final_msaa_count, sk_color_type, backing_impl()->color_space().ToSkColorSpace(), &surface_props); + access_mode_ = kWrite; return surface_; } void ExternalVkImageSkiaRepresentation::EndWriteAccess( sk_sp<SkSurface> surface) { - DCHECK(surface_) << "EndWriteAccess is called before BeginWriteAccess"; + DCHECK_EQ(access_mode_, kWrite) + << "EndWriteAccess is called before BeginWriteAccess"; + DCHECK(surface_); surface_ = nullptr; EndAccess(false /* readonly */); + access_mode_ = kNone; } -sk_sp<SkPromiseImageTexture> ExternalVkImageSkiaRepresentation::BeginReadAccess( - SkSurface* sk_surface) { - DCHECK(!surface_) << "Previous access hasn't ended yet"; +sk_sp<SkPromiseImageTexture> +ExternalVkImageSkiaRepresentation::BeginReadAccess() { + DCHECK_EQ(access_mode_, kNone) << "Previous access hasn't ended yet"; + DCHECK(!surface_); auto promise_texture = BeginAccess(true /* readonly */); if (!promise_texture) return nullptr; - - // Cache the sk surface in the representation so that it can be used in the - // EndReadAccess. - surface_ = sk_ref_sp(sk_surface); + access_mode_ = kRead; return promise_texture; } void ExternalVkImageSkiaRepresentation::EndReadAccess() { - DCHECK(surface_) << "EndReadAccess is called before BeginReadAccess"; - surface_ = nullptr; + DCHECK_EQ(access_mode_, kRead) + << "EndReadAccess is called before BeginReadAccess"; EndAccess(true /* readonly */); + access_mode_ = kNone; } sk_sp<SkPromiseImageTexture> ExternalVkImageSkiaRepresentation::BeginAccess( bool readonly) { + DCHECK_EQ(access_mode_, kNone); DestroySemaphores(std::move(begin_access_semaphores_), begin_access_fence_); begin_access_semaphores_.clear(); @@ -131,6 +136,7 @@ } void ExternalVkImageSkiaRepresentation::EndAccess(bool readonly) { + DCHECK_NE(access_mode_, kNone); // Cleanup resources for previous accessing. DestroySemaphore(end_access_semaphore_, end_access_fence_);
diff --git a/gpu/command_buffer/service/external_vk_image_skia_representation.h b/gpu/command_buffer/service/external_vk_image_skia_representation.h index 029d88e..5dddc5f 100644 --- a/gpu/command_buffer/service/external_vk_image_skia_representation.h +++ b/gpu/command_buffer/service/external_vk_image_skia_representation.h
@@ -29,7 +29,7 @@ int final_msaa_count, const SkSurfaceProps& surface_props) override; void EndWriteAccess(sk_sp<SkSurface> surface) override; - sk_sp<SkPromiseImageTexture> BeginReadAccess(SkSurface* sk_surface) override; + sk_sp<SkPromiseImageTexture> BeginReadAccess() override; void EndReadAccess() override; private: @@ -69,6 +69,12 @@ VkFence CreateFence(); + enum AccessMode { + kNone = 0, + kRead = 1, + kWrite = 2, + }; + AccessMode access_mode_ = kNone; sk_sp<SkSurface> surface_; std::vector<VkSemaphore> begin_access_semaphores_;
diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc index dab9457..f801bb4 100644 --- a/gpu/command_buffer/service/framebuffer_manager.cc +++ b/gpu/command_buffer/service/framebuffer_manager.cc
@@ -385,6 +385,7 @@ draw_buffer_float32_mask_(0u), draw_buffer_bound_mask_(0u), adjusted_draw_buffer_bound_mask_(0u), + last_color_attachment_id_(-1), read_buffer_(GL_COLOR_ATTACHMENT0) { manager->StartTracking(this); DCHECK_GT(manager->max_draw_buffers_, 0u); @@ -969,7 +970,6 @@ size_t shift_bits = index * 2; draw_buffer_type_mask_ |= base_type << shift_bits; draw_buffer_bound_mask_ |= 0x3 << shift_bits; - if (GLES2Util::IsFloat32Format(internal_format)) { draw_buffer_float32_mask_ |= 0x3 << shift_bits; } @@ -998,6 +998,29 @@ } } +void Framebuffer::OnInsertUpdateLastColorAttachmentId(GLenum attachment) { + if (attachment >= GL_COLOR_ATTACHMENT0 && + attachment < GL_COLOR_ATTACHMENT0 + manager_->max_color_attachments_) { + last_color_attachment_id_ = + std::max(last_color_attachment_id_, + static_cast<GLsizei>(attachment - GL_COLOR_ATTACHMENT0)); + } +} + +void Framebuffer::OnEraseUpdateLastColorAttachmentId(GLenum attachment) { + if (attachment >= GL_COLOR_ATTACHMENT0 && + attachment < GL_COLOR_ATTACHMENT0 + manager_->max_color_attachments_ && + static_cast<GLsizei>(attachment - GL_COLOR_ATTACHMENT0) == + last_color_attachment_id_) { + for (last_color_attachment_id_--; last_color_attachment_id_ >= 0; + last_color_attachment_id_--) { + if (attachments_.find(GL_COLOR_ATTACHMENT0 + last_color_attachment_id_) != + attachments_.end()) + break; + } + } +} + void Framebuffer::AttachRenderbuffer( GLenum attachment, Renderbuffer* renderbuffer) { DCHECK_NE(static_cast<GLenum>(GL_DEPTH_STENCIL_ATTACHMENT), attachment); @@ -1008,8 +1031,10 @@ attachments_[attachment] = scoped_refptr<Attachment>( new RenderbufferAttachment(renderbuffer)); renderbuffer->AddFramebufferAttachmentPoint(this, attachment); + OnInsertUpdateLastColorAttachmentId(attachment); } else { attachments_.erase(attachment); + OnEraseUpdateLastColorAttachmentId(attachment); } UnmarkAsComplete(); } @@ -1025,8 +1050,10 @@ attachments_[attachment] = scoped_refptr<Attachment>( new TextureAttachment(texture_ref, target, level, samples, 0)); texture_ref->texture()->AttachToFramebuffer(); + OnInsertUpdateLastColorAttachmentId(attachment); } else { attachments_.erase(attachment); + OnEraseUpdateLastColorAttachmentId(attachment); } UnmarkAsComplete(); } @@ -1042,8 +1069,10 @@ attachments_[attachment] = scoped_refptr<Attachment>( new TextureAttachment(texture_ref, target, level, 0, layer)); texture_ref->texture()->AttachToFramebuffer(); + OnInsertUpdateLastColorAttachmentId(attachment); } else { attachments_.erase(attachment); + OnEraseUpdateLastColorAttachmentId(attachment); } UnmarkAsComplete(); }
diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h index f48538e..794df67 100644 --- a/gpu/command_buffer/service/framebuffer_manager.h +++ b/gpu/command_buffer/service/framebuffer_manager.h
@@ -156,6 +156,7 @@ bool HasDepthAttachment() const; bool HasStencilAttachment() const; bool HasActiveFloat32ColorAttachment() const; + GLsizei last_color_attachment_id() const { return last_color_attachment_id_; } GLenum GetDepthFormat() const; GLenum GetStencilFormat() const; GLenum GetDrawBufferInternalFormat() const; @@ -241,6 +242,11 @@ ~Framebuffer(); + // Helper function updating cached last color attachment id bound. + // Called when attachments_ changed + void OnInsertUpdateLastColorAttachmentId(GLenum attachment); + void OnEraseUpdateLastColorAttachmentId(GLenum attachment); + void MarkAsDeleted(); void MarkAttachmentsAsCleared( @@ -304,6 +310,8 @@ uint32_t draw_buffer_bound_mask_; // This is the mask for the actual draw buffers sent to driver. uint32_t adjusted_draw_buffer_bound_mask_; + // The largest i of all GL_COLOR_ATTACHMENTi + GLsizei last_color_attachment_id_; GLenum read_buffer_;
diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc index 787123b..a19ffa39 100644 --- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc +++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
@@ -1419,6 +1419,96 @@ EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) == nullptr); } +TEST_F(FramebufferInfoTest, LastColorAttachmentIdTest) { + const GLuint kTextureClient1Id = 33; + const GLuint kTextureService1Id = 333; + const GLuint kTextureClient2Id = 34; + const GLuint kTextureService2Id = 334; + const GLuint kTextureClient3Id = 35; + const GLuint kTextureService3Id = 335; + const GLuint kRenderbufferClientId = 36; + const GLuint kRenderbufferServiceId = 336; + const GLuint kTextureLayerClientId = 37; + const GLuint kTextureLayerServiceId = 337; + + const GLenum kTarget1 = GL_TEXTURE_2D; + const GLint kLevel1 = 0; + const GLint kSamples1 = 0; + + const GLenum kTargetTextureLayer = GL_TEXTURE_2D_ARRAY; + const GLint kBorder = 0; + const GLenum kType = GL_UNSIGNED_BYTE; + const GLsizei kWidth = 16; + const GLsizei kHeight = 32; + const GLint kDepth = 2; + const GLint kLevel = 0; + const GLenum kFormat = GL_RGBA; + const GLsizei kLayer = 0; + + texture_manager_->CreateTexture(kTextureClient1Id, kTextureService1Id); + scoped_refptr<TextureRef> texture1( + texture_manager_->GetTexture(kTextureClient1Id)); + ASSERT_TRUE(texture1.get() != nullptr); + texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id); + scoped_refptr<TextureRef> texture2( + texture_manager_->GetTexture(kTextureClient2Id)); + ASSERT_TRUE(texture2.get() != nullptr); + texture_manager_->CreateTexture(kTextureClient3Id, kTextureService3Id); + scoped_refptr<TextureRef> texture3( + texture_manager_->GetTexture(kTextureClient3Id)); + ASSERT_TRUE(texture3.get() != nullptr); + + renderbuffer_manager_->CreateRenderbuffer(kRenderbufferClientId, + kRenderbufferServiceId); + Renderbuffer* renderbuffer = + renderbuffer_manager_->GetRenderbuffer(kRenderbufferClientId); + ASSERT_TRUE(renderbuffer != nullptr); + + texture_manager_->CreateTexture(kTextureLayerClientId, + kTextureLayerServiceId); + scoped_refptr<TextureRef> textureLayer( + texture_manager_->GetTexture(kTextureLayerClientId)); + ASSERT_TRUE(textureLayer.get()); + + texture_manager_->SetTarget(textureLayer.get(), kTargetTextureLayer); + texture_manager_->SetLevelInfo(textureLayer.get(), kTargetTextureLayer, + kLevel, kFormat, kWidth, kHeight, kDepth, + kBorder, kFormat, kType, gfx::Rect()); + + EXPECT_EQ(framebuffer_->last_color_attachment_id(), -1); + framebuffer_->AttachTexture(GL_COLOR_ATTACHMENT0, texture1.get(), kTarget1, + kLevel1, kSamples1); + EXPECT_EQ(framebuffer_->last_color_attachment_id(), 0); + framebuffer_->AttachTexture(GL_COLOR_ATTACHMENT2, texture3.get(), kTarget1, + kLevel1, kSamples1); + EXPECT_EQ(framebuffer_->last_color_attachment_id(), 2); + framebuffer_->AttachTexture(GL_COLOR_ATTACHMENT1, texture2.get(), kTarget1, + kLevel1, kSamples1); + EXPECT_EQ(framebuffer_->last_color_attachment_id(), 2); + framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, renderbuffer); + EXPECT_EQ(framebuffer_->last_color_attachment_id(), 2); + framebuffer_->AttachRenderbuffer(GL_COLOR_ATTACHMENT3, renderbuffer); + EXPECT_EQ(framebuffer_->last_color_attachment_id(), 3); + framebuffer_->AttachTexture(GL_COLOR_ATTACHMENT4, texture1.get(), kTarget1, + kLevel1, kSamples1); + EXPECT_EQ(framebuffer_->last_color_attachment_id(), 4); + EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) != nullptr); + framebuffer_->AttachTextureLayer(GL_COLOR_ATTACHMENT5, textureLayer.get(), + kTargetTextureLayer, kLevel, kLayer); + EXPECT_EQ(framebuffer_->last_color_attachment_id(), 5); + + framebuffer_->UnbindTexture(kTargetTextureLayer, textureLayer.get()); + EXPECT_EQ(framebuffer_->last_color_attachment_id(), 4); + framebuffer_->UnbindTexture(kTarget1, texture2.get()); + EXPECT_EQ(framebuffer_->last_color_attachment_id(), 4); + framebuffer_->UnbindTexture(kTarget1, texture1.get()); + EXPECT_EQ(framebuffer_->last_color_attachment_id(), 3); + framebuffer_->UnbindRenderbuffer(GL_COLOR_ATTACHMENT3, renderbuffer); + EXPECT_EQ(framebuffer_->last_color_attachment_id(), 2); + framebuffer_->UnbindTexture(kTarget1, texture3.get()); + EXPECT_EQ(framebuffer_->last_color_attachment_id(), -1); +} + TEST_F(FramebufferInfoTest, IsCompleteMarkAsComplete) { const GLuint kRenderbufferClient1Id = 33; const GLuint kRenderbufferService1Id = 333;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 0d85a6f..2f2e98b2 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -1536,10 +1536,12 @@ // location is not -1. bool CheckCurrentProgramForUniform(GLint location, const char* function_name); - // Checks if the current program samples a texture that is also the color - // image of the current bound framebuffer, i.e., the source and destination - // of the draw operation are the same. - bool CheckDrawingFeedbackLoops(); + // Helper for CheckDrawingFeedbackLoops. Returns true if the attachment is + // the same one where it samples from during drawing. + bool CheckDrawingFeedbackLoopsHelper( + const Framebuffer::Attachment* attachment, + TextureRef* texture_ref, + const char* function_name); bool SupportsDrawBuffers() const; @@ -9935,32 +9937,15 @@ location); } -bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() { - Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER); - if (!framebuffer) - return false; - const Framebuffer::Attachment* attachment = - framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0); - if (!attachment) - return false; - - DCHECK(state_.current_program.get()); - const Program::SamplerIndices& sampler_indices = - state_.current_program->sampler_indices(); - for (size_t ii = 0; ii < sampler_indices.size(); ++ii) { - const Program::UniformInfo* uniform_info = - state_.current_program->GetUniformInfo(sampler_indices[ii]); - DCHECK(uniform_info); - for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) { - GLuint texture_unit_index = uniform_info->texture_units[jj]; - if (texture_unit_index >= state_.texture_units.size()) - continue; - TextureUnit& texture_unit = state_.texture_units[texture_unit_index]; - TextureRef* texture_ref = - texture_unit.GetInfoForSamplerType(uniform_info->type); - if (attachment->IsTexture(texture_ref)) - return true; - } +bool GLES2DecoderImpl::CheckDrawingFeedbackLoopsHelper( + const Framebuffer::Attachment* attachment, + TextureRef* texture_ref, + const char* function_name) { + if (attachment && attachment->IsTexture(texture_ref)) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, function_name, + "Source and destination textures of the draw are the same."); + return true; } return false; } @@ -10691,6 +10676,27 @@ TextureUnit& texture_unit = state_.texture_units[texture_unit_index]; TextureRef* texture_ref = texture_unit.GetInfoForSamplerType(uniform_info->type); + + // Find if the texture is also a depth or stencil attachment + // Regardless of whether depth/stencil writes and masks are enabled + // If so, there's a drawing feedback loop. + + Framebuffer* framebuffer = + GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER); + if (framebuffer) { + if (CheckDrawingFeedbackLoopsHelper( + framebuffer->GetAttachment(GL_DEPTH_ATTACHMENT), texture_ref, + function_name)) { + return false; + } + + if (CheckDrawingFeedbackLoopsHelper( + framebuffer->GetAttachment(GL_STENCIL_ATTACHMENT), + texture_ref, function_name)) { + return false; + } + } + GLenum textarget = GetBindTargetForSamplerType(uniform_info->type); const SamplerState& sampler_state = GetSamplerStateForTextureUnit( uniform_info->type, texture_unit_index); @@ -10728,6 +10734,21 @@ return false; } + // Find if the texture is also a color attachment + // If so, there's a drawing feedback loop. + + if (framebuffer) { + for (GLsizei kk = 0; kk <= framebuffer->last_color_attachment_id(); + ++kk) { + GLenum attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + kk); + if (CheckDrawingFeedbackLoopsHelper( + framebuffer->GetAttachment(attachment), texture_ref, + function_name)) { + return false; + } + } + } + if (textarget != GL_TEXTURE_CUBE_MAP) { Texture* texture = texture_ref->texture(); if (DoBindOrCopyTexImageIfNeeded(texture, textarget, @@ -10865,13 +10886,6 @@ } } - if (CheckDrawingFeedbackLoops()) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, function_name, - "Source and destination textures of the draw are the same."); - return false; - } - if (!state_.vertex_attrib_manager->ValidateBindings( function_name, this, feature_info_.get(), buffer_manager(), state_.current_program.get(), max_vertex_accessed, instanced,
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc index b60e67a..e64c55c 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc
@@ -57,6 +57,21 @@ kWrite, }; +std::ostream& operator<<(std::ostream& os, RepresentationAccessMode mode) { + switch (mode) { + case RepresentationAccessMode::kNone: + os << "kNone"; + break; + case RepresentationAccessMode::kRead: + os << "kRead"; + break; + case RepresentationAccessMode::kWrite: + os << "kWrite"; + break; + } + return os; +} + void DestroySemaphore(VkDevice vk_device, VkQueue vk_queue, VkSemaphore semaphore) { @@ -121,7 +136,6 @@ void EndVulkanAccess(gpu::VulkanImplementation* vk_implementation, VkDevice vk_device, VkQueue vk_queue, - SkSurface** surface, base::ScopedFD* sync_fd) { // Create a vk semaphore which can be exported. VkExportSemaphoreCreateInfo export_info; @@ -138,23 +152,15 @@ vkCreateSemaphore(vk_device, &sem_info, nullptr, &vk_semaphore); if (result != VK_SUCCESS) { LOG(ERROR) << "vkCreateSemaphore failed"; - (*surface) = nullptr; return; } - GrBackendSemaphore gr_semaphore; - gr_semaphore.initVulkan(vk_semaphore); - // If GrSemaphoresSubmitted::kNo is returned, the GPU back-end did not - // create or add any semaphores to signal on the GPU; the caller should not - // instruct the GPU to wait on any of the semaphores. - if ((*surface)->flushAndSignalSemaphores(1, &gr_semaphore) == - GrSemaphoresSubmitted::kNo) { + if (!SubmitSignalVkSemaphore(vk_queue, vk_semaphore, + VK_NULL_HANDLE /* vk_fence */)) { + LOG(ERROR) << "Failed to wait on semaphore"; vkDestroySemaphore(vk_device, vk_semaphore, nullptr); - (*surface) = nullptr; return; } - // TODO(ericrk): Keep the surface around for re-use. - (*surface) = nullptr; // Export a sync fd from the semaphore. SemaphoreHandle semaphore_handle = @@ -345,11 +351,12 @@ GrContext* gr_context, int final_msaa_count, const SkSurfaceProps& surface_props) override { + DCHECK_EQ(mode_, RepresentationAccessMode::kNone); CheckContext(); + // if there is already a surface_, it means previous BeginWriteAccess // doesn't have a corresponding EndWriteAccess. - if (surface_) - return nullptr; + DCHECK(!surface_); base::ScopedFD sync_fd; if (!ahb_backing()->BeginWrite(&sync_fd)) @@ -374,6 +381,7 @@ } void EndWriteAccess(sk_sp<SkSurface> surface) override { + DCHECK_EQ(mode_, RepresentationAccessMode::kWrite); DCHECK(surface_); DCHECK_EQ(surface.get(), surface_); DCHECK(surface->unique()); @@ -383,8 +391,10 @@ EndWriteAccessInternal(); } - sk_sp<SkPromiseImageTexture> BeginReadAccess(SkSurface* sk_surface) override { + sk_sp<SkPromiseImageTexture> BeginReadAccess() override { + DCHECK_EQ(mode_, RepresentationAccessMode::kNone); CheckContext(); + base::ScopedFD write_sync_fd; if (!ahb_backing()->BeginRead(this, &write_sync_fd)) return nullptr; @@ -397,6 +407,7 @@ } void EndReadAccess() override { + DCHECK_EQ(mode_, RepresentationAccessMode::kRead); CheckContext(); base::ScopedFD sync_fd = CreateEglFenceAndExportFd(); @@ -459,12 +470,7 @@ } ~SharedImageRepresentationSkiaVkAHB() override { - if (mode_ == RepresentationAccessMode::kRead) { - EndReadAccess(); - } else if (mode_ == RepresentationAccessMode::kWrite) { - EndWriteAccessInternal(); - } - + DCHECK_EQ(mode_, RepresentationAccessMode::kNone); DCHECK(!surface_); } @@ -472,9 +478,9 @@ GrContext* gr_context, int final_msaa_count, const SkSurfaceProps& surface_props) override { + DCHECK_EQ(mode_, RepresentationAccessMode::kNone); // If previous access has not ended. - if (surface_) - return nullptr; + DCHECK(!surface_); base::ScopedFD sync_fd; if (!ahb_backing()->BeginWrite(&sync_fd)) @@ -520,16 +526,14 @@ } void EndWriteAccess(sk_sp<SkSurface> surface) override { + DCHECK_EQ(mode_, RepresentationAccessMode::kWrite); DCHECK_EQ(surface.get(), surface_); DCHECK(surface->unique()); EndWriteAccessInternal(); } - sk_sp<SkPromiseImageTexture> BeginReadAccess(SkSurface* sk_surface) override { - // If previous access has not ended. - if (surface_) - return nullptr; - DCHECK(sk_surface); + sk_sp<SkPromiseImageTexture> BeginReadAccess() override { + DCHECK_EQ(mode_, RepresentationAccessMode::kNone); // Synchronise the read access with the writes. base::ScopedFD sync_fd; @@ -559,24 +563,17 @@ vk_implementation(), vk_device(), vk_phy_device(), vk_queue(), ahb_backing()->GetAhbHandle(), size(), format(), std::move(semaphore)); - // Cache the sk surface in the representation so that it can be used in the - // EndReadAccess. Also make sure previous surface_ have been consumed by - // EndReadAccess() call. - surface_ = sk_surface; - mode_ = RepresentationAccessMode::kRead; return promise_texture; } void EndReadAccess() override { - // There should be a surface_ from the BeginReadAccess(). - DCHECK_EQ(RepresentationAccessMode::kRead, mode_); - DCHECK(surface_); + DCHECK_EQ(mode_, RepresentationAccessMode::kRead); + DCHECK(!surface_); base::ScopedFD sync_fd; - EndVulkanAccess(vk_implementation(), vk_device(), vk_queue(), &surface_, - &sync_fd); + EndVulkanAccess(vk_implementation(), vk_device(), vk_queue(), &sync_fd); // pass this sync fd to the backing. ahb_backing()->EndRead(this, std::move(sync_fd)); @@ -616,8 +613,8 @@ DCHECK(surface_); base::ScopedFD sync_fd; - EndVulkanAccess(vk_implementation(), vk_device(), vk_queue(), &surface_, - &sync_fd); + EndVulkanAccess(vk_implementation(), vk_device(), vk_queue(), &sync_fd); + surface_ = nullptr; ahb_backing()->EndWrite(std::move(sync_fd)); mode_ = RepresentationAccessMode::kNone;
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc index a899c7f..52f6782 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc
@@ -126,7 +126,7 @@ EXPECT_EQ(gl_legacy_shared_image.size().width(), surface->width()); EXPECT_EQ(gl_legacy_shared_image.size().height(), surface->height()); skia_representation->EndWriteAccess(std::move(surface)); - auto promise_texture = skia_representation->BeginReadAccess(nullptr); + auto promise_texture = skia_representation->BeginReadAccess(); EXPECT_TRUE(promise_texture); if (promise_texture) { GrBackendTexture backend_texture = promise_texture->backendTexture(); @@ -187,7 +187,7 @@ auto skia_representation = shared_image_representation_factory_->ProduceSkia( mailbox, context_state_.get()); EXPECT_TRUE(skia_representation); - auto promise_texture = skia_representation->BeginReadAccess(nullptr); + auto promise_texture = skia_representation->BeginReadAccess(); EXPECT_TRUE(promise_texture); if (promise_texture) { GrBackendTexture backend_texture = promise_texture->backendTexture(); @@ -320,14 +320,8 @@ auto skia_representation2 = shared_image_representation_factory_->ProduceSkia( gl_legacy_shared_image.mailbox(), context_state_.get()); - sk_sp<SkSurface> surface = - SkSurface::MakeNull(gl_legacy_shared_image.size().width(), - gl_legacy_shared_image.size().height()); - EXPECT_TRUE(skia_representation->BeginReadAccess(surface.get())); - sk_sp<SkSurface> surface2 = - SkSurface::MakeNull(gl_legacy_shared_image.size().width(), - gl_legacy_shared_image.size().height()); - EXPECT_TRUE(skia_representation2->BeginReadAccess(surface2.get())); + EXPECT_TRUE(skia_representation->BeginReadAccess()); + EXPECT_TRUE(skia_representation2->BeginReadAccess()); skia_representation2->EndReadAccess(); skia_representation2.reset(); @@ -348,14 +342,8 @@ auto skia_representation = shared_image_representation_factory_->ProduceSkia( gl_legacy_shared_image.mailbox(), context_state_.get()); - sk_sp<SkSurface> surface = - SkSurface::MakeNull(gl_legacy_shared_image.size().width(), - gl_legacy_shared_image.size().height()); - EXPECT_TRUE(skia_representation->BeginReadAccess(surface.get())); - sk_sp<SkSurface> surface2 = - SkSurface::MakeNull(gl_legacy_shared_image.size().width(), - gl_legacy_shared_image.size().height()); - EXPECT_FALSE(skia_representation->BeginReadAccess(surface2.get())); + EXPECT_TRUE(skia_representation->BeginReadAccess()); + EXPECT_FALSE(skia_representation->BeginReadAccess()); skia_representation->EndReadAccess(); skia_representation.reset(); @@ -373,10 +361,7 @@ auto skia_representation = shared_image_representation_factory_->ProduceSkia( gl_legacy_shared_image.mailbox(), context_state_.get()); - sk_sp<SkSurface> surface = - SkSurface::MakeNull(gl_legacy_shared_image.size().width(), - gl_legacy_shared_image.size().height()); - EXPECT_TRUE(skia_representation->BeginReadAccess(surface.get())); + EXPECT_TRUE(skia_representation->BeginReadAccess()); EXPECT_FALSE(skia_representation->BeginWriteAccess( gr_context(), 0, SkSurfaceProps(0, kUnknown_SkPixelGeometry))); @@ -400,10 +385,7 @@ auto surface = skia_representation->BeginWriteAccess( gr_context(), 0, SkSurfaceProps(0, kUnknown_SkPixelGeometry)); - sk_sp<SkSurface> surface2 = - SkSurface::MakeNull(gl_legacy_shared_image.size().width(), - gl_legacy_shared_image.size().height()); - EXPECT_FALSE(skia_representation->BeginReadAccess(surface2.get())); + EXPECT_FALSE(skia_representation->BeginReadAccess()); skia_representation->EndWriteAccess(std::move(surface)); skia_representation.reset();
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc index d67d90c..90bb53f 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc
@@ -312,7 +312,7 @@ write_surface_ = nullptr; } - sk_sp<SkPromiseImageTexture> BeginReadAccess(SkSurface* sk_surface) override { + sk_sp<SkPromiseImageTexture> BeginReadAccess() override { CheckContext(); static_cast<SharedImageBackingWithReadAccess*>(backing()) ->BeginReadAccess();
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc index 445ea21..80d188e 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc
@@ -186,7 +186,7 @@ EXPECT_EQ(size.width(), surface->width()); EXPECT_EQ(size.height(), surface->height()); skia_representation->EndWriteAccess(std::move(surface)); - auto promise_texture = skia_representation->BeginReadAccess(nullptr); + auto promise_texture = skia_representation->BeginReadAccess(); EXPECT_TRUE(promise_texture); if (promise_texture) { GrBackendTexture backend_texture = promise_texture->backendTexture(); @@ -285,7 +285,7 @@ EXPECT_EQ(size.width(), surface->width()); EXPECT_EQ(size.height(), surface->height()); skia_representation->EndWriteAccess(std::move(surface)); - auto promise_texture = skia_representation->BeginReadAccess(nullptr); + auto promise_texture = skia_representation->BeginReadAccess(); EXPECT_TRUE(promise_texture); if (promise_texture) { GrBackendTexture backend_texture = promise_texture->backendTexture();
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_iosurface.mm b/gpu/command_buffer/service/shared_image_backing_factory_iosurface.mm index 2432ad9..106e681 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_iosurface.mm +++ b/gpu/command_buffer/service/shared_image_backing_factory_iosurface.mm
@@ -148,7 +148,7 @@ } } - sk_sp<SkPromiseImageTexture> BeginReadAccess(SkSurface* sk_surface) override { + sk_sp<SkPromiseImageTexture> BeginReadAccess() override { return promise_texture_; }
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_iosurface_unittest.cc b/gpu/command_buffer/service/shared_image_backing_factory_iosurface_unittest.cc index d37b3da..21d087ad 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_iosurface_unittest.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_iosurface_unittest.cc
@@ -135,7 +135,7 @@ EXPECT_EQ(size.width(), surface->width()); EXPECT_EQ(size.height(), surface->height()); skia_representation->EndWriteAccess(std::move(surface)); - auto promise_texture = skia_representation->BeginReadAccess(nullptr); + auto promise_texture = skia_representation->BeginReadAccess(); EXPECT_TRUE(promise_texture); if (promise_texture) { GrBackendTexture backend_texture = promise_texture->backendTexture(); @@ -196,7 +196,7 @@ auto skia_representation = shared_image_representation_factory_->ProduceSkia( mailbox, context_state_); EXPECT_TRUE(skia_representation); - auto promise_texture = skia_representation->BeginReadAccess(nullptr); + auto promise_texture = skia_representation->BeginReadAccess(); EXPECT_TRUE(promise_texture); if (promise_texture) { GrBackendTexture backend_texture = promise_texture->backendTexture();
diff --git a/gpu/command_buffer/service/shared_image_representation.h b/gpu/command_buffer/service/shared_image_representation.h index a1c5e550..4b6fb436 100644 --- a/gpu/command_buffer/service/shared_image_representation.h +++ b/gpu/command_buffer/service/shared_image_representation.h
@@ -154,8 +154,7 @@ int final_msaa_count, const SkSurfaceProps& surface_props) = 0; virtual void EndWriteAccess(sk_sp<SkSurface> surface) = 0; - virtual sk_sp<SkPromiseImageTexture> BeginReadAccess( - SkSurface* sk_surface) = 0; + virtual sk_sp<SkPromiseImageTexture> BeginReadAccess() = 0; virtual void EndReadAccess() = 0; };
diff --git a/gpu/command_buffer/service/wrapped_sk_image.cc b/gpu/command_buffer/service/wrapped_sk_image.cc index be608c9..fb16184 100644 --- a/gpu/command_buffer/service/wrapped_sk_image.cc +++ b/gpu/command_buffer/service/wrapped_sk_image.cc
@@ -210,7 +210,7 @@ write_surface_ = nullptr; } - sk_sp<SkPromiseImageTexture> BeginReadAccess(SkSurface* sk_surface) override { + sk_sp<SkPromiseImageTexture> BeginReadAccess() override { return wrapped_sk_image()->promise_texture(); }
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg index 3345a58..c42f673 100644 --- a/infra/config/cr-buildbucket.cfg +++ b/infra/config/cr-buildbucket.cfg
@@ -3506,7 +3506,6 @@ name: "gpu-manual-try-linux-nvidia-tsn" } builders { mixins: "linux-try" name: "leak_detection_linux" } - builders { mixins: "linux-angle-try" name: "linux-angle-rel" } builders { mixins: "linux-angle-try" name: "linux_angle_compile_dbg_ng" } builders { mixins: "linux-angle-try" name: "linux_angle_dbg_ng" } builders { mixins: "linux-angle-try" name: "linux_angle_deqp_rel_ng" } @@ -3626,7 +3625,6 @@ builders { mixins: "ios-try" name: "ios-simulator-eg" } builders { mixins: "ios-try" name: "ios-simulator-xcode-clang" } builders { mixins: "ios-try" name: "ios-slimnav" } - builders { mixins: "mac-angle-try" name: "mac-angle-rel" } builders { mixins: "mac-angle-try" name: "mac_angle_compile_dbg_ng" } builders { mixins: "mac-angle-try" name: "mac_angle_dbg_ng" } builders { mixins: "mac-angle-try" name: "mac_angle_rel_ng" }
diff --git a/infra/config/luci-milo.cfg b/infra/config/luci-milo.cfg index 79a77ad..ba67371 100644 --- a/infra/config/luci-milo.cfg +++ b/infra/config/luci-milo.cfg
@@ -4478,9 +4478,6 @@ name: "buildbucket/luci.chromium.try/android_angle_vk64_rel_ng" } builders { - name: "buildbucket/luci.chromium.try/linux-angle-rel" - } - builders { name: "buildbucket/luci.chromium.try/linux_angle_dbg_ng" } builders { @@ -4493,9 +4490,6 @@ name: "buildbucket/luci.chromium.try/linux_angle_rel_ng" } builders { - name: "buildbucket/luci.chromium.try/mac-angle-rel" - } - builders { name: "buildbucket/luci.chromium.try/mac_angle_dbg_ng" } builders { @@ -4725,9 +4719,6 @@ name: "buildbucket/luci.chromium.try/gpu-manual-try-win10-nvidia-rel" } builders { - name: "buildbucket/luci.chromium.try/linux-angle-rel" - } - builders { name: "buildbucket/luci.chromium.try/linux-blink-heap-concurrent-marking-tsan-rel" } builders { @@ -4867,9 +4858,6 @@ name: "buildbucket/luci.chromium.try/ios12-sdk-simulator" } builders { - name: "buildbucket/luci.chromium.try/mac-angle-rel" - } - builders { name: "buildbucket/luci.chromium.try/mac-jumbo-rel" } builders {
diff --git a/ios/chrome/browser/autofill/automation/automation_egtest.mm b/ios/chrome/browser/autofill/automation/automation_egtest.mm index bd85c3ce..d4b9899 100644 --- a/ios/chrome/browser/autofill/automation/automation_egtest.mm +++ b/ios/chrome/browser/autofill/automation/automation_egtest.mm
@@ -26,7 +26,6 @@ #include "components/autofill/ios/browser/autofill_driver_ios.h" #import "ios/chrome/browser/autofill/form_suggestion_label.h" #import "ios/chrome/test/app/chrome_test_util.h" -#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/web/public/test/earl_grey/web_view_actions.h" #import "ios/web/public/test/earl_grey/web_view_matchers.h" #include "ios/web/public/test/element_selector.h"
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm index e98557fb..0b6ac7f 100644 --- a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm +++ b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include <memory> #include "base/bind.h"
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder_test_util.mm b/ios/chrome/browser/metrics/tab_usage_recorder_test_util.mm index 060c56e..e5a4c5f 100644 --- a/ios/chrome/browser/metrics/tab_usage_recorder_test_util.mm +++ b/ios/chrome/browser/metrics/tab_usage_recorder_test_util.mm
@@ -4,6 +4,7 @@ #include "ios/chrome/browser/metrics/tab_usage_recorder_test_util.h" +#import <EarlGrey/EarlGrey.h> #import <Foundation/Foundation.h> #import "base/ios/block_types.h"
diff --git a/ios/chrome/browser/overlays/BUILD.gn b/ios/chrome/browser/overlays/BUILD.gn new file mode 100644 index 0000000..0f7c67d --- /dev/null +++ b/ios/chrome/browser/overlays/BUILD.gn
@@ -0,0 +1,52 @@ +# 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. + +source_set("overlays") { + sources = [ + "overlay_request.h", + "overlay_response.h", + "overlay_user_data.h", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + allow_circular_includes_from = [ ":internal" ] + + deps = [ + ":internal", + "//base", + ] +} + +source_set("internal") { + sources = [ + "overlay_request_impl.cc", + "overlay_request_impl.h", + "overlay_response_impl.cc", + "overlay_response_impl.h", + ] + + deps = [ + "//base", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ + "overlay_request_unittest.cc", + "overlay_response_unittest.cc", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ + ":overlays", + "//base/test:test_support", + "//ios/chrome/browser/overlays/test", + "//ios/web/public", + "//ios/web/public/test/fakes", + "//testing/gtest", + ] +}
diff --git a/ios/chrome/browser/overlays/README.md b/ios/chrome/browser/overlays/README.md new file mode 100644 index 0000000..f9a41fa --- /dev/null +++ b/ios/chrome/browser/overlays/README.md
@@ -0,0 +1,71 @@ +# OverlayService + +OverlayService is used to schedule the display of UI over the content area of a +WebState. + +## Classes of note: + +##### OverlayRequest + +OverlayRequests are passed to OverlayService to trigger the display of overlay +UI over a WebState's content area. Service clients should create +OverlayRequests with an OverlayUserData subclass with the information necessary +to configure the overlay UI. The config user data can later be extracted from +OverlayRequests by the service's observers and UI delegate. + +##### OverlayResponse + +OverlayResponses are provided to each OverlayRequest to describe the user's +interaction with the overlay UI. Service clients should create OverlayResponses +with an OverlayUserData subclass with the overlay UI user interaction +information necessary to execute the callback for that overlay. + +## Example usage of service: + +### Showing an alert with a title, message, an OK button, and a Cancel button + +#####1. Create OverlayUserData subclasses for the requests and responses: + +A request configuration user data should be created with the information +necessary to set up the overlay UI being requested. + + class AlertConfig : public OverlayUserData<AlertConfig> { + public: + const std::string& title() const; + const std::string& message() const; + const std::vector<std::string>& button\_titles() const; + private: + OVERLAY\_USER\_DATA\_SETUP(AlertConfig); + AlertConfig(const std::string& title, const std::string& message); + }; + +A response ino user data should be created with the information necessary to +execute the callback for the overlay. + + class AlertInfo : public OverlayUserData<AlertInfo> { + public: + const size\_t tapped\_button\_index() const; + private: + OVERLAY\_USER\_DATA\_SETUP(AlertInfo); + AlertInfo(size\_t tapped\_button\_index); + }; + +#####2. Request an overlay using the request config user data. + +An OverlayRequest for the alert can be created using: + + OverlayRequest::CreateWithConfig<AlertConfig>( + "alert title", "message text"); + +*TODO: insert OverlayService calls when interface is added.* + +#####3. Supply a response to the request. + +An OverlayResponse for the alert can be created using: + + OverlayResponse::CreateWithInfo<AlertInfo>(0); + + +*NOTE: this service is a work-in-progress, and this file only outlines how to +use the files currently in the repository. It will be updated with more +complete instructions as more of the service lands.*
diff --git a/ios/chrome/browser/overlays/overlay_request.h b/ios/chrome/browser/overlays/overlay_request.h new file mode 100644 index 0000000..66e5daac --- /dev/null +++ b/ios/chrome/browser/overlays/overlay_request.h
@@ -0,0 +1,62 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_REQUEST_H_ +#define IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_REQUEST_H_ + +#include <memory> + +#include "base/supports_user_data.h" + +class OverlayResponse; + +// Model object used to track overlays requested for OverlayService. +class OverlayRequest { + public: + OverlayRequest() = default; + virtual ~OverlayRequest() = default; + + // Creates an OverlayRequest configured with an OverlayUserData of type + // ConfigType. The ConfigType is constructed using the arguments passed to + // this function. For example, if a configuration of type StringConfig has + // a constructor that takes a string, a request configured with a StringConfig + // can be created using: + // + // OverlayRequest::CreateWithConfig<StringConfig>("configuration string"); + template <class ConfigType, typename... Args> + static std::unique_ptr<OverlayRequest> CreateWithConfig(Args&&... args) { + std::unique_ptr<OverlayRequest> request = OverlayRequest::Create(); + request->data().SetUserData( + ConfigType::UserDataKey(), + ConfigType::Create(std::forward<Args>(args)...)); + return request; + } + + // Returns the OverlayUserData of type ConfigType stored in the request's + // user data, or nullptr if it is not found. For example, a configuration of + // type Config can be retrieved using: + // + // request->GetConfig<Config>(); + template <class ConfigType> + ConfigType* GetConfig() { + return static_cast<ConfigType*>( + data().GetUserData(ConfigType::UserDataKey())); + } + + // Setter for the response object for this request. + virtual void set_response(std::unique_ptr<OverlayResponse> response) = 0; + // The response for this request. It is constructed with an + // OverlayResponseInfo containing user interaction information for the overlay + // UI resulting from this request. + virtual OverlayResponse* response() const = 0; + + private: + // Creates an unconfigured OverlayRequest. + static std::unique_ptr<OverlayRequest> Create(); + + // The container used to hold the user data. + virtual base::SupportsUserData& data() = 0; +}; + +#endif // IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_REQUEST_H_
diff --git a/ios/chrome/browser/overlays/overlay_request_impl.cc b/ios/chrome/browser/overlays/overlay_request_impl.cc new file mode 100644 index 0000000..98c5be8 --- /dev/null +++ b/ios/chrome/browser/overlays/overlay_request_impl.cc
@@ -0,0 +1,28 @@ +// 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 "ios/chrome/browser/overlays/overlay_request_impl.h" + +#include "ios/chrome/browser/overlays/overlay_response.h" + +// static +std::unique_ptr<OverlayRequest> OverlayRequest::Create() { + return std::make_unique<OverlayRequestImpl>(); +} + +OverlayRequestImpl::OverlayRequestImpl() {} +OverlayRequestImpl::~OverlayRequestImpl() {} + +base::SupportsUserData& OverlayRequestImpl::data() { + return *this; +} + +void OverlayRequestImpl::set_response( + std::unique_ptr<OverlayResponse> response) { + response_ = std::move(response); +} + +OverlayResponse* OverlayRequestImpl::response() const { + return response_.get(); +}
diff --git a/ios/chrome/browser/overlays/overlay_request_impl.h b/ios/chrome/browser/overlays/overlay_request_impl.h new file mode 100644 index 0000000..5d2c4990 --- /dev/null +++ b/ios/chrome/browser/overlays/overlay_request_impl.h
@@ -0,0 +1,30 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_REQUEST_IMPL_H_ +#define IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_REQUEST_IMPL_H_ + +#include <memory> + +#include "ios/chrome/browser/overlays/overlay_request.h" + +// Internal implementation of OverlayRequest. +class OverlayRequestImpl : public OverlayRequest, + public base::SupportsUserData { + public: + OverlayRequestImpl(); + ~OverlayRequestImpl() override; + + private: + // OverlayRequest: + void set_response(std::unique_ptr<OverlayResponse> response) override; + OverlayResponse* response() const override; + base::SupportsUserData& data() override; + + // The response containing the user interaction information for the overlay + // resulting from this response. + std::unique_ptr<OverlayResponse> response_; +}; + +#endif // IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_REQUEST_IMPL_H_
diff --git a/ios/chrome/browser/overlays/overlay_request_unittest.cc b/ios/chrome/browser/overlays/overlay_request_unittest.cc new file mode 100644 index 0000000..feee9d6 --- /dev/null +++ b/ios/chrome/browser/overlays/overlay_request_unittest.cc
@@ -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. + +#include "ios/chrome/browser/overlays/overlay_request.h" + +#include "ios/chrome/browser/overlays/test/fake_overlay_user_data.h" +#include "testing/platform_test.h" + +using OverlayRequestTest = PlatformTest; + +// Tests that OverlayRequests can be created. +TEST_F(OverlayRequestTest, CreateWithConfig) { + int value = 0; + std::unique_ptr<OverlayRequest> request = + OverlayRequest::CreateWithConfig<FakeOverlayUserData>(&value); + FakeOverlayUserData* config = request->GetConfig<FakeOverlayUserData>(); + ASSERT_TRUE(config); + EXPECT_EQ(config->value(), &value); +}
diff --git a/ios/chrome/browser/overlays/overlay_response.h b/ios/chrome/browser/overlays/overlay_response.h new file mode 100644 index 0000000..b302ce7 --- /dev/null +++ b/ios/chrome/browser/overlays/overlay_response.h
@@ -0,0 +1,51 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_RESPONSE_H_ +#define IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_RESPONSE_H_ + +#include <memory> + +#include "base/supports_user_data.h" + +// Model object used to store information about user interaction with overlay +// UI. +class OverlayResponse { + public: + OverlayResponse() = default; + virtual ~OverlayResponse() = default; + + // Creates an OverlayResponse with an OverlayUserData of type InfoType. + // The InfoType is constructed using the arguments passed to this function. + // For example, if an info of type IntInfo has a constructor that takes an + // int, a response with an IntInfo can be created using: + // + // OverlayResponse::CreateWithInfo<IntInfo>(0); + template <class InfoType, typename... Args> + static std::unique_ptr<OverlayResponse> CreateWithInfo(Args&&... args) { + std::unique_ptr<OverlayResponse> response = OverlayResponse::Create(); + response->data().SetUserData(InfoType::UserDataKey(), + InfoType::Create(std::forward<Args>(args)...)); + return response; + } + + // Returns the OverlayResponseInfo of type InfoType stored in the reponse's + // user data, or nullptr if it is not found. For example, an info of type + // Info can be retrieved using: + // + // response->GetInfo<Info>(); + template <class InfoType> + InfoType* GetInfo() { + return static_cast<InfoType*>(data().GetUserData(InfoType::UserDataKey())); + } + + private: + // Creates an OverlayResponse with no info attached to it. + static std::unique_ptr<OverlayResponse> Create(); + + // The container used to hold the user data. + virtual base::SupportsUserData& data() = 0; +}; + +#endif // IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_RESPONSE_H_
diff --git a/ios/chrome/browser/overlays/overlay_response_impl.cc b/ios/chrome/browser/overlays/overlay_response_impl.cc new file mode 100644 index 0000000..c28defe --- /dev/null +++ b/ios/chrome/browser/overlays/overlay_response_impl.cc
@@ -0,0 +1,17 @@ +// 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 "ios/chrome/browser/overlays/overlay_response_impl.h" + +// static +std::unique_ptr<OverlayResponse> OverlayResponse::Create() { + return std::make_unique<OverlayResponseImpl>(); +} + +OverlayResponseImpl::OverlayResponseImpl() {} +OverlayResponseImpl::~OverlayResponseImpl() {} + +base::SupportsUserData& OverlayResponseImpl::data() { + return *this; +}
diff --git a/ios/chrome/browser/overlays/overlay_response_impl.h b/ios/chrome/browser/overlays/overlay_response_impl.h new file mode 100644 index 0000000..1a26cdf --- /dev/null +++ b/ios/chrome/browser/overlays/overlay_response_impl.h
@@ -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. + +#ifndef IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_RESPONSE_IMPL_H_ +#define IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_RESPONSE_IMPL_H_ + +#include "ios/chrome/browser/overlays/overlay_response.h" + +// Internal implementation of OverlayResponse. +class OverlayResponseImpl : public OverlayResponse, + public base::SupportsUserData { + public: + OverlayResponseImpl(); + ~OverlayResponseImpl() override; + + private: + // OverlayResponse: + base::SupportsUserData& data() override; +}; + +#endif // IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_RESPONSE_IMPL_H_
diff --git a/ios/chrome/browser/overlays/overlay_response_unittest.cc b/ios/chrome/browser/overlays/overlay_response_unittest.cc new file mode 100644 index 0000000..8bb1e83 --- /dev/null +++ b/ios/chrome/browser/overlays/overlay_response_unittest.cc
@@ -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. + +#include "ios/chrome/browser/overlays/overlay_response.h" + +#include "ios/chrome/browser/overlays/test/fake_overlay_user_data.h" +#include "testing/platform_test.h" + +using OverlayResponseTest = PlatformTest; + +// Tests that OverlayResponses can be constructed. +TEST_F(OverlayResponseTest, CreateWithInfo) { + int value = 0; + std::unique_ptr<OverlayResponse> request = + OverlayResponse::CreateWithInfo<FakeOverlayUserData>(&value); + FakeOverlayUserData* info = request->GetInfo<FakeOverlayUserData>(); + ASSERT_TRUE(info); + EXPECT_EQ(info->value(), &value); +}
diff --git a/ios/chrome/browser/overlays/overlay_user_data.h b/ios/chrome/browser/overlays/overlay_user_data.h new file mode 100644 index 0000000..418a4fe --- /dev/null +++ b/ios/chrome/browser/overlays/overlay_user_data.h
@@ -0,0 +1,61 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_USER_DATA_H_ +#define IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_USER_DATA_H_ + +#include "base/memory/ptr_util.h" +#include "base/supports_user_data.h" + +// Macro for OverlayUserData setup [add to .h file]: +// - Declares a static variable inside subclasses. The address of this static +// variable is used as the key to associate the OverlayUserData with its +// user data container. +// - Adds a friend specification for OverlayUserData so it can access +// specializations' private constructors and user data keys. +#define OVERLAY_USER_DATA_SETUP(Type) \ + static constexpr int kUserDataKey = 0; \ + friend class OverlayUserData<Type> + +// Macro for OverlayUserData setup implementation [add to .cc/.mm file]: +// - Instantiates the static variable declared by the previous macro. It must +// live in a .cc/.mm file to ensure that there is only one instantiation of +// the static variable. +#define OVERLAY_USER_DATA_SETUP_IMPL(Type) const int Type::kUserDataKey + +// A base class for classes attached to, and scoped to, the lifetime of a user +// data container (e.g. OverlayRequest, OverlayResponse). +// +// --- in data.h --- +// class Data : public OverlayUserData<Data> { +// public: +// ~Data() override; +// // ... more public stuff here ... +// private: +// OVERLAY_USER_DATA_SETUP(Data); +// explicit Data( \* ANY ARGUMENT LIST SUPPORTED *\); +// // ... more private stuff here ... +// }; +// +// --- in data.cc --- +// OVERLAY_USER_DATA_SETUP_IMPL(Data); +template <class DataType> +class OverlayUserData : public base::SupportsUserData::Data { + public: + // Creates an OverlayUserData of type DataType. The DataType instance is + // constructed using the arguments passed to this function. For example, if + // the constructor for an OverlayUserData of type StringData takes a string, + // one can be created using: + // + // StringData::Create("string"); + template <typename... Args> + static std::unique_ptr<DataType> Create(Args&&... args) { + return base::WrapUnique(new DataType(std::forward<Args>(args)...)); + } + + // The key under which to store the user data. + static const void* UserDataKey() { return &DataType::kUserDataKey; } +}; + +#endif // IOS_CHROME_BROWSER_OVERLAYS_OVERLAY_USER_DATA_H_
diff --git a/ios/chrome/browser/overlays/test/BUILD.gn b/ios/chrome/browser/overlays/test/BUILD.gn new file mode 100644 index 0000000..851c72a --- /dev/null +++ b/ios/chrome/browser/overlays/test/BUILD.gn
@@ -0,0 +1,19 @@ +# 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. + +source_set("test") { + testonly = true + sources = [ + "fake_overlay_user_data.cc", + "fake_overlay_user_data.h", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ + "//base", + "//ios/chrome/browser/overlays", + "//testing/gtest", + ] +}
diff --git a/ios/chrome/browser/overlays/test/fake_overlay_user_data.cc b/ios/chrome/browser/overlays/test/fake_overlay_user_data.cc new file mode 100644 index 0000000..2c833395 --- /dev/null +++ b/ios/chrome/browser/overlays/test/fake_overlay_user_data.cc
@@ -0,0 +1,9 @@ +// 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 "ios/chrome/browser/overlays/test/fake_overlay_user_data.h" + +OVERLAY_USER_DATA_SETUP_IMPL(FakeOverlayUserData); + +FakeOverlayUserData::FakeOverlayUserData(void* value) : value_(value) {}
diff --git a/ios/chrome/browser/overlays/test/fake_overlay_user_data.h b/ios/chrome/browser/overlays/test/fake_overlay_user_data.h new file mode 100644 index 0000000..f8b5da3 --- /dev/null +++ b/ios/chrome/browser/overlays/test/fake_overlay_user_data.h
@@ -0,0 +1,24 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_OVERLAYS_TEST_FAKE_OVERLAY_USER_DATA_H_ +#define IOS_CHROME_BROWSER_OVERLAYS_TEST_FAKE_OVERLAY_USER_DATA_H_ + +#include "ios/chrome/browser/overlays/overlay_user_data.h" + +// Test OverlayUserData that can be used to store arbitrary pointers in +// OverlayRequests and OverlayResponses. +class FakeOverlayUserData : public OverlayUserData<FakeOverlayUserData> { + public: + // Accessor for value pointer. + void* value() const { return value_; } + + private: + OVERLAY_USER_DATA_SETUP(FakeOverlayUserData); + FakeOverlayUserData(void* value); + + void* value_ = nullptr; +}; + +#endif // IOS_CHROME_BROWSER_OVERLAYS_TEST_FAKE_OVERLAY_USER_DATA_H_
diff --git a/ios/chrome/browser/translate/legacy_translate_infobar_egtest.mm b/ios/chrome/browser/translate/legacy_translate_infobar_egtest.mm index 24a03bf3..f17e748 100644 --- a/ios/chrome/browser/translate/legacy_translate_infobar_egtest.mm +++ b/ios/chrome/browser/translate/legacy_translate_infobar_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #include <memory>
diff --git a/ios/chrome/browser/translate/translate_egtest.mm b/ios/chrome/browser/translate/translate_egtest.mm index a046993..8bdb71c9 100644 --- a/ios/chrome/browser/translate/translate_egtest.mm +++ b/ios/chrome/browser/translate/translate_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #include <memory>
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm index 8d53563..2cb9054 100644 --- a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm +++ b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #include <memory>
diff --git a/ios/chrome/browser/ui/autofill/save_card_infobar_egtest.mm b/ios/chrome/browser/ui/autofill/save_card_infobar_egtest.mm index e8700bb6..67d7ab91 100644 --- a/ios/chrome/browser/ui/autofill/save_card_infobar_egtest.mm +++ b/ios/chrome/browser/ui/autofill/save_card_infobar_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include <memory> #include "base/logging.h"
diff --git a/ios/chrome/browser/ui/autofill/save_profile_egtest.mm b/ios/chrome/browser/ui/autofill/save_profile_egtest.mm index f39bada..bae084c 100644 --- a/ios/chrome/browser/ui/autofill/save_profile_egtest.mm +++ b/ios/chrome/browser/ui/autofill/save_profile_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include <memory> #include "base/logging.h"
diff --git a/ios/chrome/browser/ui/download/download_manager_egtest.mm b/ios/chrome/browser/ui/download/download_manager_egtest.mm index 17fc9c3..a12f702 100644 --- a/ios/chrome/browser/ui/download/download_manager_egtest.mm +++ b/ios/chrome/browser/ui/download/download_manager_egtest.mm
@@ -19,6 +19,7 @@ #import "ios/chrome/test/scoped_eg_synchronization_disabler.h" #include "ios/testing/embedded_test_server_handlers.h" #import "ios/web/public/test/earl_grey/web_view_matchers.h" +#include "ios/web/public/test/element_selector.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" #include "net/test/embedded_test_server/request_handler_util.h"
diff --git a/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm b/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm index b504966..02696a7 100644 --- a/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm +++ b/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #include "base/strings/string_number_conversions.h"
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm index 0b99d19..ef801d04 100644 --- a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm +++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
@@ -37,6 +37,7 @@ // Container Stack constants. const CGFloat kContainerStackSpacing = 18.0; +const CGFloat kContainerStackVerticalPadding = 18.0; // Icon constants. const CGFloat kIconWidth = 25.0; @@ -126,10 +127,6 @@ UIStackView* labelsStackView = [[UIStackView alloc] initWithArrangedSubviews:@[ self.titleLabel, self.subTitleLabel ]]; labelsStackView.axis = UILayoutConstraintAxisVertical; - labelsStackView.alignment = UIStackViewAlignmentLeading; - labelsStackView.distribution = UIStackViewDistributionEqualCentering; - [labelsStackView setContentHuggingPriority:UILayoutPriorityRequired - forAxis:UILayoutConstraintAxisVertical]; // Button setup. self.infobarButton = [UIButton buttonWithType:UIButtonTypeSystem]; @@ -156,6 +153,9 @@ containerStack.distribution = UIStackViewDistributionFill; containerStack.alignment = UIStackViewAlignmentFill; containerStack.translatesAutoresizingMaskIntoConstraints = NO; + containerStack.layoutMarginsRelativeArrangement = YES; + containerStack.directionalLayoutMargins = NSDirectionalEdgeInsetsMake( + kContainerStackVerticalPadding, 0, kContainerStackVerticalPadding, 0); [self.view addSubview:containerStack]; // Constraints setup. @@ -166,8 +166,9 @@ constant:kContainerStackSpacing], [containerStack.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], - [containerStack.centerYAnchor - constraintEqualToAnchor:self.view.centerYAnchor], + [containerStack.topAnchor constraintEqualToAnchor:self.view.topAnchor], + [containerStack.bottomAnchor + constraintEqualToAnchor:self.view.bottomAnchor], // Icon. [iconImageView.widthAnchor constraintEqualToConstant:kIconWidth], // Button.
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm index 4b81840c..d5ff2f1 100644 --- a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm +++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm
@@ -174,6 +174,10 @@ kBannerOverlapWithOmnibox; } +- (UIView*)bannerView { + return self.bannerViewController.view; +} + #pragma mark InfobarModalDelegate - (void)modalInfobarButtonWasPressed:(UIButton*)sender {
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_positioner.h b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_positioner.h index 1f9f0d7..8fdeec2 100644 --- a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_positioner.h +++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_positioner.h
@@ -13,6 +13,11 @@ // Y axis value used to position the InfobarBanner. - (CGFloat)bannerYPosition; +// The InfobarBanner view that will be presented. Used to calculate the +// intrinsic size of the content in order to set the container view height +// appropriately. +- (UIView*)bannerView; + @end #endif // IOS_CHROME_BROWSER_UI_INFOBARS_PRESENTATION_INFOBAR_BANNER_POSITIONER_H_
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.mm b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.mm index d304bde..a13e2202 100644 --- a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.mm +++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.mm
@@ -4,6 +4,7 @@ #import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.h" +#include "base/logging.h" #import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_positioner.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -11,14 +12,12 @@ #endif namespace { -// The presented view height. -const CGFloat kDefaultContainerHeight = 70; // The presented view outer horizontal margins. const CGFloat kContainerHorizontalPadding = 8; // The presented view maximum width. -const CGFloat kContainerWidthMaxSize = 398; -// The presented view default Y axis value. -const CGFloat kDefaultBannerYPosition = 85; +const CGFloat kContainerMaxWidth = 398; +// The presented view maximum height. +const CGFloat kContainerMaxHeight = 200; } @implementation InfobarBannerPresentationController @@ -33,25 +32,32 @@ } - (UIView*)viewForPresentedView { + DCHECK(self.bannerPositioner); UIWindow* window = UIApplication.sharedApplication.keyWindow; // Calculate the Banner container width. CGFloat safeAreaWidth = CGRectGetWidth(window.bounds); CGFloat maxAvailableWidth = safeAreaWidth - 2 * kContainerHorizontalPadding; - CGFloat frameWidth = fmin(maxAvailableWidth, kContainerWidthMaxSize); + CGFloat frameWidth = fmin(maxAvailableWidth, kContainerMaxWidth); // Based on the container width, calculate the value in order to center the // Banner in the X axis. CGFloat bannerXPosition = (safeAreaWidth / 2) - (frameWidth / 2); - CGFloat bannerYPosition = [self.bannerPositioner bannerYPosition]; - if (!bannerYPosition) { - bannerYPosition = kDefaultBannerYPosition; - } - return [[UIView alloc] - initWithFrame:CGRectMake(bannerXPosition, bannerYPosition, frameWidth, - kDefaultContainerHeight)]; + // Calculate the Banner height needed to fit its content with frameWidth. + UIView* bannerView = [self.bannerPositioner bannerView]; + [bannerView setNeedsLayout]; + [bannerView layoutIfNeeded]; + CGSize frameThatFits = + [bannerView systemLayoutSizeFittingSize:CGSizeMake(frameWidth, 0) + withHorizontalFittingPriority:UILayoutPriorityRequired + verticalFittingPriority:1]; + CGFloat frameHeight = fmin(kContainerMaxHeight, frameThatFits.height); + + return + [[UIView alloc] initWithFrame:CGRectMake(bannerXPosition, bannerYPosition, + frameWidth, frameHeight)]; } @end
diff --git a/ios/chrome/browser/ui/omnibox/web_omnibox_edit_controller_impl.mm b/ios/chrome/browser/ui/omnibox/web_omnibox_edit_controller_impl.mm index 5f4068f..5f08422 100644 --- a/ios/chrome/browser/ui/omnibox/web_omnibox_edit_controller_impl.mm +++ b/ios/chrome/browser/ui/omnibox/web_omnibox_edit_controller_impl.mm
@@ -53,8 +53,6 @@ } void WebOmniboxEditControllerImpl::OnInputInProgress(bool in_progress) { - if ([delegate_ locationBarModel]) - [delegate_ locationBarModel]->set_input_in_progress(in_progress); // TODO(crbug.com/818649): see if this is really used. if (in_progress) [delegate_ locationBarBeganEdit];
diff --git a/ios/chrome/browser/ui/payments/payment_request_accessibility_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_accessibility_egtest.mm index e49dc959..430692b3 100644 --- a/ios/chrome/browser/ui/payments/payment_request_accessibility_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_accessibility_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include "base/strings/sys_string_conversions.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_test_utils.h"
diff --git a/ios/chrome/browser/ui/payments/payment_request_can_make_payment_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_can_make_payment_egtest.mm index 932a9b1..d8346ac5 100644 --- a/ios/chrome/browser/ui/payments/payment_request_can_make_payment_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_can_make_payment_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include "base/ios/ios_util.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/credit_card.h"
diff --git a/ios/chrome/browser/ui/payments/payment_request_cancel_pay_abort_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_cancel_pay_abort_egtest.mm index c0c6ad37..911e6f2 100644 --- a/ios/chrome/browser/ui/payments/payment_request_cancel_pay_abort_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_cancel_pay_abort_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include <vector> #include "base/ios/ios_util.h"
diff --git a/ios/chrome/browser/ui/payments/payment_request_data_url_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_data_url_egtest.mm index 559142f..5c80300 100644 --- a/ios/chrome/browser/ui/payments/payment_request_data_url_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_data_url_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #import "ios/chrome/browser/ui/payments/payment_request_egtest_base.h" #import "ios/chrome/test/app/chrome_test_util.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
diff --git a/ios/chrome/browser/ui/payments/payment_request_debit_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_debit_egtest.mm index 2ac8772..9a8e1cb 100644 --- a/ios/chrome/browser/ui/payments/payment_request_debit_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_debit_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include <memory> #include <vector>
diff --git a/ios/chrome/browser/ui/payments/payment_request_egtest_base.mm b/ios/chrome/browser/ui/payments/payment_request_egtest_base.mm index 88ad71a..e4e008e 100644 --- a/ios/chrome/browser/ui/payments/payment_request_egtest_base.mm +++ b/ios/chrome/browser/ui/payments/payment_request_egtest_base.mm
@@ -4,6 +4,8 @@ #import "ios/chrome/browser/ui/payments/payment_request_egtest_base.h" +#import <EarlGrey/EarlGrey.h> + #include <algorithm> #include <memory>
diff --git a/ios/chrome/browser/ui/payments/payment_request_journey_logger_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_journey_logger_egtest.mm index f74c22a..cb924445 100644 --- a/ios/chrome/browser/ui/payments/payment_request_journey_logger_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_journey_logger_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include "base/ios/ios_util.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_test_utils.h"
diff --git a/ios/chrome/browser/ui/payments/payment_request_misc_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_misc_egtest.mm index 3279a41..64efcca 100644 --- a/ios/chrome/browser/ui/payments/payment_request_misc_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_misc_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #import "ios/chrome/browser/payments/payment_request_cache.h" #import "ios/chrome/browser/ui/payments/payment_request_egtest_base.h" #import "ios/chrome/test/app/chrome_test_util.h"
diff --git a/ios/chrome/browser/ui/payments/payment_request_modifiers_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_modifiers_egtest.mm index 88045a6..3147c5a 100644 --- a/ios/chrome/browser/ui/payments/payment_request_modifiers_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_modifiers_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include "base/strings/sys_string_conversions.h" #include "base/test/scoped_feature_list.h" #include "components/autofill/core/browser/autofill_test_utils.h"
diff --git a/ios/chrome/browser/ui/payments/payment_request_payment_app_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_payment_app_egtest.mm index 917dff1b..61601c0 100644 --- a/ios/chrome/browser/ui/payments/payment_request_payment_app_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_payment_app_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include "base/ios/ios_util.h" #import "ios/chrome/browser/ui/payments/payment_request_egtest_base.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
diff --git a/ios/chrome/browser/ui/payments/payment_request_payment_method_identifier_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_payment_method_identifier_egtest.mm index c3d1b922..da02630 100644 --- a/ios/chrome/browser/ui/payments/payment_request_payment_method_identifier_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_payment_method_identifier_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include <vector> #import "ios/chrome/browser/payments/payment_request_cache.h"
diff --git a/ios/chrome/browser/ui/payments/payment_request_payment_response_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_payment_response_egtest.mm index 0151ef6..b0e02df1 100644 --- a/ios/chrome/browser/ui/payments/payment_request_payment_response_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_payment_response_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include <vector> #include "base/strings/utf_string_conversions.h"
diff --git a/ios/chrome/browser/ui/payments/payment_request_show_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_show_egtest.mm index 5515b147..5db5641 100644 --- a/ios/chrome/browser/ui/payments/payment_request_show_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_show_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #import "base/test/ios/wait_util.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/strings/grit/components_strings.h"
diff --git a/ios/chrome/browser/ui/payments/payment_request_use_stats_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_use_stats_egtest.mm index ff0e9105..bf8b07a 100644 --- a/ios/chrome/browser/ui/payments/payment_request_use_stats_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_use_stats_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include "base/time/time.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_test_utils.h"
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_egtest.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_egtest.mm index a8c21d5..5613455 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_egtest.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #include "base/strings/sys_string_conversions.h"
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_settings_egtest.mm b/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_settings_egtest.mm index b8ea908..f83a0c0 100644 --- a/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_settings_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #include "base/strings/sys_string_conversions.h"
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_profile_settings_egtest.mm b/ios/chrome/browser/ui/settings/autofill/autofill_profile_settings_egtest.mm index be033bc3..6a3fa0f 100644 --- a/ios/chrome/browser/ui/settings/autofill/autofill_profile_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/autofill/autofill_profile_settings_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #include "base/ios/ios_util.h"
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_egtest.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_egtest.mm index b254f61..1525abe 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_egtest.mm +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #include "base/test/scoped_feature_list.h"
diff --git a/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm b/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm index 4376744..5649674 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #include <TargetConditionals.h> #include <utility>
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm index 0561c2e..0bd2c17 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> + #include "base/strings/stringprintf.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_constants.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_egtest_util.h"
diff --git a/ios/chrome/browser/ui/webui/inspect/inspect_ui_egtest.mm b/ios/chrome/browser/ui/webui/inspect/inspect_ui_egtest.mm index 2dc87219..61c69d1 100644 --- a/ios/chrome/browser/ui/webui/inspect/inspect_ui_egtest.mm +++ b/ios/chrome/browser/ui/webui/inspect/inspect_ui_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <Foundation/Foundation.h> #import <XCTest/XCTest.h>
diff --git a/ios/chrome/browser/ui/webui/web_ui_egtest.mm b/ios/chrome/browser/ui/webui/web_ui_egtest.mm index 0924539..ca3f7d2 100644 --- a/ios/chrome/browser/ui/webui/web_ui_egtest.mm +++ b/ios/chrome/browser/ui/webui/web_ui_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #include "base/mac/foundation_util.h"
diff --git a/ios/chrome/browser/web/browsing_egtest.mm b/ios/chrome/browser/web/browsing_egtest.mm index 9aed63b..0ca5dc8 100644 --- a/ios/chrome/browser/web/browsing_egtest.mm +++ b/ios/chrome/browser/web/browsing_egtest.mm
@@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> + #include <map> #include <memory> #include <string>
diff --git a/ios/chrome/browser/web/forms_egtest.mm b/ios/chrome/browser/web/forms_egtest.mm index 258e66ec..019dad58 100644 --- a/ios/chrome/browser/web/forms_egtest.mm +++ b/ios/chrome/browser/web/forms_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #include <memory>
diff --git a/ios/chrome/browser/web/navigation_egtest.mm b/ios/chrome/browser/web/navigation_egtest.mm index 1714233..2d828d7 100644 --- a/ios/chrome/browser/web/navigation_egtest.mm +++ b/ios/chrome/browser/web/navigation_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #include "base/bind.h"
diff --git a/ios/chrome/browser/web/push_and_replace_state_navigation_egtest.mm b/ios/chrome/browser/web/push_and_replace_state_navigation_egtest.mm index d26c02b..d66d606 100644 --- a/ios/chrome/browser/web/push_and_replace_state_navigation_egtest.mm +++ b/ios/chrome/browser/web/push_and_replace_state_navigation_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #include "base/strings/sys_string_conversions.h"
diff --git a/ios/chrome/browser/web/tab_order_egtest.mm b/ios/chrome/browser/web/tab_order_egtest.mm index e90ff88..e75aa3c 100644 --- a/ios/chrome/browser/web/tab_order_egtest.mm +++ b/ios/chrome/browser/web/tab_order_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #import "ios/chrome/test/app/chrome_test_util.h" @@ -11,6 +12,7 @@ #import "ios/chrome/test/earl_grey/chrome_matchers.h" #import "ios/chrome/test/earl_grey/chrome_test_case.h" #import "ios/web/public/test/earl_grey/web_view_matchers.h" +#import "ios/web/public/test/element_selector.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index 502e223..8b3c4c03 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -160,6 +160,7 @@ "//ios/chrome/browser/net:unit_tests", "//ios/chrome/browser/ntp:unit_tests", "//ios/chrome/browser/omaha:unit_tests", + "//ios/chrome/browser/overlays:unit_tests", "//ios/chrome/browser/overscroll_actions:unit_tests", "//ios/chrome/browser/passwords:unit_tests", "//ios/chrome/browser/payments:unit_tests",
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.h b/ios/chrome/test/earl_grey/chrome_earl_grey.h index 49b2658e..954db9f0 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.h +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.h
@@ -5,11 +5,15 @@ #ifndef IOS_CHROME_TEST_EARL_GREY_CHROME_EARL_GREY_H_ #define IOS_CHROME_TEST_EARL_GREY_CHROME_EARL_GREY_H_ -#import <EarlGrey/EarlGrey.h> +#import <Foundation/Foundation.h> -#include "ios/web/public/test/element_selector.h" +#include <string> + #include "url/gurl.h" +@class ElementSelector; +@protocol GREYMatcher; + namespace chrome_test_util { // TODO(crbug.com/788813): Evaluate if JS helpers can be consolidated.
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.mm b/ios/chrome/test/earl_grey/chrome_earl_grey.mm index 567629c..93e4111 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
@@ -4,6 +4,7 @@ #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" +#import <EarlGrey/EarlGrey.h> #import <Foundation/Foundation.h> #import <WebKit/WebKit.h> @@ -19,7 +20,6 @@ #include "ios/chrome/test/app/navigation_test_util.h" #import "ios/chrome/test/app/static_html_view_test_util.h" #import "ios/chrome/test/app/tab_test_util.h" -#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/web/public/test/earl_grey/js_test_util.h" #include "ios/web/public/test/element_selector.h" #import "ios/web/public/test/web_view_content_test_util.h"
diff --git a/ios/chrome/test/earl_grey/device_check_egtest.mm b/ios/chrome/test/earl_grey/device_check_egtest.mm index e9f596f..2b01a6a 100644 --- a/ios/chrome/test/earl_grey/device_check_egtest.mm +++ b/ios/chrome/test/earl_grey/device_check_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
diff --git a/ios/showcase/infobars/sc_infobar_banner_coordinator.mm b/ios/showcase/infobars/sc_infobar_banner_coordinator.mm index 171f8aa..b5d6a98 100644 --- a/ios/showcase/infobars/sc_infobar_banner_coordinator.mm +++ b/ios/showcase/infobars/sc_infobar_banner_coordinator.mm
@@ -8,6 +8,7 @@ #import "ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h" #import "ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h" #import "ios/chrome/browser/ui/infobars/modals/infobar_modal_view_controller.h" +#import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_positioner.h" #import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.h" #import "ios/chrome/browser/ui/infobars/presentation/infobar_modal_transition_driver.h" @@ -20,7 +21,9 @@ NSString* const kInfobarBannerButtonLabel = @"Accept"; NSString* const kInfobarBannerPresentedModalLabel = @"Modal Infobar"; -@interface ContainerViewController : UIViewController +#pragma mark - ContainerViewController + +@interface ContainerViewController : UIViewController <InfobarBannerPositioner> @property(nonatomic, strong) InfobarBannerViewController* bannerViewController; @property(nonatomic, strong) InfobarBannerTransitionDriver* bannerTransitionDriver; @@ -32,13 +35,26 @@ [self.bannerViewController setModalPresentationStyle:UIModalPresentationCustom]; self.bannerTransitionDriver = [[InfobarBannerTransitionDriver alloc] init]; + self.bannerTransitionDriver.bannerPositioner = self; self.bannerViewController.transitioningDelegate = self.bannerTransitionDriver; [self presentViewController:self.bannerViewController animated:YES completion:nil]; } + +#pragma mark InfobarBannerPositioner + +- (CGFloat)bannerYPosition { + return 100; +} + +- (UIView*)bannerView { + return self.bannerViewController.view; +} @end +#pragma mark - SCInfobarBannerCoordinator + @interface SCInfobarBannerCoordinator () <InfobarBannerDelegate, InfobarModalDelegate> @property(nonatomic, strong) InfobarBannerViewController* bannerViewController; @@ -68,6 +84,10 @@ animated:YES]; } +- (void)dealloc { + [self dismissInfobarBanner:nil animated:YES completion:nil]; +} + #pragma mark InfobarBannerDelegate - (void)bannerInfobarButtonWasPressed:(id)sender {
diff --git a/ios/web/test/web_int_test.mm b/ios/web/test/web_int_test.mm index 727dad95..62dc6c6a 100644 --- a/ios/web/test/web_int_test.mm +++ b/ios/web/test/web_int_test.mm
@@ -77,6 +77,7 @@ [UIApplication sharedApplication].keyWindow.bounds; web_state()->SetDelegate(&web_state_delegate_); + web_state()->SetKeepRenderProcessAlive(true); } void WebIntTest::TearDown() {
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm index 090709e..3b0420c 100644 --- a/ios/web/web_state/web_state_observer_inttest.mm +++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -1901,13 +1901,6 @@ .WillOnce(Return(true)); EXPECT_CALL(observer_, DidStartNavigation(web_state(), _)); - if (@available(iOS 12.2, *)) { - // ShouldAllowResponse is called on iOS 12.0 and iOS 12.1, - // but not on iOS 12.2 or iOS 11. - } else if (@available(iOS 12, *)) { - EXPECT_CALL(*decider_, ShouldAllowResponse(_, /*for_main_frame=*/true)) - .WillOnce(Return(true)); - } EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _)); EXPECT_CALL(observer_, TitleWasSet(web_state())) .WillOnce(VerifyTitle(url.GetContent())); @@ -2443,6 +2436,8 @@ CRWSessionStorage* session_storage = [[CRWSessionStorage alloc] init]; session_storage.itemStorages = item_storages; auto web_state = WebState::CreateWithStorageSession(params, session_storage); + web_state->SetKeepRenderProcessAlive(true); + StrictMock<WebStateObserverMock> observer; ScopedObserver<WebState, WebStateObserver> scoped_observer(&observer); scoped_observer.Add(web_state.get());
diff --git a/ios/web/web_state/web_state_unittest.mm b/ios/web/web_state/web_state_unittest.mm index 97ebd47..a243eebc 100644 --- a/ios/web/web_state/web_state_unittest.mm +++ b/ios/web/web_state/web_state_unittest.mm
@@ -449,6 +449,7 @@ CRWSessionStorage* session_storage = [[CRWSessionStorage alloc] init]; session_storage.itemStorages = item_storages; auto web_state = WebState::CreateWithStorageSession(params, session_storage); + web_state->SetKeepRenderProcessAlive(true); WebState* web_state_ptr = web_state.get(); NavigationManager* navigation_manager = web_state->GetNavigationManager(); // TODO(crbug.com/873729): The session will not be restored until @@ -492,6 +493,7 @@ CRWSessionStorage* session_storage = [[CRWSessionStorage alloc] init]; session_storage.itemStorages = item_storages; auto web_state = WebState::CreateWithStorageSession(params, session_storage); + web_state->SetKeepRenderProcessAlive(true); WebState* web_state_ptr = web_state.get(); NavigationManager* navigation_manager = web_state->GetNavigationManager(); // TODO(crbug.com/873729): The session will not be restored until @@ -542,6 +544,7 @@ CRWSessionStorage* session_storage = [[CRWSessionStorage alloc] init]; session_storage.itemStorages = item_storages; auto web_state = WebState::CreateWithStorageSession(params, session_storage); + web_state->SetKeepRenderProcessAlive(true); WebState* web_state_ptr = web_state.get(); NavigationManager* navigation_manager = web_state->GetNavigationManager(); // TODO(crbug.com/873729): The session will not be restored until
diff --git a/ios/web_view/shell/test/earl_grey/web_view_shell_matchers.h b/ios/web_view/shell/test/earl_grey/web_view_shell_matchers.h index 35598eb..fa36b91 100644 --- a/ios/web_view/shell/test/earl_grey/web_view_shell_matchers.h +++ b/ios/web_view/shell/test/earl_grey/web_view_shell_matchers.h
@@ -5,9 +5,11 @@ #ifndef IOS_WEB_VIEW_SHELL_TEST_EARL_GREY_WEB_VIEW_SHELL_MATCHERS_H_ #define IOS_WEB_VIEW_SHELL_TEST_EARL_GREY_WEB_VIEW_SHELL_MATCHERS_H_ +#import <Foundation/Foundation.h> + #import <string> -#import <EarlGrey/EarlGrey.h> +@protocol GREYMatcher; NS_ASSUME_NONNULL_BEGIN
diff --git a/ios/web_view/shell/test/earl_grey/web_view_shell_matchers.mm b/ios/web_view/shell/test/earl_grey/web_view_shell_matchers.mm index 2dc8a79..5c3c6ff 100644 --- a/ios/web_view/shell/test/earl_grey/web_view_shell_matchers.mm +++ b/ios/web_view/shell/test/earl_grey/web_view_shell_matchers.mm
@@ -4,6 +4,8 @@ #import "ios/web_view/shell/test/earl_grey/web_view_shell_matchers.h" +#import <EarlGrey/EarlGrey.h> + #include "base/mac/foundation_util.h" #include "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h"
diff --git a/media/blink/webcontentdecryptionmoduleaccess_impl.cc b/media/blink/webcontentdecryptionmoduleaccess_impl.cc index fdc2b25..4e4a7a6 100644 --- a/media/blink/webcontentdecryptionmoduleaccess_impl.cc +++ b/media/blink/webcontentdecryptionmoduleaccess_impl.cc
@@ -34,14 +34,14 @@ client->CreateCdm(key_system, security_origin, cdm_config, std::move(result)); } -WebContentDecryptionModuleAccessImpl* +std::unique_ptr<WebContentDecryptionModuleAccessImpl> WebContentDecryptionModuleAccessImpl::Create( const blink::WebString& key_system, const blink::WebSecurityOrigin& security_origin, const blink::WebMediaKeySystemConfiguration& configuration, const CdmConfig& cdm_config, const base::WeakPtr<WebEncryptedMediaClientImpl>& client) { - return new WebContentDecryptionModuleAccessImpl( + return std::make_unique<WebContentDecryptionModuleAccessImpl>( key_system, security_origin, configuration, cdm_config, client); }
diff --git a/media/blink/webcontentdecryptionmoduleaccess_impl.h b/media/blink/webcontentdecryptionmoduleaccess_impl.h index 821d1f3..cde6fc7 100644 --- a/media/blink/webcontentdecryptionmoduleaccess_impl.h +++ b/media/blink/webcontentdecryptionmoduleaccess_impl.h
@@ -5,6 +5,8 @@ #ifndef MEDIA_BLINK_WEBCONTENTDECRYPTIONMODULEACCESS_IMPL_H_ #define MEDIA_BLINK_WEBCONTENTDECRYPTIONMODULEACCESS_IMPL_H_ +#include <memory> + #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "media/base/cdm_config.h" @@ -21,7 +23,13 @@ class WebContentDecryptionModuleAccessImpl : public blink::WebContentDecryptionModuleAccess { public: - static WebContentDecryptionModuleAccessImpl* Create( + static std::unique_ptr<WebContentDecryptionModuleAccessImpl> Create( + const blink::WebString& key_system, + const blink::WebSecurityOrigin& security_origin, + const blink::WebMediaKeySystemConfiguration& configuration, + const CdmConfig& cdm_config, + const base::WeakPtr<WebEncryptedMediaClientImpl>& client); + WebContentDecryptionModuleAccessImpl( const blink::WebString& key_system, const blink::WebSecurityOrigin& security_origin, const blink::WebMediaKeySystemConfiguration& configuration, @@ -37,13 +45,6 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; private: - WebContentDecryptionModuleAccessImpl( - const blink::WebString& key_system, - const blink::WebSecurityOrigin& security_origin, - const blink::WebMediaKeySystemConfiguration& configuration, - const CdmConfig& cdm_config, - const base::WeakPtr<WebEncryptedMediaClientImpl>& client); - const blink::WebString key_system_; const blink::WebSecurityOrigin security_origin_; const blink::WebMediaKeySystemConfiguration configuration_;
diff --git a/media/blink/webmediacapabilitiesclient_impl.cc b/media/blink/webmediacapabilitiesclient_impl.cc index 86015eb9..90121d9 100644 --- a/media/blink/webmediacapabilitiesclient_impl.cc +++ b/media/blink/webmediacapabilitiesclient_impl.cc
@@ -120,9 +120,9 @@ info->supported = info->smooth = info->power_efficient = true; info->content_decryption_module_access = - base::WrapUnique(WebContentDecryptionModuleAccessImpl::Create( + WebContentDecryptionModuleAccessImpl::Create( key_system_configuration->key_system, blink::WebSecurityOrigin(), - blink::WebMediaKeySystemConfiguration(), {}, nullptr)); + blink::WebMediaKeySystemConfiguration(), {}, nullptr); callbacks->OnSuccess(std::move(info)); return;
diff --git a/media/media_options.gni b/media/media_options.gni index 4460ffc..b3b9bd9 100644 --- a/media/media_options.gni +++ b/media/media_options.gni
@@ -87,7 +87,7 @@ if (is_win && target_cpu == "arm64") { # TODO: Enable dav1d for Windows ARM64. https://crbug.com/941022 enable_dav1d_decoder = false - } else if (is_fuchsia && target_cpu == "x64") { + } else if (is_fuchsia) { # TODO: Fix media_unittests for fuchsia X64. https://crbug.com/930300 enable_dav1d_decoder = false } else {
diff --git a/mojo/core/node_controller.cc b/mojo/core/node_controller.cc index 5a796e9..c0d2346 100644 --- a/mojo/core/node_controller.cc +++ b/mojo/core/node_controller.cc
@@ -731,16 +731,16 @@ OnBroadcast(name_, std::move(channel_message)); } -void NodeController::PortStatusChanged(const ports::PortRef& port) { +void NodeController::SlotStatusChanged(const ports::SlotRef& slot_ref) { scoped_refptr<ports::UserData> user_data; - node_->GetUserData(port, &user_data); + node_->GetUserData(slot_ref.port(), &user_data); PortObserver* observer = static_cast<PortObserver*>(user_data.get()); if (observer) { observer->OnPortStatusChanged(); } else { - DVLOG(2) << "Ignoring status change for " << port.name() << " because it " - << "doesn't have an observer."; + DVLOG(2) << "Ignoring status change for " << slot_ref.port().name() + << " because it doesn't have an observer."; } }
diff --git a/mojo/core/node_controller.h b/mojo/core/node_controller.h index 0b44a6a..fcf66b9 100644 --- a/mojo/core/node_controller.h +++ b/mojo/core/node_controller.h
@@ -187,7 +187,7 @@ void ForwardEvent(const ports::NodeName& node, ports::ScopedEvent event) override; void BroadcastEvent(ports::ScopedEvent event) override; - void PortStatusChanged(const ports::PortRef& port) override; + void SlotStatusChanged(const ports::SlotRef& slot) override; // NodeChannel::Delegate: void OnAcceptInvitee(const ports::NodeName& from_node,
diff --git a/mojo/core/ports/BUILD.gn b/mojo/core/ports/BUILD.gn index 68dce3f..cadaea3 100644 --- a/mojo/core/ports/BUILD.gn +++ b/mojo/core/ports/BUILD.gn
@@ -24,6 +24,8 @@ "port_locker.h", "port_ref.cc", "port_ref.h", + "slot_ref.cc", + "slot_ref.h", "user_data.h", "user_message.cc", "user_message.h",
diff --git a/mojo/core/ports/event.cc b/mojo/core/ports/event.cc index f3cf74e..6da6aed 100644 --- a/mojo/core/ports/event.cc +++ b/mojo/core/ports/event.cc
@@ -29,9 +29,15 @@ struct UserMessageEventData { uint64_t sequence_num; uint32_t num_ports; - uint32_t padding; + SlotId slot_id; }; +// Sanity check to ensure that we aren't breaking the binary structure of +// UserMessageEventData for older Mojo core versions. The structure has always +// been 16 bytes wide. +static_assert(sizeof(UserMessageEventData) == 16, + "Bad UserMessageEventData size"); + struct ObserveProxyEventData { NodeName proxy_node_name; PortName proxy_port_name; @@ -52,6 +58,12 @@ Event::PortDescriptor new_port_descriptor; }; +struct SlotClosedEventData { + uint64_t last_sequence_num; + SlotId slot_id; + char padding[4]; +}; + #pragma pack(pop) static_assert(sizeof(Event::PortDescriptor) % kPortsMessageAlignment == 0, @@ -75,6 +87,9 @@ static_assert(sizeof(MergePortEventData) % kPortsMessageAlignment == 0, "Invalid MergePortEventData size."); +static_assert(sizeof(SlotClosedEventData) % kPortsMessageAlignment == 0, + "Invalid SlotClosedEventData size."); + } // namespace Event::PortDescriptor::PortDescriptor() { @@ -105,6 +120,8 @@ return ObserveClosureEvent::Deserialize(port_name, header + 1, data_size); case Type::kMergePort: return MergePortEvent::Deserialize(port_name, header + 1, data_size); + case Type::kSlotClosed: + return SlotClosedEvent::Deserialize(port_name, header + 1, data_size); default: DVLOG(2) << "Ingoring unknown port event type: " << static_cast<uint32_t>(header->type); @@ -174,6 +191,7 @@ auto event = base::WrapUnique(new UserMessageEvent(port_name, data->sequence_num)); event->ReservePorts(data->num_ports); + event->set_slot_id(data->slot_id); const auto* in_descriptors = reinterpret_cast<const PortDescriptor*>(data + 1); std::copy(in_descriptors, in_descriptors + data->num_ports, @@ -210,7 +228,7 @@ data->sequence_num = sequence_num_; DCHECK(base::IsValueInRangeForNumericType<uint32_t>(ports_.size())); data->num_ports = static_cast<uint32_t>(ports_.size()); - data->padding = 0; + data->slot_id = slot_id_; auto* ports_data = reinterpret_cast<PortDescriptor*>(data + 1); std::copy(port_descriptors_.begin(), port_descriptors_.end(), ports_data); @@ -378,6 +396,37 @@ data->new_port_descriptor = new_port_descriptor_; } +SlotClosedEvent::SlotClosedEvent(const PortName& port_name, + SlotId slot_id, + uint64_t last_sequence_num) + : Event(Type::kSlotClosed, port_name), + slot_id_(slot_id), + last_sequence_num_(last_sequence_num) {} + +SlotClosedEvent::~SlotClosedEvent() = default; + +// static +ScopedEvent SlotClosedEvent::Deserialize(const PortName& port_name, + const void* buffer, + size_t num_bytes) { + if (num_bytes < sizeof(SlotClosedEventData)) + return nullptr; + + const auto* data = static_cast<const SlotClosedEventData*>(buffer); + return std::make_unique<SlotClosedEvent>(port_name, data->slot_id, + data->last_sequence_num); +} + +size_t SlotClosedEvent::GetSerializedDataSize() const { + return sizeof(SlotClosedEventData); +} + +void SlotClosedEvent::SerializeData(void* buffer) const { + auto* data = static_cast<SlotClosedEventData*>(buffer); + data->slot_id = slot_id_; + data->last_sequence_num = last_sequence_num_; +} + } // namespace ports } // namespace core } // namespace mojo
diff --git a/mojo/core/ports/event.h b/mojo/core/ports/event.h index c9a7d6a..8a4852c9 100644 --- a/mojo/core/ports/event.h +++ b/mojo/core/ports/event.h
@@ -21,6 +21,26 @@ class Event; +using SlotId = uint32_t; + +// The default slot on an entangled port pair. When a new port pair is created, +// this is the only slot available to either endpoint. +constexpr SlotId kDefaultSlotId = 0; + +// Bit toggled on non-default slot IDs when referring to the remote peer's +// equivalent of a local slot. For example, for entangled ports A and B, if A +// establishes a new slot 5 when sending a message to B, the slot will always be +// known to B as (kPeerAllocatedSlotIdBit | 5). +// +// Likewise when B sends a message on slot (kPeerAllocatedSlotIdBit | 5), its +// peer A will receive and queue that message on local slot 5. +// +// This allows each endpoint to allocate new slots independently. For any given +// local slot ID value, having this bit set means the slot was initially +// established by a message from the remote peer to the local port. Unset means +// the slot was established by a message from the local port to the remote port. +constexpr SlotId kPeerAllocatedSlotIdBit = 0x80000000u; + using ScopedEvent = std::unique_ptr<Event>; // A Event is the fundamental unit of operation and communication within and @@ -56,6 +76,14 @@ // Used to request the merging of two routes via two sacrificial receiving // ports, one from each route. kMergePort, + + // Used to signal that a slot on a port has been closed. + // + // NOTE: This event type is not supported by older versions of Mojo core + // which lack support for port slots. It is therefore important to ensure + // that this event never gets generated unless a port has more than the + // single default slot. + kSlotClosed, }; #pragma pack(push, 1) @@ -131,6 +159,9 @@ uint64_t sequence_num() const { return sequence_num_; } void set_sequence_num(uint64_t sequence_num) { sequence_num_ = sequence_num; } + SlotId slot_id() const { return slot_id_; } + void set_slot_id(SlotId id) { slot_id_ = id; } + size_t num_ports() const { return ports_.size(); } PortDescriptor* port_descriptors() { return port_descriptors_.data(); } PortName* ports() { return ports_.data(); } @@ -148,6 +179,7 @@ void SerializeData(void* buffer) const override; uint64_t sequence_num_ = 0; + SlotId slot_id_ = 0; std::vector<PortDescriptor> port_descriptors_; std::vector<PortName> ports_; std::unique_ptr<UserMessage> message_; @@ -277,6 +309,30 @@ DISALLOW_COPY_AND_ASSIGN(MergePortEvent); }; +class COMPONENT_EXPORT(MOJO_CORE_PORTS) SlotClosedEvent : public Event { + public: + SlotClosedEvent(const PortName& port_name, + SlotId slot_id, + uint64_t last_sequence_num); + ~SlotClosedEvent() override; + + SlotId slot_id() const { return slot_id_; } + uint64_t last_sequence_num() const { return last_sequence_num_; } + + static ScopedEvent Deserialize(const PortName& port_name, + const void* buffer, + size_t num_bytes); + + private: + size_t GetSerializedDataSize() const override; + void SerializeData(void* buffer) const override; + + const SlotId slot_id_; + const uint64_t last_sequence_num_; + + DISALLOW_COPY_AND_ASSIGN(SlotClosedEvent); +}; + } // namespace ports } // namespace core } // namespace mojo
diff --git a/mojo/core/ports/message_queue.cc b/mojo/core/ports/message_queue.cc index 0abb713..58c5ad9 100644 --- a/mojo/core/ports/message_queue.cc +++ b/mojo/core/ports/message_queue.cc
@@ -15,9 +15,9 @@ namespace ports { // Used by std::{push,pop}_heap functions -inline bool operator<(const std::unique_ptr<UserMessageEvent>& a, - const std::unique_ptr<UserMessageEvent>& b) { - return a->sequence_num() > b->sequence_num(); +inline bool operator<(const MessageQueue::Entry& a, + const MessageQueue::Entry& b) { + return a.message->sequence_num() > b.message->sequence_num(); } MessageQueue::MessageQueue() : MessageQueue(kInitialSequenceNum) {} @@ -31,27 +31,93 @@ MessageQueue::~MessageQueue() { #if DCHECK_IS_ON() size_t num_leaked_ports = 0; - for (const auto& message : heap_) - num_leaked_ports += message->num_ports(); + for (const auto& entry : heap_) + num_leaked_ports += entry.message->num_ports(); DVLOG_IF(1, num_leaked_ports > 0) << "Leaking " << num_leaked_ports << " ports in unreceived messages"; #endif } -bool MessageQueue::HasNextMessage() const { - return !heap_.empty() && heap_[0]->sequence_num() == next_sequence_num_; +bool MessageQueue::HasNextMessage(base::Optional<SlotId> slot_id) { + DropNextIgnoredMessages(); + return !heap_.empty() && + heap_[0].message->sequence_num() == next_sequence_num_ && + (!slot_id || heap_[0].message->slot_id() == slot_id); } -void MessageQueue::GetNextMessage(std::unique_ptr<UserMessageEvent>* message, +base::Optional<SlotId> MessageQueue::GetNextMessageSlot() { + DropNextIgnoredMessages(); + if (heap_.empty() || heap_[0].message->sequence_num() != next_sequence_num_) + return base::nullopt; + return heap_[0].message->slot_id(); +} + +void MessageQueue::GetNextMessage(base::Optional<SlotId> slot_id, + std::unique_ptr<UserMessageEvent>* message, MessageFilter* filter) { - if (!HasNextMessage() || (filter && !filter->Match(*heap_[0]))) { + if (!HasNextMessage(slot_id) || + (filter && !filter->Match(*heap_[0].message))) { message->reset(); return; } + *message = DequeueMessage(); +} + +void MessageQueue::AcceptMessage( + std::unique_ptr<UserMessageEvent> message, + base::Optional<SlotId>* slot_with_next_message) { + // TODO: Handle sequence number roll-over. + + EnqueueMessage(std::move(message), false /* ignored */); + if (heap_[0].message->sequence_num() == next_sequence_num_) + *slot_with_next_message = heap_[0].message->slot_id(); + else + slot_with_next_message->reset(); +} + +void MessageQueue::IgnoreMessage(std::unique_ptr<UserMessageEvent>* message) { + if ((*message)->sequence_num() == next_sequence_num_) { + // Fast path -- if we're ignoring the next message in the sequence, just + // advance the queue's sequence number. + next_sequence_num_++; + return; + } + + EnqueueMessage(std::move(*message), true /* ignored */); +} + +void MessageQueue::TakeAllMessages( + std::vector<std::unique_ptr<UserMessageEvent>>* messages) { + for (auto& entry : heap_) + messages->emplace_back(std::move(entry.message)); + heap_.clear(); + total_queued_bytes_ = 0; +} + +void MessageQueue::TakeAllLeadingMessagesForSlot( + SlotId slot_id, + std::vector<std::unique_ptr<UserMessageEvent>>* messages) { + std::unique_ptr<UserMessageEvent> message; + for (;;) { + GetNextMessage(slot_id, &message, nullptr); + if (!message) + return; + messages->push_back(std::move(message)); + } +} + +void MessageQueue::EnqueueMessage(std::unique_ptr<UserMessageEvent> message, + bool ignored) { + total_queued_bytes_ += message->GetSizeIfSerialized(); + heap_.emplace_back(ignored, std::move(message)); + std::push_heap(heap_.begin(), heap_.end()); +} + +std::unique_ptr<UserMessageEvent> MessageQueue::DequeueMessage() { std::pop_heap(heap_.begin(), heap_.end()); - *message = std::move(heap_.back()); - total_queued_bytes_ -= (*message)->GetSizeIfSerialized(); + auto message = std::move(heap_.back().message); + total_queued_bytes_ -= message->GetSizeIfSerialized(); heap_.pop_back(); // We keep the capacity of |heap_| in check so that a large batch of incoming @@ -65,28 +131,27 @@ } next_sequence_num_++; + + return message; } -void MessageQueue::AcceptMessage(std::unique_ptr<UserMessageEvent> message, - bool* has_next_message) { - // TODO: Handle sequence number roll-over. - - total_queued_bytes_ += message->GetSizeIfSerialized(); - heap_.emplace_back(std::move(message)); - std::push_heap(heap_.begin(), heap_.end()); - - if (!signalable_) { - *has_next_message = false; - } else { - *has_next_message = (heap_[0]->sequence_num() == next_sequence_num_); +void MessageQueue::DropNextIgnoredMessages() { + while (!heap_.empty() && + heap_[0].message->sequence_num() == next_sequence_num_ && + heap_[0].ignored) { + DequeueMessage(); } } -void MessageQueue::TakeAllMessages( - std::vector<std::unique_ptr<UserMessageEvent>>* messages) { - *messages = std::move(heap_); - total_queued_bytes_ = 0; -} +MessageQueue::Entry::Entry(bool ignored, + std::unique_ptr<UserMessageEvent> message) + : ignored(ignored), message(std::move(message)) {} + +MessageQueue::Entry::Entry(Entry&&) = default; + +MessageQueue::Entry::~Entry() = default; + +MessageQueue::Entry& MessageQueue::Entry::operator=(Entry&&) = default; } // namespace ports } // namespace core
diff --git a/mojo/core/ports/message_queue.h b/mojo/core/ports/message_queue.h index 1d34222..d8a03cf 100644 --- a/mojo/core/ports/message_queue.h +++ b/mojo/core/ports/message_queue.h
@@ -13,6 +13,7 @@ #include "base/component_export.h" #include "base/macros.h" +#include "base/optional.h" #include "mojo/core/ports/event.h" namespace mojo { @@ -30,19 +31,38 @@ // enforcing it for the producer (see AcceptMessage() below.) class COMPONENT_EXPORT(MOJO_CORE_PORTS) MessageQueue { public: + struct Entry { + Entry(bool ignored, std::unique_ptr<UserMessageEvent> message); + Entry(Entry&&); + ~Entry(); + + Entry& operator=(Entry&&); + + bool ignored; + std::unique_ptr<UserMessageEvent> message; + }; + explicit MessageQueue(); explicit MessageQueue(uint64_t next_sequence_num); ~MessageQueue(); - void set_signalable(bool value) { signalable_ = value; } - uint64_t next_sequence_num() const { return next_sequence_num_; } - bool HasNextMessage() const; + // Indicates if the next message in the queue's sequence is available and + // is targeting slot |slot_id|, if given. + bool HasNextMessage(base::Optional<SlotId> slot_id); + + // Indicates if the next message in the queue's sequence is available, + // regardless of targeted slot ID. If it is, this returns the SlotId of the + // next available message. Otherwise it returns |base::nullopt|. + base::Optional<SlotId> GetNextMessageSlot(); // Gives ownership of the message. If |filter| is non-null, the next message - // will only be retrieved if the filter successfully matches it. - void GetNextMessage(std::unique_ptr<UserMessageEvent>* message, + // will only be retrieved if the filter successfully matches it. If |slot_id| + // is given, this next message will only be retrieved if it belongs to that + // slot. + void GetNextMessage(base::Optional<SlotId> slot_id, + std::unique_ptr<UserMessageEvent>* message, MessageFilter* filter); // Takes ownership of the message. Note: Messages are ordered, so while we @@ -50,18 +70,33 @@ // ahead of this one before we can let any of the messages be returned by // GetNextMessage. // - // Furthermore, once has_next_message is set to true, it will remain false - // until GetNextMessage is called enough times to return a null message. - // In other words, has_next_message acts like an edge trigger. - // + // |*slot_with_next_message| is set to the SlotId of the slot which has the + // next message in the sequence available to it, iff the next message in the + // sequence is available. void AcceptMessage(std::unique_ptr<UserMessageEvent> message, - bool* has_next_message); + base::Optional<SlotId>* slot_with_next_message); + + // Places |*message| in the queue to be ignored. It is important that the + // message not simply be discarded because messages can arrive out of + // sequential order. The queue will retain this message until all preceding + // messages in the sequence are read from the queue, at which point |*message| + // can be safely discarded and the sequence can be advanced beyond it. + // + // Note that if |*message| is the next expected message in this queue, the + // queue is simply advanced beyond its sequence number and ownership of + // |*message| is *not* transferred to the queue. + void IgnoreMessage(std::unique_ptr<UserMessageEvent>* message); // Takes all messages from this queue. Used to safely destroy queued messages // without holding any Port lock. void TakeAllMessages( std::vector<std::unique_ptr<UserMessageEvent>>* messages); + // Takes all leading messages from the queue which target |slot_id|. + void TakeAllLeadingMessagesForSlot( + SlotId slot_id, + std::vector<std::unique_ptr<UserMessageEvent>>* messages); + // The number of messages queued here, regardless of whether the next expected // message has arrived yet. size_t queued_message_count() const { return heap_.size(); } @@ -71,9 +106,12 @@ size_t queued_num_bytes() const { return total_queued_bytes_; } private: - std::vector<std::unique_ptr<UserMessageEvent>> heap_; + void EnqueueMessage(std::unique_ptr<UserMessageEvent> message, bool ignored); + std::unique_ptr<UserMessageEvent> DequeueMessage(); + void DropNextIgnoredMessages(); + + std::vector<Entry> heap_; uint64_t next_sequence_num_; - bool signalable_ = true; size_t total_queued_bytes_ = 0; DISALLOW_COPY_AND_ASSIGN(MessageQueue);
diff --git a/mojo/core/ports/node.cc b/mojo/core/ports/node.cc index 767e37c..c95739a 100644 --- a/mojo/core/ports/node.cc +++ b/mojo/core/ports/node.cc
@@ -80,7 +80,7 @@ #define OOPS(x) DebugError(#x, x) -bool CanAcceptMoreMessages(const Port* port) { +bool CanAcceptMoreMessages(Port* port, SlotId slot_id) { // Have we already doled out the last message (i.e., do we expect to NOT // receive further messages)? uint64_t next_sequence_num = port->message_queue.next_sequence_num(); @@ -90,7 +90,13 @@ if (port->last_sequence_num_to_receive == next_sequence_num - 1) return false; } - return true; + + Port::Slot* slot = port->GetSlot(slot_id); + if (!slot) + return false; + + return !slot->peer_closed || + slot->last_sequence_num_to_receive >= next_sequence_num; } void GenerateRandomPortName(PortName* name) { @@ -193,9 +199,15 @@ port->state = Port::kReceiving; UpdatePortPeerAddress(port_ref.name(), port, peer_node_name, peer_port_name); + + Port::Slot& default_slot = port->slots[kDefaultSlotId]; + default_slot.can_signal = true; + default_slot.peer_closed = false; + default_slot.last_sequence_num_sent = 0; + default_slot.last_sequence_num_to_receive = 0; } - delegate_->PortStatusChanged(port_ref); + delegate_->SlotStatusChanged(SlotRef(port_ref, kDefaultSlotId)); return OK; } @@ -246,85 +258,55 @@ return OK; } +int Node::ClosePortSlot(const SlotRef& slot_ref) { + return ClosePortOrSlotImpl(slot_ref.port(), slot_ref.slot_id()); +} + int Node::ClosePort(const PortRef& port_ref) { - std::vector<std::unique_ptr<UserMessageEvent>> undelivered_messages; - NodeName peer_node_name; - PortName peer_port_name; - uint64_t last_sequence_num = 0; - bool was_initialized = false; - { - SinglePortLocker locker(&port_ref); - auto* port = locker.port(); - switch (port->state) { - case Port::kUninitialized: - break; + return ClosePortOrSlotImpl(port_ref, base::nullopt); +} - case Port::kReceiving: - was_initialized = true; - port->state = Port::kClosed; +int Node::GetStatus(const SlotRef& slot_ref, SlotStatus* slot_status) { + SinglePortLocker locker(&slot_ref.port()); + auto* port = locker.port(); + if (port->state != Port::kReceiving) + return ERROR_PORT_STATE_UNEXPECTED; - // We pass along the sequence number of the last message sent from this - // port to allow the peer to have the opportunity to consume all inbound - // messages before notifying the embedder that this port is closed. - last_sequence_num = port->next_sequence_num_to_send - 1; + slot_status->has_messages = + port->message_queue.HasNextMessage(slot_ref.slot_id()); + slot_status->receiving_messages = + CanAcceptMoreMessages(port, slot_ref.slot_id()); + slot_status->peer_remote = port->peer_node_name != name_; + slot_status->queued_message_count = + port->message_queue.queued_message_count(); + slot_status->queued_num_bytes = port->message_queue.queued_num_bytes(); - peer_node_name = port->peer_node_name; - peer_port_name = port->peer_port_name; - - // If the port being closed still has unread messages, then we need to - // take care to close those ports so as to avoid leaking memory. - port->message_queue.TakeAllMessages(&undelivered_messages); - break; - - default: - return ERROR_PORT_STATE_UNEXPECTED; - } - } - - ErasePort(port_ref.name()); - - if (was_initialized) { - DVLOG(2) << "Sending ObserveClosure from " << port_ref.name() << "@" - << name_ << " to " << peer_port_name << "@" << peer_node_name; - delegate_->ForwardEvent(peer_node_name, - std::make_unique<ObserveClosureEvent>( - peer_port_name, last_sequence_num)); - for (const auto& message : undelivered_messages) { - for (size_t i = 0; i < message->num_ports(); ++i) { - PortRef ref; - if (GetPort(message->ports()[i], &ref) == OK) - ClosePort(ref); - } - } + if (port->peer_closed) { + slot_status->peer_closed = port->peer_closed; + } else { + Port::Slot* slot = port->GetSlot(slot_ref.slot_id()); + if (!slot) + return ERROR_PORT_STATE_UNEXPECTED; + slot_status->peer_closed = slot->peer_closed; } return OK; } int Node::GetStatus(const PortRef& port_ref, PortStatus* port_status) { - SinglePortLocker locker(&port_ref); - auto* port = locker.port(); - if (port->state != Port::kReceiving) - return ERROR_PORT_STATE_UNEXPECTED; - - port_status->has_messages = port->message_queue.HasNextMessage(); - port_status->receiving_messages = CanAcceptMoreMessages(port); - port_status->peer_closed = port->peer_closed; - port_status->peer_remote = port->peer_node_name != name_; - port_status->queued_message_count = - port->message_queue.queued_message_count(); - port_status->queued_num_bytes = port->message_queue.queued_num_bytes(); - return OK; + return GetStatus(SlotRef(port_ref, kDefaultSlotId), port_status); } -int Node::GetMessage(const PortRef& port_ref, +int Node::GetMessage(const SlotRef& slot_ref, std::unique_ptr<UserMessageEvent>* message, MessageFilter* filter) { *message = nullptr; - DVLOG(4) << "GetMessage for " << port_ref.name() << "@" << name_; + DVLOG(4) << "GetMessage for " << slot_ref.port().name() << "@" << name_; + + bool peer_closed = false; { - SinglePortLocker locker(&port_ref); + SinglePortLocker locker(&slot_ref.port()); auto* port = locker.port(); // This could also be treated like the port being unknown since the @@ -334,13 +316,16 @@ // Let the embedder get messages until there are no more before reporting // that the peer closed its end. - if (!CanAcceptMoreMessages(port)) - return ERROR_PORT_PEER_CLOSED; - - port->message_queue.GetNextMessage(message, filter); + if (CanAcceptMoreMessages(port, slot_ref.slot_id())) + port->message_queue.GetNextMessage(slot_ref.slot_id(), message, filter); + else + peer_closed = true; } - // Allow referenced ports to trigger PortStatusChanged calls. + // Allow referenced ports to trigger SlotStatusChanged calls now that the + // message which contains them is actually being read. A consumer who cares + // about the status updates can ensure that they are properly watching for + // these events before making any calls to |GetMessage()|. if (*message) { for (size_t i = 0; i < (*message)->num_ports(); ++i) { PortRef new_port_ref; @@ -351,26 +336,47 @@ SinglePortLocker locker(&new_port_ref); DCHECK(locker.port()->state == Port::kReceiving); - locker.port()->message_queue.set_signalable(true); + + Port::Slot* slot = locker.port()->GetSlot(kDefaultSlotId); + DCHECK(slot); + slot->can_signal = true; } // The user may retransmit this message from another port. We reset the // sequence number so that the message will get a new one if that happens. (*message)->set_sequence_num(0); + + // If we read a message, we may need to flush subsequent unreadable messages + // to unblock the rest of the message sequence. Note that we only notify + // the slot with the next available message (if any) when it's different + // from the slot we just read. + base::Optional<SlotId> slot_to_notify = + FlushUnreadableMessages(slot_ref.port()); + if (slot_to_notify && slot_to_notify != slot_ref.slot_id()) + delegate_->SlotStatusChanged(SlotRef(slot_ref.port(), *slot_to_notify)); } + if (peer_closed) + return ERROR_PORT_PEER_CLOSED; + return OK; } -int Node::SendUserMessage(const PortRef& port_ref, +int Node::GetMessage(const PortRef& port_ref, + std::unique_ptr<UserMessageEvent>* message, + MessageFilter* filter) { + return GetMessage(SlotRef(port_ref, kDefaultSlotId), message, filter); +} + +int Node::SendUserMessage(const SlotRef& slot_ref, std::unique_ptr<UserMessageEvent> message) { - int rv = SendUserMessageInternal(port_ref, &message); + int rv = SendUserMessageInternal(slot_ref, &message); if (rv != OK) { // If send failed, close all carried ports. Note that we're careful not to // close the sending port itself if it happened to be one of the encoded // ports (an invalid but possible condition.) for (size_t i = 0; i < message->num_ports(); ++i) { - if (message->ports()[i] == port_ref.name()) + if (message->ports()[i] == slot_ref.port().name()) continue; PortRef port; @@ -381,6 +387,21 @@ return rv; } +int Node::SendUserMessage(const PortRef& port_ref, + std::unique_ptr<UserMessageEvent> message) { + return SendUserMessage(SlotRef(port_ref, kDefaultSlotId), std::move(message)); +} + +SlotId Node::AllocateSlot(const PortRef& port_ref) { + SinglePortLocker locker(&port_ref); + return locker.port()->AllocateSlot(); +} + +bool Node::AddSlotFromPeer(const PortRef& port_ref, SlotId peer_slot_id) { + SinglePortLocker locker(&port_ref); + return locker.port()->AddSlotFromPeer(peer_slot_id); +} + int Node::AcceptEvent(ScopedEvent event) { switch (event->type()) { case Event::Type::kUserMessage: @@ -395,6 +416,8 @@ return OnObserveClosure(Event::Cast<ObserveClosureEvent>(&event)); case Event::Type::kMergePort: return OnMergePort(Event::Cast<MergePortEvent>(&event)); + case Event::Type::kSlotClosed: + return OnSlotClosed(Event::Cast<SlotClosedEvent>(&event)); } return OOPS(ERROR_NOT_IMPLEMENTED); } @@ -427,7 +450,7 @@ // update so it notices that its peer is now remote. PortRef local_peer; if (GetPort(new_port_descriptor.peer_port_name, &local_peer) == OK) - delegate_->PortStatusChanged(local_peer); + delegate_->SlotStatusChanged(SlotRef(local_peer, kDefaultSlotId)); } delegate_->ForwardEvent( @@ -455,9 +478,91 @@ return OK; } +int Node::ClosePortOrSlotImpl(const PortRef& port_ref, + base::Optional<SlotId> slot_id) { + std::vector<std::unique_ptr<UserMessageEvent>> undelivered_messages; + NodeName peer_node_name; + PortName peer_port_name; + uint64_t last_sequence_num = 0; + bool was_initialized = false; + bool port_closed = false; + { + SinglePortLocker locker(&port_ref); + auto* port = locker.port(); + switch (port->state) { + case Port::kUninitialized: + port_closed = true; + break; + + case Port::kReceiving: { + was_initialized = true; + + Port::Slot* slot = slot_id ? port->GetSlot(*slot_id) : nullptr; + if (!slot_id || (slot && port->slots.size() == 1)) { + // If no SlotId was given or we are closing the last slot on the port, + // close the whole port. + port->state = Port::kClosed; + port_closed = true; + + // We pass along the sequence number of the last message sent from + // this port to allow the peer to have the opportunity to consume all + // inbound messages before notifying the embedder that the port or + // slot is closed. + last_sequence_num = port->next_sequence_num_to_send - 1; + } else { + last_sequence_num = slot->last_sequence_num_sent; + port->slots.erase(*slot_id); + } + + peer_node_name = port->peer_node_name; + peer_port_name = port->peer_port_name; + + // If the port being closed still has unread messages, then we need to + // take care to close those ports so as to avoid leaking memory. + if (port_closed) { + port->message_queue.TakeAllMessages(&undelivered_messages); + } else { + port->message_queue.TakeAllLeadingMessagesForSlot( + *slot_id, &undelivered_messages); + } + break; + } + + default: + return ERROR_PORT_STATE_UNEXPECTED; + } + } + + if (port_closed) + ErasePort(port_ref.name()); + + base::Optional<SlotId> slot_to_notify; + if (was_initialized) { + if (port_closed) { + DVLOG(2) << "Sending ObserveClosure from " << port_ref.name() << "@" + << name_ << " to " << peer_port_name << "@" << peer_node_name; + delegate_->ForwardEvent(peer_node_name, + std::make_unique<ObserveClosureEvent>( + peer_port_name, last_sequence_num)); + } else { + // This path is only hit when closing a non-default slot of a port with + // multiple slots. + delegate_->ForwardEvent(peer_node_name, + std::make_unique<SlotClosedEvent>( + peer_port_name, *slot_id, last_sequence_num)); + slot_to_notify = FlushUnreadableMessages(port_ref); + } + DiscardUnreadMessages(std::move(undelivered_messages)); + } + + if (slot_to_notify) + delegate_->SlotStatusChanged(SlotRef(port_ref, *slot_to_notify)); + + return OK; +} + int Node::OnUserMessage(std::unique_ptr<UserMessageEvent> message) { PortName port_name = message->port_name(); - #if DCHECK_IS_ON() std::ostringstream ports_buf; for (size_t i = 0; i < message->num_ports(); ++i) { @@ -496,50 +601,64 @@ } } - PortRef port_ref; - GetPort(port_name, &port_ref); - bool has_next_message = false; + PortRef receiving_port_ref; + GetPort(port_name, &receiving_port_ref); + base::Optional<SlotId> slot_with_next_message; bool message_accepted = false; bool should_forward_messages = false; - if (port_ref.is_valid()) { - SinglePortLocker locker(&port_ref); + if (receiving_port_ref.is_valid()) { + SinglePortLocker locker(&receiving_port_ref); auto* port = locker.port(); // Reject spurious messages if we've already received the last expected // message. - if (CanAcceptMoreMessages(port)) { + SlotId slot_id = message->slot_id(); + if (CanAcceptMoreMessages(port, slot_id)) { message_accepted = true; - port->message_queue.AcceptMessage(std::move(message), &has_next_message); + port->message_queue.AcceptMessage(std::move(message), + &slot_with_next_message); if (port->state == Port::kBuffering) { - has_next_message = false; + slot_with_next_message.reset(); } else if (port->state == Port::kProxying) { - has_next_message = false; + slot_with_next_message.reset(); should_forward_messages = true; + } else { + Port::Slot* slot = port->GetSlot(slot_id); + if (!slot || !slot->can_signal) + slot_with_next_message.reset(); } } } if (should_forward_messages) { - int rv = ForwardUserMessagesFromProxy(port_ref); + int rv = ForwardUserMessagesFromProxy(receiving_port_ref); if (rv != OK) return rv; - TryRemoveProxy(port_ref); + TryRemoveProxy(receiving_port_ref); } if (!message_accepted) { DVLOG(2) << "Message not accepted!\n"; - // Close all newly accepted ports as they are effectively orphaned. - for (size_t i = 0; i < message->num_ports(); ++i) { - PortRef attached_port_ref; - if (GetPort(message->ports()[i], &attached_port_ref) == OK) { - ClosePort(attached_port_ref); - } else { - DLOG(WARNING) << "Cannot close non-existent port!\n"; + DiscardPorts(message.get()); + + if (receiving_port_ref.is_valid()) { + { + // We still have to inform the MessageQueue about this message so it can + // keep the sequence progressing forward. + SinglePortLocker locker(&receiving_port_ref); + locker.port()->message_queue.IgnoreMessage(&message); } + + // It's possible that some later message in the sequence was already in + // queue, and it may now be unblocked by the discarding of this message. + slot_with_next_message = FlushUnreadableMessages(receiving_port_ref); } - } else if (has_next_message) { - delegate_->PortStatusChanged(port_ref); + } + + if (slot_with_next_message) { + delegate_->SlotStatusChanged( + SlotRef(receiving_port_ref, *slot_with_next_message)); } return OK; @@ -593,7 +712,7 @@ << event->proxy_target_port_name() << "@" << event->proxy_target_node_name(); - bool update_status = false; + base::StackVector<SlotId, 2> slots_to_update; ScopedEvent event_to_forward; NodeName event_target_node; { @@ -613,7 +732,9 @@ event_target_node = event->proxy_node_name(); event_to_forward = std::make_unique<ObserveProxyAckEvent>( event->proxy_port_name(), port->next_sequence_num_to_send - 1); - update_status = true; + slots_to_update.container().reserve(port->slots.size()); + for (const auto& entry : port->slots) + slots_to_update.container().push_back(entry.first); DVLOG(2) << "Forwarding ObserveProxyAck from " << event->port_name() << "@" << name_ << " to " << event->proxy_port_name() << "@" << event_target_node; @@ -648,8 +769,8 @@ if (event_to_forward) delegate_->ForwardEvent(event_target_node, std::move(event_to_forward)); - if (update_status) - delegate_->PortStatusChanged(port_ref); + for (auto slot_id : slots_to_update.container()) + delegate_->SlotStatusChanged(SlotRef(port_ref, slot_id)); return OK; } @@ -701,7 +822,7 @@ // the receiving end, and this message serves as an equivalent to // ObserveProxyAck. - bool notify_delegate = false; + base::StackVector<SlotId, 2> slots_to_update; NodeName peer_node_name; PortName peer_port_name; bool try_remove_proxy = false; @@ -722,8 +843,9 @@ // are notified to remove themselves. if (port->state == Port::kReceiving) { - notify_delegate = true; - + slots_to_update.container().reserve(port->slots.size()); + for (const auto& entry : port->slots) + slots_to_update.container().push_back(entry.first); // When forwarding along the other half of the port cycle, this will only // reach dead-end proxies. Tell them we've sent our last message so they // can go away. @@ -757,8 +879,8 @@ event->set_port_name(peer_port_name); delegate_->ForwardEvent(peer_node_name, std::move(event)); - if (notify_delegate) - delegate_->PortStatusChanged(port_ref); + for (auto slot_id : slots_to_update.container()) + delegate_->SlotStatusChanged(SlotRef(port_ref, slot_id)); return OK; } @@ -799,6 +921,34 @@ false /* allow_close_on_bad_state */); } +int Node::OnSlotClosed(std::unique_ptr<SlotClosedEvent> event) { + // OK if the port doesn't exist, as it may have been closed already. + PortRef port_ref; + if (GetPort(event->port_name(), &port_ref) != OK) + return OK; + + SlotId local_slot_id = event->slot_id() == kDefaultSlotId + ? kDefaultSlotId + : (event->slot_id() ^ kPeerAllocatedSlotIdBit); + { + SinglePortLocker locker(&port_ref); + Port* port = locker.port(); + + // The local slot may have been closed already. No need to take further + // action here. + Port::Slot* slot = port->GetSlot(local_slot_id); + if (!slot) + return OK; + + slot->peer_closed = true; + slot->last_sequence_num_to_receive = event->last_sequence_num(); + } + + delegate_->SlotStatusChanged(SlotRef(port_ref, local_slot_id)); + + return OK; +} + int Node::AddPortWithName(const PortName& port_name, scoped_refptr<Port> port) { PortLocker::AssertNoPortsLockedOnCurrentThread(); base::AutoLock lock(ports_lock_); @@ -837,16 +987,19 @@ DVLOG(2) << "Deleted port " << port_name << "@" << name_; } -int Node::SendUserMessageInternal(const PortRef& port_ref, +int Node::SendUserMessageInternal(const SlotRef& slot_ref, std::unique_ptr<UserMessageEvent>* message) { std::unique_ptr<UserMessageEvent>& m = *message; for (size_t i = 0; i < m->num_ports(); ++i) { - if (m->ports()[i] == port_ref.name()) + if (m->ports()[i] == slot_ref.port().name()) return ERROR_PORT_CANNOT_SEND_SELF; } + if (slot_ref.slot_id() != kDefaultSlotId) + m->set_slot_id(slot_ref.slot_id() ^ kPeerAllocatedSlotIdBit); + NodeName target_node; - int rv = PrepareToForwardUserMessage(port_ref, Port::kReceiving, + int rv = PrepareToForwardUserMessage(slot_ref, Port::kReceiving, false /* ignore_closed_peer */, m.get(), &target_node); if (rv != OK) @@ -1040,9 +1193,15 @@ << "; last_sequence_num_to_receive=" << port->last_sequence_num_to_receive << "]"; - // A newly accepted port is not signalable until the message referencing the - // new port finds its way to the consumer (see GetMessage). - port->message_queue.set_signalable(false); + // Initialize the default slot on this port. Newly accepted ports must have + // only the default slot, as ports with additional slots are non-transferrable + // and thus can't be the subject of an |AcceptPort()| call. + Port::Slot& slot = port->slots[kDefaultSlotId]; + slot.can_signal = false; + slot.peer_closed = port_descriptor.peer_closed; + slot.last_sequence_num_to_receive = + port_descriptor.last_sequence_num_to_receive; + slot.last_sequence_num_sent = port_descriptor.next_sequence_num_to_send - 1; int rv = AddPortWithName(port_name, std::move(port)); if (rv != OK) @@ -1055,7 +1214,7 @@ return OK; } -int Node::PrepareToForwardUserMessage(const PortRef& forwarding_port_ref, +int Node::PrepareToForwardUserMessage(const SlotRef& forwarding_slot_ref, Port::State expected_port_state, bool ignore_closed_peer, UserMessageEvent* message, @@ -1064,7 +1223,7 @@ for (;;) { NodeName target_node_name; { - SinglePortLocker locker(&forwarding_port_ref); + SinglePortLocker locker(&forwarding_slot_ref.port()); target_node_name = locker.port()->peer_node_name; } @@ -1086,7 +1245,7 @@ base::StackVector<const PortRef*, 5> ports_to_lock; attached_port_refs.container().resize(message->num_ports()); ports_to_lock.container().resize(message->num_ports() + 1); - ports_to_lock[0] = &forwarding_port_ref; + ports_to_lock[0] = &forwarding_slot_ref.port(); for (size_t i = 0; i < message->num_ports(); ++i) { const PortName& attached_port_name = message->ports()[i]; auto iter = ports_.find(attached_port_name); @@ -1096,7 +1255,7 @@ } PortLocker locker(ports_to_lock.container().data(), ports_to_lock.container().size()); - auto* forwarding_port = locker.GetPort(forwarding_port_ref); + auto* forwarding_port = locker.GetPort(forwarding_slot_ref.port()); if (forwarding_port->peer_node_name != target_node_name) { // The target node has already changed since we last held the lock. @@ -1118,7 +1277,7 @@ // Messages may already have a sequence number if they're being forwarded by // a proxy. Otherwise, use the next outgoing sequence number. if (message->sequence_num() == 0) - message->set_sequence_num(forwarding_port->next_sequence_num_to_send++); + message->set_sequence_num(forwarding_port->next_sequence_num_to_send); #if DCHECK_IS_ON() std::ostringstream ports_buf; for (size_t i = 0; i < message->num_ports(); ++i) { @@ -1130,23 +1289,18 @@ if (message->num_ports() > 0) { // Sanity check to make sure we can actually send all the attached ports. - // They must all be in the |kReceiving| state and must not be the sender's - // own peer. + // They must all be in the |kReceiving| state, must not be the sender's + // own peer, and must have no slots aside from the default slot. DCHECK_EQ(message->num_ports(), attached_port_refs.container().size()); for (size_t i = 0; i < message->num_ports(); ++i) { auto* attached_port = locker.GetPort(attached_port_refs[i]); - int error = OK; - if (attached_port->state != Port::kReceiving) { - error = ERROR_PORT_STATE_UNEXPECTED; + if (attached_port->state != Port::kReceiving || + attached_port->slots.size() != 1 || + attached_port->slots.count(kDefaultSlotId) != 1) { + return ERROR_PORT_STATE_UNEXPECTED; } else if (attached_port_refs[i].name() == forwarding_port->peer_port_name) { - error = ERROR_PORT_CANNOT_SEND_PEER; - } - - if (error != OK) { - // Not going to send. Backpedal on the sequence number. - forwarding_port->next_sequence_num_to_send--; - return error; + return ERROR_PORT_CANNOT_SEND_PEER; } } @@ -1168,10 +1322,21 @@ #if DCHECK_IS_ON() DVLOG(4) << "Sending message " << message->sequence_num() << " [ports=" << ports_buf.str() << "]" - << " from " << forwarding_port_ref.name() << "@" << name_ << " to " - << forwarding_port->peer_port_name << "@" << target_node_name; + << " from " << forwarding_slot_ref.port().name() << "@" << name_ + << " to " << forwarding_port->peer_port_name << "@" + << target_node_name; #endif + // We're definitely going to send this message, so we can bump the port's + // and slot's outgoing sequence number now. + Port::Slot* forwarding_slot = + forwarding_port->GetSlot(forwarding_slot_ref.slot_id()); + if (forwarding_slot) { + forwarding_slot->last_sequence_num_sent = + forwarding_port->next_sequence_num_to_send; + } + ++forwarding_port->next_sequence_num_to_send; + *forward_to_node = target_node_name; message->set_port_name(forwarding_port->peer_port_name); break; @@ -1186,7 +1351,7 @@ if (descriptor.peer_node_name == name_) { PortRef local_peer; if (GetPort(descriptor.peer_port_name, &local_peer) == OK) - delegate_->PortStatusChanged(local_peer); + delegate_->SlotStatusChanged(SlotRef(local_peer, kDefaultSlotId)); } } } @@ -1244,15 +1409,16 @@ std::unique_ptr<UserMessageEvent> message; { SinglePortLocker locker(&port_ref); - locker.port()->message_queue.GetNextMessage(&message, nullptr); + locker.port()->message_queue.GetNextMessage(base::nullopt, &message, + nullptr); if (!message) break; } NodeName target_node; - int rv = PrepareToForwardUserMessage(port_ref, Port::kProxying, - true /* ignore_closed_peer */, - message.get(), &target_node); + int rv = PrepareToForwardUserMessage( + SlotRef(port_ref, kDefaultSlotId), Port::kProxying, + true /* ignore_closed_peer */, message.get(), &target_node); if (rv != OK) return rv; @@ -1295,7 +1461,7 @@ if (!port->remove_proxy_on_last_message) return; - if (!CanAcceptMoreMessages(port)) { + if (!CanAcceptMoreMessages(port, kDefaultSlotId)) { should_erase = true; if (port->send_on_proxy_removal) { removal_target_node = port->send_on_proxy_removal->first; @@ -1395,9 +1561,18 @@ DVLOG(2) << "Forcibly deleted port " << proxy_name << "@" << name_; } - // Wake up any receiving ports who have just observed simulated peer closure. - for (const auto& port : ports_to_notify) - delegate_->PortStatusChanged(port); + // Wake up any receiving slots who have just observed simulated peer closure. + for (const auto& port : ports_to_notify) { + base::StackVector<SlotId, 2> slots_to_update; + { + SinglePortLocker locker(&port); + slots_to_update.container().reserve(locker.port()->slots.size()); + for (const auto& entry : locker.port()->slots) + slots_to_update.container().push_back(entry.first); + } + for (auto slot_id : slots_to_update) + delegate_->SlotStatusChanged(SlotRef(port, slot_id)); + } for (const auto& proxy_name : dead_proxies_to_broadcast) { // Broadcast an event signifying that this proxy is no longer functioning. @@ -1412,14 +1587,7 @@ DestroyAllPortsWithPeer(name_, proxy_name); } - // Close any ports referenced by undelivered messages. - for (const auto& message : undelivered_messages) { - for (size_t i = 0; i < message->num_ports(); ++i) { - PortRef ref; - if (GetPort(message->ports()[i], &ref) == OK) - ClosePort(ref); - } - } + DiscardUnreadMessages(std::move(undelivered_messages)); } void Node::UpdatePortPeerAddress(const PortName& local_port_name, @@ -1489,7 +1657,56 @@ DCHECK(node_); } -Node::DelegateHolder::~DelegateHolder() {} +void Node::DiscardUnreadMessages( + std::vector<std::unique_ptr<UserMessageEvent>> messages) { + PortLocker::AssertNoPortsLockedOnCurrentThread(); + for (const auto& message : messages) + DiscardPorts(message.get()); +} + +void Node::DiscardPorts(UserMessageEvent* message) { + PortLocker::AssertNoPortsLockedOnCurrentThread(); + for (size_t i = 0; i < message->num_ports(); ++i) { + PortRef ref; + if (GetPort(message->ports()[i], &ref) == OK) + ClosePort(ref); + } +} + +base::Optional<SlotId> Node::FlushUnreadableMessages(const PortRef& port_ref) { + std::vector<std::unique_ptr<UserMessageEvent>> unread_messages; + base::Optional<SlotId> slot_to_notify; + + { + SinglePortLocker locker(&port_ref); + Port* port = locker.port(); + + base::Optional<SlotId> next_message_slot; + while ((next_message_slot = port->message_queue.GetNextMessageSlot())) { + if (port->GetSlot(*next_message_slot)) { + // The next message goes to a valid port slot, leave it in queue and + // make sure the slot knows about this. + slot_to_notify = *next_message_slot; + break; + } + + std::vector<std::unique_ptr<UserMessageEvent>> messages; + port->message_queue.TakeAllLeadingMessagesForSlot(*next_message_slot, + &messages); + std::move(messages.begin(), messages.end(), + std::back_inserter(unread_messages)); + } + } + + // If we discarded some messages and a new message is now available, notify + // its slot that this is the case. + if (unread_messages.empty()) + return base::nullopt; + + return slot_to_notify; +} + +Node::DelegateHolder::~DelegateHolder() = default; #if DCHECK_IS_ON() void Node::DelegateHolder::EnsureSafeDelegateAccess() const {
diff --git a/mojo/core/ports/node.h b/mojo/core/ports/node.h index 9c771eb2..2e0c24ee 100644 --- a/mojo/core/ports/node.h +++ b/mojo/core/ports/node.h
@@ -15,11 +15,13 @@ #include "base/containers/flat_map.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/optional.h" #include "base/synchronization/lock.h" #include "mojo/core/ports/event.h" #include "mojo/core/ports/name.h" #include "mojo/core/ports/port.h" #include "mojo/core/ports/port_ref.h" +#include "mojo/core/ports/slot_ref.h" #include "mojo/core/ports/user_data.h" namespace mojo { @@ -37,7 +39,7 @@ ERROR_NOT_IMPLEMENTED = -100, }; -struct PortStatus { +struct SlotStatus { bool has_messages; bool receiving_messages; bool peer_closed; @@ -46,6 +48,10 @@ size_t queued_num_bytes; }; +// TODO(https://crbug.com/941809): Remove this alias, which only exists to +// reduce churn while switching Mojo core from ports to slots. +using PortStatus = SlotStatus; + class MessageFilter; class NodeDelegate; @@ -111,17 +117,25 @@ int SetUserData(const PortRef& port_ref, scoped_refptr<UserData> user_data); int GetUserData(const PortRef& port_ref, scoped_refptr<UserData>* user_data); + // Closes a single slot on port. No more messages can be sent from or + // delivered to the slot. If it's the last slot on its port, the port is also + // closed. + int ClosePortSlot(const SlotRef& slot_ref); + // Prevents further messages from being sent from this port or delivered to // this port. The port is removed, and the port's peer is notified of the // closure after it has consumed all pending messages. int ClosePort(const PortRef& port_ref); - // Returns the current status of the port. + // Returns the current status of the port slot. + int GetStatus(const SlotRef& slot_ref, SlotStatus* slot_status); + + // Returns the current status of the default slot on the port. int GetStatus(const PortRef& port_ref, PortStatus* port_status); - // Returns the next available message on the specified port or returns a null - // message if there are none available. Returns ERROR_PORT_PEER_CLOSED to - // indicate that this port's peer has closed. In such cases GetMessage may + // Returns the next available message on the specified port slot or returns a + // null message if there are none available. Returns ERROR_PORT_PEER_CLOSED to + // indicate that this slot's peer has closed. In such cases GetMessage may // be called until it yields a null message, indicating that no more messages // may be read from the port. // @@ -130,16 +144,44 @@ // available message, GetMessage() behaves as if there is no message // available. Ownership of |filter| is not taken, and it must outlive the // extent of this call. + int GetMessage(const SlotRef& slot_ref, + std::unique_ptr<UserMessageEvent>* message, + MessageFilter* filter); + + // TODO(https://crbug.com/941809): Remove this helper, which exists only to + // reduce intermediate churn while switching to SlotRef in other places. This + // retrieves a message from the default slot of |port_ref|. See above for more + // details. int GetMessage(const PortRef& port_ref, std::unique_ptr<UserMessageEvent>* message, MessageFilter* filter); - // Sends a message from the specified port to its peer. Note that the message - // notification may arrive synchronously (via PortStatusChanged() on the - // delegate) if the peer is local to this Node. + // Sends a message from the specified port slot to its peer. Note that the + // message notification may arrive synchronously (via SlotStatusChanged() on + // the delegate) if the peer is local to this Node. + int SendUserMessage(const SlotRef& slot_ref, + std::unique_ptr<UserMessageEvent> message); + + // TODO(https://crbug.com/941809): Remove this helper, which exists only to + // reduce intermediate churn while switching to SlotRef in other places. This + // sends a message on the default slot of |port_ref|. See above for more + // details. int SendUserMessage(const PortRef& port_ref, std::unique_ptr<UserMessageEvent> message); + // Allocates a new slot on the given port and returns its SlotId. Note that + // in order to get end-to-end communication on this slot, the port's peer must + // also add a slot with the same ID plus |kPeerAllocatedSlotIdBit| set. This + // can be achieved by calling AddSlotFromPeer on the peer slot with the same + // ID returned by this call. + SlotId AllocateSlot(const PortRef& port_ref); + + // Adds a new slot on the given port, corresponding to the port's peer slot + // |peer_slot_id|. The local ID of this added slot will always be + // |peer_slot_id | kPeerAllocatedSlotIdBit|. Returns |true| iff |port_ref| was + // valid and a corresponding slot on the port did not already exist. + bool AddSlotFromPeer(const PortRef& port_ref, SlotId peer_slot_id); + // Corresponding to NodeDelegate::ForwardEvent. int AcceptEvent(ScopedEvent event); @@ -194,17 +236,23 @@ DISALLOW_COPY_AND_ASSIGN(DelegateHolder); }; + // Closes a specific slot or an entire Port, depending on whether |slot_id| + // has a value. + int ClosePortOrSlotImpl(const PortRef& port_ref, + base::Optional<SlotId> slot_id); + int OnUserMessage(std::unique_ptr<UserMessageEvent> message); int OnPortAccepted(std::unique_ptr<PortAcceptedEvent> event); int OnObserveProxy(std::unique_ptr<ObserveProxyEvent> event); int OnObserveProxyAck(std::unique_ptr<ObserveProxyAckEvent> event); int OnObserveClosure(std::unique_ptr<ObserveClosureEvent> event); int OnMergePort(std::unique_ptr<MergePortEvent> event); + int OnSlotClosed(std::unique_ptr<SlotClosedEvent> event); int AddPortWithName(const PortName& port_name, scoped_refptr<Port> port); void ErasePort(const PortName& port_name); - int SendUserMessageInternal(const PortRef& port_ref, + int SendUserMessageInternal(const SlotRef& port_ref, std::unique_ptr<UserMessageEvent>* message); int MergePortsInternal(const PortRef& port0_ref, const PortRef& port1_ref, @@ -216,7 +264,7 @@ int AcceptPort(const PortName& port_name, const Event::PortDescriptor& port_descriptor); - int PrepareToForwardUserMessage(const PortRef& forwarding_port_ref, + int PrepareToForwardUserMessage(const SlotRef& forwarding_slot_ref, Port::State expected_port_state, bool ignore_closed_peer, UserMessageEvent* message, @@ -249,6 +297,27 @@ const PortName& port1_name, Port* port1); + // Safely discards a collection of UserMessageEvent objects which may contain + // unclaimed local Port references. Ensures that any such ports are properly + // cleaned up. + void DiscardUnreadMessages( + std::vector<std::unique_ptr<UserMessageEvent>> messages); + + // Closes all ports carried by a message. If a message is being discarded + // without anyone reading it, its carried ports cannot possibly be useful. + // Discarding them avoids leaking memory. + void DiscardPorts(UserMessageEvent* message); + + // Flushes any unreadable messages for dead slots on |port_ref|. This is + // called any time a port's MessageQueue is changed in a way that might make + // a new message available (e.g. a slot is closed, or a message is read). + // + // If this returns a valid SlotId, the port's MessageQueue was modified by + // this call, the next message in the queue is now available, and the message + // targets the returned slot. Returns nullopt if either the queue was + // unchanged by the call or the next message in queue is not available yet. + base::Optional<SlotId> FlushUnreadableMessages(const PortRef& port_ref); + const NodeName name_; const DelegateHolder delegate_;
diff --git a/mojo/core/ports/node_delegate.h b/mojo/core/ports/node_delegate.h index afe1c4c..9415af9 100644 --- a/mojo/core/ports/node_delegate.h +++ b/mojo/core/ports/node_delegate.h
@@ -25,10 +25,10 @@ // Broadcast an event to all nodes. virtual void BroadcastEvent(ScopedEvent event) = 0; - // Indicates that the port's status has changed recently. Use Node::GetStatus - // to query the latest status of the port. Note, this event could be spurious - // if another thread is simultaneously modifying the status of the port. - virtual void PortStatusChanged(const PortRef& port_ref) = 0; + // Indicates that the slot's status has changed recently. Use Node::GetStatus + // to query the latest status of the slot. Note, this event could be spurious + // if another thread is simultaneously modifying the status of the slot. + virtual void SlotStatusChanged(const SlotRef& slot_ref) = 0; }; } // namespace ports
diff --git a/mojo/core/ports/port.cc b/mojo/core/ports/port.cc index 7186979..c6e136d 100644 --- a/mojo/core/ports/port.cc +++ b/mojo/core/ports/port.cc
@@ -19,6 +19,27 @@ Port::~Port() {} +Port::Slot* Port::GetSlot(SlotId slot_id) { + auto it = slots.find(slot_id); + if (it == slots.end()) + return nullptr; + return &it->second; +} + +SlotId Port::AllocateSlot() { + DCHECK_EQ(state, kReceiving); + SlotId id = ++last_allocated_slot_id; + CHECK_EQ(id & kPeerAllocatedSlotIdBit, 0u); + slots.emplace(id, Slot{}); + return id; +} + +bool Port::AddSlotFromPeer(SlotId peer_slot_id) { + if (state != kReceiving || (peer_slot_id & kPeerAllocatedSlotIdBit) != 0) + return false; + return slots.emplace(peer_slot_id | kPeerAllocatedSlotIdBit, Slot{}).second; +} + } // namespace ports } // namespace core } // namespace mojo
diff --git a/mojo/core/ports/port.h b/mojo/core/ports/port.h index d1a825e2..cba3382 100644 --- a/mojo/core/ports/port.h +++ b/mojo/core/ports/port.h
@@ -5,13 +5,15 @@ #ifndef MOJO_CORE_PORTS_PORT_H_ #define MOJO_CORE_PORTS_PORT_H_ +#include <map> #include <memory> -#include <queue> +#include <set> #include <utility> #include <vector> #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/optional.h" #include "base/synchronization/lock.h" #include "mojo/core/ports/event.h" #include "mojo/core/ports/message_queue.h" @@ -107,7 +109,7 @@ PortName peer_port_name; // The next available sequence number to use for outgoing user message events - // originating from this port. + // originating from any slot on this port. uint64_t next_sequence_num_to_send; // The sequence number of the last message this Port should ever expect to @@ -148,9 +150,36 @@ // non-zero cyclic routing distance) receiving Port has been closed. bool peer_closed; + // The next available slot ID to allocate for a new slot on this port. + SlotId last_allocated_slot_id = kDefaultSlotId; + + // Structure for status related to a single slot of this port. + struct Slot { + // Indicates that the slot can signal the embedder about available messages. + bool can_signal = true; + + // Indicates that the peer slot for this slot is closed. + bool peer_closed = false; + + // The last sequence number expected for this slot to receive if the peer is + // closed. + uint64_t last_sequence_num_to_receive; + + // The last sequence number sent on this slot. Will always be less than + // the Port's own |next_sequence_num_to_send|. + uint64_t last_sequence_num_sent; + }; + + // Status information for each slot on this port. + std::map<SlotId, Slot> slots; + Port(uint64_t next_sequence_num_to_send, uint64_t next_sequence_num_to_receive); + Slot* GetSlot(SlotId slot_id); + SlotId AllocateSlot(); + bool AddSlotFromPeer(SlotId peer_slot_id); + void AssertLockAcquired() { #if DCHECK_IS_ON() lock_.AssertAcquired();
diff --git a/mojo/core/ports/ports_unittest.cc b/mojo/core/ports/ports_unittest.cc index e3a2a085..3e8b20d 100644 --- a/mojo/core/ports/ports_unittest.cc +++ b/mojo/core/ports/ports_unittest.cc
@@ -139,6 +139,10 @@ return node_.SendUserMessage(port, NewUserMessageEvent(s, 0)); } + int SendStringMessage(const SlotRef& slot, const std::string& s) { + return node_.SendUserMessage(slot, NewUserMessageEvent(s, 0)); + } + int SendStringMessageWithPort(const PortRef& port, const std::string& s, const PortName& sent_port_name) { @@ -167,6 +171,10 @@ return node_.GetMessage(port, message, nullptr) == OK && *message; } + bool ReadMessage(const SlotRef& slot, ScopedMessage* message) { + return node_.GetMessage(slot, message, nullptr) == OK && *message; + } + bool GetSavedMessage(ScopedMessage* message) { base::AutoLock lock(lock_); if (saved_messages_.empty()) { @@ -210,7 +218,7 @@ router_->BroadcastEvent(this, std::move(event)); } - void PortStatusChanged(const PortRef& port) override { + void SlotStatusChanged(const SlotRef& slot) override { // The port may be closed, in which case we ignore the notification. base::AutoLock lock(lock_); if (!save_messages_) @@ -220,7 +228,7 @@ ScopedMessage message; { base::AutoUnlock unlock(lock_); - if (!ReadMessage(port, &message)) + if (!ReadMessage(slot.port(), &message)) break; } @@ -1638,6 +1646,411 @@ EXPECT_EQ(OK, node0.node().ClosePort(b)); } +TEST_F(PortsTest, BasicSlotUsage) { + TestNode node0(0); + AddNode(&node0); + + PortRef a, b; + node0.node().CreatePortPair(&a, &b); + + SlotId slot_id = node0.node().AllocateSlot(a); + ASSERT_TRUE(node0.node().AddSlotFromPeer(b, slot_id)); + + // Test the default slot. + const char* kMessage1 = "hey"; + ScopedMessage message; + EXPECT_EQ(OK, node0.SendStringMessage(a, kMessage1)); + ASSERT_TRUE(node0.ReadMessage(b, &message)); + EXPECT_TRUE(MessageEquals(message, kMessage1)); + + // Test our newly added slot. + const char* kMessage2 = "hey again"; + EXPECT_EQ(OK, node0.SendStringMessage(SlotRef(a, slot_id), kMessage2)); + ASSERT_TRUE(node0.ReadMessage(SlotRef(b, slot_id | kPeerAllocatedSlotIdBit), + &message)); + EXPECT_TRUE(MessageEquals(message, kMessage2)); + + // Also test it in the reverse direction. + const char* kMessage3 = "hey one more time"; + EXPECT_EQ(OK, node0.SendStringMessage( + SlotRef(b, slot_id | kPeerAllocatedSlotIdBit), kMessage3)); + ASSERT_TRUE(node0.ReadMessage(SlotRef(a, slot_id), &message)); + EXPECT_TRUE(MessageEquals(message, kMessage3)); + + EXPECT_EQ(OK, node0.node().ClosePort(a)); + EXPECT_EQ(OK, node0.node().ClosePort(b)); +} + +TEST_F(PortsTest, MultipleSlots) { + TestNode node0(0); + AddNode(&node0); + + PortRef a, b; + node0.node().CreatePortPair(&a, &b); + + SlotId slot_id1 = node0.node().AllocateSlot(a); + ASSERT_TRUE(node0.node().AddSlotFromPeer(b, slot_id1)); + + SlotId slot_id2 = node0.node().AllocateSlot(a); + ASSERT_TRUE(node0.node().AddSlotFromPeer(b, slot_id2)); + + // Test our newly added slots. + const char* kMessage1 = "hey"; + ScopedMessage message; + EXPECT_EQ(OK, node0.SendStringMessage(SlotRef(a, slot_id1), kMessage1)); + ASSERT_TRUE(node0.ReadMessage(SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit), + &message)); + EXPECT_TRUE(MessageEquals(message, kMessage1)); + + const char* kMessage2 = "hey again"; + EXPECT_EQ(OK, node0.SendStringMessage(SlotRef(a, slot_id2), kMessage2)); + ASSERT_TRUE(node0.ReadMessage(SlotRef(b, slot_id2 | kPeerAllocatedSlotIdBit), + &message)); + EXPECT_TRUE(MessageEquals(message, kMessage2)); + + EXPECT_EQ(OK, node0.node().ClosePort(a)); + EXPECT_EQ(OK, node0.node().ClosePort(b)); +} + +TEST_F(PortsTest, RemoteSlotUsage) { + TestNode node0(0); + AddNode(&node0); + + TestNode node1(1); + AddNode(&node1); + + PortRef a, b; + EXPECT_EQ(OK, node0.node().CreateUninitializedPort(&a)); + EXPECT_EQ(OK, node1.node().CreateUninitializedPort(&b)); + EXPECT_EQ(OK, node0.node().InitializePort(a, node1.name(), b.name())); + EXPECT_EQ(OK, node1.node().InitializePort(b, node0.name(), a.name())); + + SlotId slot_id = node0.node().AllocateSlot(a); + ASSERT_TRUE(node1.node().AddSlotFromPeer(b, slot_id)); + + // Test the default slot. + const char* kMessage1 = "hey"; + ScopedMessage message; + EXPECT_EQ(OK, node0.SendStringMessage(a, kMessage1)); + WaitForIdle(); + ASSERT_TRUE(node1.ReadMessage(b, &message)); + EXPECT_TRUE(MessageEquals(message, kMessage1)); + + // Test our newly added slot. + const char* kMessage2 = "hey again"; + EXPECT_EQ(OK, node0.SendStringMessage(SlotRef(a, slot_id), kMessage2)); + WaitForIdle(); + ASSERT_TRUE(node1.ReadMessage(SlotRef(b, slot_id | kPeerAllocatedSlotIdBit), + &message)); + EXPECT_TRUE(MessageEquals(message, kMessage2)); + + // Also test it in the reverse direction. + const char* kMessage3 = "hey one more time"; + EXPECT_EQ(OK, node1.SendStringMessage( + SlotRef(b, slot_id | kPeerAllocatedSlotIdBit), kMessage3)); + WaitForIdle(); + ASSERT_TRUE(node0.ReadMessage(SlotRef(a, slot_id), &message)); + EXPECT_TRUE(MessageEquals(message, kMessage3)); + + EXPECT_EQ(OK, node0.node().ClosePort(a)); + EXPECT_EQ(OK, node1.node().ClosePort(b)); +} + +TEST_F(PortsTest, SlotsStrictOrdering) { + TestNode node0(0); + AddNode(&node0); + + TestNode node1(1); + AddNode(&node1); + + PortRef a, b; + EXPECT_EQ(OK, node0.node().CreateUninitializedPort(&a)); + EXPECT_EQ(OK, node1.node().CreateUninitializedPort(&b)); + EXPECT_EQ(OK, node0.node().InitializePort(a, node1.name(), b.name())); + EXPECT_EQ(OK, node1.node().InitializePort(b, node0.name(), a.name())); + + SlotId slot_id1 = node0.node().AllocateSlot(a); + ASSERT_TRUE(node1.node().AddSlotFromPeer(b, slot_id1)); + SlotId slot_id2 = node0.node().AllocateSlot(a); + ASSERT_TRUE(node1.node().AddSlotFromPeer(b, slot_id2)); + + const char* kMessage1 = "hey"; + EXPECT_EQ(OK, node0.SendStringMessage(a, kMessage1)); + + const char* kMessage2 = "hey again"; + EXPECT_EQ(OK, node0.SendStringMessage(SlotRef(a, slot_id1), kMessage2)); + + const char* kMessage3 = "hey one more time"; + EXPECT_EQ(OK, node0.SendStringMessage(SlotRef(a, slot_id2), kMessage3)); + + const char* kMessage4 = "last hey"; + EXPECT_EQ(OK, node0.SendStringMessage(a, kMessage4)); + + WaitForIdle(); + + // Verify that we can only observe the received messages in precise order, + // despite spanning many slot endpoints. + ScopedMessage message; + EXPECT_FALSE(node1.ReadMessage(SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit), + &message)); + EXPECT_FALSE(node1.ReadMessage(SlotRef(b, slot_id2 | kPeerAllocatedSlotIdBit), + &message)); + ASSERT_TRUE(node1.ReadMessage(b, &message)); + EXPECT_TRUE(MessageEquals(message, kMessage1)); + + EXPECT_FALSE(node1.ReadMessage(b, &message)); + EXPECT_FALSE(node1.ReadMessage(SlotRef(b, slot_id2 | kPeerAllocatedSlotIdBit), + &message)); + ASSERT_TRUE(node1.ReadMessage(SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit), + &message)); + EXPECT_TRUE(MessageEquals(message, kMessage2)); + + EXPECT_FALSE(node1.ReadMessage(b, &message)); + EXPECT_FALSE(node1.ReadMessage(SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit), + &message)); + ASSERT_TRUE(node1.ReadMessage(SlotRef(b, slot_id2 | kPeerAllocatedSlotIdBit), + &message)); + EXPECT_TRUE(MessageEquals(message, kMessage3)); + + EXPECT_FALSE(node1.ReadMessage(SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit), + &message)); + EXPECT_FALSE(node1.ReadMessage(SlotRef(b, slot_id2 | kPeerAllocatedSlotIdBit), + &message)); + ASSERT_TRUE(node1.ReadMessage(b, &message)); + EXPECT_TRUE(MessageEquals(message, kMessage4)); + + EXPECT_EQ(OK, node0.node().ClosePort(a)); + EXPECT_EQ(OK, node1.node().ClosePort(b)); +} + +TEST_F(PortsTest, ClosedSlotDiscardsNewMessages) { + TestNode node0(0); + AddNode(&node0); + + TestNode node1(1); + AddNode(&node1); + + PortRef a, b; + EXPECT_EQ(OK, node0.node().CreateUninitializedPort(&a)); + EXPECT_EQ(OK, node1.node().CreateUninitializedPort(&b)); + EXPECT_EQ(OK, node0.node().InitializePort(a, node1.name(), b.name())); + EXPECT_EQ(OK, node1.node().InitializePort(b, node0.name(), a.name())); + + SlotId slot_id1 = node0.node().AllocateSlot(a); + ASSERT_TRUE(node1.node().AddSlotFromPeer(b, slot_id1)); + + const char* kMessage1 = "message 1"; + EXPECT_EQ(OK, node0.SendStringMessage(a, kMessage1)); + + node1.node().ClosePortSlot(SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit)); + + const char* kMessage2 = "message 2"; + EXPECT_EQ(OK, node0.SendStringMessage(SlotRef(a, slot_id1), kMessage2)); + + const char* kMessage3 = "message 3"; + EXPECT_EQ(OK, node0.SendStringMessage(a, kMessage3)); + + WaitForIdle(); + + ScopedMessage message; + ASSERT_TRUE(node1.ReadMessage(b, &message)); + EXPECT_TRUE(MessageEquals(message, kMessage1)); + + ASSERT_TRUE(node1.ReadMessage(b, &message)); + EXPECT_TRUE(MessageEquals(message, kMessage3)); + + EXPECT_EQ(OK, node0.node().ClosePort(a)); + EXPECT_EQ(OK, node1.node().ClosePort(b)); +} + +TEST_F(PortsTest, ClosedSlotDiscardsQueuedMessages) { + TestNode node0(0); + AddNode(&node0); + + TestNode node1(1); + AddNode(&node1); + + PortRef a, b; + EXPECT_EQ(OK, node0.node().CreateUninitializedPort(&a)); + EXPECT_EQ(OK, node1.node().CreateUninitializedPort(&b)); + EXPECT_EQ(OK, node0.node().InitializePort(a, node1.name(), b.name())); + EXPECT_EQ(OK, node1.node().InitializePort(b, node0.name(), a.name())); + + SlotId slot_id1 = node0.node().AllocateSlot(a); + ASSERT_TRUE(node1.node().AddSlotFromPeer(b, slot_id1)); + + const char* kMessage1 = "message 1"; + EXPECT_EQ(OK, node0.SendStringMessage(a, kMessage1)); + + const char* kMessage2 = "message 2"; + EXPECT_EQ(OK, node0.SendStringMessage(SlotRef(a, slot_id1), kMessage2)); + + const char* kMessage3 = "message 3"; + EXPECT_EQ(OK, node0.SendStringMessage(a, kMessage3)); + + WaitForIdle(); + + node1.node().ClosePortSlot(SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit)); + + ScopedMessage message; + ASSERT_TRUE(node1.ReadMessage(b, &message)); + EXPECT_TRUE(MessageEquals(message, kMessage1)); + + ASSERT_TRUE(node1.ReadMessage(b, &message)); + EXPECT_TRUE(MessageEquals(message, kMessage3)); + + EXPECT_EQ(OK, node0.node().ClosePort(a)); + EXPECT_EQ(OK, node1.node().ClosePort(b)); +} + +TEST_F(PortsTest, CanCloseDefaultSlot) { + TestNode node0(0); + AddNode(&node0); + + TestNode node1(1); + AddNode(&node1); + + PortRef a, b; + EXPECT_EQ(OK, node0.node().CreateUninitializedPort(&a)); + EXPECT_EQ(OK, node1.node().CreateUninitializedPort(&b)); + EXPECT_EQ(OK, node0.node().InitializePort(a, node1.name(), b.name())); + EXPECT_EQ(OK, node1.node().InitializePort(b, node0.name(), a.name())); + + SlotId slot_id1 = node0.node().AllocateSlot(a); + ASSERT_TRUE(node1.node().AddSlotFromPeer(b, slot_id1)); + + const char* kMessage1 = "message 1"; + EXPECT_EQ(OK, node0.SendStringMessage(a, kMessage1)); + + const char* kMessage2 = "message 2"; + EXPECT_EQ(OK, node0.SendStringMessage(SlotRef(a, slot_id1), kMessage2)); + + const char* kMessage3 = "message 3"; + EXPECT_EQ(OK, node0.SendStringMessage(a, kMessage3)); + + WaitForIdle(); + + node1.node().ClosePortSlot(SlotRef(b, kDefaultSlotId)); + + ScopedMessage message; + EXPECT_FALSE(node1.ReadMessage(b, &message)); + ASSERT_TRUE(node1.ReadMessage(SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit), + &message)); + EXPECT_TRUE(MessageEquals(message, kMessage2)); + EXPECT_FALSE(node1.ReadMessage(b, &message)); + + EXPECT_EQ(OK, node0.node().ClosePort(a)); + EXPECT_EQ(OK, node1.node().ClosePort(b)); +} + +TEST_F(PortsTest, ClosingAllSlotsClosesPort) { + TestNode node0(0); + AddNode(&node0); + + TestNode node1(1); + AddNode(&node1); + + PortRef a, b; + EXPECT_EQ(OK, node0.node().CreateUninitializedPort(&a)); + EXPECT_EQ(OK, node1.node().CreateUninitializedPort(&b)); + EXPECT_EQ(OK, node0.node().InitializePort(a, node1.name(), b.name())); + EXPECT_EQ(OK, node1.node().InitializePort(b, node0.name(), a.name())); + + SlotId slot_id1 = node0.node().AllocateSlot(a); + ASSERT_TRUE(node1.node().AddSlotFromPeer(b, slot_id1)); + + node0.node().ClosePortSlot(SlotRef(a, slot_id1)); + node0.node().ClosePortSlot(SlotRef(a, kDefaultSlotId)); + + node1.node().ClosePortSlot(SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit)); + node1.node().ClosePortSlot(SlotRef(b, kDefaultSlotId)); + + EXPECT_EQ(ERROR_PORT_UNKNOWN, node1.node().GetPort(a.name(), &a)); + EXPECT_EQ(ERROR_PORT_UNKNOWN, node1.node().GetPort(b.name(), &b)); +} + +TEST_F(PortsTest, SlotPeerClosureDetectedSequentially) { + // This test verifies that when a slot is closed its peer can still read + // messages up to the point in the sequence where closure occurred. + + TestNode node0(0); + AddNode(&node0); + + TestNode node1(1); + AddNode(&node1); + + PortRef a, b; + EXPECT_EQ(OK, node0.node().CreateUninitializedPort(&a)); + EXPECT_EQ(OK, node1.node().CreateUninitializedPort(&b)); + EXPECT_EQ(OK, node0.node().InitializePort(a, node1.name(), b.name())); + EXPECT_EQ(OK, node1.node().InitializePort(b, node0.name(), a.name())); + + SlotId slot_id1 = node0.node().AllocateSlot(a); + ASSERT_TRUE(node1.node().AddSlotFromPeer(b, slot_id1)); + + const char* kMessage1 = "message 1"; + EXPECT_EQ(OK, node0.SendStringMessage(a, kMessage1)); + + const char* kMessage2 = "message 2"; + EXPECT_EQ(OK, node0.SendStringMessage(SlotRef(a, slot_id1), kMessage2)); + + node0.node().ClosePortSlot(SlotRef(a, slot_id1)); + + const char* kMessage3 = "message 3"; + EXPECT_EQ(OK, node0.SendStringMessage(a, kMessage3)); + + WaitForIdle(); + + // |slot1_id|'s peer in |b| should still appear to be receiving messages + // despite |slot_id| being closed in |a|. This is because the system expects + // the slot in |b| to have at least one more message currently or imminently + // in queue. + SlotStatus status; + EXPECT_EQ(OK, node1.node().GetStatus( + SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit), &status)); + EXPECT_TRUE(status.peer_closed); + EXPECT_TRUE(status.receiving_messages); + EXPECT_FALSE(status.has_messages); + + // Sanity check the default slot's status while we're here too. + EXPECT_EQ(OK, node1.node().GetStatus(SlotRef(b, kDefaultSlotId), &status)); + EXPECT_FALSE(status.peer_closed); + EXPECT_TRUE(status.receiving_messages); + EXPECT_TRUE(status.has_messages); + + ScopedMessage message; + + EXPECT_FALSE(node1.ReadMessage(SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit), + &message)); + ASSERT_TRUE(node1.ReadMessage(b, &message)); + EXPECT_TRUE(MessageEquals(message, kMessage1)); + + // The queued message for this slot should now be readable. The peer still + // appears to be closed. + EXPECT_EQ(OK, node1.node().GetStatus( + SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit), &status)); + EXPECT_TRUE(status.peer_closed); + EXPECT_TRUE(status.receiving_messages); + EXPECT_TRUE(status.has_messages); + + EXPECT_FALSE(node1.ReadMessage(b, &message)); + ASSERT_TRUE(node1.ReadMessage(SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit), + &message)); + EXPECT_TRUE(MessageEquals(message, kMessage2)); + + // Now that the last message has been read from the slot, the slot should + // appear to no longer have or be receiving new messages. In conjunction with + // peer closure this implies the slot will never receive messages again. + EXPECT_EQ(OK, node1.node().GetStatus( + SlotRef(b, slot_id1 | kPeerAllocatedSlotIdBit), &status)); + EXPECT_TRUE(status.peer_closed); + EXPECT_FALSE(status.receiving_messages); + EXPECT_FALSE(status.has_messages); + + EXPECT_EQ(OK, node0.node().ClosePort(a)); + EXPECT_EQ(OK, node1.node().ClosePort(b)); +} + } // namespace test } // namespace ports } // namespace core
diff --git a/mojo/core/ports/slot_ref.cc b/mojo/core/ports/slot_ref.cc new file mode 100644 index 0000000..255db366 --- /dev/null +++ b/mojo/core/ports/slot_ref.cc
@@ -0,0 +1,28 @@ +// 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 "mojo/core/ports/slot_ref.h" + +namespace mojo { +namespace core { +namespace ports { + +SlotRef::SlotRef() = default; + +SlotRef::SlotRef(const PortRef& port, SlotId slot_id) + : port_(port), slot_id_(slot_id) {} + +SlotRef::~SlotRef() = default; + +SlotRef::SlotRef(const SlotRef&) = default; + +SlotRef::SlotRef(SlotRef&&) = default; + +SlotRef& SlotRef::operator=(const SlotRef&) = default; + +SlotRef& SlotRef::operator=(SlotRef&&) = default; + +} // namespace ports +} // namespace core +} // namespace mojo
diff --git a/mojo/core/ports/slot_ref.h b/mojo/core/ports/slot_ref.h new file mode 100644 index 0000000..4a17f98 --- /dev/null +++ b/mojo/core/ports/slot_ref.h
@@ -0,0 +1,43 @@ +// 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 MOJO_CORE_PORTS_SLOT_REF_H_ +#define MOJO_CORE_PORTS_SLOT_REF_H_ + +#include "base/component_export.h" +#include "mojo/core/ports/event.h" +#include "mojo/core/ports/port_ref.h" + +namespace mojo { +namespace core { +namespace ports { + +// A reference to a specific slot on a specific port. +class COMPONENT_EXPORT(MOJO_CORE_PORTS) SlotRef { + public: + SlotRef(); + SlotRef(const PortRef& port, SlotId slot_id); + ~SlotRef(); + + SlotRef(const SlotRef& other); + SlotRef(SlotRef&& other); + + SlotRef& operator=(const SlotRef& other); + SlotRef& operator=(SlotRef&& other); + + const PortRef& port() const { return port_; } + SlotId slot_id() const { return slot_id_; } + + bool is_valid() const { return port_.is_valid(); } + + private: + PortRef port_; + SlotId slot_id_; +}; + +} // namespace ports +} // namespace core +} // namespace mojo + +#endif // MOJO_CORE_PORTS_SLOT_REF_H_
diff --git a/net/base/port_util.cc b/net/base/port_util.cc index ea3e30b..f6ab41c8 100644 --- a/net/base/port_util.cc +++ b/net/base/port_util.cc
@@ -107,7 +107,7 @@ return port >= 0 && port < 1024; } -bool IsPortAllowedForScheme(int port, const std::string& url_scheme) { +bool IsPortAllowedForScheme(int port, base::StringPiece url_scheme) { // Reject invalid ports. if (!IsPortValid(port)) return false;
diff --git a/net/base/port_util.h b/net/base/port_util.h index d1cc5fe..72d4b39 100644 --- a/net/base/port_util.h +++ b/net/base/port_util.h
@@ -10,6 +10,7 @@ #include <string> #include "base/macros.h" +#include "base/strings/string_piece.h" #include "net/base/net_export.h" namespace net { @@ -25,7 +26,7 @@ // Checks if the port is allowed for the specified scheme. Ports set as allowed // with SetExplicitlyAllowedPorts() or by using ScopedPortException() will be // considered allowed for any scheme. -NET_EXPORT bool IsPortAllowedForScheme(int port, const std::string& url_scheme); +NET_EXPORT bool IsPortAllowedForScheme(int port, base::StringPiece url_scheme); // Returns the number of explicitly allowed ports; for testing. NET_EXPORT_PRIVATE size_t GetCountOfExplicitlyAllowedPorts();
diff --git a/net/disk_cache/blockfile/entry_impl.h b/net/disk_cache/blockfile/entry_impl.h index 867b24f2..616673e 100644 --- a/net/disk_cache/blockfile/entry_impl.h +++ b/net/disk_cache/blockfile/entry_impl.h
@@ -295,6 +295,9 @@ // Logs this entry to the internal trace buffer. void Log(const char* msg); + // |net_log_| should be early since some field destructors (at least + // ~SparseControl) can touch it. + net::NetLogWithSource net_log_; CacheEntryBlock entry_; // Key related information for this entry. CacheRankingsBlock node_; // Rankings related information for this entry. base::WeakPtr<BackendImpl> backend_; // Back pointer to the cache. @@ -309,8 +312,6 @@ bool dirty_; // True if we detected that this is a dirty entry. std::unique_ptr<SparseControl> sparse_; // Support for sparse entries. - net::NetLogWithSource net_log_; - DISALLOW_COPY_AND_ASSIGN(EntryImpl); };
diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc index 3bc8f26..2fe639b 100644 --- a/net/disk_cache/entry_unittest.cc +++ b/net/disk_cache/entry_unittest.cc
@@ -5208,6 +5208,36 @@ entry2->Close(); } +TEST_F(DiskCacheEntryTest, BlockFileSparsePendingAfterDtor) { + // Test of behavior of ~EntryImpl for sparse entry that runs after backend + // destruction. + // + // Hand-creating the backend for realistic shutdown behavior. + CleanupCacheDir(); + CreateBackend(disk_cache::kNone); + + disk_cache::Entry* entry = nullptr; + ASSERT_THAT(CreateEntry("key", &entry), IsOk()); + ASSERT_TRUE(entry != nullptr); + + const int kSize = 61184; + + scoped_refptr<net::IOBuffer> buf = base::MakeRefCounted<net::IOBuffer>(kSize); + CacheTestFillBuffer(buf->data(), kSize, false); + + // The write pattern here avoids the second write being handled by the + // buffering layer, making SparseControl have to deal with its asynchrony. + EXPECT_EQ(1, WriteSparseData(entry, 65535, buf.get(), 1)); + EXPECT_EQ(net::ERR_IO_PENDING, + entry->WriteSparseData(2560, buf.get(), kSize, base::DoNothing())); + entry->Close(); + cache_.reset(); + + // Create a new instance as a way of flushing the thread. + InitCache(); + FlushQueueForTest(); +} + class DiskCacheSimplePrefetchTest : public DiskCacheEntryTest { public: DiskCacheSimplePrefetchTest()
diff --git a/net/http/http_stream_factory_job.cc b/net/http/http_stream_factory_job.cc index 6932f03..2dcc8c3 100644 --- a/net/http/http_stream_factory_job.cc +++ b/net/http/http_stream_factory_job.cc
@@ -708,7 +708,7 @@ // Don't connect to restricted ports. if (!IsPortAllowedForScheme(destination_.port(), - request_info_.url.scheme())) { + request_info_.url.scheme_piece())) { return ERR_UNSAFE_PORT; }
diff --git a/net/nqe/network_quality_estimator_params.cc b/net/nqe/network_quality_estimator_params.cc index ca44e02..6b036c0 100644 --- a/net/nqe/network_quality_estimator_params.cc +++ b/net/nqe/network_quality_estimator_params.cc
@@ -501,7 +501,7 @@ GetStringValueForVariationParamWithDefaultValue( params_, "cap_ect_based_on_signal_strength", - "false") == "true"), + "true") != "false"), upper_bound_typical_kbps_multiplier_( GetDoubleValueForVariationParamWithDefaultValue( params_,
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index 1f445ccd..506b040 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -575,6 +575,7 @@ if (fresh_resolve_host_request_) { DCHECK(race_stale_dns_on_connection_); + dns_resolution_end_time_ = base::TimeTicks::Now(); if (rv != OK) { CloseStaleHostConnection(); resolve_host_request_ = std::move(fresh_resolve_host_request_);
diff --git a/net/socket/udp_socket_unittest.cc b/net/socket/udp_socket_unittest.cc index 94f59034..17f7d11 100644 --- a/net/socket/udp_socket_unittest.cc +++ b/net/socket/udp_socket_unittest.cc
@@ -682,7 +682,13 @@ #if !defined(OS_FUCHSIA) // TODO(https://crbug.com/900709): SO_REUSEPORT doesn't work on Fuchsia. -TEST_F(UDPSocketTest, SharedMulticastAddress) { +#if defined(OS_IOS) +// TODO(https://crbug.com/947115): failing on device on iOS 12.2. +#define MAYBE_SharedMulticastAddress DISABLED_SharedMulticastAddress +#else +#define MAYBE_SharedMulticastAddress SharedMulticastAddress +#endif +TEST_F(UDPSocketTest, MAYBE_SharedMulticastAddress) { const char kGroup[] = "224.0.0.251"; IPAddress group_ip;
diff --git a/net/url_request/ftp_protocol_handler.cc b/net/url_request/ftp_protocol_handler.cc index f8b4b56..9334ca7 100644 --- a/net/url_request/ftp_protocol_handler.cc +++ b/net/url_request/ftp_protocol_handler.cc
@@ -36,7 +36,7 @@ DCHECK_EQ("ftp", request->url().scheme()); if (!IsPortAllowedForScheme(request->url().EffectiveIntPort(), - request->url().scheme())) { + request->url().scheme_piece())) { return new URLRequestErrorJob(request, network_delegate, ERR_UNSAFE_PORT); }
diff --git a/remoting/signaling/BUILD.gn b/remoting/signaling/BUILD.gn index 971d7a9c..613a72e0 100644 --- a/remoting/signaling/BUILD.gn +++ b/remoting/signaling/BUILD.gn
@@ -90,6 +90,7 @@ cc_grpc_library("ftl_grpc_library") { sources = [ + "chromoting_message.proto", "ftl.proto", "ftl_services.proto", ]
diff --git a/remoting/signaling/chromoting_message.proto b/remoting/signaling/chromoting_message.proto new file mode 100644 index 0000000..de29884 --- /dev/null +++ b/remoting/signaling/chromoting_message.proto
@@ -0,0 +1,21 @@ +// 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.ftl; + +// Next Id: 2 +message ChromotingMessage { + oneof message { ChromotingXmppMessage xmpp = 1; } +} + +// Chromoting Legacy XMPP message. +// Next Id: 2 +message ChromotingXmppMessage { + // A serialized version of the IQ stanza. + optional string stanza = 1; +}
diff --git a/remoting/signaling/ftl.proto b/remoting/signaling/ftl.proto index 97b4755..9cbba67 100644 --- a/remoting/signaling/ftl.proto +++ b/remoting/signaling/ftl.proto
@@ -150,10 +150,6 @@ Id receiver_id = 2; } -message ChromotingMessage { - string message = 1; -} - // Requests and responses message GetICEServerRequest {
diff --git a/remoting/signaling/ftl_message_reception_channel.cc b/remoting/signaling/ftl_message_reception_channel.cc index ef436d0..e1a2237 100644 --- a/remoting/signaling/ftl_message_reception_channel.cc +++ b/remoting/signaling/ftl_message_reception_channel.cc
@@ -66,12 +66,15 @@ on_incoming_msg_ = on_incoming_msg; } -void FtlMessageReceptionChannel::StartReceivingMessages(DoneCallback on_done) { +void FtlMessageReceptionChannel::StartReceivingMessages( + base::OnceClosure on_ready, + DoneCallback on_closed) { + stream_closed_callbacks_.push_back(std::move(on_closed)); if (state_ == State::STARTED) { - std::move(on_done).Run(grpc::Status::OK); + std::move(on_ready).Run(); return; } - start_receiving_messages_callbacks_.push_back(std::move(on_done)); + stream_ready_callbacks_.push_back(std::move(on_ready)); if (state_ == State::STARTING) { return; } @@ -83,7 +86,7 @@ return; } StopReceivingMessagesInternal(); - RunStartReceivingMessagesCallbacks(grpc::Status::CANCELLED); + RunStreamClosedCallbacks(grpc::Status::CANCELLED); } const net::BackoffEntry& @@ -106,7 +109,7 @@ return; } StopReceivingMessagesInternal(); - RunStartReceivingMessagesCallbacks(status); + RunStreamClosedCallbacks(status); } void FtlMessageReceptionChannel::OnMessageReceived( @@ -123,7 +126,7 @@ break; case ftl::ReceiveMessagesResponse::BodyCase::kStartOfBatch: state_ = State::STARTED; - RunStartReceivingMessagesCallbacks(grpc::Status::OK); + RunStreamReadyCallbacks(); BeginStreamTimers(); break; case ftl::ReceiveMessagesResponse::BodyCase::kEndOfBatch: @@ -135,15 +138,25 @@ } } -void FtlMessageReceptionChannel::RunStartReceivingMessagesCallbacks( - const grpc::Status& status) { - if (start_receiving_messages_callbacks_.empty()) { +void FtlMessageReceptionChannel::RunStreamReadyCallbacks() { + if (stream_ready_callbacks_.empty()) { return; } - for (DoneCallback& callback : start_receiving_messages_callbacks_) { + for (base::OnceClosure& callback : stream_ready_callbacks_) { + std::move(callback).Run(); + } + stream_ready_callbacks_.clear(); +} + +void FtlMessageReceptionChannel::RunStreamClosedCallbacks( + const grpc::Status& status) { + if (stream_closed_callbacks_.empty()) { + return; + } + for (DoneCallback& callback : stream_closed_callbacks_) { std::move(callback).Run(status); } - start_receiving_messages_callbacks_.clear(); + stream_closed_callbacks_.clear(); } void FtlMessageReceptionChannel::RetryStartReceivingMessagesWithBackoff() {
diff --git a/remoting/signaling/ftl_message_reception_channel.h b/remoting/signaling/ftl_message_reception_channel.h index 37e2ed1..5c4731b9 100644 --- a/remoting/signaling/ftl_message_reception_channel.h +++ b/remoting/signaling/ftl_message_reception_channel.h
@@ -36,7 +36,8 @@ // MessageReceptionChannel implementations. void Initialize(const StreamOpener& stream_opener, const MessageCallback& on_incoming_msg) override; - void StartReceivingMessages(DoneCallback on_done) override; + void StartReceivingMessages(base::OnceClosure on_ready, + DoneCallback on_closed) override; void StopReceivingMessages() override; const net::BackoffEntry& GetReconnectRetryBackoffEntryForTesting() const; @@ -57,7 +58,8 @@ void OnReceiveMessagesStreamClosed(const grpc::Status& status); void OnMessageReceived(const ftl::ReceiveMessagesResponse& response); - void RunStartReceivingMessagesCallbacks(const grpc::Status& status); + void RunStreamReadyCallbacks(); + void RunStreamClosedCallbacks(const grpc::Status& status); void RetryStartReceivingMessagesWithBackoff(); void RetryStartReceivingMessages(); void StartReceivingMessagesInternal(); @@ -70,7 +72,8 @@ StreamOpener stream_opener_; MessageCallback on_incoming_msg_; std::unique_ptr<ScopedGrpcServerStream> receive_messages_stream_; - std::list<DoneCallback> start_receiving_messages_callbacks_; + std::list<base::OnceClosure> stream_ready_callbacks_; + std::list<DoneCallback> stream_closed_callbacks_; State state_ = State::STOPPED; net::BackoffEntry reconnect_retry_backoff_; base::OneShotTimer reconnect_retry_timer_;
diff --git a/remoting/signaling/ftl_message_reception_channel_unittest.cc b/remoting/signaling/ftl_message_reception_channel_unittest.cc index 63f32fb7..00bee86c 100644 --- a/remoting/signaling/ftl_message_reception_channel_unittest.cc +++ b/remoting/signaling/ftl_message_reception_channel_unittest.cc
@@ -64,11 +64,6 @@ return response; } -base::OnceCallback<void(const grpc::Status& status)> AssertOkCallback() { - return base::BindOnce( - [](const grpc::Status& status) { ASSERT_TRUE(status.ok()); }); -} - // Creates a gmock EXPECT_CALL action that: // 1. Creates a fake server stream and returns it as the start stream result // 2. Posts a task to call |on_stream_opened| at the end of current sequence @@ -97,6 +92,14 @@ return StartStream(on_stream_opened, nullptr); } +base::OnceClosure NotReachedClosure() { + return base::BindOnce([]() { NOTREACHED(); }); +} + +base::RepeatingCallback<void(const grpc::Status&)> NotReachedStatusCallback() { + return base::BindRepeating([](const grpc::Status&) { NOTREACHED(); }); +} + } // namespace class FtlMessageReceptionChannelTest : public testing::Test { @@ -148,8 +151,10 @@ channel_->StopReceivingMessages(); })); - channel_->StartReceivingMessages(test::CheckStatusThenQuitRunLoopCallback( - FROM_HERE, grpc::StatusCode::CANCELLED, &run_loop)); + channel_->StartReceivingMessages( + NotReachedClosure(), + test::CheckStatusThenQuitRunLoopCallback( + FROM_HERE, grpc::StatusCode::CANCELLED, &run_loop)); run_loop.Run(); } @@ -166,8 +171,10 @@ .Run(grpc::Status(grpc::StatusCode::UNAUTHENTICATED, "")); })); - channel_->StartReceivingMessages(test::CheckStatusThenQuitRunLoopCallback( - FROM_HERE, grpc::StatusCode::UNAUTHENTICATED, &run_loop)); + channel_->StartReceivingMessages( + NotReachedClosure(), + test::CheckStatusThenQuitRunLoopCallback( + FROM_HERE, grpc::StatusCode::UNAUTHENTICATED, &run_loop)); run_loop.Run(); } @@ -183,8 +190,8 @@ on_incoming_msg.Run(CreateStartOfBatchResponse()); })); - channel_->StartReceivingMessages(test::CheckStatusThenQuitRunLoopCallback( - FROM_HERE, grpc::StatusCode::OK, &run_loop)); + channel_->StartReceivingMessages(run_loop.QuitClosure(), + NotReachedStatusCallback()); run_loop.Run(); } @@ -227,8 +234,8 @@ ASSERT_EQ(0, GetRetryFailureCount()); })); - channel_->StartReceivingMessages(test::CheckStatusThenQuitRunLoopCallback( - FROM_HERE, grpc::StatusCode::OK, &run_loop)); + channel_->StartReceivingMessages(run_loop.QuitClosure(), + NotReachedStatusCallback()); run_loop.Run(); } @@ -237,15 +244,13 @@ TestStartReceivingMessages_MultipleCalls) { base::RunLoop run_loop; - base::MockCallback<FtlMessageReceptionChannel::DoneCallback> - start_receiving_messages_callback; + base::MockCallback<base::OnceClosure> stream_ready_callback; // Exits the run loop iff the callback is called three times with OK. - EXPECT_CALL(start_receiving_messages_callback, - Run(Property(&grpc::Status::error_code, grpc::StatusCode::OK))) + EXPECT_CALL(stream_ready_callback, Run()) .WillOnce(Return()) .WillOnce(Return()) - .WillOnce(Invoke([&](const grpc::Status& status) { run_loop.Quit(); })); + .WillOnce([&]() { run_loop.Quit(); }); EXPECT_CALL(mock_stream_opener_, Run(_, _)) .WillOnce(StartStream( @@ -254,9 +259,12 @@ on_incoming_msg.Run(CreateStartOfBatchResponse()); })); - channel_->StartReceivingMessages(start_receiving_messages_callback.Get()); - channel_->StartReceivingMessages(start_receiving_messages_callback.Get()); - channel_->StartReceivingMessages(start_receiving_messages_callback.Get()); + channel_->StartReceivingMessages(stream_ready_callback.Get(), + NotReachedStatusCallback()); + channel_->StartReceivingMessages(stream_ready_callback.Get(), + NotReachedStatusCallback()); + channel_->StartReceivingMessages(stream_ready_callback.Get(), + NotReachedStatusCallback()); run_loop.Run(); } @@ -297,7 +305,9 @@ std::move(on_channel_closed).Run(grpc::Status::OK); })); - channel_->StartReceivingMessages(AssertOkCallback()); + channel_->StartReceivingMessages( + base::DoNothing(), test::CheckStatusThenQuitRunLoopCallback( + FROM_HERE, grpc::StatusCode::OK, &run_loop)); run_loop.Run(); } @@ -338,7 +348,8 @@ run_loop.Quit(); })); - channel_->StartReceivingMessages(AssertOkCallback()); + channel_->StartReceivingMessages(base::DoNothing(), + NotReachedStatusCallback()); run_loop.Run(); } @@ -380,7 +391,8 @@ run_loop.Quit(); })); - channel_->StartReceivingMessages(AssertOkCallback()); + channel_->StartReceivingMessages(base::DoNothing(), + NotReachedStatusCallback()); run_loop.Run(); } @@ -426,7 +438,8 @@ scoped_task_environment_.FastForwardBy(time_until_retry); })); - channel_->StartReceivingMessages(AssertOkCallback()); + channel_->StartReceivingMessages(base::DoNothing(), + NotReachedStatusCallback()); run_loop.Run(); }
diff --git a/remoting/signaling/ftl_messaging_client.cc b/remoting/signaling/ftl_messaging_client.cc index da06bfc..249ab05 100644 --- a/remoting/signaling/ftl_messaging_client.cc +++ b/remoting/signaling/ftl_messaging_client.cc
@@ -84,7 +84,7 @@ void FtlMessagingClient::SendMessage( const std::string& destination, const std::string& destination_registration_id, - const std::string& message_text, + const ftl::ChromotingMessage& message, DoneCallback on_done) { ftl::InboxSendRequest request; *request.mutable_header() = FtlGrpcContext::CreateRequestHeader( @@ -93,10 +93,8 @@ // TODO(yuweih): See if we need to set requester_id *request.mutable_dest_id() = FtlGrpcContext::CreateIdFromString(destination); - ftl::ChromotingMessage crd_message; - crd_message.set_message(message_text); std::string serialized_message; - bool succeeded = crd_message.SerializeToString(&serialized_message); + bool succeeded = message.SerializeToString(&serialized_message); DCHECK(succeeded); request.mutable_message()->set_message(serialized_message); @@ -118,8 +116,10 @@ executor_->ExecuteRpc(std::move(grpc_request)); } -void FtlMessagingClient::StartReceivingMessages(DoneCallback on_done) { - reception_channel_->StartReceivingMessages(std::move(on_done)); +void FtlMessagingClient::StartReceivingMessages(base::OnceClosure on_ready, + DoneCallback on_closed) { + reception_channel_->StartReceivingMessages(std::move(on_ready), + std::move(on_closed)); } void FtlMessagingClient::StopReceivingMessages() { @@ -213,8 +213,7 @@ ftl::ChromotingMessage chromoting_message; chromoting_message.ParseFromString(message.message()); callback_list_.Notify(message.sender_id().id(), - message.sender_registration_id(), - chromoting_message.message()); + message.sender_registration_id(), chromoting_message); } void FtlMessagingClient::OnMessageReceived(const ftl::InboxMessage& message) {
diff --git a/remoting/signaling/ftl_messaging_client.h b/remoting/signaling/ftl_messaging_client.h index 1b175abe..e5d526a 100644 --- a/remoting/signaling/ftl_messaging_client.h +++ b/remoting/signaling/ftl_messaging_client.h
@@ -11,6 +11,7 @@ #include "base/callback_forward.h" #include "base/callback_list.h" #include "base/macros.h" +#include "remoting/signaling/chromoting_message.pb.h" #include "remoting/signaling/ftl_services.grpc.pb.h" namespace remoting { @@ -27,11 +28,12 @@ using MessageCallback = base::RepeatingCallback<void(const std::string& sender_id, const std::string& sender_registration_id, - const std::string& message)>; - using MessageCallbackSubscription = + const ftl::ChromotingMessage& message)>; + using MessageCallbackList = base::CallbackList<void(const std::string&, const std::string&, - const std::string&)>::Subscription; + const ftl::ChromotingMessage&)>; + using MessageCallbackSubscription = MessageCallbackList::Subscription; using DoneCallback = base::OnceCallback<void(const grpc::Status& status)>; // |token_getter| and |registration_manager| must outlive |this|. @@ -52,14 +54,17 @@ void PullMessages(DoneCallback on_done); void SendMessage(const std::string& destination, const std::string& destination_registration_id, - const std::string& message_text, + const ftl::ChromotingMessage& message, DoneCallback on_done); // Opens a stream to continuously receive new messages from the server and // calls the registered MessageCallback once a new message is received. - // |on_done| is called once the stream is successfully opened or failed to - // open due to an error. - void StartReceivingMessages(DoneCallback on_done); + // |on_ready| is called once the stream is successfully started. + // |on_closed| is called if the stream fails to start, in which case + // |on_ready| will not be called, or when the stream is closed or dropped, + // in which case it is called after |on_ready| is called. + void StartReceivingMessages(base::OnceClosure on_ready, + DoneCallback on_closed); // Stops the stream for continuously receiving new messages. void StopReceivingMessages(); @@ -102,9 +107,7 @@ RegistrationManager* registration_manager_; std::unique_ptr<Messaging::Stub> messaging_stub_; std::unique_ptr<MessageReceptionChannel> reception_channel_; - base::CallbackList< - void(const std::string&, const std::string&, const std::string&)> - callback_list_; + MessageCallbackList callback_list_; DISALLOW_COPY_AND_ASSIGN(FtlMessagingClient); };
diff --git a/remoting/signaling/ftl_messaging_client_unittest.cc b/remoting/signaling/ftl_messaging_client_unittest.cc index f51badfd..b6020591 100644 --- a/remoting/signaling/ftl_messaging_client_unittest.cc +++ b/remoting/signaling/ftl_messaging_client_unittest.cc
@@ -37,6 +37,7 @@ using ::testing::Invoke; using ::testing::Property; using ::testing::Return; +using ::testing::Truly; using PullMessagesResponder = test::GrpcServerResponder<ftl::PullMessagesResponse>; @@ -51,16 +52,21 @@ constexpr char kMessage1Text[] = "Message 1"; constexpr char kMessage2Text[] = "Message 2"; -ftl::InboxMessage CreateMessage(const std::string& message_id, - const std::string& message_text) { +ftl::ChromotingMessage CreateXmppMessage(const std::string& message_text) { + ftl::ChromotingMessage crd_message; + crd_message.mutable_xmpp()->set_stanza(message_text); + return crd_message; +} + +ftl::InboxMessage CreateInboxMessage(const std::string& message_id, + const std::string& message_text) { ftl::InboxMessage message; message.mutable_sender_id()->set_id(kFakeSenderId); message.mutable_receiver_id()->set_id(kFakeReceiverId); message.set_sender_registration_id(kFakeSenderRegId); message.set_message_type(ftl::InboxMessage_MessageType_CHROMOTING_MESSAGE); message.set_message_id(message_id); - ftl::ChromotingMessage crd_message; - crd_message.set_message(message_text); + ftl::ChromotingMessage crd_message = CreateXmppMessage(message_text); std::string serialized_message; bool succeeded = crd_message.SerializeToString(&serialized_message); EXPECT_TRUE(succeeded); @@ -73,7 +79,7 @@ message.message_type()); ftl::ChromotingMessage chromoting_message; chromoting_message.ParseFromString(message.message()); - return chromoting_message.message(); + return chromoting_message.xmpp().stanza(); } class MockMessageReceptionChannel : public MessageReceptionChannel { @@ -88,7 +94,7 @@ on_incoming_msg_ = on_incoming_msg; } - MOCK_METHOD1(StartReceivingMessages, void(DoneCallback)); + MOCK_METHOD2(StartReceivingMessages, void(base::OnceClosure, DoneCallback)); MOCK_METHOD0(StopReceivingMessages, void()); StreamOpener* stream_opener() { return &stream_opener_; } @@ -113,6 +119,12 @@ MOCK_CONST_METHOD0(GetFtlAuthToken, std::string()); }; +decltype(auto) StanzaTextMatches(const std::string& expected_stanza) { + return Truly([=](const ftl::ChromotingMessage& message) { + return expected_stanza == message.xmpp().stanza(); + }); +} + } // namespace class FtlMessagingClientTest : public testing::Test { @@ -222,10 +234,11 @@ TEST_F(FtlMessagingClientTest, TestPullMessages_ReturnsNoMessage) { base::RunLoop run_loop; - auto subscription = messaging_client_->RegisterMessageCallback( - base::BindRepeating([](const std::string& sender_id, - const std::string& sender_registration_id, - const std::string& message) { NOTREACHED(); })); + auto subscription = + messaging_client_->RegisterMessageCallback(base::BindRepeating( + [](const std::string& sender_id, + const std::string& sender_registration_id, + const ftl::ChromotingMessage& message) { NOTREACHED(); })); messaging_client_->PullMessages(test::CheckStatusThenQuitRunLoopCallback( FROM_HERE, grpc::StatusCode::OK, &run_loop)); ServerWaitAndRespondToPullMessagesRequest(ftl::PullMessagesResponse(), @@ -235,10 +248,11 @@ TEST_F(FtlMessagingClientTest, TestPullMessages_Unauthenticated) { base::RunLoop run_loop; - auto subscription = messaging_client_->RegisterMessageCallback( - base::BindRepeating([](const std::string& sender_id, - const std::string& sender_registration_id, - const std::string& message) { NOTREACHED(); })); + auto subscription = + messaging_client_->RegisterMessageCallback(base::BindRepeating( + [](const std::string& sender_id, + const std::string& sender_registration_id, + const ftl::ChromotingMessage& message) { NOTREACHED(); })); messaging_client_->PullMessages(test::CheckStatusThenQuitRunLoopCallback( FROM_HERE, grpc::StatusCode::UNAUTHENTICATED, &run_loop)); ServerWaitAndRespondToPullMessagesRequest( @@ -250,10 +264,11 @@ TEST_F(FtlMessagingClientTest, TestPullMessages_IgnoresUnknownMessageType) { base::RunLoop run_loop; - auto subscription = messaging_client_->RegisterMessageCallback( - base::BindRepeating([](const std::string& sender_id, - const std::string& sender_registration_id, - const std::string& message) { NOTREACHED(); })); + auto subscription = + messaging_client_->RegisterMessageCallback(base::BindRepeating( + [](const std::string& sender_id, + const std::string& sender_registration_id, + const ftl::ChromotingMessage& message) { NOTREACHED(); })); messaging_client_->PullMessages(test::CheckStatusThenQuitRunLoopCallback( FROM_HERE, grpc::StatusCode::OK, &run_loop)); @@ -281,11 +296,11 @@ base::MockCallback<FtlMessagingClient::MessageCallback> mock_on_incoming_msg; - EXPECT_CALL(mock_on_incoming_msg, - Run(kFakeSenderId, kFakeSenderRegId, kMessage1Text)) + EXPECT_CALL(mock_on_incoming_msg, Run(kFakeSenderId, kFakeSenderRegId, + StanzaTextMatches(kMessage1Text))) .WillOnce(Return()); - EXPECT_CALL(mock_on_incoming_msg, - Run(kFakeSenderId, kFakeSenderRegId, kMessage2Text)) + EXPECT_CALL(mock_on_incoming_msg, Run(kFakeSenderId, kFakeSenderRegId, + StanzaTextMatches(kMessage2Text))) .WillOnce(Return()); auto subscription = @@ -296,9 +311,9 @@ ftl::PullMessagesResponse pull_messages_response; ftl::InboxMessage* message = pull_messages_response.add_messages(); - *message = CreateMessage(kMessage1Id, kMessage1Text); + *message = CreateInboxMessage(kMessage1Id, kMessage1Text); message = pull_messages_response.add_messages(); - *message = CreateMessage(kMessage2Id, kMessage2Text); + *message = CreateInboxMessage(kMessage2Id, kMessage2Text); ServerWaitAndRespondToPullMessagesRequest(pull_messages_response, grpc::Status::OK); @@ -319,7 +334,7 @@ TEST_F(FtlMessagingClientTest, TestSendMessage_Unauthenticated) { base::RunLoop run_loop; messaging_client_->SendMessage( - kFakeReceiverId, kFakeSenderRegId, kMessage1Text, + kFakeReceiverId, kFakeSenderRegId, CreateXmppMessage(kMessage1Text), test::CheckStatusThenQuitRunLoopCallback( FROM_HERE, grpc::StatusCode::UNAUTHENTICATED, &run_loop)); ServerWaitAndRespondToInboxSendRequest( @@ -334,7 +349,7 @@ TEST_F(FtlMessagingClientTest, TestSendMessage_SendOneMessageWithoutRegId) { base::RunLoop run_loop; messaging_client_->SendMessage( - kFakeReceiverId, "", kMessage1Text, + kFakeReceiverId, "", CreateXmppMessage(kMessage1Text), test::CheckStatusThenQuitRunLoopCallback(FROM_HERE, grpc::StatusCode::OK, &run_loop)); ServerWaitAndRespondToInboxSendRequest( @@ -353,7 +368,7 @@ TEST_F(FtlMessagingClientTest, TestSendMessage_SendOneMessageWithRegId) { base::RunLoop run_loop; messaging_client_->SendMessage( - kFakeReceiverId, kFakeSenderRegId, kMessage1Text, + kFakeReceiverId, kFakeSenderRegId, CreateXmppMessage(kMessage1Text), test::CheckStatusThenQuitRunLoopCallback(FROM_HERE, grpc::StatusCode::OK, &run_loop)); ServerWaitAndRespondToInboxSendRequest( @@ -370,17 +385,22 @@ run_loop.Run(); } -TEST_F(FtlMessagingClientTest, - TestStartReceivingMessages_DoneCallbackForwarded) { +TEST_F(FtlMessagingClientTest, TestStartReceivingMessages_CallbacksForwarded) { base::RunLoop run_loop; - EXPECT_CALL(*mock_message_reception_channel_, StartReceivingMessages(_)) - .WillOnce(Invoke([&](FtlMessagingClient::DoneCallback callback) { - std::move(callback).Run( + EXPECT_CALL(*mock_message_reception_channel_, StartReceivingMessages(_, _)) + .WillOnce(Invoke([&](base::OnceClosure on_ready, + FtlMessagingClient::DoneCallback on_closed) { + std::move(on_ready).Run(); + std::move(on_closed).Run( grpc::Status(grpc::StatusCode::UNAUTHENTICATED, "")); })); + base::MockCallback<base::OnceClosure> mock_on_ready_closure; + EXPECT_CALL(mock_on_ready_closure, Run()).WillOnce(Return()); + messaging_client_->StartReceivingMessages( + mock_on_ready_closure.Get(), base::BindLambdaForTesting([&](const grpc::Status& status) { ASSERT_EQ(grpc::StatusCode::UNAUTHENTICATED, status.error_code()); run_loop.Quit(); @@ -452,7 +472,7 @@ TestOnMessageReceived_MessagePassedToSubscriberAndAcked) { base::RunLoop run_loop; - ftl::InboxMessage message = CreateMessage(kMessage1Id, kMessage1Text); + ftl::InboxMessage message = CreateInboxMessage(kMessage1Id, kMessage1Text); mock_message_reception_channel_->on_incoming_msg()->Run(message); ServerWaitAndRespondToAckMessagesRequest(
diff --git a/remoting/signaling/message_reception_channel.h b/remoting/signaling/message_reception_channel.h index 910dcffc..962f8fe 100644 --- a/remoting/signaling/message_reception_channel.h +++ b/remoting/signaling/message_reception_channel.h
@@ -37,9 +37,13 @@ const MessageCallback& on_incoming_msg) = 0; // Opens a server streaming channel to the FTL API to enable message reception - // over the fast path. |on_done| is called to signal success or failure for - // starting the stream. - virtual void StartReceivingMessages(DoneCallback on_done) = 0; + // over the fast path. + // |on_ready| is called once the stream is successfully started. + // |on_closed| is called if the stream fails to start, in which case + // |on_ready| will not be called, or when the stream is closed or dropped, + // in which case it is called after |on_ready| is called. + virtual void StartReceivingMessages(base::OnceClosure on_ready, + DoneCallback on_closed) = 0; // Closes the streaming channel. virtual void StopReceivingMessages() = 0;
diff --git a/remoting/test/ftl_services_playground.cc b/remoting/test/ftl_services_playground.cc index 8bd7d337..da4da5f 100644 --- a/remoting/test/ftl_services_playground.cc +++ b/remoting/test/ftl_services_playground.cc
@@ -251,8 +251,10 @@ weak_factory_.GetWeakPtr(), receiver_id, registration_id, std::move(on_done)); + ftl::ChromotingMessage crd_message; + crd_message.mutable_xmpp()->set_stanza(message); messaging_client_->SendMessage( - receiver_id, registration_id, message, + receiver_id, registration_id, crd_message, base::BindOnce(&FtlServicesPlayground::OnSendMessageResponse, weak_factory_.GetWeakPtr(), std::move(on_continue))); } @@ -272,9 +274,12 @@ void FtlServicesPlayground::StartReceivingMessages(base::OnceClosure on_done) { VLOG(0) << "Running StartReceivingMessages..."; + receive_messages_done_callback_ = std::move(on_done); messaging_client_->StartReceivingMessages( - base::BindOnce(&FtlServicesPlayground::OnStartReceivingMessagesDone, - weak_factory_.GetWeakPtr(), std::move(on_done))); + base::BindOnce(&FtlServicesPlayground::OnReceiveMessagesStreamReady, + weak_factory_.GetWeakPtr()), + base::BindOnce(&FtlServicesPlayground::OnReceiveMessagesStreamClosed, + weak_factory_.GetWeakPtr())); } void FtlServicesPlayground::StopReceivingMessages(base::OnceClosure on_done) { @@ -285,32 +290,48 @@ void FtlServicesPlayground::OnMessageReceived( const std::string& sender_id, const std::string& sender_registration_id, - const std::string& message) { + const ftl::ChromotingMessage& message) { + std::string message_text = message.xmpp().stanza(); printf( "Received message:\n" " Sender ID=%s\n" " Sender Registration ID=%s\n" " Message=%s\n", - sender_id.c_str(), sender_registration_id.c_str(), message.c_str()); + sender_id.c_str(), sender_registration_id.c_str(), message_text.c_str()); } -void FtlServicesPlayground::OnStartReceivingMessagesDone( - base::OnceClosure on_done, +void FtlServicesPlayground::OnReceiveMessagesStreamReady() { + printf("Started receiving messages. Press enter to stop streaming...\n"); + test::WaitForEnterKey(base::BindOnce( + &FtlServicesPlayground::StopReceivingMessages, weak_factory_.GetWeakPtr(), + std::move(receive_messages_done_callback_))); +} + +void FtlServicesPlayground::OnReceiveMessagesStreamClosed( const grpc::Status& status) { + base::OnceClosure callback = std::move(receive_messages_done_callback_); + bool is_callback_null = callback.is_null(); + if (is_callback_null) { + callback = base::DoNothing::Once(); + } if (status.error_code() == grpc::StatusCode::CANCELLED) { printf("ReceiveMessages stream canceled by client.\n"); - std::move(on_done).Run(); + std::move(callback).Run(); return; } if (!status.ok()) { - HandleGrpcStatusError(std::move(on_done), status); - return; + HandleGrpcStatusError(std::move(callback), status); + } else { + printf("Stream closed by server.\n"); + std::move(callback).Run(); } - printf("Started receiving messages. Press enter to stop streaming...\n"); - test::WaitForEnterKey( - base::BindOnce(&FtlServicesPlayground::StopReceivingMessages, - weak_factory_.GetWeakPtr(), std::move(on_done))); + + if (is_callback_null) { + // Stream had been started and callback has been passed to wait for the + // enter key. + printf("Please press enter to continue...\n"); + } } void FtlServicesPlayground::HandleGrpcStatusError(base::OnceClosure on_done,
diff --git a/remoting/test/ftl_services_playground.h b/remoting/test/ftl_services_playground.h index 563d615..8b10970 100644 --- a/remoting/test/ftl_services_playground.h +++ b/remoting/test/ftl_services_playground.h
@@ -66,9 +66,9 @@ void StopReceivingMessages(base::OnceClosure on_done); void OnMessageReceived(const std::string& sender_id, const std::string& sender_registration_id, - const std::string& message); - void OnStartReceivingMessagesDone(base::OnceClosure on_done, - const grpc::Status& status); + const ftl::ChromotingMessage& message); + void OnReceiveMessagesStreamReady(); + void OnReceiveMessagesStreamClosed(const grpc::Status& status); void HandleGrpcStatusError(base::OnceClosure on_done, const grpc::Status& status); @@ -86,6 +86,8 @@ std::unique_ptr<PeerToPeer::Stub> peer_to_peer_stub_; + base::OnceClosure receive_messages_done_callback_; + base::WeakPtrFactory<FtlServicesPlayground> weak_factory_; DISALLOW_COPY_AND_ASSIGN(FtlServicesPlayground); };
diff --git a/services/tracing/BUILD.gn b/services/tracing/BUILD.gn index fde436c..f03baab 100644 --- a/services/tracing/BUILD.gn +++ b/services/tracing/BUILD.gn
@@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/chromecast_build.gni") - # There should be only one tracing service. It is currently # in the browser process. So, only //content/browser should link to this target. # Others modules should only need the public targets. @@ -45,10 +43,6 @@ deps = [ "//third_party/perfetto/protos/perfetto/trace/chrome:minimal_complete_lite", ] - - if (is_chromecast) { - defines = [ "IS_CHROMECAST" ] - } } source_set("manifest") { @@ -123,8 +117,4 @@ "//third_party/perfetto/protos/perfetto/trace/track_event:lite", ] } - - if (is_chromecast) { - defines = [ "IS_CHROMECAST" ] - } }
diff --git a/services/tracing/perfetto/consumer_host.cc b/services/tracing/perfetto/consumer_host.cc index e72cfe8..1726aee 100644 --- a/services/tracing/perfetto/consumer_host.cc +++ b/services/tracing/perfetto/consumer_host.cc
@@ -4,6 +4,7 @@ #include "services/tracing/perfetto/consumer_host.h" +#include <algorithm> #include <cstring> #include <string> #include <tuple> @@ -18,16 +19,21 @@ #include "build/build_config.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/system/wait.h" +#include "services/tracing/perfetto/json_trace_exporter.h" #include "services/tracing/perfetto/perfetto_service.h" +#include "services/tracing/perfetto/track_event_json_exporter.h" #include "third_party/perfetto/include/perfetto/tracing/core/observable_events.h" #include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h" #include "third_party/perfetto/include/perfetto/tracing/core/trace_packet.h" +#include "third_party/perfetto/include/perfetto/tracing/core/trace_stats.h" #include "third_party/perfetto/protos/perfetto/config/trace_config.pb.h" namespace tracing { namespace { +const int32_t kEnableTracingTimeoutSeconds = 10; + bool StringToProcessId(const std::string& input, base::ProcessId* output) { // Pid is encoded as uint in the string. return base::StringToUint(input, reinterpret_cast<uint32_t*>(output)); @@ -84,8 +90,10 @@ tracing_session_ = std::move(tracing_session); + perfetto::TraceConfig trace_config_copy = AdjustTraceConfig(trace_config); + filtered_pids_.clear(); - for (const auto& ds_config : trace_config.data_sources()) { + for (const auto& ds_config : trace_config_copy.data_sources()) { if (ds_config.config().name() == mojom::kTraceEventDataSourceName) { for (const auto& filter : ds_config.producer_name_filter()) { base::ProcessId pid; @@ -101,8 +109,35 @@ base::EraseIf(*pending_enable_tracing_ack_pids_, [this](base::ProcessId pid) { return !IsExpectedPid(pid); }); - consumer_endpoint_->EnableTracing(trace_config); + consumer_endpoint_->EnableTracing(trace_config_copy); MaybeSendEnableTracingAck(); + + if (pending_enable_tracing_ack_pids_) { + // We can't know for sure whether all processes we request to connect to the + // tracing service will connect back, or if all the connected services will + // ACK our EnableTracing request eventually, so we'll add a timeout for that + // case. + enable_tracing_ack_timer_.Start( + FROM_HERE, base::TimeDelta::FromSeconds(kEnableTracingTimeoutSeconds), + this, &ConsumerHost::OnEnableTracingTimeout); + } +} + +void ConsumerHost::ChangeTraceConfig( + const perfetto::TraceConfig& trace_config) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + perfetto::TraceConfig trace_config_copy = AdjustTraceConfig(trace_config); + consumer_endpoint_->ChangeTraceConfig(trace_config_copy); +} + +perfetto::TraceConfig ConsumerHost::AdjustTraceConfig( + const perfetto::TraceConfig& trace_config) { + perfetto::TraceConfig trace_config_copy(trace_config); + // Clock snapshotting is incompatible with chrome's process sandboxing. + // Telemetry uses its own way of snapshotting clocks anyway. + trace_config_copy.set_disable_clock_snapshotting(true); + return trace_config_copy; } void ConsumerHost::DisableTracing() { @@ -135,11 +170,44 @@ consumer_endpoint_->ReadBuffers(); } +void ConsumerHost::DisableTracingAndEmitJson( + const std::string& agent_label_filter, + mojo::ScopedDataPipeProducerHandle stream, + DisableTracingAndEmitJsonCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!read_buffers_stream_ && !read_buffers_callback_ && + !json_trace_exporter_); + + read_buffers_stream_ = std::move(stream); + read_buffers_callback_ = std::move(callback); + + // TODO(eseckler): Support argument/metadata filtering. + json_trace_exporter_ = std::make_unique<TrackEventJSONExporter>( + JSONTraceExporter::ArgumentFilterPredicate(), + JSONTraceExporter::MetadataFilterPredicate(), + base::BindRepeating(&ConsumerHost::OnJSONTraceData, + base::Unretained(this))); + + json_trace_exporter_->set_label_filter(agent_label_filter); + + consumer_endpoint_->DisableTracing(); +} + void ConsumerHost::FreeBuffers() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); consumer_endpoint_->FreeBuffers(); } +void ConsumerHost::RequestBufferUsage(RequestBufferUsageCallback callback) { + if (!request_buffer_usage_callback_.is_null()) { + std::move(callback).Run(false, 0); + return; + } + + request_buffer_usage_callback_ = std::move(callback); + consumer_endpoint_->GetTraceStats(); +} + void ConsumerHost::OnConnect() {} void ConsumerHost::OnDisconnect() {} @@ -147,13 +215,30 @@ void ConsumerHost::OnTracingDisabled() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(tracing_session_); + + if (enable_tracing_ack_timer_.IsRunning()) { + enable_tracing_ack_timer_.FireNow(); + } + DCHECK(!pending_enable_tracing_ack_pids_); + tracing_session_.reset(); - pending_enable_tracing_ack_pids_.reset(); + + if (json_trace_exporter_) { + consumer_endpoint_->ReadBuffers(); + } } void ConsumerHost::OnTraceData(std::vector<perfetto::TracePacket> packets, bool has_more) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (json_trace_exporter_) { + json_trace_exporter_->OnTraceData(std::move(packets), has_more); + if (!has_more) { + json_trace_exporter_.reset(); + } + return; + } + for (auto& packet : packets) { char* data; size_t size; @@ -222,6 +307,16 @@ MaybeSendEnableTracingAck(); } +void ConsumerHost::OnEnableTracingTimeout() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!pending_enable_tracing_ack_pids_) { + return; + } + DCHECK(tracing_session_); + tracing_session_->OnTracingEnabled(); + pending_enable_tracing_ack_pids_.reset(); +} + void ConsumerHost::MaybeSendEnableTracingAck() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!pending_enable_tracing_ack_pids_ || @@ -233,12 +328,50 @@ DCHECK(tracing_session_); tracing_session_->OnTracingEnabled(); pending_enable_tracing_ack_pids_.reset(); + enable_tracing_ack_timer_.Stop(); } bool ConsumerHost::IsExpectedPid(base::ProcessId pid) const { return filtered_pids_.empty() || base::ContainsKey(filtered_pids_, pid); } +void ConsumerHost::OnTraceStats(bool success, + const perfetto::TraceStats& stats) { + if (!request_buffer_usage_callback_) { + return; + } + + if (!success || stats.buffer_stats_size() != 1) { + std::move(request_buffer_usage_callback_).Run(false, 0.0f); + return; + } + + const perfetto::TraceStats::BufferStats& buf_stats = stats.buffer_stats()[0]; + size_t bytes_in_buffer = buf_stats.bytes_written() - buf_stats.bytes_read() - + buf_stats.bytes_overwritten() + + buf_stats.padding_bytes_written() - + buf_stats.padding_bytes_cleared(); + double percent_full = + bytes_in_buffer / static_cast<double>(buf_stats.buffer_size()); + percent_full = std::min(std::max(0.0, percent_full), 1.0); + std::move(request_buffer_usage_callback_).Run(true, percent_full); +} + +void ConsumerHost::OnJSONTraceData(const std::string& json, + base::DictionaryValue* metadata, + bool has_more) { + WriteToStream(json.data(), json.size()); + + if (has_more) { + return; + } + + read_buffers_stream_.reset(); + if (read_buffers_callback_) { + std::move(read_buffers_callback_).Run(); + } +} + void ConsumerHost::WriteToStream(const void* start, size_t size) { TRACE_EVENT0("ipc", "ConsumerHost::WriteToStream"); DCHECK(read_buffers_stream_.is_valid());
diff --git a/services/tracing/perfetto/consumer_host.h b/services/tracing/perfetto/consumer_host.h index 633cacc6..d88d8a8 100644 --- a/services/tracing/perfetto/consumer_host.h +++ b/services/tracing/perfetto/consumer_host.h
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" +#include "base/timer/timer.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/tracing/public/mojom/perfetto_service.mojom.h" #include "third_party/perfetto/include/perfetto/tracing/core/consumer.h" @@ -23,6 +24,7 @@ namespace tracing { +class JSONTraceExporter; class PerfettoService; // This is a Mojo interface which enables any client @@ -45,10 +47,16 @@ // mojom::ConsumerHost implementation. void EnableTracing(mojom::TracingSessionPtr tracing_session, const perfetto::TraceConfig& config) override; + void ChangeTraceConfig(const perfetto::TraceConfig& config) override; + void DisableTracing() override; void ReadBuffers(mojo::ScopedDataPipeProducerHandle stream, ReadBuffersCallback callback) override; + void DisableTracingAndEmitJson( + const std::string& agent_label_filter, + mojo::ScopedDataPipeProducerHandle stream, + DisableTracingAndEmitJsonCallback callback) override; + void RequestBufferUsage(RequestBufferUsageCallback callback) override; - void DisableTracing(); void Flush(uint32_t timeout, base::OnceCallback<void(bool)> callback); void FreeBuffers(); @@ -61,11 +69,11 @@ void OnTraceData(std::vector<perfetto::TracePacket> packets, bool has_more) override; void OnObservableEvents(const perfetto::ObservableEvents&) override; + void OnTraceStats(bool success, const perfetto::TraceStats&) override; // Unused in Chrome. void OnDetach(bool success) override {} void OnAttach(bool success, const perfetto::TraceConfig&) override {} - void OnTraceStats(bool success, const perfetto::TraceStats&) override {} // Called by TracingService. void OnActiveServicePidAdded(base::ProcessId pid); @@ -73,8 +81,14 @@ void OnActiveServicePidsInitialized(); private: + perfetto::TraceConfig AdjustTraceConfig( + const perfetto::TraceConfig& trace_config); + void OnEnableTracingTimeout(); void MaybeSendEnableTracingAck(); bool IsExpectedPid(base::ProcessId pid) const; + void OnJSONTraceData(const std::string& json, + base::DictionaryValue* metadata, + bool has_more); void WriteToStream(const void* start, size_t size); PerfettoService* const service_; @@ -86,6 +100,9 @@ // If set, we didn't issue OnTracingEnabled() on the session yet. If set and // empty, no more pids are pending and we should issue OnTracingEnabled(). base::Optional<std::set<base::ProcessId>> pending_enable_tracing_ack_pids_; + base::OneShotTimer enable_tracing_ack_timer_; + RequestBufferUsageCallback request_buffer_usage_callback_; + std::unique_ptr<JSONTraceExporter> json_trace_exporter_; SEQUENCE_CHECKER(sequence_checker_);
diff --git a/services/tracing/perfetto/perfetto_tracing_coordinator.cc b/services/tracing/perfetto/perfetto_tracing_coordinator.cc index 73afadb..591727e 100644 --- a/services/tracing/perfetto/perfetto_tracing_coordinator.cc +++ b/services/tracing/perfetto/perfetto_tracing_coordinator.cc
@@ -20,6 +20,7 @@ #include "services/tracing/perfetto/consumer_host.h" #include "services/tracing/perfetto/perfetto_service.h" #include "services/tracing/perfetto/track_event_json_exporter.h" +#include "services/tracing/public/cpp/perfetto/perfetto_config.h" #include "services/tracing/public/cpp/trace_event_args_whitelist.h" #include "services/tracing/public/mojom/constants.mojom.h" #include "services/tracing/public/mojom/perfetto_service.mojom.h" @@ -97,34 +98,11 @@ perfetto::TraceConfig CreatePerfettoConfiguration( const base::trace_event::TraceConfig& chrome_config) { - perfetto::TraceConfig perfetto_config; - size_t size_limit = chrome_config.GetTraceBufferSizeInKb(); - if (size_limit == 0) { - size_limit = 100 * 1024; - } - perfetto_config.add_buffers()->set_size_kb(size_limit); - - // Perfetto uses clock_gettime for its internal snapshotting, which gets - // blocked by the sandboxed and isn't needed for Chrome regardless. - perfetto_config.set_disable_clock_snapshotting(true); - - auto* trace_event_data_source = perfetto_config.add_data_sources(); - for (auto& enabled_pid : - chrome_config.process_filter_config().included_process_ids()) { - *trace_event_data_source->add_producer_name_filter() = base::StrCat( - {mojom::kPerfettoProducerNamePrefix, - base::NumberToString(static_cast<uint32_t>(enabled_pid))}); - } - - // We strip the process filter from the config string we send to Perfetto, - // so perfetto doesn't reject it from a future - // TracingService::ChangeTraceConfig call due to being an unsupported - // update. +#if DCHECK_IS_ON() base::trace_event::TraceConfig processfilter_stripped_config(chrome_config); processfilter_stripped_config.SetProcessFilterConfig( base::trace_event::TraceConfig::ProcessFilterConfig()); -#if DCHECK_IS_ON() // Ensure that the process filter is the only thing that gets changed // in a configuration during a tracing session. DCHECK((last_config_for_perfetto_.ToString() == @@ -134,40 +112,7 @@ last_config_for_perfetto_ = processfilter_stripped_config; #endif - auto* trace_event_config = trace_event_data_source->mutable_config(); - trace_event_config->set_name(mojom::kTraceEventDataSourceName); - trace_event_config->set_target_buffer(0); - auto* chrome_proto_config = trace_event_config->mutable_chrome_config(); - chrome_proto_config->set_trace_config( - processfilter_stripped_config.ToString()); - -// Only CrOS and Cast support system tracing. -#if defined(OS_CHROMEOS) || (defined(IS_CHROMECAST) && defined(OS_LINUX)) - auto* system_trace_config = - perfetto_config.add_data_sources()->mutable_config(); - system_trace_config->set_name(mojom::kSystemTraceDataSourceName); - system_trace_config->set_target_buffer(0); - auto* system_chrome_config = system_trace_config->mutable_chrome_config(); - system_chrome_config->set_trace_config( - processfilter_stripped_config.ToString()); -#endif - -#if defined(OS_CHROMEOS) - auto* arc_trace_config = - perfetto_config.add_data_sources()->mutable_config(); - arc_trace_config->set_name(mojom::kArcTraceDataSourceName); - arc_trace_config->set_target_buffer(0); - auto* arc_chrome_config = arc_trace_config->mutable_chrome_config(); - arc_chrome_config->set_trace_config( - processfilter_stripped_config.ToString()); -#endif - - auto* trace_metadata_config = - perfetto_config.add_data_sources()->mutable_config(); - trace_metadata_config->set_name(mojom::kMetaDataSourceName); - trace_metadata_config->set_target_buffer(0); - - return perfetto_config; + return GetDefaultPerfettoConfig(chrome_config); } void StopAndFlush(mojo::ScopedDataPipeProducerHandle stream,
diff --git a/services/tracing/public/cpp/BUILD.gn b/services/tracing/public/cpp/BUILD.gn index a5bd532..30942414 100644 --- a/services/tracing/public/cpp/BUILD.gn +++ b/services/tracing/public/cpp/BUILD.gn
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromecast_build.gni") + source_set("traced_process") { sources = [ "traced_process.cc", @@ -25,6 +27,8 @@ "base_agent.cc", "base_agent.h", "perfetto/interning_index.h", + "perfetto/perfetto_config.cc", + "perfetto/perfetto_config.h", "perfetto/producer_client.cc", "perfetto/producer_client.h", "perfetto/shared_memory.cc", @@ -68,5 +72,9 @@ "//third_party/perfetto/include/perfetto/protozero:protozero", "//third_party/perfetto/protos/perfetto/trace/chrome:minimal_complete_lite", ] + + if (is_chromecast) { + defines += [ "IS_CHROMECAST" ] + } } } # !is_nacl && !is_ios
diff --git a/services/tracing/public/cpp/perfetto/perfetto_config.cc b/services/tracing/public/cpp/perfetto/perfetto_config.cc new file mode 100644 index 0000000..2d73c53 --- /dev/null +++ b/services/tracing/public/cpp/perfetto/perfetto_config.cc
@@ -0,0 +1,83 @@ +// 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 "services/tracing/public/cpp/perfetto/perfetto_config.h" + +#include <cstdint> + +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" +#include "base/trace_event/trace_config.h" +#include "build/build_config.h" +#include "services/tracing/public/mojom/perfetto_service.mojom.h" + +namespace tracing { + +perfetto::TraceConfig GetDefaultPerfettoConfig( + const base::trace_event::TraceConfig& chrome_config) { + perfetto::TraceConfig perfetto_config; + + size_t size_limit = chrome_config.GetTraceBufferSizeInKb(); + if (size_limit == 0) { + size_limit = 100 * 1024; + } + perfetto_config.add_buffers()->set_size_kb(size_limit); + + // Perfetto uses clock_gettime for its internal snapshotting, which gets + // blocked by the sandboxed and isn't needed for Chrome regardless. + perfetto_config.set_disable_clock_snapshotting(true); + + // Capture actual trace events. + auto* trace_event_data_source = perfetto_config.add_data_sources(); + for (auto& enabled_pid : + chrome_config.process_filter_config().included_process_ids()) { + *trace_event_data_source->add_producer_name_filter() = base::StrCat( + {mojom::kPerfettoProducerNamePrefix, + base::NumberToString(static_cast<uint32_t>(enabled_pid))}); + } + + // We strip the process filter from the config string we send to Perfetto, + // so perfetto doesn't reject it from a future + // TracingService::ChangeTraceConfig call due to being an unsupported + // update. + base::trace_event::TraceConfig processfilter_stripped_config(chrome_config); + processfilter_stripped_config.SetProcessFilterConfig( + base::trace_event::TraceConfig::ProcessFilterConfig()); + std::string chrome_config_string = processfilter_stripped_config.ToString(); + + auto* trace_event_config = trace_event_data_source->mutable_config(); + trace_event_config->set_name(tracing::mojom::kTraceEventDataSourceName); + trace_event_config->set_target_buffer(0); + auto* chrome_proto_config = trace_event_config->mutable_chrome_config(); + chrome_proto_config->set_trace_config(chrome_config_string); + +// Capture system trace events if supported and enabled. The datasources will +// only emit events if system tracing is enabled in |chrome_config|. +#if defined(OS_CHROMEOS) || (defined(IS_CHROMECAST) && defined(OS_LINUX)) + auto* system_trace_config = + perfetto_config.add_data_sources()->mutable_config(); + system_trace_config->set_name(tracing::mojom::kSystemTraceDataSourceName); + system_trace_config->set_target_buffer(0); + auto* system_chrome_config = system_trace_config->mutable_chrome_config(); + system_chrome_config->set_trace_config(chrome_config_string); +#endif + +#if defined(OS_CHROMEOS) + auto* arc_trace_config = perfetto_config.add_data_sources()->mutable_config(); + arc_trace_config->set_name(tracing::mojom::kArcTraceDataSourceName); + arc_trace_config->set_target_buffer(0); + auto* arc_chrome_config = arc_trace_config->mutable_chrome_config(); + arc_chrome_config->set_trace_config(chrome_config_string); +#endif + + // Also capture global metadata. + auto* trace_metadata_config = + perfetto_config.add_data_sources()->mutable_config(); + trace_metadata_config->set_name(tracing::mojom::kMetaDataSourceName); + trace_metadata_config->set_target_buffer(0); + + return perfetto_config; +} + +} // namespace tracing
diff --git a/services/tracing/public/cpp/perfetto/perfetto_config.h b/services/tracing/public/cpp/perfetto/perfetto_config.h new file mode 100644 index 0000000..84fef0f --- /dev/null +++ b/services/tracing/public/cpp/perfetto/perfetto_config.h
@@ -0,0 +1,24 @@ +// 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 SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_CONFIG_H_ +#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_CONFIG_H_ + +#include "base/component_export.h" +#include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h" + +namespace base { +namespace trace_event { +class TraceConfig; +} // namespace trace_event +} // namespace base + +namespace tracing { + +perfetto::TraceConfig COMPONENT_EXPORT(TRACING_CPP) GetDefaultPerfettoConfig( + const base::trace_event::TraceConfig& chrome_config); + +} // namespace tracing + +#endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_CONFIG_H_
diff --git a/services/tracing/public/mojom/perfetto_service.mojom b/services/tracing/public/mojom/perfetto_service.mojom index a85ce30..97b707f 100644 --- a/services/tracing/public/mojom/perfetto_service.mojom +++ b/services/tracing/public/mojom/perfetto_service.mojom
@@ -146,6 +146,7 @@ struct DataSource { DataSourceConfig config; + array<string> producer_name_filter; }; // The configuration provided by a Consumer to the Perfetto service which @@ -165,12 +166,38 @@ // Enable Perfetto tracing with the given TracingSession interface for // signaling lifespan of the tracing session, and any future callbacks. EnableTracing(TracingSession tracing_session, TraceConfig config); + + // Update the trace config for the active tracing session. Currently, only + // (additive) updates to the |producer_name_filter| of a data source are + // supported. + ChangeTraceConfig(TraceConfig config); + + // Stop tracing for the active tracing session. The host will disconnect the + // TracingSession once tracing was disabled. Note that tracing may also stop + // without an explicit call to DisableTracing(), e.g. when a tracing duration + // is specified in the TraceConfig. + DisableTracing(); + // Tell Perfetto we're ready to receive data, over the given data pipe. // The result callback will be called when there's no more data currently // available. If the TracingSession is still active after the callback, // another call to ReadBuffers() needs to be made to receive any new // tracing data. ReadBuffers(handle<data_pipe_producer> stream) => (); + + // Disables tracing and converts the collected trace data converted into the + // legacy JSON format before returning it via the data pipe. If + // |agent_label_filter| is not empty, only data pertaining to the specified + // tracing agent label (e.g. "traceEvents") will be returned. + // + // DEPRECATED: Existing usecases only; new use cases of tracing should use the + // streaming proto format via ReadBuffers. + DisableTracingAndEmitJson(string agent_label_filter, + handle<data_pipe_producer> stream) => (); + + // Request current trace buffer usage of the active session. Will be returned + // as percentage value between 0.0f and 1.0f. + RequestBufferUsage() => (bool success, float percent_full); }; // Any client connecting to ConsumerHost should implement this
diff --git a/services/tracing/public/mojom/trace_config_mojom_traits.cc b/services/tracing/public/mojom/trace_config_mojom_traits.cc index 9c95a2eb..649fbe9 100644 --- a/services/tracing/public/mojom/trace_config_mojom_traits.cc +++ b/services/tracing/public/mojom/trace_config_mojom_traits.cc
@@ -31,6 +31,16 @@ } *out->mutable_config() = std::move(config); + + std::vector<std::string> producer_name_filter; + if (!data.ReadProducerNameFilter(&producer_name_filter)) { + return false; + } + + for (auto&& filter : producer_name_filter) { + *out->add_producer_name_filter() = std::move(filter); + } + return true; }
diff --git a/services/tracing/public/mojom/trace_config_mojom_traits.h b/services/tracing/public/mojom/trace_config_mojom_traits.h index 7606ac6..018d1bd 100644 --- a/services/tracing/public/mojom/trace_config_mojom_traits.h +++ b/services/tracing/public/mojom/trace_config_mojom_traits.h
@@ -40,6 +40,11 @@ return src.config(); } + static const std::vector<std::string>& producer_name_filter( + const perfetto::TraceConfig::DataSource& src) { + return src.producer_name_filter(); + } + static bool Read(tracing::mojom::DataSourceDataView data, perfetto::TraceConfig::DataSource* out); };
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 2244a16..9b0d13c 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -17716,11 +17716,23 @@ }, "test": "net_unittests" } + ], + "scripts": [ + { + "name": "sizes", + "script": "sizes.py" + } ] }, "android-cronet-arm-rel": { "additional_compile_targets": [ "cronet_package" + ], + "scripts": [ + { + "name": "sizes", + "script": "sizes.py" + } ] }, "android-cronet-arm64-dbg": { @@ -17734,6 +17746,12 @@ "cronet_tests_android", "cronet_unittests_android", "net_unittests" + ], + "scripts": [ + { + "name": "sizes", + "script": "sizes.py" + } ] }, "android-cronet-arm64-rel": { @@ -17747,6 +17765,12 @@ "cronet_tests_android", "cronet_unittests_android", "net_unittests" + ], + "scripts": [ + { + "name": "sizes", + "script": "sizes.py" + } ] }, "android-cronet-asan-arm-rel": { @@ -18683,6 +18707,12 @@ "cronet_tests_android", "cronet_unittests_android", "net_unittests" + ], + "scripts": [ + { + "name": "sizes", + "script": "sizes.py" + } ] }, "android-cronet-x86-rel": { @@ -18696,6 +18726,12 @@ "cronet_tests_android", "cronet_unittests_android", "net_unittests" + ], + "scripts": [ + { + "name": "sizes", + "script": "sizes.py" + } ] }, "android-incremental-dbg": {
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 213b240..6747b7d 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -1,2630 +1,6 @@ { "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, "AAAAA2 See generate_buildbot_json.py to make changes": {}, - "ANGLE GPU Linux Release (Intel HD 630)": { - "gtest_tests": [ - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "shards": 4 - }, - "test": "angle_end2end_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0", - "--no-xvfb" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "angle_unittests" - }, - { - "args": [ - "--test-launcher-retry-limit=0" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "angle_white_box_tests" - }, - { - "args": [ - "--enable-gpu", - "--test-launcher-bot-mode", - "--test-launcher-jobs=1", - "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*", - "--no-xvfb" - ], - "name": "tab_capture_end2end_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "browser_tests" - }, - { - "args": [ - "--enable-gpu", - "--test-launcher-bot-mode", - "--test-launcher-jobs=1", - "--test-launcher-filter-file=../../testing/buildbot/filters/vulkan.content_browsertests.filter", - "--enable-features=VizDisplayCompositor,UseSkiaRenderer,UiGpuRasterization", - "--use-gl=any", - "--enable-oop-rasterization", - "--enable-vulkan", - "--enable-gpu-rasterization", - "--enable-raster-to-sk-image", - "--force-gpu-rasterization", - "--disable-software-compositing-fallback", - "--no-xvfb" - ], - "name": "vulkan_content_browsertests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "content_browsertests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "shards": 4 - }, - "test": "dawn_end2end_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--use-cmd-decoder=validating" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gl_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--no-xvfb" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gl_unittests" - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gles2_conform_test" - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "swiftshader_unittests" - } - ], - "isolated_scripts": [ - { - "args": [ - "context_lost", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "context_lost_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "depth_capture", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "depth_capture_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "gpu_process", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "gpu_process_launch_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "hardware_accelerated_feature", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "hardware_accelerated_feature_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "info_collection", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--expected-vendor-id", - "8086", - "--expected-device-id", - "5912" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "info_collection_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "maps", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--os-type", - "linux", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "maps_pixel_test", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "pixel", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--refimg-cloud-storage-bucket", - "chromium-gpu-archive/reference-images", - "--os-type", - "linux", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}", - "--use-skia-gold" - ], - "experiment_percentage": 100, - "isolate_name": "telemetry_gpu_integration_test", - "name": "pixel_skia_gold_test", - "non_precommit_args": [ - "--upload-refimg-to-cloud-storage" - ], - "precommit_args": [ - "--download-refimg-from-cloud-storage", - "--review-patch-issue", - "${patch_issue}", - "--review-patch-set", - "${patch_set}", - "--buildbucket-build-id", - "${buildbucket_build_id}" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com" - } - }, - { - "args": [ - "pixel", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--refimg-cloud-storage-bucket", - "chromium-gpu-archive/reference-images", - "--os-type", - "linux", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "pixel_test", - "non_precommit_args": [ - "--upload-refimg-to-cloud-storage" - ], - "precommit_args": [ - "--download-refimg-from-cloud-storage" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "screenshot_sync", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "screenshot_sync_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "trace_test", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "trace_test", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough", - "--webgl-conformance-version=2.0.1", - "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl2_conformance_gl_passthrough_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "shards": 20 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--webgl-conformance-version=2.0.1", - "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl2_conformance_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "shards": 20 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_gl_passthrough_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "shards": 2 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "intel-hd-630-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "shards": 2 - } - } - ] - }, - "ANGLE GPU Linux Release (NVIDIA)": { - "gtest_tests": [ - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "shards": 4 - }, - "test": "angle_end2end_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0", - "--no-xvfb" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "angle_unittests" - }, - { - "args": [ - "--test-launcher-retry-limit=0" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "angle_white_box_tests" - }, - { - "args": [ - "--enable-gpu", - "--test-launcher-bot-mode", - "--test-launcher-jobs=1", - "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*", - "--no-xvfb" - ], - "name": "tab_capture_end2end_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "browser_tests" - }, - { - "args": [ - "--enable-gpu", - "--test-launcher-bot-mode", - "--test-launcher-jobs=1", - "--test-launcher-filter-file=../../testing/buildbot/filters/vulkan.content_browsertests.filter", - "--enable-features=VizDisplayCompositor,UseSkiaRenderer,UiGpuRasterization", - "--use-gl=any", - "--enable-oop-rasterization", - "--enable-vulkan", - "--enable-gpu-rasterization", - "--enable-raster-to-sk-image", - "--force-gpu-rasterization", - "--disable-software-compositing-fallback", - "--no-xvfb" - ], - "name": "vulkan_content_browsertests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "content_browsertests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "shards": 4 - }, - "test": "dawn_end2end_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--use-cmd-decoder=validating" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gl_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--no-xvfb" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gl_unittests" - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gles2_conform_test" - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - }, - "test": "swiftshader_unittests" - } - ], - "isolated_scripts": [ - { - "args": [ - "--gtest-benchmark-name=angle_perftests", - "-v", - "--one-frame-only" - ], - "isolate_name": "angle_perftests", - "merge": { - "args": [ - "--smoke-test-mode" - ], - "script": "//tools/perf/process_perf_results.py" - }, - "name": "angle_perftests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ] - } - }, - { - "args": [ - "context_lost", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "context_lost_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "depth_capture", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "depth_capture_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "gpu_process", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "gpu_process_launch_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "hardware_accelerated_feature", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "hardware_accelerated_feature_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "info_collection", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--expected-vendor-id", - "10de", - "--expected-device-id", - "1cb3" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "info_collection_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "maps", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--os-type", - "linux", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "maps_pixel_test", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "pixel", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--refimg-cloud-storage-bucket", - "chromium-gpu-archive/reference-images", - "--os-type", - "linux", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}", - "--use-skia-gold" - ], - "experiment_percentage": 100, - "isolate_name": "telemetry_gpu_integration_test", - "name": "pixel_skia_gold_test", - "non_precommit_args": [ - "--upload-refimg-to-cloud-storage" - ], - "precommit_args": [ - "--download-refimg-from-cloud-storage", - "--review-patch-issue", - "${patch_issue}", - "--review-patch-set", - "${patch_set}", - "--buildbucket-build-id", - "${buildbucket_build_id}" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com" - } - }, - { - "args": [ - "pixel", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--refimg-cloud-storage-bucket", - "chromium-gpu-archive/reference-images", - "--os-type", - "linux", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "pixel_test", - "non_precommit_args": [ - "--upload-refimg-to-cloud-storage" - ], - "precommit_args": [ - "--download-refimg-from-cloud-storage" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "screenshot_sync", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "screenshot_sync_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "trace_test", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "trace_test", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough", - "--webgl-conformance-version=2.0.1", - "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl2_conformance_gl_passthrough_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "shards": 20 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--webgl-conformance-version=2.0.1", - "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl2_conformance_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "shards": 20 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_gl_passthrough_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "shards": 2 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "nvidia-quadro-p400-ubuntu-stable", - "os": "Ubuntu", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "shards": 2 - } - } - ] - }, - "ANGLE GPU Mac Release (Intel)": { - "gtest_tests": [ - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], - "shards": 4 - }, - "test": "angle_end2end_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ] - }, - "test": "angle_unittests" - }, - { - "args": [ - "--enable-gpu", - "--test-launcher-bot-mode", - "--test-launcher-jobs=1", - "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" - ], - "name": "tab_capture_end2end_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ] - }, - "test": "browser_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], - "shards": 4 - }, - "test": "dawn_end2end_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--use-cmd-decoder=validating" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ] - }, - "test": "gl_tests" - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ] - }, - "test": "gl_unittests" - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ] - }, - "test": "gles2_conform_test" - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ] - }, - "test": "gpu_unittests" - }, - { - "args": [ - "--gtest_filter=*Detection*", - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ] - }, - "test": "services_unittests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ] - }, - "test": "swiftshader_unittests" - } - ], - "isolated_scripts": [ - { - "args": [ - "context_lost", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "context_lost_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], - "idempotent": false - } - }, - { - "args": [ - "depth_capture", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "depth_capture_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], - "idempotent": false - } - }, - { - "args": [ - "gpu_process", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "gpu_process_launch_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], - "idempotent": false - } - }, - { - "args": [ - "hardware_accelerated_feature", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "hardware_accelerated_feature_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], - "idempotent": false - } - }, - { - "args": [ - "info_collection", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--expected-vendor-id", - "8086", - "--expected-device-id", - "0a2e" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "info_collection_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], - "idempotent": false - } - }, - { - "args": [ - "maps", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--os-type", - "mac", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "maps_pixel_test", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], - "idempotent": false - } - }, - { - "args": [ - "pixel", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--refimg-cloud-storage-bucket", - "chromium-gpu-archive/reference-images", - "--os-type", - "mac", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "pixel_test", - "non_precommit_args": [ - "--upload-refimg-to-cloud-storage" - ], - "precommit_args": [ - "--download-refimg-from-cloud-storage" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], - "idempotent": false - } - }, - { - "args": [ - "screenshot_sync", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "screenshot_sync_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], - "idempotent": false - } - }, - { - "args": [ - "trace_test", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "trace_test", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], - "idempotent": false - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--webgl-conformance-version=2.0.1", - "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl2_conformance_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], - "idempotent": false, - "shards": 20 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], - "idempotent": false, - "shards": 2 - } - } - ] - }, - "ANGLE GPU Mac Retina Release (AMD)": { - "gtest_tests": [ - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "shards": 4 - }, - "test": "angle_end2end_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "angle_unittests" - }, - { - "args": [ - "--enable-gpu", - "--test-launcher-bot-mode", - "--test-launcher-jobs=1", - "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" - ], - "name": "tab_capture_end2end_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "browser_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "shards": 4 - }, - "test": "dawn_end2end_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--use-cmd-decoder=validating" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gl_tests" - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gl_unittests" - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gles2_conform_test" - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gpu_unittests" - }, - { - "args": [ - "--gtest_filter=*Detection*", - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "services_unittests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "swiftshader_unittests" - } - ], - "isolated_scripts": [ - { - "args": [ - "context_lost", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "context_lost_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "depth_capture", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "depth_capture_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "gpu_process", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "gpu_process_launch_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "hardware_accelerated_feature", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "hardware_accelerated_feature_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "info_collection", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--expected-vendor-id", - "1002", - "--expected-device-id", - "6821" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "info_collection_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "maps", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--os-type", - "mac", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "maps_pixel_test", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "pixel", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--refimg-cloud-storage-bucket", - "chromium-gpu-archive/reference-images", - "--os-type", - "mac", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "pixel_test", - "non_precommit_args": [ - "--upload-refimg-to-cloud-storage" - ], - "precommit_args": [ - "--download-refimg-from-cloud-storage" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "screenshot_sync", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "screenshot_sync_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "trace_test", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "trace_test", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--webgl-conformance-version=2.0.1", - "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl2_conformance_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "shards": 20 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "shards": 2 - } - } - ] - }, - "ANGLE GPU Mac Retina Release (NVIDIA)": { - "gtest_tests": [ - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "shards": 4 - }, - "test": "angle_end2end_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "angle_unittests" - }, - { - "args": [ - "--enable-gpu", - "--test-launcher-bot-mode", - "--test-launcher-jobs=1", - "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" - ], - "name": "tab_capture_end2end_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "browser_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "shards": 4 - }, - "test": "dawn_end2end_tests" - }, - { - "args": [ - "--use-gpu-in-tests", - "--use-cmd-decoder=validating" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gl_tests" - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gl_unittests" - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gles2_conform_test" - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "gpu_unittests" - }, - { - "args": [ - "--gtest_filter=*Detection*", - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "services_unittests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ] - }, - "test": "swiftshader_unittests" - } - ], - "isolated_scripts": [ - { - "args": [ - "context_lost", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "context_lost_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "depth_capture", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "depth_capture_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "gpu_process", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "gpu_process_launch_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "hardware_accelerated_feature", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "hardware_accelerated_feature_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "info_collection", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--expected-vendor-id", - "10de", - "--expected-device-id", - "0fe9" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "info_collection_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "maps", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--os-type", - "mac", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "maps_pixel_test", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "pixel", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--refimg-cloud-storage-bucket", - "chromium-gpu-archive/reference-images", - "--os-type", - "mac", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "pixel_test", - "non_precommit_args": [ - "--upload-refimg-to-cloud-storage" - ], - "precommit_args": [ - "--download-refimg-from-cloud-storage" - ], - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "screenshot_sync", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "screenshot_sync_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "trace_test", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "trace_test", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--webgl-conformance-version=2.0.1", - "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl2_conformance_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "shards": 20 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_tests", - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac-10.13.6", - "pool": "Chrome-GPU" - } - ], - "idempotent": false, - "shards": 2 - } - } - ] - }, "ANGLE GPU Win10 Release (Intel HD 630)": { "gtest_tests": [ {
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py index 0167c83..3f8549bb 100755 --- a/testing/buildbot/generate_buildbot_json.py +++ b/testing/buildbot/generate_buildbot_json.py
@@ -920,11 +920,6 @@ # are defined only to be mirrored into trybots, and don't actually # exist on any of the waterfalls or consoles. return [ - 'ANGLE GPU Linux Release (Intel HD 630)', - 'ANGLE GPU Linux Release (NVIDIA)', - 'ANGLE GPU Mac Release (Intel)', - 'ANGLE GPU Mac Retina Release (AMD)', - 'ANGLE GPU Mac Retina Release (NVIDIA)', 'ANGLE GPU Win10 Release (Intel HD 630)', 'ANGLE GPU Win10 Release (NVIDIA)', 'Dawn GPU Linux Release (Intel HD 630)',
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index e6e2ec3..35e7987 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -354,6 +354,7 @@ ], 'test_suites': { 'gtest_tests': 'cronet_gtests', + 'scripts': 'cronet_scripts', }, 'swarming': { 'dimension_sets': [ @@ -370,6 +371,9 @@ 'additional_compile_targets': [ 'cronet_package', ], + 'test_suites': { + 'scripts': 'cronet_scripts', + }, }, 'android-cronet-arm64-dbg': { 'additional_compile_targets': [ @@ -383,6 +387,9 @@ 'cronet_unittests_android', 'net_unittests', ], + 'test_suites': { + 'scripts': 'cronet_scripts', + }, }, 'android-cronet-arm64-rel': { 'additional_compile_targets': [ @@ -396,6 +403,9 @@ 'cronet_unittests_android', 'net_unittests', ], + 'test_suites': { + 'scripts': 'cronet_scripts', + }, }, 'android-cronet-asan-arm-rel': { 'additional_compile_targets': [ @@ -459,6 +469,9 @@ 'cronet_unittests_android', 'net_unittests', ], + 'test_suites': { + 'scripts': 'cronet_scripts', + }, }, 'android-cronet-x86-rel': { 'additional_compile_targets': [ @@ -472,6 +485,9 @@ 'cronet_unittests_android', 'net_unittests', ], + 'test_suites': { + 'scripts': 'cronet_scripts', + }, }, 'android-incremental-dbg': { 'test_suites': { @@ -2054,67 +2070,6 @@ 'name': 'chromium.gpu.fyi', 'machines': { # BEGIN Fake builder used as mirror targets for ANGLE's GPU tryservers - 'ANGLE GPU Linux Release (Intel HD 630)': { - 'os_type': 'linux', - 'browser_config': 'release', - 'mixins': [ - 'linux_intel_hd_630', - ], - 'test_suites': { - # TODO(jmadill): Use custom test lists. crbug.com/822310 - 'gtest_tests': 'gpu_fyi_linux_release_gtests', - 'gpu_telemetry_tests': 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests', - }, - }, - 'ANGLE GPU Linux Release (NVIDIA)': { - 'os_type': 'linux', - 'browser_config': 'release', - 'mixins': [ - 'linux_nvidia_quadro_p400', - ], - 'test_suites': { - # TODO(jmadill): Use custom test lists. crbug.com/822310 - 'gtest_tests': 'gpu_fyi_linux_release_gtests', - 'isolated_scripts': 'gpu_angle_perftests', - 'gpu_telemetry_tests': 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests', - }, - }, - 'ANGLE GPU Mac Release (Intel)': { - 'os_type': 'mac', - 'browser_config': 'release', - 'mixins': [ - 'mac_mini_intel_gpu', - ], - 'test_suites': { - # TODO(jmadill): Use custom test lists. crbug.com/822310 - 'gtest_tests': 'gpu_fyi_mac_release_gtests', - 'gpu_telemetry_tests': 'gpu_fyi_mac_release_telemetry_tests', - }, - }, - 'ANGLE GPU Mac Retina Release (AMD)': { - 'os_type': 'mac', - 'browser_config': 'release', - 'mixins': [ - 'mac_retina_amd_gpu', - ], - 'test_suites': { - # TODO(jmadill): Use custom test lists. crbug.com/822310 - 'gtest_tests': 'gpu_fyi_mac_release_gtests', - 'gpu_telemetry_tests': 'gpu_fyi_mac_release_telemetry_tests', - }, - }, - 'ANGLE GPU Mac Retina Release (NVIDIA)': { - 'os_type': 'mac', - 'browser_config': 'release', - 'mixins': [ - 'mac_retina_nvidia_gpu', - ], - 'test_suites': { - # TODO(jmadill): Use custom test lists. crbug.com/822310 - 'gtest_tests': 'gpu_fyi_mac_release_gtests', - 'gpu_telemetry_tests': 'gpu_fyi_mac_release_telemetry_tests', - }, - }, 'ANGLE GPU Win10 Release (Intel HD 630)': { 'os_type': 'win', 'browser_config': 'release',
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn index 88e5804e4..71447aef 100644 --- a/testing/libfuzzer/fuzzers/BUILD.gn +++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -401,7 +401,7 @@ "$target_gen_dir/javascript_parser.proto", ] proto_deps = [ ":gen_javascript_parser_proto" ] - proto_out_dir = target_gen_dir + proto_out_dir = "" } fuzzer_test("javascript_parser_proto_fuzzer") {
diff --git a/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc b/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc index 56f39a0..e38f88e 100644 --- a/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc +++ b/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc
@@ -6,7 +6,7 @@ #include <iostream> -#include "testing/libfuzzer/fuzzers/javascript_parser.pb.h" // from out/gen +#include "javascript_parser.pb.h" // from out/gen #include "testing/libfuzzer/fuzzers/javascript_parser_proto_to_string.h" #include "third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.h"
diff --git a/testing/libfuzzer/fuzzers/javascript_parser_proto_to_string.h b/testing/libfuzzer/fuzzers/javascript_parser_proto_to_string.h index d9e5a4c..285ed1a 100644 --- a/testing/libfuzzer/fuzzers/javascript_parser_proto_to_string.h +++ b/testing/libfuzzer/fuzzers/javascript_parser_proto_to_string.h
@@ -5,7 +5,7 @@ #ifndef TESTING_LIBFUZZER_FUZZERS_JAVASCRIPT_PARSER_PROTO_TO_STRING_H #define TESTING_LIBFUZZER_FUZZERS_JAVASCRIPT_PARSER_PROTO_TO_STRING_H -#include "testing/libfuzzer/fuzzers/javascript_parser.pb.h" // from out/gen +#include "javascript_parser.pb.h" // from out/gen #include <string>
diff --git a/testing/libfuzzer/proto/BUILD.gn b/testing/libfuzzer/proto/BUILD.gn index 40d3a9a..47747e3 100644 --- a/testing/libfuzzer/proto/BUILD.gn +++ b/testing/libfuzzer/proto/BUILD.gn
@@ -8,6 +8,10 @@ sources = [ "json.proto", ] + + # This way json.pb.h header goes into "$root_gen_dir" directory precisely, + # otherwise it goes into "$root_gen_dir" + "/testing/libfuzzer/proto/". + proto_out_dir = "" } source_set("json_proto_converter") { @@ -15,7 +19,6 @@ "json_proto_converter.cc", "json_proto_converter.h", ] - include_dirs = [ target_gen_dir ] deps = [ ":json_proto", ]
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index d28ea53..f2cfeb1 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1577,40 +1577,6 @@ ] } ], - "DataReductionProxyServerExperiments": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "OnDeviceSafeBrowsingFieldTrialEnabled", - "params": { - "exp": "disable_server_safebrowsing" - } - } - ] - } - ], - "DataSaverSiteBreakdownUsingPageLoadMetrics": [ - { - "platforms": [ - "android", - "windows", - "mac", - "chromeos", - "linux" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "DataSaverSiteBreakdownUsingPageLoadMetrics" - ] - } - ] - } - ], "DecoupleTranslateLanguage": [ { "platforms": [ @@ -2583,6 +2549,21 @@ ] } ], + "LazyLoad": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "LazyFrameLoading" + ] + } + ] + } + ], "LegacySymantecPKI": [ { "platforms": [ @@ -3044,28 +3025,6 @@ ] } ], - "NetworkQualityEstimator": [ - { - "platforms": [ - "android", - "windows", - "mac", - "chromeos", - "linux" - ], - "experiments": [ - { - "name": "Enabled9", - "params": { - "cap_ect_based_on_signal_strength": "true" - }, - "enable_features": [ - "NetworkQualityEstimator" - ] - } - ] - } - ], "NewExtensionUpdaterService": [ { "platforms": [
diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD.gn index 67567fe7c..7cb97e9 100644 --- a/third_party/android_deps/BUILD.gn +++ b/third_party/android_deps/BUILD.gn
@@ -599,7 +599,7 @@ # This is generated, do not edit. Update BuildConfigGenerator.groovy instead. android_aar_prebuilt("com_google_ar_core_java") { - aar_path = "libs/com_google_ar_core/core-1.6.0.aar" + aar_path = "libs/com_google_ar_core/core-1.8.0.aar" info_path = "libs/com_google_ar_core/com_google_ar_core.info" extract_native_libraries = true split_compat_class_names = [ "com/google/ar/core/InstallActivity" ]
diff --git a/third_party/android_deps/libs/com_google_ar_core/README.chromium b/third_party/android_deps/libs/com_google_ar_core/README.chromium index 19c09d0..253f7971 100644 --- a/third_party/android_deps/libs/com_google_ar_core/README.chromium +++ b/third_party/android_deps/libs/com_google_ar_core/README.chromium
@@ -1,7 +1,7 @@ Name: Short Name: core URL: https://github.com/google-ar/arcore-android-sdk -Version: 1.6.0 +Version: 1.8.0 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/android_deps/libs/com_google_ar_core/cipd.yaml b/third_party/android_deps/libs/com_google_ar_core/cipd.yaml index 2a888d1..f7f0f44 100644 --- a/third_party/android_deps/libs/com_google_ar_core/cipd.yaml +++ b/third_party/android_deps/libs/com_google_ar_core/cipd.yaml
@@ -3,8 +3,8 @@ # found in the LICENSE file. # To create CIPD package run the following command. -# cipd create --pkg-def cipd.yaml -tag version:1.6.0-cr0 +# cipd create --pkg-def cipd.yaml -tag version:1.8.0-cr0 package: chromium/third_party/android_deps/libs/com_google_ar_core description: "" data: -- file: core-1.6.0.aar +- file: core-1.8.0.aar
diff --git a/third_party/android_deps/libs/com_google_ar_core/com_google_ar_core.info b/third_party/android_deps/libs/com_google_ar_core/com_google_ar_core.info index c5073f5..88ab94a 100644 --- a/third_party/android_deps/libs/com_google_ar_core/com_google_ar_core.info +++ b/third_party/android_deps/libs/com_google_ar_core/com_google_ar_core.info
@@ -8,7 +8,7 @@ has_proguard_flags = true has_r_text_file = true is_manifest_empty = false -native_libraries = [ "jni/arm64-v8a/libarcore_sdk_c.so", "jni/arm64-v8a/libarcore_sdk_jni.so", "jni/armeabi-v7a/libarcore_sdk_c.so", "jni/armeabi-v7a/libarcore_sdk_jni.so", "jni/x86/libarcore_sdk_c.so", "jni/x86/libarcore_sdk_jni.so" ] +native_libraries = [ "jni/arm64-v8a/libarcore_sdk_c.so", "jni/arm64-v8a/libarcore_sdk_jni.so", "jni/armeabi-v7a/libarcore_sdk_c.so", "jni/armeabi-v7a/libarcore_sdk_jni.so", "jni/x86/libarcore_sdk_c.so", "jni/x86/libarcore_sdk_jni.so", "jni/x86_64/libarcore_sdk_c.so", "jni/x86_64/libarcore_sdk_jni.so" ] resources = [ "res/layout/__arcore_education.xml", "res/raw/keep.xml", "res/values-af/values.xml", "res/values-am/values.xml", "res/values-ar-rEG/values.xml", "res/values-ar-rSA/values.xml", "res/values-ar-rXB/values.xml", "res/values-az/values.xml", "res/values-b+es+419/values.xml", "res/values-b+sr+Latn/values.xml", "res/values-be/values.xml", "res/values-bg/values.xml", "res/values-bn/values.xml", "res/values-bs/values.xml", "res/values-ca/values.xml", "res/values-cs/values.xml", "res/values-da/values.xml", "res/values-de-rAT/values.xml", "res/values-de-rCH/values.xml", "res/values-de/values.xml", "res/values-el/values.xml", "res/values-en-rAU/values.xml", "res/values-en-rCA/values.xml", "res/values-en-rGB/values.xml", "res/values-en-rIE/values.xml", "res/values-en-rSG/values.xml", "res/values-en-rXA/values.xml", "res/values-en-rXC/values.xml", "res/values-en-rZA/values.xml", "res/values-es-rAR/values.xml", "res/values-es-rBO/values.xml", "res/values-es-rCL/values.xml", "res/values-es-rCO/values.xml", "res/values-es-rCR/values.xml", "res/values-es-rDO/values.xml", "res/values-es-rEC/values.xml", "res/values-es-rGT/values.xml", "res/values-es-rHN/values.xml", "res/values-es-rMX/values.xml", "res/values-es-rNI/values.xml", "res/values-es-rPA/values.xml", "res/values-es-rPE/values.xml", "res/values-es-rPR/values.xml", "res/values-es-rPY/values.xml", "res/values-es-rSV/values.xml", "res/values-es-rUS/values.xml", "res/values-es-rUY/values.xml", "res/values-es-rVE/values.xml", "res/values-es/values.xml", "res/values-et/values.xml", "res/values-eu/values.xml", "res/values-fa/values.xml", "res/values-fi/values.xml", "res/values-fil/values.xml", "res/values-fr-rCA/values.xml", "res/values-fr-rCH/values.xml", "res/values-fr/values.xml", "res/values-gl/values.xml", "res/values-gsw/values.xml", "res/values-gu/values.xml", "res/values-he/values.xml", "res/values-hi/values.xml", "res/values-hr/values.xml", "res/values-hu/values.xml", "res/values-hy/values.xml", "res/values-id/values.xml", "res/values-in/values.xml", "res/values-is/values.xml", "res/values-it/values.xml", "res/values-iw/values.xml", "res/values-ja/values.xml", "res/values-ka/values.xml", "res/values-kk/values.xml", "res/values-km/values.xml", "res/values-kn/values.xml", "res/values-ko/values.xml", "res/values-ky/values.xml", "res/values-lo/values.xml", "res/values-lt/values.xml", "res/values-lv/values.xml", "res/values-mk/values.xml", "res/values-ml/values.xml", "res/values-mn/values.xml", "res/values-mo/values.xml", "res/values-ms/values.xml", "res/values-my/values.xml", "res/values-nb/values.xml", "res/values-ne/values.xml", "res/values-nl/values.xml", "res/values-no/values.xml", "res/values-pa/values.xml", "res/values-pl/values.xml", "res/values-pt-rBR/values.xml", "res/values-pt-rPT/values.xml", "res/values-pt/values.xml", "res/values-ro/values.xml", "res/values-ru/values.xml", "res/values-si/values.xml", "res/values-sk/values.xml", "res/values-sl/values.xml", "res/values-sq/values.xml", "res/values-sr/values.xml", "res/values-sv/values.xml", "res/values-sw/values.xml", "res/values-ta/values.xml", "res/values-te/values.xml", "res/values-th/values.xml", "res/values-tl/values.xml", "res/values-tr/values.xml", "res/values-uk/values.xml", "res/values-ur/values.xml", "res/values-uz/values.xml", "res/values-vi/values.xml", "res/values-zh-rCN/values.xml", "res/values-zh-rHK/values.xml", "res/values-zh-rTW/values.xml", "res/values-zh/values.xml", "res/values-zu/values.xml", "res/values/values.xml" ] subjar_tuples = [ ] subjars = [ ]
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn index b85cbda..c9b5544a 100644 --- a/third_party/blink/public/BUILD.gn +++ b/third_party/blink/public/BUILD.gn
@@ -396,6 +396,7 @@ "web/modules/mediastream/media_stream_video_source.h", "web/modules/mediastream/media_stream_video_track.h", "web/modules/mediastream/video_track_adapter.h", + "web/modules/mediastream/video_track_adapter_settings.h", "web/modules/mediastream/web_media_stream_utils.h", "web/modules/service_worker/web_service_worker_context_client.h", "web/modules/service_worker/web_service_worker_context_proxy.h",
diff --git a/third_party/blink/public/platform/web_encrypted_media_request.h b/third_party/blink/public/platform/web_encrypted_media_request.h index d50f362d..270567e 100644 --- a/third_party/blink/public/platform/web_encrypted_media_request.h +++ b/third_party/blink/public/platform/web_encrypted_media_request.h
@@ -6,13 +6,15 @@ #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_ENCRYPTED_MEDIA_REQUEST_H_ #include "third_party/blink/public/platform/web_common.h" +#include "third_party/blink/public/platform/web_content_decryption_module_access.h" #include "third_party/blink/public/platform/web_private_ptr.h" #include "third_party/blink/public/platform/web_string.h" +#include <memory> + namespace blink { class EncryptedMediaRequest; -class WebContentDecryptionModuleAccess; struct WebMediaKeySystemConfiguration; class WebSecurityOrigin; template <typename T> @@ -31,7 +33,7 @@ BLINK_PLATFORM_EXPORT WebSecurityOrigin GetSecurityOrigin() const; BLINK_PLATFORM_EXPORT void RequestSucceeded( - WebContentDecryptionModuleAccess*); + std::unique_ptr<WebContentDecryptionModuleAccess>); BLINK_PLATFORM_EXPORT void RequestNotSupported( const WebString& error_message);
diff --git a/third_party/blink/public/platform/web_layer_tree_view.h b/third_party/blink/public/platform/web_layer_tree_view.h index 22e0fa9..93b851b 100644 --- a/third_party/blink/public/platform/web_layer_tree_view.h +++ b/third_party/blink/public/platform/web_layer_tree_view.h
@@ -41,10 +41,6 @@ #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkRefCnt.h" -namespace cc { -class PaintImage; -} - namespace blink { class WebLayerTreeView { @@ -139,14 +135,6 @@ virtual void NotifySwapTime(ReportTimeCallback callback) {} virtual void RequestBeginMainFrameNotExpected(bool new_state) {} - - virtual void RequestDecode(const cc::PaintImage& image, - base::OnceCallback<void(bool)> callback) {} - - // Runs |callback| after a new frame has been submitted to the display - // compositor, and the display-compositor has displayed it on screen. Forces a - // redraw so that a new frame is submitted. - virtual void RequestPresentationCallback(base::OnceClosure callback) {} }; } // namespace blink
diff --git a/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h b/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h index b6df0a1..7020b82 100644 --- a/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h +++ b/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h
@@ -16,7 +16,7 @@ #include "third_party/blink/public/platform/web_media_constraints.h" #include "third_party/blink/public/platform/web_media_stream_source.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_constraints_util_sets.h" -#include "third_party/blink/public/web/modules/mediastream/video_track_adapter.h" +#include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h" namespace blink {
diff --git a/third_party/blink/public/web/modules/mediastream/video_track_adapter.h b/third_party/blink/public/web/modules/mediastream/video_track_adapter.h index 57c33d6..088ea41 100644 --- a/third_party/blink/public/web/modules/mediastream/video_track_adapter.h +++ b/third_party/blink/public/web/modules/mediastream/video_track_adapter.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/optional.h" #include "base/single_thread_task_runner.h" #include "base/time/time.h" #include "media/base/video_frame.h" @@ -21,51 +22,7 @@ namespace blink { -class BLINK_EXPORT VideoTrackAdapterSettings { - public: - // Creates a VideoTrackAdapterSettings with no target resolution or frame rate - // and without any constraints on the resolution. - VideoTrackAdapterSettings(); - // Creates a VideoTrackAdapterSettings with a given target resolution and - // and frame rate, and without any constraints on the resolution. - VideoTrackAdapterSettings(const gfx::Size& target_size, - double max_frame_rate); - // Creates a VideoTrackAdapterSettings with the specified resolution, frame - // rate and resolution constraints. If |target_size| is null, it means that - // no video processing is desired. - VideoTrackAdapterSettings(base::Optional<gfx::Size> target_size, - double min_aspect_ratio, - double max_aspect_ratio, - double max_frame_rate); - VideoTrackAdapterSettings(const VideoTrackAdapterSettings& other); - VideoTrackAdapterSettings& operator=(const VideoTrackAdapterSettings& other); - bool operator==(const VideoTrackAdapterSettings& other) const; - - const base::Optional<gfx::Size>& target_size() const { return target_size_; } - int target_width() const { - DCHECK(target_size_); - return target_size_->width(); - } - int target_height() const { - DCHECK(target_size_); - return target_size_->height(); - } - double min_aspect_ratio() const { return min_aspect_ratio_; } - double max_aspect_ratio() const { return max_aspect_ratio_; } - double max_frame_rate() const { return max_frame_rate_; } - void set_max_frame_rate(double max_frame_rate) { - max_frame_rate_ = max_frame_rate; - } - - private: - base::Optional<gfx::Size> target_size_; - double min_aspect_ratio_; - double max_aspect_ratio_; - // A |max_frame_rate| of zero is used to signal that no frame-rate - // adjustment is necessary. - // TODO(guidou): Change this to base::Optional. https://crbug.com/734528 - double max_frame_rate_; -}; +class VideoTrackAdapterSettings; // VideoTrackAdapter is a helper class used by MediaStreamVideoSource used for // adapting the video resolution from a source implementation to the resolution @@ -121,8 +78,10 @@ void SetSourceFrameSize(const gfx::Size& source_frame_size); // Exported for testing. - // Returns true if |desired_size| is updated successfully, false otherwise. - // |desired_size| is not updated |settings| has rescaling disabled and + // + // Calculates the desired size of a VideoTrack instance, and returns true if + // |desired_size| is updated successfully, false otherwise. + // |desired_size| is not updated if |settings| has rescaling disabled and // |input_size| is invalid. static bool CalculateDesiredSize(bool is_rotated, const gfx::Size& input_size,
diff --git a/third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h b/third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h new file mode 100644 index 0000000..84cc2f63 --- /dev/null +++ b/third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h
@@ -0,0 +1,77 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_VIDEO_TRACK_ADAPTER_SETTINGS_H_ +#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_VIDEO_TRACK_ADAPTER_SETTINGS_H_ + +#include <stdint.h> + +#include "base/macros.h" +#include "base/optional.h" +#include "third_party/blink/public/platform/web_common.h" +#include "ui/gfx/geometry/size.h" + +namespace blink { + +class BLINK_EXPORT VideoTrackAdapterSettings { + public: + // Creates a VideoTrackAdapterSettings with no target resolution or frame rate + // and without any constraints on the resolution. + VideoTrackAdapterSettings(); + // Creates a VideoTrackAdapterSettings with a given target resolution and + // and frame rate, and without any constraints on the resolution. + VideoTrackAdapterSettings(const gfx::Size& target_size, + double max_frame_rate); + // Creates a VideoTrackAdapterSettings with the specified resolution, frame + // rate and resolution constraints. If |target_size| is null, it means that + // no video processing is desired. + VideoTrackAdapterSettings(base::Optional<gfx::Size> target_size, + double min_aspect_ratio, + double max_aspect_ratio, + double max_frame_rate); + VideoTrackAdapterSettings(const VideoTrackAdapterSettings& other); + VideoTrackAdapterSettings& operator=(const VideoTrackAdapterSettings& other); + bool operator==(const VideoTrackAdapterSettings& other) const; + + const base::Optional<gfx::Size>& target_size() const { return target_size_; } + int target_width() const { + DCHECK(target_size_); + return target_size_->width(); + } + int target_height() const { + DCHECK(target_size_); + return target_size_->height(); + } + double min_aspect_ratio() const { return min_aspect_ratio_; } + double max_aspect_ratio() const { return max_aspect_ratio_; } + double max_frame_rate() const { return max_frame_rate_; } + void set_max_frame_rate(double max_frame_rate) { + max_frame_rate_ = max_frame_rate; + } + + private: + base::Optional<gfx::Size> target_size_; + double min_aspect_ratio_; + double max_aspect_ratio_; + // A |max_frame_rate| of zero is used to signal that no frame-rate + // adjustment is necessary. + // TODO(guidou): Change this to base::Optional. https://crbug.com/734528 + double max_frame_rate_; +}; + +// Exported for testing. +// +// Calculates the desired size of a VideoTrack instance, and returns true if +// |desired_size| is updated successfully, false otherwise. +// |desired_size| is not updated if |settings| has rescaling disabled and +// |input_size| is invalid. +BLINK_EXPORT bool CalculateDesiredVideoTrackSize( + bool is_rotated, + const gfx::Size& input_size, + const VideoTrackAdapterSettings& settings, + gfx::Size* desired_size); + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_VIDEO_TRACK_ADAPTER_SETTINGS_H_
diff --git a/third_party/blink/public/web/web_widget.h b/third_party/blink/public/web/web_widget.h index 84299699..d4de9b5 100644 --- a/third_party/blink/public/web/web_widget.h +++ b/third_party/blink/public/web/web_widget.h
@@ -168,12 +168,6 @@ // transormations (e.g. pinch-zoom, dev tools emulation, etc.). virtual void PaintContent(cc::PaintCanvas*, const WebRect& view_port) {} - // Runs |callback| after a new frame has been submitted to the display - // compositor, and the display-compositor has displayed it on screen. Forces a - // redraw so that a new frame is submitted. - virtual void RequestPresentationCallbackForTesting( - base::OnceClosure callback) {} - // Called to inform the WebWidget of a change in theme. // Implementors that cache rendered copies of widgets need to re-render // on receiving this message
diff --git a/third_party/blink/public/web/web_widget_client.h b/third_party/blink/public/web/web_widget_client.h index 2a2e5cb..362ed035 100644 --- a/third_party/blink/public/web/web_widget_client.h +++ b/third_party/blink/public/web/web_widget_client.h
@@ -50,6 +50,7 @@ class SkBitmap; namespace cc { +class PaintImage; struct ViewportLayers; } @@ -249,6 +250,12 @@ bool use_anchor, float new_page_scale, double duration_sec) {} + + // Requests an image decode and will have the |callback| run asynchronously + // when it completes. Forces a new main frame to occur that will trigger + // pushing the decode through the compositor. + virtual void RequestDecode(const cc::PaintImage& image, + base::OnceCallback<void(bool)> callback) {} }; } // namespace blink
diff --git a/third_party/blink/renderer/bindings/modules/v8/BUILD.gn b/third_party/blink/renderer/bindings/modules/v8/BUILD.gn index 0745a1c..c82043e 100644 --- a/third_party/blink/renderer/bindings/modules/v8/BUILD.gn +++ b/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
@@ -50,9 +50,8 @@ } generate_origin_trial_features("bindings_modules_origin_trial_features") { - sources = - modules_idl_files + modules_global_constructors_generated_idl_files + - modules_dependency_idl_files + sources = modules_idl_files + modules_generated_dependency_idl_files + + modules_dependency_idl_files component = "modules" output_dir = bindings_modules_output_dir + "/v8" deps = [
diff --git a/third_party/blink/renderer/bindings/modules/v8/generated.gni b/third_party/blink/renderer/bindings/modules/v8/generated.gni index 7569f710..7c37c6d2 100644 --- a/third_party/blink/renderer/bindings/modules/v8/generated.gni +++ b/third_party/blink/renderer/bindings/modules/v8/generated.gni
@@ -133,6 +133,8 @@ "$bindings_modules_v8_output_dir/v8_rtc_session_description_callback.h", "$bindings_modules_v8_output_dir/v8_rtc_stats_callback.cc", "$bindings_modules_v8_output_dir/v8_rtc_stats_callback.h", + "$bindings_modules_v8_output_dir/v8_state_callback.cc", + "$bindings_modules_v8_output_dir/v8_state_callback.h", "$bindings_modules_v8_output_dir/v8_storage_error_callback.cc", "$bindings_modules_v8_output_dir/v8_storage_error_callback.h", "$bindings_modules_v8_output_dir/v8_storage_quota_callback.cc",
diff --git a/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py b/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py index ad5f3c2..318f9e6b 100644 --- a/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py +++ b/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py
@@ -221,8 +221,7 @@ # However, # - An interface defined in core cannot include an interface mixin # defined in modules. - if (not dependency_interface.is_mixin and - 'NoInterfaceObject' not in dependency_interface.extended_attributes): + if not dependency_interface.is_mixin: raise Exception('The interface:%s cannot implement ' 'the non-mixin interface: %s.' % ( target_interface.name,
diff --git a/third_party/blink/renderer/bindings/scripts/scripts.gni b/third_party/blink/renderer/bindings/scripts/scripts.gni index ec05dfe..7d31660 100644 --- a/third_party/blink/renderer/bindings/scripts/scripts.gni +++ b/third_party/blink/renderer/bindings/scripts/scripts.gni
@@ -485,8 +485,10 @@ # should be interfaces_info_core (w/o modules). This is the same issue as # above in the idl_compiler template. # http://crbug.com/358074 - deps = invoker.deps + - [ "//third_party/blink/renderer/bindings/modules:interfaces_info" ] + deps = invoker.deps + [ + "//third_party/blink/renderer/bindings/modules:interfaces_info", + "//third_party/blink/renderer/bindings/modules:modules_core_global_constructors_idls", + ] } }
diff --git a/third_party/blink/renderer/core/css/font_face_source.idl b/third_party/blink/renderer/core/css/font_face_source.idl index c7263bf..50490ea 100644 --- a/third_party/blink/renderer/core/css/font_face_source.idl +++ b/third_party/blink/renderer/core/css/font_face_source.idl
@@ -5,8 +5,7 @@ // spec: https://drafts.csswg.org/css-font-loading/#font-face-source [ - LegacyTreatAsPartialInterface, - NoInterfaceObject -] interface FontFaceSource { + LegacyTreatAsPartialInterface +] interface mixin FontFaceSource { [MeasureAs=DocumentFonts] readonly attribute FontFaceSet fonts; };
diff --git a/third_party/blink/renderer/core/dom/accessibility_role.idl b/third_party/blink/renderer/core/dom/accessibility_role.idl index cda5216e..22454d63 100644 --- a/third_party/blink/renderer/core/dom/accessibility_role.idl +++ b/third_party/blink/renderer/core/dom/accessibility_role.idl
@@ -5,9 +5,8 @@ // ARIA reflection // https://w3c.github.io/aria/#idl-interface [ - NoInterfaceObject, RuntimeEnabled=AccessibilityObjectModel -] interface AccessibilityRole { +] interface mixin AccessibilityRole { [CEReactions, Reflect] attribute DOMString? role; };
diff --git a/third_party/blink/renderer/core/dom/aria_attributes.idl b/third_party/blink/renderer/core/dom/aria_attributes.idl index 3d6d7c8..e4271c3 100644 --- a/third_party/blink/renderer/core/dom/aria_attributes.idl +++ b/third_party/blink/renderer/core/dom/aria_attributes.idl
@@ -5,9 +5,8 @@ // ARIA reflection // https://w3c.github.io/aria/#idl-interface [ - NoInterfaceObject, RuntimeEnabled=AccessibilityObjectModel -] interface AriaAttributes { +] interface mixin AriaAttributes { [CEReactions, Reflect=aria_activedescendant] attribute DOMString? ariaActiveDescendant; [CEReactions, Reflect=aria_atomic] attribute DOMString? ariaAtomic; [CEReactions, Reflect=aria_autocomplete] attribute DOMString? ariaAutoComplete;
diff --git a/third_party/blink/renderer/core/dom/child_node.idl b/third_party/blink/renderer/core/dom/child_node.idl index 1d71889..f455f95 100644 --- a/third_party/blink/renderer/core/dom/child_node.idl +++ b/third_party/blink/renderer/core/dom/child_node.idl
@@ -23,9 +23,8 @@ // https://dom.spec.whatwg.org/#interface-childnode [ - LegacyTreatAsPartialInterface, - NoInterfaceObject // Always used on target of 'implements' -] interface ChildNode { + LegacyTreatAsPartialInterface +] interface mixin ChildNode { [Unscopable, RaisesException, CEReactions, CustomElementCallbacks] void before((Node or DOMString) ... nodes); [Unscopable, RaisesException, CEReactions, CustomElementCallbacks] void after((Node or DOMString)... nodes); [Unscopable, RaisesException, CEReactions, CustomElementCallbacks] void replaceWith((Node or DOMString)... nodes);
diff --git a/third_party/blink/renderer/core/dom/document_and_element_event_handlers.idl b/third_party/blink/renderer/core/dom/document_and_element_event_handlers.idl index a42404f..73735f8 100644 --- a/third_party/blink/renderer/core/dom/document_and_element_event_handlers.idl +++ b/third_party/blink/renderer/core/dom/document_and_element_event_handlers.idl
@@ -5,9 +5,8 @@ // https://html.spec.whatwg.org/C/#documentandelementeventhandlers [ - LegacyTreatAsPartialInterface, - NoInterfaceObject // Always used on target of 'implements' -] interface DocumentAndElementEventHandlers { + LegacyTreatAsPartialInterface +] interface mixin DocumentAndElementEventHandlers { attribute EventHandler oncopy; attribute EventHandler oncut; attribute EventHandler onpaste;
diff --git a/third_party/blink/renderer/core/dom/document_or_shadow_root.idl b/third_party/blink/renderer/core/dom/document_or_shadow_root.idl index 69e7f36..f637e1a98 100644 --- a/third_party/blink/renderer/core/dom/document_or_shadow_root.idl +++ b/third_party/blink/renderer/core/dom/document_or_shadow_root.idl
@@ -5,9 +5,8 @@ // https://dom.spec.whatwg.org/#mixin-documentorshadowroot // https://w3c.github.io/webcomponents/spec/shadow/#extensions-to-the-documentorshadowroot-mixin [ - LegacyTreatAsPartialInterface, - NoInterfaceObject -] interface DocumentOrShadowRoot { + LegacyTreatAsPartialInterface +] interface mixin DocumentOrShadowRoot { // Selection API // https://w3c.github.io/selection-api/#extensions-to-document-interface [Affects=Nothing] Selection? getSelection();
diff --git a/third_party/blink/renderer/core/dom/global_event_handlers.idl b/third_party/blink/renderer/core/dom/global_event_handlers.idl index 1fd17f5..aa26190 100644 --- a/third_party/blink/renderer/core/dom/global_event_handlers.idl +++ b/third_party/blink/renderer/core/dom/global_event_handlers.idl
@@ -30,9 +30,8 @@ // https://html.spec.whatwg.org/C/#globaleventhandlers [ - LegacyTreatAsPartialInterface, - NoInterfaceObject // Always used on target of 'implements' -] interface GlobalEventHandlers { + LegacyTreatAsPartialInterface +] interface mixin GlobalEventHandlers { attribute EventHandler onabort; [RuntimeEnabled=InvisibleDOM] attribute EventHandler onactivateinvisible; [RuntimeEnabled=DisplayLocking] attribute EventHandler onbeforeactivate;
diff --git a/third_party/blink/renderer/core/dom/non_document_type_child_node.idl b/third_party/blink/renderer/core/dom/non_document_type_child_node.idl index d186e00fd..9fd6196 100644 --- a/third_party/blink/renderer/core/dom/non_document_type_child_node.idl +++ b/third_party/blink/renderer/core/dom/non_document_type_child_node.idl
@@ -5,9 +5,8 @@ // https://dom.spec.whatwg.org/#interface-nondocumenttypechildnode [ - LegacyTreatAsPartialInterface, - NoInterfaceObject // Always used on target of 'implements' -] interface NonDocumentTypeChildNode { + LegacyTreatAsPartialInterface +] interface mixin NonDocumentTypeChildNode { [PerWorldBindings] readonly attribute Element? previousElementSibling; [PerWorldBindings] readonly attribute Element? nextElementSibling; };
diff --git a/third_party/blink/renderer/core/dom/non_element_parent_node.idl b/third_party/blink/renderer/core/dom/non_element_parent_node.idl index 03511a6..572d925 100644 --- a/third_party/blink/renderer/core/dom/non_element_parent_node.idl +++ b/third_party/blink/renderer/core/dom/non_element_parent_node.idl
@@ -5,8 +5,7 @@ // https://dom.spec.whatwg.org/#interface-nonelementparentnode [ - LegacyTreatAsPartialInterface, - NoInterfaceObject // Always used on target of 'implements' -] interface NonElementParentNode { + LegacyTreatAsPartialInterface +] interface mixin NonElementParentNode { [PerWorldBindings] Element? getElementById(DOMString elementId); };
diff --git a/third_party/blink/renderer/core/dom/nonced_element.idl b/third_party/blink/renderer/core/dom/nonced_element.idl index cf3b6d7..1800aa7c 100644 --- a/third_party/blink/renderer/core/dom/nonced_element.idl +++ b/third_party/blink/renderer/core/dom/nonced_element.idl
@@ -6,8 +6,6 @@ // // TODO(mkwst): Update the link iff this lands. -[ - NoInterfaceObject -] interface NoncedElement { +interface mixin NoncedElement { [CEReactions] attribute DOMString nonce; };
diff --git a/third_party/blink/renderer/core/dom/parent_node.idl b/third_party/blink/renderer/core/dom/parent_node.idl index 546a6305..6c99394 100644 --- a/third_party/blink/renderer/core/dom/parent_node.idl +++ b/third_party/blink/renderer/core/dom/parent_node.idl
@@ -31,9 +31,8 @@ // https://dom.spec.whatwg.org/#interface-parentnode [ - LegacyTreatAsPartialInterface, - NoInterfaceObject // Always used on target of 'implements' -] interface ParentNode { + LegacyTreatAsPartialInterface +] interface mixin ParentNode { [Affects=Nothing, SameObject, PerWorldBindings] readonly attribute HTMLCollection children; [Affects=Nothing, PerWorldBindings] readonly attribute Element? firstElementChild; [Affects=Nothing, PerWorldBindings] readonly attribute Element? lastElementChild;
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 6baa3d4..a9368fdf 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1628,11 +1628,6 @@ } } -void WebViewImpl::RequestPresentationCallbackForTesting( - base::OnceClosure callback) { - layer_tree_view_->RequestPresentationCallback(std::move(callback)); -} - void WebViewImpl::PaintContent(cc::PaintCanvas* canvas, const WebRect& rect) { // This should only be used when compositing is not being used for this // WebView, and it is painting into the recording of its parent.
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index 0243b305d6..e537691c 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -446,8 +446,6 @@ void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override; void UpdateLifecycle(LifecycleUpdate requested_update, LifecycleUpdateReason reason) override; - void RequestPresentationCallbackForTesting( - base::OnceClosure callback) override; void PaintContent(cc::PaintCanvas*, const WebRect&) override; void ThemeChanged() override; WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&) override;
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy.cc b/third_party/blink/renderer/core/feature_policy/feature_policy.cc index bbfcf65..0c8b6fd 100644 --- a/third_party/blink/renderer/core/feature_policy/feature_policy.cc +++ b/third_party/blink/renderer/core/feature_policy/feature_policy.cc
@@ -45,6 +45,44 @@ return PolicyValue(false); } +PolicyValue ParseValueForType(mojom::PolicyValueType feature_type, + const String& value_string, + bool* ok) { + *ok = false; + PolicyValue value; + switch (feature_type) { + case mojom::PolicyValueType::kBool: + // recognize true, false + if (value_string.LowerASCII() == "true") { + value = PolicyValue(true); + *ok = true; + } else if (value_string.LowerASCII() == "false") { + value = PolicyValue(false); + *ok = true; + } + break; + case mojom::PolicyValueType::kDecDouble: { + if (value_string.LowerASCII() == "inf") { + value = PolicyValue::CreateMaxPolicyValue(feature_type); + *ok = true; + } else { + double parsed_value = value_string.ToDouble(ok); + if (*ok && parsed_value >= 0.0f) { + value = PolicyValue(parsed_value); + } else { + *ok = false; + } + } + break; + } + default: + NOTREACHED(); + } + if (!*ok) + return PolicyValue(); + return value; +} + } // namespace ParsedFeaturePolicy ParseFeaturePolicyHeader( @@ -160,43 +198,109 @@ } for (wtf_size_t i = 1; i < tokens.size(); i++) { - // TODO(loonybear): for each token, parse the policy value from the - // new syntax. if (!tokens[i].ContainsOnlyASCIIOrEmpty()) { messages->push_back("Non-ASCII characters in origin."); continue; } - if (EqualIgnoringASCIICase(tokens[i], "'self'")) { - values[self_origin->ToUrlOrigin()] = value; - } else if (src_origin && EqualIgnoringASCIICase(tokens[i], "'src'")) { - // Only the iframe allow attribute can define |src_origin|. - // When parsing feature policy header, 'src' is disallowed and - // |src_origin| = nullptr. - // If the iframe will have an opaque origin (for example, if it is - // sandboxed, or has a data: URL), then 'src' needs to refer to the - // opaque origin of the frame, which is not known yet. In this case, - // the |opaque_value| on the declaration is set, rather than adding - // an origin to the allowlist. - if (src_origin->IsOpaque()) { - allowlist.opaque_value = value; - } else { - values[src_origin->ToUrlOrigin()] = value; + + // Break the token into an origin and a value. Either one may be + // omitted. + PolicyValue value = PolicyValue::CreateMaxPolicyValue(feature_type); + String origin_string = tokens[i]; + String value_string; + wtf_size_t param_start = origin_string.find('('); + if (param_start != kNotFound) { + // There is a value attached to this origin + if (!origin_string.EndsWith(')')) { + // The declaration is malformed if the value is not the last part of + // the string. + if (messages) + messages->push_back("Unable to parse policy value."); + continue; } - } else if (EqualIgnoringASCIICase(tokens[i], "'none'")) { + value_string = origin_string.Substring( + param_start + 1, origin_string.length() - param_start - 2); + origin_string = origin_string.Substring(0, param_start); + bool ok = false; + value = ParseValueForType(feature_type, value_string, &ok); + if (!ok) { + if (messages) + messages->push_back("Unable to parse policy value."); + continue; + } + } + + // Determine the target of the declaration. This may be a specific + // origin, either explicitly written, or one of the special keywords + // 'self' or 'src'. ('src' can only be used in the iframe allow + // attribute.) + url::Origin target_origin; + + // If the iframe will have an opaque origin (for example, if it is + // sandboxed, or has a data: URL), then 'src' needs to refer to the + // opaque origin of the frame, which is not known yet. In this case, + // the |opaque_value| on the declaration is set, rather than adding + // an origin to the allowlist. + bool target_is_opaque = false; + bool target_is_all = false; + + // 'self' origin is used if either the origin is omitted (and there is + // no 'src' origin available) or the origin is exactly 'self'. + if ((origin_string.length() == 0 && !src_origin) || + EqualIgnoringASCIICase(origin_string, "'self'")) { + target_origin = self_origin->ToUrlOrigin(); + } + // 'src' origin is used if |src_origin| is available and either the + // origin is omitted or is a match for 'src'. |src_origin| is only set + // when parsing an iframe allow attribute. + else if (src_origin && + (origin_string.length() == 0 || + EqualIgnoringASCIICase(origin_string, "'src'"))) { + if (!src_origin->IsOpaque()) { + target_origin = src_origin->ToUrlOrigin(); + } else { + target_is_opaque = true; + } + } else if (EqualIgnoringASCIICase(origin_string, "'none'")) { continue; - } else if (tokens[i] == "*") { + } else if (origin_string == "*") { + target_is_all = true; + } + // Otherwise, parse the origin string and verify that the result is + // valid. Invalid strings will produce an opaque origin, which will + // result in an error message. + else { + scoped_refptr<SecurityOrigin> parsed_origin = + SecurityOrigin::CreateFromString(origin_string); + if (!parsed_origin->IsOpaque()) { + target_origin = parsed_origin->ToUrlOrigin(); + } else if (messages) { + messages->push_back("Unrecognized origin: '" + origin_string + + "'."); + continue; + } + } + + // Assign the value to the target origin(s). + if (target_is_all) { allowlist.fallback_value = value; allowlist.opaque_value = value; - break; + } else if (target_is_opaque) { + allowlist.opaque_value = value; } else { - scoped_refptr<SecurityOrigin> target_origin = - SecurityOrigin::CreateFromString(tokens[i]); - if (!target_origin->IsOpaque()) - values[target_origin->ToUrlOrigin()] = value; - else if (messages) - messages->push_back("Unrecognized origin: '" + tokens[i] + "'."); + DCHECK(!target_origin.opaque()); + values[target_origin] = value; } } + // Size reduction: remove all items in the allowlist whose value is the + // same as the fallback. + for (auto it = values.begin(); it != values.end();) { + if (it->second == allowlist.fallback_value) + it = values.erase(it); + else + it++; + } + allowlist.values = std::move(values); allowlists.push_back(allowlist); }
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc b/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc index b408d15..be888f3 100644 --- a/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc +++ b/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
@@ -48,6 +48,18 @@ "geolocation 'none' 'none' 'none'", "geolocation " ORIGIN_A " *", "fullscreen " ORIGIN_A "; payment 'self'", + "fullscreen " ORIGIN_A "(true)", + "fullscreen " ORIGIN_A "(false)", + "fullscreen " ORIGIN_A "(True)", + "fullscreen " ORIGIN_A "(TRUE)", + "oversized-images " ORIGIN_A "(2.0)", + "oversized-images " ORIGIN_A "(0.0)", + "oversized-images " ORIGIN_A "(4)", + "oversized-images " ORIGIN_A "(20000)", + "oversized-images " ORIGIN_A "(2e50)", + "oversized-images " ORIGIN_A "(inf)", + "oversized-images " ORIGIN_A "(Inf)", + "oversized-images " ORIGIN_A "(INF)", "fullscreen " ORIGIN_A "; payment *, geolocation 'self'"}; const char* const kInvalidPolicies[] = { @@ -59,7 +71,17 @@ "geolocation https:/bad,origin", "geolocation https://example.com, https://a.com", "geolocation *, payment data://badorigin", - "geolocation ws://xn--fd\xbcwsw3taaaaaBaa333aBBBBBBJBBJBBBt"}; + "geolocation ws://xn--fd\xbcwsw3taaaaaBaa333aBBBBBBJBBJBBBt", + "fullscreen(true)", + "fullscreen " ORIGIN_A "(notabool)", + "fullscreen " ORIGIN_A "(2.0)", + "oversized-images " ORIGIN_A "(true)", + "oversized-images " ORIGIN_A "(Something else)", + "oversized-images " ORIGIN_A "(1", + "oversized-images " ORIGIN_A "(-1)", + "oversized-images " ORIGIN_A "(1.2.3)", + "oversized-images " ORIGIN_A "(1.a.3)", + "fullscreen " ORIGIN_A "()"}; } // namespace @@ -89,8 +111,12 @@ const PolicyValue min_value = PolicyValue(false); const PolicyValue max_value = PolicyValue(true); - const PolicyValue min_double_value = + const PolicyValue sample_double_value = + PolicyValue(1.5, mojom::PolicyValueType::kDecDouble); + const PolicyValue default_double_value = PolicyValue(2.0, mojom::PolicyValueType::kDecDouble); + const PolicyValue min_double_value = + PolicyValue::CreateMinPolicyValue(mojom::PolicyValueType::kDecDouble); const PolicyValue max_double_value = PolicyValue::CreateMaxPolicyValue(mojom::PolicyValueType::kDecDouble); }; @@ -101,7 +127,7 @@ messages.clear(); ParseFeaturePolicy(policy_string, origin_a_.get(), origin_b_.get(), &messages, test_feature_name_map); - EXPECT_EQ(0UL, messages.size()); + EXPECT_EQ(0UL, messages.size()) << "Should parse " << policy_string; } } @@ -111,7 +137,7 @@ messages.clear(); ParseFeaturePolicy(policy_string, origin_a_.get(), origin_b_.get(), &messages, test_feature_name_map); - EXPECT_LT(0UL, messages.size()); + EXPECT_LT(0UL, messages.size()) << "Should fail to parse " << policy_string; } } @@ -303,6 +329,308 @@ expected_url_origin_b_)); } +TEST_F(FeaturePolicyParserTest, BooleanPolicyParametersParsedCorrectly) { + Vector<String> messages; + ParsedFeaturePolicy parsed_policy; + + // Test no origin specified, in a container policy context. + // (true) + parsed_policy = + ParseFeaturePolicy("fullscreen (true)", origin_a_.get(), origin_b_.get(), + &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + EXPECT_EQ(mojom::FeaturePolicyFeature::kFullscreen, parsed_policy[0].feature); + EXPECT_EQ(min_value, parsed_policy[0].fallback_value); + EXPECT_EQ(min_value, parsed_policy[0].opaque_value); + EXPECT_EQ(1UL, parsed_policy[0].values.size()); + EXPECT_TRUE(parsed_policy[0].values.begin()->first.IsSameOriginWith( + expected_url_origin_b_)); + EXPECT_EQ(max_value, parsed_policy[0].values.begin()->second); + + // Test no origin specified, in a header context. + // (true) + parsed_policy = ParseFeaturePolicy("fullscreen (true)", origin_a_.get(), + nullptr, &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + EXPECT_EQ(mojom::FeaturePolicyFeature::kFullscreen, parsed_policy[0].feature); + EXPECT_EQ(min_value, parsed_policy[0].fallback_value); + EXPECT_EQ(min_value, parsed_policy[0].opaque_value); + EXPECT_EQ(1UL, parsed_policy[0].values.size()); + EXPECT_TRUE(parsed_policy[0].values.begin()->first.IsSameOriginWith( + expected_url_origin_a_)); + EXPECT_EQ(max_value, parsed_policy[0].values.begin()->second); + + // Test no origin specified, in a sandboxed container policy context. + // (true) + scoped_refptr<SecurityOrigin> opaque_origin = + SecurityOrigin::CreateUniqueOpaque(); + parsed_policy = + ParseFeaturePolicy("fullscreen (true)", origin_a_.get(), opaque_origin, + &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + EXPECT_EQ(mojom::FeaturePolicyFeature::kFullscreen, parsed_policy[0].feature); + EXPECT_EQ(min_value, parsed_policy[0].fallback_value); + EXPECT_EQ(max_value, parsed_policy[0].opaque_value); + EXPECT_EQ(0UL, parsed_policy[0].values.size()); + + // 'self'(true) + parsed_policy = + ParseFeaturePolicy("fullscreen 'self'(true)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kFullscreen, parsed_policy[0].feature); + EXPECT_EQ(min_value, parsed_policy[0].fallback_value); + EXPECT_EQ(min_value, parsed_policy[0].opaque_value); + EXPECT_EQ(1UL, parsed_policy[0].values.size()); + EXPECT_TRUE(parsed_policy[0].values.begin()->first.IsSameOriginWith( + expected_url_origin_a_)); + EXPECT_EQ(max_value, parsed_policy[0].values.begin()->second); + + // *(false) + parsed_policy = + ParseFeaturePolicy("fullscreen *(false)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kFullscreen, parsed_policy[0].feature); + EXPECT_EQ(min_value, parsed_policy[0].fallback_value); + EXPECT_EQ(min_value, parsed_policy[0].opaque_value); + EXPECT_EQ(0UL, parsed_policy[0].values.size()); + + // *(true) + parsed_policy = + ParseFeaturePolicy("fullscreen *(true)", origin_a_.get(), origin_b_.get(), + &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kFullscreen, parsed_policy[0].feature); + EXPECT_EQ(max_value, parsed_policy[0].fallback_value); + EXPECT_EQ(max_value, parsed_policy[0].opaque_value); + EXPECT_EQ(0UL, parsed_policy[0].values.size()); +} + +TEST_F(FeaturePolicyParserTest, DoublePolicyParametersParsedCorrectly) { + Vector<String> messages; + ParsedFeaturePolicy parsed_policy; + + // 'self'(inf) + parsed_policy = + ParseFeaturePolicy("oversized-images 'self'(inf)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kOversizedImages, + parsed_policy[0].feature); + EXPECT_EQ(default_double_value, parsed_policy[0].fallback_value); + EXPECT_EQ(default_double_value, parsed_policy[0].opaque_value); + EXPECT_EQ(1UL, parsed_policy[0].values.size()); + EXPECT_TRUE(parsed_policy[0].values.begin()->first.IsSameOriginWith( + expected_url_origin_a_)); + EXPECT_EQ(max_double_value, parsed_policy[0].values.begin()->second); + + // 'self'(1.5) + parsed_policy = + ParseFeaturePolicy("oversized-images 'self'(1.5)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kOversizedImages, + parsed_policy[0].feature); + EXPECT_EQ(default_double_value, parsed_policy[0].fallback_value); + EXPECT_EQ(default_double_value, parsed_policy[0].opaque_value); + EXPECT_EQ(1UL, parsed_policy[0].values.size()); + EXPECT_TRUE(parsed_policy[0].values.begin()->first.IsSameOriginWith( + expected_url_origin_a_)); + EXPECT_EQ(sample_double_value, parsed_policy[0].values.begin()->second); + + // *(inf) + parsed_policy = + ParseFeaturePolicy("oversized-images *(inf)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kOversizedImages, + parsed_policy[0].feature); + EXPECT_EQ(max_double_value, parsed_policy[0].fallback_value); + EXPECT_EQ(max_double_value, parsed_policy[0].opaque_value); + EXPECT_EQ(0UL, parsed_policy[0].values.size()); + + // *(0) + parsed_policy = + ParseFeaturePolicy("oversized-images *(0)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kOversizedImages, + parsed_policy[0].feature); + EXPECT_EQ(min_double_value, parsed_policy[0].fallback_value); + EXPECT_EQ(min_double_value, parsed_policy[0].opaque_value); + EXPECT_EQ(0UL, parsed_policy[0].values.size()); + + // *(1.5) + parsed_policy = + ParseFeaturePolicy("oversized-images *(1.5)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kOversizedImages, + parsed_policy[0].feature); + EXPECT_EQ(sample_double_value, parsed_policy[0].fallback_value); + EXPECT_EQ(sample_double_value, parsed_policy[0].opaque_value); + EXPECT_EQ(0UL, parsed_policy[0].values.size()); + + // 'self'(1.5) 'src'(inf) + // Fallbacks should be default values. + parsed_policy = ParseFeaturePolicy("oversized-images 'self'(1.5) 'src'(inf)", + origin_a_.get(), origin_b_.get(), + &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kOversizedImages, + parsed_policy[0].feature); + EXPECT_EQ(default_double_value, parsed_policy[0].fallback_value); + EXPECT_EQ(default_double_value, parsed_policy[0].opaque_value); + EXPECT_EQ(2UL, parsed_policy[0].values.size()); + auto origin_and_value = parsed_policy[0].values.begin(); + EXPECT_TRUE(origin_and_value->first.IsSameOriginWith(expected_url_origin_a_)); + EXPECT_EQ(sample_double_value, origin_and_value->second); + origin_and_value++; + EXPECT_TRUE(origin_and_value->first.IsSameOriginWith(expected_url_origin_b_)); + EXPECT_EQ(max_double_value, origin_and_value->second); + + // *(1.5) 'src'(inf) + // Fallbacks should be 1.5 + parsed_policy = + ParseFeaturePolicy("oversized-images *(1.5) 'src'(inf)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kOversizedImages, + parsed_policy[0].feature); + EXPECT_EQ(sample_double_value, parsed_policy[0].fallback_value); + EXPECT_EQ(sample_double_value, parsed_policy[0].opaque_value); + EXPECT_EQ(1UL, parsed_policy[0].values.size()); + origin_and_value = parsed_policy[0].values.begin(); + EXPECT_TRUE(origin_and_value->first.IsSameOriginWith(expected_url_origin_b_)); + EXPECT_EQ(max_double_value, origin_and_value->second); + + // Test policy: 'self'(1.5) https://example.org(inf) + // Fallbacks should be default value. + parsed_policy = ParseFeaturePolicy( + "oversized-images 'self'(1.5) " ORIGIN_C "(inf)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kOversizedImages, + parsed_policy[0].feature); + EXPECT_EQ(default_double_value, parsed_policy[0].fallback_value); + EXPECT_EQ(default_double_value, parsed_policy[0].opaque_value); + EXPECT_EQ(2UL, parsed_policy[0].values.size()); + origin_and_value = parsed_policy[0].values.begin(); + EXPECT_TRUE(origin_and_value->first.IsSameOriginWith(expected_url_origin_a_)); + EXPECT_EQ(sample_double_value, origin_and_value->second); + origin_and_value++; + EXPECT_TRUE(origin_and_value->first.IsSameOriginWith(expected_url_origin_c_)); + EXPECT_EQ(max_double_value, origin_and_value->second); + + // Test policy: 'self'(1.5) https://example.org(inf) *(0) + // Fallbacks should be 0. + parsed_policy = ParseFeaturePolicy( + "oversized-images 'self'(1.5) " ORIGIN_C "(inf) *(0)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kOversizedImages, + parsed_policy[0].feature); + EXPECT_EQ(min_double_value, parsed_policy[0].fallback_value); + EXPECT_EQ(min_double_value, parsed_policy[0].opaque_value); + EXPECT_EQ(2UL, parsed_policy[0].values.size()); + origin_and_value = parsed_policy[0].values.begin(); + EXPECT_TRUE(origin_and_value->first.IsSameOriginWith(expected_url_origin_a_)); + EXPECT_EQ(sample_double_value, origin_and_value->second); + origin_and_value++; + EXPECT_TRUE(origin_and_value->first.IsSameOriginWith(expected_url_origin_c_)); + EXPECT_EQ(max_double_value, origin_and_value->second); +} + +TEST_F(FeaturePolicyParserTest, RedundantBooleanItemsRemoved) { + Vector<String> messages; + ParsedFeaturePolicy parsed_policy; + + // 'self'(true) *(true) + parsed_policy = + ParseFeaturePolicy("fullscreen 'self'(true) *(true)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kFullscreen, parsed_policy[0].feature); + EXPECT_EQ(max_value, parsed_policy[0].fallback_value); + EXPECT_EQ(max_value, parsed_policy[0].opaque_value); + EXPECT_EQ(0UL, parsed_policy[0].values.size()); + + // 'self'(false) + parsed_policy = + ParseFeaturePolicy("fullscreen 'self'(false)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kFullscreen, parsed_policy[0].feature); + EXPECT_EQ(min_value, parsed_policy[0].fallback_value); + EXPECT_EQ(min_value, parsed_policy[0].opaque_value); + EXPECT_EQ(0UL, parsed_policy[0].values.size()); + + // (true) + parsed_policy = + ParseFeaturePolicy("fullscreen (false)", origin_a_.get(), origin_b_.get(), + &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + EXPECT_EQ(mojom::FeaturePolicyFeature::kFullscreen, parsed_policy[0].feature); + EXPECT_EQ(min_value, parsed_policy[0].fallback_value); + EXPECT_EQ(min_value, parsed_policy[0].opaque_value); + EXPECT_EQ(0UL, parsed_policy[0].values.size()); +} + +TEST_F(FeaturePolicyParserTest, RedundantDoubleItemsRemoved) { + Vector<String> messages; + ParsedFeaturePolicy parsed_policy; + + // 'self'(1.5) *(1.5) + parsed_policy = + ParseFeaturePolicy("oversized-images 'self'(1.5) *(1.5)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kOversizedImages, + parsed_policy[0].feature); + EXPECT_EQ(sample_double_value, parsed_policy[0].fallback_value); + EXPECT_EQ(sample_double_value, parsed_policy[0].opaque_value); + EXPECT_EQ(0UL, parsed_policy[0].values.size()); + + // 'self'(inf) + parsed_policy = + ParseFeaturePolicy("oversized-images 'self'(2.0)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + + EXPECT_EQ(mojom::FeaturePolicyFeature::kOversizedImages, + parsed_policy[0].feature); + EXPECT_EQ(default_double_value, parsed_policy[0].fallback_value); + EXPECT_EQ(default_double_value, parsed_policy[0].opaque_value); + EXPECT_EQ(0UL, parsed_policy[0].values.size()); + + // (inf) + parsed_policy = + ParseFeaturePolicy("oversized-images (2.0)", origin_a_.get(), + origin_b_.get(), &messages, test_feature_name_map); + EXPECT_EQ(1UL, parsed_policy.size()); + EXPECT_EQ(mojom::FeaturePolicyFeature::kOversizedImages, + parsed_policy[0].feature); + EXPECT_EQ(default_double_value, parsed_policy[0].fallback_value); + EXPECT_EQ(default_double_value, parsed_policy[0].opaque_value); + EXPECT_EQ(0UL, parsed_policy[0].values.size()); +} + // Test histogram counting the use of feature policies in header. TEST_F(FeaturePolicyParserTest, HeaderHistogram) { const char* histogram_name = "Blink.UseCounter.FeaturePolicy.Header"; @@ -418,7 +746,7 @@ EXPECT_EQ(mojom::FeaturePolicyFeature::kOversizedImages, parsed_policy[0].feature); - EXPECT_GE(min_double_value, parsed_policy[0].fallback_value); + EXPECT_GE(default_double_value, parsed_policy[0].fallback_value); EXPECT_LE(max_double_value, parsed_policy[0].opaque_value); EXPECT_EQ(1UL, parsed_policy[0].values.size()); EXPECT_LE(max_double_value, parsed_policy[0].values.begin()->second);
diff --git a/third_party/blink/renderer/core/fetch/body.idl b/third_party/blink/renderer/core/fetch/body.idl index c9aa946..79a8952 100644 --- a/third_party/blink/renderer/core/fetch/body.idl +++ b/third_party/blink/renderer/core/fetch/body.idl
@@ -5,9 +5,8 @@ // https://fetch.spec.whatwg.org/#body [ - ActiveScriptWrappable, - NoInterfaceObject -] interface Body { + ActiveScriptWrappable +] interface mixin Body { [RaisesException] readonly attribute boolean bodyUsed; [CallWith=ScriptState, NewObject, RaisesException] Promise<ArrayBuffer> arrayBuffer(); [CallWith=ScriptState, NewObject, RaisesException] Promise<Blob> blob();
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index a6f7152..f0e2a6d 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -4405,4 +4405,28 @@ } } +#if DCHECK_IS_ON() +LocalFrameView::DisallowLayoutInvalidationScope:: + DisallowLayoutInvalidationScope(LocalFrameView* view) + : local_frame_view_(view) { + local_frame_view_->allows_layout_invalidation_after_layout_clean_ = false; + local_frame_view_->ForAllChildLocalFrameViews([](LocalFrameView& frame_view) { + if (!frame_view.ShouldThrottleRendering()) + frame_view.CheckDoesNotNeedLayout(); + frame_view.allows_layout_invalidation_after_layout_clean_ = false; + }); +} + +LocalFrameView::DisallowLayoutInvalidationScope:: + ~DisallowLayoutInvalidationScope() { + local_frame_view_->allows_layout_invalidation_after_layout_clean_ = true; + local_frame_view_->ForAllChildLocalFrameViews([](LocalFrameView& frame_view) { + if (!frame_view.ShouldThrottleRendering()) + frame_view.CheckDoesNotNeedLayout(); + frame_view.allows_layout_invalidation_after_layout_clean_ = true; + }); +} + +#endif + } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h index 82b27669..fa26378 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -734,25 +734,8 @@ STACK_ALLOCATED(); public: - DisallowLayoutInvalidationScope(LocalFrameView* view) - : local_frame_view_(view) { - local_frame_view_->allows_layout_invalidation_after_layout_clean_ = false; - local_frame_view_->ForAllChildLocalFrameViews( - [](LocalFrameView& frame_view) { - if (!frame_view.ShouldThrottleRendering()) - frame_view.CheckDoesNotNeedLayout(); - frame_view.allows_layout_invalidation_after_layout_clean_ = false; - }); - } - ~DisallowLayoutInvalidationScope() { - local_frame_view_->allows_layout_invalidation_after_layout_clean_ = true; - local_frame_view_->ForAllChildLocalFrameViews( - [](LocalFrameView& frame_view) { - if (!frame_view.ShouldThrottleRendering()) - frame_view.CheckDoesNotNeedLayout(); - frame_view.allows_layout_invalidation_after_layout_clean_ = true; - }); - } + explicit DisallowLayoutInvalidationScope(LocalFrameView* view); + ~DisallowLayoutInvalidationScope(); private: UntracedMember<LocalFrameView> local_frame_view_;
diff --git a/third_party/blink/renderer/core/frame/navigator_automation_information.idl b/third_party/blink/renderer/core/frame/navigator_automation_information.idl index e14af26..263575ea 100644 --- a/third_party/blink/renderer/core/frame/navigator_automation_information.idl +++ b/third_party/blink/renderer/core/frame/navigator_automation_information.idl
@@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://w3c.github.io/webdriver/webdriver-spec.html#interface +// https://w3c.github.io/webdriver/#interface [ - NoInterfaceObject, // Always used on target of 'implements' - Exposed=(Window), + Exposed=Window, RuntimeEnabled=AutomationControlled -] interface NavigatorAutomationInformation { +] interface mixin NavigatorAutomationInformation { readonly attribute boolean webdriver; };
diff --git a/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.idl b/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.idl index 8976b5f..f10248c8 100644 --- a/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.idl +++ b/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.idl
@@ -5,8 +5,7 @@ // https://html.spec.whatwg.org/C/#navigator.hardwareconcurrency [ - NoInterfaceObject, - Exposed=(Window,Worker) -] interface NavigatorConcurrentHardware { + Exposed=(Window, Worker) +] interface mixin NavigatorConcurrentHardware { [HighEntropy, MeasureAs=NavigatorHardwareConcurrency] readonly attribute unsigned long long hardwareConcurrency; };
diff --git a/third_party/blink/renderer/core/frame/navigator_cookies.idl b/third_party/blink/renderer/core/frame/navigator_cookies.idl index 12b9b92..3909adb 100644 --- a/third_party/blink/renderer/core/frame/navigator_cookies.idl +++ b/third_party/blink/renderer/core/frame/navigator_cookies.idl
@@ -4,7 +4,6 @@ // https://html.spec.whatwg.org/C/#cookies -[NoInterfaceObject] -interface NavigatorCookies { +interface mixin NavigatorCookies { readonly attribute boolean cookieEnabled; };
diff --git a/third_party/blink/renderer/core/frame/navigator_device_memory.idl b/third_party/blink/renderer/core/frame/navigator_device_memory.idl index 03e558c8..7a8e26b 100644 --- a/third_party/blink/renderer/core/frame/navigator_device_memory.idl +++ b/third_party/blink/renderer/core/frame/navigator_device_memory.idl
@@ -5,9 +5,8 @@ // https://github.com/w3c/device-memory#the-web-exposed-api [ - NoInterfaceObject, - Exposed=(Window,Worker) -] interface NavigatorDeviceMemory { + Exposed=(Window, Worker) +] interface mixin NavigatorDeviceMemory { [HighEntropy,MeasureAs=NavigatorDeviceMemory,RuntimeEnabled=NavigatorDeviceMemory,SecureContext] readonly attribute float deviceMemory; };
diff --git a/third_party/blink/renderer/core/frame/navigator_id.idl b/third_party/blink/renderer/core/frame/navigator_id.idl index a402a6968..803f5e2 100644 --- a/third_party/blink/renderer/core/frame/navigator_id.idl +++ b/third_party/blink/renderer/core/frame/navigator_id.idl
@@ -31,9 +31,8 @@ // https://html.spec.whatwg.org/C/#client-identification [ - NoInterfaceObject, // Always used on target of 'implements' Exposed=(Window,Worker) -] interface NavigatorID { +] interface mixin NavigatorID { readonly attribute DOMString appCodeName; // constant "Mozilla" readonly attribute DOMString appName; // constant "Netscape" [HighEntropy, MeasureAs=NavigatorAppVersion] readonly attribute DOMString appVersion;
diff --git a/third_party/blink/renderer/core/frame/navigator_language.idl b/third_party/blink/renderer/core/frame/navigator_language.idl index 7a72f53..cba24ed0 100644 --- a/third_party/blink/renderer/core/frame/navigator_language.idl +++ b/third_party/blink/renderer/core/frame/navigator_language.idl
@@ -5,9 +5,8 @@ // https://html.spec.whatwg.org/C/#language-preferences [ - NoInterfaceObject, - Exposed=(Window,Worker) -] interface NavigatorLanguage { + Exposed=(Window, Worker) +] interface mixin NavigatorLanguage { [HighEntropy, MeasureAs=NavigatorLanguage] readonly attribute DOMString language; [CachedAttribute=IsLanguagesDirty, HighEntropy, MeasureAs=NavigatorLanguages] readonly attribute FrozenArray<DOMString> languages; };
diff --git a/third_party/blink/renderer/core/frame/navigator_on_line.idl b/third_party/blink/renderer/core/frame/navigator_on_line.idl index 16dda054..4fcfb13 100644 --- a/third_party/blink/renderer/core/frame/navigator_on_line.idl +++ b/third_party/blink/renderer/core/frame/navigator_on_line.idl
@@ -31,8 +31,7 @@ // https://html.spec.whatwg.org/C/#navigator.online [ - NoInterfaceObject, // Always used on target of 'implements' Exposed=(Window,Worker) -] interface NavigatorOnLine { +] interface mixin NavigatorOnLine { readonly attribute boolean onLine; };
diff --git a/third_party/blink/renderer/core/frame/navigator_user_agent.idl b/third_party/blink/renderer/core/frame/navigator_user_agent.idl index b9aa924..a7bbe07 100644 --- a/third_party/blink/renderer/core/frame/navigator_user_agent.idl +++ b/third_party/blink/renderer/core/frame/navigator_user_agent.idl
@@ -3,10 +3,10 @@ // found in the LICENSE file. // https://github.com/WICG/ua-client-hints + [ - NoInterfaceObject, // Always used on target of 'implements' RuntimeEnabled=UserAgentClientHint, Exposed=Window -] interface NavigatorUserAgent { +] interface mixin NavigatorUserAgent { [SecureContext, CallWith=ScriptState] Promise<UserAgent> getUserAgent(); };
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc index d165254..8bc8bc1 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
@@ -342,11 +342,10 @@ base::OnceCallback<void(bool)> callback) { // If we have a LayerTreeView, propagate the request, otherwise fail it since // otherwise it would remain in a unresolved and unrejected state. - if (WebLayerTreeView* layer_tree_view = GetLayerTreeView()) { - layer_tree_view->RequestDecode(image, std::move(callback)); - } else { + // TODO(danakj): This should be based on |does_composite| instead. + if (!GetLayerTreeView()) std::move(callback).Run(false); - } + Client()->RequestDecode(image, std::move(callback)); } void WebFrameWidgetBase::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/frame/window_event_handlers.idl b/third_party/blink/renderer/core/frame/window_event_handlers.idl index 595cf78..dba180e 100644 --- a/third_party/blink/renderer/core/frame/window_event_handlers.idl +++ b/third_party/blink/renderer/core/frame/window_event_handlers.idl
@@ -30,9 +30,8 @@ // https://html.spec.whatwg.org/C/#windoweventhandlers [ - LegacyTreatAsPartialInterface, - NoInterfaceObject // Always used on target of 'implements' -] interface WindowEventHandlers { + LegacyTreatAsPartialInterface +] interface mixin WindowEventHandlers { attribute EventHandler onafterprint; attribute EventHandler onbeforeprint; // FIXME: onbeforeunload should be an OnBeforeUnloadEventHandler.
diff --git a/third_party/blink/renderer/core/frame/window_or_worker_global_scope.idl b/third_party/blink/renderer/core/frame/window_or_worker_global_scope.idl index 219aab54..9acd0e6 100644 --- a/third_party/blink/renderer/core/frame/window_or_worker_global_scope.idl +++ b/third_party/blink/renderer/core/frame/window_or_worker_global_scope.idl
@@ -40,9 +40,8 @@ [ LegacyTreatAsPartialInterface, - NoInterfaceObject, // Always used on target of 'implements' Exposed=(Window,Worker) -] interface WindowOrWorkerGlobalScope { +] interface mixin WindowOrWorkerGlobalScope { // base64 utility methods [RaisesException] DOMString btoa(DOMString btoa); [RaisesException] DOMString atob(DOMString atob);
diff --git a/third_party/blink/renderer/core/html/html_hyperlink_element_utils.idl b/third_party/blink/renderer/core/html/html_hyperlink_element_utils.idl index ff9057d..e46519a 100644 --- a/third_party/blink/renderer/core/html/html_hyperlink_element_utils.idl +++ b/third_party/blink/renderer/core/html/html_hyperlink_element_utils.idl
@@ -4,9 +4,7 @@ // https://html.spec.whatwg.org/C/#htmlhyperlinkelementutils -[ - NoInterfaceObject // Always used on target of 'implements' -] interface HTMLHyperlinkElementUtils { +interface mixin HTMLHyperlinkElementUtils { [CEReactions, RaisesException=Setter] stringifier attribute URLString href; readonly attribute USVString origin;
diff --git a/third_party/blink/renderer/core/inspector/browser_protocol.pdl b/third_party/blink/renderer/core/inspector/browser_protocol.pdl index 1d0800e..e7b2297 100644 --- a/third_party/blink/renderer/core/inspector/browser_protocol.pdl +++ b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
@@ -6405,6 +6405,13 @@ # Configuration for memory dump triggers. Used only when "memory-infra" category is enabled. optional MemoryDumpConfig memoryDumpConfig + # Data format of a trace. Can be either the legacy JSON format or the + # protocol buffer format. Note that the JSON format will be deprecated soon. + type StreamFormat extends string + enum + json + proto + # Compression type to use for traces returned via streams. type StreamCompression extends string enum @@ -6448,6 +6455,9 @@ optional enum transferMode ReportEvents ReturnAsStream + # Trace data format to use. This only applies when using `ReturnAsStream` + # transfer mode (defaults to `json`). + optional StreamFormat streamFormat # Compression format to use. This only applies when using `ReturnAsStream` # transfer mode (defaults to `none`) optional StreamCompression streamCompression @@ -6476,6 +6486,8 @@ parameters # A handle of the stream that holds resulting trace data. optional IO.StreamHandle stream + # Trace data format of returned stream. + optional StreamFormat traceFormat # Compression format of returned stream. optional StreamCompression streamCompression
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc index 0909aaa..be5c65d 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc +++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -437,30 +437,30 @@ } } - if (old_style && HasLayer() && !Layer()->NeedsRepaint()) { - if (old_style->BackfaceVisibility() != StyleRef().BackfaceVisibility()) { - // We need to repaint the layer to update the backface visibility value of - // the paint chunk. + if (old_style && + old_style->BackfaceVisibility() != StyleRef().BackfaceVisibility()) { + SetNeedsPaintPropertyUpdate(); + } + + if (old_style && HasLayer() && !Layer()->NeedsRepaint() && + diff.TransformChanged() && + (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() || + !Layer()->HasStyleDeterminedDirectCompositingReasons())) { + // PaintLayerPainter::PaintLayerWithAdjustedRoot skips painting of a layer + // whose transform is not invertible, so we need to repaint the layer when + // invertible status changes. + TransformationMatrix old_transform; + TransformationMatrix new_transform; + old_style->ApplyTransform( + old_transform, LayoutSize(), ComputedStyle::kExcludeTransformOrigin, + ComputedStyle::kExcludeMotionPath, + ComputedStyle::kIncludeIndependentTransformProperties); + StyleRef().ApplyTransform( + new_transform, LayoutSize(), ComputedStyle::kExcludeTransformOrigin, + ComputedStyle::kExcludeMotionPath, + ComputedStyle::kIncludeIndependentTransformProperties); + if (old_transform.IsInvertible() != new_transform.IsInvertible()) Layer()->SetNeedsRepaint(); - } else if (diff.TransformChanged() && - (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() || - !Layer()->HasStyleDeterminedDirectCompositingReasons())) { - // PaintLayerPainter::PaintLayerWithAdjustedRoot skips painting of a layer - // whose transform is not invertible, so we need to repaint the layer when - // invertible status changes. - TransformationMatrix old_transform; - TransformationMatrix new_transform; - old_style->ApplyTransform( - old_transform, LayoutSize(), ComputedStyle::kExcludeTransformOrigin, - ComputedStyle::kExcludeMotionPath, - ComputedStyle::kIncludeIndependentTransformProperties); - StyleRef().ApplyTransform( - new_transform, LayoutSize(), ComputedStyle::kExcludeTransformOrigin, - ComputedStyle::kExcludeMotionPath, - ComputedStyle::kIncludeIndependentTransformProperties); - if (old_transform.IsInvertible() != new_transform.IsInvertible()) - Layer()->SetNeedsRepaint(); - } } }
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index 00d5808..12561842 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -3539,7 +3539,6 @@ void LayoutObject::ForceLayout() { SetSelfNeedsLayoutForAvailableSpace(true); - MarkContainerNeedsCollectInlines(); UpdateLayout(); }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc index e2c22b7..1503b10 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
@@ -538,6 +538,23 @@ TEST_ITEM_TYPE_OFFSET((*items[4]), kText, 6u, 8u); } +TEST_F(NGInlineNodeTest, NeedsCollectInlinesOnForceLayout) { + SetBodyInnerHTML(R"HTML( + <div id="container"> + <span id="target"> + <span id="child" style="position: absolute">X</span> + </span> + </div> + )HTML"); + + LayoutObject* container = GetLayoutObjectByElementId("container"); + LayoutObject* target = GetLayoutObjectByElementId("target"); + LayoutObject* child = GetLayoutObjectByElementId("child"); + child->ForceLayout(); + EXPECT_FALSE(container->NeedsCollectInlines()); + EXPECT_FALSE(target->NeedsCollectInlines()); +} + TEST_F(NGInlineNodeTest, InvalidateAddSpan) { SetupHtml("t", "<div id=t>before</div>"); EXPECT_FALSE(layout_block_flow_->NeedsCollectInlines());
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc index 9ae716b7..aa408850 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -432,22 +432,24 @@ const NGOutOfFlowPositionedDescendant& descendant, const LayoutBox* only_layout, NGLogicalOffset* offset) { + NGBlockNode node = descendant.node; + // "NGOutOfFlowLayoutPart container is ContainingBlock" invariant cannot - // be enforced for tables. Tables are special, in that ContainingBlock is + // be enforced for tables. Tables are special, in that the ContainingBlock is // TABLE, but constraint space is generated by TBODY/TR/. This happens // because TBODY/TR are not LayoutBlocks, but LayoutBoxModelObjects. DCHECK((container_builder_->GetLayoutObject() == - descendant.node.GetLayoutBox()->ContainingBlock()) || - descendant.node.GetLayoutBox()->ContainingBlock()->IsTable()); + node.GetLayoutBox()->ContainingBlock()) || + node.GetLayoutBox()->ContainingBlock()->IsTable()); const ContainingBlockInfo& container_info = GetContainingBlockInfo(descendant); - const ComputedStyle& descendant_style = descendant.node.Style(); + const ComputedStyle& descendant_style = node.Style(); WritingMode container_writing_mode(container_info.style->GetWritingMode()); WritingMode descendant_writing_mode(descendant_style.GetWritingMode()); - // Adjust the static_position (which is currently relative to the default + // Adjust the |static_position| (which is currently relative to the default // container's border-box). ng_absolute_utils expects the static position to // be relative to the container's padding-box. NGStaticPosition static_position(descendant.static_position); @@ -465,19 +467,19 @@ .ToConstraintSpace(); NGBoxStrut border_padding = - ComputeBorders(descendant_constraint_space, descendant.node) + + ComputeBorders(descendant_constraint_space, node) + ComputePadding(descendant_constraint_space, descendant_style); - // The block_estimate is in the descendant's writing mode. + // The |block_estimate| is wrt. the descendant's writing mode. base::Optional<LayoutUnit> block_estimate; base::Optional<MinMaxSize> min_max_size; - scoped_refptr<const NGLayoutResult> layout_result = nullptr; - NGBlockNode node = descendant.node; + bool is_replaced = node.IsReplaced(); + bool should_be_considered_as_replaced = node.ShouldBeConsideredAsReplaced(); + if (AbsoluteNeedsChildInlineSize(descendant_style) || - NeedMinMaxSize(descendant_style) || - descendant.node.ShouldBeConsideredAsReplaced()) { + NeedMinMaxSize(descendant_style) || should_be_considered_as_replaced) { // This is a new formatting context, so whatever happened on the outside // doesn't concern us. MinMaxSizeInput input(container_content_size.block_size); @@ -486,10 +488,10 @@ } base::Optional<NGLogicalSize> replaced_size; - if (descendant.node.IsReplaced()) { - replaced_size = ComputeReplacedSize( - descendant.node, descendant_constraint_space, min_max_size); - } else if (descendant.node.ShouldBeConsideredAsReplaced()) { + if (is_replaced) { + replaced_size = + ComputeReplacedSize(node, descendant_constraint_space, min_max_size); + } else if (should_be_considered_as_replaced) { replaced_size = NGLogicalSize{ min_max_size->ShrinkToFit( descendant_constraint_space.AvailableSize().inline_size), @@ -501,15 +503,14 @@ static_position, min_max_size, replaced_size, container_writing_mode, container_info.style->Direction()); - // ShouldBeConsideredAsReplaced sets inline size. - // It does not set block size. This is a compatiblity quirk. - if (!descendant.node.IsReplaced() && - descendant.node.ShouldBeConsideredAsReplaced()) + // |should_be_considered_as_replaced| sets the inline-size. + // It does not set the block-size. This is a compatibility quirk. + if (!is_replaced && should_be_considered_as_replaced) replaced_size.reset(); if (AbsoluteNeedsChildBlockSize(descendant_style)) { - layout_result = GenerateFragment(descendant.node, container_info, - block_estimate, node_position); + layout_result = + GenerateFragment(node, container_info, block_estimate, node_position); DCHECK(layout_result->PhysicalFragment()); NGFragment fragment(descendant_writing_mode, @@ -523,12 +524,12 @@ static_position, block_estimate, replaced_size, container_writing_mode, container_info.style->Direction(), &node_position); - // Skip this step if we produced a fragment when estimating the block size. + // Skip this step if we produced a fragment when estimating the block-size. if (!layout_result) { block_estimate = node_position.size.ConvertToLogical(descendant_writing_mode).block_size; - layout_result = GenerateFragment(descendant.node, container_info, - block_estimate, node_position); + layout_result = + GenerateFragment(node, container_info, block_estimate, node_position); } if (node.GetLayoutBox()->IsLayoutNGObject()) { ToLayoutBlock(node.GetLayoutBox()) @@ -538,7 +539,7 @@ NGBoxStrut inset = node_position.inset.ConvertToLogical( container_writing_mode, default_containing_block_.style->Direction()); - // inset is relative to the container's padding-box. Convert this to being + // |inset| is relative to the container's padding-box. Convert this to being // relative to the default container's border-box. offset->inline_offset = inset.inline_start + container_info.container_offset.inline_offset; @@ -546,8 +547,7 @@ inset.block_start + container_info.container_offset.block_offset; base::Optional<LayoutUnit> y = ComputeAbsoluteDialogYPosition( - *descendant.node.GetLayoutBox(), - layout_result->PhysicalFragment()->Size().height); + *node.GetLayoutBox(), layout_result->PhysicalFragment()->Size().height); if (y.has_value()) { if (IsHorizontalWritingMode(container_writing_mode)) offset->block_offset = *y; @@ -560,7 +560,7 @@ // can only be computed by a block that is an ancestor of all fragments // generated by css container. That block is parent of anonymous containing // block. - // That is why instead of OOF being placed by its anononymous container, + // That is why instead of OOF being placed by its anonymous container, // they get placed by anonymous container's parent. // This is different from all other OOF blocks, and requires special // handling in several places in the OOF code. @@ -593,7 +593,7 @@ if (only_layout) return layout_result; - const LayoutObject* container = descendant.node.GetLayoutBox()->Container(); + const LayoutObject* container = node.GetLayoutBox()->Container(); if (container->IsAnonymousBlock()) { NGLogicalOffset container_offset = container_builder_->GetChildOffset(container);
diff --git a/third_party/blink/renderer/core/loader/progress_tracker.cc b/third_party/blink/renderer/core/loader/progress_tracker.cc index 98ff4d6..23998db 100644 --- a/third_party/blink/renderer/core/loader/progress_tracker.cc +++ b/third_party/blink/renderer/core/loader/progress_tracker.cc
@@ -54,15 +54,9 @@ struct ProgressItem { USING_FAST_MALLOC(ProgressItem); - public: - explicit ProgressItem(int64_t length) - : bytes_received(0), estimated_length(length) {} - - int64_t bytes_received; - int64_t estimated_length; - - DISALLOW_COPY_AND_ASSIGN(ProgressItem); + int64_t bytes_received = 0; + int64_t estimated_length = 0; }; ProgressTracker::ProgressTracker(LocalFrame* frame) @@ -96,6 +90,8 @@ last_notified_progress_time_ = 0; finished_parsing_ = false; did_first_contentful_paint_ = false; + bytes_received_ = 0; + estimated_bytes_for_pending_requests_ = 0; } LocalFrameClient* ProgressTracker::GetLocalFrameClient() const { @@ -144,31 +140,34 @@ return; if (HaveParsedAndPainted() || priority < ResourceLoadPriority::kHigh) return; - progress_items_.Set(identifier, std::make_unique<ProgressItem>( - kProgressItemDefaultEstimatedLength)); + ProgressItem new_item; + UpdateProgressItem(new_item, 0, kProgressItemDefaultEstimatedLength); + progress_items_.Set(identifier, new_item); } void ProgressTracker::IncrementProgress(uint64_t identifier, const ResourceResponse& response) { - ProgressItem* item = progress_items_.at(identifier); - if (!item) + auto item = progress_items_.find(identifier); + if (item == progress_items_.end()) return; int64_t estimated_length = response.ExpectedContentLength(); if (estimated_length < 0) estimated_length = kProgressItemDefaultEstimatedLength; - item->bytes_received = 0; - item->estimated_length = estimated_length; + UpdateProgressItem(item->value, 0, estimated_length); } void ProgressTracker::IncrementProgress(uint64_t identifier, uint64_t length) { - ProgressItem* item = progress_items_.at(identifier); - if (!item) + auto item = progress_items_.find(identifier); + if (item == progress_items_.end()) return; - item->bytes_received += length; - if (item->bytes_received > item->estimated_length) - item->estimated_length = item->bytes_received * 2; + ProgressItem& progress_item = item->value; + int64_t bytes_received = progress_item.bytes_received + length; + int64_t estimated_length = bytes_received > progress_item.estimated_length + ? bytes_received * 2 + : progress_item.estimated_length; + UpdateProgressItem(progress_item, bytes_received, estimated_length); MaybeSendProgress(); } @@ -176,6 +175,19 @@ return finished_parsing_ && did_first_contentful_paint_; } +void ProgressTracker::UpdateProgressItem(ProgressItem& item, + int64_t bytes_received, + int64_t estimated_length) { + bytes_received_ += (bytes_received - item.bytes_received); + estimated_bytes_for_pending_requests_ += + (estimated_length - item.estimated_length); + DCHECK_GE(bytes_received_, 0); + DCHECK_GE(estimated_bytes_for_pending_requests_, bytes_received_); + + item.bytes_received = bytes_received; + item.estimated_length = estimated_length; +} + void ProgressTracker::MaybeSendProgress() { if (!frame_->IsLoading()) return; @@ -186,27 +198,17 @@ if (did_first_contentful_paint_) progress_value_ += 0.1; - int64_t bytes_received = 0; - int64_t estimated_bytes_for_pending_requests = 0; - for (const auto& progress_item : progress_items_) { - bytes_received += progress_item.value->bytes_received; - estimated_bytes_for_pending_requests += - progress_item.value->estimated_length; - } - DCHECK_GE(estimated_bytes_for_pending_requests, 0); - DCHECK_GE(estimated_bytes_for_pending_requests, bytes_received); - if (HaveParsedAndPainted() && - estimated_bytes_for_pending_requests == bytes_received) { + estimated_bytes_for_pending_requests_ == bytes_received_) { SendFinalProgress(); return; } double percent_of_bytes_received = - !estimated_bytes_for_pending_requests + !estimated_bytes_for_pending_requests_ ? 1.0 - : (double)bytes_received / - (double)estimated_bytes_for_pending_requests; + : (double)bytes_received_ / + (double)estimated_bytes_for_pending_requests_; progress_value_ += percent_of_bytes_received / 2; DCHECK_GE(progress_value_, kInitialProgressValue); @@ -230,11 +232,13 @@ } void ProgressTracker::CompleteProgress(uint64_t identifier) { - ProgressItem* item = progress_items_.at(identifier); - if (!item) + auto item = progress_items_.find(identifier); + if (item == progress_items_.end()) return; - item->estimated_length = item->bytes_received; + ProgressItem& progress_item = item->value; + UpdateProgressItem(item->value, progress_item.bytes_received, + progress_item.bytes_received); MaybeSendProgress(); }
diff --git a/third_party/blink/renderer/core/loader/progress_tracker.h b/third_party/blink/renderer/core/loader/progress_tracker.h index b81db1c..0e4ba58f 100644 --- a/third_party/blink/renderer/core/loader/progress_tracker.h +++ b/third_party/blink/renderer/core/loader/progress_tracker.h
@@ -71,6 +71,10 @@ private: LocalFrameClient* GetLocalFrameClient() const; + void UpdateProgressItem(ProgressItem& item, + int64_t bytes_received, + int64_t estimated_length); + void MaybeSendProgress(); void SendFinalProgress(); void Reset(); @@ -84,7 +88,10 @@ bool did_first_contentful_paint_; double progress_value_; - HashMap<uint64_t, std::unique_ptr<ProgressItem>> progress_items_; + int64_t bytes_received_ = 0; + int64_t estimated_bytes_for_pending_requests_ = 0; + + HashMap<uint64_t, ProgressItem> progress_items_; DISALLOW_COPY_AND_ASSIGN(ProgressTracker); };
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc index 8d2cbcdb..004eb75 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc +++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
@@ -499,15 +499,18 @@ // unoptimized image feature policy on |context|. bool ImageResourceContent::IsAcceptableCompressionRatio( const SecurityContext& context) { + if (!image_) + return true; + uint64_t pixels = IntrinsicSize(kDoNotRespectImageOrientation).Area(); if (!pixels) return true; - DCHECK(image_); + double resource_length = static_cast<double>(GetResponse().ExpectedContentLength()); - if (resource_length <= 0 && GetImage() && GetImage()->Data()) { + if (resource_length <= 0 && image_->Data()) { // WPT and LayoutTests server returns -1 or 0 for the content length. - resource_length = static_cast<double>(GetImage()->Data()->size()); + resource_length = static_cast<double>(image_->Data()->size()); } // Calculate the image's compression ratio (in bytes per pixel) with both 1k @@ -516,12 +519,19 @@ double compression_ratio_1k = (resource_length - 1024) / pixels; double compression_ratio_10k = (resource_length - 10240) / pixels; - // Note that this approach may not always correctly identify the image (for - // example, due to a misconfigured web server). This approach SHOULD work in - // all usual cases, but content sniffing could be used in the future to more - // confidently identify the image type. - // TODO(crbug.com/943203): Implement content sniffing. - AtomicString mime_type = GetResponse().HttpContentType(); + // Attempt to sniff the image content to determine the true MIME type of the + // image, and fall back on the provided MIME type if this is not + // possible. + // + // Note that if the type cannot be sniffed AND the provided type is incorrect + // (for example, due to a misconfigured web server), then it is possible that + // either the wrong policy (or no policy) will be enforced. However, this case + // should be exceedingly rare. + String mime_type = + image_->Data() && + ImageDecoder::HasSufficientDataToSniffImageType(*image_->Data().get()) + ? ImageDecoder::SniffImageType(image_->Data()) + : GetResponse().HttpContentType(); if (MIMETypeRegistry::IsLossyImageMIMEType(mime_type)) { // Enforce the lossy image policy. return context.IsFeatureEnabled(
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc index 57d2ce3..6f284898 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
@@ -1688,4 +1688,13 @@ EXPECT_TRUE(paint_artifact_compositor->NeedsUpdate()); } +TEST_P(PaintPropertyTreeUpdateTest, BackfaceVisibilityInvalidatesProperties) { + SetBodyInnerHTML("<span id='span'>a</span>"); + + auto* span = GetDocument().getElementById("span"); + span->setAttribute(html_names::kStyleAttr, "backface-visibility: hidden;"); + GetDocument().View()->UpdateLifecycleToLayoutClean(); + EXPECT_TRUE(span->GetLayoutObject()->NeedsPaintPropertyUpdate()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/theme_painter_default.cc b/third_party/blink/renderer/core/paint/theme_painter_default.cc index 02c262ed..d4f4e51b 100644 --- a/third_party/blink/renderer/core/paint/theme_painter_default.cc +++ b/third_party/blink/renderer/core/paint/theme_painter_default.cc
@@ -214,15 +214,6 @@ if (style.HasBorderRadius() || style.HasBackgroundImage()) return true; - // Don't use the theme painter if dark mode is enabled. It has a separate - // graphics pipeline that doesn't go through GraphicsContext and so does not - // currently know how to handle Dark Mode, causing elements to be rendered - // incorrectly (e.g. https://crbug.com/937872). - // TODO(gilmanmh): Implement a more permanent solution that allows use of - // native dark themes. - if (paint_info.context.dark_mode_settings().mode != DarkMode::kOff) - return true; - ControlPart part = style.Appearance(); WebThemeEngine::ExtraParams extra_params; @@ -475,7 +466,8 @@ // pixel off-center, it will be one pixel closer to the bottom of the field. // This tends to look better with the text. LayoutRect cancel_button_rect( - cancel_button_object.OffsetFromAncestor(&input_layout_box).Width(), + cancel_button_object.OffsetFromAncestor(&input_layout_box) + .Width(), input_content_box.Y() + (input_content_box.Height() - cancel_button_size + 1) / 2, cancel_button_size, cancel_button_size);
diff --git a/third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.idl b/third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.idl index 08d9194..f6852b7 100644 --- a/third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.idl +++ b/third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.idl
@@ -26,9 +26,7 @@ // https://drafts.fxtf.org/filter-effects/#InterfaceSVGFilterPrimitiveStandardAttributes -[ - NoInterfaceObject // Always used on target of 'implements' -] interface SVGFilterPrimitiveStandardAttributes { +interface mixin SVGFilterPrimitiveStandardAttributes { [MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedLength x; [MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedLength y; [MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedLength width;
diff --git a/third_party/blink/renderer/core/svg/svg_fit_to_view_box.idl b/third_party/blink/renderer/core/svg/svg_fit_to_view_box.idl index b8af7cf..4f78218 100644 --- a/third_party/blink/renderer/core/svg/svg_fit_to_view_box.idl +++ b/third_party/blink/renderer/core/svg/svg_fit_to_view_box.idl
@@ -26,9 +26,7 @@ // https://svgwg.org/svg2-draft/types.html#InterfaceSVGFitToViewBox -[ - NoInterfaceObject // Always used on target of 'implements' -] interface SVGFitToViewBox { +interface mixin SVGFitToViewBox { [MeasureAs=SVG1DOMFitToViewBox] readonly attribute SVGAnimatedRect viewBox; [MeasureAs=SVG1DOMFitToViewBox] readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio; };
diff --git a/third_party/blink/renderer/core/svg/svg_tests.idl b/third_party/blink/renderer/core/svg/svg_tests.idl index 665ac6f5a1..edd7450 100644 --- a/third_party/blink/renderer/core/svg/svg_tests.idl +++ b/third_party/blink/renderer/core/svg/svg_tests.idl
@@ -26,9 +26,7 @@ // https://svgwg.org/svg2-draft/types.html#InterfaceSVGTests -[ - NoInterfaceObject // Always used on target of 'implements' -] interface SVGTests { +interface mixin SVGTests { [MeasureAs=SVG1DOMSVGTests] readonly attribute SVGStringList requiredExtensions; [MeasureAs=SVG1DOMSVGTests] readonly attribute SVGStringList systemLanguage; };
diff --git a/third_party/blink/renderer/core/svg/svg_uri_reference.idl b/third_party/blink/renderer/core/svg/svg_uri_reference.idl index 6f6cee2b..71d563f6 100644 --- a/third_party/blink/renderer/core/svg/svg_uri_reference.idl +++ b/third_party/blink/renderer/core/svg/svg_uri_reference.idl
@@ -26,8 +26,6 @@ // https://svgwg.org/svg2-draft/types.html#InterfaceSVGURIReference -[ - NoInterfaceObject // Always used on target of 'implements' -] interface SVGURIReference { +interface mixin SVGURIReference { [MeasureAs=SVG1DOMUriReference] readonly attribute SVGAnimatedString href; };
diff --git a/third_party/blink/renderer/core/svg/svg_zoom_and_pan.idl b/third_party/blink/renderer/core/svg/svg_zoom_and_pan.idl index 20e6ce5..d156aac 100644 --- a/third_party/blink/renderer/core/svg/svg_zoom_and_pan.idl +++ b/third_party/blink/renderer/core/svg/svg_zoom_and_pan.idl
@@ -26,9 +26,7 @@ // https://svgwg.org/svg2-draft/types.html#InterfaceSVGZoomAndPan -[ - NoInterfaceObject // Always used on target of 'implements' -] interface SVGZoomAndPan { +interface mixin SVGZoomAndPan { // Zoom and Pan Types const unsigned short SVG_ZOOMANDPAN_UNKNOWN = 0;
diff --git a/third_party/blink/renderer/core/workers/abstract_worker.idl b/third_party/blink/renderer/core/workers/abstract_worker.idl index 99091a7..8c3e449 100644 --- a/third_party/blink/renderer/core/workers/abstract_worker.idl +++ b/third_party/blink/renderer/core/workers/abstract_worker.idl
@@ -33,8 +33,7 @@ [ LegacyTreatAsPartialInterface, - NoInterfaceObject, // Always used on target of 'implements' Exposed=(Window,Worker) -] interface AbstractWorker { +] interface mixin AbstractWorker { attribute EventHandler onerror; };
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc index 30b5b91..3411fca 100644 --- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc +++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc
@@ -4,21 +4,26 @@ #include "third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h" +#include "base/optional.h" +#include "third_party/blink/renderer/bindings/core/v8/generated_code_helper.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h" #include "third_party/blink/renderer/bindings/core/v8/v8_function.h" #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_animate_callback.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_animator_constructor.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_state_callback.h" #include "third_party/blink/renderer/core/workers/global_scope_creation_params.h" #include "third_party/blink/renderer/core/workers/worker_thread.h" #include "third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.h" #include "third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h" #include "third_party/blink/renderer/platform/bindings/callback_method_retriever.h" +#include "third_party/blink/renderer/platform/bindings/exception_code.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h" #include "third_party/blink/renderer/platform/bindings/v8_object_constructor.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/wtf/time.h" +#include "v8/include/v8.h" namespace blink { @@ -63,10 +68,12 @@ Animator* AnimationWorkletGlobalScope::CreateAnimatorFor( int animation_id, const String& name, - WorkletAnimationOptions* options, + WorkletAnimationOptions options, + scoped_refptr<SerializedScriptValue> serialized_state, int num_effects) { DCHECK(!animators_.at(animation_id)); - Animator* animator = CreateInstance(name, options, num_effects); + Animator* animator = + CreateInstance(name, options, serialized_state, num_effects); if (!animator) return nullptr; animators_.Set(animation_id, animator); @@ -90,11 +97,14 @@ const String name = String::FromUTF8(animation.name.data(), animation.name.size()); + WorkletAnimationOptions options(nullptr); // Down casting to blink type to access the serialized value. - WorkletAnimationOptions* options = - static_cast<WorkletAnimationOptions*>(animation.options.get()); - - CreateAnimatorFor(id, name, options, animation.num_effects); + if (animation.options) { + options = + *(static_cast<WorkletAnimationOptions*>(animation.options.get())); + } + CreateAnimatorFor(id, name, options, nullptr /* serialized_state */, + animation.num_effects); } } @@ -190,11 +200,16 @@ if (exception_state.HadException()) return; V8AnimateCallback* animate = V8AnimateCallback::Create(v8_animate); + v8::Local<v8::Value> v8_state = retriever.GetMethodOrUndefined("state", exception_state); - V8Function* state = v8_state->IsFunction() - ? V8Function::Create(v8_state.As<v8::Function>()) - : nullptr; + if (exception_state.HadException()) + return; + + V8StateCallback* state = + v8_state->IsFunction() + ? V8StateCallback::Create(v8_state.As<v8::Function>()) + : nullptr; AnimatorDefinition* definition = MakeGarbageCollected<AnimatorDefinition>(animator_ctor, animate, state); @@ -213,34 +228,98 @@ Animator* AnimationWorkletGlobalScope::CreateInstance( const String& name, - WorkletAnimationOptions* options, + WorkletAnimationOptions options, + scoped_refptr<SerializedScriptValue> serialized_state, int num_effects) { DCHECK(IsContextThread()); AnimatorDefinition* definition = animator_definitions_.at(name); if (!definition) return nullptr; - v8::Isolate* isolate = ScriptController()->GetScriptState()->GetIsolate(); + ScriptState* script_state = ScriptController()->GetScriptState(); + ScriptState::Scope scope(script_state); + v8::Isolate* isolate = script_state->GetIsolate(); + + v8::TryCatch try_catch(isolate); + try_catch.SetVerbose(true); + v8::Local<v8::Value> v8_options = - options && options->GetData() ? options->GetData()->Deserialize(isolate) - : v8::Undefined(isolate).As<v8::Value>(); - ScriptValue options_value(ScriptController()->GetScriptState(), v8_options); + options.GetData() ? options.GetData()->Deserialize(isolate) + : v8::Undefined(isolate).As<v8::Value>(); + v8::Local<v8::Value> v8_state = serialized_state + ? serialized_state->Deserialize(isolate) + : v8::Undefined(isolate).As<v8::Value>(); + ScriptValue options_value(script_state, v8_options); + ScriptValue state_value(script_state, v8_state); ScriptValue instance; if (!definition->ConstructorFunction() - ->Construct(options_value) + ->Construct(options_value, state_value) .To(&instance)) { return nullptr; } return MakeGarbageCollected<Animator>(isolate, definition, instance.V8Value(), - num_effects); + name, std::move(options), num_effects); } bool AnimationWorkletGlobalScope::IsAnimatorStateful(int animation_id) { return animators_.at(animation_id)->IsStateful(); } +// Implementation of "Migrating an Animator Instance": +// https://drafts.css-houdini.org/css-animationworklet/#migrating-animator +// Note that per specification if the state function does not exist, the +// migration process should be aborted. However the following implementation +// is used for both the stateful and stateless animators. For the latter ones +// the migration (including name, options etc.) should be completed regardless +// the state function. +void AnimationWorkletGlobalScope::MigrateAnimatorsTo( + AnimationWorkletGlobalScope* target_global_scope) { + DCHECK_NE(this, target_global_scope); + + ScriptState* script_state = ScriptController()->GetScriptState(); + ScriptState::Scope scope(script_state); + v8::Isolate* isolate = script_state->GetIsolate(); + + for (const auto& animator_map : animators_) { + int animation_id = animator_map.key; + Animator* animator = animator_map.value; + scoped_refptr<SerializedScriptValue> serialized_state; + if (animator->IsStateful()) { + ExceptionState exception_state(script_state->GetIsolate(), + ExceptionState::kExecutionContext, + "Animator", "state"); + // If an animator state function throws or the state is not + // serializable, the animator will be removed from the global scope. + // TODO(yigu): We should post an error message to console in case of + // exceptions. + v8::Local<v8::Value> state = animator->State(isolate, exception_state); + if (exception_state.HadException()) { + exception_state.ClearException(); + continue; + } + + // Do not skip migrating the stateful animator if its state is + // undefined. + if (!state->IsNullOrUndefined()) { + serialized_state = SerializedScriptValue::Serialize( + isolate, state, SerializedScriptValue::SerializeOptions(), + exception_state); + if (exception_state.HadException()) { + exception_state.ClearException(); + continue; + } + } + } + + target_global_scope->CreateAnimatorFor( + animation_id, animator->name(), animator->options(), serialized_state, + animator->num_effects()); + } + animators_.clear(); +} + AnimatorDefinition* AnimationWorkletGlobalScope::FindDefinitionForTest( const String& name) { return animator_definitions_.at(name);
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h index f27dcaea..88a1731d3 100644 --- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h +++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h
@@ -55,17 +55,25 @@ AnimatorDefinition* FindDefinitionForTest(const String& name); bool IsAnimatorStateful(int animation_id); + void MigrateAnimatorsTo(AnimationWorkletGlobalScope*); + Animator* GetAnimator(int animation_id) { + return animators_.at(animation_id); + } unsigned GetAnimatorsSizeForTest() { return animators_.size(); } private: void RegisterWithProxyClientIfNeeded(); - Animator* CreateInstance(const String& name, - WorkletAnimationOptions* options, - int num_effects); - Animator* CreateAnimatorFor(int animation_id, - const String& name, - WorkletAnimationOptions* options, - int num_effects); + Animator* CreateInstance( + const String& name, + WorkletAnimationOptions options, + scoped_refptr<SerializedScriptValue> serialized_state, + int num_effects); + Animator* CreateAnimatorFor( + int animation_id, + const String& name, + WorkletAnimationOptions options, + scoped_refptr<SerializedScriptValue> serialized_state, + int num_effects); typedef HeapHashMap<String, Member<AnimatorDefinition>> DefinitionMap; DefinitionMap animator_definitions_;
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.idl b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.idl index b03e72e..08be78f2 100644 --- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.idl +++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.idl
@@ -14,6 +14,8 @@ // Blink-specific types // https://wicg.github.io/animation-worklet/#create-a-new-animator-instance -callback AnimatorConstructor = any (any options); +callback AnimatorConstructor = any (any options, any state); // https://wicg.github.io/animation-worklet/#run-animators callback AnimateCallback = void (double currentTime, (EffectProxy or WorkletGroupEffectProxy) effect); +// https://drafts.css-houdini.org/css-animationworklet/#stateful-animator-desc +callback StateCallback = any ();
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.cc index c26fe1b..5c07675 100644 --- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.cc +++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.cc
@@ -21,7 +21,6 @@ namespace { static const wtf_size_t kMaxMutateCountToSwitch = 10u; -static const wtf_size_t kStatefulGlobalScopeIndex = 0u; } // end namespace @@ -43,7 +42,7 @@ : worklet_id_(worklet_id), state_(RunState::kUninitialized), next_global_scope_switch_countdown_(0), - current_stateless_global_scope_index_(0) { + current_global_scope_index_(0) { DCHECK(IsMainThread()); // The dispatchers are weak pointers that may come from another thread. It's @@ -164,24 +163,14 @@ << worklet_id_; #endif - // Create or destroy instances of animators on each global scope. - for (auto global_scope : global_scopes_) { - global_scope->UpdateAnimatorsList(*input); - } + AnimationWorkletGlobalScope* global_scope = + SelectGlobalScopeAndUpdateAnimatorsIfNecessary(); + DCHECK(global_scope); + // Create or destroy instances of animators on current global scope. + global_scope->UpdateAnimatorsList(*input); - AnimationWorkletGlobalScope* stateful_global_scope = - SelectStatefulGlobalScope(); - DCHECK(stateful_global_scope); - stateful_global_scope->UpdateAnimators( - *input, output.get(), - [](Animator* animator) { return animator->IsStateful(); }); - - AnimationWorkletGlobalScope* stateless_global_scope = - SelectStatelessGlobalScope(); - DCHECK(stateless_global_scope); - stateless_global_scope->UpdateAnimators( - *input, output.get(), - [](Animator* animator) { return !animator->IsStateful(); }); + global_scope->UpdateAnimators(*input, output.get(), + [](Animator* animator) { return true; }); UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES( "Animation.AnimationWorklet.MutateDuration", timer.Elapsed(), @@ -192,21 +181,19 @@ } AnimationWorkletGlobalScope* -AnimationWorkletProxyClient::SelectStatelessGlobalScope() { +AnimationWorkletProxyClient::SelectGlobalScopeAndUpdateAnimatorsIfNecessary() { if (--next_global_scope_switch_countdown_ < 0) { - current_stateless_global_scope_index_ = - (++current_stateless_global_scope_index_ % global_scopes_.size()); + int last_global_scope_index = current_global_scope_index_; + current_global_scope_index_ = + (++current_global_scope_index_ % global_scopes_.size()); + global_scopes_[last_global_scope_index]->MigrateAnimatorsTo( + global_scopes_[current_global_scope_index_]); // Introduce an element of randomness in the switching interval to make // stateful dependences easier to spot. next_global_scope_switch_countdown_ = base::RandInt(0, kMaxMutateCountToSwitch - 1); } - return global_scopes_[current_stateless_global_scope_index_]; -} - -AnimationWorkletGlobalScope* -AnimationWorkletProxyClient::SelectStatefulGlobalScope() { - return global_scopes_[kStatefulGlobalScopeIndex]; + return global_scopes_[current_global_scope_index_]; } void AnimationWorkletProxyClient::AddGlobalScopeForTesting(
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.h b/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.h index 5e7f9af..74770067 100644 --- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.h +++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.h
@@ -62,22 +62,17 @@ static AnimationWorkletProxyClient* From(WorkerClients*); private: + friend class AnimationWorkletProxyClientTest; FRIEND_TEST_ALL_PREFIXES(AnimationWorkletProxyClientTest, AnimationWorkletProxyClientConstruction); FRIEND_TEST_ALL_PREFIXES(AnimationWorkletProxyClientTest, RegisteredAnimatorNameShouldSyncOnce); - FRIEND_TEST_ALL_PREFIXES(AnimationWorkletProxyClientTest, SelectGlobalScope); - // Separate global scope selectors are used instead of overriding - // Worklet::SelectGlobalScope since two different selection mechanisms are - // required in order to support statefulness and enforce statelessness - // depending on the animators. - // The stateless global scope periodically switches in order to enforce - // stateless behavior. Prior state is lost on each switch to global scope. - AnimationWorkletGlobalScope* SelectStatelessGlobalScope(); - // The stateful global scope remains fixed to preserve state between mutate - // calls. - AnimationWorkletGlobalScope* SelectStatefulGlobalScope(); + // The global scope periodically switches in order to enforce stateless + // behavior. For stateless animators, prior state is lost on each switch to + // global scope. For stateful animators, prior state is transferred to the new + // global scope. + AnimationWorkletGlobalScope* SelectGlobalScopeAndUpdateAnimatorsIfNecessary(); const int worklet_id_; @@ -98,7 +93,7 @@ enum RunState { kUninitialized, kWorking, kDisposed } state_; int next_global_scope_switch_countdown_; - wtf_size_t current_stateless_global_scope_index_; + wtf_size_t current_global_scope_index_; }; void MODULES_EXPORT
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_test.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_test.cc index 5637841..82ac234 100644 --- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_test.cc +++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_test.cc
@@ -13,6 +13,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h" #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h" +#include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" #include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h" #include "third_party/blink/renderer/modules/worklet/worklet_thread_test_common.h" @@ -62,38 +63,101 @@ } using TestCallback = - void (AnimationWorkletProxyClientTest::*)(WorkerThread*, - AnimationWorkletProxyClient*, + void (AnimationWorkletProxyClientTest::*)(AnimationWorkletProxyClient*, base::WaitableEvent*); - void RunTestOnWorkletThread(TestCallback callback) { - std::unique_ptr<WorkerThread> worklet_thread = + + void RunMultipleGlobalScopeTestsOnWorklet(TestCallback callback) { + // Global scopes must be created on worker threads. + std::unique_ptr<WorkerThread> first_worklet = + CreateThreadAndProvideAnimationWorkletProxyClient( + &GetDocument(), reporting_proxy_.get(), proxy_client_); + std::unique_ptr<WorkerThread> second_worklet = CreateThreadAndProvideAnimationWorkletProxyClient( &GetDocument(), reporting_proxy_.get(), proxy_client_); + ASSERT_NE(first_worklet, second_worklet); + + // Register global scopes with proxy client. This step must be performed on + // the worker threads. base::WaitableEvent waitable_event; PostCrossThreadTask( - *worklet_thread->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, + *first_worklet->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, + CrossThreadBind( + &AnimationWorkletProxyClientTest::AddGlobalScopeForTesting, + CrossThreadUnretained(this), + CrossThreadUnretained(first_worklet.get()), + CrossThreadPersistent<AnimationWorkletProxyClient>(proxy_client_), + CrossThreadUnretained(&waitable_event))); + waitable_event.Wait(); + + waitable_event.Reset(); + PostCrossThreadTask( + *second_worklet->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, + CrossThreadBind( + &AnimationWorkletProxyClientTest::AddGlobalScopeForTesting, + CrossThreadUnretained(this), + CrossThreadUnretained(second_worklet.get()), + CrossThreadPersistent<AnimationWorkletProxyClient>(proxy_client_), + CrossThreadUnretained(&waitable_event))); + waitable_event.Wait(); + + PostCrossThreadTask( + *first_worklet->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, CrossThreadBind( callback, CrossThreadUnretained(this), - CrossThreadUnretained(worklet_thread.get()), CrossThreadPersistent<AnimationWorkletProxyClient>(proxy_client_), CrossThreadUnretained(&waitable_event))); waitable_event.Wait(); waitable_event.Reset(); - worklet_thread->Terminate(); - worklet_thread->WaitForShutdownForTesting(); + first_worklet->Terminate(); + first_worklet->WaitForShutdownForTesting(); + second_worklet->Terminate(); + second_worklet->WaitForShutdownForTesting(); } - void RunMutateCorrectAnimatorOnWorklet( - WorkerThread* thread, + void RunSelectGlobalScopeOnWorklet(AnimationWorkletProxyClient* proxy_client, + base::WaitableEvent* waitable_event) { + AnimationWorkletGlobalScope* first_global_scope = + proxy_client->global_scopes_[0]; + AnimationWorkletGlobalScope* second_global_scope = + proxy_client->global_scopes_[1]; + + // Initialize switch countdown to 1, to force a switch in the stateless + // global scope on the second call. + proxy_client->next_global_scope_switch_countdown_ = 1; + EXPECT_EQ(proxy_client->SelectGlobalScopeAndUpdateAnimatorsIfNecessary(), + first_global_scope); + EXPECT_EQ(proxy_client->SelectGlobalScopeAndUpdateAnimatorsIfNecessary(), + second_global_scope); + + // Increase countdown and verify that the switchover adjusts as expected. + proxy_client->next_global_scope_switch_countdown_ = 3; + EXPECT_EQ(proxy_client->SelectGlobalScopeAndUpdateAnimatorsIfNecessary(), + second_global_scope); + EXPECT_EQ(proxy_client->SelectGlobalScopeAndUpdateAnimatorsIfNecessary(), + second_global_scope); + EXPECT_EQ(proxy_client->SelectGlobalScopeAndUpdateAnimatorsIfNecessary(), + second_global_scope); + EXPECT_EQ(proxy_client->SelectGlobalScopeAndUpdateAnimatorsIfNecessary(), + first_global_scope); + + waitable_event->Signal(); + } + + void RunMigrateAnimatorsBetweenGlobalScopesOnWorklet( AnimationWorkletProxyClient* proxy_client, base::WaitableEvent* waitable_event) { + AnimationWorkletGlobalScope* first_global_scope = + proxy_client->global_scopes_[0]; + AnimationWorkletGlobalScope* second_global_scope = + proxy_client->global_scopes_[1]; + String source_code = R"JS( class Stateful { animate () {} - state () {} + state () { return { foo: 'bar'}; } } class Stateless { @@ -104,16 +168,15 @@ registerAnimator('stateless_animator', Stateless); )JS"; - auto* global_scope = To<AnimationWorkletGlobalScope>(thread->GlobalScope()); - ASSERT_TRUE(global_scope->ScriptController()->Evaluate( + ASSERT_TRUE(first_global_scope->ScriptController()->Evaluate( + ScriptSourceCode(source_code), SanitizeScriptErrors::kDoNotSanitize)); + ASSERT_TRUE(second_global_scope->ScriptController()->Evaluate( ScriptSourceCode(source_code), SanitizeScriptErrors::kDoNotSanitize)); std::unique_ptr<AnimationWorkletInput> state = std::make_unique<AnimationWorkletInput>(); cc::WorkletAnimationId first_animation_id = {1, 1}; cc::WorkletAnimationId second_animation_id = {1, 2}; - cc::WorkletAnimationId third_animation_id = {1, 3}; - cc::WorkletAnimationId forth_animation_id = {1, 4}; state->added_and_updated_animations.emplace_back( first_animation_id, // animation id "stateless_animator", // name associated with the animation @@ -123,26 +186,17 @@ ); state->added_and_updated_animations.emplace_back( second_animation_id, "stateful_animator", 5000, nullptr, 1); - state->added_and_updated_animations.emplace_back( - third_animation_id, "stateful_animator", 5000, nullptr, 1); - state->added_and_updated_animations.emplace_back( - forth_animation_id, "stateless_animator", 5000, nullptr, 1); - std::unique_ptr<AnimationWorkletOutput> output = - proxy_client->Mutate(std::move(state)); - EXPECT_EQ(4u, output->animations.size()); + // Initialize switch countdown to 1, to force a switch on the second call. + proxy_client->next_global_scope_switch_countdown_ = 1; - auto has_id = [&](WorkletAnimationId id) { - auto found = - std::find_if(output->animations.begin(), output->animations.end(), - [&](auto& it) { return it.worklet_animation_id == id; }); - return found != output->animations.end(); - }; + proxy_client->Mutate(std::move(state)); + EXPECT_EQ(first_global_scope->GetAnimatorsSizeForTest(), 2u); + EXPECT_EQ(second_global_scope->GetAnimatorsSizeForTest(), 0u); - EXPECT_TRUE(has_id(first_animation_id)); - EXPECT_TRUE(has_id(second_animation_id)); - EXPECT_TRUE(has_id(third_animation_id)); - EXPECT_TRUE(has_id(forth_animation_id)); + proxy_client->SelectGlobalScopeAndUpdateAnimatorsIfNecessary(); + EXPECT_EQ(second_global_scope->GetAnimatorsSizeForTest(), 2u); + EXPECT_EQ(first_global_scope->GetAnimatorsSizeForTest(), 0u); waitable_event->Signal(); } @@ -194,81 +248,14 @@ } TEST_F(AnimationWorkletProxyClientTest, SelectGlobalScope) { - // Global scopes must be created on worker threads. - std::unique_ptr<WorkerThread> first_worklet = - CreateThreadAndProvideAnimationWorkletProxyClient( - &GetDocument(), reporting_proxy_.get(), proxy_client_); - std::unique_ptr<WorkerThread> second_worklet = - CreateThreadAndProvideAnimationWorkletProxyClient( - &GetDocument(), reporting_proxy_.get(), proxy_client_); - - ASSERT_NE(first_worklet, second_worklet); - - // Register global scopes with proxy client. This step must be performed on - // the worker threads. - base::WaitableEvent waitable_event; - PostCrossThreadTask( - *first_worklet->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, - CrossThreadBind( - &AnimationWorkletProxyClientTest::AddGlobalScopeForTesting, - CrossThreadUnretained(this), - CrossThreadUnretained(first_worklet.get()), - CrossThreadPersistent<AnimationWorkletProxyClient>(proxy_client_), - CrossThreadUnretained(&waitable_event))); - waitable_event.Wait(); - - waitable_event.Reset(); - PostCrossThreadTask( - *second_worklet->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, - CrossThreadBind( - &AnimationWorkletProxyClientTest::AddGlobalScopeForTesting, - CrossThreadUnretained(this), - CrossThreadUnretained(second_worklet.get()), - CrossThreadPersistent<AnimationWorkletProxyClient>(proxy_client_), - CrossThreadUnretained(&waitable_event))); - waitable_event.Wait(); - - AnimationWorkletGlobalScope* stateful_global_scope = - proxy_client_->global_scopes_[0]; - AnimationWorkletGlobalScope* first_stateless_global_scope = - proxy_client_->global_scopes_[0]; - AnimationWorkletGlobalScope* second_stateless_global_scope = - proxy_client_->global_scopes_[1]; - - // Initialize switch countdown to 1, to force a switch in the stateless - // global scope on the second call. - proxy_client_->next_global_scope_switch_countdown_ = 1; - EXPECT_EQ(proxy_client_->SelectStatefulGlobalScope(), stateful_global_scope); - EXPECT_EQ(proxy_client_->SelectStatelessGlobalScope(), - first_stateless_global_scope); - EXPECT_EQ(proxy_client_->SelectStatefulGlobalScope(), stateful_global_scope); - EXPECT_EQ(proxy_client_->SelectStatelessGlobalScope(), - second_stateless_global_scope); - - // Increase countdown and verify that the switchover adjusts as expected. - proxy_client_->next_global_scope_switch_countdown_ = 3; - EXPECT_EQ(proxy_client_->SelectStatefulGlobalScope(), stateful_global_scope); - EXPECT_EQ(proxy_client_->SelectStatelessGlobalScope(), - second_stateless_global_scope); - EXPECT_EQ(proxy_client_->SelectStatefulGlobalScope(), stateful_global_scope); - EXPECT_EQ(proxy_client_->SelectStatelessGlobalScope(), - second_stateless_global_scope); - EXPECT_EQ(proxy_client_->SelectStatefulGlobalScope(), stateful_global_scope); - EXPECT_EQ(proxy_client_->SelectStatelessGlobalScope(), - second_stateless_global_scope); - EXPECT_EQ(proxy_client_->SelectStatefulGlobalScope(), stateful_global_scope); - EXPECT_EQ(proxy_client_->SelectStatelessGlobalScope(), - first_stateless_global_scope); - - first_worklet->Terminate(); - first_worklet->WaitForShutdownForTesting(); - second_worklet->Terminate(); - second_worklet->WaitForShutdownForTesting(); + RunMultipleGlobalScopeTestsOnWorklet( + &AnimationWorkletProxyClientTest::RunSelectGlobalScopeOnWorklet); } -TEST_F(AnimationWorkletProxyClientTest, MutateCorrectAnimator) { - RunTestOnWorkletThread( - &AnimationWorkletProxyClientTest::RunMutateCorrectAnimatorOnWorklet); +TEST_F(AnimationWorkletProxyClientTest, MigrateAnimatorsBetweenGlobalScopes) { + RunMultipleGlobalScopeTestsOnWorklet( + &AnimationWorkletProxyClientTest:: + RunMigrateAnimatorsBetweenGlobalScopesOnWorklet); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/animationworklet/animator.cc b/third_party/blink/renderer/modules/animationworklet/animator.cc index c79ff47..f7f37b49 100644 --- a/third_party/blink/renderer/modules/animationworklet/animator.cc +++ b/third_party/blink/renderer/modules/animationworklet/animator.cc
@@ -7,16 +7,23 @@ #include "base/stl_util.h" #include "third_party/blink/renderer/bindings/modules/v8/effect_proxy_or_worklet_group_effect_proxy.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_animate_callback.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_state_callback.h" #include "third_party/blink/renderer/modules/animationworklet/animator_definition.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" +#include "v8/include/v8.h" namespace blink { Animator::Animator(v8::Isolate* isolate, AnimatorDefinition* definition, v8::Local<v8::Value> instance, + const String& name, + WorkletAnimationOptions options, int num_effects) : definition_(definition), instance_(isolate, instance), + name_(name), + options_(options), group_effect_( MakeGarbageCollected<WorkletGroupEffectProxy>(num_effects)) { DCHECK_GE(num_effects, 1); @@ -70,4 +77,21 @@ return definition_->IsStateful(); } +v8::Local<v8::Value> Animator::State(v8::Isolate* isolate, + ExceptionState& exception_state) { + if (!IsStateful()) + return v8::Undefined(isolate); + + v8::Local<v8::Value> instance = instance_.NewLocal(isolate); + DCHECK(!IsUndefinedOrNull(instance)); + + v8::TryCatch try_catch(isolate); + v8::Maybe<ScriptValue> state = definition_->StateFunction()->Invoke(instance); + if (try_catch.HasCaught()) { + exception_state.RethrowV8Exception(try_catch.Exception()); + return v8::Undefined(isolate); + } + return state.ToChecked().V8Value(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/animationworklet/animator.h b/third_party/blink/renderer/modules/animationworklet/animator.h index ca354fb0..f1ab17ab 100644 --- a/third_party/blink/renderer/modules/animationworklet/animator.h +++ b/third_party/blink/renderer/modules/animationworklet/animator.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_ANIMATOR_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_ANIMATOR_H_ +#include "third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h" #include "third_party/blink/renderer/modules/animationworklet/worklet_group_effect_proxy.h" #include "third_party/blink/renderer/platform/bindings/name_client.h" #include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h" @@ -26,6 +27,8 @@ Animator(v8::Isolate*, AnimatorDefinition*, v8::Local<v8::Value> instance, + const String& name, + WorkletAnimationOptions options, int num_effects); ~Animator(); void Trace(blink::Visitor*); @@ -37,15 +40,27 @@ bool Animate(v8::Isolate* isolate, double current_time, AnimationWorkletDispatcherOutput::AnimationState* output); + v8::Local<v8::Value> State(v8::Isolate*, ExceptionState&); std::vector<base::Optional<TimeDelta>> GetLocalTimes() const; bool IsStateful() const; + const String& name() const { return name_; } + WorkletAnimationOptions options() { return options_; } + int num_effects() const { return group_effect_->getChildren().size(); } + private: // This object keeps the definition object, and animator instance alive. // It participates in wrapper tracing as it holds onto V8 wrappers. Member<AnimatorDefinition> definition_; TraceWrapperV8Reference<v8::Value> instance_; + // The 'name' and 'options' of the animator need to be stored to be + // migrated to the new animator upon switching global scopes. For other + // properties, 'animation id' and 'number of effects' can be, and 'state' + // should be queried on the fly. + String name_; + WorkletAnimationOptions options_; + Member<WorkletGroupEffectProxy> group_effect_; };
diff --git a/third_party/blink/renderer/modules/animationworklet/animator_definition.cc b/third_party/blink/renderer/modules/animationworklet/animator_definition.cc index 0eaf9c8..a19cd4d 100644 --- a/third_party/blink/renderer/modules/animationworklet/animator_definition.cc +++ b/third_party/blink/renderer/modules/animationworklet/animator_definition.cc
@@ -7,12 +7,13 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_function.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_animate_callback.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_animator_constructor.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_state_callback.h" namespace blink { AnimatorDefinition::AnimatorDefinition(V8AnimatorConstructor* constructor, V8AnimateCallback* animate, - V8Function* state) + V8StateCallback* state) : constructor_(constructor), animate_(animate), state_(state) { DCHECK(constructor_); DCHECK(animate_);
diff --git a/third_party/blink/renderer/modules/animationworklet/animator_definition.h b/third_party/blink/renderer/modules/animationworklet/animator_definition.h index 3d1647a..85658f2 100644 --- a/third_party/blink/renderer/modules/animationworklet/animator_definition.h +++ b/third_party/blink/renderer/modules/animationworklet/animator_definition.h
@@ -13,7 +13,7 @@ class V8AnimateCallback; class V8AnimatorConstructor; -class V8Function; +class V8StateCallback; // Represents a valid registered Javascript animator. In particular it owns two // |v8::Function|s that are the "constructor" and "animate" functions of the @@ -26,7 +26,7 @@ public: explicit AnimatorDefinition(V8AnimatorConstructor* constructor, V8AnimateCallback* animate, - V8Function* state); + V8StateCallback* state); ~AnimatorDefinition(); virtual void Trace(blink::Visitor* visitor); const char* NameInHeapSnapshot() const override { @@ -35,6 +35,7 @@ V8AnimatorConstructor* ConstructorFunction() const { return constructor_; } V8AnimateCallback* AnimateFunction() const { return animate_; } + V8StateCallback* StateFunction() const { return state_; } bool IsStateful() const { return state_; } private: @@ -42,7 +43,7 @@ // alive. It participates in wrapper tracing as it holds onto V8 wrappers. Member<V8AnimatorConstructor> constructor_; Member<V8AnimateCallback> animate_; - Member<V8Function> state_; + Member<V8StateCallback> state_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h b/third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h index 4868ad2b..e11a3d2 100644 --- a/third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h +++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h
@@ -5,17 +5,18 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_OPTIONS_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_OPTIONS_H_ +#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/animation/compositor_animation.h" namespace blink { -class SerializedScriptValue; - class MODULES_EXPORT WorkletAnimationOptions final : public cc::AnimationOptions { public: explicit WorkletAnimationOptions(scoped_refptr<SerializedScriptValue>); + WorkletAnimationOptions(const WorkletAnimationOptions&) = default; + WorkletAnimationOptions& operator=(const WorkletAnimationOptions&) = default; std::unique_ptr<cc::AnimationOptions> Clone() const override; scoped_refptr<SerializedScriptValue> GetData() { return data_; }
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.idl b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.idl index 29bfbaf..81a279a 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.idl +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.idl
@@ -4,9 +4,7 @@ // https://html.spec.whatwg.org/C/#canvaspath -[ - NoInterfaceObject // Always used on target of 'implements' -] interface CanvasPath { +interface mixin CanvasPath { // shared path API methods void closePath(); void moveTo(unrestricted float x, unrestricted float y);
diff --git a/third_party/blink/renderer/modules/credentialmanager/credential_user_data.idl b/third_party/blink/renderer/modules/credentialmanager/credential_user_data.idl index 970140e..c2082ee 100644 --- a/third_party/blink/renderer/modules/credentialmanager/credential_user_data.idl +++ b/third_party/blink/renderer/modules/credentialmanager/credential_user_data.idl
@@ -4,8 +4,7 @@ // https://w3c.github.io/webappsec-credential-management/#credentialuserdata -[NoInterfaceObject] -interface CredentialUserData { +interface mixin CredentialUserData { readonly attribute USVString name; readonly attribute USVString iconURL; };
diff --git a/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc b/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc index cf8b72a..ee5079d 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc +++ b/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc
@@ -127,7 +127,8 @@ return supported_configurations_; } const SecurityOrigin* GetSecurityOrigin() const override; - void RequestSucceeded(WebContentDecryptionModuleAccess*) override; + void RequestSucceeded( + std::unique_ptr<WebContentDecryptionModuleAccess>) override; void RequestNotSupported(const WebString& error_message) override; ScriptPromise Promise() { return resolver_->Promise(); } @@ -216,14 +217,14 @@ } void MediaKeySystemAccessInitializer::RequestSucceeded( - WebContentDecryptionModuleAccess* access) { + std::unique_ptr<WebContentDecryptionModuleAccess> access) { DVLOG(3) << __func__; if (!IsExecutionContextValid()) return; resolver_->Resolve( - MakeGarbageCollected<MediaKeySystemAccess>(base::WrapUnique(access))); + MakeGarbageCollected<MediaKeySystemAccess>(std::move(access))); resolver_.Clear(); }
diff --git a/third_party/blink/renderer/modules/mediastream/BUILD.gn b/third_party/blink/renderer/modules/mediastream/BUILD.gn index 0ca5ecb..3ee2db8 100644 --- a/third_party/blink/renderer/modules/mediastream/BUILD.gn +++ b/third_party/blink/renderer/modules/mediastream/BUILD.gn
@@ -48,6 +48,7 @@ "user_media_request.cc", "user_media_request.h", "video_track_adapter.cc", + "video_track_adapter_settings.cc", "web_media_stream_utils.cc", ] }
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc index 7b5c0965..9665996 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc
@@ -16,7 +16,7 @@ #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_sink.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h" -#include "third_party/blink/public/web/modules/mediastream/video_track_adapter.h" +#include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h" #include "third_party/blink/public/web/web_heap.h" #include "third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
diff --git a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc b/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc index 40b9252..83f8f2cb 100644 --- a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc +++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
@@ -24,6 +24,7 @@ #include "media/base/limits.h" #include "media/base/video_util.h" #include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h" #include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h" namespace blink { @@ -472,49 +473,6 @@ base::BindOnce(frame_dropped_cb_, reason)); } -VideoTrackAdapterSettings::VideoTrackAdapterSettings() - : VideoTrackAdapterSettings(base::nullopt, - 0.0, - std::numeric_limits<double>::max(), - 0.0) {} - -VideoTrackAdapterSettings::VideoTrackAdapterSettings( - const gfx::Size& target_size, - double max_frame_rate) - : VideoTrackAdapterSettings(target_size, 0.0, HUGE_VAL, max_frame_rate) {} - -VideoTrackAdapterSettings::VideoTrackAdapterSettings( - base::Optional<gfx::Size> target_size, - double min_aspect_ratio, - double max_aspect_ratio, - double max_frame_rate) - : target_size_(std::move(target_size)), - min_aspect_ratio_(min_aspect_ratio), - max_aspect_ratio_(max_aspect_ratio), - max_frame_rate_(max_frame_rate) { - DCHECK(!target_size_ || - (target_size_->width() >= 0 && target_size_->height() >= 0)); - DCHECK(!std::isnan(min_aspect_ratio_)); - DCHECK_GE(min_aspect_ratio_, 0.0); - DCHECK(!std::isnan(max_aspect_ratio_)); - DCHECK_GE(max_aspect_ratio_, min_aspect_ratio_); - DCHECK(!std::isnan(max_frame_rate_)); - DCHECK_GE(max_frame_rate_, 0.0); -} - -VideoTrackAdapterSettings::VideoTrackAdapterSettings( - const VideoTrackAdapterSettings& other) = default; -VideoTrackAdapterSettings& VideoTrackAdapterSettings::operator=( - const VideoTrackAdapterSettings& other) = default; - -bool VideoTrackAdapterSettings::operator==( - const VideoTrackAdapterSettings& other) const { - return target_size_ == other.target_size_ && - min_aspect_ratio_ == other.min_aspect_ratio_ && - max_aspect_ratio_ == other.max_aspect_ratio_ && - max_frame_rate_ == other.max_frame_rate_; -} - VideoTrackAdapter::VideoTrackAdapter( scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, base::RepeatingCallback<void(media::VideoCaptureFrameDropReason)> @@ -617,7 +575,6 @@ this, source_frame_size)); } -// static bool VideoTrackAdapter::CalculateDesiredSize( bool is_rotated, const gfx::Size& original_input_size,
diff --git a/third_party/blink/renderer/modules/mediastream/video_track_adapter_settings.cc b/third_party/blink/renderer/modules/mediastream/video_track_adapter_settings.cc new file mode 100644 index 0000000..b23e06d --- /dev/null +++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter_settings.cc
@@ -0,0 +1,56 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h" + +#include <limits> +#include <memory> +#include <utility> + +namespace blink { + +VideoTrackAdapterSettings::VideoTrackAdapterSettings() + : VideoTrackAdapterSettings(base::nullopt, + 0.0, + std::numeric_limits<double>::max(), + 0.0) {} + +VideoTrackAdapterSettings::VideoTrackAdapterSettings( + const gfx::Size& target_size, + double max_frame_rate) + : VideoTrackAdapterSettings(target_size, 0.0, HUGE_VAL, max_frame_rate) {} + +VideoTrackAdapterSettings::VideoTrackAdapterSettings( + base::Optional<gfx::Size> target_size, + double min_aspect_ratio, + double max_aspect_ratio, + double max_frame_rate) + : target_size_(std::move(target_size)), + min_aspect_ratio_(min_aspect_ratio), + max_aspect_ratio_(max_aspect_ratio), + max_frame_rate_(max_frame_rate) { + DCHECK(!target_size_ || + (target_size_->width() >= 0 && target_size_->height() >= 0)); + DCHECK(!std::isnan(min_aspect_ratio_)); + DCHECK_GE(min_aspect_ratio_, 0.0); + DCHECK(!std::isnan(max_aspect_ratio_)); + DCHECK_GE(max_aspect_ratio_, min_aspect_ratio_); + DCHECK(!std::isnan(max_frame_rate_)); + DCHECK_GE(max_frame_rate_, 0.0); +} + +VideoTrackAdapterSettings::VideoTrackAdapterSettings( + const VideoTrackAdapterSettings& other) = default; +VideoTrackAdapterSettings& VideoTrackAdapterSettings::operator=( + const VideoTrackAdapterSettings& other) = default; + +bool VideoTrackAdapterSettings::operator==( + const VideoTrackAdapterSettings& other) const { + return target_size_ == other.target_size_ && + min_aspect_ratio_ == other.min_aspect_ratio_ && + max_aspect_ratio_ == other.max_aspect_ratio_ && + max_frame_rate_ == other.max_frame_rate_; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl index 9cd92a0f..fedeb6c7 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl +++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl
@@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -[ - NoInterfaceObject -] interface WebGL2ComputeRenderingContextBase { +interface mixin WebGL2ComputeRenderingContextBase { // TODO(jiajia.qin@intel.com): add more enums and apis const GLenum COMPUTE_SHADER = 0x91B9; const GLenum UNIFORM = 0x92E1;
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.idl b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.idl index beb3f21a..060d0be 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.idl +++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.idl
@@ -7,9 +7,7 @@ typedef long long GLint64; typedef unsigned long long GLuint64; -[ - NoInterfaceObject -] interface WebGL2RenderingContextBase { +interface mixin WebGL2RenderingContextBase { const GLenum READ_BUFFER = 0x0C02; const GLenum UNPACK_ROW_LENGTH = 0x0CF2; const GLenum UNPACK_SKIP_ROWS = 0x0CF3;
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl index d3a2f114..b825f7e 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl
@@ -40,12 +40,7 @@ typedef unrestricted float GLfloat; typedef unrestricted float GLclampf; -[ - // FIXME: [DoNotCheckConstants] should be applied to members and not need to - // be put on implementing interface - // DoNotCheckConstants, // need to put on implementing interface - NoInterfaceObject // Always used on target of 'implements' -] interface WebGLRenderingContextBase { +interface mixin WebGLRenderingContextBase { [ImplementedAs=getHTMLOrOffscreenCanvas] readonly attribute (HTMLCanvasElement or OffscreenCanvas) canvas;
diff --git a/third_party/blink/renderer/modules/xr/xr.cc b/third_party/blink/renderer/modules/xr/xr.cc index f693347c..f8ecd32 100644 --- a/third_party/blink/renderer/modules/xr/xr.cc +++ b/third_party/blink/renderer/modules/xr/xr.cc
@@ -505,10 +505,11 @@ XRSession::SessionMode mode, XRSession::EnvironmentBlendMode blend_mode, device::mojom::blink::XRSessionClientRequest client_request, - device::mojom::blink::VRDisplayInfoPtr display_info) { + device::mojom::blink::VRDisplayInfoPtr display_info, + bool sensorless_session) { XRSession* session = MakeGarbageCollected<XRSession>( this, client_request ? std::move(client_request) : nullptr, mode, - sessionModeToString(mode), blend_mode); + sessionModeToString(mode), blend_mode, sensorless_session); if (display_info) session->SetXRDisplayInfo(std::move(display_info)); sessions_.insert(session); @@ -519,8 +520,8 @@ // TODO(https://crbug.com/944936): The blend mode could be "additive". XRSession::EnvironmentBlendMode blend_mode = XRSession::kBlendModeOpaque; return CreateSession(XRSession::kModeInline, blend_mode, - nullptr /* client request */, - nullptr /* display_info */); + nullptr /* client request */, nullptr /* display_info */, + true /* sensorless_session */); } void XR::Dispose() {
diff --git a/third_party/blink/renderer/modules/xr/xr.h b/third_party/blink/renderer/modules/xr/xr.h index f50d4890d..80cb19d 100644 --- a/third_party/blink/renderer/modules/xr/xr.h +++ b/third_party/blink/renderer/modules/xr/xr.h
@@ -111,7 +111,8 @@ XRSession::SessionMode mode, XRSession::EnvironmentBlendMode blend_mode, device::mojom::blink::XRSessionClientRequest client_request, - device::mojom::blink::VRDisplayInfoPtr display_info); + device::mojom::blink::VRDisplayInfoPtr display_info, + bool sensorless_session = false); XRSession* CreateSensorlessInlineSession(); void Dispose();
diff --git a/third_party/blink/renderer/modules/xr/xr_session.cc b/third_party/blink/renderer/modules/xr/xr_session.cc index 815cd29..e96c3a2e 100644 --- a/third_party/blink/renderer/modules/xr/xr_session.cc +++ b/third_party/blink/renderer/modules/xr/xr_session.cc
@@ -112,7 +112,8 @@ device::mojom::blink::XRSessionClientRequest client_request, XRSession::SessionMode mode, const String& mode_string, - EnvironmentBlendMode environment_blend_mode) + EnvironmentBlendMode environment_blend_mode, + bool sensorless_session) : xr_(xr), mode_(mode), mode_string_(mode_string), @@ -121,7 +122,8 @@ client_binding_(this, std::move(client_request)), callback_collection_( MakeGarbageCollected<XRFrameRequestCallbackCollection>( - xr_->GetExecutionContext())) { + xr_->GetExecutionContext())), + sensorless_session_(sensorless_session) { render_state_ = MakeGarbageCollected<XRRenderState>(); viewer_space_ = MakeGarbageCollected<XRViewerSpace>(this); blurred_ = !HasAppropriateFocus(); @@ -235,6 +237,12 @@ kSessionEnded)); } + if (sensorless_session_ && options->type() != "identity") { + return ScriptPromise::RejectWithDOMException( + script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError, + kReferenceSpaceNotSupported)); + } + XRReferenceSpace* reference_space = nullptr; if (options->type() == "identity") { reference_space = MakeGarbageCollected<XRReferenceSpace>(this);
diff --git a/third_party/blink/renderer/modules/xr/xr_session.h b/third_party/blink/renderer/modules/xr/xr_session.h index 18c6811..d8c25720 100644 --- a/third_party/blink/renderer/modules/xr/xr_session.h +++ b/third_party/blink/renderer/modules/xr/xr_session.h
@@ -65,7 +65,8 @@ device::mojom::blink::XRSessionClientRequest client_request, SessionMode mode, const String& mode_string, - EnvironmentBlendMode environment_blend_mode); + EnvironmentBlendMode environment_blend_mode, + bool sensorless_session); ~XRSession() override = default; XR* xr() const { return xr_; } @@ -252,6 +253,10 @@ // Dimensions of the output canvas. int output_width_ = 1; int output_height_ = 1; + + // Indicates that this is a sensorless session which should only support the + // identity reference space. + bool sensorless_session_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/encrypted_media_request.h b/third_party/blink/renderer/platform/encrypted_media_request.h index 92e73fb..143f47c 100644 --- a/third_party/blink/renderer/platform/encrypted_media_request.h +++ b/third_party/blink/renderer/platform/encrypted_media_request.h
@@ -5,6 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_ENCRYPTED_MEDIA_REQUEST_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_ENCRYPTED_MEDIA_REQUEST_H_ +#include <memory> + #include "third_party/blink/renderer/platform/heap/handle.h" namespace blink { @@ -27,7 +29,8 @@ virtual const SecurityOrigin* GetSecurityOrigin() const = 0; - virtual void RequestSucceeded(WebContentDecryptionModuleAccess*) = 0; + virtual void RequestSucceeded( + std::unique_ptr<WebContentDecryptionModuleAccess>) = 0; virtual void RequestNotSupported(const WebString& error_message) = 0; virtual void Trace(blink::Visitor* visitor) {}
diff --git a/third_party/blink/renderer/platform/exported/web_encrypted_media_request.cc b/third_party/blink/renderer/platform/exported/web_encrypted_media_request.cc index 470722c..e0a066e 100644 --- a/third_party/blink/renderer/platform/exported/web_encrypted_media_request.cc +++ b/third_party/blink/renderer/platform/exported/web_encrypted_media_request.cc
@@ -40,8 +40,8 @@ } void WebEncryptedMediaRequest::RequestSucceeded( - WebContentDecryptionModuleAccess* access) { - private_->RequestSucceeded(access); + std::unique_ptr<WebContentDecryptionModuleAccess> access) { + private_->RequestSucceeded(std::move(access)); } void WebEncryptedMediaRequest::RequestNotSupported(
diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc index 6133e01..cd3399c 100644 --- a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc +++ b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc
@@ -138,6 +138,31 @@ return data.size() >= kLongestSignatureLength; } +// static +String ImageDecoder::SniffImageType(scoped_refptr<SharedBuffer> image_data) { + // Access the first kLongestSignatureLength chars to sniff the signature. + // (note: FastSharedBufferReader only makes a copy if the bytes are segmented) + char buffer[kLongestSignatureLength]; + const FastSharedBufferReader fast_reader( + SegmentReader::CreateFromSharedBuffer(std::move(image_data))); + const char* contents = + fast_reader.GetConsecutiveData(0, kLongestSignatureLength, buffer); + + if (MatchesJPEGSignature(contents)) + return "image/jpeg"; + if (MatchesPNGSignature(contents)) + return "image/png"; + if (MatchesGIFSignature(contents)) + return "image/gif"; + if (MatchesWebPSignature(contents)) + return "image/webp"; + if (MatchesICOSignature(contents) || MatchesCURSignature(contents)) + return "image/x-icon"; + if (MatchesBMPSignature(contents)) + return "image/bmp"; + return String(); +} + size_t ImageDecoder::FrameCount() { const size_t old_size = frame_buffer_cache_.size(); const size_t new_size = DecodeFrameCount();
diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder.h b/third_party/blink/renderer/platform/image-decoders/image_decoder.h index bbb221c8..56488d7a 100644 --- a/third_party/blink/renderer/platform/image-decoders/image_decoder.h +++ b/third_party/blink/renderer/platform/image-decoders/image_decoder.h
@@ -168,6 +168,9 @@ // failure is due to insufficient or bad data. static bool HasSufficientDataToSniffImageType(const SharedBuffer&); + // Looks at the image data to determine and return the image MIME type. + static String SniffImageType(scoped_refptr<SharedBuffer> image_data); + void SetData(scoped_refptr<SegmentReader> data, bool all_data_received) { if (failed_) return;
diff --git a/third_party/blink/renderer/platform/weborigin/known_ports.cc b/third_party/blink/renderer/platform/weborigin/known_ports.cc index 609b35a..5cf7ba7 100644 --- a/third_party/blink/renderer/platform/weborigin/known_ports.cc +++ b/third_party/blink/renderer/platform/weborigin/known_ports.cc
@@ -79,7 +79,7 @@ if (!effective_port) effective_port = DefaultPortForProtocol(protocol); StringUTF8Adaptor utf8(protocol); - return net::IsPortAllowedForScheme(effective_port, utf8.AsStdString()); + return net::IsPortAllowedForScheme(effective_port, utf8.AsStringPiece()); } } // namespace blink
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 6d231b94..dc2a98d9 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -6063,6 +6063,7 @@ crbug.com/937416 http/tests/devtools/resource-tree/resource-tree-frame-navigate.js [ Pass Failure ] crbug.com/937416 virtual/nobinary-for-devtools/http/tests/devtools/resource-tree/resource-tree-frame-navigate.js [ Pass Failure ] crbug.com/937546 [ Win7 ] http/tests/security/xss-DENIED-cross-origin-stack-overflow.html [ Pass Timeout ] +crbug.com/937546 [ Win7 ] virtual/outofblink-cors/http/tests/security/xss-DENIED-cross-origin-stack-overflow.html [ Pass Timeout ] # Sheriff 2019-03-02 crbug.com/937639 [ Linux Debug ] external/wpt/html/browsers/browsing-the-web/read-media/pageload-image-in-popup.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 552c4c70..62792d4 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -482,13 +482,8 @@ }, { "prefix": "dark-mode", - "base": "paint/dark-mode/native-theme-off", - "args": ["--blink-settings=darkMode=3"] - }, - { - "prefix": "dark-mode", - "base": "paint/dark-mode/native-theme-on", - "args": ["--blink-settings=darkMode=3"] + "base": "paint/dark-mode/svg-invert-all", + "args": ["--blink-settings=darkMode=3,darkModeImagePolicy=0"] }, { "prefix": "outofblink-cors",
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json index e07cff4..ba86f88 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -159811,6 +159811,11 @@ {} ] ], + "dom/events/EventTarget-dispatchEvent-expected.txt": [ + [ + {} + ] + ], "dom/events/event-global-extra.window-expected.txt": [ [ {} @@ -199896,11 +199901,6 @@ {} ] ], - "webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt": [ - [ - {} - ] - ], "webrtc/RTCPeerConnection-setDescription-transceiver-expected.txt": [ [ {} @@ -407757,12 +407757,16 @@ "b0e7614e625b3de018eb76c90148c7710b6c807f", "testharness" ], + "dom/events/EventTarget-dispatchEvent-expected.txt": [ + "625adecb9f4c0c5700e99243c5be7fa6bbabb71a", + "support" + ], "dom/events/EventTarget-dispatchEvent-returnvalue.html": [ "c4466e0d6cdada90be82a95a208c1ee025cfb96a", "testharness" ], "dom/events/EventTarget-dispatchEvent.html": [ - "1a8bf3de915d5cb8c608ecdef69511d4dbffe113", + "8a0d7353bc62ba8330069fef4c71a0e33321b0aa", "testharness" ], "dom/events/EventTarget-removeEventListener.html": [ @@ -430042,11 +430046,11 @@ "testharness" ], "html/semantics/forms/textfieldselection/selection-start-end-extra-expected.txt": [ - "b2174bf856c36ffa08037200b5ee884d6fc5f60d", + "953645a241941b237fd639992f26e9db8ee9dc43", "support" ], "html/semantics/forms/textfieldselection/selection-start-end-extra.html": [ - "af51354035c5cae33d35cbff03e2eed5d5359f85", + "e76f5f6ea70c2ba769fe6a75e9aa1c95d98e2760", "testharness" ], "html/semantics/forms/textfieldselection/selection-start-end.html": [ @@ -475758,7 +475762,7 @@ "support" ], "url/resources/urltestdata.json": [ - "26b8ea2e0bc9a166deef8af1a0df87e0a7e0fda4", + "bf4e2a7833d17fab604eb634051e627887fe936a", "support" ], "url/toascii.window-expected.txt": [ @@ -480425,12 +480429,8 @@ "2fd33ca541148ca6a7be5f5624e303795c7c458d", "testharness" ], - "webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt": [ - "62c3abf9a08a1fcbc0c5454a5b417ea4c85623e3", - "support" - ], "webrtc/RTCPeerConnection-onnegotiationneeded.html": [ - "f7bf8bd3e3bdc24c63a92da22eaae77b95f0d4fd", + "336b100de058200ab49400fac9ae00f8524b9da9", "testharness" ], "webrtc/RTCPeerConnection-onsignalingstatechanged.https.html": [
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/stateful-animator.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/stateful-animator.https.html new file mode 100644 index 0000000..c4b6301 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/stateful-animator.https.html
@@ -0,0 +1,162 @@ +<!DOCTYPE html> +<title>Basic use of stateful animator</title> +<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/web-animations/testcommon.js"></script> +<script src="common.js"></script> + +<div id="target"></div> + +<script id="stateful_animator_basic" type="text/worklet"> + registerAnimator("stateful_animator_basic", class { + constructor(options, state = { test_local_time: 0 }) { + this.test_local_time = state.test_local_time; + } + animate(currentTime, effect) { + effect.localTime = this.test_local_time++; + } + state() { + return { + test_local_time: this.test_local_time + }; + } + }); +</script> + +<script id="stateless_animator_basic" type="text/worklet"> + registerAnimator("stateless_animator_basic", class { + constructor(options, state = { test_local_time: 0 }) { + this.test_local_time = state.test_local_time; + } + animate(currentTime, effect) { + effect.localTime = this.test_local_time++; + } + // Unless a valid state function is provided, the animator is considered + // stateless. e.g. animator with incorrect state function name. + State() { + return { + test_local_time: this.test_local_time + }; + } + }); +</script> + +<script id="state_function_returns_empty" type="text/worklet"> + registerAnimator("state_function_returns_empty", class { + constructor(options, state = { test_local_time: 0 }) { + this.test_local_time = state.test_local_time; + } + animate(currentTime, effect) { + effect.localTime = this.test_local_time++; + } + state() {} + }); +</script> + +<script id="state_function_returns_not_serializable" type="text/worklet"> + registerAnimator("state_function_returns_not_serializable", class { + constructor(options) { + this.test_local_time = 0; + } + animate(currentTime, effect) { + effect.localTime = this.test_local_time++; + } + state() { + return new Error('foo'); + } + }); +</script> + +<script> + async function localTimeDoesNotUpdate(animation) { + // The local time stops increasing after the animator instance being dropped. + // e.g. 0, 1, 2, .., n, n, n, n, .. where n is the frame that the global + // scope switches at. + let last_local_time = animation.effect.getComputedTiming().localTime; + let frame_count = 0; + const FRAMES_WITHOUT_CHANGE = 10; + do { + await new Promise(window.requestAnimationFrame); + let current_local_time = animation.effect.getComputedTiming().localTime; + if (last_local_time == current_local_time) + ++frame_count; + else + frame_count = 0; + last_local_time = current_local_time; + } while (frame_count < FRAMES_WITHOUT_CHANGE); + } + + async function localTimeResetsToZero(animation) { + // The local time is reset upon global scope switching. e.g. + // 0, 1, 2, .., 0, 1, 2, .., 0, 1, 2, .., 0, 1, 2, ... + let reset_count = 0; + const LOCAL_TIME_RESET_CHECK = 3; + do { + await new Promise(window.requestAnimationFrame); + if (0 == animation.effect.getComputedTiming().localTime) + ++reset_count; + } while (reset_count < LOCAL_TIME_RESET_CHECK); + } + + promise_test(async t => { + await runInAnimationWorklet(document.getElementById('stateful_animator_basic').textContent); + const target = document.getElementById('target'); + const effect = new KeyframeEffect(target, [{ opacity: 0 }], { duration: 1000 }); + const animation = new WorkletAnimation('stateful_animator_basic', effect); + animation.play(); + + // effect.localTime should be correctly increased upon global scope + // switches for stateful animators. + const EXPECTED_FRAMES_TO_A_SCOPE_SWITCH = 15; + await waitForAnimationFrameWithCondition(_ => { + return animation.effect.getComputedTiming().localTime == + EXPECTED_FRAMES_TO_A_SCOPE_SWITCH; + }); + + animation.cancel(); + }, "Stateful animator can use its state to update the animation. Pass if test does not timeout"); + + promise_test(async t => { + await runInAnimationWorklet(document.getElementById('stateless_animator_basic').textContent); + const target = document.getElementById('target'); + const effect = new KeyframeEffect(target, [{ opacity: 0 }], { duration: 1000 }); + const animation = new WorkletAnimation('stateless_animator_basic', effect); + animation.play(); + + // The local time should be reset to 0 upon global scope switching for + // stateless animators. + await localTimeResetsToZero(animation); + + animation.cancel(); + }, "Stateless animator gets reecreated with 'undefined' state."); + + promise_test(async t => { + await runInAnimationWorklet(document.getElementById('state_function_returns_empty').textContent); + const target = document.getElementById('target'); + const effect = new KeyframeEffect(target, [{ opacity: 0 }], { duration: 1000 }); + const animation = new WorkletAnimation('state_function_returns_empty', effect); + animation.play(); + + // The local time should be reset to 0 upon global scope switching for + // stateless animators. + await localTimeResetsToZero(animation); + + animation.cancel(); + }, "Stateful animator gets recreated with 'undefined' state if state function returns undefined."); + + promise_test(async t => { + await runInAnimationWorklet(document.getElementById('state_function_returns_not_serializable').textContent); + const target = document.getElementById('target'); + const effect = new KeyframeEffect(target, [{ opacity: 0 }], { duration: 1000, iteration: Infinity }); + const animation = new WorkletAnimation('state_function_returns_not_serializable', effect); + animation.play(); + + // The local time of an animation increases until the registered animator + // gets removed. + await localTimeDoesNotUpdate(animation); + + animation.cancel(); + }, "Stateful Animator instance gets dropped (does not get migrated) if state function is not serializable."); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/EventTarget-dispatchEvent-expected.txt b/third_party/blink/web_tests/external/wpt/dom/events/EventTarget-dispatchEvent-expected.txt new file mode 100644 index 0000000..625adecb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/dom/events/EventTarget-dispatchEvent-expected.txt
@@ -0,0 +1,29 @@ +This is a testharness.js-based test. +PASS Calling dispatchEvent(null). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (BeforeUnloadEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (CompositionEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (CustomEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (DeviceMotionEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (DeviceOrientationEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (DragEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (Event). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (Events). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (FocusEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (HashChangeEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (HTMLEvents). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (KeyboardEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (MessageEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (MouseEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (MouseEvents). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (StorageEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (SVGEvents). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (TextEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (TouchEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (UIEvent). +PASS If the event's initialized flag is not set, an InvalidStateError must be thrown (UIEvents). +PASS If the event's dispatch flag is set, an InvalidStateError must be thrown. +PASS Exceptions from event listeners must not be propagated. +PASS Event listeners added during dispatch should be called +FAIL Capturing event listeners should be called before non-capturing ones assert_array_equals: property 1, expected 3 but got 2 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/EventTarget-dispatchEvent.html b/third_party/blink/web_tests/external/wpt/dom/events/EventTarget-dispatchEvent.html index 1a8bf3d..8a0d735 100644 --- a/third_party/blink/web_tests/external/wpt/dom/events/EventTarget-dispatchEvent.html +++ b/third_party/blink/web_tests/external/wpt/dom/events/EventTarget-dispatchEvent.html
@@ -98,7 +98,7 @@ results.push(3) }), true) b.dispatchEvent(new Event("x")) - assert_array_equals(results, [1, 2, 3]) + assert_array_equals(results, [1, 3, 2]) this.done() -}, "Event listeners should be called in order of addition") +}, "Capturing event listeners should be called before non-capturing ones") </script>
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters-inf.html b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters-inf.html new file mode 100644 index 0000000..db21427 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters-inf.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>Test oversized-images policy with threshold 'inf'</title> +</head> +<body> + <!-- The sample image has an intrinsic image size of 200x200px --> + <img src="resources/sample-1.png" width="200" height="200"> + <img src="resources/sample-1.png" width="100" height="200"> + <img src="resources/sample-1.png" width="50" height="200"> + <br> + <img src="resources/sample-1.png" width="200" height="100"> + <img src="resources/sample-1.png" width="100" height="100"> + <img src="resources/sample-1.png" width="50" height="100"> + <br> + <img src="resources/sample-1.png" width="200" height="50"> + <img src="resources/sample-1.png" width="100" height="50"> + <img src="resources/sample-1.png" width="50" height="50"> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters-inf.html.headers b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters-inf.html.headers new file mode 100644 index 0000000..1ec0034 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters-inf.html.headers
@@ -0,0 +1 @@ +Feature-Policy: oversized-images (inf)
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters-with-frames.html b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters-with-frames.html new file mode 100644 index 0000000..de0a3ab1e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters-with-frames.html
@@ -0,0 +1,44 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/feature-policy/resources/featurepolicy.js"></script> + <title>Test oversized-images policy with threshold 1.5</title> +</head> +<body> + <iframe scrolling="no" name="a" style="overflow:hidden" width="380" height="220"></iframe> + <iframe scrolling="no" name="b" style="overflow:hidden" width="380" height="220"></iframe> + <iframe scrolling="no" name="c" style="overflow:hidden" width="380" height="220"></iframe> + <iframe scrolling="no" name="d" style="overflow:hidden" width="380" height="220"></iframe> + <iframe scrolling="no" name="e" style="overflow:hidden" width="380" height="220"></iframe> + + <script> + const frame_to_test_map = {}; + window.addEventListener('message', ev => { + if (ev.data.type == "finished") { + if (frame_to_test_map.hasOwnProperty(ev.data.name)) { + frame_to_test_map[ev.data.name].done(); + } + } + }); + const config = { + a: {threshold: 0.0, blocked: 3}, + b: {threshold: 1.0, blocked: 2}, + c: {threshold: 2.5, blocked: 1}, + d: {threshold: 4.0, blocked: 0}, + e: {threshold: "inf", blocked: 0} + }; + const iframes = document.querySelectorAll('iframe'); + const total_iframes = iframes.length; + iframes.forEach(iframe => { + const frame_config = config[iframe.name] + async_test(t => { + frame_to_test_map[iframe.name] = t; + iframe.src = "resources/feature-parameters-frame.html?name="+iframe.name+"&n="+frame_config.blocked+"&pipe=header(Feature-Policy,oversized-images%20("+frame_config.threshold+"\\);)"; + }, "Test frame with threshold " + frame_config.threshold + " should block " + frame_config.blocked + " images."); + }); + </script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters.html b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters.html new file mode 100644 index 0000000..9830f93e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/feature-policy/resources/featurepolicy.js"></script> + <title>Test oversized-images policy with threshold 1.5</title> +</head> +<body> + <!-- The sample image has an intrinsic image size of 200x200px --> + <img src="resources/sample-1.png" width="200" height="200"> + <img src="resources/sample-1.png" width="100" height="200"> + <img src="resources/sample-1.png" width="50" height="200"> + <br> + <img src="resources/sample-1.png" width="200" height="100"> + <img src="resources/sample-1.png" width="100" height="100"> + <img src="resources/sample-1.png" width="50" height="100"> + <br> + <img src="resources/sample-1.png" width="200" height="50"> + <img src="resources/sample-1.png" width="100" height="50"> + <img src="resources/sample-1.png" width="50" height="50"> + + <script> + expect_reports(8, "oversized-images", "8 images should be blocked by policy"); + </script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters.html.headers b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters.html.headers new file mode 100644 index 0000000..b4fa805 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/feature-parameters.html.headers
@@ -0,0 +1 @@ +Feature-Policy: oversized-images (1.5)
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/parameters/resources/feature-parameters-frame.html b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/resources/feature-parameters-frame.html new file mode 100644 index 0000000..4f01f85 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/resources/feature-parameters-frame.html
@@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/feature-policy/resources/featurepolicy.js"></script> + <title>Test oversized-images policy in subframe</title> +</head> +<body> + <!-- The sample image has an intrinsic image size of 200x200px --> + <img width="200" height="200"> + <img width="100" height="200"> + <img width="50" height="200"> + + <script> + const policy_name = "oversized-images"; + const params = new URLSearchParams(document.location.search); + const frame_name = params.get('name'); + const expected_report_count = +params.get('n'); + var num_received_reports = 0; + + const images = document.querySelectorAll('img'); + const total_images = images.length; + var images_loaded = 0; + + const notifyIfDone = () => { + if (num_received_reports >= expected_report_count && + images_loaded == total_images) { + parent.postMessage({ + "type": "finished", + "name": frame_name + },"*"); + } + }; + + images.forEach(image => { + image.addEventListener('load', () => { images_loaded++; notifyIfDone(); }); + image.src = "sample-1.png"; + }); + + new ReportingObserver((reports, observer) => { + const relevant_reports = reports.filter(r => (r.body.featureId === policy_name)); + num_received_reports += relevant_reports.length; + notifyIfDone(); + }, {types: ['feature-policy-violation'], buffered: true}).observe(); + </script> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/parameters/resources/sample-1.png b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/resources/sample-1.png new file mode 100644 index 0000000..92901925 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/feature-policy/parameters/resources/sample-1.png Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/resources/featurepolicy.js b/third_party/blink/web_tests/external/wpt/feature-policy/resources/featurepolicy.js index e2577f3..744c4c6 100644 --- a/third_party/blink/web_tests/external/wpt/feature-policy/resources/featurepolicy.js +++ b/third_party/blink/web_tests/external/wpt/feature-policy/resources/featurepolicy.js
@@ -433,3 +433,16 @@ assert_false(frame_policy.allowedFeatures().includes(feature)); } } + +function expect_reports(report_count, policy_name, description) { + async_test(t => { + var num_received_reports = 0; + new ReportingObserver(t.step_func((reports, observer) => { + const relevant_reports = reports.filter(r => (r.body.featureId === policy_name)); + num_received_reports += relevant_reports.length; + if (num_received_reports >= report_count) { + t.done(); + } + }), {types: ['feature-policy-violation'], buffered: true}).observe(); + }, description); +}
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/textfieldselection/selection-start-end-extra-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/forms/textfieldselection/selection-start-end-extra-expected.txt index b2174bf..953645a 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/textfieldselection/selection-start-end-extra-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/textfieldselection/selection-start-end-extra-expected.txt
@@ -4,10 +4,11 @@ PASS Setting textContent in a textarea should move selection{Start,End} to the end PASS Adding children to a textarea should move selection{Start,End} to the end PASS Removing children from a textarea should update selection{Start,End} -FAIL Setting the same value (with different newlines) in a textarea should NOT update selection{Start,End} assert_equals: expected 3 but got 14 +PASS Setting the same value (with different newlines) in a textarea should NOT update selection{Start,End} +FAIL Removing child nodes in non-dirty textarea should make selection{Start,End} 0 assert_equals: selectionStart after appendChild expected 0 but got 6 PASS Setting value to a shorter string than defaultValue should correct the cursor position PASS Shortening value by turning the input type into 'url' should correct selection{Start,End} -FAIL Shortening value by turning the input type into 'color' and back to 'text' should correct selection{Start,End} assert_equals: expected 7 but got 9 +FAIL Shortening value by turning the input type into 'color' and back to 'text' should correct selection{Start,End} assert_equals: expected 0 but got 9 PASS Resetting a value to a shorter string than defaultValue should correct the cursor position Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/textfieldselection/selection-start-end-extra.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/textfieldselection/selection-start-end-extra.html index af51354..e76f5f6 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/textfieldselection/selection-start-end-extra.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/textfieldselection/selection-start-end-extra.html
@@ -69,13 +69,39 @@ el.selectionStart = 3; el.selectionEnd = 5; - el.textContent = "abcdef\r\nwhatevs"; + el.firstChild.data = "abcdef\r\nwhatevs"; assert_equals(el.selectionStart, 3); assert_equals(el.selectionEnd, 5); }, "Setting the same value (with different newlines) in a textarea should NOT update selection{Start,End}"); test(function() { var el = document.createElement("textarea"); + el.textContent = "foobar"; + el.selectionStart = 3; + el.selectionEnd = 5; + el.firstChild.remove(); + assert_equals(el.selectionStart, 0, 'selectionStart after node removal'); + assert_equals(el.selectionEnd, 0, 'selectionEnd after node removal'); + el.appendChild(document.createTextNode("foobar")); + assert_equals(el.selectionStart, 0, 'selectionStart after appendChild'); + assert_equals(el.selectionEnd, 0, 'selectionEnd after appendChild'); + + el.selectionStart = 3; + el.selectionEnd = 5; + el.textContent = "foobar2"; // This removes the child node first. + assert_equals(el.selectionStart, 0, 'selectionStart after textContent setter'); + assert_equals(el.selectionEnd, 0, 'selectionEnd after textContent setter'); + + el.selectionStart = 3; + el.selectionEnd = 5; + el.defaultValue = "foobar"; // Same as textContent setter. + assert_equals(el.selectionStart, 0, 'selectionStart after defaultValue setter'); + assert_equals(el.selectionEnd, 0, 'selectionEnd after defaultValue setter'); + + }, "Removing child nodes in non-dirty textarea should make selection{Start,End} 0"); + + test(function() { + var el = document.createElement("textarea"); el.defaultValue = "123"; assert_equals(el.value.length, 3); assert_equals(el.selectionStart, 3); @@ -105,8 +131,12 @@ assert_equals(el.selectionEnd, 9); el.type = "color"; el.type = "text"; - assert_equals(el.selectionStart, 7); - assert_equals(el.selectionEnd, 7); + // https://html.spec.whatwg.org/C/input.html#the-input-element:attr-input-type-15 + // 9. If previouslySelectable is false and nowSelectable is true, set the + // element's text entry cursor position to the beginning of the text + // control, ... + assert_equals(el.selectionStart, 0); + assert_equals(el.selectionEnd, 0); }, "Shortening value by turning the input type into 'color' and back to 'text' should correct selection{Start,End}"); test(function() {
diff --git a/third_party/blink/web_tests/flag-specific/disable-perfetto/inspector-protocol/timeline/tracing-proto-format-expected.txt b/third_party/blink/web_tests/flag-specific/disable-perfetto/inspector-protocol/timeline/tracing-proto-format-expected.txt new file mode 100644 index 0000000..e1a7e53 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-perfetto/inspector-protocol/timeline/tracing-proto-format-expected.txt
@@ -0,0 +1,3 @@ +Tests that tracing with proto format outputs something resembling protos. +Start failed: Proto format is only supported with the perfetto backend. +
diff --git a/third_party/blink/web_tests/http/tests/resources/slow-notify-done.php b/third_party/blink/web_tests/http/tests/resources/slow-notify-done.php index 08d7d4a..1df013ef 100644 --- a/third_party/blink/web_tests/http/tests/resources/slow-notify-done.php +++ b/third_party/blink/web_tests/http/tests/resources/slow-notify-done.php
@@ -1,5 +1,5 @@ <?php -usleep(1000000); +usleep(100000); ?> DONE! <script>
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 5a77993..65977c53 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1257,6 +1257,9 @@ getter readable getter writable method constructor +interface TrustedTypePolicyFactory + attribute @@toStringTag + method constructor interface URL attribute @@toStringTag getter hash
diff --git a/third_party/blink/web_tests/inspector-protocol/timeline/tracing-proto-format-expected.txt b/third_party/blink/web_tests/inspector-protocol/timeline/tracing-proto-format-expected.txt new file mode 100644 index 0000000..22ca095 --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/timeline/tracing-proto-format-expected.txt
@@ -0,0 +1,4 @@ +Tests that tracing with proto format outputs something resembling protos. +Tracing complete +First byte: 10 +
diff --git a/third_party/blink/web_tests/inspector-protocol/timeline/tracing-proto-format.js b/third_party/blink/web_tests/inspector-protocol/timeline/tracing-proto-format.js new file mode 100644 index 0000000..ac2e8990 --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/timeline/tracing-proto-format.js
@@ -0,0 +1,21 @@ +(async function(testRunner) { + const {page, session, dp} = await testRunner.startBlank( + `Tests that tracing with proto format outputs something resembling protos.`); + + const TracingHelper = await testRunner.loadScript('../resources/tracing-test.js'); + const tracingHelper = new TracingHelper(testRunner, session); + + const startResponse = await dp.Tracing.start( + {transferMode: 'ReturnAsStream', streamFormat: 'proto'}); + if (startResponse.error) { + testRunner.log('Start failed: ' + startResponse.error.message); + testRunner.completeTest(); + return; + } + + const stream = await tracingHelper.stopTracingAndReturnStream(); + const data = await tracingHelper.retrieveStream(stream, null, null); + // First byte should be TracePacket field ID preamble (byte value 10). + testRunner.log('First byte: ' + data.charCodeAt(0)); + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/paint/dark-mode/native-theme-off/text-input-elements.html b/third_party/blink/web_tests/paint/dark-mode/native-theme-off/text-input-elements.html deleted file mode 100644 index 846b0912f..0000000 --- a/third_party/blink/web_tests/paint/dark-mode/native-theme-off/text-input-elements.html +++ /dev/null
@@ -1 +0,0 @@ -<input style="border-width: thick"><textarea style="border-width: thick"></textarea>
diff --git a/third_party/blink/web_tests/paint/dark-mode/native-theme-on/text-input-elements.html b/third_party/blink/web_tests/paint/dark-mode/native-theme-on/text-input-elements.html deleted file mode 100644 index f2e3d4c..0000000 --- a/third_party/blink/web_tests/paint/dark-mode/native-theme-on/text-input-elements.html +++ /dev/null
@@ -1 +0,0 @@ -<input><textarea></textarea>
diff --git a/third_party/blink/web_tests/paint/dark-mode/svg-invert-all/resources/circle.svg b/third_party/blink/web_tests/paint/dark-mode/svg-invert-all/resources/circle.svg new file mode 100644 index 0000000..7dcc595 --- /dev/null +++ b/third_party/blink/web_tests/paint/dark-mode/svg-invert-all/resources/circle.svg
@@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 100 100"> + <circle cx="50" cy="50" r="40" stroke="black" stroke-width="2" fill="white" /> +</svg>
diff --git a/third_party/blink/web_tests/paint/dark-mode/svg-invert-all/svg-as-image.html b/third_party/blink/web_tests/paint/dark-mode/svg-invert-all/svg-as-image.html new file mode 100644 index 0000000..21c0f06 --- /dev/null +++ b/third_party/blink/web_tests/paint/dark-mode/svg-invert-all/svg-as-image.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<img src="resources/circle.svg" />
diff --git a/third_party/blink/web_tests/paint/dark-mode/svg-invert-all/svg-in-html.html b/third_party/blink/web_tests/paint/dark-mode/svg-invert-all/svg-in-html.html new file mode 100644 index 0000000..c51e435 --- /dev/null +++ b/third_party/blink/web_tests/paint/dark-mode/svg-invert-all/svg-in-html.html
@@ -0,0 +1,4 @@ +<!DOCTYPE html> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 100 100"> + <circle cx="50" cy="50" r="40" stroke="black" stroke-width="2" fill="white" /> +</svg>
diff --git a/third_party/blink/web_tests/platform/linux/paint/dark-mode/native-theme-off/text-input-elements-expected.png b/third_party/blink/web_tests/platform/linux/paint/dark-mode/native-theme-off/text-input-elements-expected.png deleted file mode 100644 index 9adc149..0000000 --- a/third_party/blink/web_tests/platform/linux/paint/dark-mode/native-theme-off/text-input-elements-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/dark-mode/native-theme-on/text-input-elements-expected.png b/third_party/blink/web_tests/platform/linux/paint/dark-mode/native-theme-on/text-input-elements-expected.png deleted file mode 100644 index 8315438..0000000 --- a/third_party/blink/web_tests/platform/linux/paint/dark-mode/native-theme-on/text-input-elements-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png deleted file mode 100644 index 0e3e22f0..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png deleted file mode 100644 index 310a6f2..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/dark-mode/native-theme-off/text-input-elements-expected.png b/third_party/blink/web_tests/platform/mac/paint/dark-mode/native-theme-off/text-input-elements-expected.png deleted file mode 100644 index 0d5bd5a..0000000 --- a/third_party/blink/web_tests/platform/mac/paint/dark-mode/native-theme-off/text-input-elements-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/dark-mode/native-theme-on/text-input-elements-expected.png b/third_party/blink/web_tests/platform/mac/paint/dark-mode/native-theme-on/text-input-elements-expected.png deleted file mode 100644 index b71efac..0000000 --- a/third_party/blink/web_tests/platform/mac/paint/dark-mode/native-theme-on/text-input-elements-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/dark-mode/svg-invert-all/svg-as-image-expected.png b/third_party/blink/web_tests/platform/mac/paint/dark-mode/svg-invert-all/svg-as-image-expected.png new file mode 100644 index 0000000..b64980e --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/paint/dark-mode/svg-invert-all/svg-as-image-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/dark-mode/svg-invert-all/svg-in-html-expected.png b/third_party/blink/web_tests/platform/mac/paint/dark-mode/svg-invert-all/svg-in-html-expected.png new file mode 100644 index 0000000..b64980e --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/paint/dark-mode/svg-invert-all/svg-in-html-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png deleted file mode 100644 index 8dd35947..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png deleted file mode 100644 index 80b2276..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/svg-invert-all/svg-as-image-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/svg-invert-all/svg-as-image-expected.png new file mode 100644 index 0000000..fe6af93 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/svg-invert-all/svg-as-image-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/svg-invert-all/svg-in-html-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/svg-invert-all/svg-in-html-expected.png new file mode 100644 index 0000000..93ae99c0 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/svg-invert-all/svg-in-html-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/dark-mode/native-theme-off/text-input-elements-expected.png b/third_party/blink/web_tests/platform/win/paint/dark-mode/native-theme-off/text-input-elements-expected.png deleted file mode 100644 index 67a425c..0000000 --- a/third_party/blink/web_tests/platform/win/paint/dark-mode/native-theme-off/text-input-elements-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/dark-mode/native-theme-on/text-input-elements-expected.png b/third_party/blink/web_tests/platform/win/paint/dark-mode/native-theme-on/text-input-elements-expected.png deleted file mode 100644 index c52b4fd..0000000 --- a/third_party/blink/web_tests/platform/win/paint/dark-mode/native-theme-on/text-input-elements-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/dark-mode/svg-invert-all/svg-as-image-expected.png b/third_party/blink/web_tests/platform/win/paint/dark-mode/svg-invert-all/svg-as-image-expected.png new file mode 100644 index 0000000..89592fe --- /dev/null +++ b/third_party/blink/web_tests/platform/win/paint/dark-mode/svg-invert-all/svg-as-image-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/dark-mode/svg-invert-all/svg-in-html-expected.png b/third_party/blink/web_tests/platform/win/paint/dark-mode/svg-invert-all/svg-in-html-expected.png new file mode 100644 index 0000000..89592fe --- /dev/null +++ b/third_party/blink/web_tests/platform/win/paint/dark-mode/svg-invert-all/svg-in-html-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png deleted file mode 100644 index 5b4aadf..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png deleted file mode 100644 index 8257781..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/svg-invert-all/svg-as-image-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/svg-invert-all/svg-as-image-expected.png new file mode 100644 index 0000000..c4a10d1f --- /dev/null +++ b/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/svg-invert-all/svg-as-image-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/svg-invert-all/svg-in-html-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/svg-invert-all/svg-in-html-expected.png new file mode 100644 index 0000000..839dc5d1 --- /dev/null +++ b/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/svg-invert-all/svg-in-html-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/native-theme-on/README.txt b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/native-theme-on/README.txt deleted file mode 100644 index cb49f2e..0000000 --- a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/native-theme-on/README.txt +++ /dev/null
@@ -1,3 +0,0 @@ -# This suite runs the tests in LayoutTests/paint/dark-mode -# with --blink-settings="darkMode=3" -# See the virtual_test_suites() method in tools/blinkpy/web_tests/port/base.py.
diff --git a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/native-theme-off/README.txt b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/svg-invert-all/README.txt similarity index 70% rename from third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/native-theme-off/README.txt rename to third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/svg-invert-all/README.txt index cb49f2e..a656a64d 100644 --- a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/native-theme-off/README.txt +++ b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/svg-invert-all/README.txt
@@ -1,3 +1,3 @@ # This suite runs the tests in LayoutTests/paint/dark-mode -# with --blink-settings="darkMode=3" +# with --blink-settings="darkMode=3,darkModeImagePolicy=0" # See the virtual_test_suites() method in tools/blinkpy/web_tests/port/base.py.
diff --git a/third_party/cacheinvalidation/src/google/cacheinvalidation/BUILD.gn b/third_party/cacheinvalidation/src/google/cacheinvalidation/BUILD.gn index fc92fb5..3bbb844 100644 --- a/third_party/cacheinvalidation/src/google/cacheinvalidation/BUILD.gn +++ b/third_party/cacheinvalidation/src/google/cacheinvalidation/BUILD.gn
@@ -23,6 +23,5 @@ ] } - proto_out_dir = "$target_gen_dir/google/cacheinvalidation" - public_include_dirs = [ target_gen_dir ] + proto_out_dir = "google/cacheinvalidation" }
diff --git a/third_party/crc32c/BUILD.gn b/third_party/crc32c/BUILD.gn index 963a3c08..db9f98d 100644 --- a/third_party/crc32c/BUILD.gn +++ b/third_party/crc32c/BUILD.gn
@@ -129,6 +129,8 @@ "-Xclang", "+crypto", ] + } else { + cflags = [ "-march=armv8-a+crc+crypto" ] } }
diff --git a/third_party/node/OWNERS b/third_party/node/OWNERS index 79ae090..ca467ff7f 100644 --- a/third_party/node/OWNERS +++ b/third_party/node/OWNERS
@@ -1,3 +1,2 @@ dbeam@chromium.org dpapad@chromium.org -scottchen@chromium.org
diff --git a/third_party/polymer/OWNERS b/third_party/polymer/OWNERS index cc0c2c7..0e971c4f 100644 --- a/third_party/polymer/OWNERS +++ b/third_party/polymer/OWNERS
@@ -1,4 +1,3 @@ dbeam@chromium.org dpapad@chromium.org michaelpg@chromium.org -scottchen@chromium.org
diff --git a/third_party/protobuf/proto_library.gni b/third_party/protobuf/proto_library.gni index 9798fd68..5c4ffa01 100644 --- a/third_party/protobuf/proto_library.gni +++ b/third_party/protobuf/proto_library.gni
@@ -16,8 +16,8 @@ # # proto_out_dir (optional) # Specifies the path suffix that output files are generated under. -# If a relative path is provided, it be appended to |root_gen_dir|. -# For python stubs it will be appended to |root_build_dir|/pyproto. +# This path will be appended to |root_gen_dir|, but for python stubs +# it will be appended to |root_build_dir|/pyproto. # # generate_python (optional, default true) # Generate Python protobuf stubs. @@ -98,9 +98,6 @@ # A list of config labels that will be removed from the configs apllying # to the source set. # -# public_include_dirs (optional) -# Add a public config with given include_dirs. -# # Example: # proto_library("mylib") { # sources = [ @@ -110,11 +107,6 @@ import("//build/config/sanitizers/sanitizers.gni") -declare_args() { - # TODO(agrieve): Remove arg after all offenders have been fixed. - allow_proto_library_outside_of_target_gen_dir = true -} - template("proto_library") { assert(defined(invoker.sources), "Need sources for proto_library") proto_sources = invoker.sources @@ -196,65 +188,22 @@ if (defined(invoker.proto_out_dir)) { proto_out_dir = invoker.proto_out_dir - - # TODO(agrieve): Remove special case once perfetto is updated. - # Note: Other perfetto paths already pass this check because - # get_path_info normalizes "a//b" -> "a/b". - proto_out_dir_is_abs = - proto_out_dir != "//third_party/perfetto/" && - get_path_info(proto_out_dir, "abspath") == proto_out_dir + } else { + # Absolute path to the directory of current BUILD.gn file excluding "//". + proto_out_dir = rebase_path(".", "//") + if (proto_in_dir != ".") { + proto_out_dir += "/$proto_in_dir" + } } # We need both absolute path to use in GN statements and a relative one # to pass to external script. if (generate_cc || generate_with_plugin) { - if (defined(proto_out_dir)) { - if (!proto_out_dir_is_abs) { - proto_out_dir = "$root_gen_dir/$proto_out_dir" - } - - if (!allow_proto_library_outside_of_target_gen_dir) { - # Use sources filter to test the prefix of proto_out_dir. - set_sources_assignment_filter([ - target_gen_dir, - "$target_gen_dir/*", - ]) - sources = [ - proto_out_dir, - ] - set_sources_assignment_filter([]) - if (sources != []) { - # TODO(agrieve): Change this to an assert. - print( - "proto_out_dir must be subdirectory of \$target_gen_dir (https://crbug.com/944928)") - print(" target_gen_dir=$target_gen_dir") - print(" proto_out_dir=$proto_out_dir") - sources = [] - } - } - - cc_out_dir = proto_out_dir - } else { - cc_out_dir = target_gen_dir - if (rebase_path(".", "//") != ".") { - cc_out_dir += "/$proto_in_dir" - } - } + cc_out_dir = "$root_gen_dir/" + proto_out_dir rel_cc_out_dir = rebase_path(cc_out_dir, root_build_dir) } if (generate_python) { - if (defined(proto_out_dir) && proto_out_dir_is_abs) { - py_out_dir = proto_out_dir - } else { - if (!defined(proto_out_dir)) { - # Absolute path to the directory of current BUILD.gn file excluding "//". - proto_out_dir = rebase_path(".", "//") - if (proto_in_dir != ".") { - proto_out_dir += "/$proto_in_dir" - } - } - py_out_dir = "$root_out_dir/pyproto/" + proto_out_dir - } + py_out_dir = "$root_out_dir/pyproto/" + proto_out_dir rel_py_out_dir = rebase_path(py_out_dir, root_build_dir) } @@ -283,7 +232,7 @@ } } - action_name = "${target_name}__gen" + action_name = "${target_name}_gen" source_set_name = target_name # Generate protobuf stubs. @@ -395,21 +344,15 @@ # use relative paths starting at |cc_out_dir|. # However there is no necessity to add an additional directory, if all protos # are located in the same directory which is in the search path by default. - if (has_nested_dirs || defined(invoker.import_dirs) || - defined(invoker.public_include_dirs)) { - config_name = "${target_name}__config" - config(config_name) { - include_dirs = [] - if (has_nested_dirs) { - include_dirs += [ cc_out_dir ] - } - if (defined(invoker.import_dirs)) { - foreach(path, invoker.import_dirs) { - include_dirs += [ "$root_gen_dir/" + rebase_path(path, "//") ] - } - } - if (defined(invoker.public_include_dirs)) { - include_dirs += invoker.public_include_dirs + config_name = "${target_name}_config" + config(config_name) { + include_dirs = [] + if (has_nested_dirs) { + include_dirs += [ cc_out_dir ] + } + if (defined(invoker.import_dirs)) { + foreach(path, invoker.import_dirs) { + include_dirs += [ "$root_gen_dir/" + rebase_path(path, "//") ] } } } @@ -444,7 +387,7 @@ if (generate_cc || generate_with_plugin) { # Not necessary if all protos are located in the same directory. - if (defined(config_name)) { + if (has_nested_dirs || defined(invoker.import_dirs)) { # It's not enough to set |include_dirs| for target since public imports # expose corresponding includes to header files as well. public_configs += [ ":$config_name" ]
diff --git a/third_party/unrar/README.chromium b/third_party/unrar/README.chromium index 8ef4d71..7782eec 100644 --- a/third_party/unrar/README.chromium +++ b/third_party/unrar/README.chromium
@@ -33,3 +33,6 @@ - Put all symbols into a namespace third_party_unrar to avoid polluting global namespace (add_namespaces.patch) - Remove unnecessary semicolons from header files (semicolons.patch) +- Fix a bug with NOVOLUME implementation (https://crbug.com/949787). This + should be temporary, until the fix can be pulled from upstream. + (fix_novolume.patch)
diff --git a/third_party/unrar/patches/fix_novolume.patch b/third_party/unrar/patches/fix_novolume.patch new file mode 100644 index 0000000..0074cc5 --- /dev/null +++ b/third_party/unrar/patches/fix_novolume.patch
@@ -0,0 +1,24 @@ +diff --git a/third_party/unrar/src/extract.cpp b/third_party/unrar/src/extract.cpp +index d33306d82dc8..209047e130aa 100644 +--- a/third_party/unrar/src/extract.cpp ++++ b/third_party/unrar/src/extract.cpp +@@ -270,15 +270,17 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) + { + if (Arc.EndArcHead.NextVolume) + { +-#ifndef NOVOLUME ++#ifdef NOOVLUME ++ return false; ++#else + if (!MergeArchive(Arc,&DataIO,false,Command)) + { + ErrHandler.SetErrorCode(RARX_WARNING); + return false; + } +-#endif + Arc.Seek(Arc.CurBlockPos,SEEK_SET); + return true; ++#endif + } + else + return false;
diff --git a/third_party/unrar/src/extract.cpp b/third_party/unrar/src/extract.cpp index d33306d8..209047e13 100644 --- a/third_party/unrar/src/extract.cpp +++ b/third_party/unrar/src/extract.cpp
@@ -270,15 +270,17 @@ { if (Arc.EndArcHead.NextVolume) { -#ifndef NOVOLUME +#ifdef NOOVLUME + return false; +#else if (!MergeArchive(Arc,&DataIO,false,Command)) { ErrHandler.SetErrorCode(RARX_WARNING); return false; } -#endif Arc.Seek(Arc.CurBlockPos,SEEK_SET); return true; +#endif } else return false;
diff --git a/third_party/webxr_test_pages/webxr-samples/360-photos.html b/third_party/webxr_test_pages/webxr-samples/360-photos.html index 9f8487f..2d933bf 100644 --- a/third_party/webxr_test_pages/webxr-samples/360-photos.html +++ b/third_party/webxr_test_pages/webxr-samples/360-photos.html
@@ -145,6 +145,16 @@ // solely on the device orientation. (As an added bonus this mode may // be more power efficient on some hardware!) session.requestReferenceSpace({ type: 'stationary', subtype: 'position-disabled' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else {
diff --git a/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html b/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html index 0f349ee44..8e396ae 100644 --- a/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html +++ b/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html
@@ -163,6 +163,16 @@ }); session.requestReferenceSpace({ type: 'stationary', subtype: 'eye-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else { @@ -225,7 +235,7 @@ // only when we resize for efficency. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); - // We're drawing with our own projection and view matrix now, and we + // We're drawing with our own projection and view matrix now, and we // don't have a list of view to loop through, but otherwise all of the // WebGL drawing logic is exactly the same. scene.draw(projectionMatrix, viewMatrix);
diff --git a/third_party/webxr_test_pages/webxr-samples/input-selection.html b/third_party/webxr_test_pages/webxr-samples/input-selection.html index 136b9dc9..0facbb28 100644 --- a/third_party/webxr_test_pages/webxr-samples/input-selection.html +++ b/third_party/webxr_test_pages/webxr-samples/input-selection.html
@@ -201,6 +201,16 @@ }); session.requestReferenceSpace({ type: 'stationary', subtype: 'floor-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else {
diff --git a/third_party/webxr_test_pages/webxr-samples/input-tracking.html b/third_party/webxr_test_pages/webxr-samples/input-tracking.html index efedc1d4..f27ad2f 100644 --- a/third_party/webxr_test_pages/webxr-samples/input-tracking.html +++ b/third_party/webxr_test_pages/webxr-samples/input-tracking.html
@@ -144,6 +144,16 @@ }); session.requestReferenceSpace({ type: 'stationary', subtype: 'floor-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else {
diff --git a/third_party/webxr_test_pages/webxr-samples/magic-window.html b/third_party/webxr_test_pages/webxr-samples/magic-window.html index 29a32fa..e743307 100644 --- a/third_party/webxr_test_pages/webxr-samples/magic-window.html +++ b/third_party/webxr_test_pages/webxr-samples/magic-window.html
@@ -137,6 +137,16 @@ }); session.requestReferenceSpace({ type: 'stationary', subtype: 'eye-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { // Since we're dealing with multple sessions now we need to track // which XRReferenceSpace is associated with which XRSession. if (session.mode.startsWith('immersive')) {
diff --git a/third_party/webxr_test_pages/webxr-samples/positional-audio.html b/third_party/webxr_test_pages/webxr-samples/positional-audio.html index b284250..2b94f87 100644 --- a/third_party/webxr_test_pages/webxr-samples/positional-audio.html +++ b/third_party/webxr_test_pages/webxr-samples/positional-audio.html
@@ -158,7 +158,7 @@ function createBufferSource(source, buffer, analyser) { // Create a buffer source. This will need to be recreated every time - // we wish to start the audio, see + // we wish to start the audio, see // https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode let bufferSource = audioContext.createBufferSource(); bufferSource.loop = true; @@ -362,6 +362,16 @@ }); session.requestReferenceSpace({ type: 'stationary', subtype: 'floor-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else {
diff --git a/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html b/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html index b71847f..5510d66 100644 --- a/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html +++ b/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html
@@ -140,6 +140,16 @@ }); session.requestReferenceSpace({ type: 'stationary', subtype: 'eye-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else { @@ -210,7 +220,7 @@ // Draw(views): // for each object in scene: - // bindProgram(); + // bindProgram(); // bindUniforms(); // bindBuffers(); // bindTextures();
diff --git a/third_party/webxr_test_pages/webxr-samples/room-scale.html b/third_party/webxr_test_pages/webxr-samples/room-scale.html index 05bb828..70abfbd 100644 --- a/third_party/webxr_test_pages/webxr-samples/room-scale.html +++ b/third_party/webxr_test_pages/webxr-samples/room-scale.html
@@ -143,6 +143,16 @@ // emulated stage, where the view is translated up by a static height so // that the scene still renders in approximately the right place. session.requestReferenceSpace({ type: 'stationary', subtype: 'floor-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; let boundsRenderer = new BoundsRenderer();
diff --git a/third_party/webxr_test_pages/webxr-samples/spectator-mode.html b/third_party/webxr_test_pages/webxr-samples/spectator-mode.html index d72e646..26e31bad 100644 --- a/third_party/webxr_test_pages/webxr-samples/spectator-mode.html +++ b/third_party/webxr_test_pages/webxr-samples/spectator-mode.html
@@ -172,6 +172,16 @@ session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) }); session.requestReferenceSpace({ type: 'stationary', subtype: 'floor-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else {
diff --git a/third_party/webxr_test_pages/webxr-samples/stereo-video.html b/third_party/webxr_test_pages/webxr-samples/stereo-video.html index 76843a3..041c7dc 100644 --- a/third_party/webxr_test_pages/webxr-samples/stereo-video.html +++ b/third_party/webxr_test_pages/webxr-samples/stereo-video.html
@@ -86,7 +86,7 @@ video: video, displayMode: 'stereoTopBottom' }); - + // When the video is clicked we'll pause it if it's playing. videoNode.onSelect(() => { if (!video.paused) { @@ -198,6 +198,16 @@ // to the center chair, as if they're sitting in it, rather than // somewhere in the room relative to the floor. session.requestReferenceSpace({ type: 'stationary', subtype: 'eye-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else {
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/cube-sea.html b/third_party/webxr_test_pages/webxr-samples/tests/cube-sea.html index f4188e9a..7c4d264 100644 --- a/third_party/webxr_test_pages/webxr-samples/tests/cube-sea.html +++ b/third_party/webxr_test_pages/webxr-samples/tests/cube-sea.html
@@ -324,7 +324,7 @@ framebufferScaleFactor: appSettings.framebufferScale, antialias: appSettings.antialias}); session.updateRenderState({ baseLayer: webglLayer }); - + if (session.mode.startsWith('immersive') && appSettings.mirrorCanvas) { let outputCanvas = document.createElement('canvas'); document.body.appendChild(outputCanvas); @@ -332,6 +332,16 @@ } session.requestReferenceSpace({ type: 'stationary', subtype: 'eye-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else {
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/offscreen-canvas.html b/third_party/webxr_test_pages/webxr-samples/tests/offscreen-canvas.html index 28a239e0..04c7db9 100644 --- a/third_party/webxr_test_pages/webxr-samples/tests/offscreen-canvas.html +++ b/third_party/webxr_test_pages/webxr-samples/tests/offscreen-canvas.html
@@ -128,6 +128,16 @@ }); session.requestReferenceSpace({ type: 'stationary', subtype: 'eye-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else {
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/permission-request.html b/third_party/webxr_test_pages/webxr-samples/tests/permission-request.html index 8dbd653a..9c6149a 100644 --- a/third_party/webxr_test_pages/webxr-samples/tests/permission-request.html +++ b/third_party/webxr_test_pages/webxr-samples/tests/permission-request.html
@@ -224,6 +224,16 @@ }); session.requestReferenceSpace({ type: 'stationary', subtype: 'floor-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else {
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/pointer-painter.html b/third_party/webxr_test_pages/webxr-samples/tests/pointer-painter.html index 15160b95..45b0891d 100644 --- a/third_party/webxr_test_pages/webxr-samples/tests/pointer-painter.html +++ b/third_party/webxr_test_pages/webxr-samples/tests/pointer-painter.html
@@ -139,6 +139,16 @@ }); session.requestReferenceSpace({ type: 'stationary', subtype: 'floor-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else {
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/sponza.html b/third_party/webxr_test_pages/webxr-samples/tests/sponza.html index d97e9b5..5dbee32 100644 --- a/third_party/webxr_test_pages/webxr-samples/tests/sponza.html +++ b/third_party/webxr_test_pages/webxr-samples/tests/sponza.html
@@ -152,6 +152,16 @@ }); session.requestReferenceSpace({ type: 'stationary', subtype: 'floor-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else { @@ -163,7 +173,7 @@ } function onSelect(ev) { - + } function onEndSession(session) {
diff --git a/third_party/webxr_test_pages/webxr-samples/viewport-scaling.html b/third_party/webxr_test_pages/webxr-samples/viewport-scaling.html index 47732d5..f34145b 100644 --- a/third_party/webxr_test_pages/webxr-samples/viewport-scaling.html +++ b/third_party/webxr_test_pages/webxr-samples/viewport-scaling.html
@@ -164,6 +164,16 @@ }); session.requestReferenceSpace({ type: 'stationary', subtype: 'eye-level' }).then((refSpace) => { + return refSpace; + }, (e) => { + if (!session.mode.startsWith('immersive')) { + // If we're in inline mode, our underlying platform may not support + // the stationary reference space, but an identity space is guaranteed. + return session.requestReferenceSpace({ type: 'identity' }); + } else { + throw e; + } + }).then((refSpace) => { if (session.mode.startsWith('immersive')) { xrImmersiveRefSpace = refSpace; } else {
diff --git a/tools/android/roll/android_deps/build.gradle b/tools/android/roll/android_deps/build.gradle index a3a4734..141aa0d 100644 --- a/tools/android/roll/android_deps/build.gradle +++ b/tools/android/roll/android_deps/build.gradle
@@ -78,7 +78,7 @@ compile "com.google.protobuf:protobuf-lite:3.0.1" // ARCore - needed for WebXR implementation on Android - compile "com.google.ar:core:1.6.0" + compile "com.google.ar:core:1.8.0" // Androidx test libraries testCompile "androidx.test:core:1.0.0"
diff --git a/tools/binary_size/diagnose_bloat.py b/tools/binary_size/diagnose_bloat.py index 4e8af31..ae850c1 100755 --- a/tools/binary_size/diagnose_bloat.py +++ b/tools/binary_size/diagnose_bloat.py
@@ -498,6 +498,34 @@ logging.info('See detailed diff results here: %s', os.path.relpath(diff_path)) + def GenerateHtmlReport(self, before_id, after_id): + """Generate HTML report given two build archives.""" + before = self.build_archives[before_id] + after = self.build_archives[after_id] + diff_path = self._DiffDir(before, after) + if not self._CanDiff(before, after): + logging.info( + 'Skipping HTML report for %s due to missing build archives.', + diff_path) + return + + supersize_path = os.path.join(_BINARY_SIZE_DIR, 'supersize') + + report_path = os.path.join(diff_path, 'diff.ndjson') + + supersize_cmd = [supersize_path, 'html_report', '--diff-with', + before.archived_size_path, + after.archived_size_path, + report_path] + + logging.info('Creating HTML report') + + _RunCmd(supersize_cmd) + + logging.info('View using a local server via: %s start_server %s', + os.path.relpath(supersize_path), + os.path.relpath(report_path)) + def Summarize(self): path = os.path.join(self.archive_dir, 'last_diff_summary.txt') if self._summary_stats: @@ -1000,6 +1028,7 @@ subrepo, args.include_slow_options, args.unstripped) consecutive_failures = 0 + i = 0 for i, archive in enumerate(diff_mngr.build_archives): if archive.Exists(): step = 'download' if build.IsCloud() else 'build' @@ -1029,6 +1058,7 @@ if i != 0: diff_mngr.MaybeDiff(i - 1, i) + diff_mngr.GenerateHtmlReport(0, i) diff_mngr.Summarize()
diff --git a/tools/chrome_proxy/webdriver/bypass.py b/tools/chrome_proxy/webdriver/bypass.py index fd691f8..fea8ae1 100644 --- a/tools/chrome_proxy/webdriver/bypass.py +++ b/tools/chrome_proxy/webdriver/bypass.py
@@ -21,7 +21,7 @@ self.assertEqual(2, len(responses)) for response in responses: if response.url == "http://check.googlezip.net/image.png": - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) else: self.assertNotHasChromeProxyViaHeader(response) @@ -49,7 +49,7 @@ responses = t.GetHTTPResponses() self.assertEqual(2, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) # Load HTTPS page and check that Data Saver is not used. t.LoadURL('https://check.googlezip.net/test.html') @@ -75,7 +75,7 @@ for response in test_driver.GetHTTPResponses(): # The origin header implies that |response| is a CORS request. if ('origin' not in response.request_headers): - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) same_origin_requests = same_origin_requests + 1 else: self.assertNotHasChromeProxyViaHeader(response) @@ -102,7 +102,7 @@ responses = test_driver.GetHTTPResponses() self.assertNotEqual(0, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) # Verify that Chrome does not bypass the proxy when a response gets a missing # via header. @@ -199,7 +199,7 @@ responses = test_driver.GetHTTPResponses() self.assertNotEqual(0, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) # Verify that loading the exp directive test page with # "exp=client_test_bypass" triggers a bypass. @@ -218,7 +218,7 @@ responses = test_driver.GetHTTPResponses() self.assertNotEqual(0, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) # Data Saver uses a HTTPS proxy by default, if that fails it will fall back to # a HTTP proxy. @@ -245,7 +245,7 @@ responses = test_driver.GetHTTPResponses() self.assertNotEqual(0, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) if 'chrome-proxy' in response.request_headers: chrome_proxy_header = response.request_headers['chrome-proxy'] chrome_proxy_directives = chrome_proxy_header.split(',')
diff --git a/tools/chrome_proxy/webdriver/client_config.py b/tools/chrome_proxy/webdriver/client_config.py index f87ed26..048c67e3 100644 --- a/tools/chrome_proxy/webdriver/client_config.py +++ b/tools/chrome_proxy/webdriver/client_config.py
@@ -23,7 +23,7 @@ self.assertEqual(2, len(responses)) for response in responses: # Verify that the proxy server honored the session ID. - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) self.assertEqual(200, response.status) # Ensure Chrome uses a direct connection when no valid client config is given.
diff --git a/tools/chrome_proxy/webdriver/common.py b/tools/chrome_proxy/webdriver/common.py index 738e2c5..7531935 100644 --- a/tools/chrome_proxy/webdriver/common.py +++ b/tools/chrome_proxy/webdriver/common.py
@@ -76,6 +76,10 @@ parser.add_argument('--via_header_value', default='1.1 Chrome-Compression-Proxy', help='What the via should match to ' 'be considered valid') + parser.add_argument('--aceh_header_value', + default='Chrome-Proxy,Chrome-Proxy-Content-Transform,Via', help='Comma ' + 'separated list of values that should be in the ' + 'Access-Control-Expose-Headers header.') parser.add_argument('--android', help='If given, attempts to run the test on ' 'Android via adb. Ignores usage of --chrome_exec', action='store_true') parser.add_argument('--android_package', @@ -770,20 +774,41 @@ unittest.TestCase class. """ - def assertHasChromeProxyViaHeader(self, http_response): - """Asserts that the Via header in the given HTTPResponse matches the - expected value as given on the command line. + def assertHasProxyHeaders(self, http_response): + """Asserts that Proxy headers are present contain the expected values + as provided on the command line. + + The Proxy adds two headers: Via, and Access-Control-Expose-Headers. + This checks that both headers contain the values enumerated in both + --via_header_value and --aceh_header_value. Both headers are additive, + so there may be more values in the headers than expected. Args: http_response: The HTTPResponse object to check. """ + # Via header check self.assertIn('via', http_response.response_headers) - expected_via_header = ParseFlags().via_header_value - actual_via_headers = http_response.response_headers['via'].split(',') + expected_via_header = ParseFlags().via_header_value.lower() + actual_via_headers = set( + [h.lower() for h in http_response.response_headers['via'].split(',')]) self.assertIn(expected_via_header, actual_via_headers, "Via header not in " "response headers! Expected: %s, Actual: %s" % (expected_via_header, actual_via_headers)) + # Access-Control-Expose-Headers header check. + if ParseFlags().aceh_header_value: + aceh = 'access-control-expose-headers' + self.assertIn(aceh, http_response.response_headers) + expected_aceh_header = set( + [h.lower() for h in ParseFlags().aceh_header_value.split(',')]) + actual_aceh_header = set( + [h.lower() for h in http_response.response_headers[aceh].split(',')]) + diff = expected_aceh_header - actual_aceh_header + self.assertTrue(len(diff) == 0, "Access-Control-Expose-Headers missing " + "values (%s)! Expected: [%s], Actual: [%s]" % + (",".join(diff), ",".join(expected_aceh_header), + ",".join(actual_aceh_header))) + def assertNotHasChromeProxyViaHeader(self, http_response): """Asserts that the Via header in the given HTTPResponse does not match the expected value as given on the command line. @@ -857,7 +882,7 @@ """ if (expected_lo_fi) : - self.assertHasChromeProxyViaHeader(http_response) + self.assertHasProxyHeaders(http_response) content_length = http_response.response_headers['content-length'] cpat_request = http_response.request_headers[ 'chrome-proxy-accept-transform'] @@ -891,7 +916,7 @@ Whether the response was a Lite Page. """ - self.assertHasChromeProxyViaHeader(http_response) + self.assertHasProxyHeaders(http_response) if ('chrome-proxy-content-transform' not in http_response.response_headers): return False; cpct_response = http_response.response_headers[
diff --git a/tools/chrome_proxy/webdriver/compression_regression.py b/tools/chrome_proxy/webdriver/compression_regression.py index e397ec2..6b7b99e0 100644 --- a/tools/chrome_proxy/webdriver/compression_regression.py +++ b/tools/chrome_proxy/webdriver/compression_regression.py
@@ -148,7 +148,7 @@ compression = {} for response in t.GetHTTPResponses(): # Check that the response was proxied. - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) # Compute compression metrics. cl = response.response_headers['content-length'] ofcl = getChromeProxyOFCL(response)
diff --git a/tools/chrome_proxy/webdriver/data_use.py b/tools/chrome_proxy/webdriver/data_use.py index 7426c2b..0a004d53 100644 --- a/tools/chrome_proxy/webdriver/data_use.py +++ b/tools/chrome_proxy/webdriver/data_use.py
@@ -26,7 +26,7 @@ t.LoadURL('http://check.googlezip.net/test.html') responses = t.GetHTTPResponses() for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) # Load the extension page and verify the host appears in data use list. t.LoadURL('chrome-extension://pfmgfdlgomnbgkofeojodiodmgpgmkac/'
diff --git a/tools/chrome_proxy/webdriver/fallback.py b/tools/chrome_proxy/webdriver/fallback.py index a28c325..240ff5b 100644 --- a/tools/chrome_proxy/webdriver/fallback.py +++ b/tools/chrome_proxy/webdriver/fallback.py
@@ -37,7 +37,7 @@ responses = test_driver.GetHTTPResponses() self.assertNotEqual(0, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) self.assertEqual(u'http/2+quic/43', response.protocol) # Verify that when Chrome receives a non-4xx response through a Data Reduction @@ -61,7 +61,7 @@ responses = test_driver.GetHTTPResponses() self.assertNotEqual(0, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) self.assertEqual(u'http/1.1', response.protocol) # Check that the BypassTypePrimary histogram has a single entry in the
diff --git a/tools/chrome_proxy/webdriver/html5.py b/tools/chrome_proxy/webdriver/html5.py index 036b019..b08edc5 100644 --- a/tools/chrome_proxy/webdriver/html5.py +++ b/tools/chrome_proxy/webdriver/html5.py
@@ -22,7 +22,7 @@ # Site has a lot on it, just check the main page. if (response.url == 'http://html5test.com/' or response.url == 'http://html5test.com/index.html'): - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) checked_main_page = True if not checked_main_page: self.fail("Did not check any page!")
diff --git a/tools/chrome_proxy/webdriver/lite_page.py b/tools/chrome_proxy/webdriver/lite_page.py index 3c84a4bb..c9bc029 100644 --- a/tools/chrome_proxy/webdriver/lite_page.py +++ b/tools/chrome_proxy/webdriver/lite_page.py
@@ -194,7 +194,7 @@ in response.response_headers['content-type']): continue # Make sure non-video requests are proxied. - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) # Make sure there are no 4XX or 5xx status codes. self.assertLess(response.status, 400)
diff --git a/tools/chrome_proxy/webdriver/lofi.py b/tools/chrome_proxy/webdriver/lofi.py index 03d825d..2f12c5a 100644 --- a/tools/chrome_proxy/webdriver/lofi.py +++ b/tools/chrome_proxy/webdriver/lofi.py
@@ -300,7 +300,7 @@ if not response.request_headers: continue responses = responses + 1 - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) self.checkLoFiResponse(response, False) # Verify that responses were seen. @@ -388,7 +388,7 @@ if not response.request_headers: continue responses = responses + 1 - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) self.checkLoFiResponse(response, False) # Verify that responses were seen. @@ -493,7 +493,7 @@ image_response_count = 0 for response in test_driver.GetHTTPResponses(): if response.url.endswith('.png'): - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) self.assertIn('range', response.request_headers) self.assertIn('content-range', response.response_headers) self.assertTrue(response.response_headers['content-range'].startswith(
diff --git a/tools/chrome_proxy/webdriver/quic.py b/tools/chrome_proxy/webdriver/quic.py index bd57e11..53d4528e 100644 --- a/tools/chrome_proxy/webdriver/quic.py +++ b/tools/chrome_proxy/webdriver/quic.py
@@ -31,7 +31,7 @@ responses = t.GetHTTPResponses() self.assertEqual(2, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) # Ensure Chrome uses QUIC DataSaver proxy when QUIC is enabled. This test # may fail if QUIC is disabled on the server side. @@ -52,7 +52,7 @@ responses = t.GetHTTPResponses() self.assertEqual(2, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) # Verify that histogram DataReductionProxy.Quic.ProxyStatus has at least 1 # sample. This sample must be in bucket 0 (QUIC_PROXY_STATUS_AVAILABLE). @@ -60,14 +60,5 @@ self.assertLessEqual(1, proxy_status['count']) self.assertEqual(0, proxy_status['sum']) - # Navigate to one more page to ensure that established QUIC connection - # is used for the next request. Give 3 seconds extra headroom for the QUIC - # connection to be established. - time.sleep(3) - t.LoadURL('http://check.googlezip.net/test.html') - proxy_usage = t.GetHistogram('Net.QuicAlternativeProxy.Usage') - # Bucket ALTERNATIVE_PROXY_USAGE_NO_RACE should have at least onesample. - self.assertLessEqual(1, proxy_usage['buckets'][0]['count']) - if __name__ == '__main__': IntegrationTest.RunAllTests()
diff --git a/tools/chrome_proxy/webdriver/reenable_after_bypass.py b/tools/chrome_proxy/webdriver/reenable_after_bypass.py index 4fcea97a..3d0ade8 100644 --- a/tools/chrome_proxy/webdriver/reenable_after_bypass.py +++ b/tools/chrome_proxy/webdriver/reenable_after_bypass.py
@@ -46,7 +46,7 @@ responses = test_driver.GetHTTPResponses() self.assertNotEqual(0, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) # Verify that when the Data Reduction Proxy responds with the "block=0" # directive, Chrome bypasses all proxies for the next 1-5 minutes. @@ -78,7 +78,7 @@ responses = test_driver.GetHTTPResponses() self.assertNotEqual(0, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) if __name__ == '__main__':
diff --git a/tools/chrome_proxy/webdriver/safebrowsing.py b/tools/chrome_proxy/webdriver/safebrowsing.py index 6e7e371..b0f3f5e 100644 --- a/tools/chrome_proxy/webdriver/safebrowsing.py +++ b/tools/chrome_proxy/webdriver/safebrowsing.py
@@ -54,7 +54,7 @@ responses = t.GetHTTPResponses() self.assertEqual(1, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) if __name__ == '__main__': IntegrationTest.RunAllTests()
diff --git a/tools/chrome_proxy/webdriver/smoke.py b/tools/chrome_proxy/webdriver/smoke.py index 54a38eb..2f27d17b 100644 --- a/tools/chrome_proxy/webdriver/smoke.py +++ b/tools/chrome_proxy/webdriver/smoke.py
@@ -93,7 +93,7 @@ self.assertNotEqual(0, len(responses)) num_chrome_proxy_request_headers = 0 for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) if ('chrome-proxy' in response.request_headers): num_chrome_proxy_request_headers += 1 t.SleepUntilHistogramHasEntry('PageLoad.Clients.DataReductionProxy.' @@ -161,7 +161,7 @@ for response in responses: if not response.request_headers: continue - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) self.assertEqual(200, response.status) chrome_proxy_header = response.request_headers['chrome-proxy'] chrome_proxy_directives = chrome_proxy_header.split(',') @@ -194,7 +194,7 @@ responses = t.GetHTTPResponses() self.assertNotEqual(0, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) if __name__ == '__main__': IntegrationTest.RunAllTests()
diff --git a/tools/chrome_proxy/webdriver/video.py b/tools/chrome_proxy/webdriver/video.py index cdab171..58237ea10 100644 --- a/tools/chrome_proxy/webdriver/video.py +++ b/tools/chrome_proxy/webdriver/video.py
@@ -31,7 +31,7 @@ responses = t.GetHTTPResponses() self.assertEquals(2, len(responses)) for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) # Videos fetched via an XHR request should not be proxied. def testNoCompressionOnXHR(self): @@ -52,7 +52,7 @@ self.assertNotHasChromeProxyViaHeader(response) saw_video_response = True else: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) self.assertTrue(saw_video_response, 'No video request seen in test!') @ChromeVersionEqualOrAfterM(64) @@ -70,7 +70,7 @@ ) saw_range_response = False for response in t.GetHTTPResponses(): - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) if response.response_headers['status']=='206': saw_range_response = True content_range = response.response_headers['content-range'] @@ -105,7 +105,7 @@ responses = t.GetHTTPResponses() saw_range_response = False for response in responses: - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) if response.response_headers['status']=='206': saw_range_response = True content_range = response.response_headers['content-range'] @@ -131,7 +131,7 @@ 'http://check.googlezip.net/cacheable/video/buck_bunny_tiny.html') # Check request was proxied and we got a compressed video back. for response in t.GetHTTPResponses(): - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) if ('content-type' in response.response_headers and 'video' in response.response_headers['content-type']): self.assertEqual('video/webm', @@ -193,7 +193,7 @@ video_etag = None num_partial_requests = 0 for response in t.GetHTTPResponses(): - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) rh = response.response_headers if ('content-type' in rh and 'video' in rh['content-type']): self.assertTrue('etag' in rh), @@ -254,7 +254,7 @@ if ('content-type' in resp.response_headers and resp.response_headers['content-type'] == 'video/webm'): loaded_compressed_video = True - self.assertHasChromeProxyViaHeader(resp) + self.assertHasProxyHeaders(resp) else: # Take a breath before requesting again. time.sleep(1) @@ -292,7 +292,7 @@ 'window.playerState == YT.PlayerState.PLAYING', 30) for response in t.GetHTTPResponses(): if not response.url.startswith('https'): - self.assertHasChromeProxyViaHeader(response) + self.assertHasProxyHeaders(response) if __name__ == '__main__': IntegrationTest.RunAllTests()
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids index dc660db..47b4836 100644 --- a/tools/gritsettings/resource_ids +++ b/tools/gritsettings/resource_ids
@@ -83,8 +83,10 @@ "includes": [11000], "structures": [12000], }, + "chrome/browser/resources/chromeos/cellular_setup/cellular_setup_resources.grd": { + "structures": [12040], + }, "chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_resources.grd": { - "includes": [12040], "structures": [12045], }, "chrome/browser/resources/component_extension_resources.grd": {
diff --git a/tools/json_schema_compiler/idl_schema.py b/tools/json_schema_compiler/idl_schema.py index f9f73442..cfa9e81 100755 --- a/tools/json_schema_compiler/idl_schema.py +++ b/tools/json_schema_compiler/idl_schema.py
@@ -362,6 +362,8 @@ for node in self.node.GetChildren(): if node.cls == 'EnumItem': enum_value = {'name': node.GetName()} + if node.GetProperty('nodoc'): + enum_value['nodoc'] = True for child in node.GetChildren(): if child.cls == 'Comment': enum_value['description'] = ProcessComment(child.GetName())[0]
diff --git a/tools/json_schema_compiler/idl_schema_test.py b/tools/json_schema_compiler/idl_schema_test.py index 8d4e8b9..b9d1435a 100755 --- a/tools/json_schema_compiler/idl_schema_test.py +++ b/tools/json_schema_compiler/idl_schema_test.py
@@ -150,6 +150,25 @@ self.assertTrue(enum_with_nodoc is not None) self.assertTrue(enum_with_nodoc['nodoc']) + def testNoDocOnEnumValue(self): + schema = self.idl_basics + expected = { + 'enum': [{ + 'name': 'name1' + }, { + 'name': 'name2', + 'nodoc': True, + 'description': 'comment2' + }, { + 'name': 'name3', + 'description': 'comment3' + }], + 'type': 'string', + 'id': 'EnumTypeWithNoDocValue', + 'description': '' + } + self.assertEquals(expected, getType(schema, expected['id'])) + def testInternalNamespace(self): idl_basics = self.idl_basics self.assertEquals('idl_basics', idl_basics['namespace'])
diff --git a/tools/json_schema_compiler/test/idl_basics.idl b/tools/json_schema_compiler/test/idl_basics.idl index c4fb5aa..b0ca3fa 100644 --- a/tools/json_schema_compiler/test/idl_basics.idl +++ b/tools/json_schema_compiler/test/idl_basics.idl
@@ -17,6 +17,14 @@ name2 }; + enum EnumTypeWithNoDocValue { + name1, + // comment2 + [nodoc] name2, + // comment3 + name3 + }; + dictionary MyType1 { // This comment tests "double-quotes". [legalValues=(1,2)] long x;
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 496c60d..67880387 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -669,12 +669,10 @@ 'android_angle_deqp_rel_ng': 'deqp_android_release_trybot_arm64', 'android_angle_vk32_deqp_rel_ng': 'deqp_android_vulkan_release_trybot', 'android_angle_vk64_deqp_rel_ng': 'deqp_android_vulkan_release_trybot_arm64', - 'linux-angle-rel': 'gpu_fyi_tests_release_trybot', 'linux_angle_ozone_rel_ng': 'gpu_fyi_tests_ozone_linux_system_gbm_libdrm_release_trybot', 'linux_angle_dbg_ng': 'gpu_fyi_tests_debug_trybot', 'linux_angle_deqp_rel_ng': 'deqp_release_trybot', 'linux_angle_rel_ng': 'gpu_fyi_tests_release_trybot', - 'mac-angle-rel': 'gpu_fyi_tests_release_trybot', 'mac_angle_dbg_ng': 'gpu_fyi_tests_debug_trybot', 'mac_angle_rel_ng': 'gpu_fyi_tests_release_trybot', 'win-angle-rel': 'gpu_fyi_tests_release_trybot_x86',
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 8796f44..f94590d 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -11870,6 +11870,9 @@ </action> <action name="MobileNTPSwitchToBookmarks"> + <obsolete> + Removed with deprecation of Bookmark suggestions category. + </obsolete> <owner>ianwen@chromium.org</owner> <description> Action indicating the user has clicked the boomkark button on NTP to swith @@ -11878,6 +11881,9 @@ </action> <action name="MobileNTPSwitchToDownloadManager"> + <obsolete> + Removed with deprecation of Download suggestions category. + </obsolete> <owner>bauerb@chromium.org</owner> <description> Android: User clicked on the "More" card at the end of the section @@ -19980,6 +19986,9 @@ </action> <action name="Suggestions.Category.ViewAll"> + <obsolete> + Removed with deprecation of Download suggestions category. + </obsolete> <owner>finkm@chromium.org</owner> <owner>dgn@chromium.org</owner> <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 83e353f..2a6fc27 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -8902,7 +8902,7 @@ <enum name="ContentSuggestionsCategory"> <int value="0" label="Experimental"/> <int value="1" label="Recent Tabs (obsolete)"/> - <int value="2" label="Downloads"/> + <int value="2" label="Downloads (obsolete)"/> <int value="3" label="Bookmarks (obsolete)"/> <int value="4" label="Physical Web Pages (obsolete)"/> <int value="5" label="Foreign Tabs (obsolete)"/> @@ -33849,6 +33849,7 @@ <int value="782167080" label="enable-new-qp-input-view"/> <int value="783270752" label="AndroidHistoryManager:enabled"/> <int value="787385958" label="RegionalLocalesAsDisplayUI:enabled"/> + <int value="799680074" label="ContextualSearchTranslationModel:enabled"/> <int value="803282885" label="PreferHtmlOverPlugins:disabled"/> <int value="806334184" label="AndroidSpellChecker:enabled"/> <int value="807447752" label="ChromeMemex:disabled"/> @@ -33935,6 +33936,7 @@ <int value="955340765" label="ChromeHomeOptOutSnackbar:enabled"/> <int value="963457392" label="ChromeHomeModernLayout:disabled"/> <int value="963671232" label="DrawOcclusion:disabled"/> + <int value="964613807" label="ContextualSearchTranslationModel:disabled"/> <int value="966415988" label="SyncPseudoUSSPasswords:enabled"/> <int value="969340095" label="EnableDspHotword:disabled"/> <int value="972228058" label="SyncUSSSessions:disabled"/> @@ -36632,6 +36634,17 @@ <int value="1" label="Remote"/> </enum> +<enum name="MediaSessionAction"> + <int value="0" label="Play"/> + <int value="1" label="Pause"/> + <int value="2" label="Previous Track"/> + <int value="3" label="Next Track"/> + <int value="4" label="Seek Backward"/> + <int value="5" label="Seek Forward"/> + <int value="6" label="Skip Ad"/> + <int value="7" label="Stop"/> +</enum> + <enum name="MediaSessionActionSource"> <int value="0" label="Media Notification"/> <int value="1" label="MediaSession (Android)"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 55bea1c..6a23f5ba 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -51969,6 +51969,15 @@ </summary> </histogram> +<histogram name="Media.Notification.UserAction" enum="MediaSessionAction" + expires_after="2019-12-31"> + <owner>beccahughes@chromium.org</owner> + <owner>media-dev@chromium.org</owner> + <summary> + The action (e.g. pause) that a user clicked on a media notification. + </summary> +</histogram> + <histogram name="Media.OutputStreamDuration" units="ms"> <owner>maxmorin@chromium.org</owner> <summary> @@ -106901,7 +106910,10 @@ </histogram> <histogram name="Search.ContextualSearchShouldTranslate" - enum="ContextualSearchShouldTranslate"> + enum="ContextualSearchShouldTranslate" expires_after="2019-04-05"> + <obsolete> + Removed in M75 because the data is no longer needed. + </obsolete> <owner>donnd@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -107087,7 +107099,6 @@ <histogram name="Search.ContextualSearchTranslateCondition" enum="Boolean" expires_after="M77"> <owner>donnd@chromium.org</owner> - <owner>mahmoudi@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> For each contextual search that is triggered by tap, records whether the
diff --git a/tools/perf/core/upload_results_to_perf_dashboard.py b/tools/perf/core/upload_results_to_perf_dashboard.py index 818505e..884dfab 100755 --- a/tools/perf/core/upload_results_to_perf_dashboard.py +++ b/tools/perf/core/upload_results_to_perf_dashboard.py
@@ -77,10 +77,7 @@ is_reference_build = 'reference' in options.name stripped_test_name = options.name.replace('.reference', '') - # 30 MB max_bytes was chosen to be large enough that we rarely have to break - # up perf data into chunks since it is slow (crbug.com/947035) but small - # enough that we don't cause crbug.com/909961. - max_bytes = 30 << 20 + max_bytes = 1 << 20 output_dir = tempfile.mkdtemp() try:
diff --git a/tools/traffic_annotation/auditor/BUILD.gn b/tools/traffic_annotation/auditor/BUILD.gn index 7931a890..5f01c32 100644 --- a/tools/traffic_annotation/auditor/BUILD.gn +++ b/tools/traffic_annotation/auditor/BUILD.gn
@@ -9,6 +9,8 @@ assert(is_win || is_linux) proto_library("chrome_settings_full_runtime") { + proto_out_dir = "/tools/traffic_annotation" + cc_include = "components/policy/proto/policy_proto_export.h" sources = [
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn index 8ce6a2e..a8b692a 100644 --- a/ui/accessibility/BUILD.gn +++ b/ui/accessibility/BUILD.gn
@@ -132,12 +132,15 @@ defines = [ "ACCESSIBILITY_IMPLEMENTATION" ] + deps = [ + "//third_party/cld_3/src/src:cld_3", + ] + public_deps = [ ":ax_constants_mojo", ":ax_enums_mojo", "//base", "//base:i18n", - "//third_party/cld_3/src/src:cld_3", "//ui/base", "//ui/display", "//ui/gfx",
diff --git a/ui/accessibility/accessibility_switches.cc b/ui/accessibility/accessibility_switches.cc index 07371fb..e96dd18 100644 --- a/ui/accessibility/accessibility_switches.cc +++ b/ui/accessibility/accessibility_switches.cc
@@ -18,6 +18,11 @@ const char kEnableExperimentalAccessibilityAutoclick[] = "enable-experimental-accessibility-autoclick"; +// Enables support for visually debugging the accessibility labels +// feature, which provides images descriptions for screen reader users. +const char kEnableExperimentalAccessibilityLabelsDebugging[] = + "enable-experimental-accessibility-labels-debugging"; + // Enables language detection on in-page text content which is then exposed to // accessibility technology such as screen readers. const char kEnableExperimentalAccessibilityLanguageDetection[] =
diff --git a/ui/accessibility/accessibility_switches.h b/ui/accessibility/accessibility_switches.h index 8579f94..159a0ad 100644 --- a/ui/accessibility/accessibility_switches.h +++ b/ui/accessibility/accessibility_switches.h
@@ -13,6 +13,7 @@ AX_EXPORT extern const char kEnableExperimentalAccessibilityFeatures[]; AX_EXPORT extern const char kEnableExperimentalAccessibilityAutoclick[]; +AX_EXPORT extern const char kEnableExperimentalAccessibilityLabelsDebugging[]; AX_EXPORT extern const char kEnableExperimentalAccessibilityLanguageDetection[]; AX_EXPORT extern const char kEnableExperimentalAccessibilitySwitchAccess[]; AX_EXPORT extern const char
diff --git a/ui/accessibility/ax_node_position_unittest.cc b/ui/accessibility/ax_node_position_unittest.cc index 4861c5a..31cd999 100644 --- a/ui/accessibility/ax_node_position_unittest.cc +++ b/ui/accessibility/ax_node_position_unittest.cc
@@ -1440,38 +1440,42 @@ ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); ASSERT_TRUE(text_position->IsTextPosition()); + test_position = text_position->CreateNextCharacterPosition( AXBoundaryBehavior::StopAtAnchorBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(inline_box1_.id, test_position->anchor_id()); - EXPECT_EQ(5, test_position->text_offset()); - test_position = text_position->CreateNextCharacterPosition( - AXBoundaryBehavior::CrossBoundary); - EXPECT_NE(nullptr, test_position); - EXPECT_TRUE(test_position->IsTextPosition()); - EXPECT_EQ(line_break_.id, test_position->anchor_id()); - EXPECT_EQ(0, test_position->text_offset()); - + EXPECT_EQ(6, test_position->text_offset()); test_position = test_position->CreateNextCharacterPosition( AXBoundaryBehavior::StopAtAnchorBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); - EXPECT_EQ(line_break_.id, test_position->anchor_id()); - EXPECT_EQ(0, test_position->text_offset()); - test_position = test_position->CreateNextCharacterPosition( + EXPECT_EQ(inline_box1_.id, test_position->anchor_id()); + EXPECT_EQ(6, test_position->text_offset()); + + test_position = text_position->CreateNextCharacterPosition( AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); - EXPECT_EQ(inline_box2_.id, test_position->anchor_id()); - EXPECT_EQ(0, test_position->text_offset()); + EXPECT_EQ(inline_box1_.id, test_position->anchor_id()); + EXPECT_EQ(6, test_position->text_offset()); test_position = test_position->CreateNextCharacterPosition( AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); + EXPECT_EQ(line_break_.id, test_position->anchor_id()); + EXPECT_EQ(0, test_position->text_offset()); + + // The line break doesn't reach its max length (1) to distinguish between the + // "before" and "after" positions + test_position = test_position->CreateNextCharacterPosition( + AXBoundaryBehavior::CrossBoundary); + EXPECT_NE(nullptr, test_position); + EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(inline_box2_.id, test_position->anchor_id()); - EXPECT_EQ(1, test_position->text_offset()); + EXPECT_EQ(0, test_position->text_offset()); text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, check_box_.id, 0 /* text_offset */, @@ -1504,6 +1508,20 @@ EXPECT_EQ(1, test_position->text_offset()); // Affinity should have been reset to downstream. EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity()); + + text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, text_field_.id, 12 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + test_position = text_position->CreateNextCharacterPosition( + AXBoundaryBehavior::CrossBoundary); + EXPECT_NE(nullptr, test_position); + EXPECT_TRUE(test_position->IsTextPosition()); + EXPECT_EQ(text_field_.id, test_position->anchor_id()); + EXPECT_EQ(13, test_position->text_offset()); + // Affinity should have been reset to downstream. + EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity()); } TEST_F(AXPositionTest, CreatePreviousCharacterPosition) {
diff --git a/ui/accessibility/ax_position.h b/ui/accessibility/ax_position.h index 5df467d..1a207a14 100644 --- a/ui/accessibility/ax_position.h +++ b/ui/accessibility/ax_position.h
@@ -634,15 +634,18 @@ if (text_position->IsNullPosition()) return text_position; + const int max_position = text_position->MaxTextOffset(); + // Note that |BoundaryBehavior::StopIfAlreadyAtBoundary| doesn't make // sense for character boundaries. DCHECK_NE(boundary_behavior, AXBoundaryBehavior::StopIfAlreadyAtBoundary); if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary && - (text_position->text_offset_ + 1) >= text_position->MaxTextOffset()) { + (text_position->text_offset_) >= max_position) { return Clone(); } - if ((text_position->text_offset_ + 1) < text_position->MaxTextOffset()) { + if (!text_position->AtEndOfLine() && + (text_position->text_offset_ + 1) <= max_position) { text_position->text_offset_ += 1; // Even if our affinity was upstream, moving to the next character should // inevitably reset it to downstream.
diff --git a/ui/display/manager/display_configurator.cc b/ui/display/manager/display_configurator.cc index c81b1e8..6dce07f 100644 --- a/ui/display/manager/display_configurator.cc +++ b/ui/display/manager/display_configurator.cc
@@ -573,7 +573,6 @@ has_pending_power_state_(false), pending_power_flags_(kSetDisplayPowerNoFlags), force_configure_(false), - next_display_protection_client_id_(1), display_externally_controlled_(false), display_control_changing_(false), displays_suspended_(false), @@ -593,9 +592,9 @@ query_protection_callbacks_.pop(); } - while (!set_protection_callbacks_.empty()) { - std::move(set_protection_callbacks_.front()).Run(false); - set_protection_callbacks_.pop(); + while (!apply_protection_callbacks_.empty()) { + std::move(apply_protection_callbacks_.front()).Run(false); + apply_protection_callbacks_.pop(); } } @@ -638,7 +637,7 @@ std::unique_ptr<NativeDisplayDelegate> display_delegate, bool is_panel_fitting_enabled) { is_panel_fitting_enabled_ = is_panel_fitting_enabled; - if (!configure_display_ || display_externally_controlled_) + if (configurator_disabled()) return; // If the delegate is already initialized don't update it (For example, tests @@ -740,7 +739,7 @@ } void DisplayConfigurator::ForceInitialConfigure() { - if (!configure_display_ || display_externally_controlled_) + if (configurator_disabled()) return; DCHECK(native_display_delegate_); @@ -759,25 +758,29 @@ configuration_task_->Run(); } -uint64_t DisplayConfigurator::RegisterContentProtectionClient() { - if (!configure_display_ || display_externally_controlled_) - return INVALID_CLIENT_ID; +DisplayConfigurator::ContentProtectionClientId +DisplayConfigurator::RegisterContentProtectionClient() { + if (configurator_disabled()) + return base::nullopt; - return next_display_protection_client_id_++; + return next_content_protection_client_id_++; } void DisplayConfigurator::UnregisterContentProtectionClient( - uint64_t client_id) { - client_protection_requests_.erase(client_id); + ContentProtectionClientId client_id) { + if (!client_id) + return; + + content_protection_requests_.erase(*client_id); ContentProtections protections; - for (const auto& requests_pair : client_protection_requests_) { + for (const auto& requests_pair : content_protection_requests_) { for (const auto& protections_pair : requests_pair.second) { protections[protections_pair.first] |= protections_pair.second; } } - set_protection_callbacks_.push(base::DoNothing()); + apply_protection_callbacks_.push(base::DoNothing()); ApplyContentProtectionTask* task = new ApplyContentProtectionTask( layout_manager_.get(), native_display_delegate_.get(), protections, base::Bind(&DisplayConfigurator::OnContentProtectionClientUnregistered, @@ -793,38 +796,41 @@ DCHECK(!content_protection_tasks_.empty()); content_protection_tasks_.pop(); - DCHECK(!set_protection_callbacks_.empty()); - SetProtectionCallback callback = std::move(set_protection_callbacks_.front()); - set_protection_callbacks_.pop(); + DCHECK(!apply_protection_callbacks_.empty()); + ApplyContentProtectionCallback callback = + std::move(apply_protection_callbacks_.front()); + apply_protection_callbacks_.pop(); if (!content_protection_tasks_.empty()) content_protection_tasks_.front().Run(); } -void DisplayConfigurator::QueryContentProtectionStatus( - uint64_t client_id, +void DisplayConfigurator::QueryContentProtection( + ContentProtectionClientId client_id, int64_t display_id, - QueryProtectionCallback callback) { + QueryContentProtectionCallback callback) { + if (!client_id || configurator_disabled()) { + std::move(callback).Run(/*success=*/false, DISPLAY_CONNECTION_TYPE_NONE, + CONTENT_PROTECTION_METHOD_NONE); + return; + } + // Exclude virtual displays so that protected content will not be recaptured // through the cast stream. for (const DisplaySnapshot* display : cached_displays_) { if (display->display_id() == display_id && !IsPhysicalDisplayType(display->type())) { - std::move(callback).Run(false, 0, 0); + std::move(callback).Run(/*success=*/false, DISPLAY_CONNECTION_TYPE_NONE, + CONTENT_PROTECTION_METHOD_NONE); return; } } - if (!configure_display_ || display_externally_controlled_) { - std::move(callback).Run(false, 0, 0); - return; - } - query_protection_callbacks_.push(std::move(callback)); QueryContentProtectionTask* task = new QueryContentProtectionTask( layout_manager_.get(), native_display_delegate_.get(), display_id, base::Bind(&DisplayConfigurator::OnContentProtectionQueried, - weak_ptr_factory_.GetWeakPtr(), client_id, display_id)); + weak_ptr_factory_.GetWeakPtr(), *client_id, display_id)); content_protection_tasks_.push( base::Bind(&QueryContentProtectionTask::Run, base::Owned(task))); if (content_protection_tasks_.size() == 1) @@ -834,93 +840,99 @@ void DisplayConfigurator::OnContentProtectionQueried( uint64_t client_id, int64_t display_id, - QueryContentProtectionTask::Response task_response) { - bool success = task_response.success; - uint32_t link_mask = task_response.link_mask; - uint32_t protection_mask = 0; + QueryContentProtectionTask::Response response) { + bool success = response.success; + uint32_t connection_mask = response.link_mask; + uint32_t protection_mask = response.enabled & ~response.unfulfilled; + uint32_t client_mask = CONTENT_PROTECTION_METHOD_NONE; // Don't reveal protections requested by other clients. - ProtectionRequests::iterator it = client_protection_requests_.find(client_id); - if (success && it != client_protection_requests_.end()) { - uint32_t requested_mask = 0; - if (it->second.find(display_id) != it->second.end()) - requested_mask = it->second[display_id]; - protection_mask = - task_response.enabled & ~task_response.unfulfilled & requested_mask; + auto it = content_protection_requests_.find(client_id); + if (success && it != content_protection_requests_.end()) { + const ContentProtections& protections = it->second; + + auto it = protections.find(display_id); + if (it != protections.end()) + client_mask = it->second; } + protection_mask &= client_mask; + DCHECK(!content_protection_tasks_.empty()); content_protection_tasks_.pop(); DCHECK(!query_protection_callbacks_.empty()); - QueryProtectionCallback callback = + QueryContentProtectionCallback callback = std::move(query_protection_callbacks_.front()); query_protection_callbacks_.pop(); - std::move(callback).Run(success, link_mask, protection_mask); + std::move(callback).Run(success, connection_mask, protection_mask); if (!content_protection_tasks_.empty()) content_protection_tasks_.front().Run(); } -void DisplayConfigurator::SetContentProtection(uint64_t client_id, - int64_t display_id, - uint32_t desired_method_mask, - SetProtectionCallback callback) { - if (!configure_display_ || display_externally_controlled_) { - std::move(callback).Run(false); +void DisplayConfigurator::ApplyContentProtection( + ContentProtectionClientId client_id, + int64_t display_id, + uint32_t protection_mask, + ApplyContentProtectionCallback callback) { + if (!client_id || configurator_disabled()) { + std::move(callback).Run(/*success=*/false); return; } ContentProtections protections; - for (const auto& requests_pair : client_protection_requests_) { + for (const auto& requests_pair : content_protection_requests_) { for (const auto& protections_pair : requests_pair.second) { - if (requests_pair.first == client_id && + if (requests_pair.first == *client_id && protections_pair.first == display_id) continue; protections[protections_pair.first] |= protections_pair.second; } } - protections[display_id] |= desired_method_mask; + protections[display_id] |= protection_mask; - set_protection_callbacks_.push(std::move(callback)); + apply_protection_callbacks_.push(std::move(callback)); ApplyContentProtectionTask* task = new ApplyContentProtectionTask( layout_manager_.get(), native_display_delegate_.get(), protections, - base::Bind(&DisplayConfigurator::OnSetContentProtectionCompleted, - weak_ptr_factory_.GetWeakPtr(), client_id, display_id, - desired_method_mask)); + base::Bind(&DisplayConfigurator::OnContentProtectionApplied, + weak_ptr_factory_.GetWeakPtr(), *client_id, display_id, + protection_mask)); content_protection_tasks_.push( base::Bind(&ApplyContentProtectionTask::Run, base::Owned(task))); if (content_protection_tasks_.size() == 1) content_protection_tasks_.front().Run(); } -void DisplayConfigurator::OnSetContentProtectionCompleted( - uint64_t client_id, - int64_t display_id, - uint32_t desired_method_mask, - bool success) { +void DisplayConfigurator::OnContentProtectionApplied(uint64_t client_id, + int64_t display_id, + uint32_t protection_mask, + bool success) { DCHECK(!content_protection_tasks_.empty()); content_protection_tasks_.pop(); - DCHECK(!set_protection_callbacks_.empty()); - SetProtectionCallback callback = std::move(set_protection_callbacks_.front()); - set_protection_callbacks_.pop(); + DCHECK(!apply_protection_callbacks_.empty()); + ApplyContentProtectionCallback callback = + std::move(apply_protection_callbacks_.front()); + apply_protection_callbacks_.pop(); if (!success) { std::move(callback).Run(false); return; } - if (desired_method_mask == CONTENT_PROTECTION_METHOD_NONE) { - if (client_protection_requests_.find(client_id) != - client_protection_requests_.end()) { - client_protection_requests_[client_id].erase(display_id); - if (client_protection_requests_[client_id].size() == 0) - client_protection_requests_.erase(client_id); + if (protection_mask == CONTENT_PROTECTION_METHOD_NONE) { + auto it = content_protection_requests_.find(client_id); + if (it != content_protection_requests_.end()) { + ContentProtections& protections = it->second; + protections.erase(display_id); + + if (protections.empty()) + content_protection_requests_.erase(client_id); } } else { - client_protection_requests_[client_id][display_id] = desired_method_mask; + content_protection_requests_[client_id][display_id] = protection_mask; } std::move(callback).Run(true); @@ -997,7 +1009,7 @@ chromeos::DisplayPowerState power_state, int flags, const ConfigurationCallback& callback) { - if (!configure_display_ || display_externally_controlled_) { + if (configurator_disabled()) { callback.Run(false); return; } @@ -1012,7 +1024,7 @@ } void DisplayConfigurator::SetDisplayMode(MultipleDisplayState new_state) { - if (!configure_display_ || display_externally_controlled_) + if (configurator_disabled()) return; VLOG(1) << "SetDisplayMode: state=" @@ -1064,7 +1076,7 @@ void DisplayConfigurator::SuspendDisplays( const ConfigurationCallback& callback) { - if (!configure_display_ || display_externally_controlled_) { + if (configurator_disabled()) { callback.Run(false); return; } @@ -1084,7 +1096,7 @@ } void DisplayConfigurator::ResumeDisplays() { - if (!configure_display_ || display_externally_controlled_) + if (configurator_disabled()) return; displays_suspended_ = false; @@ -1114,7 +1126,7 @@ } void DisplayConfigurator::ConfigureDisplays() { - if (!configure_display_ || display_externally_controlled_) + if (configurator_disabled()) return; force_configure_ = true;
diff --git a/ui/display/manager/display_configurator.h b/ui/display/manager/display_configurator.h index 1ceb678..f7be296 100644 --- a/ui/display/manager/display_configurator.h +++ b/ui/display/manager/display_configurator.h
@@ -7,11 +7,11 @@ #include <stdint.h> -#include <map> #include <memory> #include <string> #include <vector> +#include "base/containers/flat_map.h" #include "base/containers/queue.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -48,28 +48,20 @@ class DISPLAY_MANAGER_EXPORT DisplayConfigurator : public NativeDisplayObserver { public: - enum : uint64_t { - INVALID_CLIENT_ID = 0, - }; - using ConfigurationCallback = base::Callback<void(bool /* success */)>; - using SetProtectionCallback = base::OnceCallback<void(bool /* success */)>; + // |connection_mask| is a DisplayConnectionType bitmask, and |protection_mask| + // is a ContentProtectionMethod bitmask. + using QueryContentProtectionCallback = base::OnceCallback< + void(bool success, uint32_t connection_mask, uint32_t protection_mask)>; + using ApplyContentProtectionCallback = base::OnceCallback<void(bool success)>; - // link_mask: The type of connected display links, which is a bitmask of - // DisplayConnectionType values. - // protection_mask: The desired protection methods, which is a bitmask of the - // ContentProtectionMethod values. - using QueryProtectionCallback = - base::OnceCallback<void(bool /* success */, - uint32_t /* link_mask */, - uint32_t /* protection_mask */)>; - using DisplayControlCallback = base::OnceCallback<void(bool /* success */)>; + using DisplayControlCallback = base::OnceCallback<void(bool success)>; using DisplayStateList = std::vector<DisplaySnapshot*>; - // Mapping a display_id to a protection request bitmask. - using ContentProtections = std::map<int64_t, uint32_t>; + using ContentProtections = + base::flat_map<int64_t /* display_id */, uint32_t /* protection_mask */>; class Observer { public: @@ -267,27 +259,19 @@ // suspended. void ResumeDisplays(); - // Registers a client for display protection and requests a client id. Returns - // 0 if requesting failed. - uint64_t RegisterContentProtectionClient(); + using ContentProtectionClientId = base::Optional<uint64_t>; - // Unregisters the client. - void UnregisterContentProtectionClient(uint64_t client_id); + ContentProtectionClientId RegisterContentProtectionClient(); + void UnregisterContentProtectionClient(ContentProtectionClientId client_id); - // Queries link status and protection status. |callback| is used to respond - // to the query. - void QueryContentProtectionStatus(uint64_t client_id, - int64_t display_id, - QueryProtectionCallback callback); - - // Requests the desired protection methods. - // |protection_mask| is the desired protection methods, which is a bitmask - // of the ContentProtectionMethod values. - // Returns true when the protection request has been made. - void SetContentProtection(uint64_t client_id, - int64_t display_id, - uint32_t protection_mask, - SetProtectionCallback callback); + void QueryContentProtection(ContentProtectionClientId client_id, + int64_t display_id, + QueryContentProtectionCallback callback); + // |protection_mask| is a ContentProtectionMethod bitmask. + void ApplyContentProtection(ContentProtectionClientId client_id, + int64_t display_id, + uint32_t protection_mask, + ApplyContentProtectionCallback callback); // Returns true if there is at least one display on. bool IsDisplayOn() const; @@ -321,8 +305,9 @@ class DisplayLayoutManagerImpl; - // Mapping a client to its protection request. - using ProtectionRequests = std::map<uint64_t, ContentProtections>; + bool configurator_disabled() const { + return !configure_display_ || display_externally_controlled_; + } // Updates |pending_*| members and applies the passed-in state. |callback| is // invoked (perhaps synchronously) on completion. @@ -345,9 +330,6 @@ MultipleDisplayState ChooseDisplayState( chromeos::DisplayPowerState power_state) const; - // Applies display protections according to requests. - bool ApplyProtections(const ContentProtections& requests); - // If |configuration_task_| isn't initialized, initializes it and starts the // configuration task. void RunPendingConfiguration(); @@ -382,10 +364,10 @@ uint64_t client_id, int64_t display_id, QueryContentProtectionTask::Response response); - void OnSetContentProtectionCompleted(uint64_t client_id, - int64_t display_id, - uint32_t desired_method_mask, - bool success); + void OnContentProtectionApplied(uint64_t client_id, + int64_t display_id, + uint32_t protection_mask, + bool success); void OnContentProtectionClientUnregistered(bool success); // Callbacks used to signal when the native platform has released/taken @@ -446,8 +428,8 @@ std::vector<ConfigurationCallback> in_progress_configuration_callbacks_; base::queue<base::Closure> content_protection_tasks_; - base::queue<QueryProtectionCallback> query_protection_callbacks_; - base::queue<SetProtectionCallback> set_protection_callbacks_; + base::queue<QueryContentProtectionCallback> query_protection_callbacks_; + base::queue<ApplyContentProtectionCallback> apply_protection_callbacks_; // True if the caller wants to force the display configuration process. bool force_configure_; @@ -462,11 +444,10 @@ // display configuration events when they are reported in short time spans. base::OneShotTimer configure_timer_; - // Id for next display protection client. - uint64_t next_display_protection_client_id_; + uint64_t next_content_protection_client_id_ = 0; - // Display protection requests of each client. - ProtectionRequests client_protection_requests_; + // Content protections requested by each client. + base::flat_map<uint64_t, ContentProtections> content_protection_requests_; // Display controlled by an external entity. bool display_externally_controlled_;
diff --git a/ui/display/manager/display_configurator_unittest.cc b/ui/display/manager/display_configurator_unittest.cc index d1018a88..3fb738a 100644 --- a/ui/display/manager/display_configurator_unittest.cc +++ b/ui/display/manager/display_configurator_unittest.cc
@@ -203,20 +203,8 @@ class DisplayConfiguratorTest : public testing::Test { public: - DisplayConfiguratorTest() - : small_mode_(gfx::Size(1366, 768), false, 60.0f), - big_mode_(gfx::Size(2560, 1600), false, 60.0f), - observer_(&configurator_), - test_api_(&configurator_), - config_waiter_(&test_api_), - set_content_protection_status_(false), - set_content_protection_call_count_(0), - query_content_protection_response_success_(false), - query_content_protection_response_link_mask_(0), - query_content_protection_response_protection_mask_(0), - query_content_protection_call_count_(0), - display_control_result_(CALLBACK_NOT_CALLED) {} - ~DisplayConfiguratorTest() override {} + DisplayConfiguratorTest() = default; + ~DisplayConfiguratorTest() override = default; void SetUp() override { log_.reset(new ActionLogger()); @@ -260,27 +248,27 @@ UpdateOutputs(2, false); } - void OnDisplayControlUpdated(bool status) { - display_control_result_ = (status ? CALLBACK_SUCCESS : CALLBACK_FAILURE); + void OnDisplayControlUpdated(bool success) { + display_control_result_ = success ? CALLBACK_SUCCESS : CALLBACK_FAILURE; } - void SetContentProtectionCallback(bool status) { - set_content_protection_status_ = status; - set_content_protection_call_count_++; + void ApplyContentProtectionCallback(bool success) { + apply_content_protection_success_ = success; + apply_content_protection_call_count_++; } void QueryContentProtectionCallback(bool success, - uint32_t link_mask, + uint32_t connection_mask, uint32_t protection_mask) { - query_content_protection_response_success_ = success; - query_content_protection_response_link_mask_ = link_mask; - query_content_protection_response_protection_mask_ = protection_mask; + query_content_protection_success_ = success; + query_content_protection_connection_mask_ = connection_mask; + query_content_protection_protection_mask_ = protection_mask; query_content_protection_call_count_++; } // Predefined modes that can be used by outputs. - const DisplayMode small_mode_; - const DisplayMode big_mode_; + const DisplayMode small_mode_{gfx::Size(1366, 768), false, 60.0f}; + const DisplayMode big_mode_{gfx::Size(2560, 1600), false, 60.0f}; protected: // Configures |native_display_delegate_| to return the first |num_outputs| @@ -331,21 +319,22 @@ TestStateController state_controller_; TestMirroringController mirroring_controller_; DisplayConfigurator configurator_; - TestObserver observer_; + TestObserver observer_{&configurator_}; std::unique_ptr<ActionLogger> log_; TestNativeDisplayDelegate* native_display_delegate_; // not owned - DisplayConfigurator::TestApi test_api_; - ConfigurationWaiter config_waiter_; - bool set_content_protection_status_; - int set_content_protection_call_count_; - bool query_content_protection_response_success_; - uint32_t query_content_protection_response_link_mask_; - uint32_t query_content_protection_response_protection_mask_; - int query_content_protection_call_count_; + DisplayConfigurator::TestApi test_api_{&configurator_}; + ConfigurationWaiter config_waiter_{&test_api_}; + + bool apply_content_protection_success_ = false; + int apply_content_protection_call_count_ = 0; + bool query_content_protection_success_ = false; + int query_content_protection_call_count_ = 0; + uint32_t query_content_protection_connection_mask_ = 0; + uint32_t query_content_protection_protection_mask_ = 0; std::unique_ptr<DisplaySnapshot> outputs_[3]; - CallbackResult display_control_result_; + CallbackResult display_control_result_ = CALLBACK_NOT_CALLED; private: DISALLOW_COPY_AND_ASSIGN(DisplayConfiguratorTest); @@ -942,60 +931,60 @@ configurator_.ForceInitialConfigure(); EXPECT_NE(kNoActions, log_->GetActionsAndClear()); - uint64_t id = configurator_.RegisterContentProtectionClient(); - EXPECT_NE(0u, id); + auto id = configurator_.RegisterContentProtectionClient(); + EXPECT_TRUE(id); // One output. UpdateOutputs(1, true); EXPECT_NE(kNoActions, log_->GetActionsAndClear()); - configurator_.QueryContentProtectionStatus( + configurator_.QueryContentProtection( id, outputs_[0]->display_id(), - base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback, - base::Unretained(this))); + base::BindOnce(&DisplayConfiguratorTest::QueryContentProtectionCallback, + base::Unretained(this))); EXPECT_EQ(1, query_content_protection_call_count_); - EXPECT_TRUE(query_content_protection_response_success_); + EXPECT_TRUE(query_content_protection_success_); EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_INTERNAL), - query_content_protection_response_link_mask_); + query_content_protection_connection_mask_); EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE), - query_content_protection_response_protection_mask_); + query_content_protection_protection_mask_); EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); // Two outputs. UpdateOutputs(2, true); EXPECT_NE(kNoActions, log_->GetActionsAndClear()); - configurator_.QueryContentProtectionStatus( + configurator_.QueryContentProtection( id, outputs_[1]->display_id(), - base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback, - base::Unretained(this))); + base::BindOnce(&DisplayConfiguratorTest::QueryContentProtectionCallback, + base::Unretained(this))); EXPECT_EQ(2, query_content_protection_call_count_); - EXPECT_TRUE(query_content_protection_response_success_); + EXPECT_TRUE(query_content_protection_success_); EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), - query_content_protection_response_link_mask_); + query_content_protection_connection_mask_); EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE), - query_content_protection_response_protection_mask_); + query_content_protection_protection_mask_); EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); - configurator_.SetContentProtection( + configurator_.ApplyContentProtection( id, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP, - base::Bind(&DisplayConfiguratorTest::SetContentProtectionCallback, - base::Unretained(this))); - EXPECT_EQ(1, set_content_protection_call_count_); - EXPECT_TRUE(set_content_protection_status_); + base::BindOnce(&DisplayConfiguratorTest::ApplyContentProtectionCallback, + base::Unretained(this))); + EXPECT_EQ(1, apply_content_protection_call_count_); + EXPECT_TRUE(apply_content_protection_success_); EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_DESIRED), log_->GetActionsAndClear()); // Enable protection. native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED); - configurator_.QueryContentProtectionStatus( + configurator_.QueryContentProtection( id, outputs_[1]->display_id(), - base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback, - base::Unretained(this))); + base::BindOnce(&DisplayConfiguratorTest::QueryContentProtectionCallback, + base::Unretained(this))); EXPECT_EQ(3, query_content_protection_call_count_); - EXPECT_TRUE(query_content_protection_response_success_); + EXPECT_TRUE(query_content_protection_success_); EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), - query_content_protection_response_link_mask_); + query_content_protection_connection_mask_); EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_HDCP), - query_content_protection_response_protection_mask_); + query_content_protection_protection_mask_); EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); // Protections should be disabled after unregister. @@ -1090,8 +1079,8 @@ } TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClients) { - uint64_t client1 = configurator_.RegisterContentProtectionClient(); - uint64_t client2 = configurator_.RegisterContentProtectionClient(); + auto client1 = configurator_.RegisterContentProtectionClient(); + auto client2 = configurator_.RegisterContentProtectionClient(); EXPECT_NE(client1, client2); Init(false); @@ -1100,60 +1089,60 @@ EXPECT_NE(kNoActions, log_->GetActionsAndClear()); // Clients never know state enableness for methods that they didn't request. - configurator_.SetContentProtection( + configurator_.ApplyContentProtection( client1, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP, - base::Bind(&DisplayConfiguratorTest::SetContentProtectionCallback, - base::Unretained(this))); - EXPECT_EQ(1, set_content_protection_call_count_); - EXPECT_TRUE(set_content_protection_status_); + base::BindOnce(&DisplayConfiguratorTest::ApplyContentProtectionCallback, + base::Unretained(this))); + EXPECT_EQ(1, apply_content_protection_call_count_); + EXPECT_TRUE(apply_content_protection_success_); EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_DESIRED).c_str(), log_->GetActionsAndClear()); native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED); - configurator_.QueryContentProtectionStatus( + configurator_.QueryContentProtection( client1, outputs_[1]->display_id(), - base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback, - base::Unretained(this))); + base::BindOnce(&DisplayConfiguratorTest::QueryContentProtectionCallback, + base::Unretained(this))); EXPECT_EQ(1, query_content_protection_call_count_); - EXPECT_TRUE(query_content_protection_response_success_); + EXPECT_TRUE(query_content_protection_success_); EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), - query_content_protection_response_link_mask_); + query_content_protection_connection_mask_); EXPECT_EQ(CONTENT_PROTECTION_METHOD_HDCP, - query_content_protection_response_protection_mask_); + query_content_protection_protection_mask_); - configurator_.QueryContentProtectionStatus( + configurator_.QueryContentProtection( client2, outputs_[1]->display_id(), - base::Bind(&DisplayConfiguratorTest::QueryContentProtectionCallback, - base::Unretained(this))); + base::BindOnce(&DisplayConfiguratorTest::QueryContentProtectionCallback, + base::Unretained(this))); EXPECT_EQ(2, query_content_protection_call_count_); - EXPECT_TRUE(query_content_protection_response_success_); + EXPECT_TRUE(query_content_protection_success_); EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), - query_content_protection_response_link_mask_); + query_content_protection_connection_mask_); EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, - query_content_protection_response_protection_mask_); + query_content_protection_protection_mask_); // Protections will be disabled only if no more clients request them. - configurator_.SetContentProtection( + configurator_.ApplyContentProtection( client2, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_NONE, - base::Bind(&DisplayConfiguratorTest::SetContentProtectionCallback, - base::Unretained(this))); - EXPECT_EQ(2, set_content_protection_call_count_); - EXPECT_TRUE(set_content_protection_status_); + base::BindOnce(&DisplayConfiguratorTest::ApplyContentProtectionCallback, + base::Unretained(this))); + EXPECT_EQ(2, apply_content_protection_call_count_); + EXPECT_TRUE(apply_content_protection_success_); EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); - configurator_.SetContentProtection( + configurator_.ApplyContentProtection( client1, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_NONE, - base::Bind(&DisplayConfiguratorTest::SetContentProtectionCallback, - base::Unretained(this))); - EXPECT_EQ(3, set_content_protection_call_count_); - EXPECT_TRUE(set_content_protection_status_); + base::BindOnce(&DisplayConfiguratorTest::ApplyContentProtectionCallback, + base::Unretained(this))); + EXPECT_EQ(3, apply_content_protection_call_count_); + EXPECT_TRUE(apply_content_protection_success_); EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_UNDESIRED).c_str(), log_->GetActionsAndClear()); } TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClientsEnable) { - uint64_t client1 = configurator_.RegisterContentProtectionClient(); - uint64_t client2 = configurator_.RegisterContentProtectionClient(); + auto client1 = configurator_.RegisterContentProtectionClient(); + auto client2 = configurator_.RegisterContentProtectionClient(); EXPECT_NE(client1, client2); Init(false); @@ -1162,36 +1151,36 @@ log_->GetActionsAndClear(); // Only enable once if HDCP is enabling. - configurator_.SetContentProtection( + configurator_.ApplyContentProtection( client1, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP, - base::Bind(&DisplayConfiguratorTest::SetContentProtectionCallback, - base::Unretained(this))); - EXPECT_EQ(1, set_content_protection_call_count_); - EXPECT_TRUE(set_content_protection_status_); + base::BindOnce(&DisplayConfiguratorTest::ApplyContentProtectionCallback, + base::Unretained(this))); + EXPECT_EQ(1, apply_content_protection_call_count_); + EXPECT_TRUE(apply_content_protection_success_); native_display_delegate_->set_hdcp_state(HDCP_STATE_DESIRED); - configurator_.SetContentProtection( + configurator_.ApplyContentProtection( client2, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP, - base::Bind(&DisplayConfiguratorTest::SetContentProtectionCallback, - base::Unretained(this))); - EXPECT_EQ(2, set_content_protection_call_count_); - EXPECT_TRUE(set_content_protection_status_); + base::BindOnce(&DisplayConfiguratorTest::ApplyContentProtectionCallback, + base::Unretained(this))); + EXPECT_EQ(2, apply_content_protection_call_count_); + EXPECT_TRUE(apply_content_protection_success_); EXPECT_EQ(GetSetHDCPStateAction(*outputs_[1], HDCP_STATE_DESIRED).c_str(), log_->GetActionsAndClear()); native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED); // Don't enable again if HDCP is already active. - configurator_.SetContentProtection( + configurator_.ApplyContentProtection( client1, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP, - base::Bind(&DisplayConfiguratorTest::SetContentProtectionCallback, - base::Unretained(this))); - EXPECT_EQ(3, set_content_protection_call_count_); - EXPECT_TRUE(set_content_protection_status_); - configurator_.SetContentProtection( + base::BindOnce(&DisplayConfiguratorTest::ApplyContentProtectionCallback, + base::Unretained(this))); + EXPECT_EQ(3, apply_content_protection_call_count_); + EXPECT_TRUE(apply_content_protection_success_); + configurator_.ApplyContentProtection( client2, outputs_[1]->display_id(), CONTENT_PROTECTION_METHOD_HDCP, - base::Bind(&DisplayConfiguratorTest::SetContentProtectionCallback, - base::Unretained(this))); - EXPECT_EQ(4, set_content_protection_call_count_); - EXPECT_TRUE(set_content_protection_status_); + base::BindOnce(&DisplayConfiguratorTest::ApplyContentProtectionCallback, + base::Unretained(this))); + EXPECT_EQ(4, apply_content_protection_call_count_); + EXPECT_TRUE(apply_content_protection_success_); EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners.js b/ui/file_manager/file_manager/foreground/js/ui/banners.js index 5b369986..eeaa760 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/banners.js +++ b/ui/file_manager/file_manager/foreground/js/ui/banners.js
@@ -3,91 +3,6 @@ // found in the LICENSE file. /** - * Responsible for showing following banners in the file list. - * - WelcomeBanner - * - AuthFailBanner - * @param {DirectoryModel} directoryModel The model. - * @param {!VolumeManager} volumeManager The manager. - * @param {Document} document HTML document. - * @param {boolean} showWelcome True if the welcome banner can be shown. - * @constructor - * @extends {cr.EventTarget} - */ -function Banners(directoryModel, volumeManager, document, showWelcome) { - this.directoryModel_ = directoryModel; - this.volumeManager_ = volumeManager; - this.document_ = assert(document); - this.showWelcome_ = showWelcome; - this.driveEnabled_ = false; - - this.privateOnDirectoryChangedBound_ = - this.privateOnDirectoryChanged_.bind(this); - - const handler = this.checkSpaceAndMaybeShowWelcomeBanner_.bind(this); - this.directoryModel_.addEventListener('scan-completed', handler); - this.directoryModel_.addEventListener('rescan-completed', handler); - this.directoryModel_.addEventListener( - 'directory-changed', this.onDirectoryChanged_.bind(this)); - - this.unmountedPanel_ = this.document_.querySelector('#unmounted-panel'); - this.volumeManager_.volumeInfoList.addEventListener( - 'splice', this.onVolumeInfoListSplice_.bind(this)); - this.volumeManager_.addEventListener( - 'drive-connection-changed', this.onDriveConnectionChanged_.bind(this)); - - chrome.storage.onChanged.addListener(this.onStorageChange_.bind(this)); - this.welcomeHeaderCounter_ = WELCOME_HEADER_COUNTER_LIMIT; - this.warningDismissedCounter_ = 0; - this.downloadsWarningDismissedTime_ = 0; - - this.ready_ = new Promise((resolve, reject) => { - chrome.storage.local.get( - [ - WELCOME_HEADER_COUNTER_KEY, DRIVE_WARNING_DISMISSED_KEY, - DOWNLOADS_WARNING_DISMISSED_KEY - ], - values => { - if (chrome.runtime.lastError) { - reject( - 'Failed to load banner data from chrome.storage: ' + - chrome.runtime.lastError.message); - return; - } - this.welcomeHeaderCounter_ = - parseInt(values[WELCOME_HEADER_COUNTER_KEY], 10) || 0; - this.warningDismissedCounter_ = - parseInt(values[DRIVE_WARNING_DISMISSED_KEY], 10) || 0; - this.downloadsWarningDismissedTime_ = - parseInt(values[DOWNLOADS_WARNING_DISMISSED_KEY], 10) || 0; - - // If it's in test, override the counter to show the header by - // force. - if (chrome.test) { - this.welcomeHeaderCounter_ = 0; - this.warningDismissedCounter_ = 0; - } - resolve(); - }); - }); - - // Authentication failed banner. - this.authFailedBanner_ = - this.document_.querySelector('#drive-auth-failed-warning'); - const authFailedText = this.authFailedBanner_.querySelector('.drive-text'); - authFailedText.innerHTML = util.htmlUnescape(str('DRIVE_NOT_REACHED')); - authFailedText.querySelector('a').addEventListener('click', e => { - chrome.fileManagerPrivate.logoutUserForReauthentication(); - e.preventDefault(); - }); - this.maybeShowAuthFailBanner_(); -} - -/** - * Banners extends cr.EventTarget. - */ -Banners.prototype.__proto__ = cr.EventTarget.prototype; - -/** * Key in localStorage to keep number of times the Drive Welcome * banner has shown. */ @@ -131,579 +46,671 @@ const DOWNLOADS_SPACE_WARNING_DISMISS_DURATION = 36 * 60 * 60 * 1000; /** - * @param {number} value How many times the Drive Welcome header banner - * has shown. - * @private + * Responsible for showing following banners in the file list. + * - WelcomeBanner + * - AuthFailBanner */ -Banners.prototype.setWelcomeHeaderCounter_ = value => { - const values = {}; - values[WELCOME_HEADER_COUNTER_KEY] = value; - chrome.storage.local.set(values); -}; +class Banners extends cr.EventTarget { + /** + * @param {DirectoryModel} directoryModel The model. + * @param {!VolumeManager} volumeManager The manager. + * @param {Document} document HTML document. + * @param {boolean} showWelcome True if the welcome banner can be shown. + */ + constructor(directoryModel, volumeManager, document, showWelcome) { + super(); -/** - * @param {number} value How many times the low space warning has dismissed. - * @private - */ -Banners.prototype.setWarningDismissedCounter_ = value => { - const values = {}; - values[DRIVE_WARNING_DISMISSED_KEY] = value; - chrome.storage.local.set(values); -}; + this.directoryModel_ = directoryModel; + this.volumeManager_ = volumeManager; + this.document_ = assert(document); + this.showWelcome_ = showWelcome; + this.driveEnabled_ = false; -/** - * chrome.storage.onChanged event handler. - * @param {Object<Object>} changes Changes values. - * @param {string} areaName "local" or "sync". - * @private - */ -Banners.prototype.onStorageChange_ = function(changes, areaName) { - if (areaName == 'local' && WELCOME_HEADER_COUNTER_KEY in changes) { - this.welcomeHeaderCounter_ = changes[WELCOME_HEADER_COUNTER_KEY].newValue; - } - if (areaName == 'local' && DRIVE_WARNING_DISMISSED_KEY in changes) { - this.warningDismissedCounter_ = - changes[DRIVE_WARNING_DISMISSED_KEY].newValue; - } - if (areaName == 'local' && DOWNLOADS_WARNING_DISMISSED_KEY in changes) { - this.downloadsWarningDismissedTime_ = - changes[DOWNLOADS_WARNING_DISMISSED_KEY].newValue; - } -}; + /** @private {boolean} */ + this.previousDirWasOnDrive_ = false; -/** - * Invoked when the drive connection status is change in the volume manager. - * @private - */ -Banners.prototype.onDriveConnectionChanged_ = function() { - this.maybeShowAuthFailBanner_(); -}; + this.privateOnDirectoryChangedBound_ = + this.privateOnDirectoryChanged_.bind(this); -/** - * @param {string} type 'none'|'page'|'header'. - * @param {string} messageId Resource ID of the message. - * @private - */ -Banners.prototype.prepareAndShowWelcomeBanner_ = function(type, messageId) { - if (!this.showWelcome_) { - return; - } + const handler = this.checkSpaceAndMaybeShowWelcomeBanner_.bind(this); + this.directoryModel_.addEventListener('scan-completed', handler); + this.directoryModel_.addEventListener('rescan-completed', handler); + this.directoryModel_.addEventListener( + 'directory-changed', this.onDirectoryChanged_.bind(this)); - this.showWelcomeBanner_(type); + this.unmountedPanel_ = this.document_.querySelector('#unmounted-panel'); + this.volumeManager_.volumeInfoList.addEventListener( + 'splice', this.onVolumeInfoListSplice_.bind(this)); + this.volumeManager_.addEventListener( + 'drive-connection-changed', this.onDriveConnectionChanged_.bind(this)); - const container = - queryRequiredElement('.drive-welcome.' + type, this.document_); - if (container.firstElementChild) { - return; - } // Do not re-create. + chrome.storage.onChanged.addListener(this.onStorageChange_.bind(this)); + this.welcomeHeaderCounter_ = WELCOME_HEADER_COUNTER_LIMIT; + this.warningDismissedCounter_ = 0; + this.downloadsWarningDismissedTime_ = 0; - if (!this.document_.querySelector('link[drive-welcome-style]')) { - const style = this.document_.createElement('link'); - style.rel = 'stylesheet'; - style.href = constants.DRIVE_WELCOME_CSS; - style.setAttribute('drive-welcome-style', ''); - this.document_.head.appendChild(style); - } + this.ready_ = new Promise((resolve, reject) => { + chrome.storage.local.get( + [ + WELCOME_HEADER_COUNTER_KEY, DRIVE_WARNING_DISMISSED_KEY, + DOWNLOADS_WARNING_DISMISSED_KEY + ], + values => { + if (chrome.runtime.lastError) { + reject( + 'Failed to load banner data from chrome.storage: ' + + chrome.runtime.lastError.message); + return; + } + this.welcomeHeaderCounter_ = + parseInt(values[WELCOME_HEADER_COUNTER_KEY], 10) || 0; + this.warningDismissedCounter_ = + parseInt(values[DRIVE_WARNING_DISMISSED_KEY], 10) || 0; + this.downloadsWarningDismissedTime_ = + parseInt(values[DOWNLOADS_WARNING_DISMISSED_KEY], 10) || 0; - const wrapper = util.createChild(container, 'drive-welcome-wrapper'); - util.createChild(wrapper, 'drive-welcome-icon'); + // If it's in test, override the counter to show the header by + // force. + if (chrome.test) { + this.welcomeHeaderCounter_ = 0; + this.warningDismissedCounter_ = 0; + } + resolve(); + }); + }); - if (type === 'header') { - util.createChild(wrapper, 'banner-cloud-bg'); - util.createChild(wrapper, 'banner-people'); - } - - const close = util.createChild(wrapper, 'banner-close'); - close.addEventListener('click', this.closeWelcomeBanner_.bind(this)); - - const message = util.createChild(wrapper, 'drive-welcome-message'); - - const title = util.createChild(message, 'drive-welcome-title'); - - const text = util.createChild(message, 'drive-welcome-text'); - text.innerHTML = str(messageId); - - const links = util.createChild(message, 'drive-welcome-links'); - - title.textContent = str('DRIVE_WELCOME_TITLE'); - const more = util.createChild(links, 'plain-link', 'a'); - more.textContent = str('DRIVE_LEARN_MORE'); - more.href = str('GOOGLE_DRIVE_OVERVIEW_URL'); - more.tabIndex = 21; // See: go/filesapp-tabindex. - more.id = 'drive-welcome-link'; - more.target = '_blank'; - - const dismiss = util.createChild(links, 'plain-link'); - dismiss.classList.add('drive-welcome-dismiss'); - dismiss.textContent = str('DRIVE_WELCOME_DISMISS'); - dismiss.addEventListener('click', this.closeWelcomeBanner_.bind(this)); - - this.previousDirWasOnDrive_ = false; -}; - -/** - * Show or hide the "Low Google Drive space" warning. - * @param {boolean} show True if the box need to be shown. - * @param {Object=} opt_sizeStats Size statistics. Should be defined when - * showing the warning. - * @private - */ -Banners.prototype.showLowDriveSpaceWarning_ = function(show, opt_sizeStats) { - const box = this.document_.querySelector('#volume-space-warning'); - - // Avoid showing two banners. - // TODO(kaznacheev): Unify the low space warning and the promo header. - if (show) { - this.cleanupWelcomeBanner_(); - } - - if (box.hidden == !show) { - return; - } - - if (this.warningDismissedCounter_) { - if (opt_sizeStats && - // Quota had not changed - this.warningDismissedCounter_ == opt_sizeStats.totalSize && - opt_sizeStats.remainingSize / opt_sizeStats.totalSize < 0.15) { - // Since the last dismissal decision the quota has not changed AND - // the user did not free up significant space. Obey the dismissal. - show = false; - } else { - // Forget the dismissal. Warning will be shown again. - this.setWarningDismissedCounter_(0); - } - } - - box.textContent = ''; - if (show && opt_sizeStats) { - const icon = this.document_.createElement('div'); - icon.className = 'drive-icon'; - box.appendChild(icon); - - const text = this.document_.createElement('div'); - text.className = 'drive-text'; - text.textContent = strf( - 'DRIVE_SPACE_AVAILABLE_LONG', - util.bytesToString(opt_sizeStats.remainingSize)); - box.appendChild(text); - - const link = this.document_.createElement('a'); - link.href = str('GOOGLE_DRIVE_BUY_STORAGE_URL'); - link.target = '_blank'; - const button = this.document_.createElement('button'); - button.className = 'imitate-paper-button'; - button.textContent = str('DRIVE_BUY_MORE_SPACE_LINK'); - link.appendChild(button); - box.appendChild(link); - - const close = this.document_.createElement('div'); - close.className = 'banner-close'; - box.appendChild(close); - close.addEventListener('click', ((total) => { - const values = {}; - values[DRIVE_WARNING_DISMISSED_KEY] = - total; - chrome.storage.local.set(values); - box.hidden = true; - this.requestRelayout_(100); - }).bind(null, opt_sizeStats.totalSize)); - } - - if (box.hidden != !show) { - box.hidden = !show; - this.requestRelayout_(100); - } -}; -/** - * Closes the Drive Welcome banner. - * @private - */ -Banners.prototype.closeWelcomeBanner_ = function() { - this.cleanupWelcomeBanner_(); - // Stop showing the welcome banner. - this.setWelcomeHeaderCounter_(WELCOME_HEADER_COUNTER_LIMIT); -}; - -/** - * Shows or hides the welcome banner for drive. - * @private - */ -Banners.prototype.checkSpaceAndMaybeShowWelcomeBanner_ = function() { - this.ready_.then(() => { - if (!this.isOnCurrentProfileDrive()) { - // We are not on the drive file system. Do not show (close) the welcome - // banner. - this.cleanupWelcomeBanner_(); - this.previousDirWasOnDrive_ = false; - return; - } - - const driveVolume = this.volumeManager_.getCurrentProfileVolumeInfo( - VolumeManagerCommon.VolumeType.DRIVE); - if (this.welcomeHeaderCounter_ >= WELCOME_HEADER_COUNTER_LIMIT || - !driveVolume || driveVolume.error) { - // The banner is already shown enough times or the drive FS is not - // mounted. So, do nothing here. - return; - } - - this.maybeShowWelcomeBanner_(); - }); -}; - -/** - * Decides which banner should be shown, and show it. This method is designed - * to be called only from checkSpaceAndMaybeShowWelcomeBanner_. - * @private - */ -Banners.prototype.maybeShowWelcomeBanner_ = function() { - this.ready_.then(() => { - if (this.directoryModel_.getFileList().length == 0 && - this.welcomeHeaderCounter_ == 0) { - // Only show the full page banner if the header banner was never shown. - // Do not increment the counter. - // The timeout below is required because sometimes another - // 'rescan-completed' event arrives shortly with non-empty file list. - setTimeout(() => { - if (this.isOnCurrentProfileDrive() && this.welcomeHeaderCounter_ == 0) { - this.prepareAndShowWelcomeBanner_('page', 'DRIVE_WELCOME_TEXT_LONG'); - } - }, 2000); - } else { - // We do not want to increment the counter when the user navigates - // between different directories on Drive, but we increment the counter - // once anyway to prevent the full page banner from showing. - if (!this.previousDirWasOnDrive_ || this.welcomeHeaderCounter_ == 0) { - this.setWelcomeHeaderCounter_(this.welcomeHeaderCounter_ + 1); - this.prepareAndShowWelcomeBanner_('header', 'DRIVE_WELCOME_TEXT_SHORT'); - } - } - this.previousDirWasOnDrive_ = true; - }); -}; - -/** - * @return {boolean} True if current directory is on Drive root of current - * profile. - */ -Banners.prototype.isOnCurrentProfileDrive = function() { - const entry = this.directoryModel_.getCurrentDirEntry(); - if (!entry || util.isFakeEntry(entry)) { - return false; - } - const locationInfo = this.volumeManager_.getLocationInfo(entry); - if (!locationInfo) { - return false; - } - return locationInfo.rootType === VolumeManagerCommon.RootType.DRIVE && - locationInfo.volumeInfo.profile.isCurrentProfile; -}; - -/** - * Shows the Drive Welcome banner. - * @param {string} type 'page'|'head'|'none'. - * @private - */ -Banners.prototype.showWelcomeBanner_ = function(type) { - const container = this.document_.querySelector('.dialog-container'); - if (container.getAttribute('drive-welcome') != type) { - container.setAttribute('drive-welcome', type); - this.requestRelayout_(200); // Resize only after the animation is done. - } -}; - -/** - * Update the UI when the current directory changes. - * - * @param {Event} event The directory-changed event. - * @private - */ -Banners.prototype.onDirectoryChanged_ = function(event) { - const rootVolume = this.volumeManager_.getVolumeInfo(event.newDirEntry); - if (!rootVolume) { - return; - } - const previousRootVolume = event.previousDirEntry ? - this.volumeManager_.getVolumeInfo(event.previousDirEntry) : - null; - - // Show (or hide) the low space warning. - this.maybeShowLowSpaceWarning_(rootVolume); - - // Add or remove listener to show low space warning, if necessary. - const isLowSpaceWarningTarget = this.isLowSpaceWarningTarget_(rootVolume); - if (isLowSpaceWarningTarget !== - this.isLowSpaceWarningTarget_(previousRootVolume)) { - if (isLowSpaceWarningTarget) { - chrome.fileManagerPrivate.onDirectoryChanged.addListener( - this.privateOnDirectoryChangedBound_); - } else { - chrome.fileManagerPrivate.onDirectoryChanged.removeListener( - this.privateOnDirectoryChangedBound_); - } - } - - if (!this.isOnCurrentProfileDrive()) { - this.cleanupWelcomeBanner_(); - this.authFailedBanner_.hidden = true; - } - - this.updateDriveUnmountedPanel_(); - if (this.isOnCurrentProfileDrive()) { - this.unmountedPanel_.classList.remove('retry-enabled'); - this.maybeShowAuthFailBanner_(); - } -}; - -/** - * @param {VolumeInfo} volumeInfo Volume info to be checked. - * @return {boolean} true if the file system specified by |root| is a target - * to show low space warning. Otherwise false. - * @private - */ -Banners.prototype.isLowSpaceWarningTarget_ = volumeInfo => { - if (!volumeInfo) { - return false; - } - return volumeInfo.profile.isCurrentProfile && - (volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DOWNLOADS || - volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DRIVE); -}; - -/** - * Callback which is invoked when the file system has been changed. - * @param {Object} event chrome.fileManagerPrivate.onDirectoryChanged event. - * @private - */ -Banners.prototype.privateOnDirectoryChanged_ = function(event) { - const currentDirEntry = this.directoryModel_.getCurrentDirEntry(); - if (!currentDirEntry) { - return; - } - const currentVolume = this.volumeManager_.getVolumeInfo(currentDirEntry); - if (!currentVolume) { - return; - } - const eventVolume = this.volumeManager_.getVolumeInfo(event.entry); - if (currentVolume === eventVolume) { - // The file system we are currently on is changed. - // So, check the free space. - this.maybeShowLowSpaceWarning_(currentVolume); - } -}; - -/** - * Shows or hides the low space warning. - * @param {VolumeInfo} volume Type of volume, which we are interested in. - * @private - */ -Banners.prototype.maybeShowLowSpaceWarning_ = function(volume) { - // TODO(kaznacheev): Unify the two low space warning. - switch (volume.volumeType) { - case VolumeManagerCommon.VolumeType.DOWNLOADS: - this.showLowDriveSpaceWarning_(false); - break; - case VolumeManagerCommon.VolumeType.DRIVE: - this.showLowDownloadsSpaceWarning_(false); - break; - default: - // If the current file system is neither the DOWNLOAD nor the DRIVE, - // just hide the warning. - this.showLowDownloadsSpaceWarning_(false); - this.showLowDriveSpaceWarning_(false); - return; - } - - // If not mounted correctly, then do not continue. - if (!volume.fileSystem) { - return; - } - - chrome.fileManagerPrivate.getSizeStats(volume.volumeId, sizeStats => { - const currentVolume = this.volumeManager_.getVolumeInfo( - assert(this.directoryModel_.getCurrentDirEntry())); - if (volume !== currentVolume) { - // This happens when the current directory is moved during requesting - // the file system size. Just ignore it. - return; - } - // sizeStats is undefined, if some error occurs. - if (!sizeStats || sizeStats.totalSize == 0) { - return; - } - - if (volume.volumeType === VolumeManagerCommon.VolumeType.DOWNLOADS) { - // Show the warning banner when the available space is less than 1GB. - this.showLowDownloadsSpaceWarning_( - sizeStats.remainingSize < DOWNLOADS_SPACE_WARNING_THRESHOLD_SIZE); - } else { - // Show the warning banner when the available space ls less than 10%. - const remainingRatio = sizeStats.remainingSize / sizeStats.totalSize; - this.showLowDriveSpaceWarning_( - remainingRatio < DRIVE_SPACE_WARNING_THRESHOLD_RATIO, sizeStats); - } - }); -}; - -/** - * removes the Drive Welcome banner. - * @private - */ -Banners.prototype.cleanupWelcomeBanner_ = function() { - this.showWelcomeBanner_('none'); -}; - -/** - * Notifies the file manager what layout must be recalculated. - * @param {number} delay In milliseconds. - * @private - */ -Banners.prototype.requestRelayout_ = function(delay) { - const self = this; - setTimeout(() => { - cr.dispatchSimpleEvent(self, 'relayout'); - }, delay); -}; - -/** - * Show or hide the "Low disk space" warning. - * @param {boolean} show True if the box need to be shown. - * @private - */ -Banners.prototype.showLowDownloadsSpaceWarning_ = function(show) { - const box = this.document_.querySelector('.downloads-warning'); - - if (box.hidden == !show) { - return; - } - - if (this.downloadsWarningDismissedTime_) { - if (Date.now() - this.downloadsWarningDismissedTime_ < - DOWNLOADS_SPACE_WARNING_DISMISS_DURATION) { - show = false; - } - } - - box.textContent = ''; - if (show) { - const icon = this.document_.createElement('div'); - icon.className = 'warning-icon'; - const message = this.document_.createElement('div'); - message.className = 'warning-message'; - message.innerHTML = util.htmlUnescape(str('DOWNLOADS_DIRECTORY_WARNING')); - box.appendChild(icon); - box.appendChild(message); - box.querySelector('a').addEventListener('click', e => { - util.visitURL(str('DOWNLOADS_LOW_SPACE_WARNING_HELP_URL')); + // Authentication failed banner. + this.authFailedBanner_ = + this.document_.querySelector('#drive-auth-failed-warning'); + const authFailedText = this.authFailedBanner_.querySelector('.drive-text'); + authFailedText.innerHTML = util.htmlUnescape(str('DRIVE_NOT_REACHED')); + authFailedText.querySelector('a').addEventListener('click', e => { + chrome.fileManagerPrivate.logoutUserForReauthentication(); e.preventDefault(); }); - - const close = this.document_.createElement('div'); - close.className = 'banner-close'; - close.tabIndex = 0; - box.appendChild(close); - close.addEventListener('click', () => { - const values = {}; - values[DOWNLOADS_WARNING_DISMISSED_KEY] = Date.now(); - chrome.storage.local.set(values); - box.hidden = true; - // We explicitly mark the banner-close element as hidden as due to the - // use of position absolute in it's layout it does not get hidden by - // hiding it's parent. - close.hidden = true; - this.requestRelayout_(100); - }); - } - - box.hidden = !show; - this.requestRelayout_(100); -}; - -/** - * Creates contents for the DRIVE unmounted panel. - * @private - */ -Banners.prototype.ensureDriveUnmountedPanelInitialized_ = function() { - const panel = this.unmountedPanel_; - if (panel.firstElementChild) { - return; + this.maybeShowAuthFailBanner_(); } /** - * Creates an element using given parameters. - * @param {!Element} parent Parent element of the new element. - * @param {string} tag Tag of the new element. - * @param {string} className Class name of the new element. - * @param {string=} opt_textContent Text content of the new element. - * @return {!Element} The newly created element. + * @param {number} value How many times the Drive Welcome header banner + * has shown. + * @private */ - const create = (parent, tag, className, opt_textContent) => { - const div = panel.ownerDocument.createElement(tag); - div.className = className; - div.textContent = opt_textContent || ''; - parent.appendChild(div); - return div; - }; - - create(panel, 'div', 'error', str('DRIVE_CANNOT_REACH')); - - const learnMore = - create(panel, 'a', 'learn-more plain-link', str('DRIVE_LEARN_MORE')); - learnMore.href = str('GOOGLE_DRIVE_ERROR_HELP_URL'); - learnMore.target = '_blank'; -}; - -/** - * Called when volume info list is updated. - * @param {Event} event Splice event data on volume info list. - * @private - */ -Banners.prototype.onVolumeInfoListSplice_ = function(event) { - const isDriveVolume = volumeInfo => { - return volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DRIVE; - }; - if (event.removed.some(isDriveVolume) || event.added.some(isDriveVolume)) { - this.updateDriveUnmountedPanel_(); + setWelcomeHeaderCounter_(value) { + const values = {}; + values[WELCOME_HEADER_COUNTER_KEY] = value; + chrome.storage.local.set(values); } -}; -/** - * Shows the panel when current directory is DRIVE and it's unmounted. - * Hides it otherwise. The panel shows an error message if it failed. - * @private - */ -Banners.prototype.updateDriveUnmountedPanel_ = function() { - const node = this.document_.body; - if (this.isOnCurrentProfileDrive()) { - const driveVolume = this.volumeManager_.getCurrentProfileVolumeInfo( - VolumeManagerCommon.VolumeType.DRIVE); - if (driveVolume) { - if (driveVolume.error) { - this.ensureDriveUnmountedPanelInitialized_(); - this.unmountedPanel_.classList.add('retry-enabled'); - node.setAttribute('drive', 'error'); + /** + * @param {number} value How many times the low space warning has dismissed. + * @private + */ + setWarningDismissedCounter_(value) { + const values = {}; + values[DRIVE_WARNING_DISMISSED_KEY] = value; + chrome.storage.local.set(values); + } + + /** + * chrome.storage.onChanged event handler. + * @param {Object<Object>} changes Changes values. + * @param {string} areaName "local" or "sync". + * @private + */ + onStorageChange_(changes, areaName) { + if (areaName == 'local' && WELCOME_HEADER_COUNTER_KEY in changes) { + this.welcomeHeaderCounter_ = changes[WELCOME_HEADER_COUNTER_KEY].newValue; + } + if (areaName == 'local' && DRIVE_WARNING_DISMISSED_KEY in changes) { + this.warningDismissedCounter_ = + changes[DRIVE_WARNING_DISMISSED_KEY].newValue; + } + if (areaName == 'local' && DOWNLOADS_WARNING_DISMISSED_KEY in changes) { + this.downloadsWarningDismissedTime_ = + changes[DOWNLOADS_WARNING_DISMISSED_KEY].newValue; + } + } + + /** + * Invoked when the drive connection status is change in the volume manager. + * @private + */ + onDriveConnectionChanged_() { + this.maybeShowAuthFailBanner_(); + } + + /** + * @param {string} type 'none'|'page'|'header'. + * @param {string} messageId Resource ID of the message. + * @private + */ + prepareAndShowWelcomeBanner_(type, messageId) { + if (!this.showWelcome_) { + return; + } + + this.showWelcomeBanner_(type); + + const container = + queryRequiredElement('.drive-welcome.' + type, this.document_); + if (container.firstElementChild) { + return; + } // Do not re-create. + + if (!this.document_.querySelector('link[drive-welcome-style]')) { + const style = this.document_.createElement('link'); + style.rel = 'stylesheet'; + style.href = constants.DRIVE_WELCOME_CSS; + style.setAttribute('drive-welcome-style', ''); + this.document_.head.appendChild(style); + } + + const wrapper = util.createChild(container, 'drive-welcome-wrapper'); + util.createChild(wrapper, 'drive-welcome-icon'); + + if (type === 'header') { + util.createChild(wrapper, 'banner-cloud-bg'); + util.createChild(wrapper, 'banner-people'); + } + + const close = util.createChild(wrapper, 'banner-close'); + close.addEventListener('click', this.closeWelcomeBanner_.bind(this)); + + const message = util.createChild(wrapper, 'drive-welcome-message'); + + const title = util.createChild(message, 'drive-welcome-title'); + + const text = util.createChild(message, 'drive-welcome-text'); + text.innerHTML = str(messageId); + + const links = util.createChild(message, 'drive-welcome-links'); + + title.textContent = str('DRIVE_WELCOME_TITLE'); + const more = util.createChild(links, 'plain-link', 'a'); + more.textContent = str('DRIVE_LEARN_MORE'); + more.href = str('GOOGLE_DRIVE_OVERVIEW_URL'); + more.tabIndex = 21; // See: go/filesapp-tabindex. + more.id = 'drive-welcome-link'; + more.target = '_blank'; + + const dismiss = util.createChild(links, 'plain-link'); + dismiss.classList.add('drive-welcome-dismiss'); + dismiss.textContent = str('DRIVE_WELCOME_DISMISS'); + dismiss.addEventListener('click', this.closeWelcomeBanner_.bind(this)); + + this.previousDirWasOnDrive_ = false; + } + + /** + * Show or hide the "Low Google Drive space" warning. + * @param {boolean} show True if the box need to be shown. + * @param {Object=} opt_sizeStats Size statistics. Should be defined when + * showing the warning. + * @private + */ + showLowDriveSpaceWarning_(show, opt_sizeStats) { + const box = this.document_.querySelector('#volume-space-warning'); + + // Avoid showing two banners. + // TODO(kaznacheev): Unify the low space warning and the promo header. + if (show) { + this.cleanupWelcomeBanner_(); + } + + if (box.hidden == !show) { + return; + } + + if (this.warningDismissedCounter_) { + if (opt_sizeStats && + // Quota had not changed + this.warningDismissedCounter_ == opt_sizeStats.totalSize && + opt_sizeStats.remainingSize / opt_sizeStats.totalSize < 0.15) { + // Since the last dismissal decision the quota has not changed AND + // the user did not free up significant space. Obey the dismissal. + show = false; } else { - node.setAttribute('drive', 'mounted'); + // Forget the dismissal. Warning will be shown again. + this.setWarningDismissedCounter_(0); + } + } + + box.textContent = ''; + if (show && opt_sizeStats) { + const icon = this.document_.createElement('div'); + icon.className = 'drive-icon'; + box.appendChild(icon); + + const text = this.document_.createElement('div'); + text.className = 'drive-text'; + text.textContent = strf( + 'DRIVE_SPACE_AVAILABLE_LONG', + util.bytesToString(opt_sizeStats.remainingSize)); + box.appendChild(text); + + const link = this.document_.createElement('a'); + link.href = str('GOOGLE_DRIVE_BUY_STORAGE_URL'); + link.target = '_blank'; + const button = this.document_.createElement('button'); + button.className = 'imitate-paper-button'; + button.textContent = str('DRIVE_BUY_MORE_SPACE_LINK'); + link.appendChild(button); + box.appendChild(link); + + const close = this.document_.createElement('div'); + close.className = 'banner-close'; + box.appendChild(close); + close.addEventListener('click', ((total) => { + const values = {}; + values[DRIVE_WARNING_DISMISSED_KEY] = + total; + chrome.storage.local.set(values); + box.hidden = true; + this.requestRelayout_(100); + }).bind(null, opt_sizeStats.totalSize)); + } + + if (box.hidden != !show) { + box.hidden = !show; + this.requestRelayout_(100); + } + } + + /** + * Closes the Drive Welcome banner. + * @private + */ + closeWelcomeBanner_() { + this.cleanupWelcomeBanner_(); + // Stop showing the welcome banner. + this.setWelcomeHeaderCounter_(WELCOME_HEADER_COUNTER_LIMIT); + } + + /** + * Shows or hides the welcome banner for drive. + * @private + */ + checkSpaceAndMaybeShowWelcomeBanner_() { + this.ready_.then(() => { + if (!this.isOnCurrentProfileDrive()) { + // We are not on the drive file system. Do not show (close) the welcome + // banner. + this.cleanupWelcomeBanner_(); + this.previousDirWasOnDrive_ = false; + return; + } + + const driveVolume = this.volumeManager_.getCurrentProfileVolumeInfo( + VolumeManagerCommon.VolumeType.DRIVE); + if (this.welcomeHeaderCounter_ >= WELCOME_HEADER_COUNTER_LIMIT || + !driveVolume || driveVolume.error) { + // The banner is already shown enough times or the drive FS is not + // mounted. So, do nothing here. + return; + } + + this.maybeShowWelcomeBanner_(); + }); + } + + /** + * Decides which banner should be shown, and show it. This method is designed + * to be called only from checkSpaceAndMaybeShowWelcomeBanner_. + * @private + */ + maybeShowWelcomeBanner_() { + this.ready_.then(() => { + if (this.directoryModel_.getFileList().length == 0 && + this.welcomeHeaderCounter_ == 0) { + // Only show the full page banner if the header banner was never shown. + // Do not increment the counter. + // The timeout below is required because sometimes another + // 'rescan-completed' event arrives shortly with non-empty file list. + setTimeout(() => { + if (this.isOnCurrentProfileDrive() && + this.welcomeHeaderCounter_ == 0) { + this.prepareAndShowWelcomeBanner_( + 'page', 'DRIVE_WELCOME_TEXT_LONG'); + } + }, 2000); + } else { + // We do not want to increment the counter when the user navigates + // between different directories on Drive, but we increment the counter + // once anyway to prevent the full page banner from showing. + if (!this.previousDirWasOnDrive_ || this.welcomeHeaderCounter_ == 0) { + this.setWelcomeHeaderCounter_(this.welcomeHeaderCounter_ + 1); + this.prepareAndShowWelcomeBanner_( + 'header', 'DRIVE_WELCOME_TEXT_SHORT'); + } + } + this.previousDirWasOnDrive_ = true; + }); + } + + /** + * @return {boolean} True if current directory is on Drive root of current + * profile. + */ + isOnCurrentProfileDrive() { + const entry = this.directoryModel_.getCurrentDirEntry(); + if (!entry || util.isFakeEntry(entry)) { + return false; + } + const locationInfo = this.volumeManager_.getLocationInfo(entry); + if (!locationInfo) { + return false; + } + return locationInfo.rootType === VolumeManagerCommon.RootType.DRIVE && + locationInfo.volumeInfo.profile.isCurrentProfile; + } + + /** + * Shows the Drive Welcome banner. + * @param {string} type 'page'|'head'|'none'. + * @private + */ + showWelcomeBanner_(type) { + const container = this.document_.querySelector('.dialog-container'); + if (container.getAttribute('drive-welcome') != type) { + container.setAttribute('drive-welcome', type); + this.requestRelayout_(200); // Resize only after the animation is done. + } + } + + /** + * Update the UI when the current directory changes. + * + * @param {Event} event The directory-changed event. + * @private + */ + onDirectoryChanged_(event) { + const rootVolume = this.volumeManager_.getVolumeInfo(event.newDirEntry); + if (!rootVolume) { + return; + } + const previousRootVolume = event.previousDirEntry ? + this.volumeManager_.getVolumeInfo(event.previousDirEntry) : + null; + + // Show (or hide) the low space warning. + this.maybeShowLowSpaceWarning_(rootVolume); + + // Add or remove listener to show low space warning, if necessary. + const isLowSpaceWarningTarget = this.isLowSpaceWarningTarget_(rootVolume); + if (isLowSpaceWarningTarget !== + this.isLowSpaceWarningTarget_(previousRootVolume)) { + if (isLowSpaceWarningTarget) { + chrome.fileManagerPrivate.onDirectoryChanged.addListener( + this.privateOnDirectoryChangedBound_); + } else { + chrome.fileManagerPrivate.onDirectoryChanged.removeListener( + this.privateOnDirectoryChangedBound_); + } + } + + if (!this.isOnCurrentProfileDrive()) { + this.cleanupWelcomeBanner_(); + this.authFailedBanner_.hidden = true; + } + + this.updateDriveUnmountedPanel_(); + if (this.isOnCurrentProfileDrive()) { + this.unmountedPanel_.classList.remove('retry-enabled'); + this.maybeShowAuthFailBanner_(); + } + } + + /** + * @param {VolumeInfo} volumeInfo Volume info to be checked. + * @return {boolean} true if the file system specified by |root| is a target + * to show low space warning. Otherwise false. + * @private + */ + isLowSpaceWarningTarget_(volumeInfo) { + if (!volumeInfo) { + return false; + } + return volumeInfo.profile.isCurrentProfile && + (volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DOWNLOADS || + volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DRIVE); + } + + /** + * Callback which is invoked when the file system has been changed. + * @param {Object} event chrome.fileManagerPrivate.onDirectoryChanged event. + * @private + */ + privateOnDirectoryChanged_(event) { + const currentDirEntry = this.directoryModel_.getCurrentDirEntry(); + if (!currentDirEntry) { + return; + } + const currentVolume = this.volumeManager_.getVolumeInfo(currentDirEntry); + if (!currentVolume) { + return; + } + const eventVolume = this.volumeManager_.getVolumeInfo(event.entry); + if (currentVolume === eventVolume) { + // The file system we are currently on is changed. + // So, check the free space. + this.maybeShowLowSpaceWarning_(currentVolume); + } + } + + /** + * Shows or hides the low space warning. + * @param {VolumeInfo} volume Type of volume, which we are interested in. + * @private + */ + maybeShowLowSpaceWarning_(volume) { + // TODO(kaznacheev): Unify the two low space warning. + switch (volume.volumeType) { + case VolumeManagerCommon.VolumeType.DOWNLOADS: + this.showLowDriveSpaceWarning_(false); + break; + case VolumeManagerCommon.VolumeType.DRIVE: + this.showLowDownloadsSpaceWarning_(false); + break; + default: + // If the current file system is neither the DOWNLOAD nor the DRIVE, + // just hide the warning. + this.showLowDownloadsSpaceWarning_(false); + this.showLowDriveSpaceWarning_(false); + return; + } + + // If not mounted correctly, then do not continue. + if (!volume.fileSystem) { + return; + } + + chrome.fileManagerPrivate.getSizeStats(volume.volumeId, sizeStats => { + const currentVolume = this.volumeManager_.getVolumeInfo( + assert(this.directoryModel_.getCurrentDirEntry())); + if (volume !== currentVolume) { + // This happens when the current directory is moved during requesting + // the file system size. Just ignore it. + return; + } + // sizeStats is undefined, if some error occurs. + if (!sizeStats || sizeStats.totalSize == 0) { + return; + } + + if (volume.volumeType === VolumeManagerCommon.VolumeType.DOWNLOADS) { + // Show the warning banner when the available space is less than 1GB. + this.showLowDownloadsSpaceWarning_( + sizeStats.remainingSize < DOWNLOADS_SPACE_WARNING_THRESHOLD_SIZE); + } else { + // Show the warning banner when the available space ls less than 10%. + const remainingRatio = sizeStats.remainingSize / sizeStats.totalSize; + this.showLowDriveSpaceWarning_( + remainingRatio < DRIVE_SPACE_WARNING_THRESHOLD_RATIO, sizeStats); + } + }); + } + + /** + * removes the Drive Welcome banner. + * @private + */ + cleanupWelcomeBanner_() { + this.showWelcomeBanner_('none'); + } + + /** + * Notifies the file manager what layout must be recalculated. + * @param {number} delay In milliseconds. + * @private + */ + requestRelayout_(delay) { + const self = this; + setTimeout(() => { + cr.dispatchSimpleEvent(self, 'relayout'); + }, delay); + } + + /** + * Show or hide the "Low disk space" warning. + * @param {boolean} show True if the box need to be shown. + * @private + */ + showLowDownloadsSpaceWarning_(show) { + const box = this.document_.querySelector('.downloads-warning'); + + if (box.hidden == !show) { + return; + } + + if (this.downloadsWarningDismissedTime_) { + if (Date.now() - this.downloadsWarningDismissedTime_ < + DOWNLOADS_SPACE_WARNING_DISMISS_DURATION) { + show = false; + } + } + + box.textContent = ''; + if (show) { + const icon = this.document_.createElement('div'); + icon.className = 'warning-icon'; + const message = this.document_.createElement('div'); + message.className = 'warning-message'; + message.innerHTML = util.htmlUnescape(str('DOWNLOADS_DIRECTORY_WARNING')); + box.appendChild(icon); + box.appendChild(message); + box.querySelector('a').addEventListener('click', e => { + util.visitURL(str('DOWNLOADS_LOW_SPACE_WARNING_HELP_URL')); + e.preventDefault(); + }); + + const close = this.document_.createElement('div'); + close.className = 'banner-close'; + close.tabIndex = 0; + box.appendChild(close); + close.addEventListener('click', () => { + const values = {}; + values[DOWNLOADS_WARNING_DISMISSED_KEY] = Date.now(); + chrome.storage.local.set(values); + box.hidden = true; + // We explicitly mark the banner-close element as hidden as due to the + // use of position absolute in it's layout it does not get hidden by + // hiding it's parent. + close.hidden = true; + this.requestRelayout_(100); + }); + } + + box.hidden = !show; + this.requestRelayout_(100); + } + + /** + * Creates contents for the DRIVE unmounted panel. + * @private + */ + ensureDriveUnmountedPanelInitialized_() { + const panel = this.unmountedPanel_; + if (panel.firstElementChild) { + return; + } + + /** + * Creates an element using given parameters. + * @param {!Element} parent Parent element of the new element. + * @param {string} tag Tag of the new element. + * @param {string} className Class name of the new element. + * @param {string=} opt_textContent Text content of the new element. + * @return {!Element} The newly created element. + */ + const create = (parent, tag, className, opt_textContent) => { + const div = panel.ownerDocument.createElement(tag); + div.className = className; + div.textContent = opt_textContent || ''; + parent.appendChild(div); + return div; + }; + + create(panel, 'div', 'error', str('DRIVE_CANNOT_REACH')); + + const learnMore = + create(panel, 'a', 'learn-more plain-link', str('DRIVE_LEARN_MORE')); + learnMore.href = str('GOOGLE_DRIVE_ERROR_HELP_URL'); + learnMore.target = '_blank'; + } + + /** + * Called when volume info list is updated. + * @param {Event} event Splice event data on volume info list. + * @private + */ + onVolumeInfoListSplice_(event) { + const isDriveVolume = volumeInfo => { + return volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DRIVE; + }; + if (event.removed.some(isDriveVolume) || event.added.some(isDriveVolume)) { + this.updateDriveUnmountedPanel_(); + } + } + + /** + * Shows the panel when current directory is DRIVE and it's unmounted. + * Hides it otherwise. The panel shows an error message if it failed. + * @private + */ + updateDriveUnmountedPanel_() { + const node = this.document_.body; + if (this.isOnCurrentProfileDrive()) { + const driveVolume = this.volumeManager_.getCurrentProfileVolumeInfo( + VolumeManagerCommon.VolumeType.DRIVE); + if (driveVolume) { + if (driveVolume.error) { + this.ensureDriveUnmountedPanelInitialized_(); + this.unmountedPanel_.classList.add('retry-enabled'); + node.setAttribute('drive', 'error'); + } else { + node.setAttribute('drive', 'mounted'); + } + } else { + this.unmountedPanel_.classList.remove('retry-enabled'); + node.setAttribute('drive', 'unmounted'); } } else { - this.unmountedPanel_.classList.remove('retry-enabled'); - node.setAttribute('drive', 'unmounted'); + node.removeAttribute('drive'); } - } else { - node.removeAttribute('drive'); } -}; -/** - * Updates the visibility of Drive Connection Warning banner, retrieving the - * current connection information. - * @private - */ -Banners.prototype.maybeShowAuthFailBanner_ = function() { - const connection = this.volumeManager_.getDriveConnectionState(); - const showDriveNotReachedMessage = this.isOnCurrentProfileDrive() && - connection.type == VolumeManagerCommon.DriveConnectionType.OFFLINE && - connection.reason == VolumeManagerCommon.DriveConnectionReason.NOT_READY; - this.authFailedBanner_.hidden = !showDriveNotReachedMessage; -}; + /** + * Updates the visibility of Drive Connection Warning banner, retrieving the + * current connection information. + * @private + */ + maybeShowAuthFailBanner_() { + const connection = this.volumeManager_.getDriveConnectionState(); + const showDriveNotReachedMessage = this.isOnCurrentProfileDrive() && + connection.type == VolumeManagerCommon.DriveConnectionType.OFFLINE && + connection.reason == + VolumeManagerCommon.DriveConnectionReason.NOT_READY; + this.authFailedBanner_.hidden = !showDriveNotReachedMessage; + } +}
diff --git a/ui/file_manager/file_manager/foreground/js/ui/location_line.js b/ui/file_manager/file_manager/foreground/js/ui/location_line.js index ac11e59..15fc8c9 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/location_line.js +++ b/ui/file_manager/file_manager/foreground/js/ui/location_line.js
@@ -4,408 +4,413 @@ /** * Location line. - * - * @extends {cr.EventTarget} - * @param {!Element} breadcrumbs Container element for breadcrumbs. - * @param {!VolumeManager} volumeManager Volume manager. - * @constructor */ -function LocationLine(breadcrumbs, volumeManager) { - this.breadcrumbs_ = breadcrumbs; - this.volumeManager_ = volumeManager; - this.entry_ = null; - this.components_ = []; -} +class LocationLine extends cr.EventTarget { + /** + * @param {!Element} breadcrumbs Container element for breadcrumbs. + * @param {!VolumeManager} volumeManager Volume manager. + */ + constructor(breadcrumbs, volumeManager) { + super(); -/** - * Extends cr.EventTarget. - */ -LocationLine.prototype.__proto__ = cr.EventTarget.prototype; - -/** - * Shows breadcrumbs. This operation is done without IO. - * - * @param {!Entry|!FakeEntry} entry Target entry or fake entry. - */ -LocationLine.prototype.show = function(entry) { - if (entry === this.entry_) { - return; + this.breadcrumbs_ = breadcrumbs; + this.volumeManager_ = volumeManager; + this.entry_ = null; + this.components_ = []; } - this.update_(this.getComponents_(entry)); -}; - -/** - * Returns current path components built by the current directory entry. - * @return {!Array<!LocationLine.PathComponent>} Current path components. - */ -LocationLine.prototype.getCurrentPathComponents = function() { - return this.components_; -}; - -/** - * Replace the root directory name at the end of a url. - * The input, |url| is a displayRoot URL of a Drive volume like - * filesystem:chrome-extension://....foo.com-hash/root - * The output is like: - * filesystem:chrome-extension://....foo.com-hash/other - * - * @param {string} url which points to a volume display root - * @param {string} newRoot new root directory name - * @return {string} new URL with the new root directory name - * @private - */ -LocationLine.prototype.replaceRootName_ = (url, newRoot) => { - return url.slice(0, url.length - '/root'.length) + newRoot; -}; - -/** - * Get components for the path of entry. - * @param {!Entry|!FilesAppEntry} entry An entry. - * @return {!Array<!LocationLine.PathComponent>} Components. - * @private - */ -LocationLine.prototype.getComponents_ = function(entry) { - const components = []; - const locationInfo = this.volumeManager_.getLocationInfo(entry); - - if (!locationInfo) { - return components; - } - - if (util.isFakeEntry(entry)) { - components.push(new LocationLine.PathComponent( - util.getEntryLabel(locationInfo, entry), entry.toURL(), - /** @type {!FakeEntry} */ (entry))); - return components; - } - - // Add volume component. - let displayRootUrl = locationInfo.volumeInfo.displayRoot.toURL(); - let displayRootFullPath = locationInfo.volumeInfo.displayRoot.fullPath; - - const prefixEntry = locationInfo.volumeInfo.prefixEntry; - if (prefixEntry) { - components.push(new LocationLine.PathComponent( - prefixEntry.name, prefixEntry.toURL(), prefixEntry)); - } - if (locationInfo.rootType === VolumeManagerCommon.RootType.DRIVE_OTHER) { - // When target path is a shared directory, volume should be shared with me. - const match = entry.fullPath.match(/\/\.files-by-id\/\d+\//); - if (match) { - displayRootFullPath = match[0]; - } else { - displayRootFullPath = '/other'; - } - displayRootUrl = this.replaceRootName_(displayRootUrl, displayRootFullPath); - const sharedWithMeFakeEntry = - locationInfo.volumeInfo - .fakeEntries[VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME]; - components.push(new LocationLine.PathComponent( - str('DRIVE_SHARED_WITH_ME_COLLECTION_LABEL'), - sharedWithMeFakeEntry.toURL(), sharedWithMeFakeEntry)); - } else if ( - locationInfo.rootType === VolumeManagerCommon.RootType.SHARED_DRIVE) { - displayRootUrl = this.replaceRootName_( - displayRootUrl, VolumeManagerCommon.SHARED_DRIVES_DIRECTORY_PATH); - components.push(new LocationLine.PathComponent( - util.getRootTypeLabel(locationInfo), displayRootUrl)); - } else if (locationInfo.rootType === VolumeManagerCommon.RootType.COMPUTER) { - displayRootUrl = this.replaceRootName_( - displayRootUrl, VolumeManagerCommon.COMPUTERS_DIRECTORY_PATH); - components.push(new LocationLine.PathComponent( - util.getRootTypeLabel(locationInfo), displayRootUrl)); - } else { - components.push(new LocationLine.PathComponent( - util.getRootTypeLabel(locationInfo), displayRootUrl)); - } - - // Get relative path to display root (e.g. /root/foo/bar -> foo/bar). - let relativePath = entry.fullPath.slice(displayRootFullPath.length); - if (entry.fullPath.startsWith( - VolumeManagerCommon.SHARED_DRIVES_DIRECTORY_PATH)) { - relativePath = entry.fullPath.slice( - VolumeManagerCommon.SHARED_DRIVES_DIRECTORY_PATH.length); - } else if (entry.fullPath.startsWith( - VolumeManagerCommon.COMPUTERS_DIRECTORY_PATH)) { - relativePath = entry.fullPath.slice( - VolumeManagerCommon.COMPUTERS_DIRECTORY_PATH.length); - } - if (relativePath.indexOf('/') === 0) { - relativePath = relativePath.slice(1); - } - if (relativePath.length === 0) { - return components; - } - - // currentUrl should be without trailing slash. - let currentUrl = /^.+\/$/.test(displayRootUrl) ? - displayRootUrl.slice(0, displayRootUrl.length - 1) : - displayRootUrl; - - // Add directory components to the target path. - const paths = relativePath.split('/'); - for (let i = 0; i < paths.length; i++) { - currentUrl += '/' + encodeURIComponent(paths[i]); - components.push(new LocationLine.PathComponent(paths[i], currentUrl)); - } - - return components; -}; - -/** - * Updates the breadcrumb display. - * @param {!Array<!LocationLine.PathComponent>} components Components to the - * target path. - * @private - */ -LocationLine.prototype.update_ = function(components) { - this.components_ = components; - - // Make the new breadcrumbs temporarily. - const newBreadcrumbs = document.createElement('div'); - for (let i = 0; i < components.length; i++) { - // Add a component. - const component = components[i]; - const button = document.createElement('button'); - button.id = 'breadcrumb-path-' + i; - button.classList.add( - 'breadcrumb-path', 'entry-name', 'imitate-paper-button'); - const nameElement = document.createElement('div'); - nameElement.classList.add('name'); - nameElement.textContent = component.name; - button.appendChild(nameElement); - button.addEventListener('click', this.onClick_.bind(this, i)); - newBreadcrumbs.appendChild(button); - - const ripple = document.createElement('paper-ripple'); - ripple.classList.add('recenteringTouch'); - ripple.setAttribute('fit', ''); - button.appendChild(ripple); - - // If this is the last component, break here. - if (i === components.length - 1) { - break; - } - - // Add a separator. - const separator = document.createElement('span'); - separator.classList.add('separator'); - newBreadcrumbs.appendChild(separator); - } - - // Replace the shown breadcrumbs with the new one, keeping the DOMs for common - // prefix of the path. - // 1. Forward the references to the path element while in the common prefix. - let childOriginal = this.breadcrumbs_.firstChild; - let childNew = newBreadcrumbs.firstChild; - let cnt = 0; - while (childOriginal && childNew && - childOriginal.textContent === childNew.textContent) { - childOriginal = childOriginal.nextSibling; - childNew = childNew.nextSibling; - cnt++; - } - // 2. Remove all elements in original breadcrumbs which are not in the common - // prefix. - while (childOriginal) { - const childToRemove = childOriginal; - childOriginal = childOriginal.nextSibling; - this.breadcrumbs_.removeChild(childToRemove); - } - // 3. Append new elements after the common prefix. - while (childNew) { - const childToAppend = childNew; - childNew = childNew.nextSibling; - this.breadcrumbs_.appendChild(childToAppend); - } - // 4. Reset the tab index and class 'breadcrumb-last'. - for (let el = this.breadcrumbs_.firstChild; el; el = el.nextSibling) { - if (el.classList.contains('breadcrumb-path')) { - const isLast = !el.nextSibling; - el.tabIndex = isLast ? -1 : 9; - el.classList.toggle('breadcrumb-last', isLast); - } - } - - this.breadcrumbs_.hidden = false; - this.truncate(); -}; - -/** - * Updates breadcrumbs widths in order to truncate it properly. - */ -LocationLine.prototype.truncate = function() { - if (!this.breadcrumbs_.firstChild) { - return; - } - - // Assume style.width == clientWidth (items have no margins). - - for (let item = this.breadcrumbs_.firstChild; item; item = item.nextSibling) { - item.removeAttribute('style'); - item.removeAttribute('collapsed'); - item.removeAttribute('hidden'); - } - - const containerWidth = this.breadcrumbs_.getBoundingClientRect().width; - - let pathWidth = 0; - let currentWidth = 0; - let lastSeparator; - for (let item = this.breadcrumbs_.firstChild; item; item = item.nextSibling) { - if (item.className == 'separator') { - pathWidth += currentWidth; - currentWidth = item.getBoundingClientRect().width; - lastSeparator = item; - } else { - currentWidth += item.getBoundingClientRect().width; - } - } - if (pathWidth + currentWidth <= containerWidth) { - return; - } - if (!lastSeparator) { - this.breadcrumbs_.lastChild.style.width = - Math.min(currentWidth, containerWidth) + 'px'; - return; - } - const lastCrumbSeparatorWidth = lastSeparator.getBoundingClientRect().width; - // Current directory name may occupy up to 70% of space or even more if the - // path is short. - let maxPathWidth = - Math.max(Math.round(containerWidth * 0.3), containerWidth - currentWidth); - maxPathWidth = Math.min(pathWidth, maxPathWidth); - - const parentCrumb = lastSeparator.previousSibling; - - // Pre-calculate the minimum width for crumbs. - parentCrumb.setAttribute('collapsed', ''); - const minCrumbWidth = parentCrumb.getBoundingClientRect().width; - parentCrumb.removeAttribute('collapsed'); - - let collapsedWidth = 0; - if (parentCrumb && - pathWidth - parentCrumb.getBoundingClientRect().width + minCrumbWidth > - maxPathWidth) { - // At least one crumb is hidden completely (or almost completely). - // Show sign of hidden crumbs like this: - // root > some di... > ... > current directory. - parentCrumb.setAttribute('collapsed', ''); - collapsedWidth = - Math.min(maxPathWidth, parentCrumb.getBoundingClientRect().width); - maxPathWidth -= collapsedWidth; - if (parentCrumb.getBoundingClientRect().width != collapsedWidth) { - parentCrumb.style.width = collapsedWidth + 'px'; - } - - lastSeparator = parentCrumb.previousSibling; - if (!lastSeparator) { + /** + * Shows breadcrumbs. This operation is done without IO. + * + * @param {!Entry|!FakeEntry} entry Target entry or fake entry. + */ + show(entry) { + if (entry === this.entry_) { return; } - collapsedWidth += lastSeparator.clientWidth; - maxPathWidth = Math.max(0, maxPathWidth - lastSeparator.clientWidth); + + this.update_(this.getComponents_(entry)); } - pathWidth = 0; - for (let item = this.breadcrumbs_.firstChild; item != lastSeparator; - item = item.nextSibling) { - // TODO(serya): Mixing access item.clientWidth and modifying style and - // attributes could cause multiple layout reflows. - if (pathWidth === maxPathWidth) { - item.setAttribute('hidden', ''); - } else { - if (item.classList.contains('separator')) { - // If the current separator and the following crumb don't fit in the - // breadcrumbs area, hide remaining separators and crumbs. - if (pathWidth + item.getBoundingClientRect().width + minCrumbWidth > - maxPathWidth) { - item.setAttribute('hidden', ''); - maxPathWidth = pathWidth; - } else { - pathWidth += item.getBoundingClientRect().width; - } + /** + * Returns current path components built by the current directory entry. + * @return {!Array<!LocationLine.PathComponent>} Current path components. + */ + getCurrentPathComponents() { + return this.components_; + } + + /** + * Replace the root directory name at the end of a url. + * The input, |url| is a displayRoot URL of a Drive volume like + * filesystem:chrome-extension://....foo.com-hash/root + * The output is like: + * filesystem:chrome-extension://....foo.com-hash/other + * + * @param {string} url which points to a volume display root + * @param {string} newRoot new root directory name + * @return {string} new URL with the new root directory name + * @private + */ + replaceRootName_(url, newRoot) { + return url.slice(0, url.length - '/root'.length) + newRoot; + } + + /** + * Get components for the path of entry. + * @param {!Entry|!FilesAppEntry} entry An entry. + * @return {!Array<!LocationLine.PathComponent>} Components. + * @private + */ + getComponents_(entry) { + const components = []; + const locationInfo = this.volumeManager_.getLocationInfo(entry); + + if (!locationInfo) { + return components; + } + + if (util.isFakeEntry(entry)) { + components.push(new LocationLine.PathComponent( + util.getEntryLabel(locationInfo, entry), entry.toURL(), + /** @type {!FakeEntry} */ (entry))); + return components; + } + + // Add volume component. + let displayRootUrl = locationInfo.volumeInfo.displayRoot.toURL(); + let displayRootFullPath = locationInfo.volumeInfo.displayRoot.fullPath; + + const prefixEntry = locationInfo.volumeInfo.prefixEntry; + if (prefixEntry) { + components.push(new LocationLine.PathComponent( + prefixEntry.name, prefixEntry.toURL(), prefixEntry)); + } + if (locationInfo.rootType === VolumeManagerCommon.RootType.DRIVE_OTHER) { + // When target path is a shared directory, volume should be shared with + // me. + const match = entry.fullPath.match(/\/\.files-by-id\/\d+\//); + if (match) { + displayRootFullPath = match[0]; } else { - // If the current crumb doesn't fully fit in the breadcrumbs area, - // shorten the crumb and hide remaining separators and crums. - if (pathWidth + item.getBoundingClientRect().width > maxPathWidth) { - item.style.width = (maxPathWidth - pathWidth) + 'px'; - pathWidth = maxPathWidth; + displayRootFullPath = '/other'; + } + displayRootUrl = + this.replaceRootName_(displayRootUrl, displayRootFullPath); + const sharedWithMeFakeEntry = + locationInfo.volumeInfo + .fakeEntries[VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME]; + components.push(new LocationLine.PathComponent( + str('DRIVE_SHARED_WITH_ME_COLLECTION_LABEL'), + sharedWithMeFakeEntry.toURL(), sharedWithMeFakeEntry)); + } else if ( + locationInfo.rootType === VolumeManagerCommon.RootType.SHARED_DRIVE) { + displayRootUrl = this.replaceRootName_( + displayRootUrl, VolumeManagerCommon.SHARED_DRIVES_DIRECTORY_PATH); + components.push(new LocationLine.PathComponent( + util.getRootTypeLabel(locationInfo), displayRootUrl)); + } else if ( + locationInfo.rootType === VolumeManagerCommon.RootType.COMPUTER) { + displayRootUrl = this.replaceRootName_( + displayRootUrl, VolumeManagerCommon.COMPUTERS_DIRECTORY_PATH); + components.push(new LocationLine.PathComponent( + util.getRootTypeLabel(locationInfo), displayRootUrl)); + } else { + components.push(new LocationLine.PathComponent( + util.getRootTypeLabel(locationInfo), displayRootUrl)); + } + + // Get relative path to display root (e.g. /root/foo/bar -> foo/bar). + let relativePath = entry.fullPath.slice(displayRootFullPath.length); + if (entry.fullPath.startsWith( + VolumeManagerCommon.SHARED_DRIVES_DIRECTORY_PATH)) { + relativePath = entry.fullPath.slice( + VolumeManagerCommon.SHARED_DRIVES_DIRECTORY_PATH.length); + } else if (entry.fullPath.startsWith( + VolumeManagerCommon.COMPUTERS_DIRECTORY_PATH)) { + relativePath = entry.fullPath.slice( + VolumeManagerCommon.COMPUTERS_DIRECTORY_PATH.length); + } + if (relativePath.indexOf('/') === 0) { + relativePath = relativePath.slice(1); + } + if (relativePath.length === 0) { + return components; + } + + // currentUrl should be without trailing slash. + let currentUrl = /^.+\/$/.test(displayRootUrl) ? + displayRootUrl.slice(0, displayRootUrl.length - 1) : + displayRootUrl; + + // Add directory components to the target path. + const paths = relativePath.split('/'); + for (let i = 0; i < paths.length; i++) { + currentUrl += '/' + encodeURIComponent(paths[i]); + components.push(new LocationLine.PathComponent(paths[i], currentUrl)); + } + + return components; + } + + /** + * Updates the breadcrumb display. + * @param {!Array<!LocationLine.PathComponent>} components Components to the + * target path. + * @private + */ + update_(components) { + this.components_ = components; + + // Make the new breadcrumbs temporarily. + const newBreadcrumbs = document.createElement('div'); + for (let i = 0; i < components.length; i++) { + // Add a component. + const component = components[i]; + const button = document.createElement('button'); + button.id = 'breadcrumb-path-' + i; + button.classList.add( + 'breadcrumb-path', 'entry-name', 'imitate-paper-button'); + const nameElement = document.createElement('div'); + nameElement.classList.add('name'); + nameElement.textContent = component.name; + button.appendChild(nameElement); + button.addEventListener('click', this.onClick_.bind(this, i)); + newBreadcrumbs.appendChild(button); + + const ripple = document.createElement('paper-ripple'); + ripple.classList.add('recenteringTouch'); + ripple.setAttribute('fit', ''); + button.appendChild(ripple); + + // If this is the last component, break here. + if (i === components.length - 1) { + break; + } + + // Add a separator. + const separator = document.createElement('span'); + separator.classList.add('separator'); + newBreadcrumbs.appendChild(separator); + } + + // Replace the shown breadcrumbs with the new one, keeping the DOMs for + // common prefix of the path. + // 1. Forward the references to the path element while in the common prefix. + let childOriginal = this.breadcrumbs_.firstChild; + let childNew = newBreadcrumbs.firstChild; + let cnt = 0; + while (childOriginal && childNew && + childOriginal.textContent === childNew.textContent) { + childOriginal = childOriginal.nextSibling; + childNew = childNew.nextSibling; + cnt++; + } + // 2. Remove all elements in original breadcrumbs which are not in the + // common prefix. + while (childOriginal) { + const childToRemove = childOriginal; + childOriginal = childOriginal.nextSibling; + this.breadcrumbs_.removeChild(childToRemove); + } + // 3. Append new elements after the common prefix. + while (childNew) { + const childToAppend = childNew; + childNew = childNew.nextSibling; + this.breadcrumbs_.appendChild(childToAppend); + } + // 4. Reset the tab index and class 'breadcrumb-last'. + for (let el = this.breadcrumbs_.firstChild; el; el = el.nextSibling) { + if (el.classList.contains('breadcrumb-path')) { + const isLast = !el.nextSibling; + el.tabIndex = isLast ? -1 : 9; + el.classList.toggle('breadcrumb-last', isLast); + } + } + + this.breadcrumbs_.hidden = false; + this.truncate(); + } + + /** + * Updates breadcrumbs widths in order to truncate it properly. + */ + truncate() { + if (!this.breadcrumbs_.firstChild) { + return; + } + + // Assume style.width == clientWidth (items have no margins). + + for (let item = this.breadcrumbs_.firstChild; item; + item = item.nextSibling) { + item.removeAttribute('style'); + item.removeAttribute('collapsed'); + item.removeAttribute('hidden'); + } + + const containerWidth = this.breadcrumbs_.getBoundingClientRect().width; + + let pathWidth = 0; + let currentWidth = 0; + let lastSeparator; + for (let item = this.breadcrumbs_.firstChild; item; + item = item.nextSibling) { + if (item.className == 'separator') { + pathWidth += currentWidth; + currentWidth = item.getBoundingClientRect().width; + lastSeparator = item; + } else { + currentWidth += item.getBoundingClientRect().width; + } + } + if (pathWidth + currentWidth <= containerWidth) { + return; + } + if (!lastSeparator) { + this.breadcrumbs_.lastChild.style.width = + Math.min(currentWidth, containerWidth) + 'px'; + return; + } + const lastCrumbSeparatorWidth = lastSeparator.getBoundingClientRect().width; + // Current directory name may occupy up to 70% of space or even more if the + // path is short. + let maxPathWidth = Math.max( + Math.round(containerWidth * 0.3), containerWidth - currentWidth); + maxPathWidth = Math.min(pathWidth, maxPathWidth); + + const parentCrumb = lastSeparator.previousSibling; + + // Pre-calculate the minimum width for crumbs. + parentCrumb.setAttribute('collapsed', ''); + const minCrumbWidth = parentCrumb.getBoundingClientRect().width; + parentCrumb.removeAttribute('collapsed'); + + let collapsedWidth = 0; + if (parentCrumb && + pathWidth - parentCrumb.getBoundingClientRect().width + minCrumbWidth > + maxPathWidth) { + // At least one crumb is hidden completely (or almost completely). + // Show sign of hidden crumbs like this: + // root > some di... > ... > current directory. + parentCrumb.setAttribute('collapsed', ''); + collapsedWidth = + Math.min(maxPathWidth, parentCrumb.getBoundingClientRect().width); + maxPathWidth -= collapsedWidth; + if (parentCrumb.getBoundingClientRect().width != collapsedWidth) { + parentCrumb.style.width = collapsedWidth + 'px'; + } + + lastSeparator = parentCrumb.previousSibling; + if (!lastSeparator) { + return; + } + collapsedWidth += lastSeparator.clientWidth; + maxPathWidth = Math.max(0, maxPathWidth - lastSeparator.clientWidth); + } + + pathWidth = 0; + for (let item = this.breadcrumbs_.firstChild; item != lastSeparator; + item = item.nextSibling) { + // TODO(serya): Mixing access item.clientWidth and modifying style and + // attributes could cause multiple layout reflows. + if (pathWidth === maxPathWidth) { + item.setAttribute('hidden', ''); + } else { + if (item.classList.contains('separator')) { + // If the current separator and the following crumb don't fit in the + // breadcrumbs area, hide remaining separators and crumbs. + if (pathWidth + item.getBoundingClientRect().width + minCrumbWidth > + maxPathWidth) { + item.setAttribute('hidden', ''); + maxPathWidth = pathWidth; + } else { + pathWidth += item.getBoundingClientRect().width; + } } else { - pathWidth += item.getBoundingClientRect().width; + // If the current crumb doesn't fully fit in the breadcrumbs area, + // shorten the crumb and hide remaining separators and crums. + if (pathWidth + item.getBoundingClientRect().width > maxPathWidth) { + item.style.width = (maxPathWidth - pathWidth) + 'px'; + pathWidth = maxPathWidth; + } else { + pathWidth += item.getBoundingClientRect().width; + } } } } + + currentWidth = + Math.min(currentWidth, containerWidth - pathWidth - collapsedWidth); + this.breadcrumbs_.lastChild.style.width = + (currentWidth - lastCrumbSeparatorWidth) + 'px'; } - currentWidth = - Math.min(currentWidth, containerWidth - pathWidth - collapsedWidth); - this.breadcrumbs_.lastChild.style.width = - (currentWidth - lastCrumbSeparatorWidth) + 'px'; -}; - -/** - * Hide breadcrumbs div. - */ -LocationLine.prototype.hide = function() { - this.breadcrumbs_.hidden = true; -}; - -/** - * Execute an element. - * @param {number} index The index of clicked path component. - * @param {!Event} event The MouseEvent object. - * @private - */ -LocationLine.prototype.onClick_ = function(index, event) { - if (index >= this.components_.length - 1) { - return; + /** + * Hide breadcrumbs div. + */ + hide() { + this.breadcrumbs_.hidden = true; } - // Remove 'focused' state from the clicked button. - let button = event.target; - while (button && !button.classList.contains('breadcrumb-path')) { - button = button.parentElement; - } - if (button) { - button.blur(); - } + /** + * Execute an element. + * @param {number} index The index of clicked path component. + * @param {!Event} event The MouseEvent object. + * @private + */ + onClick_(index, event) { + if (index >= this.components_.length - 1) { + return; + } - const pathComponent = this.components_[index]; - pathComponent.resolveEntry().then(entry => { - const pathClickEvent = new Event('pathclick'); - pathClickEvent.entry = entry; - this.dispatchEvent(pathClickEvent); - }); - metrics.recordUserAction('ClickBreadcrumbs'); -}; + // Remove 'focused' state from the clicked button. + let button = event.target; + while (button && !button.classList.contains('breadcrumb-path')) { + button = button.parentElement; + } + if (button) { + button.blur(); + } + + const pathComponent = this.components_[index]; + pathComponent.resolveEntry().then(entry => { + const pathClickEvent = new Event('pathclick'); + pathClickEvent.entry = entry; + this.dispatchEvent(pathClickEvent); + }); + metrics.recordUserAction('ClickBreadcrumbs'); + } +} /** * Path component. - * @param {string} name Name. - * @param {string} url Url. - * @param {FilesAppEntry=} opt_fakeEntry Fake entry should be set when - * this component represents fake entry. - * @constructor - * @struct */ -LocationLine.PathComponent = function(name, url, opt_fakeEntry) { - this.name = name; - this.url_ = url; - this.fakeEntry_ = opt_fakeEntry || null; -}; +LocationLine.PathComponent = class { + /** + * @param {string} name Name. + * @param {string} url Url. + * @param {FilesAppEntry=} opt_fakeEntry Fake entry should be set when + * this component represents fake entry. + */ + constructor(name, url, opt_fakeEntry) { + this.name = name; + this.url_ = url; + this.fakeEntry_ = opt_fakeEntry || null; + } -/** - * Resolve an entry of the component. - * @return {!Promise<!Entry|!FilesAppEntry>} A promise which is - * resolved with an entry. - */ -LocationLine.PathComponent.prototype.resolveEntry = function() { - if (this.fakeEntry_) { - return /** @type {!Promise<!Entry|!FilesAppEntry>} */ ( - Promise.resolve(this.fakeEntry_)); - } else { - return new Promise( - window.webkitResolveLocalFileSystemURL.bind(null, this.url_)); + /** + * Resolve an entry of the component. + * @return {!Promise<!Entry|!FilesAppEntry>} A promise which is + * resolved with an entry. + */ + resolveEntry() { + if (this.fakeEntry_) { + return /** @type {!Promise<!Entry|!FilesAppEntry>} */ ( + Promise.resolve(this.fakeEntry_)); + } else { + return new Promise( + window.webkitResolveLocalFileSystemURL.bind(null, this.url_)); + } } };
diff --git a/ui/latency/BUILD.gn b/ui/latency/BUILD.gn index 6afee94..b40ad83 100644 --- a/ui/latency/BUILD.gn +++ b/ui/latency/BUILD.gn
@@ -7,6 +7,8 @@ jumbo_source_set("latency") { sources = [ + "average_lag_tracker.cc", + "average_lag_tracker.h", "fixed_point.cc", "fixed_point.h", "frame_metrics.cc", @@ -49,6 +51,7 @@ test("latency_unittests") { sources = [ + "average_lag_tracker_unittest.cc", "fixed_point_unittest.cc", "frame_metrics_test_common.cc", "frame_metrics_test_common.h",
diff --git a/ui/latency/average_lag_tracker.cc b/ui/latency/average_lag_tracker.cc new file mode 100644 index 0000000..e1419ba --- /dev/null +++ b/ui/latency/average_lag_tracker.cc
@@ -0,0 +1,159 @@ +// 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 "ui/latency/average_lag_tracker.h" + +#include "base/metrics/histogram_functions.h" + +namespace ui { + +AverageLagTracker::AverageLagTracker() = default; + +AverageLagTracker::~AverageLagTracker() = default; + +void AverageLagTracker::AddLatencyInFrame( + const ui::LatencyInfo& latency, + base::TimeTicks gpu_swap_begin_timestamp, + const std::string& scroll_name) { + base::TimeTicks event_timestamp; + bool found_component = latency.FindLatency( + ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, + &event_timestamp); + DCHECK(found_component); + // Skip if no event timestamp. + if (!found_component) + return; + + if (scroll_name == "ScrollBegin") { + // Flush all unfinished frames. + while (!frame_lag_infos_.empty()) { + base::TimeTicks last_time = + std::max(last_event_timestamp_, last_finished_frame_time_); + frame_lag_infos_.front().lag_area += + std::abs(last_event_accumulated_delta_ - + frame_lag_infos_.front().rendered_accumulated_delta) * + (frame_lag_infos_.front().frame_time - last_time).InMillisecondsF(); + // Record UMA when it's the last item in queue. + CalculateAndReportAverageLagUma(frame_lag_infos_.size() == 1); + } + // |accumulated_lag_| should be cleared/reset. + DCHECK(accumulated_lag_ == 0); + + // Create ScrollBegin report, with report time equals to gpu swap time. + LagAreaInFrame first_frame(gpu_swap_begin_timestamp); + frame_lag_infos_.push_back(first_frame); + + // Reset fields. + last_reported_time_ = event_timestamp; + last_finished_frame_time_ = event_timestamp; + last_event_accumulated_delta_ = 0; + last_rendered_accumulated_delta_ = 0; + is_begin_ = true; + } else if (scroll_name == "ScrollUpdate" && + !last_event_timestamp_.is_null()) { + DCHECK((event_timestamp - last_event_timestamp_).InMilliseconds() >= 0); + // Pop all frames where frame_time <= event_timestamp. + while (!frame_lag_infos_.empty() && + frame_lag_infos_.front().frame_time <= event_timestamp) { + base::TimeTicks front_time = + std::max(last_event_timestamp_, last_finished_frame_time_); + base::TimeTicks back_time = frame_lag_infos_.front().frame_time; + frame_lag_infos_.front().lag_area += + LagBetween(front_time, back_time, latency, event_timestamp); + + CalculateAndReportAverageLagUma(); + } + + // Initialize a new LagAreaInFrame when current_frame_time > frame_time. + if (frame_lag_infos_.empty() || + gpu_swap_begin_timestamp > frame_lag_infos_.back().frame_time) { + LagAreaInFrame new_frame(gpu_swap_begin_timestamp, + last_rendered_accumulated_delta_); + frame_lag_infos_.push_back(new_frame); + } + + // last_frame_time <= event_timestamp < frame_time + if (!frame_lag_infos_.empty()) { + // The front element in queue (if any) must satisfy frame_time > + // event_timestamp, otherwise it would be popped in the while loop. + DCHECK(last_finished_frame_time_ <= event_timestamp && + event_timestamp <= frame_lag_infos_.front().frame_time); + base::TimeTicks front_time = + std::max(last_finished_frame_time_, last_event_timestamp_); + base::TimeTicks back_time = event_timestamp; + + frame_lag_infos_.front().lag_area += + LagBetween(front_time, back_time, latency, event_timestamp); + } + } + + last_event_timestamp_ = event_timestamp; + last_event_accumulated_delta_ += latency.scroll_update_delta(); + last_rendered_accumulated_delta_ += latency.scroll_update_delta(); +} + +float AverageLagTracker::LagBetween(base::TimeTicks front_time, + base::TimeTicks back_time, + const LatencyInfo& latency, + base::TimeTicks event_timestamp) { + // In some tests, we use const event time. return 0 to avoid divided by 0. + if (event_timestamp == last_event_timestamp_) + return 0; + + float front_delta = + (last_event_accumulated_delta_ + + (latency.scroll_update_delta() * + ((front_time - last_event_timestamp_).InMillisecondsF() / + (event_timestamp - last_event_timestamp_).InMillisecondsF()))) - + frame_lag_infos_.front().rendered_accumulated_delta; + + float back_delta = + (last_event_accumulated_delta_ + + latency.scroll_update_delta() * + + ((back_time - last_event_timestamp_).InMillisecondsF() / + (event_timestamp - last_event_timestamp_).InMillisecondsF())) - + frame_lag_infos_.front().rendered_accumulated_delta; + + // Calculate the trapezoid area. + if (front_delta * back_delta >= 0) { + return 0.5f * std::abs(front_delta + back_delta) * + (back_time - front_time).InMillisecondsF(); + } + + // Corner case that rendered_accumulated_delta is in between of front_pos + // and back_pos. + return 0.5f * + std::abs((front_delta * front_delta + back_delta * back_delta) / + (back_delta - front_delta)) * + (back_time - front_time).InMillisecondsF(); +} + +void AverageLagTracker::CalculateAndReportAverageLagUma(bool send_anyway) { + DCHECK(!frame_lag_infos_.empty()); + const LagAreaInFrame& frame_lag = frame_lag_infos_.front(); + + DCHECK(frame_lag.lag_area >= 0.f); + accumulated_lag_ += frame_lag.lag_area; + + // |send_anyway| is true when we are flush all remaining frames on next + // |ScrollBegin|. Otherwise record UMA when it's ScrollBegin, or when + // reaching the 1 second gap. + if (send_anyway || is_begin_ || + (frame_lag.frame_time - last_reported_time_).InSecondsF() >= 1.0f) { + std::string scroll_name = is_begin_ ? "ScrollBegin" : "ScrollUpdate"; + base::UmaHistogramCounts1000( + "Event.Latency." + scroll_name + ".Touch.AverageLag", + accumulated_lag_ / + (frame_lag.frame_time - last_reported_time_).InMillisecondsF()); + accumulated_lag_ = 0; + last_reported_time_ = frame_lag.frame_time; + is_begin_ = false; + } + + last_finished_frame_time_ = frame_lag.frame_time; + frame_lag_infos_.pop_front(); +} + +} // namespace ui
diff --git a/ui/latency/average_lag_tracker.h b/ui/latency/average_lag_tracker.h new file mode 100644 index 0000000..bcde09d7 --- /dev/null +++ b/ui/latency/average_lag_tracker.h
@@ -0,0 +1,78 @@ +// 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 UI_LATENCY_AVERAGE_LAG_TRACKER_H_ +#define UI_LATENCY_AVERAGE_LAG_TRACKER_H_ + +#include <deque> + +#include "base/macros.h" +#include "ui/latency/latency_info.h" + +namespace ui { + +// A class for reporting AverageLag metrics. See +// https://docs.google.com/document/d/1e8NuzPblIv2B9bz01oSj40rmlse7_PHq5oFS3lqz6N4/ +class AverageLagTracker { + public: + AverageLagTracker(); + ~AverageLagTracker(); + void AddLatencyInFrame(const LatencyInfo& latency, + base::TimeTicks gpu_swap_begin_timestamp, + const std::string& scroll_name); + + private: + typedef struct LagAreaInFrame { + LagAreaInFrame(base::TimeTicks time, float rendered_pos = 0) + : frame_time(time), + rendered_accumulated_delta(rendered_pos), + lag_area(0) {} + base::TimeTicks frame_time; + float rendered_accumulated_delta; + float lag_area; + } LagAreaInFrame; + + // Calculate lag in 1 seconds intervals and report UMA. + void CalculateAndReportAverageLagUma(bool send_anyway = false); + + // Helper function to calculate lag area between |front_time| to + // |back_time|. + float LagBetween(base::TimeTicks front_time, + base::TimeTicks back_time, + const LatencyInfo& latency, + base::TimeTicks event_time); + + std::deque<LagAreaInFrame> frame_lag_infos_; + + // Last scroll event's timestamp in the sequence, reset on ScrollBegin. + base::TimeTicks last_event_timestamp_; + // Timestamp of the last frame popped from |frame_lag_infos_| queue. + base::TimeTicks last_finished_frame_time_; + + // Accumulated scroll delta for actual scroll update events. Cumulated from + // latency.scroll_update_delta(). Reset on ScrollBegin. + float last_event_accumulated_delta_ = 0; + // Accumulated scroll delta got rendered on gpu swap. Cumulated from + // latency.predicted_scroll_update_delta(). It always has same value as + // |last_event_accumulated_delta_| when scroll prediction is disabled. + float last_rendered_accumulated_delta_ = 0; + + // This keeps track of the last report_time when we report to UMA, so we can + // calculate the report's duration by current - last. Reset on ScrollBegin. + base::TimeTicks last_reported_time_; + + // True if the first element of |frame_lag_infos_| is for ScrollBegin. + // For ScrollBegin, we don't wait for the 1 second interval but record the + // UMA once the frame is finished. + bool is_begin_ = false; + + // Accumulated lag area in the 1 second intervals. + float accumulated_lag_ = 0; + + DISALLOW_COPY_AND_ASSIGN(AverageLagTracker); +}; + +} // namespace ui + +#endif // UI_LATENCY_AVERAGE_LAG_TRACKER_H_
diff --git a/ui/latency/average_lag_tracker_unittest.cc b/ui/latency/average_lag_tracker_unittest.cc new file mode 100644 index 0000000..c4c34f1 --- /dev/null +++ b/ui/latency/average_lag_tracker_unittest.cc
@@ -0,0 +1,248 @@ +// 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 "ui/latency/average_lag_tracker.h" + +#include "base/test/metrics/histogram_tester.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::Bucket; +using testing::ElementsAre; + +namespace ui { +namespace { + +class AverageLagTrackerTest : public testing::Test { + public: + AverageLagTrackerTest() { ResetHistograms(); } + + void ResetHistograms() { + histogram_tester_.reset(new base::HistogramTester()); + } + + const base::HistogramTester& histogram_tester() { return *histogram_tester_; } + + void SetUp() override { + average_lag_tracker_ = std::make_unique<AverageLagTracker>(); + } + + void SyntheticTouchScrollBeginLatencyInfo(base::TimeTicks event_time, + base::TimeTicks frame_time, + float delta) { + ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH); + touch_latency.set_scroll_update_delta(delta); + touch_latency.AddLatencyNumberWithTimestamp( + ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, + event_time, 1); + touch_latency.AddLatencyNumberWithTimestamp( + ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, event_time, + 1); + average_lag_tracker_->AddLatencyInFrame(touch_latency, frame_time, + "ScrollBegin"); + } + + void SyntheticTouchScrollUpdateLatencyInfo(base::TimeTicks event_time, + base::TimeTicks frame_time, + float delta) { + ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH); + touch_latency.set_scroll_update_delta(delta); + touch_latency.AddLatencyNumberWithTimestamp( + ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, event_time, + 1); + touch_latency.AddLatencyNumberWithTimestamp( + ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, event_time, + 1); + average_lag_tracker_->AddLatencyInFrame(touch_latency, frame_time, + "ScrollUpdate"); + } + + protected: + std::unique_ptr<AverageLagTracker> average_lag_tracker_; + + std::unique_ptr<base::HistogramTester> histogram_tester_; +}; + +base::TimeTicks MillisecondsToTimeTicks(float t_ms) { + return base::TimeTicks() + base::TimeDelta::FromMilliseconds(t_ms); +} + +// Simulate a simple situation that events at every 10ms and start at t=15ms, +// frame swaps at every 10ms too and start at t=20ms and test we record one +// UMA for ScrollUpdate in one second. +TEST_F(AverageLagTrackerTest, OneSecondInterval) { + base::TimeTicks event_time = + base::TimeTicks() + base::TimeDelta::FromMilliseconds(5); + base::TimeTicks frame_time = + base::TimeTicks() + base::TimeDelta::FromMilliseconds(10); + float scroll_delta = 10; + + // ScrollBegin + event_time += base::TimeDelta::FromMilliseconds(10); // 15ms + frame_time += base::TimeDelta::FromMilliseconds(10); // 20ms + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, scroll_delta); + + // Send 101 ScrollUpdate events to verify that there is 1 AverageLag record + // per 1 second. + const int kUpdates = 101; + for (int i = 0; i < kUpdates; i++) { + event_time += base::TimeDelta::FromMilliseconds(10); + frame_time += base::TimeDelta::FromMilliseconds(10); + // First 50 has positive delta, others negetive delta. + const int sign = (i < kUpdates / 2) ? 1 : -1; + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, + sign * scroll_delta); + } + + // ScrollBegin report_time is at 20ms, so the next ScrollUpdate report_time is + // at 1020ms. The last event_time that finish this report should be later than + // 1020ms. + EXPECT_EQ(event_time, + base::TimeTicks() + base::TimeDelta::FromMilliseconds(1025)); + EXPECT_EQ(frame_time, + base::TimeTicks() + base::TimeDelta::FromMilliseconds(1030)); + + // ScrollBegin AverageLag are the area between the event original component + // (time=15ms, delta=10px) to the frame swap time (time=20ms, expect finger + // position at delta=15px). The AverageLag scaled to 1 second is + // (0.5*(10px+15px)*5ms)/5ms = 12.5px. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollBegin.Touch.AverageLag"), + ElementsAre(Bucket(12, 1))); + // This ScrollUpdate AverageLag are calculated as the finger uniformly scroll + // 10px each frame. For scroll up/down frame, the Lag at the last frame swap + // is 5px, and Lag at this frame swap is 15px. For the one changing direction, + // the Lag is from 5 to 10 and down to 5 again. So total LagArea is 99 * 100, + // plus 75. the AverageLag in 1 second is 9.975px. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollUpdate.Touch.AverageLag"), + ElementsAre(Bucket(9, 1))); + ResetHistograms(); + + // Send another ScrollBegin to end the unfinished ScrollUpdate report. + event_time += base::TimeDelta::FromMilliseconds(10); + frame_time += base::TimeDelta::FromMilliseconds(10); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, scroll_delta); + + // The last ScrollUpdate's lag is 8.75px and truncated to 8. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollUpdate.Touch.AverageLag"), + ElementsAre(Bucket(8, 1))); +} + +// Test the case that event's frame swap time is later than next event's +// creation time. (i.e, event at t=10ms will be dispatch at t=30ms, while next +// event is at t=20ms). +TEST_F(AverageLagTrackerTest, LargerLatency) { + base::TimeTicks event_time = MillisecondsToTimeTicks(10); + base::TimeTicks frame_time = + event_time + base::TimeDelta::FromMilliseconds(20); + float scroll_delta = 10; + + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, scroll_delta); + + // Send 2 ScrollUpdate. The second one will record AverageLag.ScrollBegin as + // it's event_time is larger or equal to ScrollBegin's frame_time. + for (int i = 0; i < 2; i++) { + event_time += base::TimeDelta::FromMilliseconds(10); + frame_time = event_time + base::TimeDelta::FromMilliseconds(20); + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, scroll_delta); + } + + // ScrollBegin AveragLag are from t=10ms to t=30ms, with absolute scroll + // position from 10 to 30. The AverageLag should be: + // (0.5*(10px + 30px)*20ms/20ms) = 20px. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollBegin.Touch.AverageLag"), + ElementsAre(Bucket(20, 1))); + + // Another ScrollBegin to flush unfinished frames. + // event_time doesn't matter here because the previous frames' lag are + // compute from their frame_time. + event_time = MillisecondsToTimeTicks(1000); + frame_time = MillisecondsToTimeTicks(1000); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, scroll_delta); + // The to unfinished frames' lag are (finger_positon-rendered_position)*time, + // AverageLag is ((30px-10px)*10ms+(30px-20px)*10ms)/20ms = 15px. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollUpdate.Touch.AverageLag"), + ElementsAre(Bucket(14, 1))); +} + +// Test that multiple latency being flush in the same frame swap. +TEST_F(AverageLagTrackerTest, TwoLatencyInfoInSameFrame) { + // ScrollBegin + base::TimeTicks event_time = MillisecondsToTimeTicks(10); + base::TimeTicks frame_time = MillisecondsToTimeTicks(20); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, + -10 /* scroll_delta */); + + // ScrollUpdate with event_time >= ScrollBegin frame_time will generate + // a histogram for AverageLag.ScrollBegin. + event_time = MillisecondsToTimeTicks(20); + frame_time = MillisecondsToTimeTicks(30); + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, + -10 /* scroll_delta */); + + // Absolute position from -10 to -20. The AverageLag should be: + // (0.5*(10px + 20px)*10ms/10ms) = 15px. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollBegin.Touch.AverageLag"), + ElementsAre(Bucket(14, 1))); + + event_time = MillisecondsToTimeTicks(25); + frame_time = MillisecondsToTimeTicks(30); + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, + 5 /* scroll_delta */); + + // Another ScrollBegin to flush unfinished frames. + event_time = MillisecondsToTimeTicks(1000); + frame_time = MillisecondsToTimeTicks(1000); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, 0); + + // The ScrollUpdates are at t=20ms, finger_pos=-20px, rendered_pos=-10px, + // at t=25ms, finger_pos=-15px, rendered_pos=-10px; + // To t=30ms both events get flush. + // AverageLag is (0.5*(10px+5px)*5ms + 5px*5ms)/10ms = 6.25px + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollUpdate.Touch.AverageLag"), + ElementsAre(Bucket(6, 1))); +} + +// Test the case that switching direction causes lag at current frame +// time and previous frame time are in different direction. +TEST_F(AverageLagTrackerTest, ChangeDirectionInFrame) { + // ScrollBegin + base::TimeTicks event_time = MillisecondsToTimeTicks(10); + base::TimeTicks frame_time = MillisecondsToTimeTicks(20); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, + 10 /* scroll_delta */); + + // At t=20, lag = 10px. + event_time = MillisecondsToTimeTicks(20); + frame_time = MillisecondsToTimeTicks(30); + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, + 10 /* scroll_delta */); + + // At t=30, lag = -10px. + event_time = MillisecondsToTimeTicks(30); + frame_time = MillisecondsToTimeTicks(40); + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, + -20 /* scroll_delta */); + + // Another ScrollBegin to flush unfinished frames. + event_time = MillisecondsToTimeTicks(1000); + frame_time = MillisecondsToTimeTicks(1000); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, 0); + + // From t=20 to t=30, lag_area=2*(0.5*10px*5ms)=50px*ms. + // From t=30 to t=40, lag_area=20px*10ms=200px*ms + // AverageLag = (50+200)/20 = 12.5px. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollUpdate.Touch.AverageLag"), + ElementsAre(Bucket(12, 1))); +} + +} // namespace +} // namespace ui
diff --git a/ui/latency/latency_tracker.cc b/ui/latency/latency_tracker.cc index d98a8e0..4c851c1 100644 --- a/ui/latency/latency_tracker.cc +++ b/ui/latency/latency_tracker.cc
@@ -260,7 +260,8 @@ (IsInertialScroll(latency) && scroll_name == "ScrollInertial")); if (!IsInertialScroll(latency) && input_modality == "Touch") - CalculateAverageLag(latency, gpu_swap_begin_timestamp, scroll_name); + average_lag_tracker_.AddLatencyInFrame(latency, gpu_swap_begin_timestamp, + scroll_name); base::TimeTicks rendering_scheduled_timestamp; bool rendering_scheduled_on_main = latency.FindLatency( @@ -343,133 +344,6 @@ gpu_swap_begin_timestamp, gpu_swap_end_timestamp); } -void LatencyTracker::CalculateAverageLag( - const ui::LatencyInfo& latency, - base::TimeTicks gpu_swap_begin_timestamp, - const std::string& scroll_name) { - base::TimeTicks event_timestamp; - bool found_component = latency.FindLatency( - ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, - &event_timestamp); - DCHECK_AND_RETURN_ON_FAIL(found_component); - - if (scroll_name == "ScrollBegin") { - // Clear both lag_reports. - ReportAverageLagUma(std::move(pending_finished_lag_report_)); - if (current_lag_report_) - current_lag_report_->report_time = last_frame_time_; - ReportAverageLagUma(std::move(current_lag_report_)); - - // Create ScrollBegin report, with report time equals to gpu swap time. - LagData new_report(scroll_name); - pending_finished_lag_report_ = std::make_unique<LagData>(scroll_name); - pending_finished_lag_report_->report_time = gpu_swap_begin_timestamp; - // For ScrollBegin, we don't have the previous time to calculate the - // interpolated area, so the lag is the area between the current event - // creation time and gpu swap begin time. - pending_finished_lag_report_->lag = - (gpu_swap_begin_timestamp - event_timestamp).InMillisecondsF() * - std::abs(latency.scroll_update_delta()); - // The next report time should be a least 1 second away from current report - // time. - next_report_time_ = pending_finished_lag_report_->report_time + - base::TimeDelta::FromSeconds(1); - // Reset last_reported_time to event time. - last_reported_time_ = event_timestamp; - } else if (scroll_name == "ScrollUpdate" && - !last_event_timestamp_.is_null()) { - DCHECK((event_timestamp - last_event_timestamp_).InMilliseconds() >= 0); - - // |pending_finger_move_lag| is the interpolated area between last event to - // current event. We assume the finger moved at a constant velocity between - // the past two events, so the lag in this duration is calculated by the - // average delta(current delta/2). - float pending_finger_move_lag = - (event_timestamp - last_event_timestamp_).InMillisecondsF() * - std::abs(latency.scroll_update_delta() / 2); - - // |event_dispatch_lag| is the area between the current event creation time - // (i.e. last coalesced event of current event creation time) and gpu swap - // begin time of this event. - float event_dispatch_lag = - (gpu_swap_begin_timestamp - event_timestamp).InMillisecondsF() * - std::abs(latency.scroll_update_delta()); - - if (pending_finished_lag_report_) { - if (event_timestamp >= pending_finished_lag_report_->report_time) { - DCHECK_GE(pending_finished_lag_report_->report_time, - last_event_timestamp_); - // This event is created after this report's report time, so part of - // the |pending_finger_move_lag| should be counted in this report, the - // rest should be count in the following report. The area of first part - // is calculated by similar triangle area. - float ratio = - (pending_finished_lag_report_->report_time - last_event_timestamp_) - .InMillisecondsF() / - (event_timestamp - last_event_timestamp_).InMillisecondsF(); - pending_finished_lag_report_->lag += - pending_finger_move_lag * ratio * ratio; - pending_finger_move_lag *= 1 - ratio * ratio; - ReportAverageLagUma(std::move(pending_finished_lag_report_)); - } else { // event_timestamp < pending_finished_lag_report_->report_time - DCHECK_LE(pending_finished_lag_report_->report_time, - gpu_swap_begin_timestamp); - // This event is created before this report's report_time, so - // |pending_finger_move_lag|, and also part of |event_dispatch_lag| that - // before |report_time| should be counted in this report. - float lag_after_report_time = - (gpu_swap_begin_timestamp - - pending_finished_lag_report_->report_time) - .InMillisecondsF() * - std::abs(latency.scroll_update_delta()); - pending_finished_lag_report_->lag += pending_finger_move_lag + - event_dispatch_lag - - lag_after_report_time; - pending_finger_move_lag = 0; - event_dispatch_lag = lag_after_report_time; - } - } - - // Remaining pending lag should be counted in the |current_lag_report_|. - if (pending_finger_move_lag + event_dispatch_lag != 0) { - if (!current_lag_report_) - current_lag_report_ = std::make_unique<LagData>(scroll_name); - - current_lag_report_->lag += pending_finger_move_lag + event_dispatch_lag; - - // When the |pending_finished_lag_report_| is finished, and the current - // gpu_swap_time is larger than the |next_report_time_|, it means the we - // reach the 1 second gap, and we can filled in the timestamp and move it - // to |pending_finished_lag_report_|. We use the - // current|gpu_swap_begin_timestamp| as the report_time, so it can be - // align with gpu swaps. - if (!pending_finished_lag_report_ && - gpu_swap_begin_timestamp >= next_report_time_) { - current_lag_report_->report_time = gpu_swap_begin_timestamp; - // The next report time is 1 second away from this report time. - next_report_time_ = - gpu_swap_begin_timestamp + base::TimeDelta::FromSeconds(1); - pending_finished_lag_report_ = std::move(current_lag_report_); - } - } - } - last_event_timestamp_ = event_timestamp; - last_frame_time_ = gpu_swap_begin_timestamp; -} - -void LatencyTracker::ReportAverageLagUma(std::unique_ptr<LagData> report) { - if (report) { - DCHECK(!report->report_time.is_null()); - DCHECK(report->lag >= 0.f); - base::UmaHistogramCounts1000( - "Event.Latency." + report->scroll_name + ".Touch.AverageLag", - report->lag / - (report->report_time - last_reported_time_).InMillisecondsF()); - - last_reported_time_ = report->report_time; - } -} - // static void LatencyTracker::SetLatencyInfoProcessorForTesting( const LatencyInfoProcessor& processor) {
diff --git a/ui/latency/latency_tracker.h b/ui/latency/latency_tracker.h index d7ac971..02ecf72 100644 --- a/ui/latency/latency_tracker.h +++ b/ui/latency/latency_tracker.h
@@ -5,8 +5,8 @@ #ifndef UI_LATENCY_LATENCY_TRACKER_H_ #define UI_LATENCY_LATENCY_TRACKER_H_ -#include <deque> #include "base/macros.h" +#include "ui/latency/average_lag_tracker.h" #include "ui/latency/latency_info.h" namespace ui { @@ -52,41 +52,7 @@ base::TimeTicks gpu_swap_end_timestamp, const LatencyInfo& latency); - void CalculateAverageLag(const ui::LatencyInfo& latency, - base::TimeTicks gpu_swap_begin_timestamp, - const std::string& scroll_name); - - // Used for reporting AverageLag metrics. - typedef struct LagData { - LagData(const std::string& name) - : report_time(base::TimeTicks()), lag(0), scroll_name(name) {} - // Lag report's report_time, align with |gpu_swap_begin_time|. It should has - // one second gap between previous report. We do not set the report_time - // before the 1 second gap is reached. - base::TimeTicks report_time; - float lag; - const std::string scroll_name; - } LagData; - - void ReportAverageLagUma(std::unique_ptr<LagData> report); - - // Last scroll event's timestamp in the sequence, reset on ScrollBegin. - base::TimeTicks last_event_timestamp_; - // next_report_time is always 1 second after the newest report's report_time. - base::TimeTicks next_report_time_; - // This keeps track the last report_time when we report to UMA, so we can - // calculate the report's duration by current - last. Reset on ScrollBegin. - base::TimeTicks last_reported_time_; - // Keeps track of last gpu_swap time, so we can end the previous unfinished - // report on the new ScrollBegin. - base::TimeTicks last_frame_time_; - // Lag report that already filled in the report_time, and it will be finished - // and report once we have an event whose timestamp is later then the - // report_time. - std::unique_ptr<LagData> pending_finished_lag_report_; - // The current unfinished lag report, which doesn't reach the 1 second length - // yet. It's report_time is null and invalid now. - std::unique_ptr<LagData> current_lag_report_; + AverageLagTracker average_lag_tracker_; DISALLOW_COPY_AND_ASSIGN(LatencyTracker); };
diff --git a/ui/webui/PLATFORM_OWNERS b/ui/webui/PLATFORM_OWNERS index 1a5610ef..b60b4c4 100644 --- a/ui/webui/PLATFORM_OWNERS +++ b/ui/webui/PLATFORM_OWNERS
@@ -7,7 +7,6 @@ hcarmona@chromium.org michaelpg@chromium.org rbpotter@chromium.org -scottchen@chromium.org stevenjb@chromium.org tommycli@chromium.org xiyuan@chromium.org
diff --git a/ui/webui/resources/cr_elements/OWNERS b/ui/webui/resources/cr_elements/OWNERS index 5fd1662..057813143 100644 --- a/ui/webui/resources/cr_elements/OWNERS +++ b/ui/webui/resources/cr_elements/OWNERS
@@ -1,3 +1,2 @@ michaelpg@chromium.org -scottchen@chromium.org stevenjb@chromium.org