diff --git a/DEPS b/DEPS index 72c8215d..d4bd6c1 100644 --- a/DEPS +++ b/DEPS
@@ -105,7 +105,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': '656cefe65d620f9aa7f689e412fa7720fe01c447', + 'skia_revision': 'f88f49d2a52e2a28eaea0f5476fa4cc3ebd2a820', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -213,7 +213,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_tools_revision': '32381e30ef56f5a15207679a55c73a206483c1c4', + 'spv_tools_revision': 'ddc705933d3f32024ea0e320a2c9d91925b78d9c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -595,7 +595,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '82b404766db2865f290fb939577b2a0a931508eb', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '42db842648806b83ba74c765083b7f4e5211dd0d', 'condition': 'checkout_linux', }, @@ -1137,7 +1137,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@928526013073be9b73b8ca5140d37030a66bc0a2', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@cd9671dd3ecf68876fb6cee9d1d07d1d4c4d614e', 'condition': 'checkout_src_internal', },
diff --git a/WATCHLISTS b/WATCHLISTS index c818caf0..25b1a8a 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1514,10 +1514,8 @@ }, 'tab_alert_indicators': { 'filepath': 'content/browser/media/audio_stream_monitor'\ - '|chrome/browser/ui/cocoa/tabs/alert_indicator_button'\ - '|chrome/browser/ui/cocoa/tabs/tab_controller\.mm'\ '|chrome/browser/ui/tabs/tab_utils'\ - '|chrome/browser/ui/views/tabs/alert_indicator_button'\ + '|chrome/browser/ui/views/tabs/alert_indicator'\ '|chrome/browser/ui/views/tabs/tab\.cc'\ '|chrome/browser/ui/views/tabs/tab_renderer_data'\ '|media/audio/audio_(output_controller|power_monitor)',
diff --git a/android_webview/browser/aw_quota_manager_bridge.cc b/android_webview/browser/aw_quota_manager_bridge.cc index ca988bb4..4d47700 100644 --- a/android_webview/browser/aw_quota_manager_bridge.cc +++ b/android_webview/browser/aw_quota_manager_bridge.cc
@@ -21,6 +21,7 @@ #include "storage/browser/quota/quota_manager.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "url/gurl.h" +#include "url/origin.h" using base::android::AttachCurrentThread; using base::android::JavaParamRef; @@ -49,10 +50,10 @@ friend class base::RefCountedThreadSafe<GetOriginsTask>; ~GetOriginsTask(); - void OnOriginsObtained(const std::set<GURL>& origins, + void OnOriginsObtained(const std::set<url::Origin>& origins, blink::mojom::StorageType type); - void OnUsageAndQuotaObtained(const GURL& origin, + void OnUsageAndQuotaObtained(const url::Origin& origin, blink::mojom::QuotaStatusCode status_code, int64_t usage, int64_t quota); @@ -92,31 +93,29 @@ base::BindOnce(&GetOriginsTask::OnOriginsObtained, this))); } -void GetOriginsTask::OnOriginsObtained(const std::set<GURL>& origins, +void GetOriginsTask::OnOriginsObtained(const std::set<url::Origin>& origins, blink::mojom::StorageType type) { DCHECK_CURRENTLY_ON(BrowserThread::IO); num_callbacks_to_wait_ = origins.size(); num_callbacks_received_ = 0u; - for (std::set<GURL>::const_iterator origin = origins.begin(); - origin != origins.end(); ++origin) { + for (const url::Origin& origin : origins) { quota_manager_->GetUsageAndQuota( - *origin, type, - base::BindOnce(&GetOriginsTask::OnUsageAndQuotaObtained, this, - *origin)); + origin, type, + base::BindOnce(&GetOriginsTask::OnUsageAndQuotaObtained, this, origin)); } CheckDone(); } void GetOriginsTask::OnUsageAndQuotaObtained( - const GURL& origin, + const url::Origin& origin, blink::mojom::QuotaStatusCode status_code, int64_t usage, int64_t quota) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (status_code == blink::mojom::QuotaStatusCode::kOk) { - origin_.push_back(origin.spec()); + origin_.push_back(origin.GetURL().spec()); usage_.push_back(usage); quota_.push_back(quota); } @@ -317,10 +316,12 @@ base::BindOnce(&AwQuotaManagerBridge::QuotaUsageCallbackImpl, weak_factory_.GetWeakPtr(), callback_id, is_quota); + // TODO(crbug.com/889590): Use helper for url::Origin creation from string. base::PostTaskWithTraits( FROM_HERE, {BrowserThread::IO}, base::BindOnce( - &QuotaManager::GetUsageAndQuota, GetQuotaManager(), GURL(origin), + &QuotaManager::GetUsageAndQuota, GetQuotaManager(), + url::Origin::Create(GURL(origin)), blink::mojom::StorageType::kTemporary, base::BindOnce(&OnUsageAndQuotaObtained, std::move(ui_callback)))); }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 90dd255..7ce5e92 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -34,7 +34,6 @@ "accelerators/accelerator_controller.h", "accessibility/accessibility_controller.h", "accessibility/accessibility_delegate.h", - "accessibility/ax_host_service.h", "accessibility/focus_ring_controller.h", "app_list/app_list_controller_impl.h", "detachable_base/detachable_base_handler.h", @@ -132,7 +131,6 @@ "accessibility/accessibility_observer.h", "accessibility/accessibility_panel_layout_manager.cc", "accessibility/accessibility_panel_layout_manager.h", - "accessibility/ax_host_service.cc", "accessibility/default_accessibility_delegate.cc", "accessibility/default_accessibility_delegate.h", "accessibility/focus_ring_controller.cc", @@ -1689,7 +1687,6 @@ "accessibility/accessibility_focus_ring_group_unittest.cc", "accessibility/accessibility_highlight_controller_unittest.cc", "accessibility/accessibility_panel_layout_manager_unittest.cc", - "accessibility/ax_host_service_unittest.cc", "accessibility/key_accessibility_enabler_unittest.cc", "accessibility/touch_accessibility_enabler_unittest.cc", "accessibility/touch_exploration_controller_unittest.cc",
diff --git a/ash/accessibility/accessibility_delegate.h b/ash/accessibility/accessibility_delegate.h index 0a33e6d3..c59d0e6 100644 --- a/ash/accessibility/accessibility_delegate.h +++ b/ash/accessibility/accessibility_delegate.h
@@ -5,15 +5,9 @@ #ifndef ASH_ACCESSIBILITY_ACCESSIBILITY_DELEGATE_H_ #define ASH_ACCESSIBILITY_ACCESSIBILITY_DELEGATE_H_ -#include <vector> - #include "ash/ash_export.h" -#include "ui/accessibility/ax_tree_id.h" -#include "ui/accessibility/ax_tree_update.h" - -namespace ui { -struct AXEvent; -} +#include "base/time/time.h" +#include "ui/accessibility/ax_enums.mojom.h" namespace ash { @@ -42,14 +36,6 @@ // is not saved, return a negative value. virtual double GetSavedScreenMagnifierScale() = 0; - // Automation API support for remote mojo apps. - // TODO(jamescook): Convert to mojo API. - virtual void DispatchAccessibilityEvent( - const ui::AXTreeID& tree_id, - const std::vector<ui::AXTreeUpdate>& updates, - const ui::AXEvent& event) = 0; - virtual void DispatchTreeDestroyedEvent(const ui::AXTreeID& tree_id) = 0; - // NOTE: Prefer adding methods to AccessibilityController, see class comment. };
diff --git a/ash/accessibility/default_accessibility_delegate.cc b/ash/accessibility/default_accessibility_delegate.cc index f4b5ec3..f57af83 100644 --- a/ash/accessibility/default_accessibility_delegate.cc +++ b/ash/accessibility/default_accessibility_delegate.cc
@@ -40,12 +40,4 @@ return std::numeric_limits<double>::min(); } -void DefaultAccessibilityDelegate::DispatchAccessibilityEvent( - const ui::AXTreeID& tree_id, - const std::vector<ui::AXTreeUpdate>& updates, - const ui::AXEvent& event) {} - -void DefaultAccessibilityDelegate::DispatchTreeDestroyedEvent( - const ui::AXTreeID& tree_id) {} - } // namespace ash
diff --git a/ash/accessibility/default_accessibility_delegate.h b/ash/accessibility/default_accessibility_delegate.h index 2f09148..4287df6 100644 --- a/ash/accessibility/default_accessibility_delegate.h +++ b/ash/accessibility/default_accessibility_delegate.h
@@ -11,7 +11,6 @@ namespace ash { -// Used in tests and non-production code like ash_shell_with_content. class ASH_EXPORT DefaultAccessibilityDelegate : public AccessibilityDelegate { public: DefaultAccessibilityDelegate(); @@ -22,10 +21,6 @@ bool ShouldShowAccessibilityMenu() const override; void SaveScreenMagnifierScale(double scale) override; double GetSavedScreenMagnifierScale() override; - void DispatchAccessibilityEvent(const ui::AXTreeID& tree_id, - const std::vector<ui::AXTreeUpdate>& updates, - const ui::AXEvent& event) override; - void DispatchTreeDestroyedEvent(const ui::AXTreeID& tree_id) override; private: bool screen_magnifier_enabled_ = false;
diff --git a/ash/ash_service.cc b/ash/ash_service.cc index 399948e4..5ec00b29 100644 --- a/ash/ash_service.cc +++ b/ash/ash_service.cc
@@ -203,7 +203,6 @@ service_manager::mojom::ServiceRequest service, const std::string& name, service_manager::mojom::PIDReceiverPtr pid_receiver) { - // TODO(jamescook): Create the AXHostService here under mash. DCHECK_EQ(name, ws::mojom::kServiceName); Shell::Get()->window_service_owner()->BindWindowService(std::move(service)); if (base::FeatureList::IsEnabled(features::kMash)) {
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 4709c96..350f866 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -1533,10 +1533,10 @@ <ph name="DEVICE_NAME">$1<ex>Pixel XL</ex></ph> added </message> <message name="IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_HOST_SWITCHED_MESSAGE" desc="Message shown as part of the notification shown to a user that has already completed the MultiDevice setup flow that a new phone is replacing the phone they currently have set up to connect to their Chromebook."> - Better Together switched to a new phone + Chromebook connected to a new phone </message> <message name="IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROMEBOOK_ADDED_TITLE" desc="Title of the notification shown to a user that has already completed the MultiDevice setup flow logging into a new Chromebook that all their Chromebooks are MultiDevice enabled."> - Better Together is on + Connected to <ph name="DEVICE_NAME">$1<ex>Pixel XL</ex></ph> </message> <message name="IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROMEBOOK_ADDED_MESSAGE" desc="Message shown as part of the notification shown to a user that has already completed the MultiDevice setup flow logging into a new Chromebook that all their Chromebooks are MultiDevice enabled."> This Chromebook and your phone will connect automatically
diff --git a/ash/assistant/assistant_controller.cc b/ash/assistant/assistant_controller.cc index 5e801e7..7a873eb 100644 --- a/ash/assistant/assistant_controller.cc +++ b/ash/assistant/assistant_controller.cc
@@ -303,7 +303,10 @@ return; } - Shell::Get()->new_window_controller()->NewTabWithUrl(url); + // The new tab should be opened with a user activation since the user + // interacted with the assistant to open the url. + Shell::Get()->new_window_controller()->NewTabWithUrl( + url, true /* from_user_interaction */); NotifyUrlOpened(url); }
diff --git a/ash/dbus/url_handler_service_provider.cc b/ash/dbus/url_handler_service_provider.cc index 6ee4f79..9af2baa 100644 --- a/ash/dbus/url_handler_service_provider.cc +++ b/ash/dbus/url_handler_service_provider.cc
@@ -69,7 +69,8 @@ return; } - ash::Shell::Get()->new_window_controller()->NewTabWithUrl(gurl); + ash::Shell::Get()->new_window_controller()->NewTabWithUrl( + gurl, false /* from_user_interaction */); response_sender.Run(dbus::Response::FromMethodCall(method_call)); }
diff --git a/ash/new_window_controller.cc b/ash/new_window_controller.cc index 9d307ea7..a47fb17 100644 --- a/ash/new_window_controller.cc +++ b/ash/new_window_controller.cc
@@ -29,9 +29,10 @@ client_->ShowKeyboardOverlay(); } -void NewWindowController::NewTabWithUrl(const GURL& url) { +void NewWindowController::NewTabWithUrl(const GURL& url, + bool from_user_interaction) { if (client_) - client_->NewTabWithUrl(url); + client_->NewTabWithUrl(url, from_user_interaction); } void NewWindowController::NewTab() {
diff --git a/ash/new_window_controller.h b/ash/new_window_controller.h index 186b407a..c28d221c 100644 --- a/ash/new_window_controller.h +++ b/ash/new_window_controller.h
@@ -29,7 +29,7 @@ void ShowKeyboardOverlay() override; // Pass throughs for methods of the same name on |client_|. - void NewTabWithUrl(const GURL& url); + void NewTabWithUrl(const GURL& url, bool from_user_interaction); void NewTab(); void NewWindow(bool incognito); void OpenFileManager();
diff --git a/ash/public/interfaces/new_window.mojom b/ash/public/interfaces/new_window.mojom index 98efe46..2c1231a 100644 --- a/ash/public/interfaces/new_window.mojom +++ b/ash/public/interfaces/new_window.mojom
@@ -24,8 +24,10 @@ // Invoked when the user uses Ctrl+T to open a new tab. NewTab(); - // Opens a new tab with the specified URL. - NewTabWithUrl(url.mojom.Url url); + // Opens a new tab with the specified URL. If the |from_user_interaction| + // is true then the page will load with a user activation. This means the + // page will be able to autoplay media without restriction. + NewTabWithUrl(url.mojom.Url url, bool from_user_interaction); // Invoked when the user uses Ctrl-N or Ctrl-Shift-N to open a new window. NewWindow(bool incognito);
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc index 783e2e7e..dd1c79a 100644 --- a/ash/test/ash_test_helper.cc +++ b/ash/test/ash_test_helper.cc
@@ -30,6 +30,7 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/power_policy_controller.h" #include "chromeos/network/network_handler.h" +#include "chromeos/system/fake_statistics_provider.h" #include "components/discardable_memory/public/interfaces/discardable_shared_memory_manager.mojom.h" #include "components/prefs/testing_pref_service.h" #include "device/bluetooth/bluetooth_adapter_factory.h" @@ -232,6 +233,9 @@ switches::kAshDisableSmoothScreenRotation); } + statistics_provider_ = + std::make_unique<chromeos::system::ScopedFakeStatisticsProvider>(); + ui::test::EventGeneratorDelegate::SetFactoryFunction(base::BindRepeating( &aura::test::EventGeneratorDelegateAura::Create, nullptr)); @@ -383,6 +387,8 @@ ui::test::EventGeneratorDelegate::SetFactoryFunction( ui::test::EventGeneratorDelegate::FactoryFunction()); + + statistics_provider_.reset(); } void AshTestHelper::SetRunningOutsideAsh() {
diff --git a/ash/test/ash_test_helper.h b/ash/test/ash_test_helper.h index a9bc8e5f..b8653a7 100644 --- a/ash/test/ash_test_helper.h +++ b/ash/test/ash_test_helper.h
@@ -23,6 +23,12 @@ } } +namespace chromeos { +namespace system { +class ScopedFakeStatisticsProvider; +} // namespace system +} // namespace chromeos + namespace display { class Display; } @@ -113,6 +119,9 @@ // Called when running in ash to create Shell. void CreateShell(); + std::unique_ptr<chromeos::system::ScopedFakeStatisticsProvider> + statistics_provider_; + std::unique_ptr<aura::test::EnvWindowTreeClientSetter> env_window_tree_client_setter_; AshTestEnvironment* ash_test_environment_; // Not owned.
diff --git a/ash/wm/non_client_frame_controller_unittest.cc b/ash/wm/non_client_frame_controller_unittest.cc index 20b61c5..df54544 100644 --- a/ash/wm/non_client_frame_controller_unittest.cc +++ b/ash/wm/non_client_frame_controller_unittest.cc
@@ -226,7 +226,7 @@ } TEST_F(NonClientFrameControllerTest, ExposesChildTreeIdToAccessibility) { - const ui::AXTreeID ax_tree_id("123"); + const ui::AXTreeID ax_tree_id = ui::AXTreeID::FromString("123"); Shell::Get()->accessibility_controller()->set_remote_ax_tree_id(ax_tree_id); std::unique_ptr<aura::Window> window = CreateTestWindow(); NonClientFrameController* non_client_frame_controller = @@ -234,8 +234,9 @@ views::View* contents_view = non_client_frame_controller->GetContentsView(); ui::AXNodeData ax_node_data; contents_view->GetAccessibleNodeData(&ax_node_data); - EXPECT_EQ(ax_tree_id, ax_node_data.GetStringAttribute( - ax::mojom::StringAttribute::kChildTreeId)); + EXPECT_EQ(ax_tree_id, + ui::AXTreeID::FromString(ax_node_data.GetStringAttribute( + ax::mojom::StringAttribute::kChildTreeId))); EXPECT_EQ(ax::mojom::Role::kClient, ax_node_data.role); }
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h index 95611a5..571d1de 100644 --- a/base/allocator/partition_allocator/partition_alloc.h +++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -348,9 +348,9 @@ size_t size, const char* type_name) { DCHECK_LT(flags, PartitionAllocLastFlag << 1); - const bool zero_fill = flags & PartitionAllocZeroFill; #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + const bool zero_fill = flags & PartitionAllocZeroFill; void* result = zero_fill ? calloc(1, size) : malloc(size); CHECK(result || flags & PartitionAllocReturnNull); return result; @@ -366,13 +366,6 @@ } PartitionAllocHooks::AllocationHookIfEnabled(ret, requested_size, type_name); - // TODO(crbug.com/864462): This is suboptimal. Change `AllocFromBucket` such - // that it tells callers if the allocation was satisfied with a fresh mapping - // from the OS, so that we can skip this step and save some time. - if (ret && zero_fill) { - memset(ret, 0, requested_size); - } - return ret; #endif }
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc index 82f4fa61..c5c08ba 100644 --- a/base/allocator/partition_allocator/partition_alloc_unittest.cc +++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -11,8 +11,11 @@ #include <vector> #include "base/allocator/partition_allocator/address_space_randomization.h" +#include "base/allocator/partition_allocator/partition_alloc.h" #include "base/bit_cast.h" #include "base/bits.h" +#include "base/rand_util.h" +#include "base/stl_util.h" #include "base/sys_info.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" @@ -86,6 +89,35 @@ #endif } +const size_t kTestSizes[] = { + 1, + 17, + 100, + base::kSystemPageSize, + base::kSystemPageSize + 1, + base::internal::PartitionBucket::get_direct_map_size(100), + 1 << 20, + 1 << 21, +}; +constexpr size_t kTestSizesCount = base::size(kTestSizes); + +void AllocateRandomly(base::PartitionRootGeneric* root, + size_t count, + int flags) { + std::vector<void*> allocations(count, nullptr); + for (size_t i = 0; i < count; ++i) { + const size_t size = kTestSizes[base::RandGenerator(kTestSizesCount)]; + allocations[i] = PartitionAllocGenericFlags(root, flags, size, nullptr); + EXPECT_NE(nullptr, allocations[i]) << " size: " << size << " i: " << i; + } + + for (size_t i = 0; i < count; ++i) { + if (allocations[i]) { + base::PartitionFree(allocations[i]); + } + } +} + } // namespace namespace base { @@ -2156,20 +2188,9 @@ } TEST_F(PartitionAllocTest, ZeroFill) { - const size_t test_sizes[] = { - 1, - 17, - 100, - kSystemPageSize, - kSystemPageSize + 1, - internal::PartitionBucket::get_direct_map_size(100), - 1 << 20, - 1 << 21, - }; - constexpr static size_t kAllZerosSentinel = std::numeric_limits<size_t>::max(); - for (size_t size : test_sizes) { + for (size_t size : kTestSizes) { char* p = static_cast<char*>(PartitionAllocGenericFlags( generic_allocator.root(), PartitionAllocZeroFill, size, nullptr)); size_t non_zero_position = kAllZerosSentinel; @@ -2183,6 +2204,11 @@ << "test allocation size: " << size; PartitionFree(p); } + + for (int i = 0; i < 10; ++i) { + SCOPED_TRACE(i); + AllocateRandomly(generic_allocator.root(), 1000, PartitionAllocZeroFill); + } } } // namespace internal
diff --git a/base/allocator/partition_allocator/partition_bucket.cc b/base/allocator/partition_allocator/partition_bucket.cc index 6751889..79d2dad 100644 --- a/base/allocator/partition_allocator/partition_bucket.cc +++ b/base/allocator/partition_allocator/partition_bucket.cc
@@ -448,11 +448,13 @@ void* PartitionBucket::SlowPathAlloc(PartitionRootBase* root, int flags, - size_t size) { + size_t size, + bool* is_already_zeroed) { // The slow path is called when the freelist is empty. DCHECK(!this->active_pages_head->freelist_head); PartitionPage* new_page = nullptr; + *is_already_zeroed = false; // For the PartitionRootGeneric::Alloc() API, we have a bunch of buckets // marked as special cases. We bounce them through to the slow path so that @@ -474,6 +476,7 @@ PartitionExcessiveAllocationSize(); } new_page = PartitionDirectMap(root, flags, size); + *is_already_zeroed = true; } else if (LIKELY(this->SetNewActivePage())) { // First, did we find an active page in the active pages list? new_page = this->active_pages_head; @@ -505,6 +508,7 @@ void* addr = PartitionPage::ToPointer(new_page); root->RecommitSystemPages(addr, new_page->bucket->get_bytes_per_span()); new_page->Reset(); + *is_already_zeroed = true; } DCHECK(new_page); } else { @@ -514,6 +518,7 @@ if (LIKELY(raw_pages != nullptr)) { new_page = PartitionPage::FromPointerNoAlignmentCheck(raw_pages); InitializeSlotSpan(new_page); + *is_already_zeroed = true; } }
diff --git a/base/allocator/partition_allocator/partition_bucket.h b/base/allocator/partition_allocator/partition_bucket.h index a626dfa8..a30b5694 100644 --- a/base/allocator/partition_allocator/partition_bucket.h +++ b/base/allocator/partition_allocator/partition_bucket.h
@@ -31,10 +31,17 @@ // Public API. void Init(uint32_t new_slot_size); + // Sets |is_already_zeroed| to true if the allocation was satisfied by + // requesting (a) new page(s) from the operating system, or false otherwise. + // This enables an optimization for when callers use |PartitionAllocZeroFill|: + // there is no need to call memset on fresh pages; the OS has already zeroed + // them. (See |PartitionRootBase::AllocFromBucket|.) + // // Note the matching Free() functions are in PartitionPage. BASE_EXPORT NOINLINE void* SlowPathAlloc(PartitionRootBase* root, int flags, - size_t size); + size_t size, + bool* is_already_zeroed); ALWAYS_INLINE bool is_direct_mapped() const { return !num_system_pages_per_slot_span;
diff --git a/base/allocator/partition_allocator/partition_root_base.h b/base/allocator/partition_allocator/partition_root_base.h index e20990e4..0d22c09 100644 --- a/base/allocator/partition_allocator/partition_root_base.h +++ b/base/allocator/partition_allocator/partition_root_base.h
@@ -86,16 +86,20 @@ ALWAYS_INLINE void* PartitionRootBase::AllocFromBucket(PartitionBucket* bucket, int flags, size_t size) { + bool zero_fill = flags & PartitionAllocZeroFill; + bool is_already_zeroed = false; + PartitionPage* page = bucket->active_pages_head; // Check that this page is neither full nor freed. DCHECK(page->num_allocated_slots >= 0); void* ret = page->freelist_head; if (LIKELY(ret != 0)) { - // If these DCHECKs fire, you probably corrupted memory. - // TODO(palmer): See if we can afford to make this a CHECK. + // If these DCHECKs fire, you probably corrupted memory. TODO(palmer): See + // if we can afford to make these CHECKs. DCHECK(PartitionRootBase::IsValidPage(page)); - // All large allocations must go through the slow path to correctly - // update the size metadata. + + // All large allocations must go through the slow path to correctly update + // the size metadata. DCHECK(page->get_raw_size() == 0); internal::PartitionFreelistEntry* new_head = internal::PartitionFreelistEntry::Transform( @@ -103,15 +107,17 @@ page->freelist_head = new_head; page->num_allocated_slots++; } else { - ret = bucket->SlowPathAlloc(this, flags, size); + ret = bucket->SlowPathAlloc(this, flags, size, &is_already_zeroed); // TODO(palmer): See if we can afford to make this a CHECK. DCHECK(!ret || PartitionRootBase::IsValidPage(PartitionPage::FromPointer(ret))); } + #if DCHECK_IS_ON() - if (!ret) - return 0; - // Fill the uninitialized pattern, and write the cookies. + if (!ret) { + return nullptr; + } + page = PartitionPage::FromPointer(ret); // TODO(ajwong): Can |page->bucket| ever not be |this|? If not, can this just // be bucket->slot_size? @@ -126,11 +132,20 @@ // The value given to the application is actually just after the cookie. ret = char_ret + kCookieSize; - // Debug fill region kUninitializedByte and surround it with 2 cookies. + // Fill the region kUninitializedByte or 0, and surround it with 2 cookies. PartitionCookieWriteValue(char_ret); - memset(ret, kUninitializedByte, no_cookie_size); + if (!zero_fill) { + memset(ret, kUninitializedByte, no_cookie_size); + } else if (!is_already_zeroed) { + memset(ret, 0, no_cookie_size); + } PartitionCookieWriteValue(char_ret + kCookieSize + no_cookie_size); +#else + if (ret && zero_fill && !is_already_zeroed) { + memset(ret, 0, size); + } #endif + return ret; }
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc index 22195837..c1d4a1a4 100644 --- a/base/message_loop/message_loop_unittest.cc +++ b/base/message_loop/message_loop_unittest.cc
@@ -346,55 +346,14 @@ #if defined(OS_WIN) -void SubPumpFunc() { - MessageLoopCurrent::Get()->SetNestableTasksAllowed(true); +void SubPumpFunc(OnceClosure on_done) { + MessageLoopCurrent::ScopedNestableTaskAllower allow_nestable_tasks; MSG msg; - while (GetMessage(&msg, NULL, 0, 0)) { - TranslateMessage(&msg); - DispatchMessage(&msg); + while (::GetMessage(&msg, NULL, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); } - RunLoop::QuitCurrentWhenIdleDeprecated(); -} - -void RunTest_PostDelayedTask_SharedTimer_SubPump() { - MessageLoop message_loop(MessageLoop::TYPE_UI); - - // Test that the interval of the timer, used to run the next delayed task, is - // set to a value corresponding to when the next delayed task should run. - - // By setting num_tasks to 1, we ensure that the first task to run causes the - // run loop to exit. - int num_tasks = 1; - TimeTicks run_time; - - message_loop.task_runner()->PostTask(FROM_HERE, BindOnce(&SubPumpFunc)); - - // This very delayed task should never run. - message_loop.task_runner()->PostDelayedTask( - FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time, &num_tasks), - TimeDelta::FromSeconds(1000)); - - // This slightly delayed task should run from within SubPumpFunc. - message_loop.task_runner()->PostDelayedTask(FROM_HERE, - BindOnce(&PostQuitMessage, 0), - TimeDelta::FromMilliseconds(10)); - - Time start_time = Time::Now(); - - RunLoop().Run(); - EXPECT_EQ(1, num_tasks); - - // Ensure that we ran in far less time than the slower timer. - TimeDelta total_time = Time::Now() - start_time; - EXPECT_GT(5000, total_time.InMilliseconds()); - - // In case both timers somehow run at nearly the same time, sleep a little - // and then run all pending to force them both to have run. This is just - // encouraging flakiness if there is any. - PlatformThread::Sleep(TimeDelta::FromMilliseconds(100)); - RunLoop().RunUntilIdle(); - - EXPECT_TRUE(run_time.is_null()); + std::move(on_done).Run(); } const wchar_t kMessageBoxTitle[] = L"MessageLoop Unit Test"; @@ -465,93 +424,6 @@ } } -// TODO(darin): These tests need to be ported since they test critical -// message loop functionality. - -// A side effect of this test is the generation a beep. Sorry. -void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) { - MessageLoop loop(message_loop_type); - - Thread worker("RecursiveDenial2_worker"); - Thread::Options options; - options.message_loop_type = message_loop_type; - ASSERT_EQ(true, worker.StartWithOptions(options)); - TaskList order; - win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); - worker.task_runner()->PostTask( - FROM_HERE, BindOnce(&RecursiveFuncWin, ThreadTaskRunnerHandle::Get(), - event.Get(), true, &order, false)); - // Let the other thread execute. - WaitForSingleObject(event.Get(), INFINITE); - RunLoop().Run(); - - ASSERT_EQ(17u, order.Size()); - EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); - EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); - EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true)); - EXPECT_EQ(order.Get(3), TaskItem(MESSAGEBOX, 2, false)); - EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, true)); - EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 3, false)); - // When EndDialogFunc is processed, the window is already dismissed, hence no - // "end" entry. - EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, true)); - EXPECT_EQ(order.Get(7), TaskItem(QUITMESSAGELOOP, 5, true)); - EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, false)); - EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 1, true)); - EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, false)); - EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 3, true)); - EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, false)); - EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, true)); - EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, false)); - EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 3, true)); - EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, false)); -} - -// A side effect of this test is the generation a beep. Sorry. This test also -// needs to process windows messages on the current thread. -void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) { - MessageLoop loop(message_loop_type); - - Thread worker("RecursiveSupport2_worker"); - Thread::Options options; - options.message_loop_type = message_loop_type; - ASSERT_EQ(true, worker.StartWithOptions(options)); - TaskList order; - win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); - worker.task_runner()->PostTask( - FROM_HERE, BindOnce(&RecursiveFuncWin, ThreadTaskRunnerHandle::Get(), - event.Get(), false, &order, true)); - // Let the other thread execute. - WaitForSingleObject(event.Get(), INFINITE); - RunLoop().Run(); - - ASSERT_EQ(18u, order.Size()); - EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); - EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); - EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true)); - // Note that this executes in the MessageBox modal loop. - EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 3, true)); - EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, false)); - EXPECT_EQ(order.Get(5), TaskItem(ENDDIALOG, 4, true)); - EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, false)); - EXPECT_EQ(order.Get(7), TaskItem(MESSAGEBOX, 2, false)); - /* The order can subtly change here. The reason is that when RecursiveFunc(1) - is called in the main thread, if it is faster than getting to the - PostTask(FROM_HERE, BindOnce(&QuitFunc) execution, the order of task - execution can change. We don't care anyway that the order isn't correct. - EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, true)); - EXPECT_EQ(order.Get(9), TaskItem(QUITMESSAGELOOP, 5, false)); - EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true)); - EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false)); - */ - EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, true)); - EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 3, false)); - EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, true)); - EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 1, false)); - EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, true)); - EXPECT_EQ(order.Get(17), TaskItem(RECURSIVE, 3, false)); -} - #endif // defined(OS_WIN) void PostNTasksThenQuit(int posts_remaining) { @@ -1734,9 +1606,10 @@ MessageLoopTypedTest::ParamInfoToString); #if defined(OS_WIN) + // Verifies that the MessageLoop ignores WM_QUIT, rather than quitting. // Users of MessageLoop typically expect to control when their RunLoops stop -// Run()ning explicitly, via QuitClosure() etc (see https://crbug.com/720078) +// Run()ning explicitly, via QuitClosure() etc (see https://crbug.com/720078). TEST_F(MessageLoopTest, WmQuitIsIgnored) { MessageLoop loop(MessageLoop::TYPE_UI); @@ -1786,9 +1659,213 @@ } TEST_F(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) { - RunTest_PostDelayedTask_SharedTimer_SubPump(); + MessageLoop message_loop(MessageLoop::TYPE_UI); + + // Test that the interval of the timer, used to run the next delayed task, is + // set to a value corresponding to when the next delayed task should run. + + // By setting num_tasks to 1, we ensure that the first task to run causes the + // run loop to exit. + int num_tasks = 1; + TimeTicks run_time; + + RunLoop run_loop; + + message_loop.task_runner()->PostTask( + FROM_HERE, BindOnce(&SubPumpFunc, run_loop.QuitClosure())); + + // This very delayed task should never run. + message_loop.task_runner()->PostDelayedTask( + FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time, &num_tasks), + TimeDelta::FromSeconds(1000)); + + // This slightly delayed task should run from within SubPumpFunc. + message_loop.task_runner()->PostDelayedTask(FROM_HERE, + BindOnce(&::PostQuitMessage, 0), + TimeDelta::FromMilliseconds(10)); + + Time start_time = Time::Now(); + + run_loop.Run(); + EXPECT_EQ(1, num_tasks); + + // Ensure that we ran in far less time than the slower timer. + TimeDelta total_time = Time::Now() - start_time; + EXPECT_GT(5000, total_time.InMilliseconds()); + + // In case both timers somehow run at nearly the same time, sleep a little + // and then run all pending to force them both to have run. This is just + // encouraging flakiness if there is any. + PlatformThread::Sleep(TimeDelta::FromMilliseconds(100)); + RunLoop().RunUntilIdle(); + + EXPECT_TRUE(run_time.is_null()); } +TEST_F(MessageLoopTest, WmQuitIsVisibleToSubPump) { + MessageLoop message_loop(MessageLoop::TYPE_UI); + + // Regression test for https://crbug.com/888559. When processing a + // kMsgHaveWork we peek and remove the next message and dispatch that ourself, + // to minimize impact of these messages on message-queue processing. If we + // received kMsgHaveWork dispatched by a nested pump (e.g. ::GetMessage() + // loop) then there is a risk that the next message is that loop's WM_QUIT + // message, which must be processed directly by ::GetMessage() for the loop to + // actually quit. This test verifies that WM_QUIT exits works as expected even + // if it happens to immediately follow a kMsgHaveWork in the queue. + + RunLoop run_loop; + + // This application task will enter the subpump. + message_loop.task_runner()->PostTask( + FROM_HERE, BindOnce(&SubPumpFunc, run_loop.QuitClosure())); + + // This application task will post a native WM_QUIT. + message_loop.task_runner()->PostTask(FROM_HERE, + BindOnce(&::PostQuitMessage, 0)); + + // The presence of this application task means that the pump will see a + // non-empty queue after processing the previous application task (which + // posted the WM_QUIT) and hence will repost a kMsgHaveWork message in the + // native event queue. Without the fix to https://crbug.com/888559, this would + // previously result in the subpump processing kMsgHaveWork and it stealing + // the WM_QUIT message, leaving the test hung in the subpump. + message_loop.task_runner()->PostTask(FROM_HERE, DoNothing()); + + // Test success is determined by not hanging in this Run() call. + run_loop.Run(); +} + +TEST_F(MessageLoopTest, RepostingWmQuitDoesntStarveUpcomingNativeLoop) { + MessageLoop message_loop(MessageLoop::TYPE_UI); + + // This test ensures that application tasks are being processed by the native + // subpump despite the kMsgHaveWork event having already been consumed by the + // time the subpump is entered. This is subtly enforced by + // MessageLoopCurrent::ScopedNestableTaskAllower which will ScheduleWork() + // upon construction (and if it's absent, the MessageLoop shouldn't process + // application tasks so kMsgHaveWork is irrelevant). + // Note: This test also fails prior to the fix for https://crbug.com/888559 + // (in fact, the last two tasks are sufficient as a regression test), probably + // because of a dangling kMsgHaveWork recreating the effect from + // MessageLoopTest.NativeMsgProcessingDoesntStealWmQuit. + + RunLoop run_loop; + + // This application task will post a native WM_QUIT which will be ignored + // by the main message pump. + message_loop.task_runner()->PostTask(FROM_HERE, + BindOnce(&::PostQuitMessage, 0)); + + // Make sure the pump does a few extra cycles and processes (ignores) the + // WM_QUIT. + message_loop.task_runner()->PostTask(FROM_HERE, DoNothing()); + message_loop.task_runner()->PostTask(FROM_HERE, DoNothing()); + + // This application task will enter the subpump. + message_loop.task_runner()->PostTask( + FROM_HERE, BindOnce(&SubPumpFunc, run_loop.QuitClosure())); + + // Post an application task that will post WM_QUIT to the nested loop. The + // test will hang if the subpump doesn't process application tasks as it + // should. + message_loop.task_runner()->PostTask(FROM_HERE, + BindOnce(&::PostQuitMessage, 0)); + + // Test success is determined by not hanging in this Run() call. + run_loop.Run(); +} + +// TODO(https://crbug.com/890016): Enable once multiple layers of nested loops +// works. +TEST_F(MessageLoopTest, + DISABLED_UnwindingMultipleSubPumpsDoesntStarveApplicationTasks) { + MessageLoop message_loop(MessageLoop::TYPE_UI); + + // Regression test for https://crbug.com/890016. + // Tests that the subpump is still processing application tasks after + // unwinding from nested subpumps (i.e. that they didn't consume the last + // kMsgHaveWork). + + RunLoop run_loop; + + // Enter multiple levels of nested subpumps. + message_loop.task_runner()->PostTask( + FROM_HERE, BindOnce(&SubPumpFunc, run_loop.QuitClosure())); + message_loop.task_runner()->PostTask( + FROM_HERE, BindOnce(&SubPumpFunc, DoNothing::Once())); + message_loop.task_runner()->PostTask( + FROM_HERE, BindOnce(&SubPumpFunc, DoNothing::Once())); + + // Quit two layers (with tasks in between to allow each quit to be handled + // before continuing -- ::PostQuitMessage() sets a bit, it's not a real queued + // message : + // https://blogs.msdn.microsoft.com/oldnewthing/20051104-33/?p=33453). + message_loop.task_runner()->PostTask(FROM_HERE, + BindOnce(&::PostQuitMessage, 0)); + message_loop.task_runner()->PostTask(FROM_HERE, DoNothing()); + message_loop.task_runner()->PostTask(FROM_HERE, DoNothing()); + message_loop.task_runner()->PostTask(FROM_HERE, + BindOnce(&::PostQuitMessage, 0)); + message_loop.task_runner()->PostTask(FROM_HERE, DoNothing()); + message_loop.task_runner()->PostTask(FROM_HERE, DoNothing()); + + bool last_task_ran = false; + message_loop.task_runner()->PostTask( + FROM_HERE, BindOnce([](bool* to_set) { *to_set = true; }, + Unretained(&last_task_ran))); + + message_loop.task_runner()->PostTask(FROM_HERE, + BindOnce(&::PostQuitMessage, 0)); + + run_loop.Run(); + + EXPECT_TRUE(last_task_ran); +} + +namespace { + +// A side effect of this test is the generation a beep. Sorry. +void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) { + MessageLoop loop(message_loop_type); + + Thread worker("RecursiveDenial2_worker"); + Thread::Options options; + options.message_loop_type = message_loop_type; + ASSERT_EQ(true, worker.StartWithOptions(options)); + TaskList order; + win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); + worker.task_runner()->PostTask( + FROM_HERE, BindOnce(&RecursiveFuncWin, ThreadTaskRunnerHandle::Get(), + event.Get(), true, &order, false)); + // Let the other thread execute. + WaitForSingleObject(event.Get(), INFINITE); + RunLoop().Run(); + + ASSERT_EQ(17u, order.Size()); + EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); + EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); + EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true)); + EXPECT_EQ(order.Get(3), TaskItem(MESSAGEBOX, 2, false)); + EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, true)); + EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 3, false)); + // When EndDialogFunc is processed, the window is already dismissed, hence no + // "end" entry. + EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, true)); + EXPECT_EQ(order.Get(7), TaskItem(QUITMESSAGELOOP, 5, true)); + EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, false)); + EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 1, true)); + EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, false)); + EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 3, true)); + EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, false)); + EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, true)); + EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, false)); + EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 3, true)); + EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, false)); +} + +} // namespace + // This test occasionally hangs. See http://crbug.com/44567. TEST_F(MessageLoopTest, DISABLED_RecursiveDenial2) { RunTest_RecursiveDenial2(MessageLoop::TYPE_DEFAULT); @@ -1796,10 +1873,51 @@ RunTest_RecursiveDenial2(MessageLoop::TYPE_IO); } +// A side effect of this test is the generation a beep. Sorry. This test also +// needs to process windows messages on the current thread. TEST_F(MessageLoopTest, RecursiveSupport2) { - // This test requires a UI loop. - RunTest_RecursiveSupport2(MessageLoop::TYPE_UI); + MessageLoop loop(MessageLoop::TYPE_UI); + + Thread worker("RecursiveSupport2_worker"); + Thread::Options options; + options.message_loop_type = MessageLoop::TYPE_UI; + ASSERT_EQ(true, worker.StartWithOptions(options)); + TaskList order; + win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); + worker.task_runner()->PostTask( + FROM_HERE, BindOnce(&RecursiveFuncWin, ThreadTaskRunnerHandle::Get(), + event.Get(), false, &order, true)); + // Let the other thread execute. + WaitForSingleObject(event.Get(), INFINITE); + RunLoop().Run(); + + ASSERT_EQ(18u, order.Size()); + EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); + EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); + EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true)); + // Note that this executes in the MessageBox modal loop. + EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 3, true)); + EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, false)); + EXPECT_EQ(order.Get(5), TaskItem(ENDDIALOG, 4, true)); + EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, false)); + EXPECT_EQ(order.Get(7), TaskItem(MESSAGEBOX, 2, false)); + /* The order can subtly change here. The reason is that when RecursiveFunc(1) + is called in the main thread, if it is faster than getting to the + PostTask(FROM_HERE, BindOnce(&QuitFunc) execution, the order of task + execution can change. We don't care anyway that the order isn't correct. + EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, true)); + EXPECT_EQ(order.Get(9), TaskItem(QUITMESSAGELOOP, 5, false)); + EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true)); + EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false)); + */ + EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, true)); + EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 3, false)); + EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, true)); + EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 1, false)); + EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, true)); + EXPECT_EQ(order.Get(17), TaskItem(RECURSIVE, 3, false)); } + #endif // defined(OS_WIN) TEST_F(MessageLoopTest, TaskObserver) {
diff --git a/base/message_loop/message_pump_win.cc b/base/message_loop/message_pump_win.cc index bba71fa7..1d6748e0 100644 --- a/base/message_loop/message_pump_win.cc +++ b/base/message_loop/message_pump_win.cc
@@ -237,9 +237,9 @@ // current thread. MSG msg = {0}; bool has_pending_sent_message = - (HIWORD(GetQueueStatus(QS_SENDMESSAGE)) & QS_SENDMESSAGE) != 0; + (HIWORD(::GetQueueStatus(QS_SENDMESSAGE)) & QS_SENDMESSAGE) != 0; if (has_pending_sent_message || - PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE)) { + ::PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE)) { return; } @@ -341,12 +341,12 @@ // case to ensure that the message loop peeks again instead of calling // MsgWaitForMultipleObjectsEx again. bool sent_messages_in_queue = false; - DWORD queue_status = GetQueueStatus(QS_SENDMESSAGE); + DWORD queue_status = ::GetQueueStatus(QS_SENDMESSAGE); if (HIWORD(queue_status) & QS_SENDMESSAGE) sent_messages_in_queue = true; MSG msg; - if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE) + if (::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE) return ProcessMessageHelper(msg); return sent_messages_in_queue; @@ -356,17 +356,14 @@ TRACE_EVENT1("base,toplevel", "MessagePumpForUI::ProcessMessageHelper", "message", msg.message); if (WM_QUIT == msg.message) { + // WM_QUIT is the standard way to exit a ::GetMessage() loop. Our + // MessageLoop has its own quit mechanism, so WM_QUIT should only terminate + // it if |enable_wm_quit_| is explicitly set (and is generally unexpected + // otherwise). if (enable_wm_quit_) { - // Repost the QUIT message so that it will be retrieved by the primary - // GetMessage() loop. state_->should_quit = true; - PostQuitMessage(static_cast<int>(msg.wParam)); return false; } - - // WM_QUIT is the standard way to exit a GetMessage() loop. Our MessageLoop - // has its own quit mechanism, so WM_QUIT is unexpected and should be - // ignored when |enable_wm_quit_| is set to false. UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", RECEIVED_WM_QUIT_ERROR, MESSAGE_LOOP_PROBLEM_MAX); return true; @@ -378,8 +375,8 @@ for (Observer& observer : observers_) observer.WillDispatchMSG(msg); - TranslateMessage(&msg); - DispatchMessage(&msg); + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); for (Observer& observer : observers_) observer.DidDispatchMSG(msg); @@ -398,7 +395,7 @@ MSG msg; const bool have_message = - PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE; + ::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE; // Expect no message or a message different than kMsgHaveWork. DCHECK(!have_message || kMsgHaveWork != msg.message || @@ -412,8 +409,29 @@ if (!have_message) return false; + if (WM_QUIT == msg.message) { + // If we're in a nested ::GetMessage() loop then we must let that loop see + // the WM_QUIT in order for it to exit. If we're in DoRunLoop then the re- + // posted WM_QUIT will be either ignored, or handled, by + // ProcessMessageHelper() called directly from ProcessNextWindowsMessage(). + ::PostQuitMessage(static_cast<int>(msg.wParam)); + // Note: we *must not* ScheduleWork() here as WM_QUIT is a low-priority + // message on Windows (it is only returned by ::PeekMessage() when idle) : + // https://blogs.msdn.microsoft.com/oldnewthing/20051104-33/?p=33453. As + // such posting a kMsgHaveWork message via ScheduleWork() would cause an + // infinite loop (kMsgHaveWork message handled first means we end up here + // again and repost WM_QUIT+ScheduleWork() again, etc.). Not leaving a + // kMsgHaveWork message behind however is also problematic as unwinding + // multiple layers of nested ::GetMessage() loops can result in starving + // application tasks. TODO(https://crbug.com/890016) : Fix this. + + // The return value is mostly irrelevant but return true like we would after + // processing a QuitClosure() task. + return true; + } + // Guarantee we'll get another time slice in the case where we go into native - // windows code. This ScheduleWork() may hurt performance a tiny bit when + // windows code. This ScheduleWork() may hurt performance a tiny bit when // tasks appear very infrequently, but when the event queue is busy, the // kMsgHaveWork events get (percentage wise) rarer and rarer. ScheduleWork();
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker.cc b/base/trace_event/heap_profiler_allocation_context_tracker.cc index 556719e..98f5d11 100644 --- a/base/trace_event/heap_profiler_allocation_context_tracker.cc +++ b/base/trace_event/heap_profiler_allocation_context_tracker.cc
@@ -259,13 +259,7 @@ ctx->backtrace.frame_count = backtrace - std::begin(ctx->backtrace.frames); - // TODO(ssid): Fix crbug.com/594803 to add file name as 3rd dimension - // (component name) in the heap profiler and not piggy back on the type name. - if (!task_contexts_.empty()) { - ctx->type_name = task_contexts_.back(); - } else { - ctx->type_name = nullptr; - } + ctx->type_name = TaskContext(); return true; }
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker.h b/base/trace_event/heap_profiler_allocation_context_tracker.h index da03b7f6..a117ea0 100644 --- a/base/trace_event/heap_profiler_allocation_context_tracker.h +++ b/base/trace_event/heap_profiler_allocation_context_tracker.h
@@ -108,6 +108,11 @@ void PushCurrentTaskContext(const char* context); void PopCurrentTaskContext(const char* context); + // Returns most recent task context added by ScopedTaskExecutionTracker. + const char* TaskContext() const { + return task_contexts_.empty() ? nullptr : task_contexts_.back(); + } + // Fills a snapshot of the current thread-local context. Doesn't fill and // returns false if allocations are being ignored. bool GetContextSnapshot(AllocationContext* snapshot);
diff --git a/build/android/gyp/jar.py b/build/android/gyp/jar.py index fcfb7a5..3e85c3b 100755 --- a/build/android/gyp/jar.py +++ b/build/android/gyp/jar.py
@@ -63,12 +63,12 @@ def JarDirectory(classes_dir, jar_path, manifest_file=None, predicate=None, provider_configurations=None, additional_files=None): - all_files = sorted(build_utils.FindInDirectory(classes_dir, '*')) + all_classes = sorted(build_utils.FindInDirectory(classes_dir, '*.class')) if predicate: - all_files = [ - f for f in all_files if predicate(os.path.relpath(f, classes_dir))] + all_classes = [ + f for f in all_classes if predicate(os.path.relpath(f, classes_dir))] - Jar(all_files, classes_dir, jar_path, manifest_file=manifest_file, + Jar(all_classes, classes_dir, jar_path, manifest_file=manifest_file, provider_configurations=provider_configurations, additional_files=additional_files)
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py index e23ac3c..3a611b4 100755 --- a/build/android/gyp/javac.py +++ b/build/android/gyp/javac.py
@@ -5,6 +5,7 @@ # found in the LICENSE file. import distutils.spawn +import itertools import optparse import os import shutil @@ -194,16 +195,6 @@ return new_args -def _FixTempPathsInIncrementalMetadata(pdb_path, temp_dir): - # The .pdb records absolute paths. Fix up paths within /tmp (srcjars). - if os.path.exists(pdb_path): - # Although its a binary file, search/replace still seems to work fine. - with open(pdb_path) as fileobj: - pdb_data = fileobj.read() - with open(pdb_path, 'w') as fileobj: - fileobj.write(re.sub(r'/tmp/[^/]*', temp_dir, pdb_data)) - - def _ParsePackageAndClassNames(java_file): package_name = '' class_names = [] @@ -235,7 +226,7 @@ (java_file, expected_path_suffix)) -def _CreateInfoFile(java_files, options, srcjar_files): +def _CreateInfoFile(java_files, options, srcjar_files, javac_generated_sources): """Writes a .jar.info file. This maps fully qualified names for classes to either the java file that they @@ -245,7 +236,7 @@ .jar.info files of its transitive dependencies. """ info_data = dict() - for java_file in java_files: + for java_file in itertools.chain(java_files, javac_generated_sources): package_name, class_names = _ParsePackageAndClassNames(java_file) for class_name in class_names: fully_qualified_name = '{}.{}'.format(package_name, class_name) @@ -258,6 +249,7 @@ 'Chromium java files must only have one class: {}'.format(source)) if options.chromium_code: _CheckPathMatchesClassName(java_file, package_name, class_names[0]) + with build_utils.AtomicOutput(options.jar_path + '.info') as f: jar_info_utils.WriteJarInfoFile(f.name, info_data, srcjar_files) @@ -299,25 +291,29 @@ # sources are stale by having their .class files be missing entirely # (by not extracting them). javac_cmd = _ConvertToJMakeArgs(javac_cmd, pdb_path) - if srcjars: - _FixTempPathsInIncrementalMetadata(pdb_path, temp_dir) - srcjar_files = dict() + generated_java_dir = options.generated_dir + # Incremental means not all files will be extracted, so don't bother + # clearing out stale generated files. + if not incremental: + shutil.rmtree(generated_java_dir, True) + + srcjar_files = {} if srcjars: - java_dir = os.path.join(temp_dir, 'java') - os.makedirs(java_dir) + build_utils.MakeDirectory(generated_java_dir) + jar_srcs = [] for srcjar in options.java_srcjars: if changed_paths: - changed_paths.update(os.path.join(java_dir, f) + changed_paths.update(os.path.join(generated_java_dir, f) for f in changes.IterChangedSubpaths(srcjar)) extracted_files = build_utils.ExtractAll( - srcjar, path=java_dir, pattern='*.java') + srcjar, path=generated_java_dir, pattern='*.java') for path in extracted_files: # We want the path inside the srcjar so the viewer can have a tree # structure. srcjar_files[path] = '{}/{}'.format( - srcjar, os.path.relpath(path, java_dir)) - jar_srcs = build_utils.FindInDirectory(java_dir, '*.java') + srcjar, os.path.relpath(path, generated_java_dir)) + jar_srcs.extend(extracted_files) java_files.extend(jar_srcs) if changed_paths: # Set the mtime of all sources to 0 since we use the absence of .class @@ -325,8 +321,6 @@ for path in jar_srcs: os.utime(path, (0, 0)) - _CreateInfoFile(java_files, options, srcjar_files) - if java_files: if changed_paths: changed_java_files = [p for p in java_files if p in changed_paths] @@ -380,6 +374,18 @@ os.unlink(pdb_path) attempt_build() + # Move any Annotation Processor-generated .java files into $out/gen + # so that codesearch can find them. + javac_generated_sources = [] + for src_path in build_utils.FindInDirectory(classes_dir, '*.java'): + dst_path = os.path.join( + generated_java_dir, os.path.relpath(src_path, classes_dir)) + build_utils.MakeDirectory(os.path.dirname(dst_path)) + shutil.move(src_path, dst_path) + javac_generated_sources.append(dst_path) + + _CreateInfoFile(java_files, options, srcjar_files, javac_generated_sources) + if options.incremental and (not java_files or not incremental): # Make sure output exists. build_utils.Touch(pdb_path) @@ -408,6 +414,10 @@ default=[], help='List of srcjars to include in compilation.') parser.add_option( + '--generated-dir', + help='Subdirectory within target_gen_dir to place extracted srcjars and ' + 'annotation processor output for codesearch to find.') + parser.add_option( '--bootclasspath', action='append', default=[],
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index f7d99bd5..7e885e0 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -2464,6 +2464,7 @@ # the variables properly. # # Variables: + # main_target_name: Used when extracting srcjars for codesearch. # java_files: Optional list of Java source file paths. # srcjar_deps: Optional list of .srcjar dependencies (not file paths). # The corresponding source files they contain will be compiled too. @@ -2578,8 +2579,12 @@ rebase_path(invoker.javac_jar_path, root_build_dir) _rebased_java_srcjars = rebase_path(_java_srcjars, root_build_dir) _rebased_depfile = rebase_path(depfile, root_build_dir) + _rebased_generated_dir = rebase_path( + "$target_gen_dir/${invoker.main_target_name}/generated_java", + root_build_dir) args = [ "--depfile=$_rebased_depfile", + "--generated-dir=$_rebased_generated_dir", "--jar-path=$_rebased_javac_jar_path", "--java-srcjars=$_rebased_java_srcjars", "--java-version=1.8", @@ -3081,6 +3086,7 @@ "provider_configurations", "javac_args", ]) + main_target_name = _main_target_name build_config = _build_config java_files = _java_files if (_java_files != []) {
diff --git a/build/config/chromeos/rules.gni b/build/config/chromeos/rules.gni index 047cab3..d5dbde7 100644 --- a/build/config/chromeos/rules.gni +++ b/build/config/chromeos/rules.gni
@@ -159,7 +159,7 @@ testonly = true tast_tests = invoker.tast_tests generated_script = "$root_build_dir/bin/run_${target_name}" - runtime_deps_file = "$root_out_dir/${target_name}/.runtime_deps" + runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps" deploy_chrome = true data_deps = [ "//:chromiumos_preflight", # Builds the browser.
diff --git a/chrome/android/java/res/color/menu_item_tint.xml b/chrome/android/java/res/color/menu_item_tint.xml new file mode 100644 index 0000000..33b9103b --- /dev/null +++ b/chrome/android/java/res/color/menu_item_tint.xml
@@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2018 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:color="@color/modern_blue_600_alpha_38_opaque" android:state_enabled="false" /> + <item android:color="@android:color/white" /> +</selector>
diff --git a/chrome/android/java/res_download/layout/download_manager_section_header.xml b/chrome/android/java/res_download/layout/download_manager_section_header.xml index 038be20..a914005 100644 --- a/chrome/android/java/res_download/layout/download_manager_section_header.xml +++ b/chrome/android/java/res_download/layout/download_manager_section_header.xml
@@ -4,13 +4,28 @@ found in the LICENSE file. --> -<TextView +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingTop="@dimen/download_manager_section_title_padding_top" - android:paddingBottom="@dimen/download_manager_section_title_padding_bottom" - android:paddingStart="@dimen/list_item_default_margin" - android:gravity="start|center_vertical" - android:textAppearance="@style/BlackHint2" - android:textAlignment="viewStart" /> \ No newline at end of file + android:orientation="horizontal"> + + <TextView + android:id="@+id/title" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:paddingTop="@dimen/download_manager_section_title_padding_top" + android:paddingBottom="@dimen/download_manager_section_title_padding_bottom" + android:paddingStart="@dimen/list_item_default_margin" + android:textAppearance="@style/BlackHint2" + android:textAlignment="viewStart"/> + + <include layout="@layout/list_menu_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" /> + +</LinearLayout>
diff --git a/chrome/android/java/res_download/menu/download_manager_menu.xml b/chrome/android/java/res_download/menu/download_manager_menu.xml index 38ad545..a610a6f7 100644 --- a/chrome/android/java/res_download/menu/download_manager_menu.xml +++ b/chrome/android/java/res_download/menu/download_manager_menu.xml
@@ -59,11 +59,13 @@ android:id="@+id/selection_mode_share_menu_id" android:icon="@drawable/ic_share_white_24dp" android:title="@string/share" - app:showAsAction="ifRoom" /> + app:showAsAction="ifRoom" + app:iconTint="@color/menu_item_tint" /> <item android:id="@+id/selection_mode_delete_menu_id" android:icon="@drawable/ic_delete_white_24dp" android:title="@string/delete" - app:showAsAction="ifRoom" /> + app:showAsAction="ifRoom" + app:iconTint="@color/menu_item_tint" /> </group> </menu>
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 80774529..c7ebb10 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -247,8 +247,10 @@ "OfflinePagesDescriptivePendingStatus"; public static final String OFFLINE_PAGES_LIVE_PAGE_SHARING = "OfflinePagesLivePageSharing"; public static final String OFFLINE_PAGES_PREFETCHING = "OfflinePagesPrefetching"; - public static final String OMNIBOX_HIDE_SCHEME_DOMAIN_IN_STEADY_STATE = - "OmniboxUIExperimentHideSteadyStateUrlSchemeAndSubdomains"; + public static final String OMNIBOX_HIDE_SCHEME_IN_STEADY_STATE = + "OmniboxUIExperimentHideSteadyStateUrlScheme"; + public static final String OMNIBOX_HIDE_TRIVIAL_SUBDOMAINS_IN_STEADY_STATE = + "OmniboxUIExperimentHideSteadyStateUrlTrivialSubdomains"; public static final String OMNIBOX_SPARE_RENDERER = "OmniboxSpareRenderer"; public static final String OMNIBOX_VOICE_SEARCH_ALWAYS_VISIBLE = "OmniboxVoiceSearchAlwaysVisible";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterChipsProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterChipsProvider.java index bb315bbe..18a12a24 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterChipsProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterChipsProvider.java
@@ -126,8 +126,8 @@ if (chip.enabled) visibleChips.add(chip); } - // Remove the none chip if no other chip is visible. - if (visibleChips.size() == 1) { + // If there is only one chip type or only NONE chips, remove the entire row of chips. + if (visibleChips.size() <= 2) { assert visibleChips.get(0).id == FilterType.NONE; visibleChips.clear(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java index f9a374a6..f73fe33 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
@@ -6,6 +6,7 @@ import android.content.Intent; import android.os.Handler; +import android.support.annotation.Nullable; import android.support.v4.util.Pair; import org.chromium.base.CollectionUtil; @@ -150,10 +151,11 @@ ListProperties.CALLBACK_RESUME, item -> mProvider.resumeDownload(item, true)); mModel.getProperties().set(ListProperties.CALLBACK_CANCEL, mProvider::cancelDownload); mModel.getProperties().set(ListProperties.CALLBACK_SHARE, this ::onShareItem); + mModel.getProperties().set(ListProperties.CALLBACK_SHARE_ALL, this ::onShareItems); mModel.getProperties().set(ListProperties.CALLBACK_REMOVE, this ::onDeleteItem); + mModel.getProperties().set(ListProperties.CALLBACK_REMOVE_ALL, this ::onDeleteItems); mModel.getProperties().set(ListProperties.PROVIDER_VISUALS, this ::getVisuals); - mModel.getProperties().set( - ListProperties.CALLBACK_SELECTION, selectionDelegate::toggleSelectionForItem); + mModel.getProperties().set(ListProperties.CALLBACK_SELECTION, this ::onSelection); } /** Tears down this mediator. */ @@ -227,6 +229,14 @@ return mTypeFilter; } + private void onSelection(@Nullable ListItem item) { + if (item == null) { + mSelectionDelegate.setSelectionModeEnabledForZeroItems(true); + } else { + mSelectionDelegate.toggleSelectionForItem(item); + } + } + private void onDeleteItem(OfflineItem item) { onDeleteItems(CollectionUtil.newArrayList(item)); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMutator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMutator.java index b032eea..dca0e42 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMutator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMutator.java
@@ -146,6 +146,7 @@ if (!mHideSectionHeaders && !mHideAllHeaders) { SectionHeaderListItem sectionHeaderItem = new SectionHeaderListItem(filter, date.getTime()); + sectionHeaderItem.items = new ArrayList<>(section.items.values()); sectionHeaderItem.isFirstSectionOfDay = sectionIndex == 0; listItems.add(sectionHeaderItem); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItem.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItem.java index 40015a1d..e79c150 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItem.java
@@ -11,6 +11,7 @@ import java.util.Calendar; import java.util.Date; +import java.util.List; /** An abstract class that represents a variety of possible list items to show in downloads home. */ public abstract class ListItem { @@ -74,6 +75,7 @@ public static class SectionHeaderListItem extends DateListItem { public final int filter; public boolean isFirstSectionOfDay; + public List<OfflineItem> items; /** * Creates a {@link SectionHeaderListItem} instance for a given {@code filter} and
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListProperties.java index c7de803..5aefcb4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListProperties.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListProperties.java
@@ -12,6 +12,8 @@ import org.chromium.components.offline_items_collection.OfflineItemVisuals; import org.chromium.components.offline_items_collection.VisualsCallback; +import java.util.List; + /** * The properties required to build a {@link ListItem} which contain two types of properties for the * download manager: (1) A set of properties that act directly on the list view itself. (2) A set of @@ -54,10 +56,18 @@ WritableObjectPropertyKey<Callback<OfflineItem>> CALLBACK_SHARE = new WritableObjectPropertyKey<>(); + /** The callback for when a UI action should share all selected {@link OfflineItem}s. */ + WritableObjectPropertyKey < Callback < List<OfflineItem>>> CALLBACK_SHARE_ALL = + new WritableObjectPropertyKey<>(); + /** The callback for when a UI action should remove a {@link OfflineItem}. */ WritableObjectPropertyKey<Callback<OfflineItem>> CALLBACK_REMOVE = new WritableObjectPropertyKey<>(); + /** The callback for when a UI action should remove all selected {@link OfflineItem}s. */ + WritableObjectPropertyKey < Callback < List<OfflineItem>>> CALLBACK_REMOVE_ALL = + new WritableObjectPropertyKey<>(); + /** The provider to retrieve expensive assets for a {@link OfflineItem}. */ WritableObjectPropertyKey<VisualsProvider> PROVIDER_VISUALS = new WritableObjectPropertyKey<>(); @@ -69,6 +79,7 @@ WritableBooleanPropertyKey SELECTION_MODE_ACTIVE = new WritableBooleanPropertyKey(); PropertyKey[] ALL_KEYS = new PropertyKey[] {ENABLE_ITEM_ANIMATIONS, CALLBACK_OPEN, - CALLBACK_PAUSE, CALLBACK_RESUME, CALLBACK_CANCEL, CALLBACK_SHARE, CALLBACK_REMOVE, - PROVIDER_VISUALS, CALLBACK_SELECTION, SELECTION_MODE_ACTIVE}; -} \ No newline at end of file + CALLBACK_PAUSE, CALLBACK_RESUME, CALLBACK_CANCEL, CALLBACK_SHARE, CALLBACK_SHARE_ALL, + CALLBACK_REMOVE, CALLBACK_REMOVE_ALL, PROVIDER_VISUALS, CALLBACK_SELECTION, + SELECTION_MODE_ACTIVE}; +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SectionTitleViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SectionTitleViewHolder.java index ab664e2..2c90e23 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SectionTitleViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SectionTitleViewHolder.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.download.home.list.holder; +import android.content.Context; import android.content.res.Resources; import android.view.LayoutInflater; import android.view.View; @@ -11,15 +12,28 @@ import android.widget.TextView; import org.chromium.chrome.browser.download.home.list.ListItem; +import org.chromium.chrome.browser.download.home.list.ListProperties; import org.chromium.chrome.browser.download.home.list.ListUtils; import org.chromium.chrome.browser.modelutil.PropertyModel; +import org.chromium.chrome.browser.widget.ListMenuButton; import org.chromium.chrome.download.R; import org.chromium.components.offline_items_collection.OfflineItemFilter; /** * A {@link ViewHolder} specifically meant to display a section header. */ -public class SectionTitleViewHolder extends ListItemViewHolder { +public class SectionTitleViewHolder extends ListItemViewHolder implements ListMenuButton.Delegate { + private final TextView mTitle; + private final ListMenuButton mMore; + + private Runnable mShareCallback; + private Runnable mDeleteCallback; + private Runnable mShareAllCallback; + private Runnable mDeleteAllCallback; + private Runnable mSelectCallback; + + private boolean mListHasMultipleItems; + /** Create a new {@link SectionTitleViewHolder} instance. */ public static SectionTitleViewHolder create(ViewGroup parent) { View view = LayoutInflater.from(parent.getContext()) @@ -29,13 +43,16 @@ private SectionTitleViewHolder(View view) { super(view); + mTitle = (TextView) view.findViewById(R.id.title); + mMore = (ListMenuButton) view.findViewById(R.id.more); + if (mMore != null) mMore.setDelegate(this); } // ListItemViewHolder implementation. @Override public void bind(PropertyModel properties, ListItem item) { ListItem.SectionHeaderListItem sectionItem = (ListItem.SectionHeaderListItem) item; - ((TextView) itemView).setText(ListUtils.getTextForSection(sectionItem.filter)); + mTitle.setText(ListUtils.getTextForSection(sectionItem.filter)); boolean isPhoto = sectionItem.filter == OfflineItemFilter.FILTER_IMAGE; Resources resources = itemView.getContext().getResources(); @@ -52,7 +69,62 @@ R.dimen.download_manager_section_title_padding_top_condensed); } - itemView.setPadding( - itemView.getPaddingLeft(), paddingTop, itemView.getPaddingRight(), paddingBottom); + mTitle.setPadding( + mTitle.getPaddingLeft(), paddingTop, mTitle.getPaddingRight(), paddingBottom); + + if (mMore != null) mMore.setVisibility(isPhoto ? View.VISIBLE : View.GONE); + + mListHasMultipleItems = sectionItem.items.size() > 1; + + if (isPhoto && mMore != null) { + assert sectionItem.items.size() > 0; + mShareCallback = () + -> properties.get(ListProperties.CALLBACK_SHARE) + .onResult(sectionItem.items.get(0)); + mDeleteCallback = () + -> properties.get(ListProperties.CALLBACK_REMOVE) + .onResult(sectionItem.items.get(0)); + + mShareAllCallback = () + -> properties.get(ListProperties.CALLBACK_SHARE_ALL) + .onResult(sectionItem.items); + mDeleteAllCallback = () + -> properties.get(ListProperties.CALLBACK_REMOVE_ALL) + .onResult(sectionItem.items); + mSelectCallback = + () -> properties.get(ListProperties.CALLBACK_SELECTION).onResult(null); + + mMore.setClickable(!properties.get(ListProperties.SELECTION_MODE_ACTIVE)); + } + } + + @Override + public ListMenuButton.Item[] getItems() { + Context context = itemView.getContext(); + if (mListHasMultipleItems) { + return new ListMenuButton.Item[] { + new ListMenuButton.Item(context, R.string.select, true), + new ListMenuButton.Item(context, R.string.share_group, true), + new ListMenuButton.Item(context, R.string.delete_group, true)}; + } else { + return new ListMenuButton.Item[] { + new ListMenuButton.Item(context, R.string.share, true), + new ListMenuButton.Item(context, R.string.delete, true)}; + } + } + + @Override + public void onItemSelected(ListMenuButton.Item item) { + if (item.getTextId() == R.string.select) { + mSelectCallback.run(); + } else if (item.getTextId() == R.string.share) { + mShareCallback.run(); + } else if (item.getTextId() == R.string.delete) { + mDeleteCallback.run(); + } else if (item.getTextId() == R.string.share_group) { + mShareAllCallback.run(); + } else if (item.getTextId() == R.string.delete_group) { + mDeleteAllCallback.run(); + } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetector.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetector.java index e64097ed..e7b2519 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetector.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/ConnectivityDetector.java
@@ -115,6 +115,7 @@ private static final int CONNECTIVITY_CHECK_MAX_DELAY_MS = 2 * 60 * 1000; private static boolean sSkipSystemCheckForTesting; + private static boolean sSkipHttpProbeForTesting; private static String sDefaultProbeUrl = DEFAULT_PROBE_URL; private static String sFallbackProbeUrl = FALLBACK_PROBE_URL; private static String sProbeMethod = PROBE_METHOD; @@ -174,6 +175,11 @@ return; } + if (sSkipHttpProbeForTesting) { + updateConnectionState(ConnectionState.VALIDATED); + return; + } + // Do manual check via sending HTTP probes to server. mConnectivityCheckDelayMs = 0; mConnectivityCheckStartTimeMs = SystemClock.elapsedRealtime(); @@ -412,6 +418,11 @@ } @VisibleForTesting + static void skipHttpProbeForTesting() { + sSkipHttpProbeForTesting = true; + } + + @VisibleForTesting static void overrideDefaultProbeUrlForTesting(String url) { sDefaultProbeUrl = url; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java index e4b58482..2b6419e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
@@ -153,11 +153,6 @@ protected void onPostExecute(Void result) { String renamedAccount = getNewSignedInAccountName(); if (renamedAccount == null) { - // SigninManager.signOut() uses the same code path as a user-triggered - // signout, which can be prohibited in some cases (e.g. child accounts). - // Here we have to sign out though to ensure account consistency, - // so override the flag. - mSigninManager.prohibitSignout(false); mSigninManager.signOut(SignoutReason.ACCOUNT_REMOVED_FROM_DEVICE); } else { validateAccountSettings(true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java index d32619b0..1f8cc50 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
@@ -568,10 +568,6 @@ nativeClearLastSignedInUser(mNativeSigninManagerAndroid); } - public void prohibitSignout(boolean prohibitSignout) { - nativeProhibitSignout(mNativeSigninManagerAndroid, prohibitSignout); - } - /** * Aborts the current sign in. * @@ -751,6 +747,4 @@ native void nativeLogInSignedInUser(long nativeSigninManagerAndroid); @VisibleForTesting native boolean nativeIsSignedInOnNative(long nativeSigninManagerAndroid); - @VisibleForTesting - native void nativeProhibitSignout(long nativeSigninManagerAndroid, boolean prohibitSignout); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java index df7ac3e..935ea8c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java
@@ -185,12 +185,9 @@ return buildUrlBarData(url, searchTerms); } - if (ChromeFeatureList.isEnabled( - ChromeFeatureList.OMNIBOX_HIDE_SCHEME_DOMAIN_IN_STEADY_STATE)) { - String urlForDisplay = getUrlForDisplay(); - if (!urlForDisplay.equals(formattedUrl)) { - return buildUrlBarData(url, urlForDisplay, formattedUrl); - } + String urlForDisplay = getUrlForDisplay(); + if (!urlForDisplay.equals(formattedUrl)) { + return buildUrlBarData(url, urlForDisplay, formattedUrl); } return buildUrlBarData(url, formattedUrl); @@ -402,7 +399,9 @@ list = AppCompatResources.getColorStateList(mContext, R.color.light_mode_tint); } else if (!hasTab() || isUsingBrandColor() || ChromeFeatureList.isEnabled( - ChromeFeatureList.OMNIBOX_HIDE_SCHEME_DOMAIN_IN_STEADY_STATE)) { + ChromeFeatureList.OMNIBOX_HIDE_SCHEME_IN_STEADY_STATE) + || ChromeFeatureList.isEnabled( + ChromeFeatureList.OMNIBOX_HIDE_TRIVIAL_SUBDOMAINS_IN_STEADY_STATE)) { // For theme colors which are not dark and are also not // light enough to warrant an opaque URL bar, use dark // icons.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/NumberRollView.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/NumberRollView.java index a7ba9fb..bb579d0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/NumberRollView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/NumberRollView.java
@@ -28,6 +28,7 @@ private float mNumber; private Animator mLastRollAnimator; private int mStringId; + private int mStringIdForZero; /** * A Property wrapper around the <code>number</code> functionality handled by the @@ -92,6 +93,14 @@ } /** + * @param stringIdForZero The id of the string to use for the description when the number is + * zero. + */ + public void setStringForZero(int stringIdForZero) { + mStringIdForZero = stringIdForZero; + } + + /** * Gets the current number roll position. */ private float getNumberRoll() { @@ -109,7 +118,9 @@ NumberFormat numberFormatter = NumberFormat.getIntegerInstance(); String newString; if (mStringId != 0) { - newString = getResources().getQuantityString(mStringId, upNumber, upNumber); + newString = upNumber == 0 && mStringIdForZero != 0 + ? getResources().getString(mStringIdForZero) + : getResources().getQuantityString(mStringId, upNumber, upNumber); } else { newString = numberFormatter.format(upNumber); } @@ -118,7 +129,9 @@ } if (mStringId != 0) { - newString = getResources().getQuantityString(mStringId, downNumber, downNumber); + newString = downNumber == 0 && mStringIdForZero != 0 + ? getResources().getString(mStringIdForZero) + : getResources().getQuantityString(mStringId, downNumber, downNumber); } else { newString = numberFormatter.format(downNumber); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java index 0e9631d..4fd14ee 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
@@ -312,6 +312,7 @@ LayoutInflater.from(getContext()).inflate(R.layout.number_roll_view, this); mNumberRollView = (NumberRollView) findViewById(R.id.selection_mode_number); mNumberRollView.setString(R.plurals.selected_items); + mNumberRollView.setStringForZero(R.string.select_items); } @Override @@ -598,6 +599,7 @@ protected void showSelectionView(List<E> selectedItems, boolean wasSelectionEnabled) { getMenu().setGroupVisible(mNormalGroupResId, false); getMenu().setGroupVisible(mSelectedGroupResId, true); + getMenu().setGroupEnabled(mSelectedGroupResId, !selectedItems.isEmpty()); if (mHasSearchView) mSearchView.setVisibility(View.GONE); setNavigationButton(NAVIGATION_BUTTON_SELECTION_BACK);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionDelegate.java index 267cd9d..8fd5e23 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionDelegate.java
@@ -19,6 +19,10 @@ // True if the SelectionDelegate should only support a single item being selected at a time. private boolean mIsSingleSelection; + // If true, we can enter the selection mode even though zero items are currently selected. + // When the number of items drops to zero again, this will automatically turn off. + private boolean mEnableSelectionForZeroItems; + /** * Observer interface to be notified of selection changes. * @param <E> The type of the selectable items this delegate interacts with. @@ -43,6 +47,15 @@ } /** + * Enables selection mode even though there are zero items selected. + * @param enable True, for entering selection mode. False, to turn-off this mode. + */ + public void setSelectionModeEnabledForZeroItems(boolean enable) { + mEnableSelectionForZeroItems = enable; + notifyObservers(); + } + + /** * Toggles the selected state for the given item. * @param item The item to toggle. * @return Whether the item is selected. @@ -55,6 +68,8 @@ mSelectedItems.add(item); } + if (mSelectedItems.isEmpty()) mEnableSelectionForZeroItems = false; + notifyObservers(); return isItemSelected(item); @@ -82,13 +97,14 @@ * @return Whether any items are selected. */ public boolean isSelectionEnabled() { - return !mSelectedItems.isEmpty(); + return !mSelectedItems.isEmpty() || mEnableSelectionForZeroItems; } /** * Clears all selected items. */ public void clearSelection() { + mEnableSelectionForZeroItems = false; mSelectedItems.clear(); notifyObservers(); }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index c266b7a..ee8a536 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -149,6 +149,9 @@ <message name="IDS_DELETE" desc="Label for a delete button. Used in multiple contexts. [CHAR-LIMIT=20]"> Delete </message> + <message name="IDS_DELETE_GROUP" desc="Label for button that deletes a group of items. [CHAR-LIMIT=20]"> + Delete group + </message> <message name="IDS_REMOVE" desc="Label for a button to remove an item (e.g. a bookmark) from a list. [CHAR-LIMIT=20]"> Remove </message> @@ -215,6 +218,9 @@ <message name="IDS_SHARE" desc="Content description for a button to share item(s). [CHAR-LIMIT=20]"> Share </message> + <message name="IDS_SHARE_GROUP" desc="Content description for a button to share a group item(s). [CHAR-LIMIT=20]"> + Share group + </message> <message name="IDS_SEARCH" desc="The label for a search button."> Search </message> @@ -3276,7 +3282,9 @@ =1 {1 selected} other {# selected}} </message> - + <message name="IDS_SELECT_ITEMS" desc="Label shown on toolbar asking user to select items from the list."> + Select items + </message> <message name="IDS_MEDIA_NOTIFICATION_LINK_TEXT" desc="Url of the current tab. The notification will display this text for the user to identify the tab to return to."> Touch to return to <ph name="URL_OF_THE_CURRENT_TAB">%1$s<ex>https://apprtc.appspot.com</ex></ph> </message>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java index ba4c907..d33cded 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java
@@ -68,6 +68,7 @@ @Before public void setUp() throws Exception { ConnectivityDetector.skipSystemCheckForTesting(); + ConnectivityDetector.skipHttpProbeForTesting(); mActivityTestRule.startMainActivityOnBlankPage(); ThreadUtils.runOnUiThreadBlocking(() -> { if (!NetworkChangeNotifier.isInitialized()) { @@ -75,6 +76,9 @@ } NetworkChangeNotifier.forceConnectivityState(true); OfflineIndicatorController.initialize(); + OfflineIndicatorController.getInstance() + .getConnectivityDetectorForTesting() + .updateConnectionState(ConnectivityDetector.ConnectionState.VALIDATED); }); } @@ -245,7 +249,7 @@ public void testDoNotShowOfflineIndicatorOnPageLoadingWhenOffline() throws Exception { EmbeddedTestServer testServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); - String testUrl = testServer.getURL(TEST_PAGE); + String testUrl = testServer.getURL("/slow?1"); // Load a page without waiting it to finish. loadPageWithoutWaiting(testUrl, null); @@ -303,6 +307,8 @@ private void waitForPageLoaded(String pageUrl) throws Exception { Tab tab = mActivityTestRule.getActivity().getActivityTab(); ChromeTabUtils.waitForTabPageLoaded(tab, pageUrl); + ChromeTabUtils.waitForInteractable(tab); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } private void savePage(String url) throws InterruptedException {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java index 8185022..6625caa 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java
@@ -20,7 +20,6 @@ import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.UrlConstants; @@ -29,8 +28,6 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ChromeTabUtils; -import org.chromium.chrome.test.util.browser.Features.DisableFeatures; -import org.chromium.chrome.test.util.browser.Features.EnableFeatures; /** * Tests for ToolbarModel. @@ -68,8 +65,7 @@ @Test @SmallTest - @DisableFeatures(ChromeFeatureList.OMNIBOX_HIDE_SCHEME_DOMAIN_IN_STEADY_STATE) - public void testDisplayAndEditText_DisabledExperiment() throws Exception { + public void testDisplayAndEditText() throws Exception { ThreadUtils.runOnUiThreadBlocking(() -> { TestToolbarModel model = new TestToolbarModel(); model.mUrl = UrlConstants.NTP_URL; @@ -81,25 +77,9 @@ assertDisplayAndEditText(model, "chrome://about", "chrome://about"); model.mUrl = "https://www.foo.com"; - model.mDisplayUrl = "foo.com"; + model.mDisplayUrl = "https://foo.com"; model.mFullUrl = "https://foo.com"; assertDisplayAndEditText(model, "https://foo.com", "https://foo.com"); - }); - } - - @Test - @SmallTest - @EnableFeatures(ChromeFeatureList.OMNIBOX_HIDE_SCHEME_DOMAIN_IN_STEADY_STATE) - public void testDisplayAndEditText_EnabledExperiment() throws Exception { - ThreadUtils.runOnUiThreadBlocking(() -> { - TestToolbarModel model = new TestToolbarModel(); - model.mUrl = UrlConstants.NTP_URL; - assertDisplayAndEditText(model, "", null); - - model.mUrl = "chrome://about"; - model.mDisplayUrl = "chrome://about"; - model.mFullUrl = "chrome://about"; - assertDisplayAndEditText(model, "chrome://about", "chrome://about"); model.mUrl = "https://www.foo.com"; model.mDisplayUrl = "foo.com";
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 296c62f..25edda30 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -142,14 +142,17 @@ Try again </message> <message name="IDS_MULTIDEVICE_SETUP_PASSWORD_PAGE_HEADER" desc="Header for the first page in the multi-device setup flow; the page displays a field in which the user must enter their password to continue."> - Set up Better Together - </message> - <message name="IDS_MULTIDEVICE_SETUP_PASSWORD_PAGE_ENTER_PASSWORD_LABEL" desc="Message displayed in the multi-device setup flow which asks the user to enter their password."> Enter your password </message> + <message name="IDS_MULTIDEVICE_SETUP_PASSWORD_PAGE_ENTER_PASSWORD_LABEL" desc="Default text in the field for user to enter their password."> + Password + </message> <message name="IDS_MULTIDEVICE_SETUP_PASSWORD_PAGE_WRONG_PASSWORD_LABEL" desc="Message displayed in the multi-device setup flow when the user has entered an incorrect password."> Wrong password </message> + <message name="IDS_MULTIDEVICE_SETUP_BACK_LABEL" desc="Label for button to navigate back in MultiDevice setup workflow."> + Back + </message> <message name="IDS_MULTIDEVICE_SETUP_SETUP_FAILED_PAGE_HEADER" desc="Header for failed setup page."> Better Together setup couldn't complete </message> @@ -160,13 +163,13 @@ All set! </message> <message name="IDS_MULTIDEVICE_SETUP_SETUP_SUCCEEDED_PAGE_MESSAGE" desc="Message for successful setup page."> - Go to <ph name="LINK_BEGIN"><a id="settings-link"></ph>Settings<ph name="LINK_END"></a></ph> to see your options for Better Together + Go to <ph name="LINK_BEGIN"><a id="settings-link"></ph>Settings<ph name="LINK_END"></a></ph> to see options for your connected phone </message> <message name="IDS_MULTIDEVICE_SETUP_START_SETUP_PAGE_HEADER" desc="Header for welcome page."> - Better Together + Connect to your phone </message> <message name="IDS_MULTIDEVICE_SETUP_START_SETUP_PAGE_MESSAGE" desc="Summary to tell user that they can share their Android's capabilities with their Chromebook; includes details on specific features that can be used and a link to an information page"> - Connect your Android phone and Chromebook to text from your computer, share your internet connection, and unlock your Chromebook with your phone.<ph name="FOOTNOTE_POINTER">$1<ex>*</ex></ph> <ph name="LINK_BEGIN"><a href="$2<ex>https://support.google.com/chromebook/?p=multidevice</ex>"></ph>Learn more<ph name="LINK_END"></a></ph> + Your Chromebook and Android phone work better together. Connect them so you can text from your computer, share your internet connection, and unlock your Chromebook with your phone.<ph name="FOOTNOTE_POINTER">$1<ex>*</ex></ph> <ph name="LINK_BEGIN"><a href="$2<ex>https://support.google.com/chromebook/?p=multidevice</ex>"></ph>Learn more<ph name="LINK_END"></a></ph> </message> <message name="IDS_MULTIDEVICE_SETUP_START_SETUP_PAGE_FOOTNOTE" desc="Footnote for multi-device feature setup page, which indicates that the exact set of features available to users differs according to the device model used."> <ph name="FOOTNOTE_POINTER">$1<ex>*</ex></ph>Features vary by device @@ -177,8 +180,8 @@ <message name="IDS_MULTIDEVICE_SETUP_START_SETUP_PAGE_MULTIPLE_DEVICE_HEADER" desc="Label appearing over a list of Android phones which this Chromebook can connect to."> Select a device </message> - <message name="IDS_MULTIDEVICE_SETUP_START_SETUP_PAGE_FEATURE_LIST_HEADER" desc="Header to introduce a list of things Better Together can do."> - Turning on Better Together means that it can: + <message name="IDS_MULTIDEVICE_SETUP_START_SETUP_PAGE_FEATURE_LIST_HEADER" desc="Header to introduce a list of the features that the user is agreeing to in the multi-device setup."> + When you connect your devices, you agree that your Chromebook can: </message> <message name="IDS_MULTIDEVICE_SETUP_START_SETUP_PAGE_AWM_DESCRIPTION" desc="Description of a feature that shows text messages received by the user's phone as notification on their Chromebook and a link to an information page."> Send you notifications and default to remembering this computer for Messages. <ph name="LINK_BEGIN"><a href="$1<ex>https://support.google.com/chromebook/?p=messages</ex>"></ph>Learn more<ph name="LINK_END"></a></ph>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index cab8bd1..078f4f2a 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -4313,11 +4313,8 @@ </message> </if> - <message name="IDS_PASSWORD_MANAGER_ACCOUNT_CHOOSER_TITLE_MANY_ACCOUNTS" desc="The title of the account chooser dialog/infobar for more than one account."> - Choose your account saved with <ph name="PASSWORD_MANAGER_BRAND">$1<ex>Google Chrome</ex></ph> to sign in - </message> - <message name="IDS_PASSWORD_MANAGER_ACCOUNT_CHOOSER_TITLE_ONE_ACCOUNT" desc="The title of the account chooser dialog/infobar for one account."> - Sign in with your account saved with <ph name="PASSWORD_MANAGER_BRAND">$1<ex>Google Chrome</ex></ph> + <message name="IDS_PASSWORD_MANAGER_ACCOUNT_CHOOSER_TITLE" desc="The title of the account chooser dialog."> + Sign in as </message> <message name="IDS_PASSWORD_MANAGER_CONFIRM_SAVED_TITLE" desc="The title text used in the passwords bubble when the user has saved a password."> Password saved @@ -4332,7 +4329,7 @@ Save password? </message> <message name="IDS_SAVE_ACCOUNT" desc="The title of the save password bubble when a federated credential can be saved."> - Do you want <ph name="PASSWORD_MANAGER_BRAND">$1<ex>Google Chrome</ex></ph> to save your account for this site? + Save username? </message> <message name="IDS_UPDATE_PASSWORD" desc="The title of the save password bubble when a password can be updated."> Update password? @@ -7963,9 +7960,6 @@ <message name="IDS_AUTO_SIGNIN_FIRST_RUN_TITLE_LOCAL_DEVICE" desc="The title of the dialog during the autosign-in first run experience for the Chrome signed out users."> Sign in easily </message> - <message name="IDS_AUTO_SIGNIN_FIRST_RUN_SMART_LOCK_TEXT" desc="The text of the dialog during the autosign-in first run experience for the Chrome syncing users."> - <ph name="PASSWORD_MANAGER_BRAND">$1<ex>Google Smart Lock</ex></ph> automatically signs you in to eligible sites and apps with passwords you saved. - </message> <message name="IDS_AUTO_SIGNIN_FIRST_RUN_TEXT" desc="The text of the dialog during the autosign-in first run experience for the Chrome signed out users."> <ph name="PASSWORD_MANAGER_BRAND">$1<ex>Google Chrome</ex></ph> automatically signs you in to eligible sites with passwords you saved. </message>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 742c10d..a1cdf36a 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -4237,10 +4237,10 @@ Connected devices </message> <message name="IDS_SETTINGS_MULTIDEVICE_SETUP_ITEM_HEADING" desc="Heading for settings item that allows the user to connect their phone to their Chromebook."> - Better Together + Android phone </message> - <message name="IDS_SETTINGS_MULTIDEVICE_SETUP_SUMMARY" desc="Description of the idea that the user can get a better experience on their Chromebook by connecting it to their phone."> - Your Chromebook works even better with your phone. <ph name="LINK_BEGIN"><a target="_blank" href="$1<ex>https://google.com/</ex>"></ph>Learn more<ph name="LINK_END"></a></ph> + <message name="IDS_SETTINGS_MULTIDEVICE_SETUP_SUMMARY" desc="Tells the user to connect their Chromebook to their phone."> + Connect your Chromebook with your phone. <ph name="LINK_BEGIN"><a target="_blank" href="$1<ex>https://google.com/</ex>"></ph>Learn more<ph name="LINK_END"></a></ph> </message> <message name="IDS_SETTINGS_MULTIDEVICE_NO_ELIGIBLE_HOSTS" desc="Tells the user that there is no phone with their account on it that can connect to their Chromebook."> No eligible devices. <ph name="LINK_BEGIN"><a target="_blank" href="$1<ex>https://google.com/</ex>"></ph>Learn more<ph name="LINK_END"></a></ph> @@ -4255,10 +4255,10 @@ Verify </message> <message name="IDS_SETTINGS_MULTIDEVICE_ENABLED" desc="Text to tell user multidevice features are turned on"> - Better Together is on + Enabled </message> <message name="IDS_SETTINGS_MULTIDEVICE_DISABLED" desc="Text to tell user multidevice features are turned off"> - Better Together is off + Disabled </message> <message name="IDS_SETTINGS_MULTIDEVICE_SMART_LOCK_SUMMARY" desc="Description of for the 'Smart Lock' setting. This feature automatically unlocks the user's Chromebook if their phone is nearby and unlocked."> Unlock your Chromebook with your phone. <ph name="LINK_BEGIN"><a target="_blank" href="$1<ex>https://google.com/</ex>"></ph>Learn more<ph name="LINK_END"></a></ph> @@ -4266,23 +4266,23 @@ <message name="IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING" desc="Name of a feature. This feature automatically offers the user to tether to their phone if their Chromebook is offline and their phone supports tethering."> Instant Tethering </message> + <message name="IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING_SUMMARY" desc="Description of for the 'Instant Tethering' setting. This feature automatically offers the user to tether to their phone if their Chromebook is offline and their phone supports tethering."> + Connect to the internet through your phone + </message> <message name="IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES" desc="Name of a feature. This feature lets the user read and reply to text messages from their Chromebook. New text messages will appear as notifications."> Messages </message> <message name="IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES_SUMMARY" desc="Description of for the 'Android Messages' setting. This feature lets the user read and reply to text messages from their Chromebook. New text messages will appear as notifications."> Send and receive text messages from your Chromebook. <ph name="LINK_BEGIN"><a target="_blank" href="$1<ex>https://google.com/</ex>"></ph>Learn more<ph name="LINK_END"></a></ph> </message> - <message name="IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE" desc="Header for a clickable menu item that makes the Chromebook forget the user's phone. This means they will no longer have access to multidevice features."> - Forget this device + <message name="IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE" desc="Header to tell the user an action will make their Chromebook forget their phone. This means they will no longer have access to multidevice features."> + Forget phone </message> <message name="IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE_EXPLANATION" desc="Explanation on a clickable menu item that makes the Chromebook forget the user's phone. It tells the user that the menu item will cause their phone to stop acting as a partner for their Chromebook for multidevice features."> - Remove from Better Together - </message> - <message name="IDS_SETTINGS_MULTIDEVICE_FORGET_DEVICE_DIALOG_HEADING" desc="Heading for a dialog that lets the user choose if their Chromebook should forget their phone. This means they will no longer have access to multidevice features."> - Forget device + Disconnect your phone from your Chromebook </message> <message name="IDS_SETTINGS_MULTIDEVICE_FORGET_DEVICE_DIALOG_MESSAGE" desc="Text of a dialog that lets the user choose if their Chromebook should forget their phone. This means they will no longer have access to multidevice features."> - Remove your phone and disable Better Together + Disconnect your phone from your Chromebook. They will no longer connect automatically. </message> </if>
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_avatar.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_avatar.png deleted file mode 100644 index 1626536f..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_avatar.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_bottom.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_bottom.png deleted file mode 100644 index 6e8e384..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_bottom.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_bottom_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_bottom_left.png deleted file mode 100644 index e2ce4e4..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_bottom_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_bottom_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_bottom_right.png deleted file mode 100644 index b048fb6..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_bottom_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_center.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_center.png deleted file mode 100644 index 1c73ed20..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_center.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_bottom.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_bottom.png deleted file mode 100644 index 4f4322c..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_bottom.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_bottom_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_bottom_left.png deleted file mode 100644 index 25b1522..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_bottom_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_bottom_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_bottom_right.png deleted file mode 100644 index baeb7d99..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_bottom_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_center.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_center.png deleted file mode 100644 index f1e5486..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_center.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_left.png deleted file mode 100644 index 55f859a..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_right.png deleted file mode 100644 index 8baf2ea..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_top.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_top.png deleted file mode 100644 index feb1f67..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_top.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_top_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_top_left.png deleted file mode 100644 index e85f90ec..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_top_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_top_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_top_right.png deleted file mode 100644 index 3379bb7c..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_hover_top_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_left.png deleted file mode 100644 index be48aa2..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_bottom.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_bottom.png deleted file mode 100644 index ce126e3..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_bottom.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_bottom_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_bottom_left.png deleted file mode 100644 index eda0cd7..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_bottom_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_bottom_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_bottom_right.png deleted file mode 100644 index aa93eb3..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_bottom_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_center.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_center.png deleted file mode 100644 index 05bfe96..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_center.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_left.png deleted file mode 100644 index c7d5730..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_right.png deleted file mode 100644 index 0b2bbc5..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_top.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_top.png deleted file mode 100644 index b54c05b7..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_top.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_top_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_top_left.png deleted file mode 100644 index 39a5491..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_top_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_top_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_top_right.png deleted file mode 100644 index 1366a76..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_pressed_top_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_right.png deleted file mode 100644 index 0d25707a..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_top.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_top.png deleted file mode 100644 index 616055c5..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_top.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_top_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_top_left.png deleted file mode 100644 index a43ee18..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_top_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_top_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_top_right.png deleted file mode 100644 index c0a6e37..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/themed/sign_in_button_top_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_avatar.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_avatar.png deleted file mode 100644 index ea0104a..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_avatar.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_bottom.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_bottom.png deleted file mode 100644 index ac2c17d..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_bottom.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_bottom_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_bottom_left.png deleted file mode 100644 index e4eb6396..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_bottom_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_bottom_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_bottom_right.png deleted file mode 100644 index 15f1fdbf..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_bottom_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_center.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_center.png deleted file mode 100644 index cf69acd..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_center.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_bottom.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_bottom.png deleted file mode 100644 index b6a7b89..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_bottom.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_bottom_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_bottom_left.png deleted file mode 100644 index ed60122f..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_bottom_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_bottom_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_bottom_right.png deleted file mode 100644 index 74044de..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_bottom_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_center.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_center.png deleted file mode 100644 index 52857c7..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_center.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_left.png deleted file mode 100644 index 5773833..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_right.png deleted file mode 100644 index 4b10e066..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_top.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_top.png deleted file mode 100644 index c829613..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_top.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_top_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_top_left.png deleted file mode 100644 index 74afb04..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_top_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_top_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_top_right.png deleted file mode 100644 index eb6a7b2..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_hover_top_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_left.png deleted file mode 100644 index 5ea1114..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_bottom.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_bottom.png deleted file mode 100644 index 34c6f18..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_bottom.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_bottom_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_bottom_left.png deleted file mode 100644 index d82f9c9..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_bottom_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_bottom_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_bottom_right.png deleted file mode 100644 index 5630611..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_bottom_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_center.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_center.png deleted file mode 100644 index b843c34..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_center.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_left.png deleted file mode 100644 index aa344b1..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_right.png deleted file mode 100644 index 91a6228..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_top.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_top.png deleted file mode 100644 index 31ffbd14..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_top.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_top_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_top_left.png deleted file mode 100644 index 89f334a..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_top_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_top_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_top_right.png deleted file mode 100644 index 192c9b1..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_pressed_top_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_right.png deleted file mode 100644 index 318e77d..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_top.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_top.png deleted file mode 100644 index d91c581..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_top.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_top_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_top_left.png deleted file mode 100644 index 2b18488..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_top_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_top_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_top_right.png deleted file mode 100644 index ed03f644..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win7/sign_in_button_top_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_avatar.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_avatar.png deleted file mode 100644 index 39cee7a..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_avatar.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_bottom.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_bottom.png deleted file mode 100644 index cd31098..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_bottom.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_bottom_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_bottom_left.png deleted file mode 100644 index cd31098..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_bottom_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_bottom_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_bottom_right.png deleted file mode 100644 index cd31098..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_bottom_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_center.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_center.png deleted file mode 100644 index 7b6c31cc..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_center.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_bottom.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_bottom.png deleted file mode 100644 index 1e05a12..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_bottom.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_bottom_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_bottom_left.png deleted file mode 100644 index 1e05a12..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_bottom_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_bottom_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_bottom_right.png deleted file mode 100644 index 1e05a12..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_bottom_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_center.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_center.png deleted file mode 100644 index 97e8d14..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_center.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_left.png deleted file mode 100644 index 97e8d14..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_right.png deleted file mode 100644 index 97e8d14..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_top.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_top.png deleted file mode 100644 index 74beec4..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_top.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_top_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_top_left.png deleted file mode 100644 index 74beec4..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_top_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_top_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_top_right.png deleted file mode 100644 index 74beec4..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_hover_top_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_left.png deleted file mode 100644 index 7b6c31cc..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_bottom.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_bottom.png deleted file mode 100644 index 58cbeba..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_bottom.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_bottom_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_bottom_left.png deleted file mode 100644 index 58cbeba..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_bottom_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_bottom_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_bottom_right.png deleted file mode 100644 index 58cbeba..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_bottom_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_center.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_center.png deleted file mode 100644 index b8616b0..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_center.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_left.png deleted file mode 100644 index b8616b0..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_right.png deleted file mode 100644 index b8616b0..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_top.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_top.png deleted file mode 100644 index 91c2828..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_top.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_top_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_top_left.png deleted file mode 100644 index 91c2828..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_top_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_top_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_top_right.png deleted file mode 100644 index 91c2828..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_pressed_top_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_right.png deleted file mode 100644 index 7b6c31cc..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_top.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_top.png deleted file mode 100644 index e6fe999..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_top.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_top_left.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_top_left.png deleted file mode 100644 index e6fe999..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_top_left.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_top_right.png b/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_top_right.png deleted file mode 100644 index e6fe999..0000000 --- a/chrome/app/theme/default_100_percent/win/avatar_button/win8/sign_in_button_top_right.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 6c3c1012..9a1bd9be 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd
@@ -251,98 +251,6 @@ <structure type="chrome_scaled_image" name="IDR_PROFILE_AVATAR_PLACEHOLDER_LARGE" file="common/profile_avatar_placeholder_large.png" /> <structure type="chrome_scaled_image" name="IDR_PROFILES_DICE_TURN_ON_SYNC" file="common/turn_on_sync_illustration.png" /> - <!-- New style avatar button --> - <if expr="is_win"> - <!-- Windows, themed --> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_AVATAR" file="win/avatar_button/themed/sign_in_button_avatar.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_BOTTOM" file="win/avatar_button/themed/sign_in_button_bottom.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_BOTTOM_LEFT" file="win/avatar_button/themed/sign_in_button_bottom_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_BOTTOM_RIGHT" file="win/avatar_button/themed/sign_in_button_bottom_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_CENTER" file="win/avatar_button/themed/sign_in_button_center.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_LEFT" file="win/avatar_button/themed/sign_in_button_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_RIGHT" file="win/avatar_button/themed/sign_in_button_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_TOP" file="win/avatar_button/themed/sign_in_button_top.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_TOP_LEFT" file="win/avatar_button/themed/sign_in_button_top_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_TOP_RIGHT" file="win/avatar_button/themed/sign_in_button_top_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_BOTTOM" file="win/avatar_button/themed/sign_in_button_hover_bottom.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_BOTTOM_LEFT" file="win/avatar_button/themed/sign_in_button_hover_bottom_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_BOTTOM_RIGHT" file="win/avatar_button/themed/sign_in_button_hover_bottom_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_CENTER" file="win/avatar_button/themed/sign_in_button_hover_center.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_LEFT" file="win/avatar_button/themed/sign_in_button_hover_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_RIGHT" file="win/avatar_button/themed/sign_in_button_hover_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_TOP" file="win/avatar_button/themed/sign_in_button_hover_top.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_TOP_LEFT" file="win/avatar_button/themed/sign_in_button_hover_top_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_TOP_RIGHT" file="win/avatar_button/themed/sign_in_button_hover_top_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_BOTTOM" file="win/avatar_button/themed/sign_in_button_pressed_bottom.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_BOTTOM_LEFT" file="win/avatar_button/themed/sign_in_button_pressed_bottom_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_BOTTOM_RIGHT" file="win/avatar_button/themed/sign_in_button_pressed_bottom_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_CENTER" file="win/avatar_button/themed/sign_in_button_pressed_center.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_LEFT" file="win/avatar_button/themed/sign_in_button_pressed_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_RIGHT" file="win/avatar_button/themed/sign_in_button_pressed_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_TOP" file="win/avatar_button/themed/sign_in_button_pressed_top.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_TOP_LEFT" file="win/avatar_button/themed/sign_in_button_pressed_top_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_TOP_RIGHT" file="win/avatar_button/themed/sign_in_button_pressed_top_right.png" /> - - <!-- Windows 7, Aero --> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_AVATAR" file="win/avatar_button/win7/sign_in_button_avatar.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_BOTTOM" file="win/avatar_button/win7/sign_in_button_bottom.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_BOTTOM_LEFT" file="win/avatar_button/win7/sign_in_button_bottom_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_BOTTOM_RIGHT" file="win/avatar_button/win7/sign_in_button_bottom_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_CENTER" file="win/avatar_button/win7/sign_in_button_center.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_LEFT" file="win/avatar_button/win7/sign_in_button_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_RIGHT" file="win/avatar_button/win7/sign_in_button_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_TOP" file="win/avatar_button/win7/sign_in_button_top.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_TOP_LEFT" file="win/avatar_button/win7/sign_in_button_top_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_TOP_RIGHT" file="win/avatar_button/win7/sign_in_button_top_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_BOTTOM" file="win/avatar_button/win7/sign_in_button_hover_bottom.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_BOTTOM_LEFT" file="win/avatar_button/win7/sign_in_button_hover_bottom_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_BOTTOM_RIGHT" file="win/avatar_button/win7/sign_in_button_hover_bottom_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_CENTER" file="win/avatar_button/win7/sign_in_button_hover_center.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_LEFT" file="win/avatar_button/win7/sign_in_button_hover_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_RIGHT" file="win/avatar_button/win7/sign_in_button_hover_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_TOP" file="win/avatar_button/win7/sign_in_button_hover_top.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_TOP_LEFT" file="win/avatar_button/win7/sign_in_button_hover_top_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_TOP_RIGHT" file="win/avatar_button/win7/sign_in_button_hover_top_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_BOTTOM" file="win/avatar_button/win7/sign_in_button_pressed_bottom.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_BOTTOM_LEFT" file="win/avatar_button/win7/sign_in_button_pressed_bottom_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_BOTTOM_RIGHT" file="win/avatar_button/win7/sign_in_button_pressed_bottom_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_CENTER" file="win/avatar_button/win7/sign_in_button_pressed_center.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_LEFT" file="win/avatar_button/win7/sign_in_button_pressed_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_RIGHT" file="win/avatar_button/win7/sign_in_button_pressed_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_TOP" file="win/avatar_button/win7/sign_in_button_pressed_top.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_TOP_LEFT" file="win/avatar_button/win7/sign_in_button_pressed_top_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_TOP_RIGHT" file="win/avatar_button/win7/sign_in_button_pressed_top_right.png" /> - - <!-- Windows 8 and up --> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_AVATAR" file="win/avatar_button/win8/sign_in_button_avatar.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_NORMAL_BOTTOM" file="win/avatar_button/win8/sign_in_button_bottom.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_NORMAL_BOTTOM_LEFT" file="win/avatar_button/win8/sign_in_button_bottom_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_NORMAL_BOTTOM_RIGHT" file="win/avatar_button/win8/sign_in_button_bottom_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_NORMAL_CENTER" file="win/avatar_button/win8/sign_in_button_center.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_NORMAL_LEFT" file="win/avatar_button/win8/sign_in_button_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_NORMAL_RIGHT" file="win/avatar_button/win8/sign_in_button_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_NORMAL_TOP" file="win/avatar_button/win8/sign_in_button_top.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_NORMAL_TOP_LEFT" file="win/avatar_button/win8/sign_in_button_top_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_NORMAL_TOP_RIGHT" file="win/avatar_button/win8/sign_in_button_top_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_HOVER_BOTTOM" file="win/avatar_button/win8/sign_in_button_hover_bottom.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_HOVER_BOTTOM_LEFT" file="win/avatar_button/win8/sign_in_button_hover_bottom_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_HOVER_BOTTOM_RIGHT" file="win/avatar_button/win8/sign_in_button_hover_bottom_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_HOVER_CENTER" file="win/avatar_button/win8/sign_in_button_hover_center.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_HOVER_LEFT" file="win/avatar_button/win8/sign_in_button_hover_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_HOVER_RIGHT" file="win/avatar_button/win8/sign_in_button_hover_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_HOVER_TOP" file="win/avatar_button/win8/sign_in_button_hover_top.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_HOVER_TOP_LEFT" file="win/avatar_button/win8/sign_in_button_hover_top_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_HOVER_TOP_RIGHT" file="win/avatar_button/win8/sign_in_button_hover_top_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_PRESSED_BOTTOM" file="win/avatar_button/win8/sign_in_button_pressed_bottom.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_PRESSED_BOTTOM_LEFT" file="win/avatar_button/win8/sign_in_button_pressed_bottom_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_PRESSED_BOTTOM_RIGHT" file="win/avatar_button/win8/sign_in_button_pressed_bottom_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_PRESSED_CENTER" file="win/avatar_button/win8/sign_in_button_pressed_center.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_PRESSED_LEFT" file="win/avatar_button/win8/sign_in_button_pressed_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_PRESSED_RIGHT" file="win/avatar_button/win8/sign_in_button_pressed_right.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_PRESSED_TOP" file="win/avatar_button/win8/sign_in_button_pressed_top.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_PRESSED_TOP_LEFT" file="win/avatar_button/win8/sign_in_button_pressed_top_left.png" /> - <structure type="chrome_scaled_image" name="IDR_AVATAR_NATIVE_BUTTON_PRESSED_TOP_RIGHT" file="win/avatar_button/win8/sign_in_button_pressed_top_right.png" /> - </if> <if expr="chromeos"> <structure type="chrome_scaled_image" name="IDR_RESET_WARNING" file="cros/reset_warning.png" /> </if>
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn index ce408882..78c4bb4 100644 --- a/chrome/app/vector_icons/BUILD.gn +++ b/chrome/app/vector_icons/BUILD.gn
@@ -12,7 +12,6 @@ "account_box.icon", "account_child.icon", "account_child_circle.icon", - "account_circle.icon", "add.icon", "ads.icon", "apps.icon", @@ -76,7 +75,6 @@ "picture_in_picture_control_background.icon", "play_arrow.icon", "picture_in_picture_alt.icon", - "profile_switcher_outline.icon", "reload_touch.icon", "remove.icon", "remove_box.icon", @@ -94,7 +92,6 @@ "sync.icon", "sync_circle.icon", "sync_error_circle.icon", - "sync_paused.icon", "sync_paused_circle.icon", "sync_problem.icon", "sync_switch_account.icon",
diff --git a/chrome/app/vector_icons/account_circle.icon b/chrome/app/vector_icons/account_circle.icon deleted file mode 100644 index 07bf0c78..0000000 --- a/chrome/app/vector_icons/account_circle.icon +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 24, -MOVE_TO, 12, 2, -CUBIC_TO, 6.48f, 2, 2, 6.48f, 2, 12, -R_CUBIC_TO, 0, 5.52f, 4.48f, 10, 10, 10, -R_CUBIC_TO, 5.52f, 0, 10, -4.48f, 10, -10, -CUBIC_TO, 22, 6.48f, 17.52f, 2, 12, 2, -CLOSE, -R_MOVE_TO, 0, 3, -R_CUBIC_TO, 1.66f, 0, 3, 1.34f, 3, 3, -R_CUBIC_TO, 0, 1.66f, -1.34f, 3, -3, 3, -R_CUBIC_TO, -1.66f, 0, -3, -1.34f, -3, -3, -R_CUBIC_TO, 0, -1.66f, 1.34f, -3, 3, -3, -CLOSE, -R_MOVE_TO, 0, 14.2f, -R_CUBIC_TO, -2.5f, 0, -4.71f, -1.28f, -6, -3.22f, -R_CUBIC_TO, 0.03f, -1.99f, 4, -3.08f, 6, -3.08f, -R_CUBIC_TO, 1.99f, 0, 5.97f, 1.09f, 6, 3.08f, -R_CUBIC_TO, -1.29f, 1.94f, -3.5f, 3.22f, -6, 3.22f, -CLOSE
diff --git a/chrome/app/vector_icons/profile_switcher_outline.icon b/chrome/app/vector_icons/profile_switcher_outline.icon deleted file mode 100644 index f7efb07..0000000 --- a/chrome/app/vector_icons/profile_switcher_outline.icon +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This is a copy of account_circle.icon with an added path for an outline. -// Outline: -STROKE, 3, -MOVE_TO, 24, 4, -CUBIC_TO, 12.95f, 4, 4, 12.95f, 4, 24, -R_CUBIC_TO, 0, 11.05f, 8.95f, 20, 20, 20, -R_CUBIC_TO, 11.05f, 0, 20, -8.95f, 20, -20, -CUBIC_TO_SHORTHAND, 35.05f, 4, 24, 4, -CLOSE, -R_MOVE_TO, 0, 6, -R_CUBIC_TO, 3.31f, 0, 6, 2.69f, 6, 6, -R_CUBIC_TO, 0, 3.32f, -2.69f, 6, -6, 6, -R_CUBIC_TO, -3.31f, 0, -6, -2.68f, -6, -6, -R_CUBIC_TO, 0, -3.31f, 2.69f, -6, 6, -6, -CLOSE, -R_MOVE_TO, 0, 28.4f, -R_CUBIC_TO, -5.01f, 0, -9.41f, -2.56f, -12, -6.44f, -R_CUBIC_TO, 0.05f, -3.97f, 8.01f, -6.16f, 12, -6.16f, -R_CUBIC_TO, 3.99f, 0, 11.94f, 2.19f, 12, 6.16f, -R_CUBIC_TO, -2.59f, 3.88f, -6.99f, 6.44f, -12, 6.44f, -CLOSE, - -// Fill: -NEW_PATH, -PATH_COLOR_ARGB, 0xff, 0xff, 0xff, 0xff, -MOVE_TO, 24, 4, -CUBIC_TO, 12.95f, 4, 4, 12.95f, 4, 24, -R_CUBIC_TO, 0, 11.05f, 8.95f, 20, 20, 20, -R_CUBIC_TO, 11.05f, 0, 20, -8.95f, 20, -20, -CUBIC_TO_SHORTHAND, 35.05f, 4, 24, 4, -CLOSE, -R_MOVE_TO, 0, 6, -R_CUBIC_TO, 3.31f, 0, 6, 2.69f, 6, 6, -R_CUBIC_TO, 0, 3.32f, -2.69f, 6, -6, 6, -R_CUBIC_TO, -3.31f, 0, -6, -2.68f, -6, -6, -R_CUBIC_TO, 0, -3.31f, 2.69f, -6, 6, -6, -CLOSE, -R_MOVE_TO, 0, 28.4f, -R_CUBIC_TO, -5.01f, 0, -9.41f, -2.56f, -12, -6.44f, -R_CUBIC_TO, 0.05f, -3.97f, 8.01f, -6.16f, 12, -6.16f, -R_CUBIC_TO, 3.99f, 0, 11.94f, 2.19f, 12, 6.16f, -R_CUBIC_TO, -2.59f, 3.88f, -6.99f, 6.44f, -12, 6.44f, -CLOSE
diff --git a/chrome/app/vector_icons/sync_paused.icon b/chrome/app/vector_icons/sync_paused.icon deleted file mode 100644 index 6eb251b..0000000 --- a/chrome/app/vector_icons/sync_paused.icon +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 16, -MOVE_TO, 6.67f, 4.23f, -V_LINE_TO, 2.84f, -R_ARC_TO, 5.48f, 5.48f, 0, 0, 0, -1.49f, 0.64f, -R_LINE_TO, 0.97f, 0.97f, -R_CUBIC_TO, 0.17f, -0.08f, 0.33f, -0.16f, 0.51f, -0.22f, -CLOSE, -R_MOVE_TO, -4.76f, -0.63f, -LINE_TO, 3.48f, 5.18f, -R_ARC_TO, 5.28f, 5.28f, 0, 0, 0, 0.76f, 6.58f, -R_LINE_TO, -1.57f, 1.57f, -R_H_LINE_TO, 4, -R_V_LINE_TO, -4, -R_LINE_TO, -1.49f, 1.49f, -ARC_TO, 4, 4, 0, 0, 1, 4, 8, -R_CUBIC_TO, 0, -0.67f, 0.17f, -1.29f, 0.45f, -1.85f, -LINE_TO, 9.84f, 11.54f, -R_ARC_TO, 3.53f, 3.53f, 0, 0, 1, -0.51f, 0.23f, -R_V_LINE_TO, 1.39f, -R_ARC_TO, 5.48f, 5.48f, 0, 0, 0, 1.49f, -0.64f, -R_LINE_TO, 1.57f, 1.57f, -R_LINE_TO, 0.85f, -0.85f, -LINE_TO, 2.76f, 2.76f, -R_LINE_TO, -0.85f, 0.85f, -CLOSE, -R_MOVE_TO, 11.43f, -0.94f, -R_H_LINE_TO, -4, -R_V_LINE_TO, 4, -R_LINE_TO, 1.49f, -1.49f, -ARC_TO, 4, 4, 0, 0, 1, 12, 8, -R_CUBIC_TO, 0, 0.67f, -0.17f, 1.29f, -0.45f, 1.85f, -R_LINE_TO, 0.97f, 0.97f, -R_ARC_TO, 5.28f, 5.28f, 0, 0, 0, -0.76f, -6.58f, -R_LINE_TO, 1.57f, -1.57f, -CLOSE -
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 632368c..4adc6a2f 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -554,8 +554,6 @@ "google/did_run_updater_win.h", "google/google_brand.cc", "google/google_brand.h", - "google/google_brand_chromeos.cc", - "google/google_brand_chromeos.h", "google/google_search_domain_mixing_metrics_emitter.cc", "google/google_search_domain_mixing_metrics_emitter.h", "google/google_search_domain_mixing_metrics_emitter_factory.cc", @@ -3076,6 +3074,10 @@ "download/notification/download_notification_manager.h", "feedback/feedback_util_chromeos.cc", "feedback/feedback_util_chromeos.h", + "google/google_brand_chromeos.cc", + "google/google_brand_chromeos.h", + "google/google_brand_code_map_chromeos.cc", + "google/google_brand_code_map_chromeos.h", "media/chromeos_login_media_access_handler.cc", "media/chromeos_login_media_access_handler.h", "media/public_session_media_access_handler.cc",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 5ce5910..7793cb5d 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -215,8 +215,11 @@ specific_include_rules = { "ash_service_registry\.cc": [ + # The following are needed for classic mode to create the WindowService. + # Once Ash runs out of process no longer needed. + "+ash/shell.h", + # Needed for classic mode. - "+ash/accessibility/ax_host_service.h", "+ash/ash_service.h", ], # TODO(mash): Fix. https://crbug.com/768439, https://crbug.com/768395.
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index d770b45..a9aba7ea 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2191,9 +2191,6 @@ flag_descriptions::kMemoryCoordinatorDescription, kOsAndroid | kOsCrOS | kOsLinux | kOsWin, FEATURE_VALUE_TYPE(features::kMemoryCoordinator)}, - {"enable-tab-audio-muting", flag_descriptions::kTabAudioMutingName, - flag_descriptions::kTabAudioMutingDescription, kOsDesktop, - SINGLE_VALUE_TYPE(switches::kEnableTabAudioMuting)}, {"reduced-referrer-granularity", flag_descriptions::kReducedReferrerGranularityName, flag_descriptions::kReducedReferrerGranularityDescription, kOsAll, @@ -3375,13 +3372,18 @@ kOsAll, FEATURE_VALUE_TYPE(omnibox::kUIExperimentElideSuggestionUrlAfterHost)}, - {"omnibox-ui-hide-steady-state-url-scheme-and-subdomains", - flag_descriptions::kOmniboxUIHideSteadyStateUrlSchemeAndSubdomainsName, + {"omnibox-ui-hide-steady-state-url-scheme", + flag_descriptions::kOmniboxUIHideSteadyStateUrlSchemeName, + flag_descriptions::kOmniboxUIHideSteadyStateUrlSchemeDescription, kOsAll, + FEATURE_VALUE_TYPE(toolbar::features::kHideSteadyStateUrlScheme)}, + + {"omnibox-ui-hide-steady-state-url-trivial-subdomains", + flag_descriptions::kOmniboxUIHideSteadyStateUrlTrivialSubdomainsName, flag_descriptions:: - kOmniboxUIHideSteadyStateUrlSchemeAndSubdomainsDescription, + kOmniboxUIHideSteadyStateUrlTrivialSubdomainsDescription, kOsAll, FEATURE_VALUE_TYPE( - omnibox::kUIExperimentHideSteadyStateUrlSchemeAndSubdomains)}, + toolbar::features::kHideSteadyStateUrlTrivialSubdomains)}, {"omnibox-ui-jog-textfield-on-popup", flag_descriptions::kOmniboxUIJogTextfieldOnPopupName,
diff --git a/chrome/browser/accessibility/DEPS b/chrome/browser/accessibility/DEPS deleted file mode 100644 index cdc3383..0000000 --- a/chrome/browser/accessibility/DEPS +++ /dev/null
@@ -1,7 +0,0 @@ -specific_include_rules = { - "accessibility_extension_api\.cc": [ - # TODO(mash): Replace with mojo API. http://crbug.com/594887 - "+ash/accessibility/accessibility_focus_ring_controller.h", - "+ash/shell.h", - ], -}
diff --git a/chrome/browser/accessibility/accessibility_extension_api.cc b/chrome/browser/accessibility/accessibility_extension_api.cc index 2ffd012..cc84c72 100644 --- a/chrome/browser/accessibility/accessibility_extension_api.cc +++ b/chrome/browser/accessibility/accessibility_extension_api.cc
@@ -38,12 +38,13 @@ #include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h" #include "ash/public/interfaces/constants.mojom.h" #include "ash/public/interfaces/event_rewriter_controller.mojom.h" -#include "ash/shell.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h" -#include "ui/aura/window_tree_host.h" +#include "services/ws/public/mojom/constants.mojom.h" +#include "services/ws/public/mojom/event_injector.mojom.h" #include "ui/base/ui_base_features.h" -#include "ui/events/event_sink.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" #endif namespace accessibility_private = extensions::api::accessibility_private; @@ -233,12 +234,6 @@ ExtensionFunction::ResponseAction AccessibilityPrivateSendSyntheticKeyEventFunction::Run() { - // TODO(crbug.com/876043): Mash support. - if (features::IsUsingWindowService()) { - NOTIMPLEMENTED(); - return RespondNow(NoArguments()); - } - std::unique_ptr<accessibility_private::SendSyntheticKeyEvent::Params> params = accessibility_private::SendSyntheticKeyEvent::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(params); @@ -256,19 +251,23 @@ modifiers |= ui::EF_SHIFT_DOWN; } - ui::KeyEvent synthetic_key_event( - key_data->type == - accessibility_private::SYNTHETIC_KEYBOARD_EVENT_TYPE_KEYUP - ? ui::ET_KEY_RELEASED - : ui::ET_KEY_PRESSED, - static_cast<ui::KeyboardCode>(key_data->key_code), - static_cast<ui::DomCode>(0), modifiers); + std::unique_ptr<ui::KeyEvent> synthetic_key_event = + std::make_unique<ui::KeyEvent>( + key_data->type == + accessibility_private::SYNTHETIC_KEYBOARD_EVENT_TYPE_KEYUP + ? ui::ET_KEY_RELEASED + : ui::ET_KEY_PRESSED, + static_cast<ui::KeyboardCode>(key_data->key_code), + static_cast<ui::DomCode>(0), modifiers); - // Only keyboard events, so dispatching to primary window suffices. - ui::EventSink* sink = - ash::Shell::GetPrimaryRootWindow()->GetHost()->event_sink(); - if (sink->OnEventFromSource(&synthetic_key_event).dispatcher_destroyed) - return RespondNow(Error("Unable to dispatch key ")); + ws::mojom::EventInjectorPtr event_injector_ptr; + content::ServiceManagerConnection* connection = + content::ServiceManagerConnection::GetForProcess(); + connection->GetConnector()->BindInterface(ws::mojom::kServiceName, + &event_injector_ptr); + event_injector_ptr->InjectEventNoAck( + display::Screen::GetScreen()->GetPrimaryDisplay().id(), + std::move(synthetic_key_event)); return RespondNow(NoArguments()); }
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index b34f7078..ff87f10 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -26,6 +26,7 @@ #include "components/payments/core/features.h" #include "components/safe_browsing/features.h" #include "components/subresource_filter/core/browser/subresource_filter_features.h" +#include "components/toolbar/toolbar_field_trial.h" #include "components/unified_consent/feature.h" #include "content/public/common/content_features.h" #include "jni/ChromeFeatureList_jni.h" @@ -161,11 +162,12 @@ &offline_pages::kOfflinePagesLivePageSharingFeature, &offline_pages::kPrefetchingOfflinePagesFeature, &omnibox::kQueryInOmnibox, - &omnibox::kUIExperimentHideSteadyStateUrlSchemeAndSubdomains, &password_manager::features::kPasswordSearchMobile, &password_manager::features::kPasswordsKeyboardAccessory, &unified_consent::kUnifiedConsent, &subresource_filter::kSafeBrowsingSubresourceFilter, + &toolbar::features::kHideSteadyStateUrlScheme, + &toolbar::features::kHideSteadyStateUrlTrivialSubdomains, }; const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
diff --git a/chrome/browser/android/signin/signin_manager_android.cc b/chrome/browser/android/signin/signin_manager_android.cc index 175e860..7d8823cc 100644 --- a/chrome/browser/android/signin/signin_manager_android.cc +++ b/chrome/browser/android/signin/signin_manager_android.cc
@@ -326,13 +326,6 @@ return SigninManagerFactory::GetForProfile(profile_)->IsAuthenticated(); } -void SigninManagerAndroid::ProhibitSignout(JNIEnv* env, - const JavaParamRef<jobject>& obj, - jboolean prohibit_signout) { - SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout( - prohibit_signout); -} - void SigninManagerAndroid::GoogleSigninFailed( const GoogleServiceAuthError& error) {}
diff --git a/chrome/browser/android/signin/signin_manager_android.h b/chrome/browser/android/signin/signin_manager_android.h index 2596442..4d711455 100644 --- a/chrome/browser/android/signin/signin_manager_android.h +++ b/chrome/browser/android/signin/signin_manager_android.h
@@ -80,10 +80,6 @@ jboolean IsSignedInOnNative(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); - void ProhibitSignout(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - jboolean prohibit_signout); - // SigninManagerBase::Observer implementation. void GoogleSigninFailed(const GoogleServiceAuthError& error) override; void GoogleSigninSucceeded(const std::string& account_id,
diff --git a/chrome/browser/ash_service_registry.cc b/chrome/browser/ash_service_registry.cc index 25d15c5..0a694395 100644 --- a/chrome/browser/ash_service_registry.cc +++ b/chrome/browser/ash_service_registry.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/ash_service_registry.h" -#include "ash/accessibility/ax_host_service.h" #include "ash/ash_service.h" #include "ash/components/quick_launch/public/mojom/constants.mojom.h" #include "ash/components/shortcut_viewer/public/mojom/shortcut_viewer.mojom.h" @@ -16,6 +15,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" +#include "chrome/browser/chromeos/accessibility/ax_host_service.h" #include "chrome/browser/chromeos/prefs/pref_connector_service.h" #include "chrome/grit/generated_resources.h" #include "content/public/common/service_manager_connection.h" @@ -84,20 +84,20 @@ (*services)[ash::mojom::kPrefConnectorServiceName] = info; } - if (features::IsMultiProcessMash()) - return; - { // Register the accessibility host service. service_manager::EmbeddedServiceInfo info; info.task_runner = base::ThreadTaskRunnerHandle::Get(); info.factory = base::BindRepeating([]() -> std::unique_ptr<service_manager::Service> { - return std::make_unique<ash::AXHostService>(); + return std::make_unique<AXHostService>(); }); (*services)[ax::mojom::kAXHostServiceName] = info; } + if (features::IsMultiProcessMash()) + return; + (*services)[ash::mojom::kServiceName] = ash::AshService::CreateEmbeddedServiceInfo(); }
diff --git a/chrome/browser/autofill/autofill_server_browsertest.cc b/chrome/browser/autofill/autofill_server_browsertest.cc index a7a3139..56cae23b 100644 --- a/chrome/browser/autofill/autofill_server_browsertest.cc +++ b/chrome/browser/autofill/autofill_server_browsertest.cc
@@ -189,6 +189,8 @@ upload.set_action_signature(15724779818122431245U); upload.set_form_name("test_form"); upload.set_passwords_revealed(false); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_HTML_FORM_SUBMISSION); test::FillUploadField(upload.add_field(), 2594484045U, "one", "text", nullptr, 2U);
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index feef0c9..1b84a87 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -71,6 +71,23 @@ <structure name="IDR_WELCOME_ONBOARDING_WELCOME_WELCOME_BROWSER_PROXY_JS" file="resources\welcome\onboarding_welcome\welcome_browser_proxy.js" type="chrome_html"/> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_WELCOME_CSS" file="resources\welcome\onboarding_welcome\welcome.css" type="chrome_html" preprocess="true"/> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_WELCOME_HTML" file="resources\welcome\onboarding_welcome\welcome.html" type="chrome_html" preprocess="true"/> + <!-- NUX files --> + <structure name="IDR_NUX_EMAIL_CHOOSER_HTML" file="resources\welcome\onboarding_welcome\email\email_chooser.html" type="chrome_html" /> + <structure name="IDR_NUX_EMAIL_CHOOSER_JS" file="resources\welcome\onboarding_welcome\email\email_chooser.js" type="chrome_html" /> + <structure name="IDR_NUX_EMAIL_HTML" file="resources\welcome\onboarding_welcome\email\nux_email.html" type="chrome_html" /> + <structure name="IDR_NUX_EMAIL_JS" file="resources\welcome\onboarding_welcome\email\nux_email.js" type="chrome_html" /> + <structure name="IDR_NUX_EMAIL_PROXY_HTML" file="resources\welcome\onboarding_welcome\email\nux_email_proxy.html" type="chrome_html" /> + <structure name="IDR_NUX_EMAIL_PROXY_JS" file="resources\welcome\onboarding_welcome\email\nux_email_proxy.js" type="chrome_html" /> + <structure name="IDR_NUX_GOOGLE_APPS_HTML" file="resources\welcome\onboarding_welcome\google_apps\nux_google_apps.html" type="chrome_html" /> + <structure name="IDR_NUX_GOOGLE_APPS_JS" file="resources\welcome\onboarding_welcome\google_apps\nux_google_apps.js" type="chrome_html" /> + <structure name="IDR_NUX_GOOGLE_APPS_PROXY_HTML" file="resources\welcome\onboarding_welcome\google_apps\nux_google_apps_proxy.html" type="chrome_html" /> + <structure name="IDR_NUX_GOOGLE_APPS_PROXY_JS" file="resources\welcome\onboarding_welcome\google_apps\nux_google_apps_proxy.js" type="chrome_html" /> + <structure name="IDR_NUX_GOOGLE_APPS_CHOOSER_HTML" file="resources\welcome\onboarding_welcome\google_apps\apps_chooser.html" type="chrome_html" /> + <structure name="IDR_NUX_GOOGLE_APPS_CHOOSER_JS" file="resources\welcome\onboarding_welcome\google_apps\apps_chooser.js" type="chrome_html" /> + <structure name="IDR_NUX_SET_AS_DEFAULT_HTML" file="resources\welcome\onboarding_welcome\set_as_default\nux_set_as_default.html" type="chrome_html" /> + <structure name="IDR_NUX_SET_AS_DEFAULT_JS" file="resources\welcome\onboarding_welcome\set_as_default\nux_set_as_default.js" type="chrome_html" /> + <structure name="IDR_NUX_SET_AS_DEFAULT_PROXY_HTML" file="resources\welcome\onboarding_welcome\set_as_default\nux_set_as_default_proxy.html" type="chrome_html" /> + <structure name="IDR_NUX_SET_AS_DEFAULT_PROXY_JS" file="resources\welcome\onboarding_welcome\set_as_default\nux_set_as_default_proxy.js" type="chrome_html" /> </if> <if expr="is_win"> <structure name="IDR_WELCOME_WIN10_CSS" file="resources\welcome\welcome_win10.css" type="chrome_html" /> @@ -670,6 +687,30 @@ <if expr="is_win"> <include name="IDR_NACL_BROKER_MANIFEST" file="../../components/nacl/broker/nacl_broker_manifest.json" type="BINDATA" /> </if> + <if expr="not is_android and not chromeos"> + <include name="IDR_NUX_EMAIL_AOL_1X" file="resources\welcome\onboarding_welcome\images\aol_1x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_AOL_2X" file="resources\welcome\onboarding_welcome\images\aol_2x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_GMAIL_1X" file="resources\welcome\onboarding_welcome\images\gmail_1x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_GMAIL_2X" file="resources\welcome\onboarding_welcome\images\gmail_2x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_ICLOUD_1X" file="resources\welcome\onboarding_welcome\images\icloud_1x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_ICLOUD_2X" file="resources\welcome\onboarding_welcome\images\icloud_2x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_OUTLOOK_1X" file="resources\welcome\onboarding_welcome\images\outlook_1x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_OUTLOOK_2X" file="resources\welcome\onboarding_welcome\images\outlook_2x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_YAHOO_1X" file="resources\welcome\onboarding_welcome\images\yahoo_1x.png" type="BINDATA" /> + <include name="IDR_NUX_EMAIL_YAHOO_2X" file="resources\welcome\onboarding_welcome\images\yahoo_2x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_CHROME_STORE_1X" file="resources\welcome\onboarding_welcome\images\chrome_store_24dp_1x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_CHROME_STORE_2X" file="resources\welcome\onboarding_welcome\images\chrome_store_24dp_2x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_GMAIL_1X" file="resources\welcome\onboarding_welcome\images\gmail_24dp_1x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_GMAIL_2X" file="resources\welcome\onboarding_welcome\images\gmail_24dp_2x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_MAPS_1X" file="resources\welcome\onboarding_welcome\images\maps_24dp_1x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_MAPS_2X" file="resources\welcome\onboarding_welcome\images\maps_24dp_2x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_NEWS_1X" file="resources\welcome\onboarding_welcome\images\news_24dp_1x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_NEWS_2X" file="resources\welcome\onboarding_welcome\images\news_24dp_2x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_TRANSLATE_1X" file="resources\welcome\onboarding_welcome\images\translate_24dp_1x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_TRANSLATE_2X" file="resources\welcome\onboarding_welcome\images\translate_24dp_2x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_YOUTUBE_1X" file="resources\welcome\onboarding_welcome\images\youtube_24dp_1x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_YOUTUBE_2X" file="resources\welcome\onboarding_welcome\images\youtube_24dp_2x.png" type="BINDATA" /> + </if> <if expr="is_win"> <include name="IDR_WELCOME_WIN10_DEFAULT_WEBP" file="resources\welcome\default.webp" type="BINDATA" /> <include name="IDR_WELCOME_WIN10_PIN_WEBP" file="resources\welcome\pin.webp" type="BINDATA" />
diff --git a/chrome/browser/browsing_data/browsing_data_quota_helper_impl.cc b/chrome/browser/browsing_data/browsing_data_quota_helper_impl.cc index 31ac756..b3aee798 100644 --- a/chrome/browser/browsing_data/browsing_data_quota_helper_impl.cc +++ b/chrome/browser/browsing_data/browsing_data_quota_helper_impl.cc
@@ -17,9 +17,9 @@ #include "chrome/common/url_constants.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" #include "storage/browser/quota/quota_manager.h" +#include "url/origin.h" using blink::mojom::StorageType; using content::BrowserThread; @@ -84,15 +84,16 @@ } } -void BrowsingDataQuotaHelperImpl::GotOrigins(PendingHosts* pending_hosts, - base::OnceClosure completion, - const std::set<GURL>& origins, - StorageType type) { +void BrowsingDataQuotaHelperImpl::GotOrigins( + PendingHosts* pending_hosts, + base::OnceClosure completion, + const std::set<url::Origin>& origins, + StorageType type) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - for (const GURL& url : origins) { - if (!BrowsingDataHelper::HasWebScheme(url)) + for (const url::Origin& origin : origins) { + if (!BrowsingDataHelper::IsWebScheme(origin.scheme())) continue; // Non-websafe state is not considered browsing data. - pending_hosts->insert(std::make_pair(url.host(), type)); + pending_hosts->insert(std::make_pair(origin.host(), type)); } std::move(completion).Run(); }
diff --git a/chrome/browser/browsing_data/browsing_data_quota_helper_impl.h b/chrome/browser/browsing_data/browsing_data_quota_helper_impl.h index d88e744..d12f37aa 100644 --- a/chrome/browser/browsing_data/browsing_data_quota_helper_impl.h +++ b/chrome/browser/browsing_data/browsing_data_quota_helper_impl.h
@@ -19,12 +19,14 @@ #include "chrome/browser/browsing_data/browsing_data_quota_helper.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -class GURL; - namespace storage { class QuotaManager; } +namespace url { +class Origin; +} + // Implementation of BrowsingDataQuotaHelper. Since a client of // BrowsingDataQuotaHelper should live in UI thread and QuotaManager lives in // IO thread, we have to communicate over thread using PostTask. @@ -47,7 +49,7 @@ // Callback function for QuotaManager::GetOriginModifiedSince. void GotOrigins(PendingHosts* pending_hosts, base::OnceClosure completion, - const std::set<GURL>& origins, + const std::set<url::Origin>& origins, blink::mojom::StorageType type); // Calls QuotaManager::GetHostUsage for each (origin, type) pair.
diff --git a/chrome/browser/browsing_data/counters/site_data_counting_helper.cc b/chrome/browser/browsing_data/counters/site_data_counting_helper.cc index 8c2f5da5..a61bac42 100644 --- a/chrome/browser/browsing_data/counters/site_data_counting_helper.cc +++ b/chrome/browser/browsing_data/counters/site_data_counting_helper.cc
@@ -24,6 +24,8 @@ #include "ppapi/buildflags/buildflags.h" #include "services/network/public/mojom/cookie_manager.mojom.h" #include "storage/browser/quota/quota_manager.h" +#include "url/gurl.h" +#include "url/origin.h" using content::BrowserThread; @@ -143,13 +145,17 @@ } void SiteDataCountingHelper::GetQuotaOriginsCallback( - const std::set<GURL>& origin_set, + const std::set<url::Origin>& origins, blink::mojom::StorageType type) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - std::vector<GURL> origins(origin_set.begin(), origin_set.end()); - base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&SiteDataCountingHelper::Done, - base::Unretained(this), origins)); + std::vector<GURL> urls; + urls.resize(origins.size()); + for (const url::Origin& origin : origins) + urls.push_back(origin.GetURL()); + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::UI}, + base::BindOnce(&SiteDataCountingHelper::Done, base::Unretained(this), + std::move(urls))); } void SiteDataCountingHelper::GetLocalStorageUsageInfoCallback(
diff --git a/chrome/browser/browsing_data/counters/site_data_counting_helper.h b/chrome/browser/browsing_data/counters/site_data_counting_helper.h index 64700c6..ac1a2624 100644 --- a/chrome/browser/browsing_data/counters/site_data_counting_helper.h +++ b/chrome/browser/browsing_data/counters/site_data_counting_helper.h
@@ -24,6 +24,10 @@ struct SessionStorageUsageInfo; } +namespace url { +class Origin; +} + namespace storage { class SpecialStoragePolicy; } @@ -52,7 +56,7 @@ const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy, const std::vector<content::LocalStorageUsageInfo>& infos); - void GetQuotaOriginsCallback(const std::set<GURL>& origin_set, + void GetQuotaOriginsCallback(const std::set<url::Origin>& origin_set, blink::mojom::StorageType type); void SitesWithFlashDataCallback(const std::vector<std::string>& sites); void GetChannelIDsOnIOThread(
diff --git a/chrome/browser/chrome_content_renderer_manifest_overlay.json b/chrome/browser/chrome_content_renderer_manifest_overlay.json index d7ec48b..2d817f18 100644 --- a/chrome/browser/chrome_content_renderer_manifest_overlay.json +++ b/chrome/browser/chrome_content_renderer_manifest_overlay.json
@@ -28,7 +28,8 @@ "extensions.mojom.AppWindow", "safe_browsing.mojom.ThreatReporter", "safe_browsing.mojom.PhishingDetector", - "spellcheck.mojom.SpellCheckPanel" + "spellcheck.mojom.SpellCheckPanel", + "subresource_filter.mojom.SubresourceFilterAgent" ] }, "requires": {
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 6004ff7..f2f94ab1 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -265,6 +265,8 @@ "accessibility/accessibility_manager.h", "accessibility/accessibility_panel.cc", "accessibility/accessibility_panel.h", + "accessibility/ax_host_service.cc", + "accessibility/ax_host_service.h", "accessibility/chromevox_panel.cc", "accessibility/chromevox_panel.h", "accessibility/dictation_chromeos.cc", @@ -2021,6 +2023,7 @@ "../policy/default_geolocation_policy_handler_unittest.cc", "../resources/chromeos/zip_archiver/test/char_coding_test.cc", "../ui/browser_finder_chromeos_unittest.cc", + "accessibility/ax_host_service_unittest.cc", "app_mode/startup_app_launcher_unittest.cc", "apps/intent_helper/apps_navigation_throttle_unittest.cc", "apps/intent_helper/page_transition_util_unittest.cc",
diff --git a/ash/accessibility/ax_host_service.cc b/chrome/browser/chromeos/accessibility/ax_host_service.cc similarity index 68% rename from ash/accessibility/ax_host_service.cc rename to chrome/browser/chromeos/accessibility/ax_host_service.cc index 00ac720c..18c0281e 100644 --- a/ash/accessibility/ax_host_service.cc +++ b/chrome/browser/chromeos/accessibility/ax_host_service.cc
@@ -2,29 +2,33 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/accessibility/ax_host_service.h" +#include "chrome/browser/chromeos/accessibility/ax_host_service.h" #include "ash/accessibility/accessibility_controller.h" -#include "ash/accessibility/accessibility_delegate.h" #include "ash/shell.h" #include "base/bind.h" +#include "chrome/browser/extensions/api/automation_internal/automation_event_router.h" +#include "chrome/common/extensions/chrome_extension_messages.h" #include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/service_context.h" #include "ui/accessibility/ax_event.h" +#include "ui/aura/env.h" #include "ui/views/mus/ax_remote_host.h" -namespace ash { - AXHostService* AXHostService::instance_ = nullptr; bool AXHostService::automation_enabled_ = false; AXHostService::AXHostService() { // AX tree ID is automatically assigned. - DCHECK(!tree_id().empty()); + DCHECK_NE(tree_id(), ui::AXTreeIDUnknown()); - // TODO(jamescook): Eliminate this when multiple remote trees are supported. - Shell::Get()->accessibility_controller()->set_remote_ax_tree_id(tree_id()); + // ash::Shell may not exist in tests. + if (ash::Shell::HasInstance()) { + // TODO(jamescook): Eliminate this when tree ID assignment is handed in ash. + ash::Shell::Get()->accessibility_controller()->set_remote_ax_tree_id( + tree_id()); + } DCHECK(!instance_); instance_ = this; @@ -63,16 +67,20 @@ } void AXHostService::HandleAccessibilityEvent( - const std::string& tree_id, + const ui::AXTreeID& tree_id, const std::vector<ui::AXTreeUpdate>& updates, const ui::AXEvent& event) { CHECK_EQ(tree_id, this->tree_id()); - // Use an in-process delegate back to Chrome for efficiency in classic ash. - // For mash we'll need to pass around a mojo interface pointer such that a - // remote app can talk directly to the browser process and not ping-pong - // through the ash process. - Shell::Get()->accessibility_delegate()->DispatchAccessibilityEvent( - tree_id, updates, event); + ExtensionMsg_AccessibilityEventBundleParams event_bundle; + event_bundle.tree_id = tree_id; + for (const ui::AXTreeUpdate& update : updates) + event_bundle.updates.push_back(update); + event_bundle.events.push_back(event); + event_bundle.mouse_location = aura::Env::GetInstance()->last_mouse_location(); + + // Forward the tree updates and the event to the accessibility extension. + extensions::AutomationEventRouter::GetInstance()->DispatchAccessibilityEvents( + event_bundle); } void AXHostService::PerformAction(const ui::AXActionData& data) { @@ -96,7 +104,6 @@ } void AXHostService::OnRemoteHostDisconnected() { - Shell::Get()->accessibility_delegate()->DispatchTreeDestroyedEvent(tree_id()); + extensions::AutomationEventRouter::GetInstance()->DispatchTreeDestroyedEvent( + tree_id(), nullptr /* browser_context */); } - -} // namespace ash
diff --git a/ash/accessibility/ax_host_service.h b/chrome/browser/chromeos/accessibility/ax_host_service.h similarity index 82% rename from ash/accessibility/ax_host_service.h rename to chrome/browser/chromeos/accessibility/ax_host_service.h index b0809cde0..c3efe1738 100644 --- a/ash/accessibility/ax_host_service.h +++ b/chrome/browser/chromeos/accessibility/ax_host_service.h
@@ -2,30 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_ACCESSIBILITY_AX_HOST_SERVICE_H_ -#define ASH_ACCESSIBILITY_AX_HOST_SERVICE_H_ +#ifndef CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_AX_HOST_SERVICE_H_ +#define CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_AX_HOST_SERVICE_H_ #include <memory> -#include "ash/ash_export.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/interface_ptr_set.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/service.h" #include "ui/accessibility/ax_host_delegate.h" -#include "ui/accessibility/ax_tree_id.h" #include "ui/accessibility/mojom/ax_host.mojom.h" -namespace ash { - // Forwards accessibility events from clients in other processes that use aura // and views (e.g. the Chrome OS keyboard shortcut_viewer) to accessibility // extensions. Renderers, PDF, etc. use a different path. Created when the first // client connects over mojo. Implements AXHostDelegate by routing actions over // mojo to the remote process. -class ASH_EXPORT AXHostService : public service_manager::Service, - public ax::mojom::AXHost, - public ui::AXHostDelegate { +class AXHostService : public service_manager::Service, + public ax::mojom::AXHost, + public ui::AXHostDelegate { public: AXHostService(); ~AXHostService() override; @@ -44,7 +40,7 @@ // ax::mojom::AXHost: void SetRemoteHost(ax::mojom::AXRemoteHostPtr remote, SetRemoteHostCallback cb) override; - void HandleAccessibilityEvent(const std::string& tree_id, + void HandleAccessibilityEvent(const ui::AXTreeID& tree_id, const std::vector<ui::AXTreeUpdate>& updates, const ui::AXEvent& event) override; @@ -70,6 +66,4 @@ DISALLOW_COPY_AND_ASSIGN(AXHostService); }; -} // namespace ash - -#endif // ASH_ACCESSIBILITY_AX_HOST_SERVICE_H_ +#endif // CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_AX_HOST_SERVICE_H_
diff --git a/ash/accessibility/ax_host_service_unittest.cc b/chrome/browser/chromeos/accessibility/ax_host_service_unittest.cc similarity index 91% rename from ash/accessibility/ax_host_service_unittest.cc rename to chrome/browser/chromeos/accessibility/ax_host_service_unittest.cc index 4ecc260b..43ac4b48 100644 --- a/ash/accessibility/ax_host_service_unittest.cc +++ b/chrome/browser/chromeos/accessibility/ax_host_service_unittest.cc
@@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/accessibility/ax_host_service.h" +#include "chrome/browser/chromeos/accessibility/ax_host_service.h" -#include "ash/test/ash_test_base.h" #include "base/bind.h" #include "base/macros.h" #include "base/test/scoped_task_environment.h" @@ -12,7 +11,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/accessibility/mojom/ax_host.mojom.h" -namespace ash { namespace { class TestAXRemoteHost : ax::mojom::AXRemoteHost { @@ -53,7 +51,16 @@ DISALLOW_COPY_AND_ASSIGN(TestAXRemoteHost); }; -using AXHostServiceTest = AshTestBase; +class AXHostServiceTest : public testing::Test { + public: + AXHostServiceTest() = default; + ~AXHostServiceTest() override = default; + + private: + base::test::ScopedTaskEnvironment scoped_task_enviroment_; + + DISALLOW_COPY_AND_ASSIGN(AXHostServiceTest); +}; TEST_F(AXHostServiceTest, AddClientThenEnable) { AXHostService service; @@ -113,4 +120,3 @@ } } // namespace -} // namespace ash
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc index d5b85cb..189b11f4 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
@@ -396,8 +396,8 @@ if (out_data->role == ax::mojom::Role::kRootWebArea) { std::string package_name; if (GetProperty(node, AXStringProperty::PACKAGE_NAME, &package_name)) { - const std::string& url = - base::StringPrintf("%s/%s", package_name.c_str(), tree_id().c_str()); + const std::string& url = base::StringPrintf("%s/%s", package_name.c_str(), + tree_id().ToString().c_str()); out_data->AddStringAttribute(ax::mojom::StringAttribute::kUrl, url); } }
diff --git a/chrome/browser/chromeos/smb_client/smb_file_system.cc b/chrome/browser/chromeos/smb_client/smb_file_system.cc index d2c7302..714d43f 100644 --- a/chrome/browser/chromeos/smb_client/smb_file_system.cc +++ b/chrome/browser/chromeos/smb_client/smb_file_system.cc
@@ -40,6 +40,10 @@ // Maximum number of entries to send at a time for read directory, constexpr uint32_t kReadDirectoryMaxBatchSize = 2048; +// Capacity of the task queue. Represents how many operations can be in-flight +// over D-Bus concurrently. +constexpr size_t kTaskQueueCapacity = 2; + constexpr ProvidedFileSystemInterface::MetadataFieldMask kRequestableFields = ProvidedFileSystemInterface::MetadataField::METADATA_FIELD_IS_DIRECTORY | ProvidedFileSystemInterface::MetadataField::METADATA_FIELD_NAME | @@ -80,6 +84,26 @@ return (fields & kRequestableFields) == 0; } +filesystem::mojom::FsFileType MapEntryType(bool is_directory) { + return is_directory ? filesystem::mojom::FsFileType::DIRECTORY + : filesystem::mojom::FsFileType::REGULAR_FILE; +} + +std::unique_ptr<smb_client::TempFileManager> CreateTempFileManager() { + return std::make_unique<smb_client::TempFileManager>(); +} + +void ConvertEntries(const smbprovider::DirectoryEntryListProto& entries_proto, + storage::AsyncFileUtil::EntryList* out_entries) { + DCHECK(out_entries); + + for (const smbprovider::DirectoryEntryProto& entry : + entries_proto.entries()) { + out_entries->emplace_back(base::FilePath(entry.name()), + MapEntryType(entry.is_directory())); + } +} + // Metrics recording. void RecordReadDirectoryCount(int count) { UMA_HISTOGRAM_COUNTS_100000("NativeSmbFileShare.ReadDirectoryCount", count); @@ -93,21 +117,6 @@ namespace smb_client { -namespace { - -filesystem::mojom::FsFileType MapEntryType(bool is_directory) { - return is_directory ? filesystem::mojom::FsFileType::DIRECTORY - : filesystem::mojom::FsFileType::REGULAR_FILE; -} - -constexpr size_t kTaskQueueCapacity = 2; - -std::unique_ptr<TempFileManager> CreateTempFileManager() { - return std::make_unique<TempFileManager>(); -} - -} // namespace - using file_system_provider::AbortCallback; SmbFileSystem::SmbFileSystem( @@ -524,6 +533,40 @@ EnqueueTask(std::move(task), operation_id); } +void SmbFileSystem::StartReadDirectory( + const base::FilePath& directory_path, + OperationId operation_id, + storage::AsyncFileUtil::ReadDirectoryCallback callback) { + base::ElapsedTimer metrics_timer; + + auto reply = base::BindOnce(&SmbFileSystem::HandleStartReadDirectoryCallback, + AsWeakPtr(), std::move(callback), operation_id, + std::move(metrics_timer)); + + SmbTask task = base::BindOnce(&SmbProviderClient::StartReadDirectory, + GetWeakSmbProviderClient(), GetMountId(), + directory_path, std::move(reply)); + + EnqueueTask(std::move(task), operation_id); +} + +void SmbFileSystem::ContinueReadDirectory( + OperationId operation_id, + int32_t read_dir_token, + storage::AsyncFileUtil::ReadDirectoryCallback callback, + int entries_count, + base::ElapsedTimer metrics_timer) { + auto reply = + base::BindOnce(&SmbFileSystem::HandleContinueReadDirectoryCallback, + AsWeakPtr(), std::move(callback), operation_id, + read_dir_token, entries_count, std::move(metrics_timer)); + SmbTask task = base::BindOnce(&SmbProviderClient::ContinueReadDirectory, + GetWeakSmbProviderClient(), GetMountId(), + read_dir_token, std::move(reply)); + + EnqueueTask(std::move(task), operation_id); +} + void SmbFileSystem::HandleRequestReadDirectoryCallback( storage::AsyncFileUtil::ReadDirectoryCallback callback, const base::ElapsedTimer& metrics_timer, @@ -631,6 +674,71 @@ std::move(callback).Run(TranslateToFileError(error)); } +void SmbFileSystem::HandleStartReadDirectoryCallback( + storage::AsyncFileUtil::ReadDirectoryCallback callback, + OperationId operation_id, + base::ElapsedTimer metrics_timer, + smbprovider::ErrorType error, + int32_t read_dir_token, + const smbprovider::DirectoryEntryListProto& entries) { + task_queue_.TaskFinished(); + + int entries_count = 0; + ProcessReadDirectoryResults(std::move(callback), operation_id, read_dir_token, + error, entries, entries_count, + std::move(metrics_timer)); +} + +void SmbFileSystem::HandleContinueReadDirectoryCallback( + storage::AsyncFileUtil::ReadDirectoryCallback callback, + OperationId operation_id, + int32_t read_dir_token, + int entries_count, + base::ElapsedTimer metrics_timer, + smbprovider::ErrorType error, + const smbprovider::DirectoryEntryListProto& entries) { + task_queue_.TaskFinished(); + + ProcessReadDirectoryResults(std::move(callback), operation_id, read_dir_token, + error, entries, entries_count, + std::move(metrics_timer)); +} + +void SmbFileSystem::ProcessReadDirectoryResults( + storage::AsyncFileUtil::ReadDirectoryCallback callback, + OperationId operation_id, + int32_t read_dir_token, + smbprovider::ErrorType error, + const smbprovider::DirectoryEntryListProto& entries, + int entries_count, + base::ElapsedTimer metrics_timer) { + storage::AsyncFileUtil::EntryList entry_list; + + if (error != smbprovider::ERROR_OPERATION_PENDING && + error != smbprovider::ERROR_OK) { + callback.Run(TranslateToFileError(error), entry_list, false /* has_more */); + } + + ConvertEntries(entries, &entry_list); + entries_count += entry_list.size(); + + const bool has_more = (error == smbprovider::ERROR_OPERATION_PENDING); + + // Run |callback| with the next batch of results; + callback.Run(base::File::FILE_OK, entry_list, has_more); + + if (has_more) { + // There are more directory entries to read. + ContinueReadDirectory(operation_id, read_dir_token, callback, entries_count, + std::move(metrics_timer)); + return; + } + + // Read Directory is complete, record metrics. + RecordReadDirectoryCount(entries_count); + RecordReadDirectoryDuration(metrics_timer.Elapsed()); +} + AbortCallback SmbFileSystem::HandleSyncRedundantGetMetadata( ProvidedFileSystemInterface::MetadataFieldMask fields, ProvidedFileSystemInterface::GetMetadataCallback callback) {
diff --git a/chrome/browser/chromeos/smb_client/smb_file_system.h b/chrome/browser/chromeos/smb_client/smb_file_system.h index 528c5df..23929cb 100644 --- a/chrome/browser/chromeos/smb_client/smb_file_system.h +++ b/chrome/browser/chromeos/smb_client/smb_file_system.h
@@ -207,6 +207,23 @@ int32_t copy_token, storage::AsyncFileUtil::StatusCallback callback); + // Starts a ReadDirectory operation for |directory_path| with the OperationId + // |operation_id|. + void StartReadDirectory( + const base::FilePath& directory_path, + OperationId operation_id, + storage::AsyncFileUtil::ReadDirectoryCallback callback); + + // Continues a ReadDirectory corresponding to |operation_id| and + // |read_dir_token|. |entries_count| and |metrics_timer| are used for metrics + // recording. + void ContinueReadDirectory( + OperationId operation_id, + int32_t read_dir_token, + storage::AsyncFileUtil::ReadDirectoryCallback callback, + int entires_count, + base::ElapsedTimer metrics_timer); + void HandleRequestUnmountCallback( storage::AsyncFileUtil::StatusCallback callback, smbprovider::ErrorType error); @@ -267,6 +284,32 @@ int32_t copy_token, smbprovider::ErrorType error); + void HandleStartReadDirectoryCallback( + storage::AsyncFileUtil::ReadDirectoryCallback callback, + OperationId operation_id, + base::ElapsedTimer metrics_timer, + smbprovider::ErrorType error, + int32_t read_dir_token, + const smbprovider::DirectoryEntryListProto& entries); + + void HandleContinueReadDirectoryCallback( + storage::AsyncFileUtil::ReadDirectoryCallback callback, + OperationId operation_id, + int32_t read_dir_token, + int entries_count, + base::ElapsedTimer metrics_timer, + smbprovider::ErrorType error, + const smbprovider::DirectoryEntryListProto& entries); + + void ProcessReadDirectoryResults( + storage::AsyncFileUtil::ReadDirectoryCallback callback, + OperationId operation_id, + int32_t read_dir_token, + smbprovider::ErrorType error, + const smbprovider::DirectoryEntryListProto& entries, + int entries_count, + base::ElapsedTimer metrics_timer); + int32_t GetMountId() const; SmbProviderClient* GetSmbProviderClient() const;
diff --git a/chrome/browser/content_settings/sound_content_setting_observer.cc b/chrome/browser/content_settings/sound_content_setting_observer.cc index b42f03a..1cab9e1 100644 --- a/chrome/browser/content_settings/sound_content_setting_observer.cc +++ b/chrome/browser/content_settings/sound_content_setting_observer.cc
@@ -138,10 +138,6 @@ if (!mute && reason == TabMutedReason::MEDIA_CAPTURE) return; - // Do not unmute if we're muted due to audio indicator. - if (!mute && reason == TabMutedReason::AUDIO_INDICATOR) - return; - // Do not override the decisions of an extension. if (reason == TabMutedReason::EXTENSION) return;
diff --git a/chrome/browser/content_settings/sound_content_setting_observer_unittest.cc b/chrome/browser/content_settings/sound_content_setting_observer_unittest.cc index eb74d3a1..3ef95ad 100644 --- a/chrome/browser/content_settings/sound_content_setting_observer_unittest.cc +++ b/chrome/browser/content_settings/sound_content_setting_observer_unittest.cc
@@ -11,7 +11,6 @@ #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/recently_audible_helper.h" -#include "chrome/common/chrome_switches.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/ukm/content/source_url_recorder.h" @@ -211,19 +210,6 @@ EXPECT_TRUE(web_contents()->IsAudioMuted()); } -TEST_F(SoundContentSettingObserverTest, DontUnmuteWhenMutedByAudioIndicator) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableTabAudioMuting); - EXPECT_FALSE(web_contents()->IsAudioMuted()); - - SetMuteStateForReason(true, TabMutedReason::AUDIO_INDICATOR); - EXPECT_TRUE(web_contents()->IsAudioMuted()); - - // Navigating to a new URL should not unmute the tab muted by audio indicator. - NavigateAndCommit(GURL(kURL2)); - EXPECT_TRUE(web_contents()->IsAudioMuted()); -} - TEST_F(SoundContentSettingObserverTest, DontUnmuteChromeTabWhenMuted) { NavigateAndCommit(GURL(kChromeURL)); EXPECT_FALSE(web_contents()->IsAudioMuted());
diff --git a/chrome/browser/devtools/devtools_eye_dropper.cc b/chrome/browser/devtools/devtools_eye_dropper.cc index 3bb3aa8..3a72b4b 100644 --- a/chrome/browser/devtools/devtools_eye_dropper.cc +++ b/chrome/browser/devtools/devtools_eye_dropper.cc
@@ -23,9 +23,9 @@ #include "third_party/blink/public/platform/web_input_event.h" #include "third_party/blink/public/platform/web_mouse_event.h" #include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkColorSpaceXform.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkPath.h" +#include "third_party/skia/include/core/SkPixmap.h" #include "ui/gfx/geometry/size_conversions.h" DevToolsEyeDropper::DevToolsEyeDropper(content::WebContents* web_contents, @@ -128,13 +128,9 @@ } SkColor sk_color = frame_.getColor(last_cursor_x_, last_cursor_y_); - uint8_t rgba_color[4] = { - SkColorGetR(sk_color), SkColorGetG(sk_color), SkColorGetB(sk_color), - SkColorGetA(sk_color), - }; - // The picked colors are expected to be sRGB. Create a color transform from - // |frame_|'s color space to sRGB. + // The picked colors are expected to be sRGB. Convert from |frame_|'s color + // space to sRGB. // TODO(ccameron): We don't actually know |frame_|'s color space, so just // use |host_|'s current display's color space. This will almost always be // the right color space, but is sloppy. @@ -142,16 +138,18 @@ content::ScreenInfo screen_info; host_->GetScreenInfo(&screen_info); gfx::ColorSpace frame_color_space = screen_info.color_space; - std::unique_ptr<SkColorSpaceXform> frame_color_space_to_srgb_xform = - SkColorSpaceXform::New(frame_color_space.ToSkColorSpace().get(), - SkColorSpace::MakeSRGB().get()); - if (frame_color_space_to_srgb_xform) { - bool xform_apply_result = frame_color_space_to_srgb_xform->apply( - SkColorSpaceXform::kRGBA_8888_ColorFormat, rgba_color, - SkColorSpaceXform::kRGBA_8888_ColorFormat, rgba_color, 1, - kUnpremul_SkAlphaType); - DCHECK(xform_apply_result); - } + + SkPixmap pm( + SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, + frame_color_space.ToSkColorSpace()), + &sk_color, sizeof(sk_color)); + + uint8_t rgba_color[4]; + bool ok = pm.readPixels( + SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kUnpremul_SkAlphaType, + SkColorSpace::MakeSRGB()), + rgba_color, sizeof(rgba_color)); + DCHECK(ok); callback_.Run(rgba_color[0], rgba_color[1], rgba_color[2], rgba_color[3]); }
diff --git a/chrome/browser/download/download_history.cc b/chrome/browser/download/download_history.cc index 3b5f2fa..3fe7a1b 100644 --- a/chrome/browser/download/download_history.cc +++ b/chrome/browser/download/download_history.cc
@@ -35,6 +35,7 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/task/post_task.h" +#include "build/build_config.h" #include "chrome/browser/download/download_crx_util.h" #include "components/download/public/common/download_features.h" #include "components/download/public/common/download_item.h" @@ -313,11 +314,20 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(notifier_.GetManager()); + int cancelled_download_cleared_from_history = 0; for (InfoVector::const_iterator it = infos->begin(); it != infos->end(); ++it) { loading_id_ = history::ToContentDownloadId(it->id); download::DownloadItem::DownloadState history_download_state = history::ToContentDownloadState(it->state); +#if defined(OS_ANDROID) + // Clean up cancelled download on Android. + if (history_download_state == download::DownloadItem::CANCELLED) { + ScheduleRemoveDownload(it->id); + ++cancelled_download_cleared_from_history; + continue; + } +#endif // defined(OS_ANDROID) download::DownloadItem* item = notifier_.GetManager()->CreateDownloadItem( it->guid, loading_id_, it->current_path, it->target_path, it->url_chain, it->referrer_url, it->site_url, it->tab_url, it->tab_referrer_url, @@ -351,6 +361,12 @@ ++history_size_; } + if (cancelled_download_cleared_from_history > 0) { + UMA_HISTOGRAM_COUNTS_1000( + "MobileDownload.CancelledDownloadRemovedFromHistory", + cancelled_download_cleared_from_history); + } + // Indicate that the history db is initialized. notifier_.GetManager()->PostInitialization( content::DownloadManager::DOWNLOAD_INITIALIZATION_DEPENDENCY_HISTORY_DB);
diff --git a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc index 19d5c616..08c2626a 100644 --- a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc +++ b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -303,8 +303,8 @@ std::unique_ptr<Params> params(Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); - content::RenderFrameHost* rfh = - content::RenderFrameHost::FromAXTreeID(params->tree_id); + content::RenderFrameHost* rfh = content::RenderFrameHost::FromAXTreeID( + ui::AXTreeID::FromString(params->tree_id)); if (!rfh) return RespondNow(Error("unable to load tab")); @@ -324,7 +324,7 @@ AutomationInternalPerformActionFunction::ConvertToAXActionData( api::automation_internal::PerformAction::Params* params, ui::AXActionData* action) { - action->target_tree_id = params->args.tree_id; + action->target_tree_id = ui::AXTreeID::FromString(params->args.tree_id); action->source_extension_id = extension_id(); action->target_node_id = params->args.automation_node_id; int* request_id = params->args.request_id.get(); @@ -477,7 +477,7 @@ EXTENSION_FUNCTION_VALIDATE(params.get()); ui::AXTreeIDRegistry* registry = ui::AXTreeIDRegistry::GetInstance(); ui::AXHostDelegate* delegate = - registry->GetHostDelegate(params->args.tree_id); + registry->GetHostDelegate(ui::AXTreeID::FromString(params->args.tree_id)); if (delegate) { #if defined(USE_AURA) ui::AXActionData data; @@ -491,8 +491,8 @@ " platform does not support desktop automation")); #endif // defined(USE_AURA) } - content::RenderFrameHost* rfh = - content::RenderFrameHost::FromAXTreeID(params->args.tree_id); + content::RenderFrameHost* rfh = content::RenderFrameHost::FromAXTreeID( + ui::AXTreeID::FromString(params->args.tree_id)); if (!rfh) return RespondNow(Error("Ignoring action on destroyed node")); @@ -563,8 +563,8 @@ std::unique_ptr<Params> params(Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); - content::RenderFrameHost* rfh = - content::RenderFrameHost::FromAXTreeID(params->args.tree_id); + content::RenderFrameHost* rfh = content::RenderFrameHost::FromAXTreeID( + ui::AXTreeID::FromString(params->args.tree_id)); if (!rfh) { return RespondNow( Error("domQuerySelector query sent on non-web or destroyed tree."));
diff --git a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc index a36c624..8d1c434 100644 --- a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc +++ b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc
@@ -151,6 +151,14 @@ std::unique_ptr<cryptotoken_private::CanAppIdGetAttestation::Params> params = cryptotoken_private::CanAppIdGetAttestation::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(params); + + const GURL origin_url(params->options.origin); + if (!origin_url.is_valid()) { + return RespondNow(Error(extensions::ErrorUtils::FormatErrorMessage( + "Security origin * is not a valid URL", params->options.origin))); + } + const url::Origin origin(url::Origin::Create(origin_url)); + const std::string& app_id = params->options.app_id; // If the appId is permitted by the enterprise policy then no permission @@ -194,7 +202,6 @@ } // The created AttestationPermissionRequest deletes itself once complete. - const url::Origin origin(url::Origin::Create(app_id_url)); permission_request_manager->AddRequest(NewAttestationPermissionRequest( origin, base::BindOnce(
diff --git a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc index 519623a..0500f7e 100644 --- a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc +++ b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc
@@ -208,6 +208,7 @@ base::Value::DictStorage dict; dict.emplace("appId", std::make_unique<base::Value>(app_id)); dict.emplace("tabId", std::make_unique<base::Value>(tab_id_)); + dict.emplace("origin", std::make_unique<base::Value>(app_id)); auto args = std::make_unique<base::Value>(base::Value::Type::LIST); args->GetList().emplace_back(std::move(dict)); auto args_list = base::ListValue::From(std::move(args));
diff --git a/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc b/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc index 2905518c..089c9f2 100644 --- a/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc +++ b/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc
@@ -30,6 +30,7 @@ #include "storage/browser/quota/quota_manager.h" #include "storage/common/fileapi/file_system_types.h" #include "storage/common/fileapi/file_system_util.h" +#include "url/origin.h" using content::BrowserContext; using content::BrowserThread; @@ -335,7 +336,7 @@ FROM_HERE, {BrowserThread::IO}, BindOnce( &storage::QuotaManager::GetUsageAndQuotaForWebApps, quota_manager, - source_url().GetOrigin(), + url::Origin::Create(source_url()), storage::FileSystemTypeToQuotaStorageType(file_system_url.type()), Bind(&SyncFileSystemGetUsageAndQuotaFunction::DidGetUsageAndQuota, this)));
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc index 3929059b..f75bb02 100644 --- a/chrome/browser/extensions/api/tabs/tabs_api.cc +++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -54,7 +54,6 @@ #include "chrome/browser/ui/tabs/tab_utils.h" #include "chrome/browser/ui/window_sizer/window_sizer.h" #include "chrome/browser/web_applications/components/web_app_helpers.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/api/tabs.h" #include "chrome/common/extensions/api/windows.h" #include "chrome/common/extensions/extension_constants.h" @@ -1313,23 +1312,11 @@ tab_index = tab_strip->GetIndexOfWebContents(contents); } - if (params->update_properties.muted.get()) { - TabMutedResult tab_muted_result = chrome::SetTabAudioMuted( - contents, *params->update_properties.muted, - TabMutedReason::EXTENSION, extension()->id()); - - switch (tab_muted_result) { - case TabMutedResult::SUCCESS: - break; - case TabMutedResult::FAIL_NOT_ENABLED: - return RespondNow(Error(ErrorUtils::FormatErrorMessage( - tabs_constants::kCannotUpdateMuteDisabled, - base::IntToString(tab_id), ::switches::kEnableTabAudioMuting))); - case TabMutedResult::FAIL_TABCAPTURE: - return RespondNow(Error(ErrorUtils::FormatErrorMessage( - tabs_constants::kCannotUpdateMuteCaptured, - base::IntToString(tab_id)))); - } + if (params->update_properties.muted.get() && + !chrome::SetTabAudioMuted(contents, *params->update_properties.muted, + TabMutedReason::EXTENSION, extension()->id())) { + return RespondNow(Error(ErrorUtils::FormatErrorMessage( + tabs_constants::kCannotUpdateMuteCaptured, base::IntToString(tab_id)))); } if (params->update_properties.opener_tab_id.get()) {
diff --git a/chrome/browser/extensions/api/tabs/tabs_constants.cc b/chrome/browser/extensions/api/tabs/tabs_constants.cc index d4861be..a68b6ee0 100644 --- a/chrome/browser/extensions/api/tabs/tabs_constants.cc +++ b/chrome/browser/extensions/api/tabs/tabs_constants.cc
@@ -104,8 +104,6 @@ const char kInvalidWindowTypeError[] = "Invalid value for type"; const char kInvalidWindowStateError[] = "Invalid value for state"; const char kScreenshotsDisabled[] = "Taking screenshots has been disabled"; -const char kCannotUpdateMuteDisabled[] = - "Failed to update mute state for tab *, --* must be enabled"; const char kCannotUpdateMuteCaptured[] = "Cannot update mute state for tab *, tab has audio or video currently " "being captured";
diff --git a/chrome/browser/extensions/api/tabs/tabs_constants.h b/chrome/browser/extensions/api/tabs/tabs_constants.h index 101362e7..bfb4386 100644 --- a/chrome/browser/extensions/api/tabs/tabs_constants.h +++ b/chrome/browser/extensions/api/tabs/tabs_constants.h
@@ -101,7 +101,6 @@ extern const char kInvalidWindowTypeError[]; extern const char kInvalidWindowStateError[]; extern const char kScreenshotsDisabled[]; -extern const char kCannotUpdateMuteDisabled[]; extern const char kCannotUpdateMuteCaptured[]; extern const char kCannotDetermineLanguageOfUnloadedTab[]; extern const char kMissingLockWindowFullscreenPrivatePermission[];
diff --git a/chrome/browser/extensions/extension_special_storage_policy.cc b/chrome/browser/extensions/extension_special_storage_policy.cc index 579e4ad..419b80a14 100644 --- a/chrome/browser/extensions/extension_special_storage_policy.cc +++ b/chrome/browser/extensions/extension_special_storage_policy.cc
@@ -35,6 +35,7 @@ #include "extensions/common/permissions/permissions_data.h" #include "storage/browser/quota/quota_manager.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" +#include "url/origin.h" using content::BrowserThread; using extensions::APIPermission; @@ -73,7 +74,8 @@ FROM_HERE, base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}), base::BindOnce(&storage::QuotaManager::GetUsageAndQuotaForWebApps, - partition->GetQuotaManager(), launch_url, + partition->GetQuotaManager(), + url::Origin::Create(launch_url), blink::mojom::StorageType::kPersistent, base::Bind(&ReportQuotaUsage))); }
diff --git a/chrome/browser/extensions/extension_storage_monitor.cc b/chrome/browser/extensions/extension_storage_monitor.cc index 7aa193d..4015427 100644 --- a/chrome/browser/extensions/extension_storage_monitor.cc +++ b/chrome/browser/extensions/extension_storage_monitor.cc
@@ -41,6 +41,8 @@ #include "ui/message_center/public/cpp/message_center_constants.h" #include "ui/message_center/public/cpp/notification.h" #include "ui/message_center/public/cpp/notifier_id.h" +#include "url/gurl.h" +#include "url/origin.h" using content::BrowserThread; @@ -113,7 +115,7 @@ ExtensionStorageMonitorIOHelper* io_helper, const std::string& extension_id, scoped_refptr<storage::QuotaManager> quota_manager, - const GURL& origin, + const url::Origin& origin, int64_t next_threshold, base::TimeDelta rate, bool should_uma) @@ -181,7 +183,7 @@ void StartObservingForExtension( scoped_refptr<storage::QuotaManager> quota_manager, const std::string& extension_id, - const GURL& site_url, + const url::Origin& site_origin, int64_t next_threshold, const base::TimeDelta& rate, bool should_uma) { @@ -192,7 +194,7 @@ storage_observers_[extension_id] = std::make_unique<SingleExtensionStorageObserver>( - this, extension_id, std::move(quota_manager), site_url.GetOrigin(), + this, extension_id, std::move(quota_manager), site_origin, next_threshold, rate, should_uma); } @@ -498,9 +500,11 @@ scoped_refptr<storage::QuotaManager> quota_manager( storage_partition->GetQuotaManager()); - GURL storage_origin(site_url.GetOrigin()); - if (extension->is_hosted_app()) - storage_origin = AppLaunchInfo::GetLaunchWebURL(extension).GetOrigin(); + url::Origin storage_origin = url::Origin::Create(site_url); + if (extension->is_hosted_app()) { + storage_origin = + url::Origin::Create(AppLaunchInfo::GetLaunchWebURL(extension)); + } // Don't give a threshold if we're not enforcing. int next_threshold =
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc index 887f2cad..4a307f1 100644 --- a/chrome/browser/extensions/extension_tab_util.cc +++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -476,12 +476,11 @@ std::unique_ptr<api::tabs::MutedInfo> ExtensionTabUtil::CreateMutedInfo( content::WebContents* contents) { DCHECK(contents); - std::unique_ptr<api::tabs::MutedInfo> info(new api::tabs::MutedInfo); + auto info = std::make_unique<api::tabs::MutedInfo>(); info->muted = contents->IsAudioMuted(); switch (chrome::GetTabAudioMutedReason(contents)) { case TabMutedReason::NONE: break; - case TabMutedReason::AUDIO_INDICATOR: case TabMutedReason::CONTENT_SETTING: case TabMutedReason::CONTENT_SETTING_CHROME: case TabMutedReason::CONTEXT_MENU: @@ -492,8 +491,9 @@ break; case TabMutedReason::EXTENSION: info->reason = api::tabs::MUTED_INFO_REASON_EXTENSION; - info->extension_id.reset( - new std::string(chrome::GetExtensionIdForMutedTab(contents))); + info->extension_id = std::make_unique<std::string>( + LastMuteMetadata::FromWebContents(contents)->extension_id); + DCHECK(!info->extension_id->empty()); break; } return info;
diff --git a/chrome/browser/extensions/installed_loader.cc b/chrome/browser/extensions/installed_loader.cc index bde6240..b6f311fc 100644 --- a/chrome/browser/extensions/installed_loader.cc +++ b/chrome/browser/extensions/installed_loader.cc
@@ -20,11 +20,13 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/load_error_reporter.h" +#include "chrome/browser/extensions/scripting_permissions_modifier.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/chrome_manifest_url_handlers.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" +#include "content/public/common/url_constants.h" #include "extensions/browser/event_router.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" @@ -334,6 +336,10 @@ RecordExtensionsMetrics(); } +void InstalledLoader::RecordExtensionsMetricsForTesting() { + RecordExtensionsMetrics(); +} + void InstalledLoader::RecordExtensionsMetrics() { Profile* profile = extension_service_->profile(); @@ -538,6 +544,38 @@ if (!ManifestURL::UpdatesFromGallery(extension)) ++off_store_item_count; + + ScriptingPermissionsModifier scripting_modifier(profile, extension); + // NOTE: CanAffectExtension() returns false in all cases when the + // RuntimeHostPermissions feature is disabled. + if (scripting_modifier.CanAffectExtension()) { + bool extension_has_withheld_hosts = + scripting_modifier.HasWithheldHostPermissions(); + UMA_HISTOGRAM_BOOLEAN( + "Extensions.RuntimeHostPermissions.ExtensionHasWithheldHosts", + extension_has_withheld_hosts); + if (extension_has_withheld_hosts) { + // Record the number of granted hosts if and only if the extension + // has withheld host permissions. This lets us equate "0" granted + // hosts to "on click only". + size_t num_granted_hosts = 0; + for (const auto& pattern : extension->permissions_data() + ->active_permissions() + .effective_hosts()) { + // Ignore chrome:-scheme patterns (like chrome://favicon); these + // aren't withheld, and thus shouldn't be considered "granted". + if (pattern.scheme() != content::kChromeUIScheme) + ++num_granted_hosts; + } + // TODO(devlin): This only takes into account the granted hosts that + // were also requested by the extension (because it looks at the active + // permissions). We could potentially also record the granted hosts that + // were explicitly not requested. + UMA_HISTOGRAM_COUNTS_100( + "Extensions.RuntimeHostPermissions.GrantedHostCount", + num_granted_hosts); + } + } } const ExtensionSet& disabled_extensions =
diff --git a/chrome/browser/extensions/installed_loader.h b/chrome/browser/extensions/installed_loader.h index 755e325..6d2714f 100644 --- a/chrome/browser/extensions/installed_loader.h +++ b/chrome/browser/extensions/installed_loader.h
@@ -28,6 +28,10 @@ // Loads all installed extensions (used by startup and testing code). void LoadAllExtensions(); + // Allows tests to verify metrics without needing to go through + // LoadAllExtensions(). + void RecordExtensionsMetricsForTesting(); + private: // Returns the flags that should be used with Extension::Create() for an // extension that is already installed.
diff --git a/chrome/browser/extensions/installed_loader_unittest.cc b/chrome/browser/extensions/installed_loader_unittest.cc new file mode 100644 index 0000000..c4a31d8 --- /dev/null +++ b/chrome/browser/extensions/installed_loader_unittest.cc
@@ -0,0 +1,146 @@ +// 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/extensions/installed_loader.h" + +#include "base/macros.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_service_test_base.h" +#include "chrome/browser/extensions/permissions_updater.h" +#include "chrome/browser/extensions/scripting_permissions_modifier.h" +#include "chrome/browser/profiles/profile.h" +#include "extensions/common/extension_builder.h" +#include "extensions/common/extension_features.h" + +namespace extensions { + +namespace { + +constexpr const char kHasWithheldHostsHistogram[] = + "Extensions.RuntimeHostPermissions.ExtensionHasWithheldHosts"; +constexpr const char kGrantedHostCountHistogram[] = + "Extensions.RuntimeHostPermissions.GrantedHostCount"; + +} // namespace + +class InstalledLoaderUnitTest : public ExtensionServiceTestBase { + public: + InstalledLoaderUnitTest() {} + ~InstalledLoaderUnitTest() override = default; + + void SetUp() override { + ExtensionServiceTestBase::SetUp(); + InitializeEmptyExtensionService(); + } + + const Extension* AddExtension(); + + private: + DISALLOW_COPY_AND_ASSIGN(InstalledLoaderUnitTest); +}; + +const Extension* InstalledLoaderUnitTest::AddExtension() { + // Metrics aren't recorded for unpacked extensions, so we need to make sure + // the extension has an INTERNAL location. + constexpr Manifest::Location kManifestLocation = Manifest::INTERNAL; + scoped_refptr<const Extension> extension = ExtensionBuilder("test") + .AddPermissions({"<all_urls>"}) + .SetLocation(kManifestLocation) + .Build(); + PermissionsUpdater updater(profile()); + updater.InitializePermissions(extension.get()); + updater.GrantActivePermissions(extension.get()); + service()->AddExtension(extension.get()); + + return extension.get(); +} + +TEST_F(InstalledLoaderUnitTest, + RuntimeHostPermissions_Metrics_FeatureDisabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature( + extensions_features::kRuntimeHostPermissions); + + AddExtension(); + + base::HistogramTester histograms; + InstalledLoader loader(service()); + loader.RecordExtensionsMetricsForTesting(); + + // No metrics should be recorded when the feature is disabled. + histograms.ExpectTotalCount(kHasWithheldHostsHistogram, 0); + histograms.ExpectTotalCount(kGrantedHostCountHistogram, 0); +} + +TEST_F(InstalledLoaderUnitTest, + RuntimeHostPermissions_Metrics_HasWithheldHosts_False) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + extensions_features::kRuntimeHostPermissions); + + AddExtension(); + + base::HistogramTester histograms; + InstalledLoader loader(service()); + loader.RecordExtensionsMetricsForTesting(); + + // The extension didn't have withheld hosts, so a single `false` record + // should be present. + histograms.ExpectUniqueSample(kHasWithheldHostsHistogram, false, 1); + // Granted host counts should only be recorded if the extension had withheld + // hosts. + histograms.ExpectTotalCount(kGrantedHostCountHistogram, 0); +} + +TEST_F(InstalledLoaderUnitTest, + RuntimeHostPermissions_Metrics_HasWithheldHosts_True) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + extensions_features::kRuntimeHostPermissions); + + const Extension* extension = AddExtension(); + ScriptingPermissionsModifier(profile(), extension) + .SetWithholdHostPermissions(true); + + base::HistogramTester histograms; + InstalledLoader loader(service()); + loader.RecordExtensionsMetricsForTesting(); + + // The extension had withheld hosts, so a single `true` record should be + // present. + histograms.ExpectUniqueSample(kHasWithheldHostsHistogram, true, 1); + // There were no granted hosts, so a single `0` record should be present. + constexpr int kGrantedHostCount = 0; + constexpr int kEmitCount = 1; + histograms.ExpectUniqueSample(kGrantedHostCountHistogram, kGrantedHostCount, + kEmitCount); +} + +TEST_F(InstalledLoaderUnitTest, + RuntimeHostPermissions_Metrics_GrantedHostCount) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + extensions_features::kRuntimeHostPermissions); + + const Extension* extension = AddExtension(); + ScriptingPermissionsModifier modifier(profile(), extension); + modifier.SetWithholdHostPermissions(true); + modifier.GrantHostPermission(GURL("https://example.com/")); + modifier.GrantHostPermission(GURL("https://chromium.org/")); + + base::HistogramTester histograms; + InstalledLoader loader(service()); + loader.RecordExtensionsMetricsForTesting(); + + histograms.ExpectUniqueSample(kHasWithheldHostsHistogram, true, 1); + // The extension had granted hosts, so a single `2` record should be present. + constexpr int kGrantedHostCount = 2; + constexpr int kEmitCount = 1; + histograms.ExpectUniqueSample(kGrantedHostCountHistogram, kGrantedHostCount, + kEmitCount); +} + +} // namespace extensions
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index a787ba6b..0b6ae8f 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1276,12 +1276,19 @@ "Elides the path, query, and ref of suggested URLs in the Omnibox " "dropdown."; -const char kOmniboxUIHideSteadyStateUrlSchemeAndSubdomainsName[] = - "Omnibox UI Hide Steady-State URL Scheme and Trivial Subdomains"; -const char kOmniboxUIHideSteadyStateUrlSchemeAndSubdomainsDescription[] = - "In the Omnibox, hide the scheme and trivial subdomains from steady state " - "displayed URLs. Hidden portions are restored during editing. For Mac, " - "this flag will have no effect unless MacViews is enabled."; +const char kOmniboxUIHideSteadyStateUrlSchemeName[] = + "Omnibox UI Hide Steady-State URL Scheme"; +const char kOmniboxUIHideSteadyStateUrlSchemeDescription[] = + "In the omnibox, hide the scheme from steady state displayed URLs. It is " + "restored during editing. For Mac, this flag will have no effect unless " + "MacViews is enabled."; + +const char kOmniboxUIHideSteadyStateUrlTrivialSubdomainsName[] = + "Omnibox UI Hide Steady-State URL Trivial Subdomains"; +const char kOmniboxUIHideSteadyStateUrlTrivialSubdomainsDescription[] = + "In the omnibox, hide trivial subdomains from steady state displayed URLs. " + "Hidden portions are restored during editing. For Mac, this flag will have " + "no effect unless MacViews is enabled."; const char kOmniboxUIJogTextfieldOnPopupName[] = "Omnibox UI Jog Textfield on Popup"; @@ -1803,12 +1810,6 @@ "keyboard shortcuts and have the events routed directly to the website " "when in fullscreen mode."; -const char kTabAudioMutingName[] = "Tab audio muting UI control"; -const char kTabAudioMutingDescription[] = - "When enabled, the audio indicators in the tab strip double as tab audio " - "mute controls. This also adds commands in the tab context menu for " - "quickly muting multiple selected tabs."; - const char kTabsInCbdName[] = "Enable tabs for the Clear Browsing Data dialog."; const char kTabsInCbdDescription[] = "Enables a basic and an advanced tab for the Clear Browsing Data dialog.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 3474b4a..1ee435a 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -795,8 +795,11 @@ extern const char kOmniboxUIElideSuggestionUrlAfterHostName[]; extern const char kOmniboxUIElideSuggestionUrlAfterHostDescription[]; -extern const char kOmniboxUIHideSteadyStateUrlSchemeAndSubdomainsName[]; -extern const char kOmniboxUIHideSteadyStateUrlSchemeAndSubdomainsDescription[]; +extern const char kOmniboxUIHideSteadyStateUrlSchemeName[]; +extern const char kOmniboxUIHideSteadyStateUrlSchemeDescription[]; + +extern const char kOmniboxUIHideSteadyStateUrlTrivialSubdomainsName[]; +extern const char kOmniboxUIHideSteadyStateUrlTrivialSubdomainsDescription[]; extern const char kOmniboxUIJogTextfieldOnPopupName[]; extern const char kOmniboxUIJogTextfieldOnPopupDescription[]; @@ -1099,9 +1102,6 @@ extern const char kSysInternalsName[]; extern const char kSysInternalsDescription[]; -extern const char kTabAudioMutingName[]; -extern const char kTabAudioMutingDescription[]; - extern const char kTabModalJsDialogName[]; extern const char kTabModalJsDialogDescription[];
diff --git a/chrome/browser/google/google_brand.cc b/chrome/browser/google/google_brand.cc index f5399e7..611ab30 100644 --- a/chrome/browser/google/google_brand.cc +++ b/chrome/browser/google/google_brand.cc
@@ -93,6 +93,15 @@ #endif +bool GetRlzBrand(std::string* brand) { +#if defined(OS_CHROMEOS) + brand->assign(google_brand::chromeos::GetRlzBrand()); + return true; +#else + return GetBrand(brand); +#endif +} + bool IsOrganic(const std::string& brand) { #if defined(OS_MACOSX) if (brand.empty()) {
diff --git a/chrome/browser/google/google_brand.h b/chrome/browser/google/google_brand.h index 6b37a80..d1dbe8e 100644 --- a/chrome/browser/google/google_brand.h +++ b/chrome/browser/google/google_brand.h
@@ -26,6 +26,11 @@ // install. Returns false if the information is not available. bool GetReactivationBrand(std::string* brand); +// The same as GetBrand() on non-ChromeOS platforms. On ChromeOS, returns a +// variation of the brand code based on enrollment type. +// TODO(crbug.com/888725): Rename this to GetBrand and replace the current one. +bool GetRlzBrand(std::string* brand); + // True if a build is strictly organic, according to its brand code. bool IsOrganic(const std::string& brand);
diff --git a/chrome/browser/google/google_brand_chromeos.cc b/chrome/browser/google/google_brand_chromeos.cc index c42aab9..3e81fb92 100644 --- a/chrome/browser/google/google_brand_chromeos.cc +++ b/chrome/browser/google/google_brand_chromeos.cc
@@ -9,8 +9,11 @@ #include "base/strings/string_util.h" #include "base/task/post_task.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" +#include "chrome/browser/google/google_brand_code_map_chromeos.h" #include "chrome/common/pref_names.h" #include "chromeos/system/statistics_provider.h" +#include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/prefs/pref_service.h" #include "content/public/browser/browser_thread.h" @@ -63,6 +66,18 @@ return g_browser_process->local_state()->GetString(prefs::kRLZBrand); } +std::string GetRlzBrand() { + policy::BrowserPolicyConnectorChromeOS* connector = + g_browser_process->platform_part()->browser_policy_connector_chromeos(); + base::Optional<policy::MarketSegment> market_segment; + if (connector->IsEnterpriseManaged()) + market_segment = connector->GetEnterpriseMarketSegment(); + // The rlz brand code may change over time (e.g. when device goes from + // unenrolled to enrolled status in OOBE). Prefer not to save it in pref to + // avoid using outdated value. + return GetRlzBrandCode(GetBrand(), market_segment); +} + void InitBrand(const base::Closure& callback) { ::chromeos::system::StatisticsProvider* provider = ::chromeos::system::StatisticsProvider::GetInstance();
diff --git a/chrome/browser/google/google_brand_chromeos.h b/chrome/browser/google/google_brand_chromeos.h index 51e1afd..beb2146 100644 --- a/chrome/browser/google/google_brand_chromeos.h +++ b/chrome/browser/google/google_brand_chromeos.h
@@ -16,6 +16,10 @@ // partner. Returns empty string if the information is not available. std::string GetBrand(); +// Returns a variation of the brand code based on enrollment type. +// TODO(crbug.com/888725): Rename this to GetBrand and replace the current one. +std::string GetRlzBrand(); + // Clears brand code for the current session (not persisted through browser // restart). Future calls to GetBrand() will return an empty string. void ClearBrandForCurrentSession();
diff --git a/chrome/browser/google/google_brand_code_map_chromeos.cc b/chrome/browser/google/google_brand_code_map_chromeos.cc new file mode 100644 index 0000000..18ff316 --- /dev/null +++ b/chrome/browser/google/google_brand_code_map_chromeos.cc
@@ -0,0 +1,48 @@ +// 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/google/google_brand_code_map_chromeos.h" + +#include "base/containers/flat_map.h" +#include "base/no_destructor.h" +#include "base/stl_util.h" + +namespace google_brand { +namespace chromeos { + +std::string GetRlzBrandCode( + const std::string& static_brand_code, + base::Optional<policy::MarketSegment> market_segment) { + struct BrandCodeValueEntry { + const char* unenrolled_brand_code; + const char* education_enrolled_brand_code; + const char* enterprise_enrolled_brand_code; + }; + static const base::NoDestructor< + base::flat_map<std::string, BrandCodeValueEntry>> + kBrandCodeMap({{"NPEC", {"BMGD", "YETH", "XAWJ"}}}); + + const auto it = kBrandCodeMap->find(static_brand_code); + if (it == kBrandCodeMap->end()) + return static_brand_code; + const auto& entry = it->second; + // An empty value indicates the device is not enrolled. + if (!market_segment.has_value()) + return entry.unenrolled_brand_code; + + switch (market_segment.value()) { + case policy::MarketSegment::EDUCATION: + return entry.education_enrolled_brand_code; + case policy::MarketSegment::ENTERPRISE: + case policy::MarketSegment::UNKNOWN: + // If the device is enrolled but market segment is unknown, it's fine to + // treat it as enterprise enrolled. + return entry.enterprise_enrolled_brand_code; + } + NOTREACHED(); + return static_brand_code; +} + +} // namespace chromeos +} // namespace google_brand \ No newline at end of file
diff --git a/chrome/browser/google/google_brand_code_map_chromeos.h b/chrome/browser/google/google_brand_code_map_chromeos.h new file mode 100644 index 0000000..32fbc0a --- /dev/null +++ b/chrome/browser/google/google_brand_code_map_chromeos.h
@@ -0,0 +1,26 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_GOOGLE_GOOGLE_BRAND_CODE_MAP_CHROMEOS_H_ +#define CHROME_BROWSER_GOOGLE_GOOGLE_BRAND_CODE_MAP_CHROMEOS_H_ + +#include <string> + +#include "base/optional.h" +#include "components/policy/core/common/cloud/cloud_policy_constants.h" + +namespace google_brand { +namespace chromeos { + +// Returns |static_brand_code| if it is not found in the map. Otherwise, returns +// a variation of the brand code based on |market_segment| (an empty value +// indicates the device is not enrolled). +std::string GetRlzBrandCode( + const std::string& static_brand_code, + base::Optional<policy::MarketSegment> market_segment); + +} // namespace chromeos +} // namespace google_brand + +#endif // CHROME_BROWSER_GOOGLE_GOOGLE_BRAND_CODE_MAP_CHROMEOS_H_ \ No newline at end of file
diff --git a/chrome/browser/google/google_brand_code_map_chromeos_unittest.cc b/chrome/browser/google/google_brand_code_map_chromeos_unittest.cc new file mode 100644 index 0000000..ec9bf4d --- /dev/null +++ b/chrome/browser/google/google_brand_code_map_chromeos_unittest.cc
@@ -0,0 +1,25 @@ +// Copyright (c) 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/google/google_brand_code_map_chromeos.h" + +#include "testing/gtest/include/gtest/gtest.h" + +using google_brand::chromeos::GetRlzBrandCode; + +TEST(GoogleBrandCodeMapTest, GetRlzBrandCode) { + // If the static brand code is in the map, |GetRlzBrandCode| returns a + // variation based on the enrollment status and market segment. + EXPECT_EQ("BMGD", GetRlzBrandCode("NPEC", base::nullopt)); + EXPECT_EQ("YETH", GetRlzBrandCode("NPEC", policy::MarketSegment::EDUCATION)); + EXPECT_EQ("XAWJ", GetRlzBrandCode("NPEC", policy::MarketSegment::ENTERPRISE)); + EXPECT_EQ("XAWJ", GetRlzBrandCode("NPEC", policy::MarketSegment::UNKNOWN)); + + // If the static brand code is not in the map, |GetRlzBrandCode| always + // returns the static brand code. + EXPECT_EQ("AAAA", GetRlzBrandCode("AAAA", base::nullopt)); + EXPECT_EQ("AAAA", GetRlzBrandCode("AAAA", policy::MarketSegment::UNKNOWN)); + EXPECT_EQ("AAAA", GetRlzBrandCode("AAAA", policy::MarketSegment::EDUCATION)); + EXPECT_EQ("AAAA", GetRlzBrandCode("AAAA", policy::MarketSegment::ENTERPRISE)); +} \ No newline at end of file
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc index 682d549b..aca8d59 100644 --- a/chrome/browser/net/profile_network_context_service.cc +++ b/chrome/browser/net/profile_network_context_service.cc
@@ -20,6 +20,7 @@ #include "chrome/common/chrome_content_client.h" #include "chrome/common/chrome_paths_internal.h" #include "chrome/common/pref_names.h" +#include "components/certificate_transparency/pref_names.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/pref_names.h" #include "components/pref_registry/pref_registry_syncable.h" @@ -38,6 +39,19 @@ #include "extensions/common/constants.h" #endif +namespace { + +std::vector<std::string> TranslateStringArray(const base::ListValue* list) { + std::vector<std::string> strings; + for (const base::Value& value : *list) { + DCHECK(value.is_string()); + strings.push_back(value.GetString()); + } + return strings; +} + +} // namespace + ProfileNetworkContextService::ProfileNetworkContextService(Profile* profile) : profile_(profile), proxy_config_monitor_(profile) { PrefService* profile_prefs = profile->GetPrefs(); @@ -62,6 +76,27 @@ // Observe content settings so they can be synced to the network service. HostContentSettingsMapFactory::GetForProfile(profile_)->AddObserver(this); + + pref_change_registrar_.Init(profile_prefs); + + // When any of the following CT preferences change, we schedule an update + // to aggregate the actual update using a |ct_policy_update_timer_|. + pref_change_registrar_.Add( + certificate_transparency::prefs::kCTRequiredHosts, + base::BindRepeating(&ProfileNetworkContextService::ScheduleUpdateCTPolicy, + base::Unretained(this))); + pref_change_registrar_.Add( + certificate_transparency::prefs::kCTExcludedHosts, + base::BindRepeating(&ProfileNetworkContextService::ScheduleUpdateCTPolicy, + base::Unretained(this))); + pref_change_registrar_.Add( + certificate_transparency::prefs::kCTExcludedSPKIs, + base::BindRepeating(&ProfileNetworkContextService::ScheduleUpdateCTPolicy, + base::Unretained(this))); + pref_change_registrar_.Add( + certificate_transparency::prefs::kCTExcludedLegacySPKIs, + base::BindRepeating(&ProfileNetworkContextService::ScheduleUpdateCTPolicy, + base::Unretained(this))); } ProfileNetworkContextService::~ProfileNetworkContextService() {} @@ -73,7 +108,11 @@ network::mojom::NetworkContextPtr network_context; PartitionInfo partition_info(in_memory, relative_partition_path); - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { + content::GetNetworkService()->CreateNetworkContext( + MakeRequest(&network_context), + CreateNetworkContextParams(in_memory, relative_partition_path)); + } else { // The corresponding |profile_io_data_network_contexts_| may already be // initialized if SetUpProfileIODataNetworkContext was called first. auto iter = profile_io_data_network_contexts_.find(partition_info); @@ -91,12 +130,11 @@ // and NetworkContexts can't be destroyed without destroying the profile. profile_io_data_network_contexts_.erase(iter); } - return network_context; } - content::GetNetworkService()->CreateNetworkContext( - MakeRequest(&network_context), - CreateNetworkContextParams(in_memory, relative_partition_path)); + std::vector<network::mojom::NetworkContext*> contexts{network_context.get()}; + UpdateCTPolicyForContexts(contexts); + return network_context; } @@ -193,6 +231,51 @@ enable_referrers_.GetValue())); } +void ProfileNetworkContextService::UpdateCTPolicyForContexts( + const std::vector<network::mojom::NetworkContext*>& contexts) { + auto* prefs = profile_->GetPrefs(); + const base::ListValue* ct_required = + prefs->GetList(certificate_transparency::prefs::kCTRequiredHosts); + const base::ListValue* ct_excluded = + prefs->GetList(certificate_transparency::prefs::kCTExcludedHosts); + const base::ListValue* ct_excluded_spkis = + prefs->GetList(certificate_transparency::prefs::kCTExcludedSPKIs); + const base::ListValue* ct_excluded_legacy_spkis = + prefs->GetList(certificate_transparency::prefs::kCTExcludedLegacySPKIs); + + std::vector<std::string> required(TranslateStringArray(ct_required)); + std::vector<std::string> excluded(TranslateStringArray(ct_excluded)); + std::vector<std::string> excluded_spkis( + TranslateStringArray(ct_excluded_spkis)); + std::vector<std::string> excluded_legacy_spkis( + TranslateStringArray(ct_excluded_legacy_spkis)); + + for (auto* context : contexts) { + context->SetCTPolicy(required, excluded, excluded_spkis, + excluded_legacy_spkis); + } +} + +void ProfileNetworkContextService::UpdateCTPolicy() { + std::vector<network::mojom::NetworkContext*> contexts; + content::BrowserContext::ForEachStoragePartition( + profile_, + base::BindRepeating( + [](std::vector<network::mojom::NetworkContext*>* contexts_ptr, + content::StoragePartition* storage_partition) { + contexts_ptr->push_back(storage_partition->GetNetworkContext()); + }, + &contexts)); + + UpdateCTPolicyForContexts(contexts); +} + +void ProfileNetworkContextService::ScheduleUpdateCTPolicy() { + ct_policy_update_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(0), + this, + &ProfileNetworkContextService::UpdateCTPolicy); +} + void ProfileNetworkContextService::FlushProxyConfigMonitorForTesting() { proxy_config_monitor_.FlushForTesting(); }
diff --git a/chrome/browser/net/profile_network_context_service.h b/chrome/browser/net/profile_network_context_service.h index b56a3c42..4656c25f 100644 --- a/chrome/browser/net/profile_network_context_service.h +++ b/chrome/browser/net/profile_network_context_service.h
@@ -9,9 +9,11 @@ #include "base/files/file_path.h" #include "base/macros.h" +#include "base/timer/timer.h" #include "chrome/browser/net/proxy_config_monitor.h" #include "components/content_settings/core/browser/content_settings_observer.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_member.h" #include "services/network/public/mojom/network_context.mojom.h" @@ -86,6 +88,15 @@ void UpdateReferrersEnabled(); + // Update the CTPolicy for the given NetworkContexts. + void UpdateCTPolicyForContexts( + const std::vector<network::mojom::NetworkContext*>& contexts); + + // Update the CTPolicy for the all of profiles_'s NetworkContexts. + void UpdateCTPolicy(); + + void ScheduleUpdateCTPolicy(); + // Creates parameters for the NetworkContext. Use |in_memory| instead of // |profile_->IsOffTheRecord()| because sometimes normal profiles want off the // record partitions (e.g. for webview tag). @@ -123,8 +134,11 @@ BooleanPrefMember quic_allowed_; StringPrefMember pref_accept_language_; BooleanPrefMember block_third_party_cookies_; - BooleanPrefMember enable_referrers_; + PrefChangeRegistrar pref_change_registrar_; + + // Used to post schedule CT policy updates + base::OneShotTimer ct_policy_update_timer_; DISALLOW_COPY_AND_ASSIGN(ProfileNetworkContextService); };
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc index b310a40..a54eead 100644 --- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
@@ -12,6 +12,7 @@ #include "base/metrics/histogram_macros.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/page_load_metrics/page_load_metrics_util.h" +#include "content/public/common/process_type.h" #include "net/http/http_response_headers.h" #include "ui/base/page_transition_types.h" @@ -83,6 +84,9 @@ "PageLoad.PaintTiming.NavigationToFirstContentfulPaint"; const char kBackgroundHistogramFirstContentfulPaint[] = "PageLoad.PaintTiming.NavigationToFirstContentfulPaint.Background"; +const char kHistogramFirstContenfulPaintInitiatingProcess[] = + "PageLoad.Internal.PaintTiming.NavigationToFirstContenfulPaint." + "InitiatingProcess"; const char kHistogramFirstMeaningfulPaint[] = "PageLoad.Experimental.PaintTiming.NavigationToFirstMeaningfulPaint"; const char kHistogramTimeToInteractive[] = @@ -391,6 +395,12 @@ PAGE_LOAD_HISTOGRAM(internal::kHistogramParseStartToFirstContentfulPaint, timing.paint_timing->first_contentful_paint.value() - timing.parse_timing->parse_start.value()); + UMA_HISTOGRAM_ENUMERATION( + internal::kHistogramFirstContenfulPaintInitiatingProcess, + info.user_initiated_info.browser_initiated + ? content::PROCESS_TYPE_BROWSER + : content::PROCESS_TYPE_RENDERER, + content::PROCESS_TYPE_CONTENT_END); if (was_no_store_main_resource_) { PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstContentfulPaintNoStore,
diff --git a/chrome/browser/password_manager/account_chooser_dialog_android.cc b/chrome/browser/password_manager/account_chooser_dialog_android.cc index 8a164bc..9fcf08b 100644 --- a/chrome/browser/password_manager/account_chooser_dialog_android.cc +++ b/chrome/browser/password_manager/account_chooser_dialog_android.cc
@@ -121,15 +121,9 @@ void AccountChooserDialogAndroid::ShowDialog() { JNIEnv* env = AttachCurrentThread(); - bool is_smartlock_branding_enabled = - password_bubble_experiment::IsSmartLockUser( - ProfileSyncServiceFactory::GetForProfile( - Profile::FromBrowserContext(web_contents_->GetBrowserContext()))); - base::string16 title; - gfx::Range title_link_range = gfx::Range(); - GetAccountChooserDialogTitleTextAndLinkRange( - is_smartlock_branding_enabled, local_credentials_forms().size() > 1, - &title, &title_link_range); + base::string16 title = + l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_ACCOUNT_CHOOSER_TITLE); + ; gfx::NativeWindow native_window = web_contents_->GetTopLevelNativeWindow(); ScopedJavaLocalRef<jobjectArray> java_credentials_array = CreateNativeCredentialArray(env, local_credentials_forms().size()); @@ -145,8 +139,7 @@ dialog_jobject_.Reset(Java_AccountChooserDialog_createAndShowAccountChooser( env, native_window->GetJavaObject(), reinterpret_cast<intptr_t>(this), java_credentials_array, - base::android::ConvertUTF16ToJavaString(env, title), - title_link_range.start(), title_link_range.end(), + base::android::ConvertUTF16ToJavaString(env, title), 0, 0, base::android::ConvertUTF8ToJavaString(env, origin), base::android::ConvertUTF16ToJavaString(env, signin_button))); network::mojom::URLLoaderFactory* loader_factory =
diff --git a/chrome/browser/password_manager/auto_signin_first_run_dialog_android.cc b/chrome/browser/password_manager/auto_signin_first_run_dialog_android.cc index 2ef8700..cbae41c 100644 --- a/chrome/browser/password_manager/auto_signin_first_run_dialog_android.cc +++ b/chrome/browser/password_manager/auto_signin_first_run_dialog_android.cc
@@ -10,8 +10,8 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" +#include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" -#include "components/browser_sync/profile_sync_service.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" #include "components/password_manager/core/browser/password_manager_constants.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" @@ -45,16 +45,9 @@ Profile* profile = Profile::FromBrowserContext(web_contents_->GetBrowserContext()); - bool is_smartlock_branding_enabled = - password_bubble_experiment::IsSmartLockUser( - ProfileSyncServiceFactory::GetForProfile(profile)); - base::string16 explanation; - gfx::Range explanation_link_range = gfx::Range(); - GetBrandedTextAndLinkRange( - is_smartlock_branding_enabled, - IDS_AUTO_SIGNIN_FIRST_RUN_SMART_LOCK_TEXT, - IDS_AUTO_SIGNIN_FIRST_RUN_TEXT, &explanation, - &explanation_link_range); + base::string16 explanation = l10n_util::GetStringFUTF16( + IDS_AUTO_SIGNIN_FIRST_RUN_TEXT, + l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_TITLE_BRAND)); gfx::NativeWindow native_window = web_contents_->GetTopLevelNativeWindow(); base::android::ScopedJavaGlobalRef<jobject> java_dialog_global; base::string16 message = l10n_util::GetStringUTF16( @@ -69,8 +62,7 @@ dialog_jobject_.Reset(Java_AutoSigninFirstRunDialog_createAndShowDialog( env, native_window->GetJavaObject(), reinterpret_cast<intptr_t>(this), base::android::ConvertUTF16ToJavaString(env, message), - base::android::ConvertUTF16ToJavaString(env, explanation), - explanation_link_range.start(), explanation_link_range.end(), + base::android::ConvertUTF16ToJavaString(env, explanation), 0, 0, base::android::ConvertUTF16ToJavaString(env, ok_button_text), base::android::ConvertUTF16ToJavaString(env, turn_off_button_text))); }
diff --git a/chrome/browser/password_manager/save_password_infobar_delegate_android.cc b/chrome/browser/password_manager/save_password_infobar_delegate_android.cc index 16ffbc9..d723390 100644 --- a/chrome/browser/password_manager/save_password_infobar_delegate_android.cc +++ b/chrome/browser/password_manager/save_password_infobar_delegate_android.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/ui/android/infobars/save_password_infobar.h" #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" +#include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/browser_sync/profile_sync_service.h" #include "components/infobars/core/infobar.h" @@ -55,16 +56,14 @@ form_to_save_(std::move(form_to_save)), infobar_response_(password_manager::metrics_util::NO_DIRECT_INTERACTION) { base::string16 message; - gfx::Range message_link_range = gfx::Range(); PasswordTitleType type = form_to_save_->GetPendingCredentials().federation_origin.opaque() ? PasswordTitleType::SAVE_PASSWORD : PasswordTitleType::SAVE_ACCOUNT; - GetSavePasswordDialogTitleTextAndLinkRange( - web_contents->GetVisibleURL(), form_to_save_->GetOrigin(), - is_smartlock_branding_enabled, type, &message, &message_link_range); + GetSavePasswordDialogTitleTextAndLinkRange(web_contents->GetVisibleURL(), + form_to_save_->GetOrigin(), type, + &message); SetMessage(message); - SetMessageLinkRange(message_link_range); if (type == PasswordTitleType::SAVE_PASSWORD && is_smartlock_branding_enabled) {
diff --git a/chrome/browser/password_manager/update_password_infobar_delegate_android.cc b/chrome/browser/password_manager/update_password_infobar_delegate_android.cc index 8778124..b7bf90a 100644 --- a/chrome/browser/password_manager/update_password_infobar_delegate_android.cc +++ b/chrome/browser/password_manager/update_password_infobar_delegate_android.cc
@@ -70,13 +70,10 @@ : infobar_response_(password_manager::metrics_util::NO_DIRECT_INTERACTION), is_smartlock_branding_enabled_(is_smartlock_branding_enabled) { base::string16 message; - gfx::Range message_link_range = gfx::Range(); GetSavePasswordDialogTitleTextAndLinkRange( web_contents->GetVisibleURL(), form_to_update->GetOrigin(), - is_smartlock_branding_enabled, PasswordTitleType::UPDATE_PASSWORD, - &message, &message_link_range); + PasswordTitleType::UPDATE_PASSWORD, &message); SetMessage(message); - SetMessageLinkRange(message_link_range); if (is_smartlock_branding_enabled) SetDetailsMessage(l10n_util::GetStringUTF16(IDS_SAVE_PASSWORD_FOOTER));
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service.cc b/chrome/browser/policy/cloud/user_policy_signin_service.cc index 2276f1c..0da36c88 100644 --- a/chrome/browser/policy/cloud/user_policy_signin_service.cc +++ b/chrome/browser/policy/cloud/user_policy_signin_service.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/signin_util.h" #include "components/account_id/account_id.h" #include "components/policy/core/common/cloud/cloud_policy_client_registration_helper.h" #include "components/policy/core/common/cloud/user_cloud_policy_manager.h" @@ -190,7 +191,8 @@ UserCloudPolicyManager* manager = policy_manager(); // Allow the user to signout again. if (manager) - signin_manager()->ProhibitSignout(false); + signin_util::SetUserSignoutAllowedForProfile(profile_, true); + UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager(); } @@ -245,7 +247,7 @@ void UserPolicySigninService::ProhibitSignoutIfNeeded() { if (policy_manager()->IsClientRegistered()) { DVLOG(1) << "User is registered for policy - prohibiting signout"; - signin_manager()->ProhibitSignout(true); + signin_util::SetUserSignoutAllowedForProfile(profile_, false); } }
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc index eedad53..0d64cfc 100644 --- a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc +++ b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
@@ -25,6 +25,7 @@ #include "chrome/browser/signin/fake_signin_manager_builder.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/signin/signin_util.h" #include "chrome/browser/signin/test_signin_client_builder.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" @@ -846,7 +847,7 @@ EXPECT_TRUE(manager_->IsClientRegistered()); #if !defined(OS_ANDROID) - EXPECT_TRUE(signin_manager_->IsSignoutProhibited()); + EXPECT_FALSE(signin_util::IsUserSignoutAllowedForProfile(profile_.get())); #endif // Kick off another policy fetch. @@ -868,7 +869,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_FALSE(manager_->IsClientRegistered()); #if !defined(OS_ANDROID) - EXPECT_FALSE(signin_manager_->IsSignoutProhibited()); + EXPECT_TRUE(signin_util::IsUserSignoutAllowedForProfile(profile_.get())); #endif }
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index a86a1f23..4898978 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -188,6 +188,7 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_constants.h" +#include "content/public/common/content_features.h" #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" #include "content/public/common/result_codes.h" @@ -4587,6 +4588,28 @@ EXPECT_FALSE(IsShowingInterstitial(tab)); EXPECT_EQ(base::UTF8ToUTF16("OK"), browser()->tab_strip_model()->GetActiveWebContents()->GetTitle()); + + // Now ensure that this setting still works after a network process crash. + if (!base::FeatureList::IsEnabled(network::features::kNetworkService) || + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSingleProcess) || + base::FeatureList::IsEnabled(features::kNetworkServiceInProcess)) { + return; + } + + ui_test_utils::NavigateToURL(browser(), + https_server_ok.GetURL("/title1.html")); + + SimulateNetworkServiceCrash(); + SetShouldRequireCTForTesting(&required); + + ui_test_utils::NavigateToURL(browser(), + https_server_ok.GetURL("/simple.html")); + + // There should be no interstitial after the page loads. + EXPECT_FALSE(IsShowingInterstitial(tab)); + EXPECT_EQ(base::UTF8ToUTF16("OK"), + browser()->tab_strip_model()->GetActiveWebContents()->GetTitle()); } IN_PROC_BROWSER_TEST_F(PolicyTest,
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 5012debc..730a4ef 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -101,7 +101,6 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/chromium_strings.h" #include "components/bookmarks/browser/bookmark_model.h" -#include "components/certificate_transparency/pref_names.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/pref_names.h" @@ -616,21 +615,6 @@ base::Bind(&ProfileImpl::UpdateIsEphemeralInStorage, base::Unretained(this))); - // When any of the following CT preferences change, we schedule an update - // to aggregate the actual update using a |ct_policy_update_timer_|. - pref_change_registrar_.Add( - certificate_transparency::prefs::kCTRequiredHosts, - base::Bind(&ProfileImpl::ScheduleUpdateCTPolicy, base::Unretained(this))); - pref_change_registrar_.Add( - certificate_transparency::prefs::kCTExcludedHosts, - base::Bind(&ProfileImpl::ScheduleUpdateCTPolicy, base::Unretained(this))); - pref_change_registrar_.Add( - certificate_transparency::prefs::kCTExcludedSPKIs, - base::Bind(&ProfileImpl::ScheduleUpdateCTPolicy, base::Unretained(this))); - pref_change_registrar_.Add( - certificate_transparency::prefs::kCTExcludedLegacySPKIs, - base::Bind(&ProfileImpl::ScheduleUpdateCTPolicy, base::Unretained(this))); - media_device_id_salt_ = new MediaDeviceIDSalt(prefs_.get()); // It would be nice to use PathService for fetching this directory, but @@ -744,8 +728,6 @@ content::URLDataSource::Add(this, std::make_unique<PrefsInternalsSource>(this)); - - ScheduleUpdateCTPolicy(); } base::FilePath ProfileImpl::last_selected_directory() { @@ -1459,36 +1441,6 @@ } } -std::vector<std::string> TranslateStringArray(const base::ListValue* list) { - std::vector<std::string> strings; - for (const base::Value& value : *list) { - DCHECK(value.is_string()); - strings.push_back(value.GetString()); - } - return strings; -} - -void ProfileImpl::ScheduleUpdateCTPolicy() { - ct_policy_update_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(0), - this, &ProfileImpl::UpdateCTPolicy); -} - -void ProfileImpl::UpdateCTPolicy() { - const base::ListValue* ct_required = - prefs_->GetList(certificate_transparency::prefs::kCTRequiredHosts); - const base::ListValue* ct_excluded = - prefs_->GetList(certificate_transparency::prefs::kCTExcludedHosts); - const base::ListValue* ct_excluded_spkis = - prefs_->GetList(certificate_transparency::prefs::kCTExcludedSPKIs); - const base::ListValue* ct_excluded_legacy_spkis = - prefs_->GetList(certificate_transparency::prefs::kCTExcludedLegacySPKIs); - - GetDefaultStoragePartition(this)->GetNetworkContext()->SetCTPolicy( - TranslateStringArray(ct_required), TranslateStringArray(ct_excluded), - TranslateStringArray(ct_excluded_spkis), - TranslateStringArray(ct_excluded_legacy_spkis)); -} - // Gets the media cache parameters from the command line. |cache_path| will be // set to the user provided path, or will not be touched if there is not an // argument. |max_size| will be the user provided value or zero by default.
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h index b7cbdf1..ca54ebc 100644 --- a/chrome/browser/profiles/profile_impl.h +++ b/chrome/browser/profiles/profile_impl.h
@@ -14,7 +14,6 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/timer/timer.h" #include "build/build_config.h" #include "chrome/browser/net/reporting_permissions_checker.h" #include "chrome/browser/profiles/profile.h" @@ -191,9 +190,6 @@ void UpdateNameInStorage(); void UpdateAvatarInStorage(); void UpdateIsEphemeralInStorage(); - void UpdateCTPolicy(); - - void ScheduleUpdateCTPolicy(); void GetMediaCacheParameters(base::FilePath* cache_path, int* max_size); @@ -290,9 +286,6 @@ ReportingPermissionsCheckerFactory reporting_permissions_checker_factory_; - // Used to post schedule CT policy updates - base::OneShotTimer ct_policy_update_timer_; - DISALLOW_COPY_AND_ASSIGN(ProfileImpl); };
diff --git a/chrome/browser/profiles/profiles_state.cc b/chrome/browser/profiles/profiles_state.cc index 8122aca..b58cc4af 100644 --- a/chrome/browser/profiles/profiles_state.cc +++ b/chrome/browser/profiles/profiles_state.cc
@@ -36,7 +36,6 @@ #include "chrome/browser/signin/signin_error_controller_factory.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/signin_pref_names.h" -#include "ui/gfx/text_elider.h" #endif namespace profiles { @@ -113,19 +112,6 @@ } #if !defined(OS_CHROMEOS) -base::string16 GetAvatarButtonTextForProfile(Profile* profile) { - const int kMaxCharactersToDisplay = 15; - base::string16 name = GetAvatarNameForProfile(profile->GetPath()); - name = gfx::TruncateString(name, - kMaxCharactersToDisplay, - gfx::CHARACTER_BREAK); - if (profile->IsLegacySupervised()) { - name = l10n_util::GetStringFUTF16( - IDS_LEGACY_SUPERVISED_USER_NEW_AVATAR_LABEL, name); - } - return name; -} - base::string16 GetProfileSwitcherTextForItem(const AvatarMenu::Item& item) { if (item.legacy_supervised) { return l10n_util::GetStringFUTF16(
diff --git a/chrome/browser/profiles/profiles_state.h b/chrome/browser/profiles/profiles_state.h index bc66518..89be5774 100644 --- a/chrome/browser/profiles/profiles_state.h +++ b/chrome/browser/profiles/profiles_state.h
@@ -53,11 +53,6 @@ base::string16 GetAvatarNameForProfile(const base::FilePath& profile_path); #if !defined(OS_CHROMEOS) -// Returns the string to use in the avatar button for the specified profile. -// This is essentially the name returned by GetAvatarNameForProfile, but it -// may be elided and contain an indicator for supervised users. -base::string16 GetAvatarButtonTextForProfile(Profile* profile); - // Returns the string to use in the fast user switcher menu for the specified // menu item. Adds a supervision indicator to the profile name if appropriate. base::string16 GetProfileSwitcherTextForItem(const AvatarMenu::Item& item);
diff --git a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc index 600e49e..ad7437e5 100644 --- a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc +++ b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
@@ -201,7 +201,8 @@ else EXPECT_EQ(tab2->GetMainFrame()->GetProcess(), rph2); - // Create another WebUI tab. It should share the process with omnibox. + // Create another WebUI tab. Each WebUI tab should get a separate process + // because of origin locking. // Note: intentionally create this tab after the normal tabs to exercise bug // 43448 where extension and WebUI tabs could get combined into normal // renderers. @@ -211,11 +212,12 @@ ::ShowSingletonTab(browser(), history); observer3.Wait(); tab_count++; + host_count++; EXPECT_EQ(tab_count, browser()->tab_strip_model()->count()); tab2 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1); EXPECT_EQ(tab2->GetURL(), GURL(history)); EXPECT_EQ(host_count, RenderProcessHostCount()); - EXPECT_EQ(tab2->GetMainFrame()->GetProcess(), rph1); + EXPECT_NE(tab2->GetMainFrame()->GetProcess(), rph1); // Create an extension tab. It should be in its own process. GURL extension_url("chrome-extension://" + extension->id());
diff --git a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc index 20c5b59..034f556 100644 --- a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
@@ -922,11 +922,15 @@ } IN_PROC_BROWSER_TEST_F(TabManagerTest, ProactiveFastShutdownSharedTabProcess) { + ASSERT_TRUE(embedded_test_server()->Start()); + // Set max renderers to 1 before opening tabs to force running out of // processes and for both these tabs to share a renderer. content::RenderProcessHost::SetMaxRendererProcessCount(1); - OpenTwoTabs(GURL(chrome::kChromeUIAboutURL), - GURL(chrome::kChromeUICreditsURL)); + OpenTwoTabs(embedded_test_server()->GetURL("a.com", "/title1.html"), + embedded_test_server()->GetURL("a.com", "/title2.html")); + EXPECT_EQ(tsm()->GetWebContentsAt(0)->GetMainFrame()->GetProcess(), + tsm()->GetWebContentsAt(1)->GetMainFrame()->GetProcess()); // The Tab Manager will not be able to fast-kill either of the tabs since they // share the same process regardless of the discard reason. No unsafe attempts @@ -941,12 +945,15 @@ } IN_PROC_BROWSER_TEST_F(TabManagerTest, UrgentFastShutdownSharedTabProcess) { + ASSERT_TRUE(embedded_test_server()->Start()); + // Set max renderers to 1 before opening tabs to force running out of // processes and for both these tabs to share a renderer. content::RenderProcessHost::SetMaxRendererProcessCount(1); - // Disable the protection of recent tabs. - OpenTwoTabs(GURL(chrome::kChromeUIAboutURL), - GURL(chrome::kChromeUICreditsURL)); + OpenTwoTabs(embedded_test_server()->GetURL("a.com", "/title1.html"), + embedded_test_server()->GetURL("a.com", "/title2.html")); + EXPECT_EQ(tsm()->GetWebContentsAt(0)->GetMainFrame()->GetProcess(), + tsm()->GetWebContentsAt(1)->GetMainFrame()->GetProcess()); // Advance time so everything is urgent discardable. test_clock_.Advance(kBackgroundUrgentProtectionTime);
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs index a4fdaaa..a16a24e 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
@@ -1761,3 +1761,18 @@ }); }); }); + +TEST_F('BackgroundTest', 'ListName', function() { + var mockFeedback = this.createMockFeedback(); + this.runWithLoadedTree(function() {/* + <div id="_md-chips-wrapper-76" tabindex="-1" class="md-chips md-readonly" aria-setsize="4" aria-label="Favorite Sports" role="list" aria-describedby="chipsNote"> + <div role="listitem">Baseball</div> + <div role="listitem">Hockey</div> + <div role="listitem">Lacrosse</div> + <div role="listitem">Football</div> + </div> + */}, function(root) { + mockFeedback.expectSpeech('Favorite Sports') + .replay(); + }); +});
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js index 8f7ca2e..26aa071 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
@@ -459,8 +459,8 @@ }, list: { enter: `$role @@list_with_items($countChildren(listItem))`, - speak: `$descendants $role @@list_with_items($countChildren(listItem)) - $description $state` + speak: `$nameFromNode $descendants $role + @@list_with_items($countChildren(listItem)) $description $state` }, listBox: { enter: `$nameFromNode
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/BUILD.gn b/chrome/browser/resources/chromeos/multidevice_setup/BUILD.gn index cac0a67..0b624c9 100644 --- a/chrome/browser/resources/chromeos/multidevice_setup/BUILD.gn +++ b/chrome/browser/resources/chromeos/multidevice_setup/BUILD.gn
@@ -6,14 +6,34 @@ js_type_check("closure_compile") { deps = [ - ":multidevice_setup_dialog", + ":multidevice_setup_post_oobe", + ":post_oobe_delegate", ] } -js_library("multidevice_setup_dialog") { +js_library("multidevice_setup_post_oobe") { deps = [ - "//ui/webui/resources/cr_components/chromeos/multidevice_setup:multidevice_setup", - "//ui/webui/resources/cr_components/chromeos/multidevice_setup:ui_mode", - "//ui/webui/resources/js:util", + ":post_oobe_delegate", + ] +} + +js_library("post_oobe_delegate") { + deps = [ + "//ui/webui/resources/cr_components/chromeos/multidevice_setup:mojo_api", + "//ui/webui/resources/cr_components/chromeos/multidevice_setup:multidevice_setup_delegate", + "//ui/webui/resources/js:cr", + ] + + extra_deps = [ + "//chromeos/services/device_sync/public/mojom:mojom_js", + "//chromeos/services/multidevice_setup/public/mojom:mojom_js", + "//mojo/public/mojom/base:base_js", + ] + + externs_list = [ + "$root_gen_dir/chromeos/services/device_sync/public/mojom/device_sync.mojom.externs.js", + "$root_gen_dir/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.externs.js", + "$root_gen_dir/mojo/public/mojom/base/time.mojom.externs.js", + "$externs_path/mojo.js", ] }
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_dialog.html b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_dialog.html index 3ba9f86..59fd688c 100644 --- a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_dialog.html +++ b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_dialog.html
@@ -16,13 +16,11 @@ </style> </head> <body> - <multidevice-setup id="main-element"></multidevice-setup> <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> <link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="i18n_setup.html"> - <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html"> - <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/ui_mode.html"> + <link rel="import" href="multidevice_setup_post_oobe.html"> + <multidevice-setup-post-oobe id="main-element"></multidevice-setup-post-oobe> </body> -<script src="multidevice_setup_dialog.js"></script> </html>
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_dialog.js b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_dialog.js deleted file mode 100644 index d0c68e8..0000000 --- a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_dialog.js +++ /dev/null
@@ -1,11 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -function closeUi() { - console.log('Closing Unified MultiDevice Setup WebUI'); - chrome.send('dialogClose'); -} - -$('main-element').uiMode = multidevice_setup.UiMode.POST_OOBE; -$('main-element').addEventListener('setup-exited', () => closeUi());
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_post_oobe.html b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_post_oobe.html new file mode 100644 index 0000000..92081b2 --- /dev/null +++ b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_post_oobe.html
@@ -0,0 +1,37 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html"> +<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="post_oobe_delegate.html"> + +<dom-module id="multidevice-setup-post-oobe"> + <template> + <style include="multidevice-setup-shared"> + #backward-button, + #forward-button { + align-items: center; + display: flex; + justify-content: center; + text-transform: none; + } + </style> + <multidevice-setup delegate="[[delegate_]]" + on-setup-exited="onExitRequested_" + forward-button-text="{{forwardButtonText_}}" + forward-button-disabled="{{forwardButtonDisabled_}}" + backward-button-text="{{backwardButtonText_}}"> + <paper-button id="backward-button" + slot="backward-button" class="cancel-button"> + [[backwardButtonText_]] + </paper-button> + <paper-button id="forward-button" + slot="forward-button" class="action-button" + disabled$="[[forwardButtonDisabled_]]"> + [[forwardButtonText_]] + </paper-button> + </multidevice-setup> + </template> + <script src="multidevice_setup_post_oobe.js"> + </script> +</dom-module>
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_post_oobe.js b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_post_oobe.js new file mode 100644 index 0000000..3af2027 --- /dev/null +++ b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_post_oobe.js
@@ -0,0 +1,52 @@ +// 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. + +/** + * MultiDevice setup flow which is shown after OOBE has completed. + */ +Polymer({ + is: 'multidevice-setup-post-oobe', + + properties: { + /** @private {!multidevice_setup.MultiDeviceSetupDelegate} */ + delegate_: Object, + + /** + * Text to be shown on the forward navigation button. + * @private {string|undefined} + */ + forwardButtonText: { + type: String, + value: '', + }, + + /** + * Whether the forward button should be disabled. + * @private + */ + forwardButtonDisabled_: { + type: Boolean, + value: false, + }, + + /** + * Text to be shown on the backward navigation button. + * @private {string|undefined} + */ + backwardButtonText_: { + type: String, + value: '', + }, + }, + + /** @override */ + attached: function() { + this.delegate_ = new multidevice_setup.PostOobeDelegate(); + }, + + /** @private */ + onExitRequested_: function() { + chrome.send('dialogClose'); + }, +});
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_resources.grd b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_resources.grd index 191cce3..81ae952 100644 --- a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_resources.grd +++ b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_resources.grd
@@ -20,8 +20,17 @@ flattenhtml="true" allowexternalscript="true" type="chrome_html" /> - <structure name="IDR_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_DIALOG_JS" - file="multidevice_setup_dialog.js" + <structure name="IDR_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_POST_OOBE_HTML" + file="multidevice_setup_post_oobe.html" + type="chrome_html" /> + <structure name="IDR_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_POST_OOBE_JS" + file="multidevice_setup_post_oobe.js" + type="chrome_html" /> + <structure name="IDR_MULTIDEVICE_SETUP_POST_OOBE_DELEGATE_HTML" + file="post_oobe_delegate.html" + type="chrome_html" /> + <structure name="IDR_MULTIDEVICE_SETUP_POST_OOBE_DELEGATE_JS" + file="post_oobe_delegate.js" type="chrome_html" /> </structures> </release>
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/post_oobe_delegate.html b/chrome/browser/resources/chromeos/multidevice_setup/post_oobe_delegate.html new file mode 100644 index 0000000..1fc839f --- /dev/null +++ b/chrome/browser/resources/chromeos/multidevice_setup/post_oobe_delegate.html
@@ -0,0 +1,3 @@ +<link rel="import" href="chrome://resources/html/cr.html"> +<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/mojo_api.html"> +<script src="post_oobe_delegate.js"></script>
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/post_oobe_delegate.js b/chrome/browser/resources/chromeos/multidevice_setup/post_oobe_delegate.js new file mode 100644 index 0000000..2bb55720 --- /dev/null +++ b/chrome/browser/resources/chromeos/multidevice_setup/post_oobe_delegate.js
@@ -0,0 +1,37 @@ +// 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. + +cr.define('multidevice_setup', function() { + /** @implements {multidevice_setup.MultiDeviceSetupDelegate} */ + class PostOobeDelegate { + /** @override */ + isPasswordRequiredToSetHost() { + return true; + } + + /** @override */ + setHostDevice(hostDeviceId, opt_authToken) { + // An authentication token is required to set the host device post-OOBE. + assert(!!opt_authToken); + + // Note: A cast is needed here because currently all Mojo functions which + // return a promise are typed only as {Promise}. The setHostDevice() + // function always returns a {!Promise<{success: boolean}>} (see + // multidevice_setup.mojom). + return /** @type {!Promise<{success: boolean}>} */ ( + multidevice_setup.MojoInterfaceProviderImpl.getInstance() + .getInterfacePtr() + .setHostDevice(hostDeviceId, opt_authToken)); + } + + /** @override */ + shouldExitSetupFlowAfterSettingHost() { + return false; + } + } + + return { + PostOobeDelegate: PostOobeDelegate, + }; +});
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/css/wallpaper_manager.css b/chrome/browser/resources/chromeos/wallpaper_manager/css/wallpaper_manager.css index a90080e..a5d7bae8 100644 --- a/chrome/browser/resources/chromeos/wallpaper_manager/css/wallpaper_manager.css +++ b/chrome/browser/resources/chromeos/wallpaper_manager/css/wallpaper_manager.css
@@ -409,6 +409,7 @@ .v2 .dialog-body { display: flex; height: 100%; + min-height: 0; } .v2 .dialog-topbar {
diff --git a/chrome/browser/resources/cryptotoken/enroller.js b/chrome/browser/resources/cryptotoken/enroller.js index 4bc7bb0..3721acc 100644 --- a/chrome/browser/resources/cryptotoken/enroller.js +++ b/chrome/browser/resources/cryptotoken/enroller.js
@@ -388,6 +388,12 @@ sendResponseOnce(sentResponse, closeable, response, sendResponse); } + var sender = createSenderFromMessageSender(messageSender); + if (!sender) { + sendErrorResponse({errorCode: ErrorCodes.BAD_REQUEST}); + return null; + } + async function getRegistrationData( appId, enrollChallenge, registrationData, opt_clientData) { var isDirect = true; @@ -397,7 +403,10 @@ } else if (chrome.cryptotokenPrivate != null) { isDirect = await(new Promise((resolve, reject) => { chrome.cryptotokenPrivate.canAppIdGetAttestation( - {'appId': appId, 'tabId': messageSender.tab.id}, resolve); + {'appId': appId, + 'tabId': messageSender.tab.id, + 'origin': sender.origin, + }, resolve); })); } @@ -452,11 +461,6 @@ sendErrorResponse({errorCode: ErrorCodes.TIMEOUT}); } - var sender = createSenderFromMessageSender(messageSender); - if (!sender) { - sendErrorResponse({errorCode: ErrorCodes.BAD_REQUEST}); - return null; - } if (sender.origin.indexOf('http://') == 0 && !HTTP_ORIGINS_ALLOWED) { sendErrorResponse({errorCode: ErrorCodes.BAD_REQUEST}); return null;
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js index 8ac4660..762ae75 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.js +++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -288,11 +288,13 @@ * Returns a timeout that can be executed early. * @param {!Function} timeout The timeout function. * @param {number} delay The timeout delay. + * @param {Object} previousContainer The pre-existing notification container. * @return {Object} */ -function createExecutableTimeout(timeout, delay) { +function createExecutableTimeout(timeout, delay, previousContainer) { let timeoutId = window.setTimeout(timeout, delay); return { + previousContainer: previousContainer, clear: () => { window.clearTimeout(timeoutId); }, @@ -700,9 +702,13 @@ * @param {!Element} notificationContainer The notification container element. */ function floatUpNotification(notification, notificationContainer) { - // Hide any pre-existing notification. + // Hide pre-existing notification if it was different type. Clear timeout and + // replace it with the new timeout and new message if it was the same type. if (delayedHideNotification) { - delayedHideNotification.trigger(); + if (delayedHideNotification.previousContainer === notificationContainer) + delayedHideNotification.clear(); + else + delayedHideNotification.trigger(); delayedHideNotification = null; } @@ -716,7 +722,7 @@ // Automatically hide the notification after a period of time. delayedHideNotification = createExecutableTimeout(() => { floatDownNotification(notification, notificationContainer); - }, NOTIFICATION_TIMEOUT); + }, NOTIFICATION_TIMEOUT, notificationContainer); }
diff --git a/chrome/browser/resources/settings/a11y_page/BUILD.gn b/chrome/browser/resources/settings/a11y_page/BUILD.gn index 7759dba..a5a8c33 100644 --- a/chrome/browser/resources/settings/a11y_page/BUILD.gn +++ b/chrome/browser/resources/settings/a11y_page/BUILD.gn
@@ -34,7 +34,7 @@ deps = [ ":externs", "..:route", - "../device_page:display_size_slider", + "../controls:settings_slider", "../languages_page:languages_browser_proxy", "../settings_page:settings_animated_pages", "//ui/webui/resources/js:i18n_behavior",
diff --git a/chrome/browser/resources/settings/a11y_page/tts_subpage.html b/chrome/browser/resources/settings/a11y_page/tts_subpage.html index 47e2e5ab..2eb88372 100644 --- a/chrome/browser/resources/settings/a11y_page/tts_subpage.html +++ b/chrome/browser/resources/settings/a11y_page/tts_subpage.html
@@ -6,7 +6,7 @@ <link rel="import" href="chrome://resources/html/md_select_css.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="../device_page/display_size_slider.html"> +<link rel="import" href="../controls/settings_slider.html"> <link rel="import" href="../i18n_setup.html"> <link rel="import" href="../languages_page/languages_browser_proxy.html"> <link rel="import" href="../settings_shared_css.html"> @@ -39,33 +39,33 @@ <h2>$i18n{textToSpeechProperties}</h2> <div class="settings-box first"> <div class="start" id="rate">$i18n{textToSpeechRate}</div> - <display-size-slider + <settings-slider show-markers pref="{{prefs.settings.tts.speech_rate}}" ticks="[[speechRateTicks_()]]" - min-label="$i18n{textToSpeechRateMinimumLabel}" - max-label="$i18n{textToSpeechRateMaximumLabel}" + label-min="$i18n{textToSpeechRateMinimumLabel}" + label-max="$i18n{textToSpeechRateMaximumLabel}" aria-describedby="rate"> - </display-size-slider> + </settings-slider> </div> <div class="settings-box continuation"> <div class="start" id="pitch">$i18n{textToSpeechPitch}</div> - <display-size-slider + <settings-slider show-markers pref="{{prefs.settings.tts.speech_pitch}}" ticks="[[speechPitchTicks_()]]" - min-label="$i18n{textToSpeechPitchMinimumLabel}" - max-label="$i18n{textToSpeechPitchMaximumLabel}" + label-min="$i18n{textToSpeechPitchMinimumLabel}" + label-max="$i18n{textToSpeechPitchMaximumLabel}" aria-describedby="pitch"> - </display-size-slider> + </settings-slider> </div> <div class="settings-box continuation"> <div class="start" id="volume">$i18n{textToSpeechVolume}</div> - <display-size-slider + <settings-slider show-markers pref="{{prefs.settings.tts.speech_volume}}" ticks="[[speechVolumeTicks_()]]" - min-label="$i18n{textToSpeechVolumeMinimumLabel}" - max-label="$i18n{textToSpeechVolumeMaximumLabel}" + label-min="$i18n{textToSpeechVolumeMinimumLabel}" + label-max="$i18n{textToSpeechVolumeMaximumLabel}" aria-describedby="volume"> - </display-size-slider> + </settings-slider> </div> <h2>$i18n{textToSpeechPreviewHeading}</h2>
diff --git a/chrome/browser/resources/settings/a11y_page/tts_subpage.js b/chrome/browser/resources/settings/a11y_page/tts_subpage.js index 0e27875..d2377f1 100644 --- a/chrome/browser/resources/settings/a11y_page/tts_subpage.js +++ b/chrome/browser/resources/settings/a11y_page/tts_subpage.js
@@ -75,7 +75,7 @@ /** * Ticks for the Speech Rate slider. Non-linear as we expect people * to want more control near 1.0. - * @return Array<SliderTick> + * @return Array<cr_slider.SliderTick> * @private */ speechRateTicks_: function() { @@ -91,7 +91,7 @@ /** * Ticks for the Speech Pitch slider. Valid pitches are between 0 and 2, * exclusive of 0. - * @return Array<SliderTick> + * @return Array<cr_slider.SliderTick> * @private */ speechPitchTicks_: function() { @@ -104,7 +104,7 @@ * Ticks for the Speech Volume slider. Valid volumes are between 0 and * 1 (100%), but volumes lower than .2 are excluded as being too quiet. * The values are linear between .2 and 1.0. - * @return Array<SliderTick> + * @return Array<cr_slider.SliderTick> * @private */ speechVolumeTicks_: function() { @@ -116,7 +116,7 @@ /** * Initializes i18n labels for ticks arrays. * @param {number} tick The value to make a tick for. - * @return {SliderTick} + * @return {cr_slider.SliderTick} * @private */ initTick_: function(tick) {
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html index f335b74..3953ab06 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html +++ b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html
@@ -16,7 +16,7 @@ <div class="start">$i18n{fontSize}</div> <settings-slider id="sizeSlider" pref="{{prefs.webkit.webprefs.default_font_size}}" - tick-values="[[fontSizeRange_]]" + ticks="[[fontSizeRange_]]" label-min="$i18n{tiny}" label-max="$i18n{huge}"> </settings-slider> </div> @@ -33,7 +33,7 @@ </div> <settings-slider id="minimumSizeSlider" pref="{{prefs.webkit.webprefs.minimum_font_size}}" - tick-values="[[minimumFontSizeRange_]]" + ticks="[[minimumFontSizeRange_]]" label-min="$i18n{tiny}" label-max="$i18n{huge}"> </settings-slider> </div>
diff --git a/chrome/browser/resources/settings/controls/settings_slider.html b/chrome/browser/resources/settings/controls/settings_slider.html index f58423c9..d6046aa 100644 --- a/chrome/browser/resources/settings/controls/settings_slider.html +++ b/chrome/browser/resources/settings/controls/settings_slider.html
@@ -8,11 +8,8 @@ <template> <style> :host { - --calculated-paper-slider-height: var(--paper-slider-height, 2px); display: inline-flex; - /* Counteract the margin on #sliderContainer in paper-slider.html. */ - margin-inline-end: - calc(-15px - var(--calculated-paper-slider-height) / 2); + margin-inline-end: -16px; } cr-policy-pref-indicator { @@ -55,9 +52,8 @@ <cr-policy-pref-indicator pref="[[pref]]"></cr-policy-pref-indicator> </template> <div class="outer"> - <cr-slider id="slider" disabled$="[[disableSlider_]]" snaps - on-immediate-value-changed="onSliderChanged_" max="[[max]]" - min="[[min]]"> + <cr-slider id="slider" disabled$="[[disableSlider_]]" ticks="[[ticks]]" + on-value-changed="onSliderChanged_" max="[[max]]" min="[[min]]"> </cr-slider> <div id="labels" disabled$="[[disableSlider_]]"> <div id="label-begin">[[labelMin]]</div>
diff --git a/chrome/browser/resources/settings/controls/settings_slider.js b/chrome/browser/resources/settings/controls/settings_slider.js index 5131b2d..d9f79075 100644 --- a/chrome/browser/resources/settings/controls/settings_slider.js +++ b/chrome/browser/resources/settings/controls/settings_slider.js
@@ -7,9 +7,6 @@ * settings-slider wraps a paper-slider. It maps the slider's values from a * linear UI range to a range of real values. When |value| does not map exactly * to a tick mark, it interpolates to the nearest tick. - * - * Unlike paper-slider, there is no distinction between value and - * immediateValue; when either changes, the |value| property is updated. */ Polymer({ is: 'settings-slider', @@ -20,16 +17,19 @@ /** @type {!chrome.settingsPrivate.PrefObject} */ pref: Object, - /** @type {!Array<number>} Values corresponding to each tick. */ - tickValues: { + /** + * Values corresponding to each tick. + * @type {!Array<cr_slider.SliderTick>|!Array<number>} + */ + ticks: { type: Array, value: () => [], }, /** * A scale factor used to support fractional pref values since paper-slider - * only supports integers. This is not compatible with |tickValues|, - * i.e. if |scale| is not 1 then |tickValues| must be empty. + * only supports integers. This is not compatible with |ticks|, + * i.e. if |scale| is not 1 then |ticks| must be empty. */ scale: { type: Number, @@ -46,30 +46,55 @@ disabled: Boolean, + showMarkers: Boolean, + /** @private */ disableSlider_: { - computed: 'computeDisableSlider_(pref.*, disabled)', + computed: 'computeDisableSlider_(pref.*, disabled, ticks.*)', type: Boolean, }, + + loaded_: Boolean, }, observers: [ - 'valueChanged_(pref.*, tickValues.*)', + 'valueChanged_(pref.*, ticks.*, loaded_)', ], + attached: function() { + this.loaded_ = true; + }, + + /** + * @param {number|cr_slider.SliderTick} tick + * @return {number|undefined} + */ + getTickValue_: function(tick) { + return typeof tick == 'object' ? tick.value : tick; + }, + + /** + * @param {number} index + * @return {number|undefined} + * @private + */ + getTickValueAtIndex_: function(index) { + return this.getTickValue_(this.ticks[index]); + }, + /** * Sets the |pref.value| property to the value corresponding to the knob * position after a user action. * @private */ onSliderChanged_: function() { - const sliderValue = isNaN(this.$.slider.immediateValue) ? - this.$.slider.value : - this.$.slider.immediateValue; + if (!this.loaded_) + return; + const sliderValue = this.$.slider.value; let newValue; - if (this.tickValues && this.tickValues.length > 0) - newValue = this.tickValues[sliderValue]; + if (this.ticks && this.ticks.length > 0) + newValue = this.getTickValueAtIndex_(sliderValue); else newValue = sliderValue / this.scale; @@ -88,70 +113,48 @@ * @private */ valueChanged_: function() { - if (this.pref == undefined) + if (this.pref == undefined || !this.loaded_) return; - // If |tickValues| is empty, simply set current value to the slider. - if (this.tickValues.length == 0) { - this.$.slider.value = - /** @type {number} */ (this.pref.value) * this.scale; + // First update the slider settings if |ticks| was set. + const numTicks = this.ticks.length; + if (numTicks == 1) { + this.$.slider.disabled = true; return; } - assert(this.scale == 1); - // First update the slider settings if |tickValues| was set. - const numTicks = Math.max(1, this.tickValues.length); - this.$.slider.max = numTicks - 1; + const prefValue = /** @type {number} */ (this.pref.value); + // If |ticks| is empty, simply set current value to the slider. + if (numTicks == 0) { + this.$.slider.value = prefValue * this.scale; + return; + } + + assert(this.scale == 1); // Limit the number of ticks to 10 to keep the slider from looking too busy. const MAX_TICKS = 10; - this.$.slider.snaps = numTicks < MAX_TICKS; - this.$.slider.maxMarkers = numTicks < MAX_TICKS ? numTicks : 0; + this.$.slider.markerCount = + (this.showMarkers || numTicks <= MAX_TICKS) ? numTicks : 0; - if (this.$.slider.dragging && this.tickValues.length > 0 && - this.pref.value != this.tickValues[this.$.slider.immediateValue]) { + const tickValue = this.getTickValueAtIndex_(this.$.slider.value); + if (this.$.slider.dragging && this.pref.value != tickValue) { // The value changed outside settings-slider but we're still holding the // knob, so set the value back to where the knob was. // Async so we don't confuse Polymer's data binding. - this.async(function() { - const newValue = this.tickValues[this.$.slider.immediateValue]; - this.set('pref.value', newValue); + this.async(() => { + this.set('pref.value', tickValue); }); return; } // Convert from the public |value| to the slider index (where the knob // should be positioned on the slider). - let sliderIndex = this.tickValues.length > 0 ? - this.tickValues.indexOf(/** @type {number} */ (this.pref.value)) : - 0; - if (sliderIndex == -1) { - // No exact match. - sliderIndex = this.findNearestIndex_( - this.tickValues, - /** @type {number} */ (this.pref.value)); - } - this.$.slider.value = sliderIndex; - }, - - /** - * Returns the index of the item in |arr| closest to |value|. - * @param {!Array<number>} arr - * @param {number} value - * @return {number} - * @private - */ - findNearestIndex_: function(arr, value) { - let closestIndex; - let minDifference = Number.MAX_VALUE; - for (let i = 0; i < arr.length; i++) { - const difference = Math.abs(arr[i] - value); - if (difference < minDifference) { - closestIndex = i; - minDifference = difference; - } - } - - assert(typeof closestIndex != 'undefined'); - return closestIndex; + this.$.slider.value = + this.ticks.map(tick => Math.abs(this.getTickValue_(tick) - prefValue)) + .reduce( + (acc, diff, index) => diff < acc.diff ? {index, diff} : acc, + {index: -1, diff: Number.MAX_VALUE}) + .index; + assert(this.$.slider.value != -1); }, });
diff --git a/chrome/browser/resources/settings/device_page/BUILD.gn b/chrome/browser/resources/settings/device_page/BUILD.gn index ddcc588..2bb5b80 100644 --- a/chrome/browser/resources/settings/device_page/BUILD.gn +++ b/chrome/browser/resources/settings/device_page/BUILD.gn
@@ -11,7 +11,6 @@ ":display", ":display_layout", ":display_overscan_dialog", - ":display_size_slider", ":drag_behavior", ":drive_cache_dialog", ":keyboard", @@ -72,8 +71,8 @@ js_library("display") { deps = [ ":display_layout", - ":display_size_slider", "../controls:settings_dropdown_menu", + "../controls:settings_slider", "../prefs:prefs_behavior", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:cr", @@ -124,24 +123,11 @@ js_library("night_light_slider") { deps = [ "../prefs:prefs_behavior", - "//third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior-extracted", "//third_party/polymer/v1_0/components-chromium/iron-resizable-behavior:iron-resizable-behavior-extracted", "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-inky-focus-behavior-extracted", ] } -js_library("display_size_slider") { - deps = [ - "../prefs:prefs_behavior", - "//third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior-extracted", - "//third_party/polymer/v1_0/components-chromium/iron-range-behavior:iron-range-behavior-extracted", - "//third_party/polymer/v1_0/components-chromium/iron-resizable-behavior:iron-resizable-behavior-extracted", - "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-inky-focus-behavior-extracted", - "//third_party/polymer/v1_0/components-chromium/paper-progress:paper-progress-extracted", - "//ui/webui/resources/cr_elements/policy:cr_policy_pref_behavior", - ] -} - js_library("power") { deps = [ ":device_page_browser_proxy",
diff --git a/chrome/browser/resources/settings/device_page/display.html b/chrome/browser/resources/settings/device_page/display.html index f271dcdc..8c7b7425 100644 --- a/chrome/browser/resources/settings/device_page/display.html +++ b/chrome/browser/resources/settings/device_page/display.html
@@ -14,7 +14,6 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-tabs/paper-tabs.html"> <link rel="import" href="display_layout.html"> <link rel="import" href="display_overscan_dialog.html"> -<link rel="import" href="display_size_slider.html"> <link rel="import" href="night_light_slider.html"> <link rel="import" href="../controls/settings_dropdown_menu.html"> <link rel="import" href="../controls/settings_slider.html"> @@ -147,12 +146,12 @@ [[logicalResolutionText_]] </div> </div> - <display-size-slider id="displaySizeSlider" + <settings-slider id="displaySizeSlider" ticks="[[zoomValues_]]" pref="{{selectedZoomPref_}}" - min-label="$i18n{displaySizeSliderMinLabel}" - max-label="$i18n{displaySizeSliderMaxLabel}" - on-immediate-value-changed="onDisplaySizeSliderDrag_"> - </display-size-slider> + label-min="$i18n{displaySizeSliderMinLabel}" + label-max="$i18n{displaySizeSliderMaxLabel}" + on-value-changed="onDisplaySizeSliderDrag_"> + </settings-slider> </div> <!-- Drop down select menu for resolution -->
diff --git a/chrome/browser/resources/settings/device_page/display.js b/chrome/browser/resources/settings/device_page/display.js index cde11ae..e3c2898 100644 --- a/chrome/browser/resources/settings/device_page/display.js +++ b/chrome/browser/resources/settings/device_page/display.js
@@ -102,7 +102,9 @@ /** @private {!Array<number>} Mode index values for slider. */ modeValues_: Array, - /** @private {SliderTicks} Display zoom slider tick values. */ + /** + * @private {!Array<cr_slider.SliderTick>} Display zoom slider tick values. + */ zoomValues_: Array, /** @private {!DropdownMenuOptionList} */ @@ -331,19 +333,17 @@ * Given the display with the current display mode, this function lists all * the display zoom values and their labels to be used by the slider. * @param {!chrome.system.display.DisplayUnitInfo} selectedDisplay - * @return {SliderTicks} + * @return {!Array<cr_slider.SliderTick>} */ getZoomValues_: function(selectedDisplay) { - /** @type {SliderTicks} */ - let zoomValues = []; - for (let i = 0; i < selectedDisplay.availableDisplayZoomFactors.length; - i++) { - const value = selectedDisplay.availableDisplayZoomFactors[i]; + return selectedDisplay.availableDisplayZoomFactors.map(value => { const ariaValue = Math.round(value * 100); - const label = this.i18n('displayZoomValue', ariaValue.toString()); - zoomValues.push({value: value, label: label, ariaValue: ariaValue}); - } - return zoomValues; + return { + value, + ariaValue, + label: this.i18n('displayZoomValue', ariaValue.toString()) + }; + }); }, /** @@ -621,6 +621,8 @@ * @private */ onDisplaySizeSliderDrag_: function(e) { + if (!this.selectedDisplay) + return; this.updateLogicalResolutionText_(/** @type {number} */ (e.detail.value)); },
diff --git a/chrome/browser/resources/settings/device_page/display_size_slider.html b/chrome/browser/resources/settings/device_page/display_size_slider.html deleted file mode 100644 index 93757c4e..0000000 --- a/chrome/browser/resources/settings/device_page/display_size_slider.html +++ /dev/null
@@ -1,230 +0,0 @@ -<link rel="import" href="chrome://resources/html/polymer.html"> - -<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_behavior.html"> -<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-behaviors/paper-inky-focus-behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-range-behavior/iron-range-behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-resizable-behavior/iron-resizable-behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-progress/paper-progress.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> -<link rel="import" href="../prefs/prefs_behavior.html"> - -<dom-module id="display-size-slider"> - <template> - <style> - :host { - cursor: default; - display: inline-flex; - font-weight: 500; - - /* Counteract the margin on #sliderContainer and match the margin from - settings-slider.html */ - margin-inline-end: -16px; - - min-width: 200px; - text-align: center; - user-select: none; - } - - /* focus shows the ripple */ - :host(:focus) { - outline: none; - } - - :host-context([dir='rtl']) #sliderContainer { - transform: scaleX(-1); - } - - /* We dont want the text to be flipped in rtl */ - :host-context([dir='rtl']) #labelText, - :host-context([dir='rtl']) #subLabelContainer { - transform: scaleX(-1); - } - - #sliderContainer { - display: inline-table; - height: 32px; - margin-left: 16px; - margin-right: 16px; - position: relative; - width: 100%; - } - - #sliderContainer:focus { - outline: 0; - } - - #labelContainer { - bottom: 36px; - display: none; - height: 1.75em; - position: absolute; - width: inherit; - z-index: 10; - } - - #sliderContainer:hover #labelContainer, - .hover #labelContainer, - :host([hold-down_]) #labelContainer { - display: block; - } - - .label { - background: var(--google-blue-600); - border-radius: 14px; - color: white; - font-size: 12px; - left: 0; - line-height: 1.5em; - padding: 0 8px; - position: absolute; - text-align: center; - transform: translateX(-50%); - transition: margin-top 200ms cubic-bezier(0, 0, 0.2, 1); - vertical-align: middle; - white-space: nowrap; - width: auto; - } - - .bar-container { - bottom: 0; - left: 0; - overflow: hidden; - position: absolute; - right: 0; - top: 0; - } - - .slider-markers { - box-sizing: border-box; - height: 2px; - left: 0; - pointer-events: none; - position: absolute; - right: -1px; - top: 15px; - @apply --layout-horizontal; - } - - .slider-marker { - @apply --layout-flex; - } - .slider-markers::after, - .slider-marker::after { - background-color: rgba(255, 255, 255, 0.54); - border-radius: 50%; - content: ''; - display: block; - height: 2px; - margin-left: -1px; - width: 2px; - } - - #sliderBar { - --paper-progress-height: 2px; - background-color: transparent; - padding: 15px 0; - width: 100%; - } - - .slider-knob { - height: 32px; - left: 0; - margin-left: -16px; - position: absolute; - top: 0; - width: 32px; - } - - .slider-knob:focus { - outline: none; - } - - .slider-knob-inner { - background-color: var(--google-blue-600); - border: 0; - border-radius: 50%; - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.4); - box-sizing: content-box; - height: 10px; - margin: 11px; - width: 10px; - } - - paper-ripple { - color: var(--google-blue-600); - } - - #subLabelContainer { - display: flex; - flex-direction: row; - justify-content: space-between; - padding-top: 24px; - pointer-events: none; - } - - #subLabelContainer > div { - font-size: 12px; - font-weight: normal; - } - - paper-progress { - --paper-progress-active-color: var(--google-blue-600); - --paper-progress-container-color: var(--google-blue-600-opacity-24); - --paper-progress-disabled-active-color: var(--google-grey-600); - } - - paper-progress[disabled] { - --paper-progress-container-color: var(--google-grey-600-opacity-24); - } - - /* Styles for disabled state */ - #sliderContainer.disabled { - pointer-events: none; - } - - #subLabelContainer[disabled] { - color: var(--google-grey-600); - } - - .slider-knob-inner[disabled] { - background-color: var(--google-grey-600); - border: 2px solid white; - box-shadow: unset; - margin: 9px; - } - </style> - <div id="sliderContainer" class$="[[getClassNames_(disabled, dragging)]]"> - <div id="labelContainer" aria-label="[[getLabelForIndex_(ticks, index)]]"> - <div id="label" class="label"> - <div id="labelText"> - [[getLabelForIndex_(ticks, index)]] - </div> - </div> - </div> - <div class="bar-container" aria-hidden="true"> - <paper-progress id="sliderBar" disabled$="[[disabled]]" - on-down="onBarDown_" on-up="onBarUp_" on-track="knobTrack_" - value="[[index]]" min="[[min]]" max="[[max]]"> - </paper-progress> - </div> - - - <div class="slider-markers"> - <template is="dom-repeat" items="[[markers]]"> - <div class="slider-marker"></div> - </template> - </div> - - <div id="sliderKnob" class="slider-knob" on-track="knobTrack_"> - <div class="slider-knob-inner" disabled$="[[disabled]]"></div> - </div> - <div id="subLabelContainer" disabled$="[[disabled]]"> - <div id="subLabelMin">[[minLabel]]</div> - <div id="subLabelMax">[[maxLabel]]</div> - </div> - </div> - </template> - <script src="display_size_slider.js"></script> -</dom-module>
diff --git a/chrome/browser/resources/settings/device_page/display_size_slider.js b/chrome/browser/resources/settings/device_page/display_size_slider.js deleted file mode 100644 index 7dd8f904a..0000000 --- a/chrome/browser/resources/settings/device_page/display_size_slider.js +++ /dev/null
@@ -1,538 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview - * display-size-slider is used to change the value of a pref via a slider - * control. This specific slider is used instead of the settings-slider due to - * its implementation of the tool tip that displays the current slider value. - * This component fires a |immediate-value-changed| event while the dragging is - * active. This event includes the immediate value of the slider. - * - * TODO (crbug.com/858882): this control should be replaced with a common - * control like settings-slider or cr-slider. - */ - -/** - * The |value| is the corresponding value that the current slider tick is - * assocated with. The string |label| is shown in the ui as the label for the - * current slider value. The |ariaValue| number is used for aria-valuemin, - * aria-valuemax, and aria-valuenow, and is optional. If missing, |value| will - * be used instead. - * @typedef {{ - * value: !number, - * label: !string, - * ariaValue: (number|undefined), - * }} - */ -let SliderTick; - -/** - * @typedef {!Array<SliderTick>} - */ -let SliderTicks; - -(function() { - -Polymer({ - is: 'display-size-slider', - - behaviors: [ - CrPolicyPrefBehavior, - Polymer.IronA11yKeysBehavior, - Polymer.IronRangeBehavior, - Polymer.IronResizableBehavior, - Polymer.PaperInkyFocusBehavior, - PrefsBehavior, - ], - - properties: { - /** The slider is disabled if true. */ - disabled: {type: Boolean, value: false, readOnly: true}, - - /** True when the user is dragging the slider knob. */ - dragging: {type: Boolean, value: false, readOnly: true}, - - /** @type {number} The index for the current slider value in |ticks|. */ - index: { - type: Number, - value: 0, - readOnly: true, - observer: 'onIndexChanged_', - }, - - /** @type {string} The label for the minimum slider value */ - minLabel: {type: String, value: ''}, - - /** @type {string} The label for the maximum slider value */ - maxLabel: {type: String, value: ''}, - - /** - * Each item in the array represents a UI element corresponding to a tick - * value. - * @type {!Array<number>} - */ - markers: { - type: Array, - readOnly: true, - value: function() { - return []; - } - }, - - /** @type {!chrome.settingsPrivate.PrefObject} */ - pref: Object, - - /** - * The data associated with each tick on the slider. Each element in the - * array contains a value and the label corresponding to that value. - * @type {SliderTicks} - */ - ticks: { - type: Array, - value: () => [], - }, - - /** @private */ - holdDown_: { - type: Boolean, - value: false, - reflectToAttribute: true, - }, - }, - - listeners: { - 'blur': 'onBlur_', - 'focus': 'onFocus_', - 'keydown': 'onKeyDown_', - 'pointerdown': 'onPointerDown_', - 'pointerup': 'onPointerUp_', - }, - - observers: [ - 'updateIndex_(pref.value)', - 'updateSliderParams_(ticks)', - 'updateMarkers_(min, max)', - 'updateDisabled_(ticks, pref.*)', - ], - - hostAttributes: {role: 'slider', tabindex: 0}, - - keyBindings: { - 'left': 'leftKeyPress_', - 'right': 'rightKeyPress_', - 'up': 'increment_', - 'down': 'decrement_', - 'pagedown home': 'resetToMinIndex_', - 'pageup end': 'resetToMaxIndex_', - }, - - /** @override */ - ready: function() { - chrome.settingsPrivate.onPrefsChanged.addListener((prefs) => { - prefs.forEach((pref) => { - if (pref.key == this.pref.key && this.pref.value != pref.value) - this.pref.value = pref.value; - }); - }); - }, - - /** @private {boolean} */ - usedMouse_: false, - - get _isRTL() { - if (this.__isRTL === undefined) { - this.__isRTL = window.getComputedStyle(this)['direction'] === 'rtl'; - } - return this.__isRTL; - }, - - /** @private */ - setRippleHoldDown_: function(holdDown) { - this.ensureRipple(); - this._ripple.holdDown = holdDown; - this.holdDown_ = holdDown; - }, - - /** @private */ - onFocus_: function() { - this.setRippleHoldDown_(true); - }, - - /** @private */ - onBlur_: function() { - this.setRippleHoldDown_(false); - }, - - /** @private */ - onChange_: function() { - this.setRippleHoldDown_(!this.usedMouse_); - this.usedMouse_ = false; - }, - - /** @private */ - onKeyDown_: function() { - this.usedMouse_ = false; - if (!this.disabled) - this.onFocus_(); - }, - - /** - * @param {!MouseEvent} event - * @private - */ - onPointerDown_: function(event) { - if (this.disabled || event.button != 0) { - event.preventDefault(); - return; - } - this.usedMouse_ = true; - this.setRippleHoldDown_(false); - setTimeout(() => { - this.setRippleHoldDown_(true); - }); - }, - - /** - * @param {!MouseEvent} event - * @private - */ - onPointerUp_: function(event) { - if (event.button != 0) - return; - this.setRippleHoldDown_(false); - }, - - /** - * Clamps the value of |newIndex| to IronRangeBehavior's max/min bounds and - * updates the value for |index|. - * @param {number} newIndex The new value for index that needs to be set. - * @private - */ - clampAndSetIndex_: function(newIndex) { - newIndex = this.clampToRange_(newIndex, this.min, this.max); - if (newIndex != this.index) { - this._setIndex(newIndex); - this.setAttribute( - 'aria-valuenow', this.getAriaValueForIndex_(this.ticks, this.index)); - this.setAttribute( - 'aria-valuetext', this.getLabelForIndex_(this.ticks, this.index)); - if (this.dragging) { - this.fire( - 'immediate-value-changed', {value: this.ticks[newIndex].value}); - } - } - }, - - /** - * Clamps the value of |newIndex| to IronRangeBehavior's max/min bounds and - * updates the value of |pref| to this clamped value. - * @param {number} newIndex The new value for index that needs to be set. - * @private - */ - clampIndexAndUpdatePref_: function(newIndex) { - newIndex = this.clampToRange_(newIndex, this.min, this.max); - if (this.ticks[newIndex].value != this.pref.value) - this.set('pref.value', this.ticks[newIndex].value); - this.onChange_(); - }, - - /** - * Clamps and returns the given |value| within the |min| and |max| range. - * @param {number} value The number to clamp. - * @param {number} min The minimum value in range. Any value below this will - * be clamped to |min|. - * @param {number} max The maximum value in range. Any value above this will - * be clamped to |max|. - * @return {number} - * @private - */ - clampToRange_: function(value, min, max) { - return Math.max(Math.min(value, max), min); - }, - - /** - * Overrides _createRipple from PaperInkyFocusBehavior to set the ripple - * container as the slider knob before creating the ripple animation. Without - * this the PaperInkyFocusBehavior does not know where to create the ripple - * animation. - * @protected - */ - _createRipple: function() { - this._rippleContainer = this.$.sliderKnob; - return Polymer.PaperInkyFocusBehaviorImpl._createRipple.call(this); - }, - - /** @private Safely decrements the slider index value by 1 and updates pref */ - decrement_: function() { - this.clampIndexAndUpdatePref_(this.index - 1); - }, - - /** - * Returns a string concatenated list of class names based on whether the - * corresponding properties are set. - * @return {string} - */ - getClassNames_: function() { - return this.mergeClasses_({ - disabled: this.disabled, - dragging: this.dragging, - }); - }, - - /** - * Returns the current label for the selected slider index. - * @param {SliderTicks} ticks Slider label and corresponding value for each - * tick. - * @param {number} index Index of the slider tick with the desired label. - * @return {string} - */ - getLabelForIndex_: function(ticks, index) { - if (!ticks || ticks.length == 0 || index >= ticks.length) - return ''; - return ticks[index].label; - }, - - /** - * Returns the aria value for a selected slider index. aria-valuenow, - * aria-valuemin and aria-valuemax are expected to be a numbers, so sliders - * which use strings for labels should populate the ariaValue with a number - * as well. - * @param {SliderTicks} ticks Slider label and corresponding value for each - * tick. - * @param {number} index Index of the slider tick with the desired label. - * @return {number|string} Returns the empty string if there is not tick at - * the given index. - */ - getAriaValueForIndex_: function(ticks, index) { - if (!ticks || ticks.length == 0 || index >= ticks.length) - return ''; - // ariaValue factored out for closure compilation. - let ariaValue = ticks[index].ariaValue; - return ariaValue !== undefined ? ariaValue : ticks[index].value; - }, - - /** @private Safely increments the slider index value by 1 and updates pref */ - increment_: function() { - this.clampIndexAndUpdatePref_(this.index + 1); - }, - - /** - * Handles the mouse drag and drop event for slider knob from start to end. - * @param {Event} event - * @private - */ - knobTrack_: function(event) { - switch (event.detail.state) { - case 'start': - this.knobTrackStart_(); - break; - case 'track': - this.knobTrackDrag_(event); - break; - case 'end': - this.knobTrackEnd_(event); - break; - } - }, - - /** - * Handles the drag event for the slider knob. - * @param {!Event} event - * @private - */ - knobTrackDrag_: function(event) { - // Distance travelled during mouse drag. - const dx = event.detail.dx; - - // Total width of the progress bar in CSS pixels. - const totalWidth = this.$.sliderBar.offsetWidth; - - // Distance between 2 consecutive tick markers. - const tickWidth = totalWidth / (this.ticks.length - 1); - - // Number of ticks covered by |dx|. - let dxInTicks = Math.round(dx / tickWidth); - - if (this._isRTL) - dxInTicks *= -1; - - let nextIndex = this.startIndex_ + dxInTicks; - - this.clampAndSetIndex_(nextIndex); - }, - - /** - * Handles the end of slider knob drag event. - * @param {!Event} event - * @private - */ - knobTrackEnd_: function(event) { - this._setDragging(false); - - // Update the pref once user stops dragging and releases mouse. - if (this.index != this.startIndex_) - this.clampIndexAndUpdatePref_(this.index); - }, - - /** - * Handles the start of the slider knob drag event. - * @private - */ - knobTrackStart_: function() { - this.startIndex_ = this.index; - this._setDragging(true); - }, - - /** @private Handles the 'left' key press. */ - leftKeyPress_: function() { - this._isRTL ? this.increment_() : this.decrement_(); - }, - - /** - * Returns a concatenated string of classnames based on the boolean table - * |classes|. - * @param {!Object<string, boolean>} classes An object mapping between - * classnames and boolean. The boolean for the corresponding classname is - * true if that classname needs to be present in the returned string. - * @return {string} - * @private - */ - mergeClasses_: function(classes) { - return Object.keys(classes) - .filter(function(className) { - return classes[className]; - }) - .join(' '); - }, - - /** - * Handles the event where the user clicks or taps on the slider bar directly. - * @param {!Event} event - * @private - */ - onBarDown_: function(event) { - const barWidth = this.$.sliderBar.offsetWidth; - const barOriginX = this.$.sliderBar.getBoundingClientRect().left; - let eventOffsetFromOriginX = event.detail.x - barOriginX; - if (this._isRTL) - eventOffsetFromOriginX = barWidth - eventOffsetFromOriginX; - const tickWidth = barWidth / (this.ticks.length - 1); - let newTickIndex = Math.round(eventOffsetFromOriginX / tickWidth); - this._setDragging(true); - this.startIndex_ = this.index; - - // Update the index but dont update the pref until mouse is released. - this.clampAndSetIndex_(newTickIndex); - }, - - /** - * Handles the event of mouse up from the slider bar. - * @private - */ - onBarUp_: function() { - if (this.dragging) - this._setDragging(false); - if (this.startIndex_ != this.index) - this.clampIndexAndUpdatePref_(this.index); - }, - - /** @private Handles the 'right' key press. */ - rightKeyPress_: function() { - this._isRTL ? this.decrement_() : this.increment_(); - }, - - /** @private Handles the 'end' and 'page up' key press. */ - resetToMaxIndex_: function() { - this.clampIndexAndUpdatePref_(this.max); - }, - - /** @private Handles the 'home' and 'page down' key press. */ - resetToMinIndex_: function() { - this.clampIndexAndUpdatePref_(this.min); - }, - - /** - * Sets the disabled property if there are no tick values or if the pref - * cannot be modified by the user. - * @private - */ - updateDisabled_: function() { - let disabled = false; - - // Disabled if no tick values are set for the slider. - if (!this.ticks || this.ticks.length <= 1) - disabled |= true; - - - // Disabled if the pref cannot be modified. - disabled |= this.isPrefEnforced(); - - this._setDisabled(!!disabled); - }, - - /** - * Updates the value for |index| based on the current set value of |pref|. - * @private - */ - updateIndex_: function() { - if (!this.ticks || this.ticks.length == 0) - return; - if (!this.pref || typeof(this.pref.value) != 'number') - return; - let resolvedTick = this.ticks.length - 1; - for (let i = 0; i < this.ticks.length; i++) { - if (this.ticks[i].value >= this.pref.value) { - resolvedTick = i; - break; - } - } - this._setIndex(resolvedTick); - this.setAttribute( - 'aria-valuenow', this.getAriaValueForIndex_(this.ticks, this.index)); - this.setAttribute( - 'aria-valuetext', this.getLabelForIndex_(this.ticks, this.index)); - }, - - /** - * Updates the knob position based on the the value of progress indicator. - * @private - */ - onIndexChanged_: function() { - this._setRatio(this._calcRatio(this.index) * 100); - - this.$.sliderKnob.style.left = this.ratio + '%'; - this.$.label.style.left = this.ratio + '%'; - }, - - /** - * Initializes the |markers| array based on the number of ticks. - * @private - */ - updateMarkers_: function(min, max) { - let steps = Math.round((max - min) / this.step); - if (steps < 0 || !isFinite(steps)) - steps = 0; - this._setMarkers(new Array(steps)); - }, - - /** - * Updates the min and max possible values for the slider. - * @private - */ - updateSliderParams_: function() { - this.min = 0; - if (this.ticks.length == 0) { - this.max = 0; - return; - } - this.max = this.ticks.length - 1; - this.setAttribute( - 'aria-valuemin', this.getAriaValueForIndex_(this.ticks, this.min)); - this.setAttribute( - 'aria-valuemax', this.getAriaValueForIndex_(this.ticks, this.max)); - this.updateIndex_(); - }, -}); -})();
diff --git a/chrome/browser/resources/settings/device_page/keyboard.html b/chrome/browser/resources/settings/device_page/keyboard.html index 415d4d6..9771d71 100644 --- a/chrome/browser/resources/settings/device_page/keyboard.html +++ b/chrome/browser/resources/settings/device_page/keyboard.html
@@ -100,7 +100,7 @@ <div class="start" id="repeatDelayLabel">$i18n{keyRepeatDelay}</div> <settings-slider id="delaySlider" pref="{{prefs.settings.language.xkb_auto_repeat_delay_r2}}" - tick-values="[[autoRepeatDelays_]]" + ticks="[[autoRepeatDelays_]]" disabled="[[ !prefs.settings.language.xkb_auto_repeat_enabled_r2.value]]" aria-labelledby="repeatDelayLabel" @@ -113,7 +113,7 @@ <settings-slider id="repeatRateSlider" pref="{{ prefs.settings.language.xkb_auto_repeat_interval_r2}}" - tick-values="[[autoRepeatIntervals_]]" + ticks="[[autoRepeatIntervals_]]" disabled="[[ !prefs.settings.language.xkb_auto_repeat_enabled_r2.value]]" aria-labelledby="repeatRateLabel"
diff --git a/chrome/browser/resources/settings/device_page/night_light_slider.html b/chrome/browser/resources/settings/device_page/night_light_slider.html index 809bec10..ceec80b 100644 --- a/chrome/browser/resources/settings/device_page/night_light_slider.html +++ b/chrome/browser/resources/settings/device_page/night_light_slider.html
@@ -1,7 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-resizable-behavior/iron-resizable-behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-behaviors/paper-inky-focus-behavior.html"> <link rel="import" href="../prefs/prefs_behavior.html"> @@ -105,7 +104,8 @@ width: 100%; } - .markers { + .active-marker, + .inactive-marker { background-color: rgba(255, 255, 255, 0.54); border-radius: 50%; display: block; @@ -117,6 +117,10 @@ z-index: 2; } + .inactive-marker { + background-color: rgba(26, 115, 232, 0.54); + } + #legendContainer { height: 10px; position: relative; @@ -159,13 +163,11 @@ <div id="markersContainer"> </div> <div id="startKnob" class="knob" tabindex="1" on-down="startDrag_" - on-up="endDrag_" on-track="continueDrag_" on-focus="onFocus_" - on-blur="onBlur_"> + on-up="endDrag_" on-track="continueDrag_"> <div class="knob-inner" tabindex="-1"></div> </div> <div id="endKnob" class="knob" tabindex="2" on-down="startDrag_" - on-up="endDrag_" on-track="continueDrag_" on-focus="onFocus_" - on-blur="onBlur_"> + on-up="endDrag_" on-track="continueDrag_"> <div class="knob-inner" tabindex="-1"></div> </div> </div>
diff --git a/chrome/browser/resources/settings/device_page/night_light_slider.js b/chrome/browser/resources/settings/device_page/night_light_slider.js index 7003fd0..7164374 100644 --- a/chrome/browser/resources/settings/device_page/night_light_slider.js +++ b/chrome/browser/resources/settings/device_page/night_light_slider.js
@@ -16,12 +16,32 @@ const OFFSET_MINUTES_6PM = 18 * 60; const TOTAL_MINUTES_PER_DAY = 24 * 60; +/** + * % is the javascript remainder operator that satisfies the following for the + * resultant z given the operands x and y as in (z = x % y): + * 1. x = k * y + z + * 2. k is an integer. + * 3. |z| < |y| + * 4. z has the same sign as x. + * + * It is more convenient to have z be the same sign as y. In most cases y + * is a positive integer, and it is more intuitive to have z also be a positive + * integer (0 <= z < y). + * + * For example (-1 % 24) equals -1 whereas modulo(-1, 24) equals 23. + * @param {number} x + * @param {number} y + * @return {number} + */ +function modulo(x, y) { + return ((x % y) + y) % y; +} + Polymer({ is: 'night-light-slider', behaviors: [ PrefsBehavior, - Polymer.IronA11yKeysBehavior, Polymer.IronResizableBehavior, Polymer.PaperInkyFocusBehavior, ], @@ -49,38 +69,28 @@ listeners: { 'iron-resize': 'onResize_', + focus: 'onFocus_', + blur: 'onBlur_', + keydown: 'onKeyDown_', }, observers: [ 'updateKnobs_(prefs.ash.night_light.custom_start_time.*, ' + 'prefs.ash.night_light.custom_end_time.*, isRTL_, isReady_)', 'hourFormatChanged_(prefs.settings.clock.use_24hour_clock.*)', + 'updateMarkers_(prefs.ash.night_light.custom_start_time.*, ' + + 'prefs.ash.night_light.custom_end_time.*, isRTL_, isReady_)', ], - keyBindings: { - 'left': 'onLeftKey_', - 'right': 'onRightKey_', - }, - /** * The object currently being dragged. Either the start or end knobs. - * @type {?Object} + * @type {Element} * @private */ dragObject_: null, /** @override */ attached: function() { - // Build the legend markers. - const markersContainer = this.$.markersContainer; - const width = markersContainer.offsetWidth; - for (let i = 0; i <= HOURS_PER_DAY; ++i) { - const marker = document.createElement('div'); - marker.className = 'markers'; - markersContainer.appendChild(marker); - marker.style.left = (i * 100 / HOURS_PER_DAY) + '%'; - } - this.isRTL_ = window.getComputedStyle(this).direction == 'rtl'; this.$.sliderContainer.addEventListener('contextmenu', function(e) { @@ -100,6 +110,51 @@ }, /** + * @return {boolean} + * @private + */ + prefsAvailable: function() { + return ['custom_start_time', 'custom_end_time'] + .map(key => `prefs.ash.night_light.${key}.value`) + .every(path => this.get(path) != undefined); + }, + + /** @private */ + updateMarkers_: function() { + if (!this.isReady_ || !this.prefsAvailable()) + return; + + const startHour = + /** @type {number} */ ( + this.getPref('ash.night_light.custom_start_time').value) / + 60.0; + const endHour = /** @type {number} */ ( + this.getPref('ash.night_light.custom_end_time').value) / + 60.0; + + const markersContainer = this.$.markersContainer; + markersContainer.innerHTML = ''; + for (let i = 0; i <= HOURS_PER_DAY; ++i) { + const marker = document.createElement('div'); + + const hourIndex = this.isRTL_ ? 24 - i : i; + // Rotate around clock by 18 hours for the 6pm start. + const hour = (hourIndex + 18) % 24; + if (startHour < endHour) { + marker.className = hour > startHour && hour < endHour ? + 'active-marker' : + 'inactive-marker'; + } else { + marker.className = hour > endHour && hour < startHour ? + 'inactive-marker' : + 'active-marker'; + } + markersContainer.appendChild(marker); + marker.style.left = (i * 100 / HOURS_PER_DAY) + '%'; + } + }, + + /** * Invoked when the element is resized and the knobs positions need to be * updated. * @private @@ -131,24 +186,6 @@ }, /** - * Expands or un-expands the knob being dragged along with its corresponding - * label bubble. - * @param {boolean} expand True to expand, and false to un-expand. - * @private - */ - setExpanded_: function(expand) { - let knob = this.$.startKnob; - let label = this.$.startLabel; - if (this.dragObject_ == this.$.endKnob) { - knob = this.$.endKnob; - label = this.$.endLabel; - } - - knob.classList.toggle('expanded-knob', expand); - label.classList.toggle('expanded-knob', expand); - }, - - /** * If one of the two knobs is focused, this function blurs it. * @private */ @@ -160,6 +197,7 @@ /** * Start dragging the target knob. + * @param {!Event} event * @private */ startDrag_: function(event) { @@ -177,19 +215,14 @@ return; } - this.setExpanded_(true); + this.handleKnobEvent_(event, this.dragObject_); - // Focus is only given to the knobs by means of keyboard tab navigations. - // When we start dragging, we don't want to see any focus halos around any - // knob. - this.blurAnyFocusedKnob_(); - - // However, our night-light-slider element must get the focus. - this.focus(); + this.valueAtDragStart_ = this.getPrefValue_(this.dragObject_); }, /** * Continues dragging the selected knob if any. + * @param {!Event} event * @private */ continueDrag_: function(event) { @@ -211,40 +244,47 @@ }, /** + * Converts horizontal pixels into number of minutes. + * @param {number} deltaX + * @return {number} + * @private + */ + getDeltaMinutes_: function(deltaX) { + return (this.isRTL_ ? -1 : 1) * + Math.floor( + TOTAL_MINUTES_PER_DAY * deltaX / this.$.sliderBar.offsetWidth); + }, + + /** * Updates the knob's corresponding pref value in response to dragging, which * will in turn update the location of the knob and its corresponding label * bubble and its text contents. + * @param {!Event} event * @private */ doKnobTracking_: function(event) { - const deltaRatio = - Math.abs(event.detail.ddx) / this.$.sliderBar.offsetWidth; - const deltaMinutes = Math.floor(deltaRatio * TOTAL_MINUTES_PER_DAY); - if (deltaMinutes <= 0) + const lastDeltaMinutes = this.getDeltaMinutes_(event.detail.ddx); + if (Math.abs(lastDeltaMinutes) < 1) return; - const knobPref = this.dragObject_ == this.$.startKnob ? - 'ash.night_light.custom_start_time' : - 'ash.night_light.custom_end_time'; - - const ddx = this.isRTL_ ? event.detail.ddx * -1 : event.detail.ddx; - if (ddx > 0) { - // Increment the knob's pref by the amount of deltaMinutes. - this.incrementPref_(knobPref, deltaMinutes); - } else { - // Decrement the knob's pref by the amount of deltaMinutes. - this.decrementPref_(knobPref, deltaMinutes); - } + // Using |ddx| to compute the delta minutes and adding that to the current + // value will result in a rounding error for every update. The cursor will + // drift away from the knob. Storing the original value and calculating the + // delta minutes from |dx| will provide a stable update that will not lose + // pixel movement due to rounding. + this.updatePref_( + this.valueAtDragStart_ + this.getDeltaMinutes_(event.detail.dx), true); }, /** * Ends the dragging. + * @param {!Event} event * @private */ endDrag_: function(event) { event.preventDefault(); - this.setExpanded_(false); this.dragObject_ = null; + this.removeRipple_(); }, /** @@ -300,6 +340,8 @@ * @private */ updateKnobs_: function() { + if (!this.isReady_ || !this.prefsAvailable()) + return; const startOffsetMinutes = /** @type {number} */ ( this.getPref('ash.night_light.custom_start_time').value); this.updateKnobLeft_(this.$.startKnob, startOffsetMinutes); @@ -414,69 +456,71 @@ }, /** - * Increments the value of the pref whose path is given by |prefPath| by the - * amount given in |increment|. - * @param {string} prefPath - * @param {number} increment + * Updates the value of the pref and wraps around if necessary. + * + * When the |updatedValue| would put the start and end times closer than the + * minimum distance, the |updatedValue| is changed to maintain the minimum + * distance. + * + * When |fromUserGesture| is true the update source is from a pointer such as + * a mouse, touch or pen. When the knobs are close, the dragging knob will + * stay on the same side with respect to the other knob. For example, when the + * minimum distance is 1 hour, the start knob is at 8:30 am, and the end knob + * is at 7:00, let's examine what happens if the start knob is dragged past + * the end knob. At first the start knob values will change past 8:20 and + * 8:10, all the way up to 8:00. Further movements in the same direction will + * not change the start knob value until the pointer crosses past the end knob + * (modulo the bar width). At that point, the start knob value will be updated + * to 6:00 and remain at 6:00 until the pointer passes the 6:00 location. + * + * When |fromUserGesture| is false, the input is coming from a key event. As + * soon as the |updatedValue| is closer than the minimum distance, the knob + * is moved to the other side of the other knob. For example, with a minimum + * distance of 1 hour, the start knob is at 8:00 am, and the end knob is at + * 7:00, if the start knob value is decreased, then the start knob will be + * updated to 6:00. + * @param {number} updatedValue + * @param {boolean} fromUserGesture * @private */ - incrementPref_: function(prefPath, increment) { - let value = this.getPref(prefPath).value + increment; - + updatePref_: function(updatedValue, fromUserGesture) { + const prefPath = assert(this.getFocusedKnobPrefPathIfAny_()); const otherValue = this.getOtherKnobPrefValue_(prefPath); - if (otherValue > value && - ((otherValue - value) < MIN_KNOBS_DISTANCE_MINUTES)) { - // We are incrementing the minutes offset moving towards the other knob. - // We have a minimum 60 minutes overlap threshold. Move this knob to the - // other side of the other knob. - // - // Was: - // ------ (+) --- 59 MIN --- + ------->> - // - // Now: - // ------ + --- 60 MIN --- (+) ------->> - // - // (+) ==> Knob being moved. - value = otherValue + MIN_KNOBS_DISTANCE_MINUTES; - } + + const totalMinutes = TOTAL_MINUTES_PER_DAY; + const minDistance = MIN_KNOBS_DISTANCE_MINUTES; + if (modulo(otherValue - updatedValue, totalMinutes) < minDistance) + updatedValue = otherValue + (fromUserGesture ? -1 : 1) * minDistance; + else if (modulo(updatedValue - otherValue, totalMinutes) < minDistance) + updatedValue = otherValue + (fromUserGesture ? 1 : -1) * minDistance; // The knobs are allowed to wrap around. - this.setPrefValue(prefPath, (value % TOTAL_MINUTES_PER_DAY)); + this.setPrefValue(prefPath, modulo(updatedValue, TOTAL_MINUTES_PER_DAY)); }, /** - * Decrements the value of the pref whose path is given by |prefPath| by the - * amount given in |decrement|. - * @param {string} prefPath - * @param {number} decrement + * @param {Element} knob + * @returns {?string} * @private */ - decrementPref_: function(prefPath, decrement) { - let value = - /** @type {number} */ (this.getPref(prefPath).value) - decrement; + getPrefPath_: function(knob) { + if (knob == this.$.startKnob) + return 'ash.night_light.custom_start_time'; - const otherValue = this.getOtherKnobPrefValue_(prefPath); - if (value > otherValue && - ((value - otherValue) < MIN_KNOBS_DISTANCE_MINUTES)) { - // We are decrementing the minutes offset moving towards the other knob. - // We have a minimum 60 minutes overlap threshold. Move this knob to the - // other side of the other knob. - // - // Was: - // <<------ + --- 59 MIN --- (+) ------- - // - // Now: - // <<------ (+) --- 60 MIN --- + ------ - // - // (+) ==> Knob being moved. - value = otherValue - MIN_KNOBS_DISTANCE_MINUTES; - } + if (knob == this.$.endKnob) + return 'ash.night_light.custom_end_time'; - // The knobs are allowed to wrap around. - if (value < 0) - value += TOTAL_MINUTES_PER_DAY; + return null; + }, - this.setPrefValue(prefPath, Math.abs(value) % TOTAL_MINUTES_PER_DAY); + /** + * @param {Element} knob + * @returns {?number} + * @private + */ + getPrefValue_: function(knob) { + const path = this.getPrefPath_(knob); + return path ? /** @type {number} */ (this.getPref(path).value) : null; }, /** @@ -486,46 +530,7 @@ * @private */ getFocusedKnobPrefPathIfAny_: function() { - const focusedElement = this.shadowRoot.activeElement; - if (focusedElement == this.$.startKnob) - return 'ash.night_light.custom_start_time'; - - if (focusedElement == this.$.endKnob) - return 'ash.night_light.custom_end_time'; - - return null; - }, - - /** - * Handles the 'left' key event. - * @private - */ - onLeftKey_: function(e) { - e.preventDefault(); - const knobPref = this.getFocusedKnobPrefPathIfAny_(); - if (!knobPref) - return; - - if (this.isRTL_) - this.incrementPref_(knobPref, 1); - else - this.decrementPref_(knobPref, 1); - }, - - /** - * Handles the 'right' key event. - * @private - */ - onRightKey_: function(e) { - e.preventDefault(); - const knobPref = this.getFocusedKnobPrefPathIfAny_(); - if (!knobPref) - return; - - if (this.isRTL_) - this.decrementPref_(knobPref, 1); - else - this.incrementPref_(knobPref, 1); + return this.getPrefPath_(this.shadowRoot.activeElement); }, /** @@ -558,10 +563,34 @@ }, /** - * Handles focus events on the start and end knobs. + * @param {!Event} event * @private */ - onFocus_: function() { + onFocus_: function(event) { + this.handleKnobEvent_(event); + }, + + /** + * Handles focus, drag and key events on the start and end knobs. + * If |overrideElement| is provided, it will be the knob that gains focus and + * and the ripple. Otherwise, the knob is determined from the |event|. + * @param {!Event} event + * @param {Element=} overrideElement + * @private + */ + handleKnobEvent_: function(event, overrideElement) { + const knob = overrideElement || + event.path.find(el => el.classList && el.classList.contains('knob')); + if (!knob) { + event.preventDefault(); + return; + } + + if (this._rippleContainer != knob) { + this.removeRipple_(); + knob.focus(); + } + this.ensureRipple(); if (this.hasRipple()) { @@ -575,12 +604,65 @@ * @private */ onBlur_: function() { + this.removeRipple_(); + }, + + /** + * Removes ripple if one exists. + * @private + */ + removeRipple_: function() { if (this.hasRipple()) { this._ripple.remove(); this._ripple = null; } }, + /** + * @param {!Event} event + * @private + */ + onKeyDown_: function(event) { + const activeElement = this.shadowRoot.activeElement; + if (event.key == 'Tab') { + if (event.shiftKey && this.$.endKnob == activeElement) { + event.preventDefault(); + this.handleKnobEvent_(event, this.$.startKnob); + return; + } + + if (!event.shiftKey && this.$.startKnob == activeElement) { + event.preventDefault(); + this.handleKnobEvent_(event, this.$.endKnob); + } + return; + } + + if (event.metaKey || event.shiftKey || event.altKey || event.ctrlKey) + return; + + const deltaKeyMap = { + ArrowDown: -1, + ArrowLeft: this.isRTL_ ? 1 : -1, + ArrowRight: this.isRTL_ ? -1 : 1, + ArrowUp: 1, + PageDown: -15, + PageUp: 15, + }; + + if (event.key in deltaKeyMap) { + this.handleKnobEvent_(event); + + event.preventDefault(); + const value = this.getPrefValue_(activeElement); + if (value == null) + return; + + const delta = deltaKeyMap[event.key]; + this.updatePref_(value + delta, false); + } + }, + /** @private */ _focusedChanged: function(receivedFocusFromKeyboard) { // Overrides the _focusedChanged() from the PaperInkyFocusBehavior so that
diff --git a/chrome/browser/resources/settings/device_page/pointers.html b/chrome/browser/resources/settings/device_page/pointers.html index 0ae8891..3208555 100644 --- a/chrome/browser/resources/settings/device_page/pointers.html +++ b/chrome/browser/resources/settings/device_page/pointers.html
@@ -45,7 +45,7 @@ <div class="settings-box"> <div class="start" id="mouseSpeedLabel">$i18n{mouseSpeed}</div> <settings-slider pref="{{prefs.settings.mouse.sensitivity2}}" - tick-values="[[sensitivityValues_]]" + ticks="[[sensitivityValues_]]" aria-labelledby="mouseSpeedLabel" label-min="$i18n{pointerSlow}" label-max="$i18n{pointerFast}"> @@ -69,7 +69,7 @@ <div class="start" id="touchpadSpeedLabel">$i18n{touchpadSpeed}</div> <settings-slider id="touchpadSensitivity" pref="{{prefs.settings.touchpad.sensitivity2}}" - tick-values="[[sensitivityValues_]]" + ticks="[[sensitivityValues_]]" aria-labelledby="touchpadSpeedLabel" label-min="$i18n{pointerSlow}" label-max="$i18n{pointerFast}">
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html b/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html index 8c0310d..383a1b23 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html
@@ -113,7 +113,7 @@ </div> </div> <cr-dialog id="forgetDeviceDialog"> - <div slot="title">$i18n{multideviceForgetDeviceDialogHeading}</div> + <div slot="title">$i18n{multideviceForgetDevice}</div> <div slot="body"> <div class="settings-box first"> $i18n{multideviceForgetDeviceDialogMessage}
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index 4dd02ed..98b783f 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -562,13 +562,6 @@ <structure name="IDR_SETTINGS_DEVICE_NIGHT_LIGHT_SLIDER_JS" file="device_page/night_light_slider.js" type="chrome_html" /> - <structure name="IDR_SETTINGS_DEVICE_DISPLAY_SIZE_SLIDER_HTML" - file="device_page/display_size_slider.html" - type="chrome_html" /> - <structure name="IDR_SETTINGS_DEVICE_DISPLAY_SIZE_SLIDER_JS" - file="device_page/display_size_slider.js" - type="chrome_html" /> - </if> <structure name="IDR_SETTINGS_DOWNLOADS_BROWSER_PROXY_HTML" file="downloads_page/downloads_browser_proxy.html"
diff --git a/components/nux/OWNERS b/chrome/browser/resources/welcome/onboarding_welcome/OWNERS similarity index 100% rename from components/nux/OWNERS rename to chrome/browser/resources/welcome/onboarding_welcome/OWNERS
diff --git a/components/nux/email/resources/BUILD.gn b/chrome/browser/resources/welcome/onboarding_welcome/email/BUILD.gn similarity index 100% rename from components/nux/email/resources/BUILD.gn rename to chrome/browser/resources/welcome/onboarding_welcome/email/BUILD.gn
diff --git a/components/nux/email/resources/email_chooser.html b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html similarity index 100% rename from components/nux/email/resources/email_chooser.html rename to chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html
diff --git a/components/nux/email/resources/email_chooser.js b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js similarity index 92% rename from components/nux/email/resources/email_chooser.js rename to chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js index d246358..277633a 100644 --- a/components/nux/email/resources/email_chooser.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js
@@ -5,7 +5,7 @@ /** * @const */ -var nux_email = nux_email || {}; +var nuxEmail = nuxEmail || {}; /** * @typedef {{ @@ -15,7 +15,7 @@ * bookmarkId: {string|undefined}, * }} */ -nux_email.EmailProviderModel; +nuxEmail.EmailProviderModel; Polymer({ is: 'email-chooser', @@ -34,7 +34,7 @@ /** @private */ finalized_: Boolean, - /** @private {nux_email.EmailProviderModel} */ + /** @private {nuxEmail.EmailProviderModel} */ selectedEmailProvider_: { type: Object, value: () => null, @@ -75,7 +75,7 @@ /** * Handle toggling the email selected. - * @param {!{model: {item: !nux_email.EmailProviderModel}}} e + * @param {!{model: {item: !nuxEmail.EmailProviderModel}}} e * @private */ onEmailClick_: function(e) { @@ -110,7 +110,7 @@ }, /** - * @param {nux_email.EmailProviderModel=} newEmail + * @param {nuxEmail.EmailProviderModel=} newEmail * @private */ revertBookmark_: function(emailProvider) { @@ -121,8 +121,8 @@ }, /** - * @param {nux_email.EmailProviderModel} newEmail - * @param {nux_email.EmailProviderModel} prevEmail + * @param {nuxEmail.EmailProviderModel} newEmail + * @param {nuxEmail.EmailProviderModel} prevEmail * @private */ onSelectedEmailProviderChange_: function(newEmail, prevEmail) {
diff --git a/components/nux/email/resources/nux_email.html b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html similarity index 100% rename from components/nux/email/resources/nux_email.html rename to chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html
diff --git a/components/nux/email/resources/nux_email.js b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js similarity index 100% rename from components/nux/email/resources/nux_email.js rename to chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js
diff --git a/components/nux/email/resources/nux_email_proxy.html b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.html similarity index 100% rename from components/nux/email/resources/nux_email_proxy.html rename to chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.html
diff --git a/components/nux/email/resources/nux_email_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js similarity index 99% rename from components/nux/email/resources/nux_email_proxy.js rename to chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js index 2c49bbdd..75d2b553 100644 --- a/components/nux/email/resources/nux_email_proxy.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js
@@ -102,7 +102,7 @@ name: loadTimeData.getString(`email_name_${i}`), icon: loadTimeData.getString(`email_name_${i}`).toLowerCase(), url: loadTimeData.getString(`email_url_${i}`) - }) + }); } return emailList; }
diff --git a/components/nux/google_apps/resources/BUILD.gn b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/BUILD.gn similarity index 100% rename from components/nux/google_apps/resources/BUILD.gn rename to chrome/browser/resources/welcome/onboarding_welcome/google_apps/BUILD.gn
diff --git a/components/nux/google_apps/resources/apps_chooser.html b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.html similarity index 100% rename from components/nux/google_apps/resources/apps_chooser.html rename to chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.html
diff --git a/components/nux/google_apps/resources/apps_chooser.js b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js similarity index 90% rename from components/nux/google_apps/resources/apps_chooser.js rename to chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js index 87c50fe..688ffb79 100644 --- a/components/nux/google_apps/resources/apps_chooser.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js
@@ -5,7 +5,7 @@ /** * @const */ -var nux_google_apps = nux_google_apps || {}; +var nuxGoogleApps = nuxGoogleApps || {}; /** * @typedef {{ @@ -17,7 +17,7 @@ * set: function(string, boolean):void * }} */ -nux_google_apps.AppsArrayModel; +nuxGoogleApps.AppsArrayModel; Polymer({ is: 'apps-chooser', @@ -73,12 +73,12 @@ * @return {Array<boolean>} */ getSelectedAppList() { - return this.appList.map(a => a.selected) + return this.appList.map(a => a.selected); }, /** * Handle toggling the apps selected. - * @param {!{model: !nux_google_apps.AppsArrayModel}} e + * @param {!{model: !nuxGoogleApps.AppsArrayModel}} e * @private */ onAppClick_: function(e) {
diff --git a/components/nux/google_apps/resources/nux_google_apps.html b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html similarity index 100% rename from components/nux/google_apps/resources/nux_google_apps.html rename to chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html
diff --git a/components/nux/google_apps/resources/nux_google_apps.js b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.js similarity index 100% rename from components/nux/google_apps/resources/nux_google_apps.js rename to chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.js
diff --git a/components/nux/google_apps/resources/nux_google_apps_proxy.html b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps_proxy.html similarity index 100% rename from components/nux/google_apps/resources/nux_google_apps_proxy.html rename to chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps_proxy.html
diff --git a/components/nux/google_apps/resources/nux_google_apps_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps_proxy.js similarity index 100% rename from components/nux/google_apps/resources/nux_google_apps_proxy.js rename to chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps_proxy.js
diff --git a/components/nux/email/resources/aol_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/aol_1x.png similarity index 100% rename from components/nux/email/resources/aol_1x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/aol_1x.png Binary files differ
diff --git a/components/nux/email/resources/aol_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/aol_2x.png similarity index 100% rename from components/nux/email/resources/aol_2x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/aol_2x.png Binary files differ
diff --git a/components/nux/google_apps/resources/chrome_store_24dp_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/chrome_store_24dp_1x.png similarity index 100% rename from components/nux/google_apps/resources/chrome_store_24dp_1x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/chrome_store_24dp_1x.png Binary files differ
diff --git a/components/nux/google_apps/resources/chrome_store_24dp_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/chrome_store_24dp_2x.png similarity index 100% rename from components/nux/google_apps/resources/chrome_store_24dp_2x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/chrome_store_24dp_2x.png Binary files differ
diff --git a/components/nux/email/resources/gmail_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/gmail_1x.png similarity index 100% rename from components/nux/email/resources/gmail_1x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/gmail_1x.png Binary files differ
diff --git a/components/nux/google_apps/resources/gmail_24dp_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/gmail_24dp_1x.png similarity index 100% rename from components/nux/google_apps/resources/gmail_24dp_1x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/gmail_24dp_1x.png Binary files differ
diff --git a/components/nux/google_apps/resources/gmail_24dp_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/gmail_24dp_2x.png similarity index 100% rename from components/nux/google_apps/resources/gmail_24dp_2x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/gmail_24dp_2x.png Binary files differ
diff --git a/components/nux/email/resources/gmail_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/gmail_2x.png similarity index 100% rename from components/nux/email/resources/gmail_2x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/gmail_2x.png Binary files differ
diff --git a/components/nux/email/resources/icloud_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/icloud_1x.png similarity index 100% rename from components/nux/email/resources/icloud_1x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/icloud_1x.png Binary files differ
diff --git a/components/nux/email/resources/icloud_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/icloud_2x.png similarity index 100% rename from components/nux/email/resources/icloud_2x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/icloud_2x.png Binary files differ
diff --git a/components/nux/google_apps/resources/maps_24dp_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/maps_24dp_1x.png similarity index 100% rename from components/nux/google_apps/resources/maps_24dp_1x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/maps_24dp_1x.png Binary files differ
diff --git a/components/nux/google_apps/resources/maps_24dp_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/maps_24dp_2x.png similarity index 100% rename from components/nux/google_apps/resources/maps_24dp_2x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/maps_24dp_2x.png Binary files differ
diff --git a/components/nux/google_apps/resources/news_24dp_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/news_24dp_1x.png similarity index 100% rename from components/nux/google_apps/resources/news_24dp_1x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/news_24dp_1x.png Binary files differ
diff --git a/components/nux/google_apps/resources/news_24dp_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/news_24dp_2x.png similarity index 100% rename from components/nux/google_apps/resources/news_24dp_2x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/news_24dp_2x.png Binary files differ
diff --git a/components/nux/email/resources/outlook_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/outlook_1x.png similarity index 100% rename from components/nux/email/resources/outlook_1x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/outlook_1x.png Binary files differ
diff --git a/components/nux/email/resources/outlook_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/outlook_2x.png similarity index 100% rename from components/nux/email/resources/outlook_2x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/outlook_2x.png Binary files differ
diff --git a/components/nux/google_apps/resources/translate_24dp_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/translate_24dp_1x.png similarity index 100% rename from components/nux/google_apps/resources/translate_24dp_1x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/translate_24dp_1x.png Binary files differ
diff --git a/components/nux/google_apps/resources/translate_24dp_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/translate_24dp_2x.png similarity index 100% rename from components/nux/google_apps/resources/translate_24dp_2x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/translate_24dp_2x.png Binary files differ
diff --git a/components/nux/email/resources/yahoo_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/yahoo_1x.png similarity index 100% rename from components/nux/email/resources/yahoo_1x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/yahoo_1x.png Binary files differ
diff --git a/components/nux/email/resources/yahoo_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/yahoo_2x.png similarity index 100% rename from components/nux/email/resources/yahoo_2x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/yahoo_2x.png Binary files differ
diff --git a/components/nux/google_apps/resources/youtube_24dp_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/youtube_24dp_1x.png similarity index 100% rename from components/nux/google_apps/resources/youtube_24dp_1x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/youtube_24dp_1x.png Binary files differ
diff --git a/components/nux/google_apps/resources/youtube_24dp_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/youtube_24dp_2x.png similarity index 100% rename from components/nux/google_apps/resources/youtube_24dp_2x.png rename to chrome/browser/resources/welcome/onboarding_welcome/images/youtube_24dp_2x.png Binary files differ
diff --git a/components/nux/set_as_default/resources/BUILD.gn b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/BUILD.gn similarity index 100% rename from components/nux/set_as_default/resources/BUILD.gn rename to chrome/browser/resources/welcome/onboarding_welcome/set_as_default/BUILD.gn
diff --git a/components/nux/set_as_default/resources/nux_set_as_default.html b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html similarity index 100% rename from components/nux/set_as_default/resources/nux_set_as_default.html rename to chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
diff --git a/components/nux/set_as_default/resources/nux_set_as_default.js b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js similarity index 100% rename from components/nux/set_as_default/resources/nux_set_as_default.js rename to chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js
diff --git a/components/nux/set_as_default/resources/nux_set_as_default_proxy.html b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default_proxy.html similarity index 100% rename from components/nux/set_as_default/resources/nux_set_as_default_proxy.html rename to chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default_proxy.html
diff --git a/components/nux/set_as_default/resources/nux_set_as_default_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default_proxy.js similarity index 85% rename from components/nux/set_as_default/resources/nux_set_as_default_proxy.js rename to chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default_proxy.js index f33fe32..19be0e40 100644 --- a/components/nux/set_as_default/resources/nux_set_as_default_proxy.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default_proxy.js
@@ -4,12 +4,10 @@ cr.define('nux', function() { /** @interface */ - class NuxSetAsDefaultProxy { - } + class NuxSetAsDefaultProxy {} /** @implements {NuxSetAsDefaultProxy} */ - class NuxSetAsDefaultProxyImpl { - } + class NuxSetAsDefaultProxyImpl {} cr.addSingletonGetter(NuxSetAsDefaultProxyImpl);
diff --git a/chrome/browser/rlz/chrome_rlz_tracker_delegate.cc b/chrome/browser/rlz/chrome_rlz_tracker_delegate.cc index e0c0610..346c93a 100644 --- a/chrome/browser/rlz/chrome_rlz_tracker_delegate.cc +++ b/chrome/browser/rlz/chrome_rlz_tracker_delegate.cc
@@ -122,7 +122,7 @@ } bool ChromeRLZTrackerDelegate::GetBrand(std::string* brand) { - return google_brand::GetBrand(brand); + return google_brand::GetRlzBrand(brand); } bool ChromeRLZTrackerDelegate::IsBrandOrganic(const std::string& brand) {
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc index d0831ee..3367067 100644 --- a/chrome/browser/search/instant_service.cc +++ b/chrome/browser/search/instant_service.cc
@@ -458,8 +458,8 @@ break; } case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: - BuildThemeInfo(); - NotifyAboutThemeInfo(); + theme_info_ = nullptr; + UpdateThemeInfo(); break; default: NOTREACHED() << "Unexpected notification type in InstantService.";
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc index 226b739..834b2fa5 100644 --- a/chrome/browser/signin/chrome_signin_client.cc +++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -65,6 +65,25 @@ #include "chrome/browser/ui/user_manager.h" #endif +namespace { +SigninClient::SignoutDecision IsSignoutAllowed( + Profile* profile, + const signin_metrics::ProfileSignout signout_source_metric) { + // TODO(chcunningham): This logic should be reworked to only prohibit user- + // initiated sign-out. For now signin_util::IsUserSignoutAllowedForProfile() + // prohibits ALL sign-outs with the exception of ACCOUNT_REMOVED_FROM_DEVICE + // because this preserves the original behavior. A follow-up CL will make the + // slightly riskier change described above. + if (signin_util::IsUserSignoutAllowedForProfile(profile) || + signout_source_metric == + signin_metrics::ProfileSignout::ACCOUNT_REMOVED_FROM_DEVICE) { + return SigninClient::SignoutDecision::ALLOW_SIGNOUT; + } + + return SigninClient::SignoutDecision::DISALLOW_SIGNOUT; +} +} // namespace + ChromeSigninClient::ChromeSigninClient( Profile* profile, SigninErrorController* signin_error_controller) @@ -186,8 +205,12 @@ } void ChromeSigninClient::PreSignOut( - const base::Callback<void()>& sign_out, + base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached, signin_metrics::ProfileSignout signout_source_metric) { + DCHECK(on_signout_decision_reached); + DCHECK(!on_signout_decision_reached_) << "SignOut already in-progress!"; + on_signout_decision_reached_ = std::move(on_signout_decision_reached); + #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) // These sign out won't remove the policy cache, keep the window opened. @@ -206,13 +229,12 @@ // Call OnCloseBrowsersSuccess to continue sign out and show UserManager // afterwards. should_display_user_manager_ = false; // Don't show UserManager twice. - OnCloseBrowsersSuccess(sign_out, signout_source_metric, - profile_->GetPath()); + OnCloseBrowsersSuccess(signout_source_metric, profile_->GetPath()); } else { BrowserList::CloseAllBrowsersWithProfile( profile_, base::Bind(&ChromeSigninClient::OnCloseBrowsersSuccess, - base::Unretained(this), sign_out, signout_source_metric), + base::Unretained(this), signout_source_metric), base::Bind(&ChromeSigninClient::OnCloseBrowsersAborted, base::Unretained(this)), signout_source_metric == signin_metrics::ABORT_SIGNIN || @@ -224,7 +246,8 @@ #else { #endif - SigninClient::PreSignOut(sign_out, signout_source_metric); + std::move(on_signout_decision_reached_) + .Run(IsSignoutAllowed(profile_, signout_source_metric)); } } @@ -390,7 +413,6 @@ } void ChromeSigninClient::OnCloseBrowsersSuccess( - const base::Callback<void()>& sign_out, const signin_metrics::ProfileSignout signout_source_metric, const base::FilePath& profile_path) { #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) @@ -398,7 +420,9 @@ force_signin_verifier_->Cancel(); } #endif - SigninClient::PreSignOut(sign_out, signout_source_metric); + + std::move(on_signout_decision_reached_) + .Run(IsSignoutAllowed(profile_, signout_source_metric)); LockForceSigninProfile(profile_path); // After sign out, lock the profile and show UserManager if necessary. @@ -412,6 +436,10 @@ void ChromeSigninClient::OnCloseBrowsersAborted( const base::FilePath& profile_path) { should_display_user_manager_ = true; + + // Disallow sign-out (aborted). + std::move(on_signout_decision_reached_) + .Run(SignoutDecision::DISALLOW_SIGNOUT); } void ChromeSigninClient::LockForceSigninProfile(
diff --git a/chrome/browser/signin/chrome_signin_client.h b/chrome/browser/signin/chrome_signin_client.h index f6e2643..d80f6f87 100644 --- a/chrome/browser/signin/chrome_signin_client.h +++ b/chrome/browser/signin/chrome_signin_client.h
@@ -46,6 +46,9 @@ // SigninClient implementation. PrefService* GetPrefs() override; + void PreSignOut( + base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached, + signin_metrics::ProfileSignout signout_source_metric) override; void OnSignedOut() override; scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; network::mojom::CookieManager* GetCookieManager() override; @@ -74,9 +77,6 @@ void PostSignedIn(const std::string& account_id, const std::string& username, const std::string& password) override; - void PreSignOut( - const base::Callback<void()>& sign_out, - signin_metrics::ProfileSignout signout_source_metric) override; // SigninErrorController::Observer implementation. void OnErrorChanged() override; @@ -116,7 +116,6 @@ void MaybeFetchSigninTokenHandle(); void VerifySyncToken(); void OnCloseBrowsersSuccess( - const base::Callback<void()>& sign_out, const signin_metrics::ProfileSignout signout_source_metric, const base::FilePath& profile_path); void OnCloseBrowsersAborted(const base::FilePath& profile_path); @@ -124,6 +123,10 @@ Profile* profile_; SigninErrorController* signin_error_controller_; + + // Stored callback from PreSignOut(); + base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached_; + #if !defined(OS_CHROMEOS) std::list<base::Closure> delayed_callbacks_; #endif
diff --git a/chrome/browser/signin/chrome_signin_client_unittest.cc b/chrome/browser/signin/chrome_signin_client_unittest.cc index 6dfd70a5..f386f0f 100644 --- a/chrome/browser/signin/chrome_signin_client_unittest.cc +++ b/chrome/browser/signin/chrome_signin_client_unittest.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/logging.h" #include "base/run_loop.h" +#include "base/stl_util.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/chrome_signin_client_factory.h" @@ -150,10 +151,11 @@ DCHECK(signin_error_controller); } - MOCK_METHOD3(DoSignOut, + MOCK_METHOD4(OnSignoutDecisionReached, void(signin_metrics::ProfileSignout, signin_metrics::SignoutDelete, - RemoveAccountsOption remove_option)); + RemoveAccountsOption remove_option, + SigninClient::SignoutDecision signout_decision)); AccountTrackerService fake_service_; }; @@ -196,10 +198,11 @@ .Times(1); EXPECT_CALL(*client_, LockForceSigninProfile(browser()->profile()->GetPath())) .Times(1); - EXPECT_CALL( - *manager_, - DoSignOut(source_metric, delete_metric, - SigninManager::RemoveAccountsOption::kRemoveAllAccounts)) + EXPECT_CALL(*manager_, + OnSignoutDecisionReached( + source_metric, delete_metric, + SigninManager::RemoveAccountsOption::kRemoveAllAccounts, + SigninClient::SignoutDecision::ALLOW_SIGNOUT)) .Times(1); manager_->SignOut(source_metric, delete_metric); @@ -218,10 +221,11 @@ .Times(0); EXPECT_CALL(*client_, LockForceSigninProfile(browser()->profile()->GetPath())) .Times(1); - EXPECT_CALL( - *manager_, - DoSignOut(source_metric, delete_metric, - SigninManager::RemoveAccountsOption::kRemoveAllAccounts)) + EXPECT_CALL(*manager_, + OnSignoutDecisionReached( + source_metric, delete_metric, + SigninManager::RemoveAccountsOption::kRemoveAllAccounts, + SigninClient::SignoutDecision::ALLOW_SIGNOUT)) .Times(1); manager_->SignOut(source_metric, delete_metric); @@ -231,10 +235,11 @@ .Times(1); EXPECT_CALL(*client_, LockForceSigninProfile(browser()->profile()->GetPath())) .Times(1); - EXPECT_CALL( - *manager_, - DoSignOut(source_metric, delete_metric, - SigninManager::RemoveAccountsOption::kRemoveAllAccounts)) + EXPECT_CALL(*manager_, + OnSignoutDecisionReached( + source_metric, delete_metric, + SigninManager::RemoveAccountsOption::kRemoveAllAccounts, + SigninClient::SignoutDecision::ALLOW_SIGNOUT)) .Times(1); manager_->SignOut(source_metric, delete_metric); } @@ -254,10 +259,11 @@ .Times(0); EXPECT_CALL(*client_, LockForceSigninProfile(browser()->profile()->GetPath())) .Times(0); - EXPECT_CALL( - *manager_, - DoSignOut(source_metric, delete_metric, - SigninManager::RemoveAccountsOption::kRemoveAllAccounts)) + EXPECT_CALL(*manager_, + OnSignoutDecisionReached( + source_metric, delete_metric, + SigninManager::RemoveAccountsOption::kRemoveAllAccounts, + SigninClient::SignoutDecision::ALLOW_SIGNOUT)) .Times(1); manager_->SignOut(source_metric, delete_metric); } @@ -280,13 +286,126 @@ .Times(0); EXPECT_CALL(*client_, LockForceSigninProfile(browser()->profile()->GetPath())) .Times(0); - EXPECT_CALL( - *manager_, - DoSignOut(source_metric, delete_metric, - SigninManager::RemoveAccountsOption::kRemoveAllAccounts)) + EXPECT_CALL(*manager_, + OnSignoutDecisionReached( + source_metric, delete_metric, + SigninManager::RemoveAccountsOption::kRemoveAllAccounts, + SigninClient::SignoutDecision::ALLOW_SIGNOUT)) .Times(1); manager_->SignOut(source_metric, delete_metric); } +class ChromeSigninClientSignoutSourceTest + : public ::testing::WithParamInterface<signin_metrics::ProfileSignout>, + public ChromeSigninClientSignoutTest {}; + +bool IsUserDrivenSignout(signin_metrics::ProfileSignout signout_source) { + switch (signout_source) { + // NOTE: SIGNOUT_TEST == SIGNOUT_PREF_CHANGED. + case signin_metrics::ProfileSignout::SIGNOUT_PREF_CHANGED: + case signin_metrics::ProfileSignout::GOOGLE_SERVICE_NAME_PATTERN_CHANGED: + case signin_metrics::ProfileSignout::SIGNIN_PREF_CHANGED_DURING_SIGNIN: + case signin_metrics::ProfileSignout::USER_CLICKED_SIGNOUT_SETTINGS: + case signin_metrics::ProfileSignout::ABORT_SIGNIN: + case signin_metrics::ProfileSignout::SERVER_FORCED_DISABLE: + case signin_metrics::ProfileSignout::TRANSFER_CREDENTIALS: + case signin_metrics::ProfileSignout:: + AUTHENTICATION_FAILED_WITH_FORCE_SIGNIN: + case signin_metrics::ProfileSignout::USER_TUNED_OFF_SYNC_FROM_DICE_UI: + return true; + case signin_metrics::ProfileSignout::ACCOUNT_REMOVED_FROM_DEVICE: + // TODO(chcunningham): Add more of the above cases to this "false" branch. + // For now only ACCOUNT_REMOVED_FROM_DEVICE is here to preserve the status + // quo. Additional internal sources of sign-out will be moved here in a + // follow up CL. + return false; + case signin_metrics::ProfileSignout::NUM_PROFILE_SIGNOUT_METRICS: + NOTREACHED(); + return false; + } +} + +TEST_P(ChromeSigninClientSignoutSourceTest, UserSignoutAllowed) { + signin_metrics::ProfileSignout signout_source = GetParam(); + + TestingProfile::Builder builder; + builder.SetGuestSession(); + std::unique_ptr<TestingProfile> profile = builder.Build(); + + CreateClient(profile.get()); + manager_ = std::make_unique<MockSigninManager>(client_.get(), + fake_controller_.get()); + + // User sign-out is allowed for this test. + ASSERT_TRUE(signin_util::IsUserSignoutAllowedForProfile(profile.get())); + + // Verify SigninManager gets callback indicating sign-out is always allowed. + signin_metrics::SignoutDelete delete_metric = + signin_metrics::SignoutDelete::IGNORE_METRIC; + EXPECT_CALL(*manager_, + OnSignoutDecisionReached( + signout_source, delete_metric, + SigninManager::RemoveAccountsOption::kRemoveAllAccounts, + SigninClient::SignoutDecision::ALLOW_SIGNOUT)) + .Times(1); + + manager_->SignOut(signout_source, delete_metric); +} + +TEST_P(ChromeSigninClientSignoutSourceTest, UserSignoutDisallowed) { + signin_metrics::ProfileSignout signout_source = GetParam(); + + TestingProfile::Builder builder; + builder.SetGuestSession(); + std::unique_ptr<TestingProfile> profile = builder.Build(); + + CreateClient(profile.get()); + manager_ = std::make_unique<MockSigninManager>(client_.get(), + fake_controller_.get()); + + // Disallow user sign-out. + ASSERT_TRUE(signin_util::IsUserSignoutAllowedForProfile(profile.get())); + signin_util::SetUserSignoutAllowedForProfile(profile.get(), false); + ASSERT_FALSE(signin_util::IsUserSignoutAllowedForProfile(profile.get())); + + // Verify SigninManager gets callback indicating sign-out is disallowed iff + // the source of the sign-out is a user-action. + SigninClient::SignoutDecision signout_decision = + IsUserDrivenSignout(signout_source) + ? SigninClient::SignoutDecision::DISALLOW_SIGNOUT + : SigninClient::SignoutDecision::ALLOW_SIGNOUT; + signin_metrics::SignoutDelete delete_metric = + signin_metrics::SignoutDelete::IGNORE_METRIC; + EXPECT_CALL(*manager_, + OnSignoutDecisionReached( + signout_source, delete_metric, + SigninManager::RemoveAccountsOption::kRemoveAllAccounts, + signout_decision)) + .Times(1); + + manager_->SignOut(signout_source, delete_metric); +} + +const signin_metrics::ProfileSignout kSignoutSources[] = { + // NOTE: SIGNOUT_TEST == SIGNOUT_PREF_CHANGED. + signin_metrics::ProfileSignout::SIGNOUT_PREF_CHANGED, + signin_metrics::ProfileSignout::GOOGLE_SERVICE_NAME_PATTERN_CHANGED, + signin_metrics::ProfileSignout::SIGNIN_PREF_CHANGED_DURING_SIGNIN, + signin_metrics::ProfileSignout::USER_CLICKED_SIGNOUT_SETTINGS, + signin_metrics::ProfileSignout::ABORT_SIGNIN, + signin_metrics::ProfileSignout::SERVER_FORCED_DISABLE, + signin_metrics::ProfileSignout::TRANSFER_CREDENTIALS, + signin_metrics::ProfileSignout::AUTHENTICATION_FAILED_WITH_FORCE_SIGNIN, + signin_metrics::ProfileSignout::USER_TUNED_OFF_SYNC_FROM_DICE_UI, + signin_metrics::ProfileSignout::ACCOUNT_REMOVED_FROM_DEVICE, +}; +static_assert(base::size(kSignoutSources) == + signin_metrics::ProfileSignout::NUM_PROFILE_SIGNOUT_METRICS, + "kSignoutSources should enumerate all ProfileSignout values"); + +INSTANTIATE_TEST_CASE_P(AllSignoutSources, + ChromeSigninClientSignoutSourceTest, + testing::ValuesIn(kSignoutSources)); + #endif // !defined(OS_ANDROID) #endif // !defined(OS_CHROMEOS)
diff --git a/chrome/browser/signin/signin_util.cc b/chrome/browser/signin/signin_util.cc index 5c6103b..90096d8 100644 --- a/chrome/browser/signin/signin_util.cc +++ b/chrome/browser/signin/signin_util.cc
@@ -4,13 +4,46 @@ #include "chrome/browser/signin/signin_util.h" +#include <memory> + +#include "base/supports_user_data.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" namespace signin_util { namespace { +constexpr char kSignoutSettingKey[] = "signout_setting"; + +class UserSignoutSetting : public base::SupportsUserData::Data { + public: + // Fetch from Profile. Make and store if not already present. + static UserSignoutSetting* GetForProfile(Profile* profile) { + UserSignoutSetting* signout_setting = static_cast<UserSignoutSetting*>( + profile->GetUserData(kSignoutSettingKey)); + + if (!signout_setting) { + profile->SetUserData(kSignoutSettingKey, + std::make_unique<UserSignoutSetting>()); + signout_setting = static_cast<UserSignoutSetting*>( + profile->GetUserData(kSignoutSettingKey)); + } + + return signout_setting; + } + + bool is_user_signout_allowed() const { return is_user_signout_allowed_; } + void set_is_user_signout_allowed(bool is_allowed) { + is_user_signout_allowed_ = is_allowed; + } + + private: + // User sign-out allowed by default. + bool is_user_signout_allowed_ = true; +}; + enum ForceSigninPolicyCache { NOT_CACHED = 0, ENABLE, @@ -42,4 +75,13 @@ g_is_force_signin_enabled_cache = NOT_CACHED; } +void SetUserSignoutAllowedForProfile(Profile* profile, bool is_allowed) { + UserSignoutSetting::GetForProfile(profile)->set_is_user_signout_allowed( + is_allowed); +} + +bool IsUserSignoutAllowedForProfile(Profile* profile) { + return UserSignoutSetting::GetForProfile(profile)->is_user_signout_allowed(); +} + } // namespace signin_util
diff --git a/chrome/browser/signin/signin_util.h b/chrome/browser/signin/signin_util.h index be53b9d8..b24763ae 100644 --- a/chrome/browser/signin/signin_util.h +++ b/chrome/browser/signin/signin_util.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_SIGNIN_SIGNIN_UTIL_H_ #define CHROME_BROWSER_SIGNIN_SIGNIN_UTIL_H_ +class Profile; + namespace signin_util { // Return whether the force sign in policy is enabled or not. @@ -17,6 +19,15 @@ // Reset force sign in to uninitialized state for testing. void ResetForceSigninForTesting(); +// Sign-out is allowed by default, but some Chrome profiles (e.g. for cloud- +// managed enterprise accounts) may wish to disallow user-initiated sign-out. +// Note that this exempts sign-outs that are not user-initiated (e.g. sign-out +// triggered when cloud policy no longer allows current email pattern). See +// ChromeSigninClient::PreSignOut(). +void SetUserSignoutAllowedForProfile(Profile* profile, bool is_allowed); + +bool IsUserSignoutAllowedForProfile(Profile* profile); + } // namespace signin_util #endif // CHROME_BROWSER_SIGNIN_SIGNIN_UTIL_H_
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.cc b/chrome/browser/supervised_user/child_accounts/child_account_service.cc index ca6ac82..77bdf64 100644 --- a/chrome/browser/supervised_user/child_accounts/child_account_service.cc +++ b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
@@ -39,6 +39,8 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/profiles/profile_helper.h" +#else +#include "chrome/browser/signin/signin_util.h" #endif const char kGaiaCookieManagerSource[] = "child_account_service"; @@ -195,7 +197,7 @@ // This is also used by user policies (UserPolicySigninService), but since // child accounts can not also be Dasher accounts, there shouldn't be any // problems. - SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout(true); + signin_util::SetUserSignoutAllowedForProfile(profile_, false); #endif // TODO(treib): Maybe store the last update time in a pref, so we don't @@ -227,7 +229,7 @@ #endif #if !defined(OS_CHROMEOS) - SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout(false); + signin_util::SetUserSignoutAllowedForProfile(profile_, true); #endif CancelFetchingFamilyInfo();
diff --git a/chrome/browser/sync/sync_ui_util.cc b/chrome/browser/sync/sync_ui_util.cc index 735a580..2b28b944 100644 --- a/chrome/browser/sync/sync_ui_util.cc +++ b/chrome/browser/sync/sync_ui_util.cc
@@ -22,8 +22,7 @@ #include "ui/base/l10n/l10n_util.h" #if !defined(OS_CHROMEOS) -#include "chrome/browser/signin/signin_manager_factory.h" -#include "components/signin/core/browser/signin_manager.h" +#include "chrome/browser/signin/signin_util.h" #endif // defined(OS_CHROMEOS) using browser_sync::ProfileSyncService; @@ -114,7 +113,7 @@ status_label->assign(l10n_util::GetStringUTF16( IDS_SYNC_STATUS_UNRECOVERABLE_ERROR)); // The message for managed accounts is the same as that of the cros. - if (SigninManagerFactory::GetForProfile(profile)->IsSignoutProhibited()) { + if (!signin_util::IsUserSignoutAllowedForProfile(profile)) { status_label->assign(l10n_util::GetStringUTF16( IDS_SYNC_STATUS_UNRECOVERABLE_ERROR_NEEDS_SIGNOUT)); } @@ -352,7 +351,7 @@ service->QueryDetailedSyncStatus(&status); if (status.sync_protocol_error.action != syncer::UPGRADE_CLIENT) { // Display different messages and buttons for managed accounts. - if (SigninManagerFactory::GetForProfile(profile)->IsSignoutProhibited()) { + if (!signin_util::IsUserSignoutAllowedForProfile(profile)) { // For a managed user, the user is directed to the signout // confirmation dialogue in the settings page. *content_string_id = IDS_SYNC_ERROR_USER_MENU_SIGNOUT_MESSAGE;
diff --git a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc index 312b76a0..74d9880 100644 --- a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc +++ b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
@@ -36,6 +36,7 @@ #include "storage/browser/test/mock_special_storage_policy.h" #include "storage/browser/test/test_file_system_options.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/origin.h" using base::File; using storage::FileSystemContext; @@ -672,7 +673,7 @@ EXPECT_TRUE(is_filesystem_opened_); DCHECK(quota_manager_.get()); quota_manager_->GetUsageAndQuota( - origin_, storage_type(), + url::Origin::Create(origin_), storage_type(), base::BindOnce(&DidGetUsageAndQuota, std::move(callback), usage, quota)); }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index d0db65d24..5566278 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1559,6 +1559,8 @@ "views/location_bar/intent_picker_view.h", "views/platform_keys_certificate_selector_chromeos.cc", "views/platform_keys_certificate_selector_chromeos.h", + "views/profiles/profile_indicator_icon.cc", + "views/profiles/profile_indicator_icon.h", # On chromeos, file manager extension handles the file open/save dialog. "views/select_file_dialog_extension.cc", @@ -1896,8 +1898,6 @@ "views/close_bubble_on_tab_activation_helper.h", "views/external_protocol_dialog.cc", "views/external_protocol_dialog.h", - "views/profiles/avatar_button.cc", - "views/profiles/avatar_button.h", "views/profiles/badged_profile_photo.cc", "views/profiles/badged_profile_photo.h", "views/profiles/dice_accounts_menu.cc", @@ -2549,8 +2549,6 @@ "views/folder_upload_confirmation_view.h", "views/frame/app_menu_button.cc", "views/frame/app_menu_button.h", - "views/frame/avatar_button_manager.cc", - "views/frame/avatar_button_manager.h", "views/frame/browser_frame.cc", "views/frame/browser_frame.h", "views/frame/browser_non_client_frame_view.cc", @@ -2784,11 +2782,8 @@ "views/permission_bubble/permission_prompt_impl.cc", "views/permission_bubble/permission_prompt_impl.h", "views/permission_bubble/permission_prompt_impl_views.cc", - "views/profiles/avatar_button_style.h", "views/profiles/avatar_toolbar_button.cc", "views/profiles/avatar_toolbar_button.h", - "views/profiles/profile_indicator_icon.cc", - "views/profiles/profile_indicator_icon.h", "views/profiles/signin_view_controller_delegate_views.cc", "views/profiles/signin_view_controller_delegate_views.h", "views/proximity_auth/proximity_auth_error_bubble_view.cc", @@ -2829,8 +2824,8 @@ "views/tab_icon_view.h", "views/tab_modal_confirm_dialog_views.cc", "views/tab_modal_confirm_dialog_views.h", - "views/tabs/alert_indicator_button.cc", - "views/tabs/alert_indicator_button.h", + "views/tabs/alert_indicator.cc", + "views/tabs/alert_indicator.h", "views/tabs/browser_tab_strip_controller.cc", "views/tabs/browser_tab_strip_controller.h", "views/tabs/glow_hover_controller.cc",
diff --git a/chrome/browser/ui/ash/chrome_accessibility_delegate.cc b/chrome/browser/ui/ash/chrome_accessibility_delegate.cc index 10072534..8001a75 100644 --- a/chrome/browser/ui/ash/chrome_accessibility_delegate.cc +++ b/chrome/browser/ui/ash/chrome_accessibility_delegate.cc
@@ -8,9 +8,6 @@ #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/accessibility/magnification_manager.h" -#include "chrome/browser/extensions/api/automation_internal/automation_event_router.h" -#include "chrome/common/extensions/chrome_extension_messages.h" -#include "ui/aura/env.h" using chromeos::AccessibilityManager; using chromeos::MagnificationManager; @@ -45,25 +42,3 @@ return std::numeric_limits<double>::min(); } - -void ChromeAccessibilityDelegate::DispatchAccessibilityEvent( - const ui::AXTreeID& tree_id, - const std::vector<ui::AXTreeUpdate>& updates, - const ui::AXEvent& event) { - ExtensionMsg_AccessibilityEventBundleParams event_bundle; - event_bundle.tree_id = tree_id; - for (const ui::AXTreeUpdate& update : updates) - event_bundle.updates.push_back(update); - event_bundle.events.push_back(event); - event_bundle.mouse_location = aura::Env::GetInstance()->last_mouse_location(); - - // Forward the tree updates and the event to the accessibility extension. - extensions::AutomationEventRouter::GetInstance()->DispatchAccessibilityEvents( - event_bundle); -} - -void ChromeAccessibilityDelegate::DispatchTreeDestroyedEvent( - const ui::AXTreeID& tree_id) { - extensions::AutomationEventRouter::GetInstance()->DispatchTreeDestroyedEvent( - tree_id, nullptr /* browser_context */); -}
diff --git a/chrome/browser/ui/ash/chrome_accessibility_delegate.h b/chrome/browser/ui/ash/chrome_accessibility_delegate.h index 773acc7..015bd0f 100644 --- a/chrome/browser/ui/ash/chrome_accessibility_delegate.h +++ b/chrome/browser/ui/ash/chrome_accessibility_delegate.h
@@ -20,10 +20,6 @@ bool ShouldShowAccessibilityMenu() const override; void SaveScreenMagnifierScale(double scale) override; double GetSavedScreenMagnifierScale() override; - void DispatchAccessibilityEvent(const ui::AXTreeID& tree_id, - const std::vector<ui::AXTreeUpdate>& updates, - const ui::AXEvent& event) override; - void DispatchTreeDestroyedEvent(const ui::AXTreeID& tree_id) override; private: DISALLOW_COPY_AND_ASSIGN(ChromeAccessibilityDelegate);
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.cc b/chrome/browser/ui/ash/chrome_new_window_client.cc index 5e52647..d4e1a718 100644 --- a/chrome/browser/ui/ash/chrome_new_window_client.cc +++ b/chrome/browser/ui/ash/chrome_new_window_client.cc
@@ -37,6 +37,7 @@ #include "components/url_formatter/url_fixer.h" #include "content/public/browser/web_contents.h" #include "content/public/common/service_manager_connection.h" +#include "content/public/common/was_activated_option.h" #include "extensions/browser/extension_system.h" #include "extensions/common/constants.h" #include "services/service_manager/public/cpp/connector.h" @@ -151,8 +152,9 @@ browser->SetFocusToLocationBar(false); } -void ChromeNewWindowClient::NewTabWithUrl(const GURL& url) { - OpenUrlImpl(url); +void ChromeNewWindowClient::NewTabWithUrl(const GURL& url, + bool from_user_interaction) { + OpenUrlImpl(url, from_user_interaction); } void ChromeNewWindowClient::NewWindow(bool is_incognito) { @@ -269,7 +271,8 @@ url_to_open = arc::ArcUrlToExternalFileUrl(url_to_open); } - content::WebContents* tab = OpenUrlImpl(url_to_open); + content::WebContents* tab = + OpenUrlImpl(url_to_open, false /* from_user_interaction */); if (!tab) return; @@ -278,7 +281,9 @@ std::make_unique<arc::ArcWebContentsData>()); } -content::WebContents* ChromeNewWindowClient::OpenUrlImpl(const GURL& url) { +content::WebContents* ChromeNewWindowClient::OpenUrlImpl( + const GURL& url, + bool from_user_interaction) { // If the url is for system settings, show the settings in a window instead of // a browser tab. if (url.GetContent() == "settings" && @@ -293,6 +298,10 @@ ProfileManager::GetActiveUserProfile(), url, ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FROM_API)); + + if (from_user_interaction) + navigate_params.was_activated = content::WasActivatedOption::kYes; + Navigate(&navigate_params); if (navigate_params.browser) {
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.h b/chrome/browser/ui/ash/chrome_new_window_client.h index b739697..8ada39d 100644 --- a/chrome/browser/ui/ash/chrome_new_window_client.h +++ b/chrome/browser/ui/ash/chrome_new_window_client.h
@@ -29,7 +29,7 @@ // Overridden from ash::mojom::NewWindowClient: void NewTab() override; - void NewTabWithUrl(const GURL& url) override; + void NewTabWithUrl(const GURL& url, bool from_user_interaction) override; void NewWindow(bool incognito) override; void OpenFileManager() override; void OpenCrosh() override; @@ -48,8 +48,11 @@ // Opens a URL in a new tab. Returns the WebContents for the tab that // opened the URL. If the URL is for a chrome://settings page, opens settings - // in a new window and returns null. - content::WebContents* OpenUrlImpl(const GURL& url); + // in a new window and returns null. If the |from_user_interaction| is true + // then the page will load with a user activation. This means it will be able + // to autoplay media without restriction. + content::WebContents* OpenUrlImpl(const GURL& url, + bool from_user_interaction); std::unique_ptr<TabRestoreHelper> tab_restore_helper_;
diff --git a/chrome/browser/ui/aura/accessibility/DEPS b/chrome/browser/ui/aura/accessibility/DEPS index fbced7a8..b2306413 100644 --- a/chrome/browser/ui/aura/accessibility/DEPS +++ b/chrome/browser/ui/aura/accessibility/DEPS
@@ -1,7 +1,6 @@ specific_include_rules = { "automation_manager_aura\.cc": [ # TODO(mash): Fix. https://crbug.com/756054 - "+ash/accessibility/ax_host_service.h", "+ash/shell.h", "+ash/wm/window_util.h", ],
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc index abda461..cc6ceae 100644 --- a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc +++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
@@ -25,9 +25,9 @@ #include "ui/views/widget/widget.h" #if defined(OS_CHROMEOS) -#include "ash/accessibility/ax_host_service.h" #include "ash/shell.h" #include "ash/wm/window_util.h" +#include "chrome/browser/chromeos/accessibility/ax_host_service.h" #include "ui/base/ui_base_features.h" #include "ui/views/widget/widget_delegate.h" #endif @@ -58,8 +58,7 @@ } } // Gain access to out-of-process native windows. - // TODO(mash): Split AXHostService into chrome and ash parts. - ash::AXHostService::SetAutomationEnabled(true); + AXHostService::SetAutomationEnabled(true); #endif } @@ -68,7 +67,7 @@ Reset(true); #if defined(OS_CHROMEOS) - ash::AXHostService::SetAutomationEnabled(false); + AXHostService::SetAutomationEnabled(false); #endif } @@ -250,13 +249,14 @@ ui::AXNodeData node_data; widget->widget_delegate()->GetContentsView()->GetAccessibleNodeData( &node_data); - child_ax_tree_id = - node_data.GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId); + child_ax_tree_id = ui::AXTreeID::FromString( + node_data.GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId)); DCHECK_NE(child_ax_tree_id, ui::AXTreeIDUnknown()); DCHECK_NE(child_ax_tree_id, ui::DesktopAXTreeID()); } else { // For normal windows the (optional) child tree is an aura window property. - std::string* child_ax_tree_id_ptr = window->GetProperty(ui::kChildAXTreeID); + ui::AXTreeID* child_ax_tree_id_ptr = + window->GetProperty(ui::kChildAXTreeID); if (child_ax_tree_id_ptr) child_ax_tree_id = *child_ax_tree_id_ptr; }
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc b/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc index b15a37a..cda6bd1 100644 --- a/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc +++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc
@@ -31,8 +31,8 @@ std::vector<views::AXAuraObjWrapper*>* web_hosts) { ui::AXNodeData node_data; tree->SerializeNode(node, &node_data); - if (node_data.GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId) == - target_ax_tree_id) { + if (ui::AXTreeID::FromString(node_data.GetStringAttribute( + ax::mojom::StringAttribute::kChildTreeId)) == target_ax_tree_id) { web_hosts->push_back(node); }
diff --git a/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.cc b/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.cc index f22ec7a..f6b86e91 100644 --- a/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.cc +++ b/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.cc
@@ -164,7 +164,7 @@ Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); local_card_migration_bubble_ = browser->window()->ShowLocalCardMigrationBubble(web_contents(), this, - true); + is_reshow_); DCHECK(local_card_migration_bubble_); UpdateIcon(); timer_.reset(new base::ElapsedTimer());
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 0605c54..15a9342 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -305,6 +305,18 @@ return nullptr; } +void UnmuteIfMutedByExtension(content::WebContents* contents, + const std::string& extension_id) { + LastMuteMetadata::CreateForWebContents(contents); // Ensures metadata exists. + LastMuteMetadata* const metadata = + LastMuteMetadata::FromWebContents(contents); + if (metadata->reason == TabMutedReason::EXTENSION && + metadata->extension_id == extension_id) { + chrome::SetTabAudioMuted(contents, false, TabMutedReason::EXTENSION, + extension_id); + } +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -2219,7 +2231,7 @@ extension->id())) { tab_strip_model_->CloseWebContentsAt(i, TabStripModel::CLOSE_NONE); } else { - chrome::UnmuteIfMutedByExtension(web_contents, extension->id()); + UnmuteIfMutedByExtension(web_contents, extension->id()); } } }
diff --git a/chrome/browser/ui/libgtkui/nav_button_provider_gtk.cc b/chrome/browser/ui/libgtkui/nav_button_provider_gtk.cc index 042b2d9..9652018a 100644 --- a/chrome/browser/ui/libgtkui/nav_button_provider_gtk.cc +++ b/chrome/browser/ui/libgtkui/nav_button_provider_gtk.cc
@@ -6,7 +6,6 @@ #include <gtk/gtk.h> -#include "chrome/browser/ui/libgtkui/gtk_background_painter.h" #include "chrome/browser/ui/libgtkui/gtk_util.h" #include "ui/base/glib/scoped_gobject.h" #include "ui/gfx/image/image_skia.h" @@ -183,13 +182,6 @@ MarginFromStyleContext(button_context, GTK_STATE_FLAG_NORMAL); } -ScopedStyleContext CreateAvatarButtonContext(GtkStyleContext* header_context) { - return AppendCssNodeToStyleContext( - header_context, GtkVersionCheck(3, 20) - ? "GtkButton#button.image-button.toggle" - : "GtkToggleButton#button.image-button"); -} - class NavButtonImageSource : public gfx::ImageSkiaSource { public: NavButtonImageSource(chrome::FrameButtonDisplayType type, @@ -417,84 +409,4 @@ return inter_button_spacing_; } -std::unique_ptr<views::Background> -NavButtonProviderGtk::CreateAvatarButtonBackground( - const views::Button* avatar_button) const { - auto header_context = CreateHeaderContext(false); - auto button_context = CreateAvatarButtonContext(header_context); - return std::make_unique<GtkBackgroundPainter>(avatar_button, - std::move(button_context)); -} - -void NavButtonProviderGtk::CalculateCaptionButtonLayout( - const gfx::Size& content_size, - int top_area_height, - gfx::Size* caption_button_size, - gfx::Insets* caption_button_spacing) const { - auto header_context = CreateHeaderContext(false); - gfx::InsetsF header_padding = - PaddingFromStyleContext(header_context, GTK_STATE_FLAG_NORMAL); - - auto button_context = CreateAvatarButtonContext(header_context); - gfx::InsetsF button_padding = - PaddingFromStyleContext(button_context, GTK_STATE_FLAG_NORMAL); - gfx::InsetsF button_border = - BorderFromStyleContext(button_context, GTK_STATE_FLAG_NORMAL); - gfx::InsetsF button_margin = - MarginFromStyleContext(button_context, GTK_STATE_FLAG_NORMAL); - - float content_width = content_size.width(); - float content_height = content_size.height(); - if (GtkVersionCheck(3, 20)) { - int min_width, min_height; -#if GTK_CHECK_VERSION(3, 90, 0) - gtk_style_context_get(button_context, "min-width", &min_width, "min-height", - &min_height, nullptr); -#else - gtk_style_context_get(button_context, GTK_STATE_FLAG_NORMAL, "min-width", - &min_width, "min-height", &min_height, nullptr); -#endif - content_width = std::max(content_width, static_cast<float>(min_width)); - content_height = std::max(content_height, static_cast<float>(min_height)); - } - - gfx::InsetsF scalable_insets = - header_padding + button_padding + button_border + button_margin; - float scalable_height = - scalable_insets.top() + scalable_insets.bottom() + content_height; - - float scale = scalable_height > top_area_height && scalable_height != 0 - ? top_area_height / scalable_height - : 1.0f; - header_padding = header_padding.Scale(scale); - button_padding = button_padding.Scale(scale); - button_border = button_border.Scale(scale); - button_margin = button_margin.Scale(scale); - // Don't scale |content_width| down if the button is wide. - if (content_width <= content_height) - content_width *= scale; - content_height *= scale; - - float button_height = content_height + button_border.top() + - button_border.bottom() + button_padding.top() + - button_padding.bottom(); - float button_height_with_margin = - button_height + button_margin.top() + button_margin.bottom(); - float shiftable_region_start = header_padding.top(); - float shiftable_region_end = top_area_height - header_padding.bottom(); - float button_offset_in_shiftable_region = - (shiftable_region_end - shiftable_region_start - - button_height_with_margin) / - 2; - - *caption_button_size = gfx::Size( - std::round(content_width + button_border.left() + button_border.right() + - button_padding.left() + button_padding.right()), - std::round(button_height)); - *caption_button_spacing = gfx::Insets( - std::round(shiftable_region_start + button_margin.top() + - button_offset_in_shiftable_region), - std::round(button_margin.left()), 0, std::round(button_margin.right())); -} - } // namespace libgtkui
diff --git a/chrome/browser/ui/libgtkui/nav_button_provider_gtk.h b/chrome/browser/ui/libgtkui/nav_button_provider_gtk.h index e2994cd..175dc194 100644 --- a/chrome/browser/ui/libgtkui/nav_button_provider_gtk.h +++ b/chrome/browser/ui/libgtkui/nav_button_provider_gtk.h
@@ -28,13 +28,6 @@ chrome::FrameButtonDisplayType type) const override; gfx::Insets GetTopAreaSpacing() const override; int GetInterNavButtonSpacing() const override; - std::unique_ptr<views::Background> CreateAvatarButtonBackground( - const views::Button* avatar_button) const override; - void CalculateCaptionButtonLayout( - const gfx::Size& content_size, - int top_area_height, - gfx::Size* caption_button_size, - gfx::Insets* caption_button_spacing) const override; private: std::map<chrome::FrameButtonDisplayType,
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc index 9561463..7242589 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc
@@ -535,9 +535,8 @@ : (pending_password_.federation_origin.opaque() ? PasswordTitleType::SAVE_PASSWORD : PasswordTitleType::SAVE_ACCOUNT); - GetSavePasswordDialogTitleTextAndLinkRange( - GetWebContents()->GetVisibleURL(), origin_, IsSyncUser(GetProfile()), - type, &title_, &title_brand_link_range_); + GetSavePasswordDialogTitleTextAndLinkRange(GetWebContents()->GetVisibleURL(), + origin_, type, &title_); } void ManagePasswordsBubbleModel::UpdateManageStateTitle() {
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model.h b/chrome/browser/ui/passwords/manage_passwords_bubble_model.h index bd03214..6141d53 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model.h +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model.h
@@ -173,6 +173,7 @@ base::string16 title_; // Range of characters in the title that contains the Smart Lock Brand and // should point to an article. For the default title the range is empty. + // TODO(crbug/890336): remove. gfx::Range title_brand_link_range_; autofill::PasswordForm pending_password_; std::vector<autofill::PasswordForm> local_credentials_;
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc index 338d09e7..3dd2618 100644 --- a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc +++ b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc
@@ -24,7 +24,6 @@ #include "ui/gfx/geometry/size.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_operations.h" -#include "ui/gfx/range/range.h" #include "url/gurl.h" #include "url/origin.h" @@ -74,13 +73,10 @@ form.username_value + base::ASCIIToUTF16("\n") + federation); } -void GetSavePasswordDialogTitleTextAndLinkRange( - const GURL& user_visible_url, - const GURL& form_origin_url, - bool is_smartlock_branding_enabled, - PasswordTitleType dialog_type, - base::string16* title, - gfx::Range* title_link_range) { +void GetSavePasswordDialogTitleTextAndLinkRange(const GURL& user_visible_url, + const GURL& form_origin_url, + PasswordTitleType dialog_type, + base::string16* title) { DCHECK(!password_manager::IsValidAndroidFacetURI(form_origin_url.spec())); std::vector<size_t> offsets; std::vector<base::string16> replacements; @@ -109,24 +105,8 @@ replacements.push_back(url_formatter::FormatUrlForSecurityDisplay( form_origin_url, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS)); } - base::string16 title_link; - if (title_id == IDS_SAVE_ACCOUNT) { - title_link = - is_smartlock_branding_enabled - ? l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SMART_LOCK) - : l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_TITLE_BRAND); - replacements.insert(replacements.begin(), title_link); - } *title = l10n_util::GetStringFUTF16(title_id, replacements, &offsets); - if (title_id == IDS_SAVE_ACCOUNT && is_smartlock_branding_enabled && - !offsets.empty()) { - // |offsets| can be empty when the localised string associated with - // |title_id| could not be found. While this situation is an error, it - // needs to be handled gracefully, see http://crbug.com/658902#c18. - *title_link_range = - gfx::Range(offsets[0], offsets[0] + title_link.length()); - } } void GetManagePasswordsDialogTitleText(const GURL& user_visible_url, @@ -152,39 +132,6 @@ } } -void GetAccountChooserDialogTitleTextAndLinkRange( - bool is_smartlock_branding_enabled, - bool many_accounts, - base::string16* title, - gfx::Range* title_link_range) { - int string_id = many_accounts - ? IDS_PASSWORD_MANAGER_ACCOUNT_CHOOSER_TITLE_MANY_ACCOUNTS - : IDS_PASSWORD_MANAGER_ACCOUNT_CHOOSER_TITLE_ONE_ACCOUNT; - GetBrandedTextAndLinkRange(is_smartlock_branding_enabled, - string_id, string_id, - title, title_link_range); -} - -void GetBrandedTextAndLinkRange(bool is_smartlock_branding_enabled, - int smartlock_string_id, - int default_string_id, - base::string16* out_string, - gfx::Range* link_range) { - if (is_smartlock_branding_enabled) { - size_t offset; - base::string16 brand_name = - l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SMART_LOCK); - *out_string = l10n_util::GetStringFUTF16(smartlock_string_id, brand_name, - &offset); - *link_range = gfx::Range(offset, offset + brand_name.length()); - } else { - *out_string = l10n_util::GetStringFUTF16( - default_string_id, - l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_TITLE_BRAND)); - *link_range = gfx::Range(); - } -} - base::string16 GetDisplayUsername(const autofill::PasswordForm& form) { return form.username_value.empty() ? l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN)
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils.h b/chrome/browser/ui/passwords/manage_passwords_view_utils.h index 6330d067..3af5e27 100644 --- a/chrome/browser/ui/passwords/manage_passwords_view_utils.h +++ b/chrome/browser/ui/passwords/manage_passwords_view_utils.h
@@ -13,7 +13,6 @@ namespace gfx { class ImageSkia; -class Range; } // namespace gfx class GURL; @@ -45,13 +44,10 @@ // bubble (depending on |dialog_type|). If the registry controlled domain of // |user_visible_url| (i.e. the one seen in the omnibox) differs from the // registry controlled domain of |form_origin_url|, it adds the site name. -void GetSavePasswordDialogTitleTextAndLinkRange( - const GURL& user_visible_url, - const GURL& form_origin_url, - bool is_smartlock_branding_enabled, - PasswordTitleType dialog_type, - base::string16* title, - gfx::Range* title_link_range); +void GetSavePasswordDialogTitleTextAndLinkRange(const GURL& user_visible_url, + const GURL& form_origin_url, + PasswordTitleType dialog_type, + base::string16* title); // Sets the formatted |title| in the Manage Passwords bubble. If the registry // controlled domain of |user_visible_url| (i.e. the one seen in the omnibox) @@ -69,29 +65,6 @@ bool has_credentials, base::string16* title); -// Sets the formatted |title| in the Account Chooser UI. -// If |is_smartlock_branding_enabled| is true, sets the |title_link_range| for -// the "Google Smart Lock" text range to be set visibly as a hyperlink in the -// dialog bubble otherwise chooses the title which doesn't contain Smart Lock -// branding. -void GetAccountChooserDialogTitleTextAndLinkRange( - bool is_smartlock_branding_enabled, - bool many_accounts, - base::string16* title, - gfx::Range* title_link_range); - -// Loads |smartlock_string_id| or |default_string_id| string from the resources -// and substitutes the placeholder with the correct password manager branding -// (Google Smart Lock, Google Chrome or Chromium) according to -// |is_smartlock_branding_enabled|. If |is_smartlock_branding_enabled| is true -// then |link_range| contains the link range for the brand name. -void GetBrandedTextAndLinkRange( - bool is_smartlock_branding_enabled, - int smartlock_string_id, - int default_string_id, - base::string16* out_string, - gfx::Range* link_range); - // Returns an username in the form that should be shown in the bubble. base::string16 GetDisplayUsername(const autofill::PasswordForm& form);
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_view_utils_unittest.cc index ba4e9f6..77286ad 100644 --- a/chrome/browser/ui/passwords/manage_passwords_view_utils_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_view_utils_unittest.cc
@@ -65,71 +65,68 @@ const struct { const char* const user_visible_url; const char* const form_origin_url; - bool is_smartlock_branding_enabled; PasswordTitleType bubble_type; const char* const expected_domain_placeholder; // domain name - size_t expected_link_range_start; - size_t expected_link_range_end; } kDomainsTestCases[] = { // Same domains. {"http://example.com/landing", "http://example.com/login#form?value=3", - false, PasswordTitleType::SAVE_PASSWORD, "", 0, 0}, + PasswordTitleType::SAVE_PASSWORD, ""}, {"http://example.com/landing", "http://example.com/login#form?value=3", - true, PasswordTitleType::SAVE_PASSWORD, "", 0, 0}, + PasswordTitleType::SAVE_PASSWORD, ""}, // Different subdomains. {"https://a.example.com/landing", - "https://b.example.com/login#form?value=3", false, - PasswordTitleType::SAVE_PASSWORD, "", 0, 0}, + "https://b.example.com/login#form?value=3", + PasswordTitleType::SAVE_PASSWORD, ""}, {"https://a.example.com/landing", - "https://b.example.com/login#form?value=3", true, - PasswordTitleType::SAVE_PASSWORD, "", 0, 0}, + "https://b.example.com/login#form?value=3", + PasswordTitleType::SAVE_PASSWORD, ""}, // Different domains. - {"https://another.org", "https://example.com:/login#form?value=3", false, - PasswordTitleType::SAVE_PASSWORD, "example.com", 0, 0}, - {"https://another.org", "https://example.com/login#form?value=3", true, - PasswordTitleType::SAVE_PASSWORD, "example.com", 0, 0}, + {"https://another.org", "https://example.com:/login#form?value=3", + PasswordTitleType::SAVE_PASSWORD, "example.com"}, + {"https://another.org", "https://example.com/login#form?value=3", + PasswordTitleType::SAVE_PASSWORD, "example.com"}, // Different domains and password form origin url with // default port for the scheme. - {"https://another.org", "https://example.com:443/login#form?value=3", false, - PasswordTitleType::SAVE_PASSWORD, "example.com", 0, 0}, - {"https://another.org", "http://example.com:80/login#form?value=3", true, - PasswordTitleType::SAVE_PASSWORD, "example.com", 0, 0}, + {"https://another.org", "https://example.com:443/login#form?value=3", + PasswordTitleType::SAVE_PASSWORD, "example.com"}, + {"https://another.org", "http://example.com:80/login#form?value=3", + PasswordTitleType::SAVE_PASSWORD, "example.com"}, // Different domains and password form origin url with // non-default port for the scheme. {"https://another.org", "https://example.com:8001/login#form?value=3", - false, PasswordTitleType::SAVE_PASSWORD, "example.com:8001", 0, 0}, - {"https://another.org", "https://example.com:8001/login#form?value=3", true, - PasswordTitleType::SAVE_PASSWORD, "example.com:8001", 0, 0}, + PasswordTitleType::SAVE_PASSWORD, "example.com:8001"}, + {"https://another.org", "https://example.com:8001/login#form?value=3", + PasswordTitleType::SAVE_PASSWORD, "example.com:8001"}, // Update bubble, same domains. {"http://example.com/landing", "http://example.com/login#form?value=3", - false, PasswordTitleType::UPDATE_PASSWORD, "", 0, 0}, + PasswordTitleType::UPDATE_PASSWORD, ""}, {"http://example.com/landing", "http://example.com/login#form?value=3", - true, PasswordTitleType::UPDATE_PASSWORD, "", 0, 0}, + PasswordTitleType::UPDATE_PASSWORD, ""}, // Update bubble, different domains. - {"https://another.org", "http://example.com/login#form?value=3", false, - PasswordTitleType::UPDATE_PASSWORD, "example.com", 0, 0}, - {"https://another.org", "http://example.com/login#form?value=3", true, - PasswordTitleType::UPDATE_PASSWORD, "example.com", 0, 0}, + {"https://another.org", "http://example.com/login#form?value=3", + PasswordTitleType::UPDATE_PASSWORD, "example.com"}, + {"https://another.org", "http://example.com/login#form?value=3", + PasswordTitleType::UPDATE_PASSWORD, "example.com"}, // Same domains, federated credential. {"http://example.com/landing", "http://example.com/login#form?value=3", - false, PasswordTitleType::SAVE_ACCOUNT, "", 0, 0}, + PasswordTitleType::SAVE_ACCOUNT, ""}, {"http://example.com/landing", "http://example.com/login#form?value=3", - true, PasswordTitleType::SAVE_ACCOUNT, "", 12, 29}, + PasswordTitleType::SAVE_ACCOUNT, ""}, // Different subdomains, federated credential. {"https://a.example.com/landing", - "https://b.example.com/login#form?value=3", false, - PasswordTitleType::SAVE_ACCOUNT, "", 0, 0}, + "https://b.example.com/login#form?value=3", + PasswordTitleType::SAVE_ACCOUNT, ""}, {"https://a.example.com/landing", - "https://b.example.com/login#form?value=3", true, - PasswordTitleType::SAVE_ACCOUNT, "", 12, 29}}; + "https://b.example.com/login#form?value=3", + PasswordTitleType::SAVE_ACCOUNT, ""}}; } // namespace @@ -142,31 +139,21 @@ << kDomainsTestCases[i].form_origin_url); base::string16 title; - gfx::Range title_link_range; GetSavePasswordDialogTitleTextAndLinkRange( GURL(kDomainsTestCases[i].user_visible_url), GURL(kDomainsTestCases[i].form_origin_url), - kDomainsTestCases[i].is_smartlock_branding_enabled, - kDomainsTestCases[i].bubble_type, &title, &title_link_range); + kDomainsTestCases[i].bubble_type, &title); // Verify against expectations. base::string16 domain = base::ASCIIToUTF16(kDomainsTestCases[i].expected_domain_placeholder); EXPECT_TRUE(title.find(domain) != base::string16::npos); - EXPECT_EQ(kDomainsTestCases[i].expected_link_range_start, - title_link_range.start()); - EXPECT_EQ(kDomainsTestCases[i].expected_link_range_end, - title_link_range.end()); if (kDomainsTestCases[i].bubble_type == PasswordTitleType::UPDATE_PASSWORD) { EXPECT_TRUE(title.find(base::ASCIIToUTF16("Update")) != base::string16::npos); - } else if (kDomainsTestCases[i].bubble_type == - PasswordTitleType::SAVE_PASSWORD) { - EXPECT_TRUE(title.find(base::ASCIIToUTF16("Save")) != - base::string16::npos); } else { - EXPECT_TRUE(title.find(base::ASCIIToUTF16("save")) != + EXPECT_TRUE(title.find(base::ASCIIToUTF16("Save")) != base::string16::npos); } } @@ -182,9 +169,7 @@ base::string16()); base::string16 title; - gfx::Range title_link_range; const GURL kExample("http://example.org"); - const bool kBrandingEnabled = true; // The arguments passed below have this importance for the codepath: // * The first two URLs need to be the same, otherwise // IDS_SAVE_PASSWORD_DIFFERENT_DOMAINS_TITLE will be used instead of @@ -195,13 +180,11 @@ // * SAVE_PASSWORD dialog type needs to be passed to match the // IDS_SAVE_PASSWORD overridden above. GetSavePasswordDialogTitleTextAndLinkRange( - kExample, kExample, kBrandingEnabled, PasswordTitleType::SAVE_PASSWORD, - &title, &title_link_range); + kExample, kExample, PasswordTitleType::SAVE_PASSWORD, &title); // Verify that the test did not pass just because // GetSavePasswordDialogTitleTextAndLinkRange changed the resource IDs it uses // (and hence did not get the overridden empty string). If the empty localised // string was used, the title and the range will be empty as well. - EXPECT_TRUE(title_link_range.is_empty()); EXPECT_THAT(title, testing::IsEmpty()); } @@ -223,45 +206,3 @@ EXPECT_TRUE(title.find(domain) != base::string16::npos); } } - -// The parameter is |many_accounts| passed to -// GetAccountChooserDialogTitleTextAndLinkRange -class AccountChooserDialogTitleTest : public ::testing::TestWithParam<bool> { -}; - -TEST_P(AccountChooserDialogTitleTest, - GetAccountChooserDialogTitleTextAndLinkRangeSmartLockUsers) { - base::string16 branding = - l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SMART_LOCK); - base::string16 title; - gfx::Range title_link_range; - GetAccountChooserDialogTitleTextAndLinkRange( - true /* is_smartlock_branding_enabled */, - GetParam(), - &title, &title_link_range); - - // Check that branding string is a part of a title. - EXPECT_LT(title.find(branding, 0), title.size()); - EXPECT_GT(title.find(branding, 0), 0U); - // Check that link range is not empty. - EXPECT_NE(0U, title_link_range.start()); - EXPECT_NE(0U, title_link_range.end()); -} - -TEST_P(AccountChooserDialogTitleTest, - GetAccountChooserDialogTitleTextAndLinkRangeNonSmartLockUsers) { - base::string16 branding = - l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SMART_LOCK); - base::string16 title; - gfx::Range title_link_range; - GetAccountChooserDialogTitleTextAndLinkRange( - false /* is_smartlock_branding_enabled */, - GetParam(), - &title, &title_link_range); - EXPECT_GE(title.find(branding, 0), title.size()); - EXPECT_EQ(0U, title_link_range.start()); - EXPECT_EQ(0U, title_link_range.end()); -} - -INSTANTIATE_TEST_CASE_P(, AccountChooserDialogTitleTest, - ::testing::Bool());
diff --git a/chrome/browser/ui/passwords/password_dialog_controller_impl.cc b/chrome/browser/ui/passwords/password_dialog_controller_impl.cc index 55e9d60..791b516 100644 --- a/chrome/browser/ui/passwords/password_dialog_controller_impl.cc +++ b/chrome/browser/ui/passwords/password_dialog_controller_impl.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" #include "chrome/browser/ui/passwords/password_dialog_prompts.h" #include "chrome/browser/ui/passwords/passwords_model_delegate.h" +#include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/autofill/core/common/password_form.h" #include "components/browser_sync/profile_sync_service.h" @@ -18,16 +19,6 @@ #include "components/prefs/pref_service.h" #include "ui/base/l10n/l10n_util.h" -namespace { - -bool IsSmartLockBrandingEnabled(Profile* profile) { - const browser_sync::ProfileSyncService* sync_service = - ProfileSyncServiceFactory::GetForProfile(profile); - return password_bubble_experiment::IsSmartLockUser(sync_service); -} - -} // namespace - PasswordDialogControllerImpl::PasswordDialogControllerImpl( Profile* profle, PasswordsModelDelegate* delegate) @@ -69,11 +60,8 @@ std::pair<base::string16, gfx::Range> PasswordDialogControllerImpl::GetAccoutChooserTitle() const { std::pair<base::string16, gfx::Range> result; - GetAccountChooserDialogTitleTextAndLinkRange( - IsSmartLockBrandingEnabled(profile_), - local_credentials_.size() > 1, - &result.first, - &result.second); + result.first = + l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_ACCOUNT_CHOOSER_TITLE); return result; } @@ -91,10 +79,9 @@ std::pair<base::string16, gfx::Range> PasswordDialogControllerImpl::GetAutoSigninText() const { std::pair<base::string16, gfx::Range> result; - GetBrandedTextAndLinkRange(IsSmartLockBrandingEnabled(profile_), - IDS_AUTO_SIGNIN_FIRST_RUN_SMART_LOCK_TEXT, - IDS_AUTO_SIGNIN_FIRST_RUN_TEXT, &result.first, - &result.second); + result.first = l10n_util::GetStringFUTF16( + IDS_AUTO_SIGNIN_FIRST_RUN_TEXT, + l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_TITLE_BRAND)); return result; }
diff --git a/chrome/browser/ui/passwords/password_dialog_controller_impl.h b/chrome/browser/ui/passwords/password_dialog_controller_impl.h index 6a2d1b6..d9520544 100644 --- a/chrome/browser/ui/passwords/password_dialog_controller_impl.h +++ b/chrome/browser/ui/passwords/password_dialog_controller_impl.h
@@ -34,9 +34,11 @@ // PasswordDialogController: const FormsVector& GetLocalForms() const override; + // TODO(890336): get rid of the range. std::pair<base::string16, gfx::Range> GetAccoutChooserTitle() const override; bool ShouldShowSignInButton() const override; base::string16 GetAutoSigninPromoTitle() const override; + // TODO(890336): get rid of the range. std::pair<base::string16, gfx::Range> GetAutoSigninText() const override; void OnSmartLockLinkClicked() override; void OnChooseCredentials(
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index b5fe118..15bda0bf 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -16,9 +16,11 @@ #include "base/metrics/user_metrics.h" #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/defaults.h" #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/lifetime/browser_shutdown.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/tab_contents/core_tab_helper.h" #include "chrome/browser/ui/tab_contents/core_tab_helper_delegate.h" #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" @@ -26,6 +28,7 @@ #include "chrome/browser/ui/tabs/tab_utils.h" #include "chrome/browser/ui/web_contents_sizer.h" #include "chrome/common/url_constants.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/feature_engagement/buildflags.h" #include "components/web_modal/web_contents_modal_dialog_manager.h" #include "content/public/browser/render_process_host.h" @@ -1121,7 +1124,7 @@ base::RecordAction( UserMetricsAction("SoundContentSetting.UnmuteBy.TabStrip")); } - chrome::SetSitesMuted(*this, indices, mute); + SetSitesMuted(indices, mute); break; } @@ -1606,6 +1609,35 @@ } } +// Sets the sound content setting for each site at the |indices|. +void TabStripModel::SetSitesMuted(const std::vector<int>& indices, + bool mute) const { + for (int tab_index : indices) { + content::WebContents* web_contents = GetWebContentsAt(tab_index); + GURL url = web_contents->GetLastCommittedURL(); + if (url.SchemeIs(content::kChromeUIScheme)) { + // chrome:// URLs don't have content settings but can be muted, so just + // mute the WebContents. + chrome::SetTabAudioMuted(web_contents, mute, + TabMutedReason::CONTENT_SETTING_CHROME, + std::string()); + } else { + Profile* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + HostContentSettingsMap* settings = + HostContentSettingsMapFactory::GetForProfile(profile); + ContentSetting setting = + mute ? CONTENT_SETTING_BLOCK : CONTENT_SETTING_ALLOW; + if (setting == settings->GetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_SOUND, nullptr)) { + setting = CONTENT_SETTING_DEFAULT; + } + settings->SetContentSettingDefaultScope( + url, url, CONTENT_SETTINGS_TYPE_SOUND, std::string(), setting); + } + } +} + // static bool TabStripModel::OpenerMatches(const std::unique_ptr<WebContentsData>& data, const WebContents* opener,
diff --git a/chrome/browser/ui/tabs/tab_strip_model.h b/chrome/browser/ui/tabs/tab_strip_model.h index 3fe845c..496bc3a 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.h +++ b/chrome/browser/ui/tabs/tab_strip_model.h
@@ -544,6 +544,9 @@ // starting at |start| to |index|. See MoveSelectedTabsTo for more details. void MoveSelectedTabsToImpl(int index, size_t start, size_t length); + // Sets the sound content setting for each site at the |indices|. + void SetSitesMuted(const std::vector<int>& indices, bool mute) const; + // Returns true if the tab represented by the specified data has an opener // that matches the specified one. If |use_group| is true, then this will // fall back to check the group relationship as well.
diff --git a/chrome/browser/ui/tabs/tab_utils.cc b/chrome/browser/ui/tabs/tab_utils.cc index 5d476e6..1111dc6 100644 --- a/chrome/browser/ui/tabs/tab_utils.cc +++ b/chrome/browser/ui/tabs/tab_utils.cc
@@ -6,152 +6,20 @@ #include <utility> -#include "base/command_line.h" #include "base/feature_list.h" -#include "base/strings/string16.h" -#include "build/build_config.h" -#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/themes/theme_properties.h" -#include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/recently_audible_helper.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/usb/usb_tab_helper.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/grit/generated_resources.h" #include "components/content_settings/core/browser/host_content_settings_map.h" -#include "content/public/browser/picture_in_picture_window_controller.h" -#include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" #include "content/public/common/url_constants.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" -#include "ui/base/theme_provider.h" -#include "ui/gfx/animation/multi_animation.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/paint_vector_icon.h" -#include "ui/native_theme/common_theme.h" -#include "ui/native_theme/native_theme.h" - -#if defined(OS_MACOSX) -#include "ui/base/resource/resource_bundle.h" -#endif - -struct LastMuteMetadata - : public content::WebContentsUserData<LastMuteMetadata> { - TabMutedReason reason = TabMutedReason::NONE; - std::string extension_id; - - private: - explicit LastMuteMetadata(content::WebContents* contents) {} - friend class content::WebContentsUserData<LastMuteMetadata>; -}; namespace chrome { -namespace { - -// Interval between frame updates of the tab indicator animations. This is not -// the usual 60 FPS because a trade-off must be made between tab UI animation -// smoothness and media recording/playback performance on low-end hardware. -const int kIndicatorFrameIntervalMs = 50; // 20 FPS - -// Fade-in/out duration for the tab indicator animations. Fade-in is quick to -// immediately notify the user. Fade-out is more gradual, so that the user has -// a chance of finding a tab that has quickly "blipped" on and off. -const int kIndicatorFadeInDurationMs = 200; -const int kIndicatorFadeOutDurationMs = 1000; - -// Animation that throbs in (towards 1.0) and out (towards 0.0), and ends in the -// "in" state. -class TabRecordingIndicatorAnimation : public gfx::MultiAnimation { - public: - ~TabRecordingIndicatorAnimation() override {} - - // Overridden to provide alternating "towards in" and "towards out" behavior. - double GetCurrentValue() const override; - - static std::unique_ptr<TabRecordingIndicatorAnimation> Create(); - - private: - TabRecordingIndicatorAnimation(const gfx::MultiAnimation::Parts& parts, - const base::TimeDelta interval) - : MultiAnimation(parts, interval) {} - - // Number of times to "toggle throb" the recording and tab capture indicators - // when they first appear. - static const int kCaptureIndicatorThrobCycles = 5; -}; - -double TabRecordingIndicatorAnimation::GetCurrentValue() const { - return current_part_index() % 2 ? - 1.0 - MultiAnimation::GetCurrentValue() : - MultiAnimation::GetCurrentValue(); -} - -std::unique_ptr<TabRecordingIndicatorAnimation> -TabRecordingIndicatorAnimation::Create() { - MultiAnimation::Parts parts; - static_assert(kCaptureIndicatorThrobCycles % 2 != 0, - "odd number of cycles required so animation finishes in showing state"); - for (int i = 0; i < kCaptureIndicatorThrobCycles; ++i) { - parts.push_back(MultiAnimation::Part( - i % 2 ? kIndicatorFadeOutDurationMs : kIndicatorFadeInDurationMs, - gfx::Tween::EASE_IN)); - } - const base::TimeDelta interval = - base::TimeDelta::FromMilliseconds(kIndicatorFrameIntervalMs); - std::unique_ptr<TabRecordingIndicatorAnimation> animation( - new TabRecordingIndicatorAnimation(parts, interval)); - animation->set_continuous(false); - return animation; -} - -} // namespace - -bool ShouldTabShowFavicon(int capacity, - bool is_pinned_tab, - bool is_active_tab, - bool has_favicon, - TabAlertState alert_state) { - if (!has_favicon) - return false; - int required_capacity = 1; - if (ShouldTabShowCloseButton(capacity, is_pinned_tab, is_active_tab)) - ++required_capacity; - if (ShouldTabShowAlertIndicator(capacity, is_pinned_tab, is_active_tab, - has_favicon, alert_state)) { - ++required_capacity; - } - return capacity >= required_capacity; -} - -bool ShouldTabShowAlertIndicator(int capacity, - bool is_pinned_tab, - bool is_active_tab, - bool has_favicon, - TabAlertState alert_state) { - if (alert_state == TabAlertState::NONE) - return false; - if (ShouldTabShowCloseButton(capacity, is_pinned_tab, is_active_tab)) - return capacity >= 2; - return capacity >= 1; -} - -bool ShouldTabShowCloseButton(int capacity, - bool is_pinned_tab, - bool is_active_tab) { - if (is_pinned_tab) - return false; - else if (is_active_tab) - return true; - else - return capacity >= 3; -} - TabAlertState GetTabAlertStateForContents(content::WebContents* contents) { if (!contents) return TabAlertState::NONE; @@ -198,196 +66,8 @@ return TabAlertState::NONE; } -gfx::Image GetTabAlertIndicatorImage(TabAlertState alert_state, - SkColor button_color) { - const gfx::VectorIcon* icon = nullptr; - int image_width = GetLayoutConstant(TAB_ALERT_INDICATOR_ICON_WIDTH); - const bool is_touch_optimized_ui = - ui::MaterialDesignController::IsTouchOptimizedUiEnabled(); - switch (alert_state) { - case TabAlertState::AUDIO_PLAYING: - icon = is_touch_optimized_ui ? &kTabAudioRoundedIcon : &kTabAudioIcon; - break; - case TabAlertState::AUDIO_MUTING: - icon = is_touch_optimized_ui ? &kTabAudioMutingRoundedIcon - : &kTabAudioMutingIcon; - break; - case TabAlertState::MEDIA_RECORDING: - case TabAlertState::DESKTOP_CAPTURING: - icon = &kTabMediaRecordingIcon; - break; - case TabAlertState::TAB_CAPTURING: - icon = is_touch_optimized_ui ? &kTabMediaCapturingWithArrowIcon - : &kTabMediaCapturingIcon; - // Tab capturing and presenting icon uses a different width compared to - // the other tab alert indicator icons. - image_width = GetLayoutConstant(TAB_ALERT_INDICATOR_CAPTURE_ICON_WIDTH); - break; - case TabAlertState::BLUETOOTH_CONNECTED: - icon = &kTabBluetoothConnectedIcon; - break; - case TabAlertState::USB_CONNECTED: - icon = &kTabUsbConnectedIcon; - break; - case TabAlertState::PIP_PLAYING: - icon = &kPictureInPictureAltIcon; - break; - case TabAlertState::NONE: - return gfx::Image(); - } - DCHECK(icon); - return gfx::Image(gfx::CreateVectorIcon(*icon, image_width, button_color)); -} - -gfx::Image GetTabAlertIndicatorAffordanceImage(TabAlertState alert_state, - SkColor button_color) { - switch (alert_state) { - case TabAlertState::AUDIO_PLAYING: - return GetTabAlertIndicatorImage(TabAlertState::AUDIO_MUTING, - button_color); - case TabAlertState::AUDIO_MUTING: - return GetTabAlertIndicatorImage(TabAlertState::AUDIO_PLAYING, - button_color); - case TabAlertState::NONE: - case TabAlertState::MEDIA_RECORDING: - case TabAlertState::TAB_CAPTURING: - case TabAlertState::BLUETOOTH_CONNECTED: - case TabAlertState::USB_CONNECTED: - case TabAlertState::PIP_PLAYING: - case TabAlertState::DESKTOP_CAPTURING: - return GetTabAlertIndicatorImage(alert_state, button_color); - } - NOTREACHED(); - return GetTabAlertIndicatorImage(alert_state, button_color); -} - -std::unique_ptr<gfx::Animation> CreateTabAlertIndicatorFadeAnimation( - TabAlertState alert_state) { - if (alert_state == TabAlertState::MEDIA_RECORDING || - alert_state == TabAlertState::TAB_CAPTURING || - alert_state == TabAlertState::DESKTOP_CAPTURING) { - return TabRecordingIndicatorAnimation::Create(); - } - - // Note: While it seems silly to use a one-part MultiAnimation, it's the only - // gfx::Animation implementation that lets us control the frame interval. - gfx::MultiAnimation::Parts parts; - const bool is_for_fade_in = (alert_state != TabAlertState::NONE); - parts.push_back(gfx::MultiAnimation::Part( - is_for_fade_in ? kIndicatorFadeInDurationMs : kIndicatorFadeOutDurationMs, - gfx::Tween::EASE_IN)); - const base::TimeDelta interval = - base::TimeDelta::FromMilliseconds(kIndicatorFrameIntervalMs); - std::unique_ptr<gfx::MultiAnimation> animation( - new gfx::MultiAnimation(parts, interval)); - animation->set_continuous(false); - return std::move(animation); -} - -base::string16 AssembleTabTooltipText(const base::string16& title, - TabAlertState alert_state) { - if (alert_state == TabAlertState::NONE) - return title; - - base::string16 result = title; - if (!result.empty()) - result.append(1, '\n'); - switch (alert_state) { - case TabAlertState::AUDIO_PLAYING: - result.append( - l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_ALERT_STATE_AUDIO_PLAYING)); - break; - case TabAlertState::AUDIO_MUTING: - result.append( - l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_ALERT_STATE_AUDIO_MUTING)); - break; - case TabAlertState::MEDIA_RECORDING: - result.append(l10n_util::GetStringUTF16( - IDS_TOOLTIP_TAB_ALERT_STATE_MEDIA_RECORDING)); - break; - case TabAlertState::TAB_CAPTURING: - result.append( - l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_ALERT_STATE_TAB_CAPTURING)); - break; - case TabAlertState::BLUETOOTH_CONNECTED: - result.append(l10n_util::GetStringUTF16( - IDS_TOOLTIP_TAB_ALERT_STATE_BLUETOOTH_CONNECTED)); - break; - case TabAlertState::USB_CONNECTED: - result.append( - l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_ALERT_STATE_USB_CONNECTED)); - break; - case TabAlertState::PIP_PLAYING: - result.append( - l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_ALERT_STATE_PIP_PLAYING)); - break; - case TabAlertState::DESKTOP_CAPTURING: - result.append(l10n_util::GetStringUTF16( - IDS_TOOLTIP_TAB_ALERT_STATE_DESKTOP_CAPTURING)); - break; - case TabAlertState::NONE: - NOTREACHED(); - break; - } - return result; -} - -base::string16 AssembleTabAccessibilityLabel(const base::string16& title, - bool is_crashed, - bool is_network_error, - TabAlertState alert_state) { - // Tab has crashed. - if (is_crashed) - return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_CRASHED_FORMAT, title); - - // Network error interstitial. - if (is_network_error) { - return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_NETWORK_ERROR_FORMAT, - title); - } - - // Alert tab states. - switch (alert_state) { - case TabAlertState::AUDIO_PLAYING: - return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_AUDIO_PLAYING_FORMAT, - title); - case TabAlertState::USB_CONNECTED: - return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_USB_CONNECTED_FORMAT, - title); - case TabAlertState::BLUETOOTH_CONNECTED: - return l10n_util::GetStringFUTF16( - IDS_TAB_AX_LABEL_BLUETOOTH_CONNECTED_FORMAT, title); - case TabAlertState::MEDIA_RECORDING: - return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_MEDIA_RECORDING_FORMAT, - title); - case TabAlertState::AUDIO_MUTING: - return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_AUDIO_MUTING_FORMAT, - title); - case TabAlertState::TAB_CAPTURING: - return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_TAB_CAPTURING_FORMAT, - title); - case TabAlertState::PIP_PLAYING: - return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_PIP_PLAYING_FORMAT, - title); - - case TabAlertState::DESKTOP_CAPTURING: - return l10n_util::GetStringFUTF16( - IDS_TAB_AX_LABEL_DESKTOP_CAPTURING_FORMAT, title); - case TabAlertState::NONE: - return title; - } - - NOTREACHED(); - return base::string16(); -} - -bool AreExperimentalMuteControlsEnabled() { - return base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableTabAudioMuting); -} - bool CanToggleAudioMute(content::WebContents* contents) { - switch (GetTabAlertStateForContents(contents)) { + switch (chrome::GetTabAlertStateForContents(contents)) { case TabAlertState::NONE: case TabAlertState::AUDIO_PLAYING: case TabAlertState::AUDIO_MUTING: @@ -427,26 +107,15 @@ return metadata->reason; } -const std::string& GetExtensionIdForMutedTab(content::WebContents* contents) { - DCHECK_EQ(GetTabAudioMutedReason(contents) != TabMutedReason::EXTENSION, - LastMuteMetadata::FromWebContents(contents)->extension_id.empty()); - return LastMuteMetadata::FromWebContents(contents)->extension_id; -} - -TabMutedResult SetTabAudioMuted(content::WebContents* contents, - bool mute, - TabMutedReason reason, - const std::string& extension_id) { +bool SetTabAudioMuted(content::WebContents* contents, + bool mute, + TabMutedReason reason, + const std::string& extension_id) { DCHECK(contents); DCHECK(TabMutedReason::NONE != reason); - if (reason == TabMutedReason::AUDIO_INDICATOR && - !AreExperimentalMuteControlsEnabled()) { - return TabMutedResult::FAIL_NOT_ENABLED; - } - if (!chrome::CanToggleAudioMute(contents)) - return TabMutedResult::FAIL_TABCAPTURE; + return false; contents->SetAudioMuted(mute); @@ -461,18 +130,7 @@ metadata->extension_id.clear(); } - return TabMutedResult::SUCCESS; -} - -void UnmuteIfMutedByExtension(content::WebContents* contents, - const std::string& extension_id) { - LastMuteMetadata::CreateForWebContents(contents); // Ensures metadata exists. - LastMuteMetadata* const metadata = - LastMuteMetadata::FromWebContents(contents); - if (metadata->reason == TabMutedReason::EXTENSION && - metadata->extension_id == extension_id) { - SetTabAudioMuted(contents, false, TabMutedReason::EXTENSION, extension_id); - } + return true; } bool AreAllTabsMuted(const TabStripModel& tab_strip, @@ -485,39 +143,9 @@ return true; } -void SetSitesMuted(const TabStripModel& tab_strip, - const std::vector<int>& indices, - const bool mute) { - for (int tab_index : indices) { - content::WebContents* web_contents = tab_strip.GetWebContentsAt(tab_index); - GURL url = web_contents->GetLastCommittedURL(); - if (url.SchemeIs(content::kChromeUIScheme)) { - // chrome:// URLs don't have content settings but can be muted, so just - // mute the WebContents. - SetTabAudioMuted(web_contents, mute, - TabMutedReason::CONTENT_SETTING_CHROME, std::string()); - } else { - Profile* profile = - Profile::FromBrowserContext(web_contents->GetBrowserContext()); - HostContentSettingsMap* settings = - HostContentSettingsMapFactory::GetForProfile(profile); - ContentSetting setting = - mute ? CONTENT_SETTING_BLOCK : CONTENT_SETTING_ALLOW; - if (setting == settings->GetDefaultContentSetting( - CONTENT_SETTINGS_TYPE_SOUND, nullptr)) { - setting = CONTENT_SETTING_DEFAULT; - } - settings->SetContentSettingDefaultScope( - url, url, CONTENT_SETTINGS_TYPE_SOUND, std::string(), setting); - } - } -} - bool IsSiteMuted(const TabStripModel& tab_strip, const int index) { content::WebContents* web_contents = tab_strip.GetWebContentsAt(index); - // TODO(steimel): Why was this not a problem for AreAllTabsMuted? Is this - // going to be a problem for SetSitesMuted? // Prevent crashes with null WebContents (https://crbug.com/797647). if (!web_contents) return false;
diff --git a/chrome/browser/ui/tabs/tab_utils.h b/chrome/browser/ui/tabs/tab_utils.h index e69e8b0d..d9b7301 100644 --- a/chrome/browser/ui/tabs/tab_utils.h +++ b/chrome/browser/ui/tabs/tab_utils.h
@@ -9,7 +9,6 @@ #include <string> #include <vector> -#include "base/strings/string16.h" #include "content/public/browser/web_contents_user_data.h" #include "third_party/skia/include/core/SkColor.h" @@ -19,11 +18,6 @@ class WebContents; } // namespace content -namespace gfx { -class Animation; -class Image; -} // namespace gfx - // Alert state for a tab. In reality, more than one of these may apply. See // comments for GetTabAlertStateForContents() below. enum class TabAlertState { @@ -41,127 +35,49 @@ enum class TabMutedReason { NONE, // The tab has never been muted or unmuted. CONTEXT_MENU, // Mute/Unmute chosen from tab context menu. - AUDIO_INDICATOR, // Mute toggled via tab-strip audio icon. MEDIA_CAPTURE, // Media recording/capture was started. EXTENSION, // Mute state changed via extension API. CONTENT_SETTING, // The sound content setting was set to BLOCK. CONTENT_SETTING_CHROME, // Mute toggled on chrome:// URL. }; -enum class TabMutedResult { - SUCCESS, - FAIL_NOT_ENABLED, - FAIL_TABCAPTURE, +struct LastMuteMetadata + : public content::WebContentsUserData<LastMuteMetadata> { + TabMutedReason reason = TabMutedReason::NONE; + std::string extension_id; // Only valid when |reason| is EXTENSION. + + private: + explicit LastMuteMetadata(content::WebContents* contents) {} + friend class content::WebContentsUserData<LastMuteMetadata>; }; namespace chrome { -// Logic to determine which components (i.e., close button, favicon, and alert -// indicator) of a tab should be shown, given current state. |capacity| -// specifies how many components can be shown, given available tab width. -// -// Precedence rules for deciding what to show when capacity is insufficient to -// show everything: -// -// Active tab: Always show the close button, then the alert indicator, then -// the favicon. -// Inactive tab: Alert indicator, then the favicon, then the close button. -// Pinned tab: Show only the alert indicator, or only the favicon -// (TabAlertState::NONE). Never show the close button. -bool ShouldTabShowFavicon(int capacity, - bool is_pinned_tab, - bool is_active_tab, - bool has_favicon, - TabAlertState alert_state); -bool ShouldTabShowAlertIndicator(int capacity, - bool is_pinned_tab, - bool is_active_tab, - bool has_favicon, - TabAlertState alert_state); -bool ShouldTabShowCloseButton(int capacity, - bool is_pinned_tab, - bool is_active_tab); - // Returns the alert state to be shown by the tab's alert indicator. When // multiple states apply (e.g., tab capture with audio playback), the one most // relevant to user privacy concerns is selected. TabAlertState GetTabAlertStateForContents(content::WebContents* contents); -// Returns a cached image, to be shown by the alert indicator for the given -// |alert_state|. Uses the global ui::ResourceBundle shared instance. -gfx::Image GetTabAlertIndicatorImage(TabAlertState alert_state, - SkColor button_color); - -// Returns the cached image, to be shown by the alert indicator button for mouse -// hover/pressed, when the indicator is in the given |alert_state|. Uses the -// global ui::ResourceBundle shared instance. -gfx::Image GetTabAlertIndicatorAffordanceImage(TabAlertState alert_state, - SkColor button_color); - -// Returns a non-continuous Animation that performs a fade-in or fade-out -// appropriate for the given |next_alert_state|. This is used by the tab alert -// indicator to alert the user that recording, tab capture, or audio playback -// has started/stopped. -std::unique_ptr<gfx::Animation> CreateTabAlertIndicatorFadeAnimation( - TabAlertState next_alert_state); - -// Returns the text to show in a tab's tooltip: The contents |title|, followed -// by a break, followed by a localized string describing the |alert_state|. -base::string16 AssembleTabTooltipText(const base::string16& title, - TabAlertState alert_state); - -// Returns the text to use for a tab's accessibility label: the |title|, -// followed by text describing |is_crashed|, |is_network_error|, and -// |alert_state|. -base::string16 AssembleTabAccessibilityLabel(const base::string16& title, - bool is_crashed, - bool is_network_error, - TabAlertState alert_state); - -// Returns true if experimental audio mute controls (UI or extension API) are -// enabled. Currently, toggling mute from a tab's context menu is the only -// non-experimental control method. -bool AreExperimentalMuteControlsEnabled(); - // Returns true if audio mute can be activated/deactivated for the given // |contents|. bool CanToggleAudioMute(content::WebContents* contents); -// Unmute a tab if it is currently muted at the request of the extension having -// the given |extension_id|. -void UnmuteIfMutedByExtension(content::WebContents* contents, - const std::string& extension_id); - // Sets whether all audio output from |contents| is muted, along with the // |reason| it is to be muted/unmuted (via UI or extension API). When |reason| // is TAB_MUTED_REASON_EXTENSION, |extension_id| must be provided; otherwise, it -// is ignored. -// -// If the |reason| is an experimental feature and the experiment is not enabled, -// this will have no effect and TAB_MUTED_RESULT_FAIL_NOT_ENABLED will be -// returned. -TabMutedResult SetTabAudioMuted(content::WebContents* contents, - bool mute, - TabMutedReason reason, - const std::string& extension_id); +// is ignored. Returns whether the tab was actually muted. +bool SetTabAudioMuted(content::WebContents* contents, + bool mute, + TabMutedReason reason, + const std::string& extension_id); // Returns the last reason a tab's mute state was changed. TabMutedReason GetTabAudioMutedReason(content::WebContents* contents); -// If the last reason a tab's mute state was changed was due to use of the -// extension API, this returns the extension's ID string. Otherwise, the empty -// string is returned. -const std::string& GetExtensionIdForMutedTab(content::WebContents* contents); - // Returns true if the tabs at the |indices| in |tab_strip| are all muted. bool AreAllTabsMuted(const TabStripModel& tab_strip, const std::vector<int>& indices); -// Sets the sound content setting for each site at the |indices| in |tab_strip|. -void SetSitesMuted(const TabStripModel& tab_strip, - const std::vector<int>& indices, - const bool mute); - // Returns true if the site at |index| in |tab_strip| is muted. bool IsSiteMuted(const TabStripModel& tab_strip, const int index);
diff --git a/chrome/browser/ui/toolbar/toolbar_model_unittest.cc b/chrome/browser/ui/toolbar/toolbar_model_unittest.cc index 318ede5e..67b1086 100644 --- a/chrome/browser/ui/toolbar/toolbar_model_unittest.cc +++ b/chrome/browser/ui/toolbar/toolbar_model_unittest.cc
@@ -10,10 +10,12 @@ #include "base/macros.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/browser_with_test_window_test.h" +#include "components/toolbar/toolbar_field_trial.h" #include "components/toolbar/toolbar_model.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/ssl_status.h" @@ -189,6 +191,12 @@ // Test URL display. TEST_F(ToolbarModelTest, ShouldDisplayURL) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {toolbar::features::kHideSteadyStateUrlScheme, + toolbar::features::kHideSteadyStateUrlTrivialSubdomains}, + {}); + AddTab(browser(), GURL(url::kAboutBlankURL)); for (const TestItem& test_item : test_items) { @@ -199,6 +207,56 @@ } } +// Tests every combination of Steady State Elision flags. +TEST_F(ToolbarModelTest, SteadyStateElisionsFlags) { + AddTab(browser(), GURL(url::kAboutBlankURL)); + + // Hide Scheme and Hide Trivial Subdomains both Disabled. + { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {}, {toolbar::features::kHideSteadyStateUrlScheme, + toolbar::features::kHideSteadyStateUrlTrivialSubdomains}); + NavigateAndCheckText(GURL("https://www.google.com/"), + base::ASCIIToUTF16("https://www.google.com"), + base::ASCIIToUTF16("https://www.google.com")); + } + + // Only Hide Scheme Enabled. + { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {toolbar::features::kHideSteadyStateUrlScheme}, + {toolbar::features::kHideSteadyStateUrlTrivialSubdomains}); + NavigateAndCheckText(GURL("https://www.google.com/"), + base::ASCIIToUTF16("https://www.google.com"), + base::ASCIIToUTF16("www.google.com")); + } + + // Only Hide Trivial Subdomains Enabled. + { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {toolbar::features::kHideSteadyStateUrlTrivialSubdomains}, + {toolbar::features::kHideSteadyStateUrlScheme}); + NavigateAndCheckText(GURL("https://www.google.com/"), + base::ASCIIToUTF16("https://www.google.com"), + base::ASCIIToUTF16("https://google.com")); + } + + // Hide Scheme and Hide Trivial Subdomains both Enabled. + { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {toolbar::features::kHideSteadyStateUrlScheme, + toolbar::features::kHideSteadyStateUrlTrivialSubdomains}, + {}); + NavigateAndCheckText(GURL("https://www.google.com/"), + base::ASCIIToUTF16("https://www.google.com"), + base::ASCIIToUTF16("google.com")); + } +} + TEST_F(ToolbarModelTest, ShouldElideLongURLs) { AddTab(browser(), GURL(url::kAboutBlankURL)); const std::string long_text(content::kMaxURLDisplayChars + 1024, '0');
diff --git a/chrome/browser/ui/view_ids.h b/chrome/browser/ui/view_ids.h index 823099e..234cb55 100644 --- a/chrome/browser/ui/view_ids.h +++ b/chrome/browser/ui/view_ids.h
@@ -22,8 +22,6 @@ VIEW_ID_CLOSE_BUTTON, VIEW_ID_WINDOW_ICON, VIEW_ID_WINDOW_TITLE, - VIEW_ID_PROFILE_INDICATOR_ICON, - VIEW_ID_AVATAR_BUTTON, VIEW_ID_HOSTED_APP_BUTTON_CONTAINER, // Tabs within a window/tab strip, counting from the left.
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.cc b/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.cc index da87d21..8c146411 100644 --- a/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.cc
@@ -108,6 +108,8 @@ kMigrationBubbleGooglePayLogoHeight); views::ImageView* icon_view = new views::ImageView(); icon_view->SetImage(&image); + icon_view->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_AUTOFILL_GOOGLE_PAY_LOGO_ACCESSIBLE_NAME)); title_container->AddChildView(icon_view); GetBubbleFrameView()->SetTitleView(std::move(title_container)); }
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc b/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc index 2cd1517..94a4758 100644 --- a/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc +++ b/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc
@@ -221,6 +221,8 @@ std::unique_ptr<views::ImageView> image = std::make_unique<views::ImageView>(); image->SetImage(rb.GetImageSkiaNamed(GetHeaderImageId())); + image->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_AUTOFILL_GOOGLE_PAY_LOGO_ACCESSIBLE_NAME)); image_container->AddChildView(image.release()); main_container->AddChildView(image_container.release());
diff --git a/chrome/browser/ui/views/autofill/migratable_card_view.cc b/chrome/browser/ui/views/autofill/migratable_card_view.cc index c8acad4d..338af4ea 100644 --- a/chrome/browser/ui/views/autofill/migratable_card_view.cc +++ b/chrome/browser/ui/views/autofill/migratable_card_view.cc
@@ -84,10 +84,14 @@ checkbox_ = new views::Checkbox(base::string16(), listener); checkbox_->SetChecked(true); checkbox_->set_tag(card_index); - checkbox_->SetVisible(true); // TODO(crbug/867194): Currently the ink drop animation circle is cut by the // border of scroll bar view. Find a way to adjust the format. checkbox_->SetInkDropMode(views::InkDropHostView::InkDropMode::OFF); + std::unique_ptr<views::Label> card_description = + std::make_unique<views::Label>( + migratable_credit_card.credit_card().NetworkAndLastFourDigits(), + views::style::CONTEXT_LABEL); + checkbox_->SetAssociatedLabel(card_description.get()); AddChildView(checkbox_); constexpr int kMigrationResultImageSize = 16; @@ -116,12 +120,10 @@ rb.GetImageNamed(CreditCard::IconResourceId( migratable_credit_card.credit_card().network())) .AsImageSkia()); + card_image->SetAccessibleName( + migratable_credit_card.credit_card().NetworkForDisplay()); card_network_and_last_four_digits->AddChildView(card_image.release()); - std::unique_ptr<views::Label> card_description = - std::make_unique<views::Label>( - migratable_credit_card.credit_card().NetworkAndLastFourDigits(), - views::style::CONTEXT_LABEL); card_network_and_last_four_digits->AddChildView(card_description.release()); std::unique_ptr<views::Label> card_expiration =
diff --git a/chrome/browser/ui/views/feature_promos/bookmark_bar_promo_bubble_view.cc b/chrome/browser/ui/views/feature_promos/bookmark_bar_promo_bubble_view.cc index 2a8e0c1..791259e3 100644 --- a/chrome/browser/ui/views/feature_promos/bookmark_bar_promo_bubble_view.cc +++ b/chrome/browser/ui/views/feature_promos/bookmark_bar_promo_bubble_view.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/grit/generated_resources.h" #include "components/bookmarks/browser/bookmark_node.h" +#include "ui/views/controls/button/label_button.h" // BookmarkBarViewObserverImpl is used to observe when the bookmark bar has // finished animating, then show the bookmark bubble. It's important to wait
diff --git a/chrome/browser/ui/views/frame/avatar_button_manager.cc b/chrome/browser/ui/views/frame/avatar_button_manager.cc deleted file mode 100644 index 93dab04..0000000 --- a/chrome/browser/ui/views/frame/avatar_button_manager.cc +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/frame/avatar_button_manager.h" - -#if !defined(OS_CHROMEOS) -#include "chrome/browser/browser_process.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/ui/view_ids.h" -#include "chrome/browser/ui/views/frame/browser_frame.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "ui/base/material_design/material_design_controller.h" -#endif // !defined(OS_CHROMEOS) - -AvatarButtonManager::AvatarButtonManager(BrowserNonClientFrameView* frame_view) -#if !defined(OS_CHROMEOS) - : frame_view_(frame_view) -#endif // defined(OS_CHROMEOS) -{ -} - -void AvatarButtonManager::Update(AvatarButtonStyle style) { -#if defined(OS_CHROMEOS) - DCHECK_EQ(style, AvatarButtonStyle::NONE); -#else - // Note: This code is being replaced by a toolbar button, see ToolbarView. - if (ui::MaterialDesignController::IsNewerMaterialUi()) - return; - BrowserView* browser_view = frame_view_->browser_view(); - BrowserFrame* frame = frame_view_->frame(); - Profile* profile = browser_view->browser()->profile(); - - // This should never be called in incognito mode. - DCHECK(browser_view->IsRegularOrGuestSession()); - ProfileAttributesEntry* unused; - if (style != AvatarButtonStyle::NONE && - ((browser_view->IsBrowserTypeNormal() && - // Tests may not have a profile manager. - g_browser_process->profile_manager() && - g_browser_process->profile_manager() - ->GetProfileAttributesStorage() - .GetProfileAttributesWithPath(profile->GetPath(), &unused)) || - // Desktop guest shows the avatar button. - browser_view->IsIncognito())) { - if (!avatar_button_) { - avatar_button_ = new AvatarButton(this, style, profile, this); - avatar_button_->set_id(VIEW_ID_AVATAR_BUTTON); - frame_view_->AddChildView(avatar_button_); - frame->GetRootView()->Layout(); - } - } else if (avatar_button_) { - delete avatar_button_; - avatar_button_ = nullptr; - frame->GetRootView()->Layout(); - } -#endif // defined(OS_CHROMEOS) -} - -void AvatarButtonManager::OnMenuButtonClicked(views::MenuButton* sender, - const gfx::Point& point, - const ui::Event* event) { -#if defined(OS_CHROMEOS) - NOTREACHED(); -#else - DCHECK(!ui::MaterialDesignController::IsNewerMaterialUi()); - DCHECK_EQ(avatar_button_, sender); - BrowserWindow::AvatarBubbleMode mode = - BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT; - if ((event->IsMouseEvent() && event->AsMouseEvent()->IsRightMouseButton()) || - (event->type() == ui::ET_GESTURE_LONG_PRESS)) { - return; - } - frame_view_->browser_view()->ShowAvatarBubbleFromAvatarButton( - mode, signin::ManageAccountsParams(), - signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN, false); - avatar_button_->OnAvatarButtonPressed(event); -#endif // defined(OS_CHROMEOS) -}
diff --git a/chrome/browser/ui/views/frame/avatar_button_manager.h b/chrome/browser/ui/views/frame/avatar_button_manager.h deleted file mode 100644 index bc7c336d..0000000 --- a/chrome/browser/ui/views/frame/avatar_button_manager.h +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_AVATAR_BUTTON_MANAGER_H_ -#define CHROME_BROWSER_UI_VIEWS_FRAME_AVATAR_BUTTON_MANAGER_H_ - -#include "chrome/browser/ui/views/profiles/avatar_button.h" -#include "chrome/browser/ui/views/profiles/avatar_button_style.h" -#include "ui/views/controls/button/menu_button_listener.h" -#include "ui/views/features.h" - -#if BUILDFLAG(ENABLE_NATIVE_WINDOW_NAV_BUTTONS) -namespace views { -class NavButtonProvider; -} // namespace views -#endif - -class BrowserNonClientFrameView; - -// Manages an avatar button displayed in a browser frame. The button displays -// the name of the active or guest profile, and may be null. -class AvatarButtonManager : public views::MenuButtonListener { - public: - explicit AvatarButtonManager(BrowserNonClientFrameView* frame_view); - - // Adds or removes the avatar button from the frame, based on the BrowserView - // properties. - void Update(AvatarButtonStyle style); - - AvatarButton* avatar_button() const { -#if defined(OS_CHROMEOS) - return nullptr; -#else - return avatar_button_; -#endif // defined(OS_CHROMEOS) - } - - // views::MenuButtonListener: - void OnMenuButtonClicked(views::MenuButton* source, - const gfx::Point& point, - const ui::Event* event) override; - -#if BUILDFLAG(ENABLE_NATIVE_WINDOW_NAV_BUTTONS) - views::NavButtonProvider* get_nav_button_provider() { - return nav_button_provider_; - } - void set_nav_button_provider(views::NavButtonProvider* nav_button_provider) { - nav_button_provider_ = nav_button_provider; - } -#endif - - private: -#if !defined(OS_CHROMEOS) - BrowserNonClientFrameView* frame_view_; // Weak. Owns |this|. - - // Menu button that displays the name of the active or guest profile. - // May be null and will not be displayed for off the record profiles. - AvatarButton* avatar_button_ = nullptr; // Owned by views hierarchy. -#endif // !defined(OS_CHROMEOS) - -#if BUILDFLAG(ENABLE_NATIVE_WINDOW_NAV_BUTTONS) - views::NavButtonProvider* nav_button_provider_ = nullptr; -#endif - - DISALLOW_COPY_AND_ASSIGN(AvatarButtonManager); -}; - -#endif // CHROME_BROWSER_UI_VIEWS_FRAME_AVATAR_BUTTON_MANAGER_H_
diff --git a/chrome/browser/ui/views/frame/browser_frame.cc b/chrome/browser/ui/views/frame/browser_frame.cc index d06e2cbb..ab7ba4e5 100644 --- a/chrome/browser/ui/views/frame/browser_frame.cc +++ b/chrome/browser/ui/views/frame/browser_frame.cc
@@ -26,6 +26,7 @@ #include "chrome/browser/ui/views/frame/top_container_view.h" #include "chrome/common/chrome_switches.h" #include "ui/base/hit_test.h" +#include "ui/base/material_design/material_design_controller.h" #include "ui/events/event_handler.h" #include "ui/gfx/font_list.h" #include "ui/native_theme/native_theme_dark_aura.h" @@ -56,10 +57,10 @@ set_is_secondary_widget(false); // Don't focus anything on creation, selecting a tab will set the focus. set_focus_on_creation(false); + md_observer_.Add(ui::MaterialDesignController::GetInstance()); } -BrowserFrame::~BrowserFrame() { -} +BrowserFrame::~BrowserFrame() {} void BrowserFrame::InitBrowserFrame() { native_browser_frame_ = @@ -241,12 +242,12 @@ return menu_model_builder_->menu_model(); } -views::Button* BrowserFrame::GetNewAvatarMenuButton() { - // Note: This profile switcher is being replaced with a toolbar menu button. - // See ToolbarView. - return browser_frame_view_->GetProfileSwitcherButton(); -} - void BrowserFrame::OnMenuClosed() { menu_runner_.reset(); } + +void BrowserFrame::OnMdModeChanged() { + client_view()->InvalidateLayout(); + non_client_view()->InvalidateLayout(); + GetRootView()->Layout(); +}
diff --git a/chrome/browser/ui/views/frame/browser_frame.h b/chrome/browser/ui/views/frame/browser_frame.h index 26c6a6cf..ec2b989 100644 --- a/chrome/browser/ui/views/frame/browser_frame.h +++ b/chrome/browser/ui/views/frame/browser_frame.h
@@ -8,9 +8,11 @@ #include "base/compiler_specific.h" #include "base/logging.h" #include "base/macros.h" +#include "base/scoped_observer.h" #include "build/build_config.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "content/public/browser/keyboard_event_processing_result.h" +#include "ui/base/material_design/material_design_controller_observer.h" #include "ui/views/context_menu_controller.h" #include "ui/views/widget/widget.h" @@ -34,15 +36,14 @@ } namespace views { -class Button; class MenuRunner; class View; } // This is a virtual interface that allows system specific browser frames. -class BrowserFrame - : public views::Widget, - public views::ContextMenuController { +class BrowserFrame : public views::Widget, + public views::ContextMenuController, + public ui::MaterialDesignControllerObserver { public: explicit BrowserFrame(BrowserView* browser_view); ~BrowserFrame() override; @@ -98,7 +99,7 @@ // Called when BrowserView creates all it's child views. void OnBrowserViewInitViewsComplete(); - // Overridden from views::Widget: + // views::Widget: views::internal::RootView* CreateRootView() override; views::NonClientFrameView* CreateNonClientFrameView() override; bool GetAccelerator(int command_id, @@ -108,13 +109,11 @@ void OnNativeWidgetWorkspaceChanged() override; void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override; - // Overridden from views::ContextMenuController: + // views::ContextMenuController: void ShowContextMenuForView(views::View* source, const gfx::Point& p, ui::MenuSourceType source_type) override; - views::Button* GetNewAvatarMenuButton(); - // Returns the menu model. BrowserFrame owns the returned model. // Note that in multi user mode this will upon each call create a new model. ui::MenuModel* GetSystemMenuModel(); @@ -123,6 +122,10 @@ return native_browser_frame_; } + protected: + // ui::MaterialDesignControllerObserver: + void OnMdModeChanged() override; + private: // Callback for MenuRunner. void OnMenuClosed(); @@ -148,6 +151,10 @@ std::unique_ptr<ui::EventHandler> browser_command_handler_; + ScopedObserver<ui::MaterialDesignController, + ui::MaterialDesignControllerObserver> + md_observer_{this}; + DISALLOW_COPY_AND_ASSIGN(BrowserFrame); };
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc index d2834b5c7..a3648bb 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -5,12 +5,10 @@ #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "base/metrics/histogram_macros.h" -#include "build/build_config.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/avatar_menu.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_attributes_entry.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/extensions/hosted_app_browser_controller.h" @@ -20,7 +18,6 @@ #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/common/chrome_features.h" #include "chrome/grit/theme_resources.h" -#include "components/signin/core/browser/profile_management_switches.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/material_design/material_design_controller.h" #include "ui/base/theme_provider.h" @@ -31,11 +28,6 @@ #include "ui/gfx/scoped_canvas.h" #include "ui/views/background.h" -#if defined(OS_CHROMEOS) -#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" -#include "chrome/browser/ui/ash/session_util.h" -#endif // defined(OS_CHROMEOS) - #if defined(OS_WIN) #include "chrome/browser/ui/views/frame/taskbar_decorator_win.h" #endif @@ -49,8 +41,6 @@ BrowserView* browser_view) : frame_(frame), browser_view_(browser_view), - profile_switcher_(this), - profile_indicator_icon_(nullptr), tab_strip_observer_(this) { // The profile manager may by null in tests. if (g_browser_process->profile_manager()) { @@ -69,11 +59,6 @@ } // static -int BrowserNonClientFrameView::GetAvatarIconPadding() { - return MD::IsNewerMaterialUi() ? 8 : 4; -} - -// static int BrowserNonClientFrameView::GetTabstripPadding() { // In Refresh, the apparent padding around the tabstrip is contained within // the tabs and/or new tab button. @@ -158,12 +143,6 @@ HasVisibleBackgroundTabShapes(kInactive); } -gfx::ImageSkia BrowserNonClientFrameView::GetIncognitoAvatarIcon() const { - const SkColor icon_color = color_utils::PickContrastingColor( - SK_ColorWHITE, gfx::kChromeIconGrey, GetFrameColor()); - return gfx::CreateVectorIcon(kIncognitoIcon, icon_color); -} - SkColor BrowserNonClientFrameView::GetFrameColor( ActiveState active_state) const { ThemeProperties::OverwritableByUserThemeProperty color_id; @@ -285,27 +264,12 @@ return id; } -views::Button* BrowserNonClientFrameView::GetProfileSwitcherButton() const { - return profile_switcher_.avatar_button(); -} - void BrowserNonClientFrameView::UpdateClientArea() {} void BrowserNonClientFrameView::UpdateMinimumSize() {} int BrowserNonClientFrameView::GetTabStripLeftInset() const { - int left_inset = GetTabstripPadding(); - if (profile_indicator_icon()) - left_inset += GetAvatarIconPadding() + GetIncognitoAvatarIcon().width(); - return left_inset; -} - -void BrowserNonClientFrameView::ChildPreferredSizeChanged(views::View* child) { - if (child == GetProfileSwitcherButton()) { - // Perform a re-layout if the avatar button has changed, since that can - // affect the size of the tabs. - frame_->GetRootView()->Layout(); - } + return GetTabstripPadding(); } void BrowserNonClientFrameView::VisibilityChanged(views::View* starting_from, @@ -391,84 +355,12 @@ : gfx::ImageSkia(); } -void BrowserNonClientFrameView::UpdateProfileIcons() { - const AvatarButtonStyle avatar_button_style = GetAvatarButtonStyle(); - if (avatar_button_style != AvatarButtonStyle::NONE && - browser_view_->IsRegularOrGuestSession()) { - // Platform supports a profile switcher that will be shown. Skip the rest. - profile_switcher_.Update(avatar_button_style); - return; - } - - if (!ShouldShowProfileIndicatorIcon()) { - if (profile_indicator_icon_) { - delete profile_indicator_icon_; - profile_indicator_icon_ = nullptr; - frame_->GetRootView()->Layout(); - } - return; - } - - if (!profile_indicator_icon_) { - profile_indicator_icon_ = new ProfileIndicatorIcon(); - profile_indicator_icon_->set_id(VIEW_ID_PROFILE_INDICATOR_ICON); - AddChildView(profile_indicator_icon_); - // Invalidate here because adding a child does not invalidate the layout. - InvalidateLayout(); - frame_->GetRootView()->Layout(); - } - - gfx::Image icon; - Profile* profile = browser_view_->browser()->profile(); - const bool is_incognito = - profile->GetProfileType() == Profile::INCOGNITO_PROFILE; - if (is_incognito) { - icon = gfx::Image(GetIncognitoAvatarIcon()); - profile_indicator_icon_->set_stroke_color(SK_ColorTRANSPARENT); - } else { -#if defined(OS_CHROMEOS) - icon = gfx::Image(GetAvatarImageForContext(profile)); - // Draw a stroke around the profile icon only for the avatar. - profile_indicator_icon_->set_stroke_color(GetToolbarTopSeparatorColor()); -#else - NOTREACHED(); -#endif - } - - profile_indicator_icon_->SetIcon(icon); -} - -void BrowserNonClientFrameView::LayoutIncognitoButton() { - DCHECK(profile_indicator_icon()); -#if !defined(OS_CHROMEOS) - // ChromeOS shows avatar on V1 app. - DCHECK(browser_view_->IsTabStripVisible()); -#endif - gfx::ImageSkia incognito_icon = GetIncognitoAvatarIcon(); - int avatar_bottom = GetTopInset(false) + browser_view_->GetTabStripHeight() - - GetAvatarIconPadding(); - int avatar_y = avatar_bottom - incognito_icon.height(); - int avatar_height = incognito_icon.height(); - gfx::Rect avatar_bounds(GetAvatarIconPadding(), avatar_y, - incognito_icon.width(), avatar_height); - - profile_indicator_icon()->SetBoundsRect(avatar_bounds); - profile_indicator_icon()->SetVisible(true); -} - -void BrowserNonClientFrameView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { - if (details.is_add && details.child == this) - UpdateProfileIcons(); -} - void BrowserNonClientFrameView::ActivationChanged(bool active) { // On Windows, while deactivating the widget, this is called before the - // active HWND has actually been changed. Since we want the avatar state to - // reflect that the window is inactive, we force NonClientFrameView to see the + // active HWND has actually been changed. Since we want the state to reflect + // that the window is inactive, we force NonClientFrameView to see the // "correct" state as an override. set_active_state_override(&active); - UpdateProfileIcons(); if (MD::IsRefreshUi()) { // Single-tab mode's availability depends on activation, but even if it's @@ -541,8 +433,7 @@ } // We claim |rect| because it is above the bottom of the tabstrip, but - // not in the tabstrip itself. In particular, the avatar label/button is left - // of the tabstrip and the window controls are right of the tabstrip. + // not in the tabstrip itself. return !should_leave_to_top_container; } @@ -560,7 +451,6 @@ void BrowserNonClientFrameView::OnProfileAvatarChanged( const base::FilePath& profile_path) { UpdateTaskbarDecoration(); - UpdateProfileIcons(); } void BrowserNonClientFrameView::OnProfileHighResAvatarLoaded( @@ -594,8 +484,7 @@ return; } - // For popups and panels which don't have the avatar button, we still - // need to draw the taskbar decoration. Even though we have an icon on the + // We need to draw the taskbar decoration. Even though we have an icon on the // window's relaunch details, we draw over it because the user may have // pinned the badge-less Chrome shortcut which will cause Windows to ignore // the relaunch details. @@ -622,38 +511,6 @@ #endif } -bool BrowserNonClientFrameView::ShouldShowProfileIndicatorIcon() const { -#if !defined(OS_CHROMEOS) - // Outside ChromeOS, in Material Refresh, we use a toolbar button for all - // profile/incognito-related purposes. ChromeOS uses it for teleportation (see - // below). - if (MD::IsRefreshUi()) - return false; -#endif // !defined(OS_CHROMEOS) - - Browser* browser = browser_view_->browser(); - Profile* profile = browser->profile(); - const bool is_incognito = - profile->GetProfileType() == Profile::INCOGNITO_PROFILE; - - // In newer material UIs we only show the avatar icon for the teleported - // browser windows between multi-user sessions (Chrome OS only). Note that you - // can't teleport an incognito window. - if (is_incognito && MD::IsNewerMaterialUi()) - return false; - -#if defined(OS_CHROMEOS) - if (!browser->is_type_tabbed() && !browser->is_app()) - return false; - - if (!is_incognito && !MultiUserWindowManager::ShouldShowAvatar( - browser_view_->GetNativeWindow())) { - return false; - } -#endif // defined(OS_CHROMEOS) - return true; -} - SkColor BrowserNonClientFrameView::GetThemeOrDefaultColor(int color_id) const { // During shutdown, there may no longer be a widget, and thus no theme // provider.
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h index 91bb9dd3..598a2dff 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -6,9 +6,8 @@ #define CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_H_ #include "base/scoped_observer.h" +#include "build/build_config.h" #include "chrome/browser/profiles/profile_attributes_storage.h" -#include "chrome/browser/ui/views/frame/avatar_button_manager.h" -#include "chrome/browser/ui/views/profiles/profile_indicator_icon.h" #include "chrome/browser/ui/views/tabs/tab_strip_observer.h" #include "chrome/browser/ui/views/tabs/tab_strip_types.h" #include "ui/views/window/non_client_view.h" @@ -37,20 +36,12 @@ BrowserNonClientFrameView(BrowserFrame* frame, BrowserView* browser_view); ~BrowserNonClientFrameView() override; - // Returns the padding on the left, right, and bottom of the avatar icon. - static int GetAvatarIconPadding(); - // Returns the padding on the sides of the tabstrip. static int GetTabstripPadding(); BrowserView* browser_view() const { return browser_view_; } BrowserFrame* frame() const { return frame_; } - const views::View* profile_indicator_icon() const { - return profile_indicator_icon_; - } - views::View* profile_indicator_icon() { return profile_indicator_icon_; } - // Called when BrowserView creates all it's child views. virtual void OnBrowserViewInitViewsComplete(); @@ -104,9 +95,6 @@ // for either active or inactive windows. bool EverHasVisibleBackgroundTabShapes() const; - // Retrieves the icon to use in the frame to indicate an incognito window. - gfx::ImageSkia GetIncognitoAvatarIcon() const; - // Returns the color of the browser frame, which is also the color of the // tabstrip background. SkColor GetFrameColor(ActiveState active_state = kUseCurrent) const; @@ -136,10 +124,6 @@ // Updates the throbber. virtual void UpdateThrobber(bool running) = 0; - // Returns the profile switcher button, if this frame has any, nullptr if it - // doesn't. - views::Button* GetProfileSwitcherButton() const; - // Provided for mus. Updates the client-area of the WindowTreeHostMus. virtual void UpdateClientArea(); @@ -161,7 +145,6 @@ // views::NonClientFrameView: using views::NonClientFrameView::ShouldPaintAsActive; - void ChildPreferredSizeChanged(views::View* child) override; void VisibilityChanged(views::View* starting_from, bool is_visible) override; // TabStripObserver: @@ -185,27 +168,11 @@ gfx::ImageSkia GetFrameOverlayImage( ActiveState active_state = kUseCurrent) const; - // Returns the style of the profile switcher avatar button. - virtual AvatarButtonStyle GetAvatarButtonStyle() const = 0; - - // Updates all the profile icons as necessary (profile switcher button, or the - // icon that indicates incognito (or a teleported window in ChromeOS)). - void UpdateProfileIcons(); - - void LayoutIncognitoButton(); - // views::NonClientFrameView: void ActivationChanged(bool active) override; bool DoesIntersectRect(const views::View* target, const gfx::Rect& rect) const override; - AvatarButtonManager* profile_switcher() { return &profile_switcher_; } - - private: - // views::NonClientFrameView: - void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; - // ProfileAttributesStorage::Observer: void OnProfileAdded(const base::FilePath& profile_path) override; void OnProfileWasRemoved(const base::FilePath& profile_path, @@ -214,18 +181,16 @@ void OnProfileHighResAvatarLoaded( const base::FilePath& profile_path) override; + private: void MaybeObserveTabstrip(); // Gets a theme provider that should be non-null even before we're added to a // view hierarchy. const ui::ThemeProvider* GetThemeProviderForProfile() const; - // Draws a taskbar icon if avatars are enabled, erases it otherwise. + // Draws a taskbar icon for non-guest sessions, erases it otherwise. void UpdateTaskbarDecoration(); - // Returns true if |profile_indicator_icon_| should be shown. - bool ShouldShowProfileIndicatorIcon() const; - // Returns the color of the given |color_id| from the theme provider or the // default theme properties. SkColor GetThemeOrDefaultColor(int color_id) const; @@ -236,14 +201,6 @@ // The BrowserView hosted within this View. BrowserView* browser_view_; - // Wrapper around the in-frame profile switcher. Might not be used on all - // platforms. - AvatarButtonManager profile_switcher_; - - // On desktop, this is used to show an incognito icon. On CrOS, it's also used - // for teleported windows (in multi-profile mode). - ProfileIndicatorIcon* profile_indicator_icon_; - ScopedObserver<TabStrip, BrowserNonClientFrameView> tab_strip_observer_; DISALLOW_COPY_AND_ASSIGN(BrowserNonClientFrameView);
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index ae43dac..a9bf0ff 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/profiles/profiles_state.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" +#include "chrome/browser/ui/ash/session_util.h" #include "chrome/browser/ui/ash/tablet_mode_client.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_command_controller.h" @@ -76,6 +77,9 @@ constexpr SkColor kNormalWindowTitleTextColor = SkColorSetRGB(40, 40, 40); constexpr SkColor kIncognitoWindowTitleTextColor = SK_ColorWHITE; +// The indicator for teleported windows is 24 DIP on a side. +constexpr int kProfileIndicatorSize = 24; + bool IsV1AppBackButtonEnabled() { return base::CommandLine::ForCurrentProcess()->HasSwitch( ash::switches::kAshEnableV1AppBackButton); @@ -106,6 +110,12 @@ return views::WindowManagerFrameValues::instance(); } +// Returns the padding on the left, right, and bottom of the profile +// indicator. +int GetProfileIndicatorPadding() { + return ui::MaterialDesignController::IsNewerMaterialUi() ? 8 : 4; +} + } // namespace /////////////////////////////////////////////////////////////////////////////// @@ -171,8 +181,7 @@ window_icon_->Update(); } - if (browser->is_app() && IsV1AppBackButtonEnabled()) - browser->command_controller()->AddCommandObserver(IDC_BACK, this); + UpdateProfileIcons(); aura::Window* window = frame()->GetNativeWindow(); window->SetProperty( @@ -203,6 +212,7 @@ TabletModeClient::Get()->AddObserver(this); if (browser->is_app() && IsV1AppBackButtonEnabled()) { + browser->command_controller()->AddCommandObserver(IDC_BACK, this); back_button_ = new ash::FrameBackButton(); AddChildView(back_button_); // TODO(oshima): Add Tooltip, accessibility name. @@ -294,8 +304,11 @@ } int BrowserNonClientFrameViewAsh::GetTabStripLeftInset() const { - return BrowserNonClientFrameView::GetTabStripLeftInset() + - frame_values().normal_insets.left(); + int left_inset = BrowserNonClientFrameView::GetTabStripLeftInset() + + frame_values().normal_insets.left(); + if (profile_indicator_icon_) + left_inset += GetProfileIndicatorPadding() + kProfileIndicatorSize; + return left_inset; } void BrowserNonClientFrameViewAsh::OnTabsMaxXChanged() { @@ -368,6 +381,8 @@ void BrowserNonClientFrameViewAsh::ActivationChanged(bool active) { BrowserNonClientFrameView::ActivationChanged(active); + UpdateProfileIcons(); + const bool should_paint_as_active = ShouldPaintAsActive(); frame_header_->SetPaintAsActive(should_paint_as_active); @@ -400,8 +415,8 @@ frame_header_->SetHeaderHeightForPainting(painted_height); - if (profile_indicator_icon()) - LayoutIncognitoButton(); + if (profile_indicator_icon_) + LayoutProfileIndicator(); if (hosted_app_button_container_) { hosted_app_button_container_->LayoutInContainer( 0, caption_button_container_->x(), 0, painted_height); @@ -656,10 +671,10 @@ /////////////////////////////////////////////////////////////////////////////// // BrowserNonClientFrameViewAsh, protected: -// BrowserNonClientFrameView: -AvatarButtonStyle BrowserNonClientFrameViewAsh::GetAvatarButtonStyle() const { - // Ash doesn't support a profile switcher button. - return AvatarButtonStyle::NONE; +void BrowserNonClientFrameViewAsh::OnProfileAvatarChanged( + const base::FilePath& profile_path) { + BrowserNonClientFrameView::OnProfileAvatarChanged(profile_path); + UpdateProfileIcons(); } /////////////////////////////////////////////////////////////////////////////// @@ -804,6 +819,55 @@ frame()->GetNativeWindow()->SetProperty(aura::client::kTopViewInset, inset); } +bool BrowserNonClientFrameViewAsh::ShouldShowProfileIndicatorIcon() const { + // We only show the profile indicator for the teleported browser windows + // between multi-user sessions. Note that you can't teleport an incognito + // window. + Browser* browser = browser_view()->browser(); + if (browser->profile()->GetProfileType() == Profile::INCOGNITO_PROFILE) + return false; + + if (!browser->is_type_tabbed() && !browser->is_app()) + return false; + + return MultiUserWindowManager::ShouldShowAvatar( + browser_view()->GetNativeWindow()); +} + +void BrowserNonClientFrameViewAsh::UpdateProfileIcons() { + View* root_view = frame()->GetRootView(); + if (ShouldShowProfileIndicatorIcon()) { + if (!profile_indicator_icon_) { + profile_indicator_icon_ = new ProfileIndicatorIcon(); + AddChildView(profile_indicator_icon_); + if (root_view) { + // Adding a child does not invalidate the layout. + InvalidateLayout(); + root_view->Layout(); + } + } + + profile_indicator_icon_->SetIcon(gfx::Image( + GetAvatarImageForContext(browser_view()->browser()->profile()))); + profile_indicator_icon_->set_stroke_color(GetToolbarTopSeparatorColor()); + } else if (profile_indicator_icon_) { + delete profile_indicator_icon_; + profile_indicator_icon_ = nullptr; + if (root_view) + root_view->Layout(); + } +} + +void BrowserNonClientFrameViewAsh::LayoutProfileIndicator() { + DCHECK(profile_indicator_icon_); + const int bottom = GetTopInset(false) + browser_view()->GetTabStripHeight() - + GetProfileIndicatorPadding(); + profile_indicator_icon_->SetBounds( + GetProfileIndicatorPadding(), bottom - kProfileIndicatorSize, + kProfileIndicatorSize, kProfileIndicatorSize); + profile_indicator_icon_->SetVisible(true); +} + ws::Id BrowserNonClientFrameViewAsh::GetServerWindowId() const { DCHECK(features::IsUsingWindowService()); return aura::WindowMus::Get(GetFrameWindow())->server_id();
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h index 306bcbe..a238d122 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -29,6 +29,7 @@ } class HostedAppButtonContainer; +class ProfileIndicatorIcon; class TabIconView; namespace ash { @@ -134,7 +135,7 @@ protected: // BrowserNonClientFrameView: - AvatarButtonStyle GetAvatarButtonStyle() const override; + void OnProfileAvatarChanged(const base::FilePath& profile_path) override; private: FRIEND_TEST_ALL_PREFIXES(BrowserNonClientFrameViewAshTest, @@ -202,6 +203,14 @@ // Updates the kTopViewInset window property after a layout. void UpdateTopViewInset(); + // Returns true if |profile_indicator_icon_| should be shown. + bool ShouldShowProfileIndicatorIcon() const; + + // Updates the icon that indicates a teleported window. + void UpdateProfileIcons(); + + void LayoutProfileIndicator(); + ws::Id GetServerWindowId() const; // Returns whether this window is currently in the overview list. @@ -219,6 +228,9 @@ // For popups, the window icon. TabIconView* window_icon_ = nullptr; + // This is used for teleported windows (in multi-profile mode). + ProfileIndicatorIcon* profile_indicator_icon_ = nullptr; + // Helper class for painting the header. std::unique_ptr<ash::FrameHeader> frame_header_;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index 4163dda2..74b1b2c 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -58,7 +58,6 @@ #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h" #include "chrome/browser/ui/views/page_action/page_action_icon_container_view.h" #include "chrome/browser/ui/views/page_info/page_info_bubble_view_base.h" -#include "chrome/browser/ui/views/profiles/profile_indicator_icon.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/toolbar/app_menu.h" @@ -310,7 +309,7 @@ aura::Window* window = browser()->window()->GetNativeWindow(); EXPECT_FALSE(MultiUserWindowManager::ShouldShowAvatar(window)); - EXPECT_FALSE(frame_view->profile_indicator_icon()); + EXPECT_FALSE(frame_view->profile_indicator_icon_); const AccountId account_id1 = multi_user_util::GetAccountIdFromProfile(browser()->profile()); @@ -325,7 +324,7 @@ // Teleport the window back to owner desktop. manager->ShowWindowForUser(window, account_id1); EXPECT_FALSE(MultiUserWindowManager::ShouldShowAvatar(window)); - EXPECT_FALSE(frame_view->profile_indicator_icon()); + EXPECT_FALSE(frame_view->profile_indicator_icon_); } IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewAshTest,
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest_win.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest_win.cc deleted file mode 100644 index 224fbfd..0000000 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest_win.cc +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" - -#include <windows.h> - -#include "chrome/browser/ui/view_ids.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "ui/base/material_design/material_design_controller.h" -#include "ui/views/widget/widget.h" -#include "ui/views/win/hwnd_util.h" - -using BrowserNonClientFrameViewTestWin = InProcessBrowserTest; - -namespace { - -int NonClientHitTest(HWND hwnd, int x, int y) { - return ::SendMessage(hwnd, WM_NCHITTEST, 0, MAKELPARAM(x, y)); -} - -void HitTestPerimeter(views::View* view) { - ASSERT_TRUE(view); - ASSERT_TRUE(view->visible()); - - HWND hwnd = views::HWNDForView(view); - gfx::Rect rect = view->GetBoundsInScreen(); - - // Coordinates within the bounds: left/middle/right and top/middle/bottom. - const int xs[] = { rect.x(), rect.x() + rect.width() / 2, rect.right() - 1 }; - const int ys[] = { rect.y(), rect.y() + rect.height() / 2, rect.bottom() - 1}; - - for (int y : ys) { - EXPECT_NE(HTCLIENT, NonClientHitTest(hwnd, xs[0] - 1, y)); - EXPECT_EQ(HTCLIENT, NonClientHitTest(hwnd, xs[0], y)); - EXPECT_EQ(HTCLIENT, NonClientHitTest(hwnd, xs[2], y)); - EXPECT_NE(HTCLIENT, NonClientHitTest(hwnd, xs[2] + 1, y)); - } - for (int x : xs) { - EXPECT_NE(HTCLIENT, NonClientHitTest(hwnd, x, ys[0] - 1)); - EXPECT_EQ(HTCLIENT, NonClientHitTest(hwnd, x, ys[0])); - EXPECT_EQ(HTCLIENT, NonClientHitTest(hwnd, x, ys[2])); - EXPECT_NE(HTCLIENT, NonClientHitTest(hwnd, x, ys[2] + 1)); - } -} - -} // namespace - -IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewTestWin, HitTestFrameItems) { - if (ui::MaterialDesignController::IsRefreshUi()) { - // In Refresh the avatar button in the frame area is replaced by a toolbar - // button. Since there is nothing else in the frame area, skip this test. - return; - } - - BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); - views::Widget* widget = browser_view->GetWidget(); - - BrowserNonClientFrameView* frame_view = - static_cast<BrowserNonClientFrameView*>( - widget->non_client_view()->frame_view()); - - EXPECT_NO_FATAL_FAILURE( - HitTestPerimeter(frame_view->GetViewByID(VIEW_ID_AVATAR_BUTTON))); -}
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h index 7ffde12..c6703c0 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h
@@ -5,11 +5,11 @@ #ifndef CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_MAC_H_ #define CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_MAC_H_ +#import <CoreGraphics/CGBase.h> + #include "base/mac/scoped_nsobject.h" #include "base/macros.h" -#include "chrome/browser/ui/views/frame/avatar_button_manager.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" -#include "chrome/browser/ui/views/profiles/profile_indicator_icon.h" #include "components/prefs/pref_change_registrar.h" @class FullscreenToolbarControllerViews; @@ -43,22 +43,15 @@ void SizeConstraintsChanged() override; // views::View: - void Layout() override; gfx::Size GetMinimumSize() const override; protected: // views::View: void OnPaint(gfx::Canvas* canvas) override; - // BrowserNonClientFrameView: - AvatarButtonStyle GetAvatarButtonStyle() const override; - private: void PaintThemedFrame(gfx::Canvas* canvas); - // Returns the width taken by any items after the tabstrip, to the edge of the - // window. Does not include any padding between the tabstrip and these items. - int GetAfterTabstripItemWidth() const; CGFloat FullscreenBackingBarHeight() const; // Calculate the y offset the top UI needs to shift down due to showing the
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm index 5cda6be8..bab415a 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
@@ -14,7 +14,6 @@ #include "chrome/browser/ui/views/frame/browser_frame.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/browser_view_layout.h" -#include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" #include "ui/base/hit_test.h" @@ -83,12 +82,10 @@ // calling through private APIs. DCHECK(tabstrip); + const int x = GetTabStripLeftInset(); const bool restored = !frame()->IsMaximized() && !frame()->IsFullscreen(); - gfx::Rect bounds = gfx::Rect(0, GetTopInset(restored), width(), - tabstrip->GetPreferredSize().height()); - bounds.Inset(GetTabStripLeftInset(), 0, - GetAfterTabstripItemWidth() + GetTabstripPadding(), 0); - return bounds; + return gfx::Rect(x, GetTopInset(restored), width() - x - GetTabstripPadding(), + tabstrip->GetPreferredSize().height()); } int BrowserNonClientFrameViewMac::GetTopInset(bool restored) const { @@ -124,18 +121,6 @@ return y_offset + top_inset; } -int BrowserNonClientFrameViewMac::GetAfterTabstripItemWidth() const { - int item_width; - views::View* profile_switcher_button = GetProfileSwitcherButton(); - if (profile_indicator_icon() && browser_view()->IsTabStripVisible()) - item_width = profile_indicator_icon()->width(); - else if (profile_switcher_button) - item_width = profile_switcher_button->GetPreferredSize().width(); - else - return 0; - return item_width + GetAvatarIconPadding(); -} - int BrowserNonClientFrameViewMac::GetThemeBackgroundXInset() const { return 0; } @@ -187,11 +172,8 @@ int BrowserNonClientFrameViewMac::GetTabStripLeftInset() const { constexpr int kTabstripLeftInset = 70; // Make room for caption buttons. - - if (frame()->IsFullscreen()) - return 0; // Do not draw caption buttons on fullscreen. - else - return kTabstripLeftInset; + // Do not draw caption buttons on fullscreen. + return frame()->IsFullscreen() ? 0 : kTabstripLeftInset; } /////////////////////////////////////////////////////////////////////////////// @@ -207,24 +189,12 @@ } int BrowserNonClientFrameViewMac::NonClientHitTest(const gfx::Point& point) { - views::View* profile_switcher_view = GetProfileSwitcherButton(); - if (profile_switcher_view) { - gfx::Point point_in_switcher(point); - views::View::ConvertPointToTarget(this, profile_switcher_view, - &point_in_switcher); - if (profile_switcher_view->HitTestPoint(point_in_switcher)) { - return HTCLIENT; - } - } - int component = frame()->client_view()->NonClientHitTest(point); - // BrowserView::NonClientHitTest will return HTNOWHERE for points that hit // the native title bar. On Mac, we need to explicitly return HTCAPTION for // those points. - if (component == HTNOWHERE && bounds().Contains(point)) - return HTCAPTION; - - return component; + const int component = frame()->client_view()->NonClientHitTest(point); + return (component == HTNOWHERE && bounds().Contains(point)) ? HTCAPTION + : component; } void BrowserNonClientFrameViewMac::GetWindowMask(const gfx::Size& size, @@ -261,31 +231,6 @@ // views::View: -void BrowserNonClientFrameViewMac::Layout() { - DCHECK(browser_view()); - views::View* profile_switcher_button = GetProfileSwitcherButton(); - if (profile_indicator_icon() && browser_view()->IsTabStripVisible()) { - LayoutIncognitoButton(); - // Mac lays out the incognito icon on the right, as the stoplight - // buttons live in its Windows/Linux location. - profile_indicator_icon()->SetX(width() - GetAfterTabstripItemWidth()); - } else if (profile_switcher_button) { - gfx::Size button_size = profile_switcher_button->GetPreferredSize(); - int button_x = width() - GetAfterTabstripItemWidth(); - int button_y = 0; - TabStrip* tabstrip = browser_view()->tabstrip(); - if (tabstrip && browser_view()->IsTabStripVisible()) { - int new_tab_button_bottom = - tabstrip->bounds().y() + tabstrip->new_tab_button_bounds().height(); - // Align the switcher's bottom to bottom of the new tab button; - button_y = new_tab_button_bottom - button_size.height(); - } - profile_switcher_button->SetBounds(button_x, button_y, button_size.width(), - button_size.height()); - } - BrowserNonClientFrameView::Layout(); -} - void BrowserNonClientFrameViewMac::OnPaint(gfx::Canvas* canvas) { if (!browser_view()->IsBrowserTypeNormal()) return; @@ -296,11 +241,6 @@ PaintThemedFrame(canvas); } -// BrowserNonClientFrameView: -AvatarButtonStyle BrowserNonClientFrameViewMac::GetAvatarButtonStyle() const { - return AvatarButtonStyle::NATIVE; -} - /////////////////////////////////////////////////////////////////////////////// // BrowserNonClientFrameViewMac, private:
diff --git a/chrome/browser/ui/views/frame/browser_root_view.h b/chrome/browser/ui/views/frame/browser_root_view.h index 63d2133..8b5da77 100644 --- a/chrome/browser/ui/views/frame/browser_root_view.h +++ b/chrome/browser/ui/views/frame/browser_root_view.h
@@ -57,7 +57,7 @@ BrowserRootView(BrowserView* browser_view, views::Widget* widget); ~BrowserRootView() override; - // Overridden from views::View: + // views::View: bool GetDropFormats( int* formats, std::set<ui::Clipboard::FormatType>* format_types) override;
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 65881ea..fa5eb90 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1812,11 +1812,52 @@ if (index == -1) return base::string16(); - base::string16 window_title = + base::string16 title = browser_->GetWindowTitleForTab(include_app_name, index); - return chrome::AssembleTabAccessibilityLabel( - window_title, tabstrip_->IsTabCrashed(index), - tabstrip_->TabHasNetworkError(index), tabstrip_->GetTabAlertState(index)); + + // Tab has crashed. + if (tabstrip_->IsTabCrashed(index)) + return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_CRASHED_FORMAT, title); + + // Network error interstitial. + if (tabstrip_->TabHasNetworkError(index)) { + return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_NETWORK_ERROR_FORMAT, + title); + } + + // Alert tab states. + switch (tabstrip_->GetTabAlertState(index)) { + case TabAlertState::AUDIO_PLAYING: + return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_AUDIO_PLAYING_FORMAT, + title); + case TabAlertState::USB_CONNECTED: + return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_USB_CONNECTED_FORMAT, + title); + case TabAlertState::BLUETOOTH_CONNECTED: + return l10n_util::GetStringFUTF16( + IDS_TAB_AX_LABEL_BLUETOOTH_CONNECTED_FORMAT, title); + case TabAlertState::MEDIA_RECORDING: + return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_MEDIA_RECORDING_FORMAT, + title); + case TabAlertState::AUDIO_MUTING: + return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_AUDIO_MUTING_FORMAT, + title); + case TabAlertState::TAB_CAPTURING: + return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_TAB_CAPTURING_FORMAT, + title); + case TabAlertState::PIP_PLAYING: + return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_PIP_PLAYING_FORMAT, + title); + + case TabAlertState::DESKTOP_CAPTURING: + return l10n_util::GetStringFUTF16( + IDS_TAB_AX_LABEL_DESKTOP_CAPTURING_FORMAT, title); + case TabAlertState::NONE: + return title; + } + + NOTREACHED(); + return base::string16(); } void BrowserView::NativeThemeUpdated(const ui::NativeTheme* theme) { @@ -2851,10 +2892,9 @@ // Never show any avatar bubble in Incognito. if (!IsRegularOrGuestSession()) return; - views::Button* avatar_button = toolbar_->avatar_button(); - if (!avatar_button) - avatar_button = frame_->GetNewAvatarMenuButton(); + // Do not show avatar bubble if there is no avatar menu button. + views::Button* avatar_button = toolbar_->avatar_button(); if (!avatar_button) return;
diff --git a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view.cc b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view.cc index 0fb105cd..42788cc 100644 --- a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view.cc
@@ -15,7 +15,6 @@ std::unique_ptr<views::NavButtonProvider> nav_button_provider) : OpaqueBrowserFrameView(frame, browser_view, layout), nav_button_provider_(std::move(nav_button_provider)) { - profile_switcher()->set_nav_button_provider(nav_button_provider_.get()); } DesktopLinuxBrowserFrameView::~DesktopLinuxBrowserFrameView() {}
diff --git a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.cc b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.cc index b2d75966..55b4ed6 100644 --- a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.cc +++ b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.cc
@@ -36,34 +36,6 @@ return spacing; } -void DesktopLinuxBrowserFrameViewLayout::LayoutNewStyleAvatar( - views::View* host) { - if (!new_avatar_button_) - return; - - gfx::Size button_size; - gfx::Insets button_spacing; - nav_button_provider_->CalculateCaptionButtonLayout( - new_avatar_button_->GetPreferredSize(), - delegate_->GetTopAreaHeight() - TitlebarTopThickness(), &button_size, - &button_spacing); - const int extra_offset = - has_trailing_buttons() ? nav_button_provider_->GetInterNavButtonSpacing() - : 0; - - const int total_width = - button_size.width() + button_spacing.right() + extra_offset; - - const int button_x = available_space_trailing_x_ - total_width; - const int button_y = button_spacing.top() + TitlebarTopThickness(); - - minimum_size_for_buttons_ += total_width; - available_space_trailing_x_ -= total_width; - - new_avatar_button_->SetBounds(button_x, button_y, button_size.width(), - button_size.height()); -} - bool DesktopLinuxBrowserFrameViewLayout::ShouldDrawImageMirrored( views::ImageButton* button, ButtonAlignment alignment) const {
diff --git a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.h b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.h index e276dde..0cf3de1 100644 --- a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.h +++ b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.h
@@ -21,7 +21,6 @@ int GetWindowCaptionSpacing(views::FrameButton button_id, bool leading_spacing, bool is_leading_button) const override; - void LayoutNewStyleAvatar(views::View* host) override; bool ShouldDrawImageMirrored(views::ImageButton* button, ButtonAlignment alignment) const override;
diff --git a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout_unittest.cc index 0c5a6d83d..37320917 100644 --- a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout_unittest.cc +++ b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout_unittest.cc
@@ -50,9 +50,6 @@ } bool ShouldShowCaptionButtons() const override { return true; } bool IsRegularOrGuestSession() const override { return true; } - gfx::ImageSkia GetIncognitoAvatarIcon() const override { - return gfx::ImageSkia(); - } bool IsMaximized() const override { return false; } bool IsMinimized() const override { return false; } bool IsTabStripVisible() const override { return true; } @@ -63,9 +60,6 @@ gfx::Size GetTabstripPreferredSize() const override { return gfx::Size(78, 29); } - gfx::Size GetNewTabButtonPreferredSize() const override { - return gfx::Size(28, 28); - } int GetTopAreaHeight() const override { return 0; } bool UseCustomFrame() const override { return true; } bool IsFrameCondensed() const override { return false; } @@ -120,17 +114,6 @@ int GetInterNavButtonSpacing() const override { return kInterNavButtonSpacing; } - - std::unique_ptr<views::Background> CreateAvatarButtonBackground( - const views::Button* avatar_button) const override { - return nullptr; - } - - void CalculateCaptionButtonLayout( - const gfx::Size& content_size, - int top_area_height, - gfx::Size* caption_button_size, - gfx::Insets* caption_button_spacing) const override {} }; } // namespace
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc index 90877f1..dd1db05 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -11,13 +11,11 @@ #include "base/win/windows_version.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/app/chrome_dll_resource.h" -#include "chrome/browser/profiles/profile.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/extensions/hosted_app_browser_controller.h" #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/hosted_app_button_container.h" -#include "chrome/browser/ui/views/profiles/profile_indicator_icon.h" #include "chrome/browser/ui/views/tabs/new_tab_button.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" @@ -48,13 +46,8 @@ HICON GlassBrowserFrameView::throbber_icons_[ GlassBrowserFrameView::kThrobberIconCount]; -using MD = ui::MaterialDesignController; - namespace { -// How far the profile switcher button is from the left of the minimize button. -constexpr int kProfileSwitcherButtonOffset = 1; - // Converts the |image| to a Windows icon and returns the corresponding HICON // handle. |image| is resized to desired |width| and |height| if needed. base::win::ScopedHICON CreateHICONFromSkBitmapSizedTo( @@ -245,7 +238,9 @@ } int GlassBrowserFrameView::GetTabStripLeftInset() const { - return incognito_bounds_.right() + GetTabstripPadding(); + if (CaptionButtonsOnLeadingEdge()) + return width() - frame()->GetMinimizeButtonOffset() + GetTabstripPadding(); + return BrowserNonClientFrameView::GetTabStripLeftInset(); } bool GlassBrowserFrameView::IsSingleTabModeAvailable() const { @@ -314,15 +309,6 @@ if (!bounds().Contains(point)) return HTNOWHERE; - // See if the point is within the incognito icon or the profile switcher menu. - views::View* profile_switcher_view = GetProfileSwitcherButton(); - if ((profile_indicator_icon() && - profile_indicator_icon()->GetMirroredBounds().Contains(point)) || - (profile_switcher_view && - profile_switcher_view->GetMirroredBounds().Contains(point))) { - return HTCLIENT; - } - if (hosted_app_button_container_) { // TODO(alancutter): Assign hit test components to all children and refactor // this entire function call to just be GetHitTestComponent(this, point). @@ -454,21 +440,6 @@ return frame()->widget_delegate()->GetWindowIcon(); } -void GlassBrowserFrameView::OnTabRemoved(int index) { - BrowserNonClientFrameView::OnTabRemoved(index); - // The profile switcher button may need to change height here, too. - // TabStripMaxXChanged is not enough when a tab other than the last tab is - // closed. - LayoutProfileSwitcher(); -} - -void GlassBrowserFrameView::OnTabsMaxXChanged() { - BrowserNonClientFrameView::OnTabsMaxXChanged(); - // The profile switcher button's height depends on the position of the new - // tab button, which may have changed if the tabs max X changed. - LayoutProfileSwitcher(); -} - bool GlassBrowserFrameView::IsMaximized() const { return frame()->IsMaximized(); } @@ -489,26 +460,15 @@ TRACE_EVENT0("views.frame", "GlassBrowserFrameView::OnPaint"); if (ShouldCustomDrawSystemTitlebar()) PaintTitlebar(canvas); - if (!browser_view()->IsTabStripVisible()) - return; - if (ClientBorderThickness(false) > 0) + if (browser_view()->IsTabStripVisible() && (ClientBorderThickness(false) > 0)) PaintClientEdge(canvas); } void GlassBrowserFrameView::Layout() { TRACE_EVENT0("views.frame", "GlassBrowserFrameView::Layout"); - // The profile switcher and incognito icon depends on the caption button - // layout, so always call it first. if (ShouldCustomDrawSystemTitlebar()) LayoutCaptionButtons(); - LayoutProfileSwitcher(); - - // The incognito area must be laid out even if we're not in incognito as - // tab-strip insets depend on it. When not in incognito the bounds will be - // zero-width but positioned correctly for the titlebar to start after it. - LayoutIncognitoIcon(); - if (ShouldCustomDrawSystemTitlebar()) LayoutTitleBar(); @@ -516,14 +476,6 @@ } /////////////////////////////////////////////////////////////////////////////// -// GlassBrowserFrameView, protected: - -// BrowserNonClientFrameView: -AvatarButtonStyle GlassBrowserFrameView::GetAvatarButtonStyle() const { - return AvatarButtonStyle::NATIVE; -} - -/////////////////////////////////////////////////////////////////////////////// // GlassBrowserFrameView, private: void GlassBrowserFrameView::ActivationChanged(bool active) { @@ -682,29 +634,8 @@ // similar vertical coordinates, we need to reserve a larger, 16 px gap to // avoid looking too cluttered. constexpr int kNewTabCaptionMaximizedSpacing = 16; - const int caption_spacing = IsMaximized() ? kNewTabCaptionMaximizedSpacing - : kNewTabCaptionRestoredSpacing; - - // The profile switcher button is optionally displayed to the left of the - // minimize button. - views::View* profile_switcher = GetProfileSwitcherButton(); - if (!profile_switcher) - return caption_spacing; - - int profile_spacing = - profile_switcher->width() + kProfileSwitcherButtonOffset; - - // In maximized mode, simply treat the profile switcher button as another - // caption button. - if (IsMaximized()) - return caption_spacing + profile_spacing; - - // When not maximized, allow the new tab button to slide completely under the - // the profile switcher button. - const auto* new_tab_button = browser_view()->tabstrip()->new_tab_button(); - profile_spacing -= new_tab_button->GetPreferredSize().width(); - - return std::max(caption_spacing, profile_spacing); + return IsMaximized() ? kNewTabCaptionMaximizedSpacing + : kNewTabCaptionRestoredSpacing; } bool GlassBrowserFrameView::IsToolbarVisible() const { @@ -713,11 +644,8 @@ } bool GlassBrowserFrameView::ShowCustomIcon() const { - // Don't show the window icon when the incognito badge is visible, since - // they're competing for the same space. // Hosted app windows don't include the window icon as per UI mocks. - return !profile_indicator_icon() && !hosted_app_button_container_ && - ShouldCustomDrawSystemTitlebar() && + return !hosted_app_button_container_ && ShouldCustomDrawSystemTitlebar() && browser_view()->ShouldShowWindowIcon(); } @@ -868,66 +796,6 @@ canvas->FillRect(side, color); } -void GlassBrowserFrameView::LayoutProfileSwitcher() { - if (!browser_view()->IsRegularOrGuestSession()) - return; - - View* profile_switcher = GetProfileSwitcherButton(); - if (!profile_switcher) - return; - - gfx::Size button_size = profile_switcher->GetPreferredSize(); - int button_width = button_size.width(); - int button_height = button_size.height(); - - int button_x; - if (CaptionButtonsOnLeadingEdge()) { - button_x = width() - frame()->GetMinimizeButtonOffset() + - kProfileSwitcherButtonOffset; - } else { - button_x = MinimizeButtonX() - kProfileSwitcherButtonOffset - button_width; - } - - int button_y = WindowTopY(); - if (IsMaximized()) { - // In maximized mode the caption buttons appear only 19 pixels high, but - // their contents are aligned as if they were 20 pixels high and extended - // 1 pixel off the top of the screen. We position the profile switcher - // button the same way to match. - button_y -= 1; - } - - // Shrink the button height when it's atop part of the tabstrip. In RTL the - // new tab button is on the left, so it can never slide under the avatar - // button, which is still on the right [http://crbug.com/560619]. - TabStrip* tabstrip = browser_view()->tabstrip(); - if (tabstrip && !CaptionButtonsOnLeadingEdge() && - (tabstrip->new_tab_button_bounds().right() > button_x)) - button_height = profile_switcher->GetMinimumSize().height(); - - profile_switcher->SetBounds(button_x, button_y, button_width, button_height); -} - -void GlassBrowserFrameView::LayoutIncognitoIcon() { - const gfx::Size size(GetIncognitoAvatarIcon().size()); - int x = ClientBorderThickness(false); - // In RTL, the icon needs to start after the caption buttons. - if (CaptionButtonsOnLeadingEdge()) { - x = width() - frame()->GetMinimizeButtonOffset() + - (GetProfileSwitcherButton() ? (GetProfileSwitcherButton()->width() + - kProfileSwitcherButtonOffset) - : 0); - } - const int bottom = GetTopInset(false) + browser_view()->GetTabStripHeight() - - GetAvatarIconPadding(); - incognito_bounds_.SetRect( - x + (profile_indicator_icon() ? GetAvatarIconPadding() : 0), - bottom - size.height(), profile_indicator_icon() ? size.width() : 0, - size.height()); - if (profile_indicator_icon()) - profile_indicator_icon()->SetBoundsRect(incognito_bounds_); -} - void GlassBrowserFrameView::LayoutTitleBar() { TRACE_EVENT0("views.frame", "GlassBrowserFrameView::LayoutTitleBar"); if (!ShowCustomIcon() && !ShowCustomTitle()) @@ -955,13 +823,9 @@ if (ShowCustomIcon()) { window_icon_->SetBoundsRect(window_icon_bounds); next_leading_x = window_icon_bounds.right() + kIconTitleSpacing; - } else if (profile_indicator_icon()) { - next_leading_x = - profile_indicator_icon()->bounds().right() + kIconTitleSpacing; } if (hosted_app_button_container_) { - DCHECK(!GetProfileSwitcherButton()); next_trailing_x = hosted_app_button_container_->LayoutInContainer( next_leading_x, next_trailing_x, window_top, titlebar_visual_height); }
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h index db422273..3a3a2cc2 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
@@ -8,7 +8,6 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/win/scoped_gdi_object.h" -#include "chrome/browser/ui/views/frame/avatar_button_manager.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/frame/windows_10_caption_button.h" #include "chrome/browser/ui/views/tab_icon_view.h" @@ -47,8 +46,6 @@ int GetTabStripLeftInset() const override; bool IsSingleTabModeAvailable() const override; bool ShouldDrawStrokes() const override; - void OnTabRemoved(int index) override; - void OnTabsMaxXChanged() override; // views::NonClientFrameView: gfx::Rect GetBoundsForClientView() const override; @@ -89,9 +86,6 @@ void OnPaint(gfx::Canvas* canvas) override; void Layout() override; - // BrowserNonClientFrameView: - AvatarButtonStyle GetAvatarButtonStyle() const override; - private: // views::NonClientFrameView: void ActivationChanged(bool active) override; @@ -161,9 +155,7 @@ gfx::Canvas* canvas) const; // Layout various sub-components of this view. - void LayoutIncognitoIcon(); void LayoutTitleBar(); - void LayoutProfileSwitcher(); void LayoutCaptionButtons(); void LayoutCaptionButton(Windows10CaptionButton* button, int previous_button_x); @@ -183,9 +175,6 @@ // Displays the next throbber frame. void DisplayNextThrobberFrame(); - // The layout rect of the incognito icon, if visible. - gfx::Rect incognito_bounds_; - // The bounds of the ClientView. gfx::Rect client_view_bounds_;
diff --git a/chrome/browser/ui/views/frame/minimize_button_metrics_win.cc b/chrome/browser/ui/views/frame/minimize_button_metrics_win.cc index 55e0086..ad8eb45 100644 --- a/chrome/browser/ui/views/frame/minimize_button_metrics_win.cc +++ b/chrome/browser/ui/views/frame/minimize_button_metrics_win.cc
@@ -9,8 +9,6 @@ #include "base/win/windows_version.h" #include "dwmapi.h" #include "ui/base/win/shell.h" -#include "ui/display/display.h" -#include "ui/display/win/dpi.h" #include "ui/display/win/screen_win.h" #include "ui/gfx/geometry/point.h" @@ -53,29 +51,6 @@ MinimizeButtonMetrics::~MinimizeButtonMetrics() { } -// static -int MinimizeButtonMetrics::GetCaptionButtonHeightInDIPs() { - // At DPI scaling settings other than 100% the result won't be exactly right. - // TODO: return a more accurate approximation [http://crbug.com/716365] - - // SM_CYSIZE returns the caption button height, but to get the full height - // from the top of the window we add SM_CYSIZEFRAME. - const int caption_height = GetSystemMetrics(SM_CYSIZE); - const int frame_thickness = GetSystemMetrics(SM_CYSIZEFRAME); - - // The result of GetSystemMetrics depends on the scale factor of the primary - // display. Divide the sum by that to convert to DIPs. (Converting SM_CYSIZE - // and SM_CYSIZEFRAME to DIPs individually adds a bigger rounding error.) - float primary_device_scale_factor = - display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor(); - float height_dips = - (caption_height + frame_thickness) / primary_device_scale_factor; - - // Testing shows that floor() gives a more accurate approximation than - // round() here. - return std::floor(height_dips); -} - void MinimizeButtonMetrics::Init(HWND hwnd) { DCHECK(!hwnd_); hwnd_ = hwnd;
diff --git a/chrome/browser/ui/views/frame/minimize_button_metrics_win.h b/chrome/browser/ui/views/frame/minimize_button_metrics_win.h index 305784f..cfc7823 100644 --- a/chrome/browser/ui/views/frame/minimize_button_metrics_win.h +++ b/chrome/browser/ui/views/frame/minimize_button_metrics_win.h
@@ -18,9 +18,6 @@ MinimizeButtonMetrics(); ~MinimizeButtonMetrics(); - // Returns the height of the native caption buttons in DIPs. - static int GetCaptionButtonHeightInDIPs(); - void Init(HWND hwnd); // Obtain the X offset of the native minimize button. Since Windows can lie
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc index 3c9ee52e..1edd5cd 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -16,7 +16,6 @@ #include "chrome/browser/ui/views/frame/hosted_app_button_container.h" #include "chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h" #include "chrome/browser/ui/views/frame/opaque_browser_frame_view_platform_specific.h" -#include "chrome/browser/ui/views/profiles/profile_indicator_icon.h" #include "chrome/browser/ui/views/tab_icon_view.h" #include "chrome/browser/ui/views/tabs/new_tab_button.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" @@ -257,29 +256,10 @@ return layout_->GetWindowBoundsForClientBounds(client_bounds); } -bool OpaqueBrowserFrameView::IsWithinAvatarMenuButtons( - const gfx::Point& point) const { - if (profile_indicator_icon() && - profile_indicator_icon()->GetMirroredBounds().Contains(point)) { - return true; - } - views::View* profile_switcher_view = GetProfileSwitcherButton(); - if (profile_switcher_view && - profile_switcher_view->GetMirroredBounds().Contains(point)) { - return true; - } - - return false; -} - int OpaqueBrowserFrameView::NonClientHitTest(const gfx::Point& point) { if (!bounds().Contains(point)) return HTNOWHERE; - // See if the point is within the avatar menu button. - if (IsWithinAvatarMenuButtons(point)) - return HTCLIENT; - int frame_component = frame()->client_view()->NonClientHitTest(point); // See if we're in the sysmenu region. We still have to check the tabstrip @@ -496,10 +476,6 @@ return browser_view()->IsRegularOrGuestSession(); } -gfx::ImageSkia OpaqueBrowserFrameView::GetIncognitoAvatarIcon() const { - return BrowserNonClientFrameView::GetIncognitoAvatarIcon(); -} - bool OpaqueBrowserFrameView::IsMaximized() const { return frame()->IsMaximized(); } @@ -529,10 +505,6 @@ return browser_view()->tabstrip()->GetPreferredSize(); } -gfx::Size OpaqueBrowserFrameView::GetNewTabButtonPreferredSize() const { - return browser_view()->tabstrip()->new_tab_button()->GetPreferredSize(); -} - int OpaqueBrowserFrameView::GetTopAreaHeight() const { const int non_client_top_height = layout_->NonClientTopHeight(false); if (!browser_view()->IsTabStripVisible()) @@ -602,10 +574,6 @@ platform_observer_->IsUsingSystemTheme(); } -AvatarButtonStyle OpaqueBrowserFrameView::GetAvatarButtonStyle() const { - return AvatarButtonStyle::THEMED; -} - void OpaqueBrowserFrameView::MaybeRedrawFrameButtons() {} ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h index 5176ba3d..17adead2 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
@@ -9,7 +9,6 @@ #include "base/macros.h" #include "chrome/browser/ui/view_ids.h" -#include "chrome/browser/ui/views/frame/avatar_button_manager.h" #include "chrome/browser/ui/views/frame/browser_frame.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h" @@ -99,14 +98,12 @@ gfx::Size GetBrowserViewMinimumSize() const override; bool ShouldShowCaptionButtons() const override; bool IsRegularOrGuestSession() const override; - gfx::ImageSkia GetIncognitoAvatarIcon() const override; bool IsMaximized() const override; bool IsMinimized() const override; bool IsTabStripVisible() const override; int GetTabStripHeight() const override; bool IsToolbarVisible() const override; gfx::Size GetTabstripPreferredSize() const override; - gfx::Size GetNewTabButtonPreferredSize() const override; int GetTopAreaHeight() const override; bool UseCustomFrame() const override; bool IsFrameCondensed() const override; @@ -127,7 +124,6 @@ // BrowserNonClientFrameView: bool ShouldPaintAsThemed() const override; - AvatarButtonStyle GetAvatarButtonStyle() const override; OpaqueBrowserFrameViewLayout* layout() { return layout_; } @@ -176,9 +172,6 @@ // window is restored regardless of the actual mode. int FrameTopBorderThickness(bool restored) const; - // Returns true if the specified point is within the avatar menu buttons. - bool IsWithinAvatarMenuButtons(const gfx::Point& point) const; - // Returns the thickness of the entire nonclient left, right, and bottom // borders, including both the window frame and any client edge. int NonClientBorderThickness() const;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc index 551d79f..0021cb17 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
@@ -8,11 +8,8 @@ #include "base/containers/adapters.h" #include "base/stl_util.h" #include "build/build_config.h" -#include "chrome/browser/profiles/profiles_state.h" #include "chrome/browser/ui/views/frame/hosted_app_button_container.h" -#include "chrome/browser/ui/views/profiles/profile_indicator_icon.h" #include "chrome/common/chrome_switches.h" -#include "components/signin/core/browser/profile_management_switches.h" #include "ui/base/material_design/material_design_controller.h" #include "ui/gfx/font.h" #include "ui/views/controls/button/image_button.h" @@ -68,8 +65,7 @@ const int OpaqueBrowserFrameViewLayout::kNewTabCaptionCondensedSpacing = 16; OpaqueBrowserFrameViewLayout::OpaqueBrowserFrameViewLayout() - : new_avatar_button_(nullptr), - available_space_leading_x_(0), + : available_space_leading_x_(0), available_space_trailing_x_(0), minimum_size_for_buttons_(0), has_leading_buttons_(false), @@ -82,7 +78,6 @@ close_button_(nullptr), window_icon_(nullptr), window_title_(nullptr), - incognito_icon_(nullptr), trailing_buttons_{views::FRAME_BUTTON_MINIMIZE, views::FRAME_BUTTON_MAXIMIZE, views::FRAME_BUTTON_CLOSE} {} @@ -113,7 +108,7 @@ min_size.Enlarge(2 * border_thickness, NonClientTopHeight(false) + border_thickness); - // Ensure that we can, at minimum, hold our window controls and avatar icon. + // Ensure that we can, at minimum, hold our window controls. min_size.set_width(std::max(min_size.width(), minimum_size_for_buttons_)); // Ensure that the minimum width is enough to hold a minimum width tab strip @@ -296,32 +291,6 @@ /////////////////////////////////////////////////////////////////////////////// // OpaqueBrowserFrameViewLayout, protected: -void OpaqueBrowserFrameViewLayout::LayoutNewStyleAvatar(views::View* host) { - if (!new_avatar_button_) - return; - - const int button_width = new_avatar_button_->GetPreferredSize().width(); - int button_width_with_offset = button_width; - if (!trailing_buttons_.empty()) - button_width_with_offset += kCaptionSpacing; - - const int button_x = available_space_trailing_x_ - button_width_with_offset; - const int button_y = DefaultCaptionButtonY(!delegate_->IsFrameCondensed()); - - minimum_size_for_buttons_ += button_width_with_offset; - available_space_trailing_x_ -= button_width_with_offset; - - // In non-maximized mode, allow the new tab button to completely slide under - // the avatar button. - if (!delegate_->IsFrameCondensed()) { - available_space_trailing_x_ += - delegate_->GetNewTabButtonPreferredSize().width() + kCaptionSpacing; - } - - new_avatar_button_->SetBounds(button_x, button_y, button_width, - kCaptionButtonHeight); -} - bool OpaqueBrowserFrameViewLayout::ShouldDrawImageMirrored( views::ImageButton* button, ButtonAlignment alignment) const { @@ -332,12 +301,6 @@ /////////////////////////////////////////////////////////////////////////////// // OpaqueBrowserFrameViewLayout, private: -bool OpaqueBrowserFrameViewLayout::ShouldIncognitoIconBeOnRight() const { - // The incognito should be shown either on the end of the left or the - // beginning of the right, depending on which side has fewer buttons. - return trailing_buttons_.size() < leading_buttons_.size(); -} - int OpaqueBrowserFrameViewLayout::TabStripCaptionSpacing() const { // In Refresh, any necessary padding after the tabstrip is contained within // the tabs and/or new tab button. @@ -446,42 +409,6 @@ } } -void OpaqueBrowserFrameViewLayout::LayoutIncognitoIcon(views::View* host) { - const int old_button_size = - available_space_leading_x_ + host->width() - available_space_trailing_x_; - - // Any buttons/icon/title were laid out based on the frame border thickness, - // but the tabstrip bounds need to be based on the non-client border thickness - // on any side where there aren't other buttons forcing a larger inset. - int min_button_width = NonClientBorderThickness(); - available_space_leading_x_ = - std::max(available_space_leading_x_, min_button_width); - // The trailing corner is a mirror of the leading one. - available_space_trailing_x_ = - std::min(available_space_trailing_x_, host->width() - min_button_width); - - if (incognito_icon_) { - const int pad = OpaqueBrowserFrameView::GetAvatarIconPadding(); - const gfx::Size size(delegate_->GetIncognitoAvatarIcon().size()); - const int incognito_width = pad + size.width(); - int x; - if (ShouldIncognitoIconBeOnRight()) { - available_space_trailing_x_ -= incognito_width; - x = available_space_trailing_x_; - } else { - x = available_space_leading_x_ + pad; - available_space_leading_x_ += incognito_width; - } - const int bottom = - GetTabStripInsetsTop(false) + delegate_->GetTabStripHeight() - pad; - incognito_icon_->SetBounds(x, bottom - size.height(), size.width(), - size.height()); - } - - minimum_size_for_buttons_ += (available_space_leading_x_ + host->width() - - available_space_trailing_x_ - old_button_size); -} - void OpaqueBrowserFrameViewLayout::ConfigureButton(views::View* host, views::FrameButton button_id, ButtonAlignment alignment) { @@ -614,8 +541,7 @@ void OpaqueBrowserFrameViewLayout::SetView(int id, views::View* view) { // Why do things this way instead of having an Init() method, where we're // passed the views we'll handle? Because OpaqueBrowserFrameView doesn't own - // all the views which are part of it. The avatar stuff, for example, will be - // added and removed by the base class of OpaqueBrowserFrameView. + // all the views which are part of it. switch (id) { case VIEW_ID_MINIMIZE_BUTTON: if (view) { @@ -655,12 +581,6 @@ } window_title_ = static_cast<views::Label*>(view); break; - case VIEW_ID_PROFILE_INDICATOR_ICON: - incognito_icon_ = view; - break; - case VIEW_ID_AVATAR_BUTTON: - new_avatar_button_ = view; - break; case VIEW_ID_HOSTED_APP_BUTTON_CONTAINER: DCHECK_EQ(view->GetClassName(), HostedAppButtonContainer::kViewClassName); hosted_app_button_container_ = @@ -689,9 +609,19 @@ LayoutWindowControls(host); LayoutTitleBar(host); - if (delegate_->IsRegularOrGuestSession()) - LayoutNewStyleAvatar(host); - LayoutIncognitoIcon(host); + // Any buttons/icon/title were laid out based on the frame border thickness, + // but the tabstrip bounds need to be based on the non-client border thickness + // on any side where there aren't other buttons forcing a larger inset. + const int old_button_size = + available_space_leading_x_ + host->width() - available_space_trailing_x_; + const int min_button_width = NonClientBorderThickness(); + available_space_leading_x_ = + std::max(available_space_leading_x_, min_button_width); + // The trailing corner is a mirror of the leading one. + available_space_trailing_x_ = + std::min(available_space_trailing_x_, host->width() - min_button_width); + minimum_size_for_buttons_ += (available_space_leading_x_ + host->width() - + available_space_trailing_x_ - old_button_size); client_view_bounds_ = CalculateClientAreaBounds( host->width(), host->height());
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h index c831e59..255f82d 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h
@@ -85,9 +85,8 @@ int GetTabStripInsetsTop(bool restored) const; // Returns the y-coordinate of the caption button when native frame buttons - // are disabled. Also used to position the profile chooser button. If - // |restored| is true, acts as if the window is restored regardless of the - // real mode. + // are disabled. If |restored| is true, acts as if the window is restored + // regardless of the real mode. int DefaultCaptionButtonY(bool restored) const; // Returns the y-coordinate of button |button_id|. If |restored| is true, @@ -150,30 +149,21 @@ bool has_trailing_buttons() const { return has_trailing_buttons_; } - virtual void LayoutNewStyleAvatar(views::View* host); - virtual bool ShouldDrawImageMirrored(views::ImageButton* button, ButtonAlignment alignment) const; OpaqueBrowserFrameViewLayoutDelegate* delegate_; - views::View* new_avatar_button_; - // The leading and trailing x positions of the empty space available for // laying out titlebar elements. int available_space_leading_x_; int available_space_trailing_x_; - // The size of the window buttons, and the avatar menu item (if any). This - // does not count labels or other elements that should be counted in a - // minimal frame. + // The size of the window buttons. This does not count labels or other + // elements that should be counted in a minimal frame. int minimum_size_for_buttons_; private: - // Determines whether the incognito icon should be shown on the right side of - // the tab strip (instead of the usual left). - bool ShouldIncognitoIconBeOnRight() const; - // Determines the amount of spacing between the tabstrip and the caption // buttons. int TabStripCaptionSpacing() const; @@ -181,7 +171,6 @@ // Layout various sub-components of this view. void LayoutWindowControls(views::View* host); void LayoutTitleBar(views::View* host); - void LayoutIncognitoIcon(views::View* host); void ConfigureButton(views::View* host, views::FrameButton button_id, @@ -235,8 +224,6 @@ HostedAppButtonContainer* hosted_app_button_container_ = nullptr; - views::View* incognito_icon_; - std::vector<views::FrameButton> leading_buttons_; std::vector<views::FrameButton> trailing_buttons_;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h index 1f8bb467..178bb9e 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h
@@ -6,7 +6,6 @@ #define CHROME_BROWSER_UI_VIEWS_FRAME_OPAQUE_BROWSER_FRAME_VIEW_LAYOUT_DELEGATE_H_ namespace gfx { -class ImageSkia; class Size; } @@ -35,10 +34,6 @@ // Returns true if in guest mode or a non off the record session. virtual bool IsRegularOrGuestSession() const = 0; - // We don't have a ThemeProvider in the layout manager, so plumb in the icon - // source here. - virtual gfx::ImageSkia GetIncognitoAvatarIcon() const = 0; - // Controls window state. virtual bool IsMaximized() const = 0; virtual bool IsMinimized() const = 0; @@ -51,9 +46,6 @@ // it. virtual gfx::Size GetTabstripPreferredSize() const = 0; - // Returns the New Tab Button's preferred size. - virtual gfx::Size GetNewTabButtonPreferredSize() const = 0; - // Computes the height of the top area of the frame. virtual int GetTopAreaHeight() const = 0;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc index ae3a293..423367e 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
@@ -8,11 +8,9 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/layout_constants.h" -#include "chrome/browser/ui/views/profiles/profile_indicator_icon.h" #include "chrome/browser/ui/views/tab_icon_view.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/views/chrome_views_test_base.h" -#include "components/signin/core/browser/profile_management_switches.h" #include "ui/base/material_design/material_design_controller.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_rep.h" @@ -65,9 +63,6 @@ return show_caption_buttons_; } bool IsRegularOrGuestSession() const override { return true; } - gfx::ImageSkia GetIncognitoAvatarIcon() const override { - return gfx::ImageSkia(gfx::ImageSkiaRep(gfx::Size(40, 29), 1.0f)); - } bool IsMaximized() const override { return maximized_; } bool IsMinimized() const override { return false; } bool IsTabStripVisible() const override { return window_title_.empty(); } @@ -78,9 +73,6 @@ gfx::Size GetTabstripPreferredSize() const override { return IsTabStripVisible() ? gfx::Size(78, 29) : gfx::Size(); } - gfx::Size GetNewTabButtonPreferredSize() const override { - return gfx::Size(28, 28); - } int GetTopAreaHeight() const override { return 0; } bool UseCustomFrame() const override { return true; } bool IsFrameCondensed() const override { @@ -171,12 +163,6 @@ root_view_->AddChildView(window_title_); } - void AddNewAvatarButton() { - avatar_button_ = new views::MenuButton(base::string16(), nullptr, false); - avatar_button_->set_id(VIEW_ID_AVATAR_BUTTON); - root_view_->AddChildView(avatar_button_); - } - int CaptionY() const { return delegate_->IsMaximized() ? 0 : views::NonClientFrameView::kFrameShadowThickness; @@ -247,21 +233,14 @@ } void ExpectTabStripAndMinimumSize(bool caption_buttons_on_left) { - int caption_buttons_width = kCaptionButtonsWidth; bool show_caption_buttons = delegate_->ShouldShowCaptionButtons(); bool maximized = delegate_->IsMaximized() || !show_caption_buttons; - if (avatar_button_) { - caption_buttons_width += - avatar_button_->GetPreferredSize().width() + - (maximized ? OpaqueBrowserFrameViewLayout::kCaptionSpacing - : -delegate_->GetNewTabButtonPreferredSize().width()); - } int tabstrip_x = OpaqueBrowserFrameView::GetTabstripPadding(); if (show_caption_buttons && caption_buttons_on_left) { int right_of_close = maximized ? kMaximizedExtraCloseWidth : OpaqueBrowserFrameViewLayout::kFrameBorderThickness; - tabstrip_x += caption_buttons_width + right_of_close; + tabstrip_x += kCaptionButtonsWidth + right_of_close; } else if (!maximized) { tabstrip_x += NonClientBorderThickness(); } @@ -284,7 +263,7 @@ const bool showing_caption_buttons_on_right = show_caption_buttons && !caption_buttons_on_left; const int caption_width = - showing_caption_buttons_on_right ? caption_buttons_width : 0; + showing_caption_buttons_on_right ? kCaptionButtonsWidth : 0; int maximized_spacing = showing_caption_buttons_on_right ? kMaximizedExtraCloseWidth : 0; int restored_spacing = @@ -365,14 +344,6 @@ EXPECT_EQ(icon_size, title_bounds.height()); } - void ExpectAvatar() { - int avatar_width = avatar_button_->GetPreferredSize().width(); - gfx::Rect avatar_bounds(avatar_button_->bounds()); - EXPECT_EQ(CaptionLeft() - avatar_width, avatar_bounds.x()); - EXPECT_EQ(CaptionY(), avatar_bounds.y()); - EXPECT_EQ(avatar_width, avatar_bounds.width()); - EXPECT_EQ(kCaptionButtonHeight, avatar_bounds.height()); - } views::Widget* widget_ = nullptr; views::View* root_view_ = nullptr; @@ -388,14 +359,12 @@ TabIconView* tab_icon_view_ = nullptr; views::Label* window_title_ = nullptr; - views::MenuButton* avatar_button_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(OpaqueBrowserFrameViewLayoutTest); }; TEST_F(OpaqueBrowserFrameViewLayoutTest, BasicWindow) { - // Tests the layout of a default chrome window with no avatars, no window - // titles, and a tabstrip. + // Tests the layout of a default chrome window with a tabstrip and no window + // title. for (int i = 0; i < 2; ++i) { root_view_->Layout(); @@ -467,17 +436,3 @@ delegate_->set_maximized(true); } } - -TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithNewAvatar) { - // Tests a normal tabstrip window with the new style avatar icon. - AddNewAvatarButton(); - - for (int i = 0; i < 2; ++i) { - root_view_->Layout(); - SCOPED_TRACE(i == 0 ? "Window is restored" : "Window is maximized"); - ExpectCaptionButtons(false, 0); - ExpectTabStripAndMinimumSize(false); - ExpectAvatar(); - delegate_->set_maximized(true); - } -}
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc b/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc index 9792013..1857798 100644 --- a/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc +++ b/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc
@@ -22,7 +22,13 @@ text_input_flags_(text_input_flags), caret_bounds_(caret_bounds) {} -RemoteTextInputClient::~RemoteTextInputClient() {} +RemoteTextInputClient::~RemoteTextInputClient() { + while (!pending_callbacks_.empty()) { + auto callback = std::move(pending_callbacks_.front()); + pending_callbacks_.pop(); + std::move(callback).Run(false); + } +} void RemoteTextInputClient::SetTextInputType( ui::TextInputType text_input_type) { @@ -33,6 +39,15 @@ caret_bounds_ = caret_bounds; } +void RemoteTextInputClient::OnDispatchKeyEventPostIMECompleted(bool completed) { + DCHECK(!pending_callbacks_.empty()); + base::OnceCallback<void(bool)> callback = + std::move(pending_callbacks_.front()); + pending_callbacks_.pop(); + if (callback) + std::move(callback).Run(completed); +} + void RemoteTextInputClient::SetCompositionText( const ui::CompositionText& composition) { remote_client_->SetCompositionText(composition); @@ -189,8 +204,10 @@ ui::EventDispatchDetails RemoteTextInputClient::DispatchKeyEventPostIME( ui::KeyEvent* event, base::OnceCallback<void(bool)> ack_callback) { + pending_callbacks_.push(std::move(ack_callback)); remote_client_->DispatchKeyEventPostIME( ui::Event::Clone(*event), - ack_callback ? std::move(ack_callback) : base::DoNothing()); + base::BindOnce(&RemoteTextInputClient::OnDispatchKeyEventPostIMECompleted, + weak_ptr_factory_.GetWeakPtr())); return ui::EventDispatchDetails(); }
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.h b/chrome/browser/ui/views/ime_driver/remote_text_input_client.h index 837d683..579ade1 100644 --- a/chrome/browser/ui/views/ime_driver/remote_text_input_client.h +++ b/chrome/browser/ui/views/ime_driver/remote_text_input_client.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_UI_VIEWS_IME_DRIVER_REMOTE_TEXT_INPUT_CLIENT_H_ #define CHROME_BROWSER_UI_VIEWS_IME_DRIVER_REMOTE_TEXT_INPUT_CLIENT_H_ +#include "base/containers/queue.h" +#include "base/memory/weak_ptr.h" #include "services/ws/public/mojom/ime/ime.mojom.h" #include "ui/base/ime/input_method_delegate.h" #include "ui/base/ime/text_input_client.h" @@ -27,6 +29,9 @@ void SetCaretBounds(const gfx::Rect& caret_bounds); private: + // See |pending_callbacks_| for details. + void OnDispatchKeyEventPostIMECompleted(bool completed); + // ui::TextInputClient: void SetCompositionText(const ui::CompositionText& composition) override; void ConfirmCompositionText() override; @@ -71,8 +76,16 @@ base::i18n::TextDirection text_direction_; int text_input_flags_; gfx::Rect caret_bounds_; - std::deque<std::unique_ptr<base::OnceCallback<void(bool)>>> - pending_callbacks_; + + // Callbacks supplied to DispatchKeyEventPostIME() are added here. When the + // response from the remote side is received + // (OnDispatchKeyEventPostIMECompleted()), the callback is removed and run. + // This is done to ensure if we are destroyed all the callbacks are run. + // This is necessary as the callbacks may have originated from a remote + // client. + base::queue<base::OnceCallback<void(bool)>> pending_callbacks_; + + base::WeakPtrFactory<RemoteTextInputClient> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(RemoteTextInputClient); };
diff --git a/chrome/browser/ui/views/nav_button_provider.h b/chrome/browser/ui/views/nav_button_provider.h index 6cbe9324..50f3f2b 100644 --- a/chrome/browser/ui/views/nav_button_provider.h +++ b/chrome/browser/ui/views/nav_button_provider.h
@@ -53,17 +53,6 @@ // Gets the spacing to be used to separate buttons. virtual int GetInterNavButtonSpacing() const = 0; - - // Creates a background for the profile chooser button. - virtual std::unique_ptr<Background> CreateAvatarButtonBackground( - const views::Button* button) const = 0; - - // Calculates the profile chooser button's size and spacing. - virtual void CalculateCaptionButtonLayout( - const gfx::Size& content_size, - int top_area_height, - gfx::Size* caption_button_size, - gfx::Insets* caption_button_spacing) const = 0; }; } // namespace views
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index 630c326..8e1f29e 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -34,6 +34,7 @@ #include "components/omnibox/browser/omnibox_popup_model.h" #include "components/search_engines/template_url_service.h" #include "components/strings/grit/components_strings.h" +#include "components/toolbar/toolbar_field_trial.h" #include "components/toolbar/toolbar_model.h" #include "content/public/browser/web_contents.h" #include "net/base/escape.h" @@ -631,8 +632,11 @@ } bool OmniboxViewViews::UnapplySteadyStateElisions(UnelisionGesture gesture) { - if (!OmniboxFieldTrial::IsHideSteadyStateUrlSchemeAndSubdomainsEnabled()) + // Early exit if no steady state elision features are enabled. + if (!toolbar::features::IsHideSteadyStateUrlSchemeEnabled() && + !toolbar::features::IsHideSteadyStateUrlTrivialSubdomainsEnabled()) { return false; + } // No need to update the text if the user is already inputting text. if (model()->user_input_in_progress())
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc index c6d8c32a..edbf2f0c 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -25,6 +25,7 @@ #include "components/omnibox/browser/omnibox_edit_model.h" #include "components/omnibox/browser/omnibox_field_trial.h" #include "components/toolbar/test_toolbar_model.h" +#include "components/toolbar/toolbar_field_trial.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/ime/input_method.h" @@ -496,8 +497,10 @@ class OmniboxViewViewsSteadyStateElisionsTest : public OmniboxViewViewsTest { public: OmniboxViewViewsSteadyStateElisionsTest() - : OmniboxViewViewsTest( - {omnibox::kUIExperimentHideSteadyStateUrlSchemeAndSubdomains}) {} + : OmniboxViewViewsTest({ + toolbar::features::kHideSteadyStateUrlScheme, + toolbar::features::kHideSteadyStateUrlTrivialSubdomains, + }) {} protected: explicit OmniboxViewViewsSteadyStateElisionsTest( @@ -897,7 +900,8 @@ public: OmniboxViewViewsSteadyStateElisionsAndQueryInOmniboxTest() : OmniboxViewViewsSteadyStateElisionsTest({ - omnibox::kUIExperimentHideSteadyStateUrlSchemeAndSubdomains, + toolbar::features::kHideSteadyStateUrlScheme, + toolbar::features::kHideSteadyStateUrlTrivialSubdomains, omnibox::kQueryInOmnibox, }) {} };
diff --git a/chrome/browser/ui/views/profiles/avatar_button.cc b/chrome/browser/ui/views/profiles/avatar_button.cc deleted file mode 100644 index e1a0431..0000000 --- a/chrome/browser/ui/views/profiles/avatar_button.cc +++ /dev/null
@@ -1,557 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/profiles/avatar_button.h" - -#include <memory> -#include <utility> - -#include "build/build_config.h" -#include "chrome/app/vector_icons/vector_icons.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/profiles/profiles_state.h" -#include "chrome/browser/signin/account_consistency_mode_manager.h" -#include "chrome/browser/signin/signin_manager_factory.h" -#include "chrome/browser/themes/theme_properties.h" -#include "chrome/browser/themes/theme_service.h" -#include "chrome/browser/themes/theme_service_factory.h" -#include "chrome/browser/ui/views/frame/avatar_button_manager.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/profiles/profile_chooser_view.h" -#include "chrome/grit/generated_resources.h" -#include "chrome/grit/theme_resources.h" -#include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h" -#include "components/signin/core/browser/signin_manager.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/base/theme_provider.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/color_palette.h" -#include "ui/gfx/color_utils.h" -#include "ui/gfx/paint_vector_icon.h" -#include "ui/views/animation/flood_fill_ink_drop_ripple.h" -#include "ui/views/animation/ink_drop_impl.h" -#include "ui/views/animation/ink_drop_mask.h" -#include "ui/views/controls/button/label_button_border.h" - -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#include "chrome/browser/ui/views/frame/minimize_button_metrics_win.h" -#endif - -#if BUILDFLAG(ENABLE_NATIVE_WINDOW_NAV_BUTTONS) -#include "chrome/browser/ui/views/nav_button_provider.h" -#endif - -namespace { - -constexpr int kGenericAvatarIconSize = 16; - -// TODO(emx): Calculate width based on caption button [http://crbug.com/716365] -constexpr int kCondensibleButtonMinWidth = 46; -// TODO(emx): Should this be calculated based on average character width? -constexpr int kCondensibleButtonMaxWidth = 98; - -#if defined(OS_WIN) -constexpr gfx::Insets kBorderInsets(2, 8, 4, 8); - -std::unique_ptr<views::Border> CreateThemedBorder( - const int normal_image_set[], - const int hot_image_set[], - const int pushed_image_set[]) { - std::unique_ptr<views::LabelButtonAssetBorder> border( - new views::LabelButtonAssetBorder(views::Button::STYLE_TEXTBUTTON)); - - border->SetPainter(false, views::Button::STATE_NORMAL, - views::Painter::CreateImageGridPainter(normal_image_set)); - border->SetPainter(false, views::Button::STATE_HOVERED, - views::Painter::CreateImageGridPainter(hot_image_set)); - border->SetPainter(false, views::Button::STATE_PRESSED, - views::Painter::CreateImageGridPainter(pushed_image_set)); - - border->set_insets(kBorderInsets); - - return std::move(border); -} -#endif - -#if defined(OS_MACOSX) -constexpr int kMacButtonHeight = 24; -#endif - -// This class draws the border (and background) of the avatar button for -// "themed" browser windows, i.e. OpaqueBrowserFrameView. Currently it's only -// used on Linux as the shape specifically matches the Linux caption buttons. -// TODO(estade): make this look nice on Windows and use it there as well. -class AvatarButtonThemedBorder : public views::Border { - public: - AvatarButtonThemedBorder() {} - ~AvatarButtonThemedBorder() override {} - - void Paint(const views::View& view, gfx::Canvas* canvas) override { - // Fill the color/background image from the theme. - cc::PaintFlags fill_flags; - fill_flags.setAntiAlias(true); - const ui::ThemeProvider* theme = view.GetThemeProvider(); - fill_flags.setColor( - theme->GetColor(ThemeProperties::COLOR_BUTTON_BACKGROUND)); - SkPath fill_path; - gfx::Rect fill_bounds = view.GetLocalBounds(); - // The fill should overlap the inner stroke but not the outer stroke. But we - // don't inset the top because as it stands, the asset-based window controls - // fill one pixel higher due to how the background masking works out. Not - // matching that is very noticeable. TODO(estade): when the window - // controls use this same code, inset all sides equally. - fill_bounds.Inset(gfx::Insets(0, kStrokeWidth, kStrokeWidth, kStrokeWidth)); - fill_path.addRoundRect(gfx::RectToSkRect(fill_bounds), kCornerRadius, - kCornerRadius); - canvas->DrawPath(fill_path, fill_flags); - fill_flags.setColor(SK_ColorBLACK); - canvas->DrawImageInPath( - *theme->GetImageSkiaNamed(IDR_THEME_WINDOW_CONTROL_BACKGROUND), 0, 0, - fill_path, fill_flags); - - // Paint an outer dark stroke. - cc::PaintFlags stroke_flags; - stroke_flags.setStyle(cc::PaintFlags::kStroke_Style); - // The colors are chosen to match the assets we use for Linux. - stroke_flags.setColor(SkColorSetA(SK_ColorBLACK, 0x2B)); - stroke_flags.setStrokeWidth(kStrokeWidth); - stroke_flags.setAntiAlias(true); - gfx::RectF stroke_bounds(view.GetLocalBounds()); - stroke_bounds.Inset(gfx::InsetsF(0.5f)); - canvas->DrawRoundRect(stroke_bounds, kCornerRadius, stroke_flags); - - // There's a second, light stroke that matches the fill bounds. - stroke_bounds.Inset(gfx::InsetsF(kStrokeWidth)); - stroke_flags.setColor(SkColorSetA(SK_ColorWHITE, 0x3F)); - canvas->DrawRoundRect(stroke_bounds, kCornerRadius, stroke_flags); - } - - gfx::Insets GetInsets() const override { - auto insets = views::LabelButtonAssetBorder::GetDefaultInsetsForStyle( - views::Button::STYLE_TEXTBUTTON); - return kBorderStrokeInsets + - gfx::Insets(0, insets.left(), 0, insets.right()); - } - - gfx::Size GetMinimumSize() const override { - return gfx::Size(GetInsets().width(), GetInsets().height()); - } - - static std::unique_ptr<views::InkDropMask> CreateInkDropMask( - const gfx::Size& size) { - return std::make_unique<views::RoundRectInkDropMask>( - size, kBorderStrokeInsets, kCornerRadius); - } - - private: - static constexpr int kStrokeWidth = 1; - - // Insets between view bounds and the interior of the strokes. - static constexpr gfx::Insets kBorderStrokeInsets{kStrokeWidth * 2}; - - // Corner radius of the roundrect. - static constexpr float kCornerRadius = 1; - - DISALLOW_COPY_AND_ASSIGN(AvatarButtonThemedBorder); -}; - -constexpr int AvatarButtonThemedBorder::kStrokeWidth; -constexpr gfx::Insets AvatarButtonThemedBorder::kBorderStrokeInsets; -constexpr float AvatarButtonThemedBorder::kCornerRadius; - -class AvatarButtonShutdownNotifierFactory - : public BrowserContextKeyedServiceShutdownNotifierFactory { - public: - static AvatarButtonShutdownNotifierFactory* GetInstance() { - return base::Singleton<AvatarButtonShutdownNotifierFactory>::get(); - } - - private: - friend struct base::DefaultSingletonTraits< - AvatarButtonShutdownNotifierFactory>; - - AvatarButtonShutdownNotifierFactory() - : BrowserContextKeyedServiceShutdownNotifierFactory( - "AvatarButtonShutdownNotifierFactory") { - DependsOn(SigninManagerFactory::GetInstance()); - } - ~AvatarButtonShutdownNotifierFactory() override {} - - DISALLOW_COPY_AND_ASSIGN(AvatarButtonShutdownNotifierFactory); -}; - -#if defined(OS_WIN) || defined(OS_MACOSX) -SkColor BaseColorForButton(const ui::ThemeProvider* theme_provider) { - return color_utils::IsDark( - theme_provider->GetColor(ThemeProperties::COLOR_FRAME)) - ? SK_ColorWHITE - : SK_ColorBLACK; -} - -gfx::ImageSkia AvatarIconWithBaseColor(const SkColor base_color) { - const SkColor icon_color = - SkColorSetA(base_color, static_cast<SkAlpha>(0.54 * 0xFF)); - return gfx::CreateVectorIcon(kAccountCircleIcon, kGenericAvatarIconSize, - icon_color); -} -#endif - -} // namespace - -AvatarButton::AvatarButton(views::MenuButtonListener* listener, - AvatarButtonStyle button_style, - Profile* profile, - AvatarButtonManager* manager) - : MenuButton(base::string16(), listener, false), - error_controller_(this, profile), - profile_(profile), - profile_observer_(this), - button_style_(button_style), - widget_observer_(this) { - DCHECK_NE(button_style, AvatarButtonStyle::NONE); -#if BUILDFLAG(ENABLE_NATIVE_WINDOW_NAV_BUTTONS) - views::NavButtonProvider* nav_button_provider = - manager->get_nav_button_provider(); - render_native_nav_buttons_ = nav_button_provider != nullptr; -#endif - set_notify_action(Button::NOTIFY_ON_PRESS); - set_triggerable_event_flags(ui::EF_LEFT_MOUSE_BUTTON | - ui::EF_RIGHT_MOUSE_BUTTON); - set_animate_on_state_change(false); -#if !defined(OS_MACOSX) - SetEnabledTextColors(SK_ColorWHITE); - SetTextSubpixelRenderingEnabled(false); -#endif - SetHorizontalAlignment(gfx::ALIGN_CENTER); - - profile_observer_.Add( - &g_browser_process->profile_manager()->GetProfileAttributesStorage()); - - // The largest text height that fits in the button. If the font list height - // is larger than this, it will be shrunk to match it. - // TODO(noms): Calculate this constant algorithmically from the button's size. - const int kDisplayFontHeight = 16; - label()->SetFontList( - label()->font_list().DeriveWithHeightUpperBound(kDisplayFontHeight)); - - bool apply_ink_drop = ShouldApplyInkDrop(); - if (render_native_nav_buttons_) { -#if BUILDFLAG(ENABLE_NATIVE_WINDOW_NAV_BUTTONS) - SetBackground(nav_button_provider->CreateAvatarButtonBackground(this)); - SetBorder(nullptr); - generic_avatar_ = - gfx::CreateVectorIcon(kProfileSwitcherOutlineIcon, - kGenericAvatarIconSize, gfx::kChromeIconGrey); -#endif - } else if (apply_ink_drop) { - SetInkDropMode(InkDropMode::ON); - SetFocusPainter(nullptr); -#if defined(OS_LINUX) - set_ink_drop_base_color(SK_ColorWHITE); - SetBorder(std::make_unique<AvatarButtonThemedBorder>()); - generic_avatar_ = - gfx::CreateVectorIcon(kProfileSwitcherOutlineIcon, - kGenericAvatarIconSize, gfx::kChromeIconGrey); -#elif defined(OS_WIN) - DCHECK_EQ(AvatarButtonStyle::NATIVE, button_style); - SetBorder(views::CreateEmptyBorder(kBorderInsets)); - } else if (button_style == AvatarButtonStyle::THEMED) { - const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_NORMAL); - const int kHoverImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_HOVER); - const int kPressedImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_PRESSED); - SetButtonAvatar(IDR_AVATAR_THEMED_BUTTON_AVATAR); - SetBorder( - CreateThemedBorder(kNormalImageSet, kHoverImageSet, kPressedImageSet)); - } else if (base::win::GetVersion() < base::win::VERSION_WIN8) { - const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_NORMAL); - const int kHoverImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_HOVER); - const int kPressedImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_PRESSED); - SetButtonAvatar(IDR_AVATAR_GLASS_BUTTON_AVATAR); - SetBorder( - CreateThemedBorder(kNormalImageSet, kHoverImageSet, kPressedImageSet)); - } else { - const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_NORMAL); - const int kHoverImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_HOVER); - const int kPressedImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_PRESSED); - SetButtonAvatar(IDR_AVATAR_NATIVE_BUTTON_AVATAR); - SetBorder( - CreateThemedBorder(kNormalImageSet, kHoverImageSet, kPressedImageSet)); -#endif - } - - profile_shutdown_notifier_ = - AvatarButtonShutdownNotifierFactory::GetInstance() - ->Get(profile_) - ->Subscribe(base::Bind(&AvatarButton::OnProfileShutdown, - base::Unretained(this))); -} - -AvatarButton::~AvatarButton() {} - -void AvatarButton::SetupThemeColorButton() { -#if defined(OS_WIN) - if (IsCondensible()) { - // TODO(bsep): This needs to also be called when the Windows accent color - // updates, but there is currently no signal for that. - const SkColor base_color = BaseColorForButton(GetThemeProvider()); - set_ink_drop_base_color(base_color); - generic_avatar_ = AvatarIconWithBaseColor(base_color); - } -#elif defined(OS_MACOSX) - const SkColor base_color = BaseColorForButton(GetThemeProvider()); - SetEnabledTextColors(base_color); - generic_avatar_ = AvatarIconWithBaseColor(base_color); -#endif -} - -void AvatarButton::OnAvatarButtonPressed(const ui::Event* event) { - views::Widget* bubble_widget = ProfileChooserView::GetCurrentBubbleWidget(); - if (bubble_widget && !widget_observer_.IsObserving(bubble_widget)) { - widget_observer_.Add(bubble_widget); - pressed_lock_ = std::make_unique<PressedLock>( - this, false, ui::LocatedEvent::FromIfValid(event)); - } -} - -void AvatarButton::AddedToWidget() { - SetupThemeColorButton(); - Update(); -} - -void AvatarButton::OnGestureEvent(ui::GestureEvent* event) { - // TODO(wjmaclean): The check for ET_GESTURE_LONG_PRESS is done here since - // no other UI button based on Button appears to handle mouse - // right-click. If other cases are identified, it may make sense to move this - // check to Button. - if (event->type() == ui::ET_GESTURE_LONG_PRESS) - NotifyClick(*event); - else - MenuButton::OnGestureEvent(event); -} - -gfx::Size AvatarButton::GetMinimumSize() const { - if (IsCondensible()) { - // Returns the size of the button when it is atop the tabstrip. Called by - // GlassBrowserFrameView::LayoutProfileSwitcher(). - // TODO(emx): Calculate the height based on the top of the new tab button. - return gfx::Size(kCondensibleButtonMinWidth, 20); - } - - return MenuButton::GetMinimumSize(); -} - -gfx::Size AvatarButton::CalculatePreferredSize() const { - if (render_native_nav_buttons_) - return MenuButton::CalculatePreferredSize(); - - // TODO(estade): Calculate the height instead of hardcoding to 20 for the - // not-condensible case. - gfx::Size size(MenuButton::CalculatePreferredSize().width(), 20); - - if (IsCondensible()) { - // Returns the normal size of the button (when it does not overlap the - // tabstrip). - size.set_width(std::min(std::max(size.width(), kCondensibleButtonMinWidth), - kCondensibleButtonMaxWidth)); -#if defined(OS_WIN) - size.set_height(MinimizeButtonMetrics::GetCaptionButtonHeightInDIPs()); -#endif - } -#if defined(OS_MACOSX) - size.set_height(kMacButtonHeight); -#endif - return size; -} - -std::unique_ptr<views::InkDropMask> AvatarButton::CreateInkDropMask() const { -#if defined(OS_MACOSX) - // On Mac, this looks and behaves like a regular MD button, so we need a hover - // background. - // TODO (lgrey): Determine and set the correct insets. - constexpr int kHoverCornerRadius = 2; - return std::make_unique<views::RoundRectInkDropMask>(size(), gfx::Insets(), - kHoverCornerRadius); -#else - if (button_style_ == AvatarButtonStyle::THEMED) - return AvatarButtonThemedBorder::CreateInkDropMask(size()); - return MenuButton::CreateInkDropMask(); -#endif -} - -std::unique_ptr<views::InkDropHighlight> AvatarButton::CreateInkDropHighlight() - const { - if (button_style_ == AvatarButtonStyle::THEMED) - return MenuButton::CreateInkDropHighlight(); - - auto ink_drop_highlight = std::make_unique<views::InkDropHighlight>( - size(), 0, gfx::RectF(GetLocalBounds()).CenterPoint(), - GetInkDropBaseColor()); - constexpr float kInkDropHighlightOpacity = 0.08f; - ink_drop_highlight->set_visible_opacity(kInkDropHighlightOpacity); - return ink_drop_highlight; -} - -SkColor AvatarButton::GetInkDropBaseColor() const { -#if defined(OS_MACOSX) - return GetThemeProvider()->GetColor( - ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON); -#else - return MenuButton::GetInkDropBaseColor(); -#endif -} - -bool AvatarButton::ShouldEnterPushedState(const ui::Event& event) { - if (ProfileChooserView::IsShowing()) - return false; - - return MenuButton::ShouldEnterPushedState(event); -} - -bool AvatarButton::ShouldUseFloodFillInkDrop() const { - return true; -} - -void AvatarButton::OnAvatarErrorChanged() { - Update(); -} - -void AvatarButton::OnProfileAdded(const base::FilePath& profile_path) { - Update(); -} - -void AvatarButton::OnProfileWasRemoved(const base::FilePath& profile_path, - const base::string16& profile_name) { - // If deleting the active profile, don't bother updating the avatar - // button, as the browser window is being closed anyway. - if (profile_->GetPath() != profile_path) - Update(); -} - -void AvatarButton::OnProfileNameChanged( - const base::FilePath& profile_path, - const base::string16& old_profile_name) { - if (profile_->GetPath() == profile_path) - Update(); -} - -void AvatarButton::OnProfileSupervisedUserIdChanged( - const base::FilePath& profile_path) { - if (profile_->GetPath() == profile_path) - Update(); -} - -void AvatarButton::OnWidgetDestroying(views::Widget* widget) { - pressed_lock_.reset(); - if (render_native_nav_buttons_) - SchedulePaint(); - widget_observer_.Remove(widget); -} - -void AvatarButton::OnProfileShutdown() { - // It looks like in some mysterious cases, the AvatarButton outlives the - // profile (see http://crbug.com/id=579690). The avatar button is owned by - // the browser frame (which is owned by the BrowserWindow), and there is an - // expectation for the UI to be destroyed before the profile is destroyed. - CHECK(false) << "Avatar button must not outlive the profile."; -} - -void AvatarButton::Update() { - // It looks like in some mysterious cases, the AvatarButton outlives the - // profile manager (see http://crbug.com/id=579690). The avatar button is - // owned by the browser frame (which is owned by the BrowserWindow), and - // there is an expectation for the UI to be destroyed before the profile - // manager is destroyed. - CHECK(g_browser_process->profile_manager()) - << "Avatar button must not outlive the profile manager"; - - ProfileAttributesStorage& storage = - g_browser_process->profile_manager()->GetProfileAttributesStorage(); - - // If we have a single local profile, then use the generic avatar - // button instead of the profile name. Never use the generic button if - // the active profile is Guest. - const bool use_generic_button = - !profile_->IsGuestSession() && storage.GetNumberOfProfiles() == 1 && - !SigninManagerFactory::GetForProfile(profile_)->IsAuthenticated(); - - // Always set the accessible name as accessible text, but don't display it if - // is just a generic button. - base::string16 name = - use_generic_button - ? l10n_util::GetStringUTF16(IDS_GENERIC_USER_AVATAR_LABEL) - : profiles::GetAvatarButtonTextForProfile(profile_); - if (use_generic_button) { - SetText(base::string16()); - SetAccessibleName(name); // Must be set after setting text to override it. - } else { - SetText(name); - } - -#if !defined(OS_MACOSX) - // If the button has no text, clear the text shadows to make sure the - // image is centered correctly. macOS doesn't use a shadow. - SetTextShadows( - use_generic_button - ? gfx::ShadowValues() - : gfx::ShadowValues( - 10, gfx::ShadowValue(gfx::Vector2d(), 2.0f, SK_ColorDKGRAY))); -#endif - - if (use_generic_button) { - SetImage(views::Button::STATE_NORMAL, generic_avatar_); - } else if (profile_->IsSyncAllowed() && error_controller_.HasAvatarError()) { - // When DICE is enabled and the error is an auth error, the sync-paused icon - // is shown. - int dummy; - const bool should_show_sync_paused_ui = - AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_) && - sync_ui_util::GetMessagesForAvatarSyncError( - profile_, *SigninManagerFactory::GetForProfile(profile_), &dummy, - &dummy) == sync_ui_util::AUTH_ERROR; - SetImage( - views::Button::STATE_NORMAL, - should_show_sync_paused_ui - ? gfx::CreateVectorIcon(kSyncPausedIcon, 16, gfx::kGoogleBlue500) - : gfx::CreateVectorIcon(kSyncProblemIcon, 16, gfx::kGoogleRed700)); - } else { - SetImage(views::Button::STATE_NORMAL, gfx::ImageSkia()); - } - - // If we are not using the generic button, then reset the spacing between - // the text and the possible authentication error icon. - const int kDefaultImageTextSpacing = 5; - SetImageLabelSpacing(use_generic_button ? 0 : kDefaultImageTextSpacing); - - PreferredSizeChanged(); -} - -void AvatarButton::SetButtonAvatar(int avatar_idr) { - ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); - generic_avatar_ = *rb->GetImageNamed(avatar_idr).ToImageSkia(); -} - -// TODO(estade): all versions of this button should condense. -bool AvatarButton::IsCondensible() const { -#if defined(OS_WIN) - return (base::win::GetVersion() >= base::win::VERSION_WIN10) && - button_style_ == AvatarButtonStyle::NATIVE; -#else - return false; -#endif -} -bool AvatarButton::ShouldApplyInkDrop() const { -#if defined(OS_LINUX) - DCHECK_EQ(AvatarButtonStyle::THEMED, button_style_); - return true; -#elif defined(OS_MACOSX) - return true; -#else - if (render_native_nav_buttons_) - return false; - return IsCondensible(); -#endif -}
diff --git a/chrome/browser/ui/views/profiles/avatar_button.h b/chrome/browser/ui/views/profiles/avatar_button.h deleted file mode 100644 index e1b127198..0000000 --- a/chrome/browser/ui/views/profiles/avatar_button.h +++ /dev/null
@@ -1,119 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_PROFILES_AVATAR_BUTTON_H_ -#define CHROME_BROWSER_UI_VIEWS_PROFILES_AVATAR_BUTTON_H_ - -#include "base/macros.h" -#include "base/scoped_observer.h" -#include "build/build_config.h" -#include "chrome/browser/profiles/profile_attributes_storage.h" -#include "chrome/browser/ui/avatar_button_error_controller.h" -#include "chrome/browser/ui/avatar_button_error_controller_delegate.h" -#include "chrome/browser/ui/views/profiles/avatar_button_style.h" -#include "components/keyed_service/core/keyed_service_shutdown_notifier.h" -#include "ui/views/controls/button/menu_button.h" -#include "ui/views/widget/widget_observer.h" - -class AvatarButtonManager; -class Profile; - -// Base class for avatar buttons that display the active profile's name in the -// caption area. -class AvatarButton : public views::MenuButton, - public AvatarButtonErrorControllerDelegate, - public ProfileAttributesStorage::Observer, - public views::WidgetObserver { - public: - AvatarButton(views::MenuButtonListener* listener, - AvatarButtonStyle button_style, - Profile* profile, - AvatarButtonManager* manager); - ~AvatarButton() override; - - void SetupThemeColorButton(); - - // Called by AvatarButtonManager when the profile chooser menu is - // shown or hidden. - void OnAvatarButtonPressed(const ui::Event* event); - - // views::LabelButton: - void AddedToWidget() override; - void OnGestureEvent(ui::GestureEvent* event) override; - gfx::Size GetMinimumSize() const override; - gfx::Size CalculatePreferredSize() const override; - std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight() - const override; - SkColor GetInkDropBaseColor() const override; - std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override; - - protected: - // views::LabelButton: - bool ShouldEnterPushedState(const ui::Event& event) override; - bool ShouldUseFloodFillInkDrop() const override; - - private: - friend class ProfileChooserViewExtensionsTest; - - // AvatarButtonErrorControllerDelegate: - void OnAvatarErrorChanged() override; - - // ProfileAttributesStorage::Observer: - void OnProfileAdded(const base::FilePath& profile_path) override; - void OnProfileWasRemoved(const base::FilePath& profile_path, - const base::string16& profile_name) override; - void OnProfileNameChanged(const base::FilePath& profile_path, - const base::string16& old_profile_name) override; - void OnProfileSupervisedUserIdChanged( - const base::FilePath& profile_path) override; - - // views::WidgetObserver - void OnWidgetDestroying(views::Widget* widget) override; - - // Called when |profile_| is shutting down. - void OnProfileShutdown(); - - // Called when the profile info cache or signin/sync error has changed, which - // means we might have to update the icon/text of the button. - void Update(); - - // Sets generic_avatar_ to the image with the specified IDR. - void SetButtonAvatar(int avatar_idr); - - // Returns true when the button can get smaller to accomodate a more crowded - // browser frame. - bool IsCondensible() const; - - // Returns true if this button should show an ink drop on hover. - bool ShouldApplyInkDrop() const; - - AvatarButtonErrorController error_controller_; - Profile* profile_; - - // TODO(msarda): Remove |profile_shutdown_notifier_| when - // http://crbug.com/579690 is fixed (it was added to track down the crash in - // that bug). - std::unique_ptr<KeyedServiceShutdownNotifier::Subscription> - profile_shutdown_notifier_; - ScopedObserver<ProfileAttributesStorage, AvatarButton> profile_observer_; - - // The icon displayed instead of the profile name in the local profile case. - // Different assets are used depending on the OS version. - gfx::ImageSkia generic_avatar_; - - AvatarButtonStyle button_style_; - - // Set on desktop Linux to indicate if the avatar button should be - // drawn using the system theme. - bool render_native_nav_buttons_ = false; - - // Shows the button in a pressed state while the bubble is open. - std::unique_ptr<PressedLock> pressed_lock_; - - ScopedObserver<views::Widget, views::WidgetObserver> widget_observer_; - - DISALLOW_COPY_AND_ASSIGN(AvatarButton); -}; - -#endif // CHROME_BROWSER_UI_VIEWS_PROFILES_AVATAR_BUTTON_H_
diff --git a/chrome/browser/ui/views/profiles/avatar_button_style.h b/chrome/browser/ui/views/profiles/avatar_button_style.h deleted file mode 100644 index b8a54e8..0000000 --- a/chrome/browser/ui/views/profiles/avatar_button_style.h +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_PROFILES_AVATAR_BUTTON_STYLE_H_ -#define CHROME_BROWSER_UI_VIEWS_PROFILES_AVATAR_BUTTON_STYLE_H_ - -// Different Avatar button styles that can be applied. -enum class AvatarButtonStyle { - NONE, // No avatar button should be used. - THEMED, // Used in a themed browser window. - NATIVE, // Used in a native aero or metro window. -}; - -#endif // CHROME_BROWSER_UI_VIEWS_PROFILES_AVATAR_BUTTON_STYLE_H_
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc index af44241..125c152 100644 --- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc +++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
@@ -80,7 +80,6 @@ set_triggerable_event_flags(ui::EF_LEFT_MOUSE_BUTTON); set_tag(IDC_SHOW_AVATAR_MENU); - set_id(VIEW_ID_AVATAR_BUTTON); // The avatar should not flip with RTL UI. This does not affect text rendering // and LabelButton image/label placement is still flipped like usual.
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc index c96cdef..c97290a 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -355,11 +355,6 @@ } // static -views::Widget* ProfileChooserView::GetCurrentBubbleWidget() { - return profile_bubble_ ? profile_bubble_->GetWidget() : nullptr; -} - -// static void ProfileChooserView::Hide() { if (IsShowing()) profile_bubble_->GetWidget()->Close();
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.h b/chrome/browser/ui/views/profiles/profile_chooser_view.h index 15aec59..83709a3 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.h +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.h
@@ -66,7 +66,6 @@ Browser* browser, bool is_source_keyboard); static bool IsShowing(); - static views::Widget* GetCurrentBubbleWidget(); static void Hide(); const Browser* browser() const { return browser_; }
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc index 794b87ee..baff434 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc
@@ -30,7 +30,6 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/test/test_browser_dialog.h" #include "chrome/browser/ui/user_manager.h" -#include "chrome/browser/ui/views/profiles/profile_indicator_icon.h" #include "chrome/browser/ui/views/profiles/user_manager_view.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" #include "chrome/common/chrome_paths.h" @@ -181,13 +180,8 @@ void OpenProfileChooserViews(Browser* browser) { BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); - views::View* button; - if (ui::MaterialDesignController::IsRefreshUi()) - button = browser_view->toolbar()->avatar_button(); - else - button = browser_view->frame()->GetNewAvatarMenuButton(); - if (!button) - NOTREACHED() << "Avatar button not found."; + views::View* button = browser_view->toolbar()->avatar_button(); + DCHECK(button); ui::MouseEvent e(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
diff --git a/chrome/browser/ui/views/profiles/profile_indicator_icon.h b/chrome/browser/ui/views/profiles/profile_indicator_icon.h index dbdbe75..4f1ee76 100644 --- a/chrome/browser/ui/views/profiles/profile_indicator_icon.h +++ b/chrome/browser/ui/views/profiles/profile_indicator_icon.h
@@ -18,10 +18,9 @@ // ProfileIndicatorIcon // -// A view used to show either the incognito avatar, or in the case of CrOS multi -// profile mode with teleported windows, a profile avatar. The icon set via -// SetIcon() will be resized and drawn inside a circle if it's too big to fit in -// the frame. +// A view used to show a profile avatar for teleported windows in CrOS. The icon +// set via SetIcon() will be resized and drawn inside a circle if it's too big +// to fit in the frame. class ProfileIndicatorIcon : public views::View { public: ProfileIndicatorIcon();
diff --git a/chrome/browser/ui/views/tabs/alert_indicator.cc b/chrome/browser/ui/views/tabs/alert_indicator.cc new file mode 100644 index 0000000..5681f7b --- /dev/null +++ b/chrome/browser/ui/views/tabs/alert_indicator.cc
@@ -0,0 +1,245 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/tabs/alert_indicator.h" + +#include "chrome/app/vector_icons/vector_icons.h" +#include "chrome/browser/ui/layout_constants.h" +#include "chrome/browser/ui/views/tabs/tab.h" +#include "ui/base/material_design/material_design_controller.h" +#include "ui/gfx/animation/animation_delegate.h" +#include "ui/gfx/animation/multi_animation.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/image/image.h" +#include "ui/gfx/paint_vector_icon.h" + +namespace { + +// Fade-in/out duration for the tab indicator animations. Fade-in is quick to +// immediately notify the user. Fade-out is more gradual, so that the user has +// a chance of finding a tab that has quickly "blipped" on and off. +constexpr int kIndicatorFadeInDurationMs = 200; +constexpr int kIndicatorFadeOutDurationMs = 1000; + +// Interval between frame updates of the tab indicator animations. This is not +// the usual 60 FPS because a trade-off must be made between tab UI animation +// smoothness and media recording/playback performance on low-end hardware. +constexpr base::TimeDelta kIndicatorFrameInterval = + base::TimeDelta::FromMilliseconds(50); // 20 FPS + +// Animation that throbs in (towards 1.0) and out (towards 0.0), and ends in the +// "in" state. +class TabRecordingIndicatorAnimation : public gfx::MultiAnimation { + public: + ~TabRecordingIndicatorAnimation() override {} + + // Overridden to provide alternating "towards in" and "towards out" behavior. + double GetCurrentValue() const override; + + static std::unique_ptr<TabRecordingIndicatorAnimation> Create(); + + private: + TabRecordingIndicatorAnimation(const gfx::MultiAnimation::Parts& parts, + const base::TimeDelta interval) + : MultiAnimation(parts, interval) {} + + // Number of times to "toggle throb" the recording and tab capture indicators + // when they first appear. + static const int kCaptureIndicatorThrobCycles = 5; +}; + +double TabRecordingIndicatorAnimation::GetCurrentValue() const { + return current_part_index() % 2 ? 1.0 - MultiAnimation::GetCurrentValue() + : MultiAnimation::GetCurrentValue(); +} + +std::unique_ptr<TabRecordingIndicatorAnimation> +TabRecordingIndicatorAnimation::Create() { + MultiAnimation::Parts parts; + static_assert( + kCaptureIndicatorThrobCycles % 2 != 0, + "odd number of cycles required so animation finishes in showing state"); + for (int i = 0; i < kCaptureIndicatorThrobCycles; ++i) { + parts.push_back(MultiAnimation::Part( + i % 2 ? kIndicatorFadeOutDurationMs : kIndicatorFadeInDurationMs, + gfx::Tween::EASE_IN)); + } + + std::unique_ptr<TabRecordingIndicatorAnimation> animation( + new TabRecordingIndicatorAnimation(parts, kIndicatorFrameInterval)); + animation->set_continuous(false); + return animation; +} + +// Returns a cached image, to be shown by the alert indicator for the given +// |alert_state|. Uses the global ui::ResourceBundle shared instance. +gfx::Image GetTabAlertIndicatorImage(TabAlertState alert_state, + SkColor button_color) { + const gfx::VectorIcon* icon = nullptr; + int image_width = GetLayoutConstant(TAB_ALERT_INDICATOR_ICON_WIDTH); + const bool is_touch_optimized_ui = + ui::MaterialDesignController::IsTouchOptimizedUiEnabled(); + switch (alert_state) { + case TabAlertState::AUDIO_PLAYING: + icon = is_touch_optimized_ui ? &kTabAudioRoundedIcon : &kTabAudioIcon; + break; + case TabAlertState::AUDIO_MUTING: + icon = is_touch_optimized_ui ? &kTabAudioMutingRoundedIcon + : &kTabAudioMutingIcon; + break; + case TabAlertState::MEDIA_RECORDING: + case TabAlertState::DESKTOP_CAPTURING: + icon = &kTabMediaRecordingIcon; + break; + case TabAlertState::TAB_CAPTURING: + icon = is_touch_optimized_ui ? &kTabMediaCapturingWithArrowIcon + : &kTabMediaCapturingIcon; + // Tab capturing and presenting icon uses a different width compared to + // the other tab alert indicator icons. + image_width = GetLayoutConstant(TAB_ALERT_INDICATOR_CAPTURE_ICON_WIDTH); + break; + case TabAlertState::BLUETOOTH_CONNECTED: + icon = &kTabBluetoothConnectedIcon; + break; + case TabAlertState::USB_CONNECTED: + icon = &kTabUsbConnectedIcon; + break; + case TabAlertState::PIP_PLAYING: + icon = &kPictureInPictureAltIcon; + break; + case TabAlertState::NONE: + return gfx::Image(); + } + DCHECK(icon); + return gfx::Image(gfx::CreateVectorIcon(*icon, image_width, button_color)); +} + +// Returns a non-continuous Animation that performs a fade-in or fade-out +// appropriate for the given |next_alert_state|. This is used by the tab alert +// indicator to alert the user that recording, tab capture, or audio playback +// has started/stopped. +std::unique_ptr<gfx::Animation> CreateTabAlertIndicatorFadeAnimation( + TabAlertState alert_state) { + if (alert_state == TabAlertState::MEDIA_RECORDING || + alert_state == TabAlertState::TAB_CAPTURING || + alert_state == TabAlertState::DESKTOP_CAPTURING) { + return TabRecordingIndicatorAnimation::Create(); + } + + // Note: While it seems silly to use a one-part MultiAnimation, it's the only + // gfx::Animation implementation that lets us control the frame interval. + gfx::MultiAnimation::Parts parts; + const bool is_for_fade_in = (alert_state != TabAlertState::NONE); + parts.push_back(gfx::MultiAnimation::Part( + is_for_fade_in ? kIndicatorFadeInDurationMs : kIndicatorFadeOutDurationMs, + gfx::Tween::EASE_IN)); + std::unique_ptr<gfx::MultiAnimation> animation( + new gfx::MultiAnimation(parts, kIndicatorFrameInterval)); + animation->set_continuous(false); + return std::move(animation); +} + +} // namespace + +class AlertIndicator::FadeAnimationDelegate : public gfx::AnimationDelegate { + public: + explicit FadeAnimationDelegate(AlertIndicator* indicator) + : indicator_(indicator) {} + ~FadeAnimationDelegate() override {} + + private: + // gfx::AnimationDelegate + void AnimationProgressed(const gfx::Animation* animation) override { + indicator_->SchedulePaint(); + } + + void AnimationCanceled(const gfx::Animation* animation) override { + AnimationEnded(animation); + } + + void AnimationEnded(const gfx::Animation* animation) override { + indicator_->showing_alert_state_ = indicator_->alert_state_; + indicator_->SchedulePaint(); + indicator_->parent_tab_->AlertStateChanged(); + } + + AlertIndicator* const indicator_; + + DISALLOW_COPY_AND_ASSIGN(FadeAnimationDelegate); +}; + +AlertIndicator::AlertIndicator(Tab* parent_tab) + : views::ImageView(), + parent_tab_(parent_tab), + alert_state_(TabAlertState::NONE), + showing_alert_state_(TabAlertState::NONE) { + DCHECK(parent_tab_); +} + +AlertIndicator::~AlertIndicator() {} + +void AlertIndicator::OnPaint(gfx::Canvas* canvas) { + double opaqueness = 1.0; + if (fade_animation_) { + opaqueness = fade_animation_->GetCurrentValue(); + if (alert_state_ == TabAlertState::NONE) + opaqueness = 1.0 - opaqueness; // Fading out, not in. + } + if (opaqueness < 1.0) + canvas->SaveLayerAlpha(opaqueness * SK_AlphaOPAQUE); + ImageView::OnPaint(canvas); + if (opaqueness < 1.0) + canvas->Restore(); +} + +void AlertIndicator::TransitionToAlertState(TabAlertState next_state) { + if (next_state == alert_state_) + return; + + TabAlertState previous_alert_showing_state = showing_alert_state_; + + if (next_state != TabAlertState::NONE) + ResetImage(next_state); + + if ((alert_state_ == TabAlertState::AUDIO_PLAYING && + next_state == TabAlertState::AUDIO_MUTING) || + (alert_state_ == TabAlertState::AUDIO_MUTING && + next_state == TabAlertState::AUDIO_PLAYING)) { + // Instant user feedback: No fade animation. + showing_alert_state_ = next_state; + fade_animation_.reset(); + } else { + if (next_state == TabAlertState::NONE) + showing_alert_state_ = alert_state_; // Fading-out indicator. + else + showing_alert_state_ = next_state; // Fading-in to next indicator. + fade_animation_ = CreateTabAlertIndicatorFadeAnimation(next_state); + if (!fade_animation_delegate_) + fade_animation_delegate_.reset(new FadeAnimationDelegate(this)); + fade_animation_->set_delegate(fade_animation_delegate_.get()); + fade_animation_->Start(); + } + + alert_state_ = next_state; + + if (previous_alert_showing_state != showing_alert_state_) + parent_tab_->AlertStateChanged(); +} + +void AlertIndicator::OnParentTabButtonColorChanged() { + if (alert_state_ == TabAlertState::AUDIO_PLAYING || + alert_state_ == TabAlertState::AUDIO_MUTING) + ResetImage(alert_state_); +} + +views::View* AlertIndicator::GetTooltipHandlerForPoint( + const gfx::Point& point) { + return nullptr; // Tab (the parent View) provides the tooltip. +} + +void AlertIndicator::ResetImage(TabAlertState state) { + SkColor color = parent_tab_->GetAlertIndicatorColor(state); + gfx::ImageSkia image = GetTabAlertIndicatorImage(state, color).AsImageSkia(); + SetImage(&image); +}
diff --git a/chrome/browser/ui/views/tabs/alert_indicator.h b/chrome/browser/ui/views/tabs/alert_indicator.h new file mode 100644 index 0000000..6327526f --- /dev/null +++ b/chrome/browser/ui/views/tabs/alert_indicator.h
@@ -0,0 +1,64 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_TABS_ALERT_INDICATOR_H_ +#define CHROME_BROWSER_UI_VIEWS_TABS_ALERT_INDICATOR_H_ + +#include <memory> + +#include "base/macros.h" +#include "chrome/browser/ui/tabs/tab_utils.h" +#include "ui/views/controls/image_view.h" + +class Tab; + +namespace gfx { +class Animation; +class AnimationDelegate; +} // namespace gfx + +// This is an ImageView subclass that serves as an indicator of various states, +// primarily media playing/recording, but also device connectivity. It is meant +// to only be used as a child view of Tab. +class AlertIndicator : public views::ImageView { + public: + explicit AlertIndicator(Tab* parent_tab); + ~AlertIndicator() override; + + // views::ImageView: + void OnPaint(gfx::Canvas* canvas) override; + + // Returns the current TabAlertState except, while the indicator image is + // fading out, returns the prior TabAlertState. + TabAlertState showing_alert_state() const { return showing_alert_state_; } + + // Calls ResetImages() and starts fade animations as appropriate. + void TransitionToAlertState(TabAlertState next_state); + + // Called when the parent tab's button color changes. Determines whether + // ResetImages() needs to be called. + void OnParentTabButtonColorChanged(); + + protected: + View* GetTooltipHandlerForPoint(const gfx::Point& point) override; + + private: + friend class AlertIndicatorTest; + friend class TabTest; + class FadeAnimationDelegate; + + // Resets the images to display on the button to reflect |state| and the + // parent tab's button color. Should be called when either of these changes. + void ResetImage(TabAlertState state); + + Tab* const parent_tab_; + TabAlertState alert_state_; + std::unique_ptr<gfx::AnimationDelegate> fade_animation_delegate_; + std::unique_ptr<gfx::Animation> fade_animation_; + TabAlertState showing_alert_state_; + + DISALLOW_COPY_AND_ASSIGN(AlertIndicator); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_TABS_ALERT_INDICATOR_H_
diff --git a/chrome/browser/ui/views/tabs/alert_indicator_button.cc b/chrome/browser/ui/views/tabs/alert_indicator_button.cc deleted file mode 100644 index d74b43dd..0000000 --- a/chrome/browser/ui/views/tabs/alert_indicator_button.cc +++ /dev/null
@@ -1,319 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/tabs/alert_indicator_button.h" - -#include "base/macros.h" -#include "base/metrics/user_metrics.h" -#include "base/timer/timer.h" -#include "chrome/browser/ui/views/tabs/tab.h" -#include "chrome/browser/ui/views/tabs/tab_controller.h" -#include "chrome/browser/ui/views/tabs/tab_renderer_data.h" -#include "ui/gfx/animation/animation_delegate.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/image/image.h" -#include "ui/views/metrics.h" - -using base::UserMetricsAction; - -namespace { - -// The minimum required click-to-select area of an inactive Tab before allowing -// the click-to-mute functionality to be enabled. These values are in terms of -// some percentage of the AlertIndicatorButton's width. See comments in -// UpdateEnabledForMuteToggle(). -const int kMinMouseSelectableAreaPercent = 250; -const int kMinGestureSelectableAreaPercent = 400; - -// Returns true if either Shift or Control are being held down. In this case, -// mouse events are delegated to the Tab, to perform tab selection in the tab -// strip instead. -bool IsShiftOrControlDown(const ui::Event& event) { - return (event.flags() & (ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)) != 0; -} - -} // namespace - -const char AlertIndicatorButton::kViewClassName[] = "AlertIndicatorButton"; - -class AlertIndicatorButton::FadeAnimationDelegate - : public gfx::AnimationDelegate { - public: - explicit FadeAnimationDelegate(AlertIndicatorButton* button) - : button_(button) {} - ~FadeAnimationDelegate() override {} - - private: - // gfx::AnimationDelegate - void AnimationProgressed(const gfx::Animation* animation) override { - button_->SchedulePaint(); - } - - void AnimationCanceled(const gfx::Animation* animation) override { - AnimationEnded(animation); - } - - void AnimationEnded(const gfx::Animation* animation) override { - button_->showing_alert_state_ = button_->alert_state_; - button_->SchedulePaint(); - button_->parent_tab_->AlertStateChanged(); - } - - AlertIndicatorButton* const button_; - - DISALLOW_COPY_AND_ASSIGN(FadeAnimationDelegate); -}; - -AlertIndicatorButton::AlertIndicatorButton(Tab* parent_tab) - : views::ImageButton(nullptr), - parent_tab_(parent_tab), - alert_state_(TabAlertState::NONE), - showing_alert_state_(TabAlertState::NONE) { - DCHECK(parent_tab_); - SetEventTargeter( - std::unique_ptr<views::ViewTargeter>(new views::ViewTargeter(this))); - - // Disable animations of hover state change, to be consistent with the - // behavior of the tab close button. - set_animate_on_state_change(false); -} - -AlertIndicatorButton::~AlertIndicatorButton() {} - -void AlertIndicatorButton::TransitionToAlertState(TabAlertState next_state) { - if (next_state == alert_state_) - return; - - TabAlertState previous_alert_showing_state = showing_alert_state_; - - if (next_state != TabAlertState::NONE) - ResetImages(next_state); - - if ((alert_state_ == TabAlertState::AUDIO_PLAYING && - next_state == TabAlertState::AUDIO_MUTING) || - (alert_state_ == TabAlertState::AUDIO_MUTING && - next_state == TabAlertState::AUDIO_PLAYING)) { - // Instant user feedback: No fade animation. - showing_alert_state_ = next_state; - fade_animation_.reset(); - } else { - if (next_state == TabAlertState::NONE) - showing_alert_state_ = alert_state_; // Fading-out indicator. - else - showing_alert_state_ = next_state; // Fading-in to next indicator. - fade_animation_ = chrome::CreateTabAlertIndicatorFadeAnimation(next_state); - if (!fade_animation_delegate_) - fade_animation_delegate_.reset(new FadeAnimationDelegate(this)); - fade_animation_->set_delegate(fade_animation_delegate_.get()); - fade_animation_->Start(); - } - - alert_state_ = next_state; - - if (previous_alert_showing_state != showing_alert_state_) - parent_tab_->AlertStateChanged(); - - UpdateEnabledForMuteToggle(); -} - -void AlertIndicatorButton::UpdateEnabledForMuteToggle() { - const bool was_enabled = enabled(); - - bool enable = chrome::AreExperimentalMuteControlsEnabled() && - (alert_state_ == TabAlertState::AUDIO_PLAYING || - alert_state_ == TabAlertState::AUDIO_MUTING); - - // If the tab is not the currently-active tab, make sure it is wide enough - // before enabling click-to-mute. This ensures that there is enough click - // area for the user to activate a tab rather than unintentionally muting it. - // Note that IsTriggerableEvent() is also overridden to provide an even wider - // requirement for tap gestures. - if (enable && !GetTab()->IsActive()) { - const int required_width = width() * kMinMouseSelectableAreaPercent / 100; - enable = (GetTab()->GetWidthOfLargestSelectableRegion() >= required_width); - } - - if (enable == was_enabled) - return; - - SetEnabled(enable); - - // If the button has become enabled, check whether the mouse is currently - // hovering. If it is, enter a dormant period where extra user clicks are - // prevented from having an effect (i.e., before the user has realized the - // button has become enabled underneath their cursor). - if (!was_enabled && state() == views::Button::STATE_HOVERED) - EnterDormantPeriod(); - else if (!enabled()) - ExitDormantPeriod(); -} - -void AlertIndicatorButton::OnParentTabButtonColorChanged() { - if (alert_state_ == TabAlertState::AUDIO_PLAYING || - alert_state_ == TabAlertState::AUDIO_MUTING) - ResetImages(alert_state_); -} - -const char* AlertIndicatorButton::GetClassName() const { - return kViewClassName; -} - -views::View* AlertIndicatorButton::GetTooltipHandlerForPoint( - const gfx::Point& point) { - return nullptr; // Tab (the parent View) provides the tooltip. -} - -bool AlertIndicatorButton::OnMousePressed(const ui::MouseEvent& event) { - // Do not handle this mouse event when anything but the left mouse button is - // pressed or when any modifier keys are being held down. Instead, the Tab - // should react (e.g., middle-click for close, right-click for context menu). - if (!event.IsOnlyLeftMouseButton() || IsShiftOrControlDown(event)) { - if (state() != views::Button::STATE_DISABLED) - SetState(views::Button::STATE_NORMAL); // Turn off hover. - return false; // Event to be handled by Tab. - } - return ImageButton::OnMousePressed(event); -} - -bool AlertIndicatorButton::OnMouseDragged(const ui::MouseEvent& event) { - const ButtonState previous_state = state(); - const bool ret = ImageButton::OnMouseDragged(event); - if (previous_state != views::Button::STATE_NORMAL && - state() == views::Button::STATE_NORMAL) - base::RecordAction(UserMetricsAction("AlertIndicatorButton_Dragged")); - return ret; -} - -void AlertIndicatorButton::OnMouseEntered(const ui::MouseEvent& event) { - // If any modifier keys are being held down, do not turn on hover. - if (state() != views::Button::STATE_DISABLED && IsShiftOrControlDown(event)) { - SetState(views::Button::STATE_NORMAL); - return; - } - ImageButton::OnMouseEntered(event); -} - -void AlertIndicatorButton::OnMouseExited(const ui::MouseEvent& event) { - ExitDormantPeriod(); - ImageButton::OnMouseExited(event); -} - -void AlertIndicatorButton::OnMouseMoved(const ui::MouseEvent& event) { - // If any modifier keys are being held down, turn off hover. - if (state() != views::Button::STATE_DISABLED && IsShiftOrControlDown(event)) { - SetState(views::Button::STATE_NORMAL); - return; - } - ImageButton::OnMouseMoved(event); -} - -void AlertIndicatorButton::OnBoundsChanged(const gfx::Rect& previous_bounds) { - UpdateEnabledForMuteToggle(); -} - -bool AlertIndicatorButton::DoesIntersectRect(const views::View* target, - const gfx::Rect& rect) const { - // If this button is not enabled, Tab (the parent View) handles all mouse - // events. - return enabled() && - views::ViewTargeterDelegate::DoesIntersectRect(target, rect); -} - -void AlertIndicatorButton::NotifyClick(const ui::Event& event) { - EnterDormantPeriod(); - - // Call TransitionToAlertState() to change the image, providing the user with - // instant feedback. In the very unlikely event that the mute toggle fails, - // TransitionToAlertState() will be called again, via another code path, to - // set the image to be consistent with the final outcome. - if (alert_state_ == TabAlertState::AUDIO_PLAYING) { - base::RecordAction(UserMetricsAction("AlertIndicatorButton_Mute")); - TransitionToAlertState(TabAlertState::AUDIO_MUTING); - } else { - DCHECK(alert_state_ == TabAlertState::AUDIO_MUTING); - base::RecordAction(UserMetricsAction("AlertIndicatorButton_Unmute")); - TransitionToAlertState(TabAlertState::AUDIO_PLAYING); - } - - GetTab()->controller()->ToggleTabAudioMute(GetTab()); -} - -bool AlertIndicatorButton::IsTriggerableEvent(const ui::Event& event) { - if (is_dormant()) - return false; - - // For mouse events, only trigger on the left mouse button and when no - // modifier keys are being held down. - if (event.IsMouseEvent() && - (!static_cast<const ui::MouseEvent*>(&event)->IsOnlyLeftMouseButton() || - IsShiftOrControlDown(event))) - return false; - - // For gesture events on an inactive tab, require an even wider tab before - // click-to-mute can be triggered. See comments in - // UpdateEnabledForMuteToggle(). - if (event.IsGestureEvent() && !GetTab()->IsActive()) { - const int required_width = width() * kMinGestureSelectableAreaPercent / 100; - if (GetTab()->GetWidthOfLargestSelectableRegion() < required_width) - return false; - } - - return views::ImageButton::IsTriggerableEvent(event); -} - -void AlertIndicatorButton::PaintButtonContents(gfx::Canvas* canvas) { - double opaqueness = 1.0; - if (fade_animation_) { - opaqueness = fade_animation_->GetCurrentValue(); - if (alert_state_ == TabAlertState::NONE) - opaqueness = 1.0 - opaqueness; // Fading out, not in. - } else if (is_dormant()) { - opaqueness = 0.5; - } - if (opaqueness < 1.0) - canvas->SaveLayerAlpha(opaqueness * SK_AlphaOPAQUE); - ImageButton::PaintButtonContents(canvas); - if (opaqueness < 1.0) - canvas->Restore(); -} - -gfx::ImageSkia AlertIndicatorButton::GetImageToPaint() { - if (is_dormant()) - return views::ImageButton::images_[views::Button::STATE_NORMAL]; - return views::ImageButton::GetImageToPaint(); -} - -Tab* AlertIndicatorButton::GetTab() const { - DCHECK_EQ(static_cast<views::View*>(parent_tab_), parent()); - return parent_tab_; -} - -void AlertIndicatorButton::ResetImages(TabAlertState state) { - SkColor color = parent_tab_->GetAlertIndicatorColor(state); - gfx::ImageSkia indicator_image = - chrome::GetTabAlertIndicatorImage(state, color).AsImageSkia(); - SetImage(views::Button::STATE_NORMAL, &indicator_image); - SetImage(views::Button::STATE_DISABLED, &indicator_image); - gfx::ImageSkia affordance_image = - chrome::GetTabAlertIndicatorAffordanceImage(state, color).AsImageSkia(); - SetImage(views::Button::STATE_HOVERED, &affordance_image); - SetImage(views::Button::STATE_PRESSED, &affordance_image); -} - -void AlertIndicatorButton::EnterDormantPeriod() { - wake_up_timer_.reset(new base::OneShotTimer()); - wake_up_timer_->Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(views::GetDoubleClickInterval()), - this, - &AlertIndicatorButton::ExitDormantPeriod); - SchedulePaint(); -} - -void AlertIndicatorButton::ExitDormantPeriod() { - const bool needs_repaint = is_dormant(); - wake_up_timer_.reset(); - if (needs_repaint) - SchedulePaint(); -}
diff --git a/chrome/browser/ui/views/tabs/alert_indicator_button.h b/chrome/browser/ui/views/tabs/alert_indicator_button.h deleted file mode 100644 index 7e8e258..0000000 --- a/chrome/browser/ui/views/tabs/alert_indicator_button.h +++ /dev/null
@@ -1,125 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_TABS_ALERT_INDICATOR_BUTTON_H_ -#define CHROME_BROWSER_UI_VIEWS_TABS_ALERT_INDICATOR_BUTTON_H_ - -#include <memory> - -#include "base/macros.h" -#include "chrome/browser/ui/tabs/tab_utils.h" -#include "ui/views/controls/button/image_button.h" -#include "ui/views/view_targeter_delegate.h" - -class Tab; - -namespace base { -class OneShotTimer; -} - -namespace gfx { -class Animation; -class AnimationDelegate; -} - -// This is an ImageButton subclass that serves as both the alert indicator icon -// (audio, tab capture, etc.), and as a mute button. It is meant to only be -// used as a child view of Tab. -// -// When the indicator is transitioned to the audio playing or muting state, the -// button functionality is enabled and begins handling mouse events. Otherwise, -// this view behaves like an image and all mouse events will be handled by the -// Tab (its parent View). -class AlertIndicatorButton : public views::ImageButton, - public views::ViewTargeterDelegate { - public: - // The AlertIndicatorButton's class name. - static const char kViewClassName[]; - - explicit AlertIndicatorButton(Tab* parent_tab); - ~AlertIndicatorButton() override; - - // Returns the current TabAlertState except, while the indicator image is - // fading out, returns the prior TabAlertState. - TabAlertState showing_alert_state() const { return showing_alert_state_; } - - // Calls ResetImages(), starts fade animations, and activates/deactivates - // button functionality as appropriate. - void TransitionToAlertState(TabAlertState next_state); - - // Determines whether the AlertIndicatorButton will be clickable for toggling - // muting. This should be called whenever the active/inactive state of a tab - // has changed. Internally, TransitionToAlertState() and OnBoundsChanged() - // calls this when the TabAlertState or the bounds have changed. - void UpdateEnabledForMuteToggle(); - - // Called when the parent tab's button color changes. Determines whether - // ResetImages() needs to be called. - void OnParentTabButtonColorChanged(); - - protected: - // views::View: - const char* GetClassName() const override; - View* GetTooltipHandlerForPoint(const gfx::Point& point) override; - bool OnMousePressed(const ui::MouseEvent& event) override; - bool OnMouseDragged(const ui::MouseEvent& event) override; - void OnMouseEntered(const ui::MouseEvent& event) override; - void OnMouseExited(const ui::MouseEvent& event) override; - void OnMouseMoved(const ui::MouseEvent& event) override; - void OnBoundsChanged(const gfx::Rect& previous_bounds) override; - - // views::ViewTargeterDelegate - bool DoesIntersectRect(const View* target, - const gfx::Rect& rect) const override; - - // views::Button: - void NotifyClick(const ui::Event& event) override; - - // views::Button: - bool IsTriggerableEvent(const ui::Event& event) override; - void PaintButtonContents(gfx::Canvas* canvas) override; - - // views::ImageButton: - gfx::ImageSkia GetImageToPaint() override; - - private: - friend class AlertIndicatorButtonTest; - friend class TabTest; - class FadeAnimationDelegate; - - // Returns the tab (parent view) of this AlertIndicatorButton. - Tab* GetTab() const; - - // Resets the images to display on the button to reflect |state| and the - // parent tab's button color. Should be called when either of these changes. - void ResetImages(TabAlertState state); - - // Enters a temporary "dormant period" where this AlertIndicatorButton will - // not trigger on clicks. The user is provided a visual affordance during - // this period. Sets a timer to call ExitDormantPeriod(). - void EnterDormantPeriod(); - - // Leaves the "dormant period," allowing clicks to once again trigger an - // enabled AlertIndicatorButton. - void ExitDormantPeriod(); - - bool is_dormant() const { return !!wake_up_timer_; } - - Tab* const parent_tab_; - - TabAlertState alert_state_; - - // Alert indicator fade-in/out animation (i.e., only on show/hide, not a - // continuous animation). - std::unique_ptr<gfx::AnimationDelegate> fade_animation_delegate_; - std::unique_ptr<gfx::Animation> fade_animation_; - TabAlertState showing_alert_state_; - - // Created on-demand, this fires to exit the "dormant period." - std::unique_ptr<base::OneShotTimer> wake_up_timer_; - - DISALLOW_COPY_AND_ASSIGN(AlertIndicatorButton); -}; - -#endif // CHROME_BROWSER_UI_VIEWS_TABS_ALERT_INDICATOR_BUTTON_H_
diff --git a/chrome/browser/ui/views/tabs/alert_indicator_button_unittest.cc b/chrome/browser/ui/views/tabs/alert_indicator_button_unittest.cc deleted file mode 100644 index e7bc548..0000000 --- a/chrome/browser/ui/views/tabs/alert_indicator_button_unittest.cc +++ /dev/null
@@ -1,114 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/tabs/alert_indicator_button.h" - -#include <utility> - -#include "chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h" -#include "chrome/browser/ui/views/tabs/tab.h" -#include "chrome/browser/ui/views/tabs/tab_strip.h" -#include "chrome/test/views/chrome_views_test_base.h" -#include "testing/gtest/include/gtest/gtest.h" - -class AlertIndicatorButtonTest : public ChromeViewsTestBase { - public: - AlertIndicatorButtonTest() {} - - ~AlertIndicatorButtonTest() override {} - - void SetUp() override { - ChromeViewsTestBase::SetUp(); - - controller_ = new FakeBaseTabStripController; - tab_strip_ = new TabStrip(std::unique_ptr<TabStripController>(controller_)); - controller_->set_tab_strip(tab_strip_); - // The tab strip must be added to the view hierarchy for it to create the - // buttons. - parent_.AddChildView(tab_strip_); - parent_.set_owned_by_client(); - - widget_.reset(new views::Widget); - views::Widget::InitParams init_params = - CreateParams(views::Widget::InitParams::TYPE_POPUP); - init_params.ownership = - views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - init_params.bounds = gfx::Rect(0, 0, 400, 400); - widget_->Init(init_params); - widget_->SetContentsView(&parent_); - } - - void TearDown() override { - // All windows need to be closed before tear down. - widget_.reset(); - - ChromeViewsTestBase::TearDown(); - } - - protected: - bool showing_close_button(Tab* tab) const { - return tab->showing_close_button_; - } - bool showing_icon(Tab* tab) const { return tab->showing_icon_; } - bool showing_alert_indicator(Tab* tab) const { - return tab->showing_alert_indicator_; - } - - void StopAnimation(Tab* tab) { - ASSERT_TRUE(tab->alert_indicator_button_->fade_animation_); - tab->alert_indicator_button_->fade_animation_->Stop(); - } - - // Owned by TabStrip. - FakeBaseTabStripController* controller_ = nullptr; - // Owns |tab_strip_|. - views::View parent_; - TabStrip* tab_strip_ = nullptr; - std::unique_ptr<views::Widget> widget_; - - private: - DISALLOW_COPY_AND_ASSIGN(AlertIndicatorButtonTest); -}; - -// This test verifies that the tab has its icon state updated when the alert -// animation fade-out finishes. -TEST_F(AlertIndicatorButtonTest, ButtonUpdateOnAudioStateAnimation) { - controller_->AddPinnedTab(0, false); - controller_->AddTab(1, true); - Tab* media_tab = tab_strip_->tab_at(0); - - // Pinned inactive tab only has an icon. - EXPECT_TRUE(showing_icon(media_tab)); - EXPECT_FALSE(showing_alert_indicator(media_tab)); - EXPECT_FALSE(showing_close_button(media_tab)); - - TabRendererData start_media; - start_media.alert_state = TabAlertState::AUDIO_PLAYING; - start_media.pinned = media_tab->data().pinned; - media_tab->SetData(std::move(start_media)); - - // When audio starts, pinned inactive tab shows indicator. - EXPECT_FALSE(showing_icon(media_tab)); - EXPECT_TRUE(showing_alert_indicator(media_tab)); - EXPECT_FALSE(showing_close_button(media_tab)); - - TabRendererData stop_media; - stop_media.alert_state = TabAlertState::NONE; - stop_media.pinned = media_tab->data().pinned; - media_tab->SetData(std::move(stop_media)); - - // When audio ends, pinned inactive tab fades out indicator. - EXPECT_FALSE(showing_icon(media_tab)); - EXPECT_TRUE(showing_alert_indicator(media_tab)); - EXPECT_FALSE(showing_close_button(media_tab)); - - // Rather than flakily waiting some unknown number of seconds for the fade - // out animation to stop, reach out and stop the fade animation directly, - // to make sure that it updates the tab appropriately when it's done. - StopAnimation(media_tab); - - EXPECT_TRUE(showing_icon(media_tab)); - EXPECT_FALSE(showing_alert_indicator(media_tab)); - EXPECT_FALSE(showing_close_button(media_tab)); -}
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index f0ede22..2861ac9a 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -271,12 +271,6 @@ TabStripModel::CLOSE_CREATE_HISTORICAL_TAB); } -void BrowserTabStripController::ToggleTabAudioMute(int model_index) { - content::WebContents* const contents = model_->GetWebContentsAt(model_index); - chrome::SetTabAudioMuted(contents, !contents->IsAudioMuted(), - TabMutedReason::AUDIO_INDICATOR, std::string()); -} - void BrowserTabStripController::ShowContextMenuForTab( Tab* tab, const gfx::Point& p,
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h index 6d79dc4..0093f8b 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
@@ -60,7 +60,6 @@ void ToggleSelected(int model_index) override; void AddSelectionFromAnchorTo(int model_index) override; void CloseTab(int model_index, CloseTabSource source) override; - void ToggleTabAudioMute(int model_index) override; void ShowContextMenuForTab(Tab* tab, const gfx::Point& p, ui::MenuSourceType source_type) override;
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc index 178eaeb..d8249d6 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
@@ -95,9 +95,6 @@ RemoveTab(index); } -void FakeBaseTabStripController::ToggleTabAudioMute(int index) { -} - void FakeBaseTabStripController::ShowContextMenuForTab( Tab* tab, const gfx::Point& p,
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h index df1cd01..171c85d 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
@@ -36,7 +36,6 @@ void ToggleSelected(int index) override; void AddSelectionFromAnchorTo(int index) override; void CloseTab(int index, CloseTabSource source) override; - void ToggleTabAudioMute(int index) override; void ShowContextMenuForTab(Tab* tab, const gfx::Point& p, ui::MenuSourceType source_type) override;
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index 9fb2bad..5d06416 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -28,7 +28,7 @@ #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/tabs/alert_indicator_button.h" +#include "chrome/browser/ui/views/tabs/alert_indicator.h" #include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" #include "chrome/browser/ui/views/tabs/tab_close_button.h" #include "chrome/browser/ui/views/tabs/tab_controller.h" @@ -401,8 +401,8 @@ icon_ = new TabIcon; AddChildView(icon_); - alert_indicator_button_ = new AlertIndicatorButton(this); - AddChildView(alert_indicator_button_); + alert_indicator_ = new AlertIndicator(this); + AddChildView(alert_indicator_); // Unretained is safe here because this class outlives its close button, and // the controller outlives this Tab. @@ -455,10 +455,8 @@ } void Tab::ButtonPressed(views::Button* sender, const ui::Event& event) { - if (!alert_indicator_button_ || !alert_indicator_button_->visible()) + if (!alert_indicator_ || !alert_indicator_->visible()) base::RecordAction(UserMetricsAction("CloseTab_NoAlertIndicator")); - else if (alert_indicator_button_->enabled()) - base::RecordAction(UserMetricsAction("CloseTab_MuteToggleAvailable")); else if (data_.alert_state == TabAlertState::AUDIO_PLAYING) base::RecordAction(UserMetricsAction("CloseTab_AudioIndicator")); else @@ -579,15 +577,15 @@ : kAlertIndicatorCloseButtonPadding; } } - const gfx::Size image_size = alert_indicator_button_->GetPreferredSize(); + const gfx::Size image_size = alert_indicator_->GetPreferredSize(); gfx::Rect bounds( std::max(contents_rect.x(), right - image_size.width()), contents_rect.y() + Center(contents_rect.height(), image_size.height()), image_size.width(), image_size.height()); MaybeAdjustLeftForPinnedTab(&bounds, bounds.width()); - alert_indicator_button_->SetBoundsRect(bounds); + alert_indicator_->SetBoundsRect(bounds); } - alert_indicator_button_->SetVisible(showing_alert_indicator_); + alert_indicator_->SetVisible(showing_alert_indicator_); // Size the title to fill the remaining width and use all available height. bool show_title = ShouldRenderAsNormalTab(); @@ -604,7 +602,7 @@ } int title_right = contents_rect.right(); if (showing_alert_indicator_) { - title_right = alert_indicator_button_->x() - after_title_padding; + title_right = alert_indicator_->x() - after_title_padding; } else if (showing_close_button_) { // Allow the title to overlay the close button's empty border padding. title_right = close_x - after_title_padding; @@ -723,11 +721,6 @@ // selection. Reset it now to handle the case where multiple tabs were // selected. controller_->SelectTab(this); - - if (alert_indicator_button_ && alert_indicator_button_->visible() && - alert_indicator_button_->bounds().Contains(event.location())) { - base::RecordAction(UserMetricsAction("TabAlertIndicator_Clicked")); - } } } @@ -795,7 +788,7 @@ bool Tab::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const { // Note: Anything that affects the tooltip text should be accounted for when // calling TooltipTextChanged() from Tab::SetData(). - *tooltip = chrome::AssembleTabTooltipText(data_.title, data_.alert_state); + *tooltip = GetTooltipText(data_.title, data_.alert_state); return !tooltip->empty(); } @@ -906,7 +899,6 @@ void Tab::ActiveStateChanged() { UpdateTabIconNeedsAttentionBlocked(); UpdateForegroundColors(); - alert_indicator_button_->UpdateEnabledForMuteToggle(); Layout(); } @@ -955,7 +947,7 @@ title_->SetText(title); if (data_.alert_state != old.alert_state) - alert_indicator_button_->TransitionToAlertState(data_.alert_state); + alert_indicator_->TransitionToAlertState(data_.alert_state); if (old.pinned != data_.pinned) showing_alert_indicator_ = false; @@ -1006,18 +998,6 @@ : controller_->GetStrokeThickness(); } -int Tab::GetWidthOfLargestSelectableRegion() const { - // Assume the entire region to the left of the alert indicator and/or close - // buttons is available for click-to-select. If neither are visible, the - // entire tab region is available. - const int indicator_left = alert_indicator_button_->visible() - ? alert_indicator_button_->x() - : width(); - const int close_button_left = - close_button_->visible() ? close_button_->x() : width(); - return std::min(indicator_left, close_button_left); -} - gfx::Insets Tab::GetContentsInsets() const { const float stroke_thickness = GetStrokeThickness(); return GetContentsHorizontalInsets() + @@ -1061,6 +1041,14 @@ } // static +int Tab::GetTabSeparatorHeight() { + constexpr int kTabSeparatorHeight = 20; + constexpr int kTabSeparatorTouchHeight = 24; + return MD::IsTouchOptimizedUiEnabled() ? kTabSeparatorTouchHeight + : kTabSeparatorHeight; +} + +// static int Tab::GetCornerRadius() { return ChromeLayoutProvider::Get()->GetCornerRadiusMetric( views::EMPHASIS_HIGH); @@ -1078,11 +1066,52 @@ } // static -int Tab::GetTabSeparatorHeight() { - constexpr int kTabSeparatorHeight = 20; - constexpr int kTabSeparatorTouchHeight = 24; - return MD::IsTouchOptimizedUiEnabled() ? kTabSeparatorTouchHeight - : kTabSeparatorHeight; +base::string16 Tab::GetTooltipText(const base::string16& title, + TabAlertState alert_state) { + if (alert_state == TabAlertState::NONE) + return title; + + base::string16 result = title; + if (!result.empty()) + result.append(1, '\n'); + switch (alert_state) { + case TabAlertState::AUDIO_PLAYING: + result.append( + l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_ALERT_STATE_AUDIO_PLAYING)); + break; + case TabAlertState::AUDIO_MUTING: + result.append( + l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_ALERT_STATE_AUDIO_MUTING)); + break; + case TabAlertState::MEDIA_RECORDING: + result.append(l10n_util::GetStringUTF16( + IDS_TOOLTIP_TAB_ALERT_STATE_MEDIA_RECORDING)); + break; + case TabAlertState::TAB_CAPTURING: + result.append( + l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_ALERT_STATE_TAB_CAPTURING)); + break; + case TabAlertState::BLUETOOTH_CONNECTED: + result.append(l10n_util::GetStringUTF16( + IDS_TOOLTIP_TAB_ALERT_STATE_BLUETOOTH_CONNECTED)); + break; + case TabAlertState::USB_CONNECTED: + result.append( + l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_ALERT_STATE_USB_CONNECTED)); + break; + case TabAlertState::PIP_PLAYING: + result.append( + l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_ALERT_STATE_PIP_PLAYING)); + break; + case TabAlertState::DESKTOP_CAPTURING: + result.append(l10n_util::GetStringUTF16( + IDS_TOOLTIP_TAB_ALERT_STATE_DESKTOP_CAPTURING)); + break; + case TabAlertState::NONE: + NOTREACHED(); + break; + } + return result; } void Tab::MaybeAdjustLeftForPinnedTab(gfx::Rect* bounds, @@ -1356,8 +1385,8 @@ const bool has_favicon = data().show_icon; const bool has_alert_icon = - (alert_indicator_button_ ? alert_indicator_button_->showing_alert_state() - : data().alert_state) != TabAlertState::NONE; + (alert_indicator_ ? alert_indicator_->showing_alert_state() + : data().alert_state) != TabAlertState::NONE; if (data().pinned) { // When the tab is pinned, we can show one of the two icons; the alert icon @@ -1372,8 +1401,7 @@ const bool is_touch_optimized = MD::IsTouchOptimizedUiEnabled(); const int favicon_width = gfx::kFaviconSize; - const int alert_icon_width = - alert_indicator_button_->GetPreferredSize().width(); + const int alert_icon_width = alert_indicator_->GetPreferredSize().width(); // In case of touch optimized UI, the close button has an extra padding on the // left that needs to be considered. const int close_button_width = @@ -1647,7 +1675,7 @@ if (button_color_ != generated_icon_color) { button_color_ = generated_icon_color; - alert_indicator_button_->OnParentTabButtonColorChanged(); + alert_indicator_->OnParentTabButtonColorChanged(); } }
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h index c124d80..45db570 100644 --- a/chrome/browser/ui/views/tabs/tab.h +++ b/chrome/browser/ui/views/tabs/tab.h
@@ -25,7 +25,7 @@ #include "ui/views/masked_targeter_delegate.h" #include "ui/views/view.h" -class AlertIndicatorButton; +class AlertIndicator; class TabCloseButton; class TabController; class TabIcon; @@ -183,10 +183,6 @@ // Returns the thickness of the stroke drawn below the tab. float GetBottomStrokeThickness(bool should_paint_as_active = false) const; - // Returns the width of the largest part of the tab that is available for the - // user to click to select/activate the tab. - int GetWidthOfLargestSelectableRegion() const; - // Returns the insets to use for laying out tab contents. gfx::Insets GetContentsInsets() const; @@ -222,8 +218,14 @@ // Returns the overlap between adjacent tabs. static int GetOverlap(); + // Returns the text to show in a tab's tooltip: The contents |title|, followed + // by a break, followed by a localized string describing the |alert_state|. + // Exposed publicly for tests. + static base::string16 GetTooltipText(const base::string16& title, + TabAlertState alert_state); + private: - friend class AlertIndicatorButtonTest; + friend class AlertIndicatorTest; friend class TabTest; friend class TabStripTest; FRIEND_TEST_ALL_PREFIXES(TabStripTest, TabCloseButtonVisibilityWhenStacked); @@ -327,7 +329,7 @@ scoped_refptr<gfx::AnimationContainer> animation_container_; TabIcon* icon_ = nullptr; - AlertIndicatorButton* alert_indicator_button_ = nullptr; + AlertIndicator* alert_indicator_ = nullptr; TabCloseButton* close_button_ = nullptr; views::Label* title_;
diff --git a/chrome/browser/ui/views/tabs/tab_controller.h b/chrome/browser/ui/views/tabs/tab_controller.h index 617588c..593834995 100644 --- a/chrome/browser/ui/views/tabs/tab_controller.h +++ b/chrome/browser/ui/views/tabs/tab_controller.h
@@ -67,9 +67,6 @@ // Closes the tab. virtual void CloseTab(Tab* tab, CloseTabSource source) = 0; - // Toggles whether tab-wide audio muting is active. - virtual void ToggleTabAudioMute(Tab* tab) = 0; - // Shows a context menu for the tab at the specified point in screen coords. virtual void ShowContextMenuForTab(Tab* tab, const gfx::Point& p,
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 3234b745..f815caf 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -14,9 +14,11 @@ #include "base/compiler_specific.h" #include "base/containers/adapters.h" +#include "base/containers/flat_map.h" #include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" +#include "base/no_destructor.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -91,8 +93,6 @@ int g_drop_indicator_width = 0; int g_drop_indicator_height = 0; -TabSizeInfo* g_tab_size_info = nullptr; - // Animation delegate used for any automatic tab movement. Hides the tab if it // is not fully visible within the tabstrip area, to prevent overflow clipping. class TabAnimationDelegate : public gfx::AnimationDelegate { @@ -154,6 +154,14 @@ AnimationEnded(animation); } +base::flat_map<ui::MaterialDesignController::Mode, TabSizeInfo>* +GetTabSizeInfoMap() { + static base::NoDestructor< + base::flat_map<ui::MaterialDesignController::Mode, TabSizeInfo>> + tab_size_info_map; + return tab_size_info_map.get(); +} + // If |dest| contains the point |point_in_source| the event handler from |dest| // is returned. Otherwise returns null. views::View* ConvertPointToViewAndGetEventHandler( @@ -185,17 +193,19 @@ } const TabSizeInfo& GetTabSizeInfo() { - if (g_tab_size_info) - return *g_tab_size_info; + TabSizeInfo& tab_size_info = + (*GetTabSizeInfoMap())[ui::MaterialDesignController::GetMode()]; - g_tab_size_info = new TabSizeInfo; - g_tab_size_info->pinned_tab_width = Tab::GetPinnedWidth(); - g_tab_size_info->min_active_width = Tab::GetMinimumActiveWidth(); - g_tab_size_info->min_inactive_width = Tab::GetMinimumInactiveWidth(); - g_tab_size_info->standard_size = + if (!tab_size_info.standard_size.IsEmpty()) + return tab_size_info; + + tab_size_info.pinned_tab_width = Tab::GetPinnedWidth(); + tab_size_info.min_active_width = Tab::GetMinimumActiveWidth(); + tab_size_info.min_inactive_width = Tab::GetMinimumInactiveWidth(); + tab_size_info.standard_size = gfx::Size(Tab::GetStandardWidth(), GetLayoutConstant(TAB_HEIGHT)); - g_tab_size_info->tab_overlap = Tab::GetOverlap(); - return *g_tab_size_info; + tab_size_info.tab_overlap = Tab::GetOverlap(); + return tab_size_info; } int GetStackableTabWidth() { @@ -885,12 +895,6 @@ controller_->CloseTab(model_index, source); } -void TabStrip::ToggleTabAudioMute(Tab* tab) { - int model_index = GetModelIndexOfTab(tab); - if (IsValidModelIndex(model_index)) - controller_->ToggleTabAudioMute(model_index); -} - void TabStrip::ShowContextMenuForTab(Tab* tab, const gfx::Point& p, ui::MenuSourceType source_type) { @@ -2304,10 +2308,7 @@ // static void TabStrip::ResetTabSizeInfoForTesting() { - if (g_tab_size_info) { - delete g_tab_size_info; - g_tab_size_info = nullptr; - } + *GetTabSizeInfoMap() = {}; } Tab* TabStrip::FindTabForEvent(const gfx::Point& point) {
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index eec04e4..5bdf393 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -221,7 +221,6 @@ void ToggleSelected(Tab* tab) override; void AddSelectionFromAnchorTo(Tab* tab) override; void CloseTab(Tab* tab, CloseTabSource source) override; - void ToggleTabAudioMute(Tab* tab) override; void ShowContextMenuForTab(Tab* tab, const gfx::Point& p, ui::MenuSourceType source_type) override;
diff --git a/chrome/browser/ui/views/tabs/tab_strip_controller.h b/chrome/browser/ui/views/tabs/tab_strip_controller.h index f8ac993d..16407c8 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/tab_strip_controller.h
@@ -66,9 +66,6 @@ // Closes the tab at the specified index in the model. virtual void CloseTab(int index, CloseTabSource source) = 0; - // Toggles audio muting for the tab at the specified index in the model. - virtual void ToggleTabAudioMute(int index) = 0; - // Shows a context menu for the tab at the specified point in screen coords. virtual void ShowContextMenuForTab(Tab* tab, const gfx::Point& p,
diff --git a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc index 63a5865e..093d24a 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
@@ -25,6 +25,7 @@ #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/path.h" #include "ui/gfx/skia_util.h" +#include "ui/views/controls/label.h" #include "ui/views/view.h" #include "ui/views/view_targeter.h" #include "ui/views/widget/widget.h"
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc index 444e3f9..0e6048b 100644 --- a/chrome/browser/ui/views/tabs/tab_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -10,10 +10,12 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/tabs/tab_utils.h" -#include "chrome/browser/ui/views/tabs/alert_indicator_button.h" +#include "chrome/browser/ui/views/tabs/alert_indicator.h" +#include "chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h" #include "chrome/browser/ui/views/tabs/tab_close_button.h" #include "chrome/browser/ui/views/tabs/tab_controller.h" #include "chrome/browser/ui/views/tabs/tab_icon.h" +#include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/grit/theme_resources.h" #include "chrome/test/views/chrome_views_test_base.h" #include "testing/gtest/include/gtest/gtest.h" @@ -52,7 +54,6 @@ void ToggleSelected(Tab* tab) override {} void AddSelectionFromAnchorTo(Tab* tab) override {} void CloseTab(Tab* tab, CloseTabSource source) override {} - void ToggleTabAudioMute(Tab* tab) override {} void ShowContextMenuForTab(Tab* tab, const gfx::Point& p, ui::MenuSourceType source_type) override {} @@ -144,8 +145,8 @@ static views::Label* GetTabTitle(const Tab& tab) { return tab.title_; } - static views::ImageButton* GetAlertIndicator(const Tab& tab) { - return tab.alert_indicator_button_; + static views::ImageView* GetAlertIndicator(const Tab& tab) { + return tab.alert_indicator_; } static views::ImageButton* GetCloseButton(const Tab& tab) { @@ -286,10 +287,10 @@ static void StopFadeAnimationIfNecessary(const Tab& tab) { // Stop the fade animation directly instead of waiting an unknown number of // seconds. - if (gfx::Animation* fade_animation = - tab.alert_indicator_button_->fade_animation_.get()) { + gfx::Animation* fade_animation = + tab.alert_indicator_->fade_animation_.get(); + if (fade_animation) fade_animation->Stop(); - } } protected: @@ -302,16 +303,74 @@ private: static gfx::Rect GetAlertIndicatorBounds(const Tab& tab) { - if (!tab.alert_indicator_button_) { + if (!tab.alert_indicator_) { ADD_FAILURE(); return gfx::Rect(); } - return tab.alert_indicator_button_->bounds(); + return tab.alert_indicator_->bounds(); } std::string original_locale_; }; +class AlertIndicatorTest : public ChromeViewsTestBase { + public: + AlertIndicatorTest() {} + ~AlertIndicatorTest() override {} + + void SetUp() override { + ChromeViewsTestBase::SetUp(); + + controller_ = new FakeBaseTabStripController; + tab_strip_ = new TabStrip(std::unique_ptr<TabStripController>(controller_)); + controller_->set_tab_strip(tab_strip_); + // The tab strip must be added to the view hierarchy for it to create the + // buttons. + parent_.AddChildView(tab_strip_); + parent_.set_owned_by_client(); + + widget_.reset(new views::Widget); + views::Widget::InitParams init_params = + CreateParams(views::Widget::InitParams::TYPE_POPUP); + init_params.ownership = + views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + init_params.bounds = gfx::Rect(0, 0, 400, 400); + widget_->Init(init_params); + widget_->SetContentsView(&parent_); + } + + void TearDown() override { + // All windows need to be closed before tear down. + widget_.reset(); + + ChromeViewsTestBase::TearDown(); + } + + protected: + bool showing_close_button(Tab* tab) const { + return tab->showing_close_button_; + } + bool showing_icon(Tab* tab) const { return tab->showing_icon_; } + bool showing_alert_indicator(Tab* tab) const { + return tab->showing_alert_indicator_; + } + + void StopAnimation(Tab* tab) { + ASSERT_TRUE(tab->alert_indicator_->fade_animation_); + tab->alert_indicator_->fade_animation_->Stop(); + } + + // Owned by TabStrip. + FakeBaseTabStripController* controller_ = nullptr; + // Owns |tab_strip_|. + views::View parent_; + TabStrip* tab_strip_ = nullptr; + std::unique_ptr<views::Widget> widget_; + + private: + DISALLOW_COPY_AND_ASSIGN(AlertIndicatorTest); +}; + TEST_F(TabTest, HitTestTopPixel) { Widget widget; InitWidget(&widget); @@ -397,8 +456,7 @@ } // Regression test for http://crbug.com/420313: Confirms that any child Views of -// Tab do not attempt to provide their own tooltip behavior/text. It also tests -// that Tab provides the expected tooltip text (according to tab_utils). +// Tab do not attempt to provide their own tooltip behavior/text. TEST_F(TabTest, TooltipProvidedByTab) { Widget widget; InitWidget(&widget); @@ -424,10 +482,11 @@ for (int i = 0; i < 2; ++i) { data.alert_state = (i == 0 ? TabAlertState::NONE : TabAlertState::AUDIO_PLAYING); - SCOPED_TRACE(::testing::Message() - << "Tab with alert indicator state " - << static_cast<uint8_t>(data.alert_state)); + SCOPED_TRACE(::testing::Message() << "Tab with alert indicator state " + << static_cast<int>(data.alert_state)); tab.SetData(data); + const base::string16 expected_tooltip = + Tab::GetTooltipText(data.title, data.alert_state); for (int j = 0; j < tab.child_count(); ++j) { views::View& child = *tab.child_at(j); @@ -443,10 +502,8 @@ const gfx::Point mouse_hover_point = midpoint + child.GetMirroredPosition().OffsetFromOrigin(); base::string16 tooltip; - EXPECT_TRUE(static_cast<views::View&>(tab).GetTooltipText( - mouse_hover_point, &tooltip)); - EXPECT_EQ(chrome::AssembleTabTooltipText(data.title, data.alert_state), - tooltip); + EXPECT_TRUE(tab.GetTooltipText(mouse_hover_point, &tooltip)); + EXPECT_EQ(expected_tooltip, tooltip); } } } @@ -752,3 +809,45 @@ } } } + +// This test verifies that the tab has its icon state updated when the alert +// animation fade-out finishes. +TEST_F(AlertIndicatorTest, ShowsAndHidesAlertIndicator) { + controller_->AddPinnedTab(0, false); + controller_->AddTab(1, true); + Tab* media_tab = tab_strip_->tab_at(0); + + // Pinned inactive tab only has an icon. + EXPECT_TRUE(showing_icon(media_tab)); + EXPECT_FALSE(showing_alert_indicator(media_tab)); + EXPECT_FALSE(showing_close_button(media_tab)); + + TabRendererData start_media; + start_media.alert_state = TabAlertState::AUDIO_PLAYING; + start_media.pinned = media_tab->data().pinned; + media_tab->SetData(std::move(start_media)); + + // When audio starts, pinned inactive tab shows indicator. + EXPECT_FALSE(showing_icon(media_tab)); + EXPECT_TRUE(showing_alert_indicator(media_tab)); + EXPECT_FALSE(showing_close_button(media_tab)); + + TabRendererData stop_media; + stop_media.alert_state = TabAlertState::NONE; + stop_media.pinned = media_tab->data().pinned; + media_tab->SetData(std::move(stop_media)); + + // When audio ends, pinned inactive tab fades out indicator. + EXPECT_FALSE(showing_icon(media_tab)); + EXPECT_TRUE(showing_alert_indicator(media_tab)); + EXPECT_FALSE(showing_close_button(media_tab)); + + // Rather than flakily waiting some unknown number of seconds for the fade + // out animation to stop, reach out and stop the fade animation directly, + // to make sure that it updates the tab appropriately when it's done. + StopAnimation(media_tab); + + EXPECT_TRUE(showing_icon(media_tab)); + EXPECT_FALSE(showing_alert_indicator(media_tab)); + EXPECT_FALSE(showing_close_button(media_tab)); +}
diff --git a/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc b/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc index b303bb6..91e0c60 100644 --- a/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc +++ b/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
@@ -54,8 +54,7 @@ bool BrowserAppMenuButton::g_open_app_immediately_for_testing = false; BrowserAppMenuButton::BrowserAppMenuButton(ToolbarView* toolbar_view) - : AppMenuButton(toolbar_view), - toolbar_view_(toolbar_view) { + : AppMenuButton(toolbar_view), toolbar_view_(toolbar_view) { SetInkDropMode(InkDropMode::ON); SetFocusPainter(nullptr); SetHorizontalAlignment(gfx::ALIGN_CENTER); @@ -73,6 +72,8 @@ const int radii = ChromeLayoutProvider::Get()->GetCornerRadiusMetric( views::EMPHASIS_MAXIMUM, gfx::Size(size, size)); set_ink_drop_corner_radii(radii, radii); + + md_observer_.Add(ui::MaterialDesignController::GetInstance()); } BrowserAppMenuButton::~BrowserAppMenuButton() {} @@ -241,6 +242,11 @@ InvalidateLayout(); } +void BrowserAppMenuButton::OnMdModeChanged() { + UpdateIcon(false); + PreferredSizeChanged(); +} + void BrowserAppMenuButton::AnimateIconIfPossible(bool with_delay) { if (!new_icon_ || !should_use_new_icon_ || severity_ == AppMenuIconController::Severity::NONE) {
diff --git a/chrome/browser/ui/views/toolbar/browser_app_menu_button.h b/chrome/browser/ui/views/toolbar/browser_app_menu_button.h index 052fe35..7370ba0 100644 --- a/chrome/browser/ui/views/toolbar/browser_app_menu_button.h +++ b/chrome/browser/ui/views/toolbar/browser_app_menu_button.h
@@ -14,6 +14,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #include "chrome/browser/ui/toolbar/app_menu_icon_controller.h" #include "chrome/browser/ui/views/frame/app_menu_button.h" +#include "ui/base/material_design/material_design_controller_observer.h" #include "ui/views/controls/animated_icon_view.h" #include "ui/views/view.h" @@ -26,7 +27,8 @@ // The app menu button in the main browser window (as opposed to hosted app // windows, which is implemented in HostedAppMenuButton). class BrowserAppMenuButton : public AppMenuButton, - public TabStripModelObserver { + public TabStripModelObserver, + public ui::MaterialDesignControllerObserver { public: explicit BrowserAppMenuButton(ToolbarView* toolbar_view); ~BrowserAppMenuButton() override; @@ -70,6 +72,10 @@ // Used only in testing. static bool g_open_app_immediately_for_testing; + protected: + // ui::MaterialDesignControllerObserver: + void OnMdModeChanged() override; + private: // Animates the icon if possible. The icon will not animate if the severity // level is none, |animation_| is nullptr or |should_use_new_icon_| is false. @@ -123,6 +129,10 @@ // a maximized state to extend to the full window width. int margin_trailing_ = 0; + ScopedObserver<ui::MaterialDesignController, + ui::MaterialDesignControllerObserver> + md_observer_{this}; + // Used to spawn weak pointers for delayed tasks to open the overflow menu. base::WeakPtrFactory<BrowserAppMenuButton> weak_factory_{this};
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.cc b/chrome/browser/ui/views/toolbar/toolbar_button.cc index 398bbc0..91b751444 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_button.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_button.cc
@@ -38,7 +38,6 @@ model_(std::move(model)), tab_strip_model_(tab_strip_model), trigger_menu_on_long_press_(trigger_menu_on_long_press), - layout_insets_(GetLayoutInsets(TOOLBAR_BUTTON)), show_menu_factory_(this) { set_has_ink_drop_action_on_click(true); set_context_menu_controller(this); @@ -92,7 +91,9 @@ SetEnabledTextColors(*highlight_color_); } - gfx::Insets insets = layout_insets_ + gfx::Insets(0, leading_margin_, 0, 0); + gfx::Insets insets = (layout_insets_ ? layout_insets_.value() + : GetLayoutInsets(TOOLBAR_BUTTON)) + + gfx::Insets(0, leading_margin_, 0, 0); if (highlight_color_) insets += gfx::Insets(0, ink_drop_large_corner_radius() / 2, 0, 0);
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.h b/chrome/browser/ui/views/toolbar/toolbar_button.h index d02bb15e..1075824 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_button.h +++ b/chrome/browser/ui/views/toolbar/toolbar_button.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#include "base/optional.h" #include "ui/gfx/geometry/point.h" #include "ui/views/context_menu_controller.h" #include "ui/views/controls/button/button.h" @@ -136,11 +137,11 @@ // to extend to the full window width. int leading_margin_ = 0; - // Base layout insets (normally GetLayoutInsets(TOOLBAR_BUTTON)) that are used - // for the button. This is overridable as AvatarToolbarButton uses smaller - // insets to accomodate for a larger avatar avatar icon. |leading_margin_| and - // |ink_drop_large_corner_radius()| are also used to calculate final insets. - gfx::Insets layout_insets_; + // Base layout insets that are used for the button. This is overridable as + // AvatarToolbarButton uses smaller insets to accommodate for a larger avatar + // avatar icon. |leading_margin_| and |ink_drop_large_corner_radius()| are + // also used to calculate final insets. + base::Optional<gfx::Insets> layout_insets_; // A highlight color is used to signal error states. When set this color is // used as a base for background, text and ink drops. When not set, uses the
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index 2e209be..149ff54 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -127,6 +127,7 @@ chrome::AddCommandObserver(browser_, IDC_LOAD_NEW_TAB_PAGE, this); UpgradeDetector::GetInstance()->AddObserver(this); + md_observer_.Add(ui::MaterialDesignController::GetInstance()); } ToolbarView::~ToolbarView() { @@ -680,6 +681,12 @@ location_bar_->SetFullKeyboardAcessibilityMode(false); } +// ui::MaterialDesignControllerObserver: +void ToolbarView::OnMdModeChanged() { + LoadImages(); + PreferredSizeChanged(); +} + //////////////////////////////////////////////////////////////////////////////// // ToolbarView, private:
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h index ae7beb3..a5d60a07 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/observer_list.h" +#include "base/scoped_observer.h" #include "chrome/browser/command_observer.h" #include "chrome/browser/ui/toolbar/app_menu_icon_controller.h" #include "chrome/browser/ui/toolbar/back_forward_menu_model.h" @@ -23,6 +24,7 @@ #include "components/translate/core/browser/translate_step.h" #include "components/translate/core/common/translate_errors.h" #include "ui/base/accelerators/accelerator.h" +#include "ui/base/material_design/material_design_controller_observer.h" #include "ui/views/accessible_pane_view.h" #include "ui/views/controls/button/menu_button.h" #include "ui/views/controls/button/menu_button_listener.h" @@ -62,7 +64,8 @@ public AppMenuIconController::Delegate, public UpgradeObserver, public ToolbarButtonProvider, - public BrowserRootView::DropTarget { + public BrowserRootView::DropTarget, + public ui::MaterialDesignControllerObserver { public: // The view class name. static const char kViewClassName[]; @@ -175,6 +178,9 @@ bool SetPaneFocusAndFocusDefault() override; void RemovePaneFocus() override; + // ui::MaterialDesignControllerObserver: + void OnMdModeChanged() override; + bool is_display_mode_normal() const { return display_mode_ == DISPLAYMODE_NORMAL; } @@ -250,6 +256,10 @@ // The display mode used when laying out the toolbar. const DisplayMode display_mode_; + ScopedObserver<ui::MaterialDesignController, + ui::MaterialDesignControllerObserver> + md_observer_{this}; + // Whether this toolbar has been initialized. bool initialized_ = false;
diff --git a/chrome/browser/ui/views_mode_controller.cc b/chrome/browser/ui/views_mode_controller.cc index 9c641bd9..ffe958a 100644 --- a/chrome/browser/ui/views_mode_controller.cc +++ b/chrome/browser/ui/views_mode_controller.cc
@@ -12,7 +12,9 @@ namespace views_mode_controller { bool IsViewsBrowserCocoa() { - return features::IsViewsBrowserCocoa(); + // TODO(https://crbug.com/832676): Delete all code guarded on this function + // returning true and then remove this function. + return false; } } // namespace views_mode_controller
diff --git a/chrome/browser/ui/views_mode_controller.h b/chrome/browser/ui/views_mode_controller.h index 9c3fadd..f9833125 100644 --- a/chrome/browser/ui/views_mode_controller.h +++ b/chrome/browser/ui/views_mode_controller.h
@@ -14,7 +14,9 @@ namespace views_mode_controller { // Returns whether a Views-capable browser build should use the Cocoa browser -// UI. +// UI. Always returns false. +// TODO(https://crbug.com/832676): Delete all code guarded on this function +// returning true and then remove this function. bool IsViewsBrowserCocoa(); } // namespace views_mode_controller
diff --git a/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_localized_strings_provider.cc b/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_localized_strings_provider.cc index edd2778..e80a1cf 100644 --- a/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_localized_strings_provider.cc
@@ -37,6 +37,7 @@ int id; } const kLocalizedStringsWithoutPlaceholders[] = { {"accept", IDS_MULTIDEVICE_SETUP_ACCEPT_LABEL}, + {"back", IDS_MULTIDEVICE_SETUP_BACK_LABEL}, {"cancel", IDS_CANCEL}, {"done", IDS_DONE}, {"passwordPageHeader", IDS_MULTIDEVICE_SETUP_PASSWORD_PAGE_HEADER},
diff --git a/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc b/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc index e600e7e7..90123fb 100644 --- a/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc +++ b/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/ui/webui/quota_internals/quota_internals_types.h" #include "content/public/browser/browser_task_traits.h" #include "net/base/url_util.h" +#include "url/origin.h" using blink::mojom::StorageType; using content::BrowserThread; @@ -138,12 +139,11 @@ std::vector<PerOriginStorageInfo> origin_info; origin_info.reserve(entries.size()); - typedef OriginInfoTableEntries::const_iterator iterator; - for (iterator itr(entries.begin()); itr != entries.end(); ++itr) { - PerOriginStorageInfo info(itr->origin, itr->type); - info.set_used_count(itr->used_count); - info.set_last_access_time(itr->last_access_time); - info.set_last_modified_time(itr->last_modified_time); + for (const auto& entry : entries) { + PerOriginStorageInfo info(entry.origin.GetURL(), entry.type); + info.set_used_count(entry.used_count); + info.set_last_access_time(entry.last_access_time); + info.set_last_modified_time(entry.last_modified_time); origin_info.push_back(info); } @@ -175,7 +175,7 @@ void QuotaInternalsProxy::RequestPerOriginInfo(StorageType type) { DCHECK(quota_manager_.get()); - std::set<GURL> origins; + std::set<url::Origin> origins; quota_manager_->GetCachedOrigins(type, &origins); std::vector<PerOriginStorageInfo> origin_info; @@ -184,13 +184,12 @@ std::set<std::string> hosts; std::vector<PerHostStorageInfo> host_info; - for (std::set<GURL>::iterator itr(origins.begin()); - itr != origins.end(); ++itr) { - PerOriginStorageInfo info(*itr, type); - info.set_in_use(quota_manager_->IsOriginInUse(*itr)); + for (const url::Origin& origin : origins) { + PerOriginStorageInfo info(origin.GetURL(), type); + info.set_in_use(quota_manager_->IsOriginInUse(origin)); origin_info.push_back(info); - std::string host(net::GetHostOrSpecFromURL(*itr)); + std::string host(net::GetHostOrSpecFromURL(origin.GetURL())); if (hosts.insert(host).second) { PerHostStorageInfo info(host, type); host_info.push_back(info);
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 bc10d2f..1dcaf52 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
@@ -2648,8 +2648,6 @@ {"multideviceForgetDevice", IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE}, {"multideviceForgetDeviceSummary", IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE_EXPLANATION}, - {"multideviceForgetDeviceDialogHeading", - IDS_SETTINGS_MULTIDEVICE_FORGET_DEVICE_DIALOG_HEADING}, {"multideviceForgetDeviceDialogMessage", IDS_SETTINGS_MULTIDEVICE_FORGET_DEVICE_DIALOG_MESSAGE}, };
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc index 4559bd51..c0a3873a 100644 --- a/chrome/browser/ui/webui/settings/people_handler.cc +++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -65,6 +65,7 @@ #include "chrome/browser/chromeos/login/quick_unlock/pin_backend.h" #include "components/signin/core/browser/signin_manager_base.h" #else +#include "chrome/browser/signin/signin_util.h" #include "chrome/browser/ui/user_manager.h" #include "chrome/browser/ui/webui/profile_helper.h" #include "components/signin/core/browser/signin_manager.h" @@ -775,11 +776,12 @@ bool delete_profile = false; args->GetBoolean(0, &delete_profile); - SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile_); - if (signin_manager->IsSignoutProhibited()) { + if (!signin_util::IsUserSignoutAllowedForProfile(profile_)) { // If the user cannot signout, the profile must be destroyed. DCHECK(delete_profile); } else { + SigninManager* signin_manager = + SigninManagerFactory::GetForProfile(profile_); if (signin_manager->IsAuthenticated()) { if (GetSyncService()) ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS); @@ -945,7 +947,7 @@ DCHECK(signin); #if !defined(OS_CHROMEOS) // Signout is not allowed if the user has policy (crbug.com/172204). - if (SigninManagerFactory::GetForProfile(profile_)->IsSignoutProhibited()) { + if (!signin_util::IsUserSignoutAllowedForProfile(profile_)) { std::string username = signin->GetAuthenticatedAccountInfo().email; // If there is no one logged in or if the profile name is empty then the
diff --git a/chrome/browser/ui/webui/welcome/nux/BUILD.gn b/chrome/browser/ui/webui/welcome/nux/BUILD.gn index 02ddf2c..5aae5db 100644 --- a/chrome/browser/ui/webui/welcome/nux/BUILD.gn +++ b/chrome/browser/ui/webui/welcome/nux/BUILD.gn
@@ -19,6 +19,7 @@ deps = [ "//chrome/app:generated_resources", + "//chrome/browser:resources", "//components/resources", "//components/strings", "//components/variations", @@ -52,6 +53,7 @@ deps = [ "//chrome/app:generated_resources", + "//chrome/browser:resources", "//components/bookmarks/browser", "//components/bookmarks/common", "//components/favicon/core", @@ -79,6 +81,7 @@ deps = [ "//chrome/app:generated_resources", + "//chrome/browser:resources", "//components/bookmarks/browser", "//components/bookmarks/common", "//components/favicon/core",
diff --git a/chrome/browser/ui/webui/welcome/nux/email_handler.cc b/chrome/browser/ui/webui/welcome/nux/email_handler.cc index e8aa7fa1..5e45b1e1 100644 --- a/chrome/browser/ui/webui/welcome/nux/email_handler.cc +++ b/chrome/browser/ui/webui/welcome/nux/email_handler.cc
@@ -10,6 +10,7 @@ #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/webui/welcome/nux/show_promo_delegate.h" +#include "chrome/grit/browser_resources.h" #include "chrome/grit/generated_resources.h" #include "components/bookmarks/common/bookmark_pref_names.h" #include "components/favicon/core/favicon_service.h"
diff --git a/chrome/browser/ui/webui/welcome/nux/google_apps_handler.cc b/chrome/browser/ui/webui/welcome/nux/google_apps_handler.cc index cbb480f..4fa31afc 100644 --- a/chrome/browser/ui/webui/welcome/nux/google_apps_handler.cc +++ b/chrome/browser/ui/webui/welcome/nux/google_apps_handler.cc
@@ -10,6 +10,7 @@ #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/webui/welcome/nux/show_promo_delegate.h" +#include "chrome/grit/browser_resources.h" #include "chrome/grit/generated_resources.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/common/bookmark_pref_names.h"
diff --git a/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.cc b/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.cc index 2683067..d153e238 100644 --- a/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.cc +++ b/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.cc
@@ -9,6 +9,7 @@ #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/grit/browser_resources.h" #include "chrome/grit/generated_resources.h" #include "components/grit/components_resources.h" #include "components/grit/components_scaled_resources.h"
diff --git a/chrome/browser/vr/test/xr_browser_test.cc b/chrome/browser/vr/test/xr_browser_test.cc index 7f8517fa1..da12d89 100644 --- a/chrome/browser/vr/test/xr_browser_test.cc +++ b/chrome/browser/vr/test/xr_browser_test.cc
@@ -30,6 +30,7 @@ constexpr base::TimeDelta XrBrowserTestBase::kPollCheckIntervalShort; constexpr base::TimeDelta XrBrowserTestBase::kPollCheckIntervalLong; constexpr base::TimeDelta XrBrowserTestBase::kPollTimeoutShort; +constexpr base::TimeDelta XrBrowserTestBase::kPollTimeoutMedium; constexpr base::TimeDelta XrBrowserTestBase::kPollTimeoutLong; constexpr char XrBrowserTestBase::kVrOverrideEnvVar[]; constexpr char XrBrowserTestBase::kVrOverrideVal[]; @@ -91,7 +92,7 @@ void XrBrowserTestBase::LoadUrlAndAwaitInitialization(const GURL& url) { ui_test_utils::NavigateToURL(browser(), url); EXPECT_TRUE(PollJavaScriptBoolean( - "isInitializationComplete()", kPollTimeoutShort, + "isInitializationComplete()", kPollTimeoutMedium, browser()->tab_strip_model()->GetActiveWebContents())) << "Timed out waiting for JavaScript test initialization."; }
diff --git a/chrome/browser/vr/test/xr_browser_test.h b/chrome/browser/vr/test/xr_browser_test.h index 213ab3839..5efd9e4d 100644 --- a/chrome/browser/vr/test/xr_browser_test.h +++ b/chrome/browser/vr/test/xr_browser_test.h
@@ -34,6 +34,8 @@ base::TimeDelta::FromMilliseconds(100); static constexpr base::TimeDelta kPollTimeoutShort = base::TimeDelta::FromMilliseconds(1000); + static constexpr base::TimeDelta kPollTimeoutMedium = + base::TimeDelta::FromMilliseconds(5000); static constexpr base::TimeDelta kPollTimeoutLong = base::TimeDelta::FromMilliseconds(10000); // Still considered XR-wide instead of VR-specific since OpenVR can be used
diff --git a/chrome/browser/vr/webxr_vr_transition_browser_test.cc b/chrome/browser/vr/webxr_vr_transition_browser_test.cc index 106544ba..5b4f7cb2 100644 --- a/chrome/browser/vr/webxr_vr_transition_browser_test.cc +++ b/chrome/browser/vr/webxr_vr_transition_browser_test.cc
@@ -80,14 +80,8 @@ // Tests that WebVR does not return any devices if OpenVR support is disabled. // Since WebVR isn't actually used, we can remove the GPU requirement. -#if defined(OS_WIN) -#define MAYBE_TestWebVrNoDevicesWithoutOpenVr \ - DISABLED_TestWebVrNoDevicesWithoutOpenVr -#else -#define MAYBE_TestWebVrNoDevicesWithoutOpenVr TestWebVrNoDevicesWithoutOpenVr -#endif IN_PROC_BROWSER_TEST_F(WebVrBrowserTestOpenVrDisabled, - MAYBE_TestWebVrNoDevicesWithoutOpenVr) { + TestWebVrNoDevicesWithoutOpenVr) { LoadUrlAndAwaitInitialization(GetHtmlTestFile("generic_webvr_page")); EXPECT_FALSE(XrDeviceFound()) << "Found a VRDisplay even with OpenVR disabled";
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 81d7e2c..7c22b38 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -329,9 +329,6 @@ const char kEnablePrintPreviewRegisterPromos[] = "enable-print-preview-register-promos"; -// Enables user control over muting tab audio from the tab strip. -const char kEnableTabAudioMuting[] = "enable-tab-audio-muting"; - // Enables DevTools server for UI (mus, ash, etc). Value should be the port the // server is started on. Default port is 9223. const char kEnableUiDevTools[] = "enable-ui-devtools";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index fe990df2..77929830 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -105,7 +105,6 @@ extern const char kEnablePotentiallyAnnoyingSecurityFeatures[]; extern const char kEnablePowerOverlay[]; extern const char kEnablePrintPreviewRegisterPromos[]; -extern const char kEnableTabAudioMuting[]; extern const char kEnableUiDevTools[]; extern const char kExtensionContentVerification[]; extern const char kExtensionContentVerificationBootstrap[];
diff --git a/chrome/common/extensions/api/cryptotoken_private.idl b/chrome/common/extensions/api/cryptotoken_private.idl index 0e4b70d..99c2e3f6 100644 --- a/chrome/common/extensions/api/cryptotoken_private.idl +++ b/chrome/common/extensions/api/cryptotoken_private.idl
@@ -17,6 +17,8 @@ // The AppId (see definition, above) that was used in the registration // request and which has been authenticated by |canOriginAssertAppId|. DOMString appId; + // The origin of the caller. + DOMString origin; // Identifies the tab in which the registration is occuring so that any // permissions prompt is correctly located. long tabId;
diff --git a/chrome/common/extensions/chrome_extension_messages.h b/chrome/common/extensions/chrome_extension_messages.h index 2d2ab50..32de1f09 100644 --- a/chrome/common/extensions/chrome_extension_messages.h +++ b/chrome/common/extensions/chrome_extension_messages.h
@@ -79,7 +79,7 @@ IPC_STRUCT_BEGIN(ExtensionMsg_AccessibilityEventBundleParams) // ID of the accessibility tree that this event applies to. - IPC_STRUCT_MEMBER(std::string, tree_id) + IPC_STRUCT_MEMBER(ui::AXTreeID, tree_id) // Zero or more updates to the accessibility tree to apply first. IPC_STRUCT_MEMBER(std::vector<ui::AXTreeUpdate>, updates) @@ -93,7 +93,7 @@ IPC_STRUCT_BEGIN(ExtensionMsg_AccessibilityLocationChangeParams) // ID of the accessibility tree that this event applies to. - IPC_STRUCT_MEMBER(std::string, tree_id) + IPC_STRUCT_MEMBER(ui::AXTreeID, tree_id) // ID of the object whose location is changing. IPC_STRUCT_MEMBER(int, id)
diff --git a/chrome/common/extensions/docs/server2/app.yaml b/chrome/common/extensions/docs/server2/app.yaml index 2a02173..f932966e 100644 --- a/chrome/common/extensions/docs/server2/app.yaml +++ b/chrome/common/extensions/docs/server2/app.yaml
@@ -1,5 +1,5 @@ application: chrome-apps-doc -version: 3-61-0 +version: 3-62-0 runtime: python27 api_version: 1 threadsafe: false
diff --git a/chrome/common/extensions/docs/static/images/runtime_host_permissions_badging.png b/chrome/common/extensions/docs/static/images/runtime_host_permissions_badging.png new file mode 100644 index 0000000..c62c81d --- /dev/null +++ b/chrome/common/extensions/docs/static/images/runtime_host_permissions_badging.png Binary files differ
diff --git a/chrome/common/extensions/docs/static/images/runtime_host_permissions_controls.png b/chrome/common/extensions/docs/static/images/runtime_host_permissions_controls.png new file mode 100644 index 0000000..b93694bd --- /dev/null +++ b/chrome/common/extensions/docs/static/images/runtime_host_permissions_controls.png Binary files differ
diff --git a/chrome/common/extensions/docs/templates/articles/runtime_host_permissions.html b/chrome/common/extensions/docs/templates/articles/runtime_host_permissions.html new file mode 100644 index 0000000..017bdb54 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/runtime_host_permissions.html
@@ -0,0 +1,191 @@ +<h1>User Controls For Host Permissions: Transition Guide</h1> + +<h2 id="summary">Summary</h2> + +<h3 id="changes">What's changing?</h3> +<p> + Beginning in Chrome 70, users have the ability to restrict extension host + access to a custom list of sites, or to configure extensions to require a + click to gain access to the current page. +</p> + +<h3 id="affected-apis">Which APIs are affected?</h3> +<p> + This change affects any APIs that are affected by the host permissions + specified in your extension's manifest, as well as content scripts. APIs + that require host permissions include + <a href="/webRequest">webRequest</a>, + <a href="/cookies">cookies</a>, + <a href="/tabs#method-executeScript">tabs.executeScript()</a> and + <a href="/tabs#method-insertCSS">tabs.insertCSS()</a>, and performing + cross-origin requests, such as through an <code>XMLHTTPRequest</code> or the + <code>fetch()</code> API. +</p> + +<h2 id="restricting-access">Restricting Access</h2> + +<h3 id="user-restricting-access">How can the user restrict access?</h3> +<p> + Users can choose to allow your extension to run on click, on a specific set of + sites, or on all requested sites. These options are presented to users on the + <code>chrome://extensions</code> page as well as in the extension context + menu. +</p> + +<img src="{{static}}/images/runtime_host_permissions_controls.png" + height="250" + alt="A screenshot of the context menu controls for runtime host permissions, including options to run the extension on click, on a specific site, or on all sites."> + +<h3 id="access-on-click"> + What happens if a user chooses to run my extension "on click"? +</h3> +<p> + The extension essentially behaves as though it used the + <a href="/activeTab">activeTab</a> permission. The extension is granted + temporary access to any host the user clicks the extension on, if that host + was requested by the extension (and isn't a restricted site, like + chrome://settings). When set to run on click, Chrome badges your extension + with a circle and drop shadow (see below) to indicate that is requesting + access on a particular site. +</p> + +<img src="{{static}}/images/runtime_host_permissions_badging.png" + height="150" + alt="A screenshot of the badging Chrome adds to the extension icon in the toolbar"> + +<h3 id="access-on-specific-sites"> + What happens if a user chooses to run my extension on specific sites? +</h3> +<p> + Your extension is allowed to run automatically on any sites the user has + chosen, and can access the site without further user action. On other sites + that your extension requested, but the user did not grant permission to, the + behavior is the same as if the user had set the extension to run on click. +</p> + +<h3 id="access-on-all-sites"> + What happens if a user chooses to run my extension on all sites? +</h3> +<p> + The extension can automatically access any sites requested in the manifest. +</p> + +<h2 id="api-behaviors">API Behaviors</h2> + +<h3 id="web-request-behavior">Web Request API</h3> +<p> + The extension can still intercept, modify, and block any requests from sites + it has access to. For sites the extension does not have access to, Chrome + badges the extension to indicate that the extension requests access to the + page. The user can then grant access to the extension; Chrome then prompts + the user to refresh the page to allow your extension to intercept the network + requests. +</p> + +<h3 id="scripts-behavior"> + Content Scripts, tabs.executeScript(), tabs.insertCSS() +</h3> +<p> + The extension can still inject scripts and style sheets automatically for any + sites it has access to. For sites the extension does not have access to, + Chrome badges the extension to indicate that the extension requests access to + the page. The user can then grant access to the extension. If the content + script was set to inject at document_idle, the script will inject immediately. + Otherwise, Chrome prompts the user to refresh the page to allow your extension + to inject scripts earlier in page load (at document_start or document_end). + The callbacks for the + <a href="/tabs#method-executeScript">tabs.executeScript()</a> and + <a href="/tabs#method-insertCSS">tabs.insertCSS()</a> methods are only invoked + if the user grants access to the site. +</p> + +<h3 id="background-behavior">Cookies and Background Page XHR</h3> +<p> + The extension can still read and modify any cookies from and perform a + cross-origin XHR to sites it has access to. Because there is no tab + associated with an extension page accessing another origin's cookies or + XHRing to another host, Chrome does not badge the extension to indicate to the + user that the extension is requesting to access a site. Trying to access a + cookie for another site or make a cross-origin XHR will fail with an error as + if the extension's manifest did not include the host permission. For these + cases, we encourage you to use optional permissions in order to allow the user + to grant runtime access to different sites. +</p> + +<p>The example below illustrates how this may work for the cookies API.</p> + +<p>Before:</p> +<pre data-filename="manifest.json"> + { + ... + "permissions": ["cookies", "https://example.com"] + } +</pre> + +<pre data-filename="background.js"> + chrome.cookies.get({url: 'https://example.com', name: 'mycookie'}, + function(cookie) { + // Use the cookie. + }); +</pre> + +<p>After:</p> +<pre data-filename="manifest.json"> + { + ... + "permissions": ["cookies"], + "optional_permissions": ["https://example.com"] + } +</pre> + +<pre data-filename="background.js"> + // Note: permissions.request() requires a user gesture, so this + // may only be done in response to a user action. + chrome.permissions.request( + {origins: ['https://example.com']}, + function(granted) { + if (granted) { + chrome.cookies.get({url: 'https://example.com', name: 'mycookie'}, + function(cookie) { + // Use the cookie. + }); + } else { + // Handle grant failure + } + }); +</pre> + +<h2 id="migration">Migration</h2> + +<h3 id="best-practices"> + What are best practices to avoid being negatively impacted? +</h3> +<p> + Extensions can use the <a href="/permissions">optional permissions</a>, + <a href="/activeTab">activeTab</a>, and + <a href="/declarativeContent">declarativeContent</a> APIs to follow best + practices. Optional permissions are granted at runtime, and allow the + extension to request specific access to a site. The + <a href="/activeTab">activeTab</a> permission is not affected, and extensions + using it continue to work normally. The + <a href="/declarativeContent">declarativeContent</a> API is a substitute for + many needs to inject scripts into every page. +</p> + +<h3 id="current-settings">What happens to my current users' settings?</h3> +<p> + This change will not immediately affect any current permissions granted to + your extension. That is, it will continue to operate as before unless the + user takes action to restrict the sites it is allowed to access. In future + releases, Chrome will provide more controls to users to adjust settings. +</p> + +<h3 id="checking-access"> + How can I check if my extension has permission to run on a site? +</h3> +<p> + You can use the + <a href="/permissions/#method-contains">permissions.contains()</a> API in + order to check whether your extension has been granted access to a given + origin. +</p>
diff --git a/chrome/common/extensions/docs/templates/intros/declarativeNetRequest.html b/chrome/common/extensions/docs/templates/intros/declarativeNetRequest.html new file mode 100644 index 0000000..586d4a9 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/declarativeNetRequest.html
@@ -0,0 +1,287 @@ +<h2 id="manifest">Manifest</h2> + +<p> +You must declare the <code>"declarativeNetRequest"</code> permission in the +extension <a href="manifest">manifest</a> to use this API, along with the +necessary <a href="declare_permissions">host permissions</a>. You must also +declare the <code>"declarative_net_request"</code> manifest key, which should be +a dictionary with a single key called <code>"rule_resources"</code>. It should +be a list containing a single element, the path to a JSON file containing the +declarative rules to use, as shown below. +</p> + +<pre data-filename="manifest.json"> +{ + "name": "My extension", + ... +<b> + "declarative_net_request" : { + "rule_resources" : ["rules.json"] + }, + "permissions": [ + "declarativeNetRequest", + "*://example.com/*" + ],</b> + ... +} +</pre> + +<h2 id="rule-resources">Rule Resources</h2> + +<p> +The JSON file specified as part of <code>"rule_resources"</code> in the manifest +contains a list of rules. The number of rules that an extension can specify is +bound by the <a href="#property-MAX_NUMBER_OF_RULES"> +chrome.declarativeNetRequest.MAX_NUMBER_OF_RULES</a> constant. +</p> + +<h2 id="rules">Rules</h2> + +<p> +A single declarative rule consists of four fields: <code>id</code>, +<code>priority</code>, <code>condition</code> and <code>action</code>. See the +<a href="#type-Rule">Rule</a> section below for more information on the format. +There are three kinds of rules: +</p> + +<ul> + <li> + Rules that block a network request. + </li> + <li> + Rules that prevent a request from getting blocked by negating any matching + blocked rules. + </li> + <li> + Rules that redirect a network request. + </li> +</ul> + +<p>An example rule:</p> +<pre> +{ + "id" : 1, + "action" : { "type" : "block" }, + "condition" : { + "urlFilter" : "abc", + "domains" : ["foo.com"], + "resource_types" : ["script"] + } +} +</pre> + +<p> +The above rule will block all script requests originating from +<code>"foo.com"</code> to any URL with <code>"abc"</code> as a substring. +</p> + +<p> +The <code>urlFilter</code> field of a rule condition is used to specify the +pattern which is matched against the request URL. Some examples of URL filters: +</p> + +<table> + <tr> + <th><code><b>urlFilter</b></code></th> + <th>Matches</th> + <th>Does not match</th> + </tr> + + <tr> + <td><code>"abc"</code></td> + <td> + https://abcd.com<br/> + https://example.com/abcd + </td> + <td>http://ab.com</td> + </tr> + + <tr> + <td><code>"abc*d"</code></td> + <td> + https://abcd.com<br/> + https://example.com/abcxyzd + </td> + <td>http://abc.com</td> + </tr> + + <tr> + <td><code>"||a.example.com"</code></td> + <td> + https://a.example.com/<br/> + https://b.a.example.com/xyz + </td> + <td>http://example.com/</td> + </tr> + + <tr> + <td><code>"|https*"</code></td> + <td>https://example.com</td> + <td> + http://example.com/<br/> + http://https.com + </td> + </tr> + + <tr> + <td><code>"example*^123|"</code></td> + <td> + https://example.com/123<br/> + http://abc.com/example?123 + </td> + <td> + https://example.com/1234<br/> + https://abc.com/example0123 + </td> + </tr> +</table> + +<h2 id="page-allowlisting">Page allowlisting</h2> + +<p> +To disable the extension ruleset on a particular page, extensions can use the +<a href="#method-addAllowedPages"> +chrome.declarativeNetRequest.addAllowedPages</a> API. This allows +extensions to specify match patterns that are compared against the tab URL. Any +requests originating from these pages are not evaluated against the extension +ruleset. The number of such patterns an extension can add is bound by the +<a href="#property-MAX_NUMBER_OF_ALLOWED_PAGES">chrome.declarativeNetRequest.MAX_NUMBER_OF_ALLOWED_PAGES</a> constant. +</p> + +<h2 id="implementation-details">Implementation details</h2> + +<h3 id="matching-algorithm">Matching algorithm</h3> + +<ul> + <li> + If any extension ruleset wants to block a request<sup>[1]</sup>, the network + request is blocked. + </li> + <li> + If the request is not blocked, the request is redirected if any extension + ruleset wants to redirect the request<sup>[2]</sup>. The most recently + installed extension gets preference here. If multiple redirect rules from an + extension’s ruleset match, the rule with the greatest priority determines + the redirect URL. + </li> +</ul> + +[1] An extension wants to block a request, if all the following are true: +<ul> + <li>The extension has a matching <code>block</code> rule.</li> + <li>The extension has no matching <code>allow</code> rule.</li> + <li> + The page from which the request originated is not allow-listed by the + extension using <a href="#method-addAllowedPages"> + chrome.declarativeNetRequest.addAllowedPages</a>. + </li> +</ul> + +[2] An extension wants to redirect a request, if all the following are true: +<ul> + <li>The extension has a matching <code>redirect</code> rule.</li> + <li> + The page from which the request originated is not allow-listed by the + extension using <a href="#method-addAllowedPages"> + chrome.declarativeNetRequest.addAllowedPages</a>. + </li> +</ul> + +<h3 id="web-request-comparison"> + Comparison with the <a href="webRequest">webRequest</a> API +</h3> + +<ul> + <li> + The declarativeNetRequest API allows for evaluating network requests in the + browser itself. This makes it more performant than the webRequest API, where + each network request is evaluated in JavaScript in the extension process. + </li> + <li> + Because the requests are not intercepted by the extension process, + declarativeNetRequest removes the need for extensions to have a background + page; resulting in less memory consumption. + </li> + <li> + Unlike the webRequest API, blocking and redirecting requests using the + declarativeNetRequest API requires host permissions to both the request URL + and the request initiator. + </li> + <li> + The declarativeNetRequest API provides better privacy to users because + extensions can't actually read the network requests made on the user's + behalf. + </li> + <li> + Unlike the webRequest API, any images or iframes blocked using the + declarativeNetRequest API are automatically collapsed in the DOM. + </li> + <li> + While deciding whether a request is to be blocked or redirected, the + declarativeNetRequest API is given priority over the webRequest API because + it allows for synchronous interception. + </li> + <li> + Evaluation of declarativeNetRequest rulesets is performed during the + <code>onBeforeRequest</code> stage of a network request. Extensions using + the webRequest API can intercept requests at different stages of the + request. + </li> + <li> + The declarativeNetRequest API only allows extensions to block or redirect + requests. The webRequest api is more flexible as compared to the + declarativeNetRequest API because it allows extensions to evaluate a request + programmatically. + </li> +</ul> + +<h2 id="examples">Example</h2> + +<p><b>manifest.json</b></p> +<pre data-filename="manifest.json"> +{ + "name" : "declarativeNetRequest extension", + "version" : "1", + "declarative_net_request" : { + "rule_resources" : ["rules.json"] + }, + "permissions" : ["*://google.com/*", "declarativeNetRequest"], + "manifest_version" : 2 +} +</pre> + +<p><b>rules.json</b></p> +<pre data-filename="rules.json"> +[ + { + "id" : 1, + "action": { "type" : "block" }, + "condition" : {"urlFilter" : "google.com", "resourceTypes" : ["main_frame"] } + }, + { + "id" : 2, + "action" : { "type" : "allow" }, + "condition" : { "urlFilter" : "google.com/123", "resourceTypes" : ["main_frame"] } + }, + { + "id" : 3, + "priority" : 1, + "action" : { "type" : "redirect", "redirectUrl" : "https://example.com" }, + "condition" : { "urlFilter" : "google.com", "resourceTypes" : ["main_frame"] } + } +] +</pre> + +<ul> + <li> + Consider a navigation to <code>"http://google.com"</code>. Rules with id (1) + and (3) match. The request will be blocked because blocking rules have + higher priority than redirect rules. + </li> + <li> + Consider a navigation to <code>"http://google.com/1234"</code>. Rules with + id (1), (2), and (3) match. Because the request has a matching + <code>allow</code> rule, the request is not blocked and instead redirected + to <code>"https://example.com"</code>. + </li> +</ul>
diff --git a/chrome/common/extensions/docs/templates/json/intro_tables.json b/chrome/common/extensions/docs/templates/json/intro_tables.json index 11e63c7..aae113b 100644 --- a/chrome/common/extensions/docs/templates/json/intro_tables.json +++ b/chrome/common/extensions/docs/templates/json/intro_tables.json
@@ -83,6 +83,18 @@ } ] }, + "declarativeNetRequest": { + "Permissions": [ + { + "class": "code", + "text": "\"declarativeNetRequest\"" + }, + { + "link": "declare_permissions#host-permissions", + "text": "host permissions" + } + ] + }, "declarativeWebRequest": { "Permissions": [ {
diff --git a/chrome/common/extensions/docs/templates/public/extensions/declarativeNetRequest.html b/chrome/common/extensions/docs/templates/public/extensions/declarativeNetRequest.html index 4942395..82cd2f9 100644 --- a/chrome/common/extensions/docs/templates/public/extensions/declarativeNetRequest.html +++ b/chrome/common/extensions/docs/templates/public/extensions/declarativeNetRequest.html
@@ -1 +1 @@ -{{+partials.standard_extensions_api api:apis.extensions.declarative_net_request/}} +{{+partials.standard_extensions_api api:apis.extensions.declarative_net_request intro:intros.declarativeNetRequest/}}
diff --git a/chrome/common/extensions/docs/templates/public/extensions/runtime_host_permissions.html b/chrome/common/extensions/docs/templates/public/extensions/runtime_host_permissions.html new file mode 100644 index 0000000..e54df3e5 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/runtime_host_permissions.html
@@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:articles.runtime_host_permissions/}}
diff --git a/chrome/renderer/extensions/automation_internal_custom_bindings.cc b/chrome/renderer/extensions/automation_internal_custom_bindings.cc index c145cee5..eb518ec0 100644 --- a/chrome/renderer/extensions/automation_internal_custom_bindings.cc +++ b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
@@ -140,7 +140,8 @@ if (args.Length() != 1 || !args[0]->IsString()) ThrowInvalidArgumentsException(automation_bindings_); - ui::AXTreeID tree_id = *v8::String::Utf8Value(isolate, args[0]); + ui::AXTreeID tree_id = + ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0])); AutomationAXTreeWrapper* tree_wrapper = automation_bindings_->GetAutomationAXTreeWrapperFromTreeID(tree_id); if (!tree_wrapper) @@ -187,7 +188,8 @@ v8::Local<v8::Context> context = automation_bindings_->context()->v8_context(); - ui::AXTreeID tree_id = *v8::String::Utf8Value(isolate, args[0]); + ui::AXTreeID tree_id = + ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0])); int node_id = args[1]->Int32Value(context).FromMaybe(0); AutomationAXTreeWrapper* tree_wrapper = @@ -241,7 +243,8 @@ v8::Local<v8::Context> context = automation_bindings_->context()->v8_context(); - ui::AXTreeID tree_id = *v8::String::Utf8Value(isolate, args[0]); + ui::AXTreeID tree_id = + ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0])); int node_id = args[1]->Int32Value(context).FromMaybe(0); std::string attribute = *v8::String::Utf8Value(isolate, args[2]); @@ -297,7 +300,8 @@ v8::Local<v8::Context> context = automation_bindings_->context()->v8_context(); - ui::AXTreeID tree_id = *v8::String::Utf8Value(isolate, args[0]); + ui::AXTreeID tree_id = + ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0])); int node_id = args[1]->Int32Value(context).FromMaybe(0); int start = args[2]->Int32Value(context).FromMaybe(0); int end = args[3]->Int32Value(context).FromMaybe(0); @@ -348,7 +352,8 @@ v8::Local<v8::Context> context = automation_bindings_->context()->v8_context(); - ui::AXTreeID tree_id = *v8::String::Utf8Value(isolate, args[0]); + ui::AXTreeID tree_id = + ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0])); int node_id = args[1]->Int32Value(context).FromMaybe(0); std::string str_val = *v8::String::Utf8Value(isolate, args[2]); bool bool_val = args[3].As<v8::Boolean>()->Value(); @@ -565,7 +570,7 @@ ui::AXNode* parent = GetParent(node, &tree_wrapper); if (parent) { gin::DataObjectBuilder response(isolate); - response.Set("treeId", tree_wrapper->tree_id()); + response.Set("treeId", tree_wrapper->tree_id().ToString()); response.Set("nodeId", parent->id()); result.Set(response.Build()); } @@ -591,28 +596,7 @@ RouteNodeIDFunction( "GetRole", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, AutomationAXTreeWrapper* tree_wrapper, ui::AXNode* node) { - auto role = node->data().role; - auto mapped_role = role; - - // These roles are remapped for simplicity in handling them in AT. - switch (role) { - case ax::mojom::Role::kLayoutTable: - mapped_role = ax::mojom::Role::kTable; - break; - case ax::mojom::Role::kLayoutTableCell: - mapped_role = ax::mojom::Role::kCell; - break; - case ax::mojom::Role::kLayoutTableColumn: - mapped_role = ax::mojom::Role::kColumn; - break; - case ax::mojom::Role::kLayoutTableRow: - mapped_role = ax::mojom::Role::kRow; - break; - default: - break; - } - - std::string role_name = ui::ToString(mapped_role); + std::string role_name = ui::ToString(node->data().role); result.Set(v8::String::NewFromUtf8(isolate, role_name.c_str(), v8::NewStringType::kNormal) .ToLocalChecked()); @@ -663,7 +647,7 @@ } gin::DataObjectBuilder response(isolate); - response.Set("treeId", tree_wrapper->tree_id()); + response.Set("treeId", tree_wrapper->tree_id().ToString()); response.Set("nodeIds", child_ids); result.Set(response.Build()); }); @@ -1065,7 +1049,8 @@ if (base::i18n::StringSearchIgnoringCaseAndAccents( search_str_16, name, nullptr, nullptr)) { gin::DataObjectBuilder response(isolate); - response.Set("treeId", (*target_tree_wrapper)->tree_id()); + response.Set("treeId", + (*target_tree_wrapper)->tree_id().ToString()); response.Set("nodeId", node->id()); result.Set(response.Build()); return; @@ -1219,7 +1204,8 @@ return; } - ui::AXTreeID tree_id = *v8::String::Utf8Value(args.GetIsolate(), args[0]); + ui::AXTreeID tree_id = ui::AXTreeID::FromString( + *v8::String::Utf8Value(args.GetIsolate(), args[0])); auto iter = tree_id_to_tree_wrapper_map_.find(tree_id); if (iter == tree_id_to_tree_wrapper_map_.end()) return; @@ -1283,8 +1269,9 @@ // Try to keep following focus recursively, by letting |tree_id| be the // new subtree to search in, while keeping |focus_tree_id| set to the tree // where we know we found a focused node. - ui::AXTreeID child_tree_id = focus->data().GetStringAttribute( - ax::mojom::StringAttribute::kChildTreeId); + ui::AXTreeID child_tree_id = + ui::AXTreeID::FromString(focus->data().GetStringAttribute( + ax::mojom::StringAttribute::kChildTreeId)); AutomationAXTreeWrapper* child_tree_wrapper = GetAutomationAXTreeWrapperFromTreeID(child_tree_id); @@ -1326,7 +1313,8 @@ return; } - ui::AXTreeID tree_id = *v8::String::Utf8Value(args.GetIsolate(), args[0]); + ui::AXTreeID tree_id = ui::AXTreeID::FromString( + *v8::String::Utf8Value(args.GetIsolate(), args[0])); AutomationAXTreeWrapper* tree_wrapper = GetAutomationAXTreeWrapperFromTreeID(tree_id); if (!tree_wrapper) @@ -1337,10 +1325,11 @@ if (!GetFocusInternal(tree_wrapper, &focused_tree_wrapper, &focused_node)) return; - args.GetReturnValue().Set(gin::DataObjectBuilder(GetIsolate()) - .Set("treeId", focused_tree_wrapper->tree_id()) - .Set("nodeId", focused_node->id()) - .Build()); + args.GetReturnValue().Set( + gin::DataObjectBuilder(GetIsolate()) + .Set("treeId", focused_tree_wrapper->tree_id().ToString()) + .Set("nodeId", focused_node->id()) + .Build()); } void AutomationInternalCustomBindings::GetHtmlAttributes( @@ -1349,7 +1338,8 @@ if (args.Length() < 2 || !args[0]->IsString() || !args[1]->IsNumber()) ThrowInvalidArgumentsException(this); - ui::AXTreeID tree_id = *v8::String::Utf8Value(isolate, args[0]); + ui::AXTreeID tree_id = + ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0])); int node_id = args[1]->Int32Value(context()->v8_context()).FromMaybe(0); AutomationAXTreeWrapper* tree_wrapper = @@ -1373,7 +1363,8 @@ if (args.Length() < 2 || !args[0]->IsString() || !args[1]->IsNumber()) ThrowInvalidArgumentsException(this); - ui::AXTreeID tree_id = *v8::String::Utf8Value(isolate, args[0]); + ui::AXTreeID tree_id = + ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0])); int node_id = args[1]->Int32Value(context()->v8_context()).FromMaybe(0); AutomationAXTreeWrapper* tree_wrapper = @@ -1458,8 +1449,8 @@ parent_tree_wrapper->tree()->GetFromId(host_node_id); if (host_node) { DCHECK_EQ((*in_out_tree_wrapper)->tree_id(), - host_node->GetStringAttribute( - ax::mojom::StringAttribute::kChildTreeId)); + ui::AXTreeID::FromString(host_node->GetStringAttribute( + ax::mojom::StringAttribute::kChildTreeId))); *in_out_tree_wrapper = parent_tree_wrapper; return host_node; } @@ -1471,14 +1462,15 @@ bool AutomationInternalCustomBindings::GetRootOfChildTree( ui::AXNode** in_out_node, AutomationAXTreeWrapper** in_out_tree_wrapper) const { - ui::AXTreeID child_tree_id; + std::string child_tree_id_str; if (!(*in_out_node) ->GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - &child_tree_id)) + &child_tree_id_str)) return false; AutomationAXTreeWrapper* child_tree_wrapper = - GetAutomationAXTreeWrapperFromTreeID(child_tree_id); + GetAutomationAXTreeWrapperFromTreeID( + ui::AXTreeID::FromString(child_tree_id_str)); if (!child_tree_wrapper) return false; @@ -1589,7 +1581,8 @@ return; } - ui::AXTreeID tree_id = *v8::String::Utf8Value(args.GetIsolate(), args[0]); + ui::AXTreeID tree_id = ui::AXTreeID::FromString( + *v8::String::Utf8Value(args.GetIsolate(), args[0])); int node_id = args[1]->Int32Value(context()->v8_context()).FromMaybe(0); const auto iter = tree_id_to_tree_wrapper_map_.find(tree_id); @@ -1613,7 +1606,7 @@ child_id = node->children()[index]->id(); gin::DataObjectBuilder response(GetIsolate()); - response.Set("treeId", tree_wrapper->tree_id()); + response.Set("treeId", tree_wrapper->tree_id().ToString()); response.Set("nodeId", child_id); args.GetReturnValue().Set(response.Build()); } @@ -1642,7 +1635,7 @@ if (!tree_wrapper->OnAccessibilityEvents(event_bundle, is_active_profile)) { LOG(ERROR) << tree_wrapper->tree()->error(); base::ListValue args; - args.AppendString(tree_id); + args.AppendString(tree_id.ToString()); bindings_system_->DispatchEventInContext( "automationInternal.onAccessibilityTreeSerializationError", &args, nullptr, context()); @@ -1675,9 +1668,10 @@ // Notify custom bindings when there's an unloaded tree; js will enable the // renderer and wait for it to load. - ui::AXTreeID child_tree_id; + std::string child_tree_id_str; if (node->data().GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - &child_tree_id)) { + &child_tree_id_str)) { + ui::AXTreeID child_tree_id = ui::AXTreeID::FromString(child_tree_id_str); auto* tree_wrapper = GetAutomationAXTreeWrapperFromTreeID(child_tree_id); if (!tree_wrapper || !tree_wrapper->tree()->data().loaded) SendChildTreeIDEvent(child_tree_id); @@ -1740,7 +1734,7 @@ did_send_event = true; base::ListValue args; args.AppendInteger(observer.id); - args.AppendString(tree_id); + args.AppendString(tree_id.ToString()); args.AppendInteger(node->id()); args.AppendString(ToString(change_type)); bindings_system_->DispatchEventInContext("automationInternal.onTreeChange", @@ -1756,7 +1750,7 @@ const ui::AXEvent& event, api::automation::EventType event_type) { auto event_params = std::make_unique<base::DictionaryValue>(); - event_params->SetString("treeID", tree_id); + event_params->SetString("treeID", tree_id.ToString()); event_params->SetInteger("targetID", event.id); event_params->SetString("eventType", api::automation::ToString(event_type)); event_params->SetString("eventFrom", ui::ToString(event.event_from)); @@ -1772,7 +1766,7 @@ void AutomationInternalCustomBindings::SendChildTreeIDEvent( ui::AXTreeID child_tree_id) { base::ListValue args; - args.AppendString(child_tree_id); + args.AppendString(child_tree_id.ToString()); bindings_system_->DispatchEventInContext("automationInternal.onChildTreeID", &args, nullptr, context()); } @@ -1787,7 +1781,7 @@ ui::AXTreeID tree_id = iter->second->tree_id(); base::ListValue args; - args.AppendString(tree_id); + args.AppendString(tree_id.ToString()); { auto nodes = std::make_unique<base::ListValue>(); for (auto id : ids)
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 6e7bb4c..b192d5e 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1485,7 +1485,6 @@ "../browser/ui/views/extensions/pwa_confirmation_view_browsertest.cc", "../browser/ui/views/external_protocol_dialog_browsertest.cc", "../browser/ui/views/folder_upload_confirmation_view_browsertest.cc", - "../browser/ui/views/frame/browser_non_client_frame_view_browsertest_win.cc", "../browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc", "../browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc", "../browser/ui/views/importer/import_lock_dialog_view_browsertest.cc", @@ -3400,6 +3399,7 @@ "../browser/chromeos/policy/policy_cert_verifier_unittest.cc", "../browser/component_updater/cros_component_installer_chromeos_unittest.cc", "../browser/component_updater/metadata_table_chromeos_unittest.cc", + "../browser/google/google_brand_code_map_chromeos_unittest.cc", "../browser/media/webrtc/desktop_media_list_ash_unittest.cc", "../browser/notifications/chrome_ash_message_center_client_unittest.cc", "../browser/renderer_context_menu/mock_render_view_context_menu.cc", @@ -3631,6 +3631,7 @@ "../browser/extensions/forced_extensions/installation_tracker_unittest.cc", "../browser/extensions/install_tracker_unittest.cc", "../browser/extensions/install_verifier_unittest.cc", + "../browser/extensions/installed_loader_unittest.cc", "../browser/extensions/menu_manager_unittest.cc", "../browser/extensions/ntp_overridden_bubble_delegate_unittest.cc", "../browser/extensions/pack_extension_unittest.cc", @@ -4339,7 +4340,6 @@ "../browser/ui/views/status_icons/status_tray_win_unittest.cc", "../browser/ui/views/sync/bubble_sync_promo_view_unittest.cc", "../browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_unittest.cc", - "../browser/ui/views/tabs/alert_indicator_button_unittest.cc", "../browser/ui/views/tabs/fake_base_tab_strip_controller.cc", "../browser/ui/views/tabs/fake_base_tab_strip_controller.h", "../browser/ui/views/tabs/stacked_tab_strip_layout_unittest.cc",
diff --git a/chrome/test/data/webui/cr_elements/cr_slider_test.js b/chrome/test/data/webui/cr_elements/cr_slider_test.js index 5cf29f2..2978110 100644 --- a/chrome/test/data/webui/cr_elements/cr_slider_test.js +++ b/chrome/test/data/webui/cr_elements/cr_slider_test.js
@@ -3,23 +3,194 @@ // found in the LICENSE file. suite('cr-slider', function() { - let element; + let crSlider; setup(function() { PolymerTest.clearBody(); - document.body.innerHTML = ` - <cr-slider min="0" max="100"></cr-slider> - `; + document.body.innerHTML = '<cr-slider min="0" max="100"></cr-slider>'; - element = document.body.querySelector('cr-slider'); + crSlider = document.body.querySelector('cr-slider'); }); - // Ensure that immediate-value-changed event bubbles, since users of - // cr-slider rely on such event. - test('immediate-value-changed bubbles', function() { - const whenFired = - test_util.eventToPromise('immediate-value-changed', element); - element.value = 50; + function pressArrowRight() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 39, [], 'ArrowRight'); + } + + function pressArrowLeft() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 37, [], 'ArrowLeft'); + } + + function pressPageUp() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 33, [], 'PageUp'); + } + + function pressPageDown() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 34, [], 'PageDown'); + } + + function pressArrowUp() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 38, [], 'ArrowUp'); + } + + function pressArrowDown() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 40, [], 'ArrowDown'); + } + + function pressHome() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 36, [], 'Home'); + } + + function pressEnd() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 35, [], 'End'); + } + + function pointerEvent(eventType, ratio) { + const rect = crSlider.$.barContainer.getBoundingClientRect(); + crSlider.dispatchEvent(new PointerEvent(eventType, { + buttons: 1, + pointerId: 1, + clientX: rect.left + (ratio * rect.width), + })); + } + + function pointerDown(ratio) { + pointerEvent('pointerdown', ratio); + } + + function pointerMove(ratio) { + pointerEvent('pointermove', ratio); + } + + function pointerUp(ratio) { + pointerEvent('pointerup', ratio); + } + + // Ensure that value-changed event bubbles, since users of cr-slider rely on + // such event. + test('value-changed bubbles', function() { + const whenFired = test_util.eventToPromise('value-changed', crSlider); + crSlider.value = 50; return whenFired; }); + + test('key events', () => { + crSlider.value = 0; + pressArrowRight(); + assertEquals(1, crSlider.value); + pressPageUp(); + assertEquals(2, crSlider.value); + pressArrowUp(); + assertEquals(3, crSlider.value); + pressHome(); + assertEquals(0, crSlider.value); + pressArrowLeft(); + assertEquals(0, crSlider.value); + pressArrowDown(); + assertEquals(0, crSlider.value); + pressPageDown(); + assertEquals(0, crSlider.value); + pressEnd(); + assertEquals(100, crSlider.value); + pressArrowRight(); + assertEquals(100, crSlider.value); + pressPageUp(); + assertEquals(100, crSlider.value); + pressArrowUp(); + assertEquals(100, crSlider.value); + pressArrowLeft(); + assertEquals(99, crSlider.value); + pressArrowDown(); + assertEquals(98, crSlider.value); + pressPageDown(); + assertEquals(97, crSlider.value); + }); + + test('mouse events', () => { + crSlider.value = 0; + pointerMove(.25); + assertEquals(0, crSlider.value); + pointerDown(.5); + assertEquals(50, crSlider.value); + assertEquals(5, crSlider.draggingEventTracker_.listeners_.length); + pointerMove(.75); + assertEquals(75, crSlider.value); + pointerMove(-1); + assertEquals(0, crSlider.value); + pointerMove(2); + assertEquals(100, crSlider.value); + pointerUp(0); + assertEquals(100, crSlider.value); + assertEquals(0, crSlider.draggingEventTracker_.listeners_.length); + pointerMove(.25); + assertEquals(100, crSlider.value); + }); + + test('snaps to closest value', () => { + crSlider.snaps = true; + pointerDown(.501); + assertEquals(50, crSlider.value); + pointerMove(.505); + assertEquals(51, crSlider.value); + }); + + test('markers', () => { + crSlider.value = 0; + assertTrue(crSlider.$.markers.hidden); + crSlider.markerCount = 10; + assertFalse(crSlider.$.markers.hidden); + Polymer.dom.flush(); + const markers = Array.from(crSlider.root.querySelectorAll('#markers div')); + assertEquals(9, markers.length); + markers.forEach((marker, i) => { + assertTrue(marker.classList.contains('inactive-marker')); + }); + crSlider.value = 100; + markers.forEach(marker => { + assertTrue(marker.classList.contains('active-marker')); + }); + crSlider.value = 50; + markers.slice(0, 5).forEach(marker => { + assertTrue(marker.classList.contains('active-marker')); + }); + markers.slice(5).forEach(marker => { + assertTrue(marker.classList.contains('inactive-marker')); + }); + }); + + test('ticks and aria', () => { + crSlider.value = 1.5; + crSlider.ticks = [1, 2, 4, 8]; + assertEquals('1', crSlider.getAttribute('aria-valuemin')); + assertEquals('8', crSlider.getAttribute('aria-valuemax')); + assertEquals('4', crSlider.getAttribute('aria-valuetext')); + assertEquals('4', crSlider.getAttribute('aria-valuenow')); + assertEquals(2, crSlider.value); + crSlider.value = 100; + assertEquals(3, crSlider.value); + assertEquals('8', crSlider.getAttribute('aria-valuetext')); + assertEquals('8', crSlider.getAttribute('aria-valuenow')); + crSlider.ticks = [ + { + value: 10, + ariaValue: 1, + label: 'First', + }, + { + value: 20, + label: 'Second', + }, + { + value: 30, + ariaValue: 3, + label: 'Third', + }, + ]; + assertEquals('1', crSlider.getAttribute('aria-valuemin')); + assertEquals('3', crSlider.getAttribute('aria-valuemax')); + assertEquals('Third', crSlider.getAttribute('aria-valuetext')); + assertEquals('3', crSlider.getAttribute('aria-valuenow')); + crSlider.value = 1; + assertEquals('Second', crSlider.getAttribute('aria-valuetext')); + assertEquals('20', crSlider.getAttribute('aria-valuenow')); + }); });
diff --git a/chrome/test/data/webui/multidevice_setup/integration_test.js b/chrome/test/data/webui/multidevice_setup/integration_test.js index 3842aba..46409f25 100644 --- a/chrome/test/data/webui/multidevice_setup/integration_test.js +++ b/chrome/test/data/webui/multidevice_setup/integration_test.js
@@ -4,6 +4,47 @@ /** @fileoverview Suite of integration tests for MultiDevice setup WebUI. */ cr.define('multidevice_setup', () => { + /** @implements {multidevice_setup.MultiDeviceSetupDelegate} */ + class FakeDelegate { + constructor() { + /** @private {boolean} */ + this.isPasswordRequiredToSetHost_ = true; + + /** @private {boolean} */ + this.shouldSetHostSucceed_ = true; + } + + set isPasswordRequired(isPasswordRequired) { + this.isPasswordRequiredToSetHost_ = isPasswordRequired; + } + + /** @override */ + isPasswordRequiredToSetHost() { + return this.isPasswordRequiredToSetHost_; + } + + set shouldSetHostSucceed(shouldSetHostSucceed) { + this.shouldSetHostSucceed_ = shouldSetHostSucceed; + } + + /** @override */ + setHostDevice(hostDeviceId, opt_authToken) { + return new Promise((resolve) => { + resolve({success: this.shouldSetHostSucceed_}); + }); + } + + set shouldExitSetupFlowAfterHostSet(shouldExitSetupFlowAfterHostSet) { + this.shouldExitSetupFlowAfterSettingHost_ = + shouldExitSetupFlowAfterHostSet; + } + + /** @override */ + shouldExitSetupFlowAfterSettingHost() { + return this.shouldExitSetupFlowAfterSettingHost_; + } + } + function registerIntegrationTests() { suite('MultiDeviceSetup', () => { /** @@ -30,8 +71,8 @@ setup(() => { multiDeviceSetupElement = document.createElement('multidevice-setup'); + multiDeviceSetupElement.delegate = new FakeDelegate(); multiDeviceSetupElement.multideviceSetup_ = new FakeMojoService(); - multiDeviceSetupElement.uiMode = multidevice_setup.UiMode.POST_OOBE; document.body.appendChild(multiDeviceSetupElement); forwardButton = multiDeviceSetupElement.$$('button-bar').$$('#forward'); @@ -39,6 +80,13 @@ multiDeviceSetupElement.$$('button-bar').$$('#backward'); }); + /** @param {boolean} isOobeMode */ + function setMode(isOobeMode) { + multiDeviceSetupElement.delegate.isPasswordRequired = !isOobeMode; + multiDeviceSetupElement.delegate.shouldExitSetupFlowAfterHostSet = + isOobeMode; + } + /** @param {string} visiblePageName */ function setVisiblePage(visiblePageName) { multiDeviceSetupElement.visiblePageName_ = visiblePageName; @@ -65,9 +113,9 @@ done(); }); + setMode(true /* isOobeMode */); setVisiblePage(START); - multiDeviceSetupElement.multideviceSetup_.shouldSetHostSucceed = true; - multiDeviceSetupElement.uiMode = multidevice_setup.UiMode.OOBE; + multiDeviceSetupElement.delegate.shouldSetHostSucceed = true; backwardButton.click(); }); @@ -76,16 +124,13 @@ 'StartSetupPage forward button sets host in background and ' + 'goes to PasswordPage (OOBE).', done => { - multiDeviceSetupElement.addEventListener( - 'visible-page-name_-changed', () => { - if (multiDeviceSetupElement.visiblePageName_ == PASSWORD) - done(); - }); + multiDeviceSetupElement.addEventListener('setup-exited', () => { + done(); + }); + setMode(true /* isOobeMode */); setVisiblePage(START); - multiDeviceSetupElement.multideviceSetup_.shouldSetHostSucceed = - true; - multiDeviceSetupElement.uiMode = multidevice_setup.UiMode.OOBE; + multiDeviceSetupElement.delegate.shouldSetHostSucceed = true; multiDeviceSetupElement.async(() => { forwardButton.click(); @@ -97,9 +142,9 @@ test('StartSetupPage backward button closes UI (post-OOBE)', done => { multiDeviceSetupElement.addEventListener('setup-exited', () => done()); + setMode(false /* isOobeMode */); setVisiblePage(START); - multiDeviceSetupElement.multideviceSetup_.shouldSetHostSucceed = true; - multiDeviceSetupElement.uiMode = multidevice_setup.UiMode.POST_OOBE; + multiDeviceSetupElement.delegate.shouldSetHostSucceed = true; backwardButton.click(); }); @@ -107,9 +152,9 @@ test('PasswordPage backward button closes UI (post-OOBE)', done => { multiDeviceSetupElement.addEventListener('setup-exited', () => done()); + setMode(false /* isOobeMode */); setVisiblePage(PASSWORD); - multiDeviceSetupElement.multideviceSetup_.shouldSetHostSucceed = true; - multiDeviceSetupElement.uiMode = multidevice_setup.UiMode.POST_OOBE; + multiDeviceSetupElement.delegate.shouldSetHostSucceed = true; backwardButton.click(); }); @@ -124,10 +169,9 @@ done(); }); + setMode(false /* isOobeMode */); setVisiblePage(PASSWORD); - multiDeviceSetupElement.multideviceSetup_.shouldSetHostSucceed = - true; - multiDeviceSetupElement.uiMode = multidevice_setup.UiMode.POST_OOBE; + multiDeviceSetupElement.delegate.shouldSetHostSucceed = true; multiDeviceSetupElement.async(() => { forwardButton.click();
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index 1e61aa8..e2d6ec1 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -2186,30 +2186,6 @@ TEST_F('CrSettingsOnStartupPageTest', 'All', function() { mocha.run(); }); -GEN('#if defined(OS_CHROMEOS)'); - -/** - * @constructor - * @extends {CrSettingsBrowserTest} - */ -function CrSettingsDisplaySizeSliderTest() {} - -CrSettingsDisplaySizeSliderTest.prototype = { - __proto__: CrSettingsBrowserTest.prototype, - - /** @override */ - browsePreload: 'chrome://settings/device_page/display_size_slider.html', - - /** @override */ - extraLibraries: CrSettingsBrowserTest.prototype.extraLibraries.concat([ - 'display_size_slider_test.js', - ]), -}; - -TEST_F('CrSettingsDisplaySizeSliderTest', 'All', function() { - mocha.run(); -}); -GEN('#endif // defined(OS_CHROMEOS)'); /** * Test fixture for FindShortcutBehavior.
diff --git a/chrome/test/data/webui/settings/device_page_tests.js b/chrome/test/data/webui/settings/device_page_tests.js index 3e2fd9f..41c61eb 100644 --- a/chrome/test/data/webui/settings/device_page_tests.js +++ b/chrome/test/data/webui/settings/device_page_tests.js
@@ -530,7 +530,7 @@ const slider = assert(pointersPage.$$('#mouse settings-slider')); expectEquals(4, slider.pref.value); MockInteractions.pressAndReleaseKeyOn( - slider.$$('cr-slider').$$('#slider'), 37 /* left */); + slider.$$('cr-slider'), 37, [], 'ArrowLeft'); expectEquals(3, devicePage.prefs.settings.mouse.sensitivity2.value); pointersPage.set('prefs.settings.mouse.sensitivity2.value', 5); @@ -546,7 +546,7 @@ const slider = assert(pointersPage.$$('#touchpad settings-slider')); expectEquals(3, slider.pref.value); MockInteractions.pressAndReleaseKeyOn( - slider.$$('cr-slider').$$('#slider'), 39 /* right */); + slider.$$('cr-slider'), 39 /* right */, [], 'ArrowRight'); expectEquals(4, devicePage.prefs.settings.touchpad.sensitivity2.value); pointersPage.set('prefs.settings.touchpad.sensitivity2.value', 2); @@ -661,13 +661,11 @@ // Test interaction with the settings-slider's underlying // paper-slider. MockInteractions.pressAndReleaseKeyOn( - keyboardPage.$$('#delaySlider').$$('cr-slider').$$('#slider'), - 37 /* left */); + keyboardPage.$$('#delaySlider').$$('cr-slider'), 37 /* left */, + [], 'ArrowLeft'); MockInteractions.pressAndReleaseKeyOn( - keyboardPage.$$('#repeatRateSlider') - .$$('cr-slider') - .$$('#slider'), - 39 /* right */); + keyboardPage.$$('#repeatRateSlider').$$('cr-slider'), 39, [], + 'ArrowRight'); const language = devicePage.prefs.settings.language; expectEquals(1000, language.xkb_auto_repeat_delay_r2.value); expectEquals(300, language.xkb_auto_repeat_interval_r2.value);
diff --git a/chrome/test/data/webui/settings/display_size_slider_test.js b/chrome/test/data/webui/settings/display_size_slider_test.js deleted file mode 100644 index 2224026..0000000 --- a/chrome/test/data/webui/settings/display_size_slider_test.js +++ /dev/null
@@ -1,307 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** @fileoverview Suite of tests for display-size-slider. */ -suite('DisplaySizeSlider', function() { - /** @type {!CrSliderElement} */ - let slider; - - /** @type {!SliderTicks} */ - let ticks = []; - - setup(function() { - PolymerTest.clearBody(); - const tickValues = [2, 4, 8, 16, 32, 64, 128]; - ticks = []; - for (let i = 0; i < tickValues.length; i++) { - ticks.push({value: tickValues[i], label: tickValues[i].toString()}); - } - - slider = document.createElement('display-size-slider'); - slider.ticks = ticks; - slider.pref = { - type: chrome.settingsPrivate.PrefType.NUMBER, - value: ticks[3].value, - }; - document.body.appendChild(slider); - }); - - test('initialization', function() { - const selectedIndex = 3; - - assertFalse(slider.disabled); - assertFalse(slider.dragging); - expectEquals(selectedIndex, slider.index); - expectEquals(ticks.length - 1, slider.markers.length); - expectEquals(ticks[selectedIndex].value, slider.pref.value); - }); - - test('check knob position changes', function() { - let expectedIndex = 3; - expectEquals(expectedIndex, slider.index); - expectEquals(ticks[expectedIndex].value, slider.pref.value); - - let expectedLeftPercentage = (expectedIndex * 100) / (ticks.length - 1); - expectEquals(expectedLeftPercentage + '%', slider.$.sliderKnob.style.left); - - // Reset the index to the first tick. - slider.resetToMinIndex_(); - expectedIndex = 0; - expectEquals(expectedIndex, slider.index); - expectEquals('0%', slider.$.sliderKnob.style.left); - expectEquals(ticks[expectedIndex].value, slider.pref.value); - - // Decrementing the slider below the lowest index should have no effect. - slider.decrement_(); - expectEquals(expectedIndex, slider.index); - expectEquals('0%', slider.$.sliderKnob.style.left); - expectEquals(ticks[expectedIndex].value, slider.pref.value); - - // Reset the index to the last tick. - slider.resetToMaxIndex_(); - expectedIndex = ticks.length - 1; - expectEquals(expectedIndex, slider.index); - expectEquals('100%', slider.$.sliderKnob.style.left); - expectEquals(ticks[expectedIndex].value, slider.pref.value); - - // Incrementing the slider when it is already at max should have no effect. - slider.increment_(); - expectEquals(expectedIndex, slider.index); - expectEquals('100%', slider.$.sliderKnob.style.left); - expectEquals(ticks[expectedIndex].value, slider.pref.value); - - slider.decrement_(); - expectedIndex -= 1; - expectEquals(expectedIndex, slider.index); - expectedLeftPercentage = (expectedIndex * 100) / (ticks.length - 1); - expectEquals( - Math.round(expectedLeftPercentage), - Math.round(parseFloat(slider.$.sliderKnob.style.left))); - expectEquals(ticks[expectedIndex].value, slider.pref.value); - - }); - - test('check keyboard events', function() { - let expectedIndex = 3; - expectEquals(expectedIndex, slider.index); - - // Right keypress should increment the slider by 1. - MockInteractions.pressAndReleaseKeyOn(slider, 39 /* right */); - expectedIndex += 1; - expectEquals(expectedIndex, slider.index); - - // Left keypress should decrement the slider by 1. - MockInteractions.pressAndReleaseKeyOn(slider, 37 /* left */); - expectedIndex -= 1; - expectEquals(expectedIndex, slider.index); - - // Page down should take the slider to the first value. - MockInteractions.pressAndReleaseKeyOn(slider, 34 /* page down */); - expectedIndex = 0; - expectEquals(expectedIndex, slider.index); - - // Page up should take the slider to the last value. - MockInteractions.pressAndReleaseKeyOn(slider, 33 /* page up */); - expectedIndex = ticks.length - 1; - expectEquals(expectedIndex, slider.index); - - // Down keypress should decrement the slider index by 1. - MockInteractions.pressAndReleaseKeyOn(slider, 40 /* down */); - expectedIndex -= 1; - expectEquals(expectedIndex, slider.index); - - // Up keypress should increment the slider index by 1. - MockInteractions.pressAndReleaseKeyOn(slider, 38 /* up */); - expectedIndex += 1; - expectEquals(expectedIndex, slider.index); - - // Home button should take the slider to the first value. - MockInteractions.pressAndReleaseKeyOn(slider, 36 /* home */); - expectedIndex = 0; - expectEquals(expectedIndex, slider.index); - - // End button should take the slider to the last value. - MockInteractions.pressAndReleaseKeyOn(slider, 35 /* up */); - expectedIndex = ticks.length - 1; - expectEquals(expectedIndex, slider.index); - }); - - test('set pref updates slider', function() { - let expectedIndex = 3; - expectEquals(expectedIndex, slider.index); - expectEquals(ticks[expectedIndex].value, slider.pref.value); - - let newIndex = 4; - slider.set('pref.value', ticks[newIndex].value); - expectEquals(newIndex, slider.index); - - let expectedLeftPercentage = (newIndex * 100) / (ticks.length - 1); - expectEquals( - Math.round(expectedLeftPercentage), - Math.round(parseFloat(slider.$.sliderKnob.style.left))); - }); - - test('check label values', function() { - expectEquals('none', getComputedStyle(slider.$.labelContainer).display); - let hoverClassName = 'hover'; - slider.$.sliderContainer.classList.add(hoverClassName); - expectEquals('block', getComputedStyle(slider.$.labelContainer).display); - - expectEquals(ticks[slider.index].label, slider.$.labelText.innerText); - - slider.increment_(); - expectEquals(ticks[slider.index].label, slider.$.labelText.innerText); - - slider.resetToMaxIndex_(); - expectEquals(ticks[slider.index].label, slider.$.labelText.innerText); - - slider.resetToMinIndex_(); - expectEquals(ticks[slider.index].label, slider.$.labelText.innerText); - }); - - test('mouse interactions with the slider knobs', function() { - // The label should be visible when focused. - expectEquals('none', getComputedStyle(slider.$.labelContainer).display); - slider.focus(); - expectEquals('block', getComputedStyle(slider.$.labelContainer).display); - - let dragEventReceived = false; - let valueInEvent = null; - slider.addEventListener('immediate-value-changed', function(e) { - dragEventReceived = true; - valueInEvent = e.detail.value; - }); - - let oldIndex = slider.index; - const sliderKnob = slider.$.sliderKnob; - // Width of each tick. - const tickWidth = slider.$.sliderBar.offsetWidth / (ticks.length - 1); - assertFalse(dragEventReceived); - MockInteractions.down(sliderKnob); - assertFalse(dragEventReceived); - - let currentPos = MockInteractions.middleOfNode(sliderKnob); - let nextPos = {x: currentPos.x + tickWidth, y: currentPos.y}; - MockInteractions.move(sliderKnob, currentPos, nextPos); - - // We moved by 1 tick width, so the slider index must have increased. - expectEquals(oldIndex + 1, slider.index); - - // The mouse is still down, so the pref should not be updated. - expectEquals(ticks[oldIndex].value, slider.pref.value); - - // The event should be fired while dragging the knob. - assertTrue(dragEventReceived); - dragEventReceived = false; - - // The value sent by the event must be the current value of the slider. - expectEquals(ticks[slider.index].value, valueInEvent); - - MockInteractions.up(sliderKnob); - - // There should be no event fired when the knob is not being dragged. - assertFalse(dragEventReceived); - - // Now that the mouse is down, the pref value should be updated. - expectEquals(ticks[oldIndex + 1].value, slider.pref.value); - - oldIndex = slider.index; - MockInteractions.track(sliderKnob, -3 * tickWidth, 0); - expectEquals(oldIndex - 3, slider.index); - expectEquals(ticks[oldIndex - 3].value, slider.pref.value); - - // Moving by a very large amount should clamp the value. - oldIndex = slider.index; - MockInteractions.track(sliderKnob, 100 * tickWidth, 0); - expectEquals(ticks.length - 1, slider.index); - expectEquals(ticks[ticks.length - 1].value, slider.pref.value); - - // Similarly for the other side. - oldIndex = slider.index; - MockInteractions.track(sliderKnob, -100 * tickWidth, 0); - expectEquals(0, slider.index); - expectEquals(ticks[0].value, slider.pref.value); - }); - - test('mouse interaction with the bar', function() { - let dragEventReceived = false; - let valueInEvent = null; - slider.addEventListener('immediate-value-changed', function(e) { - dragEventReceived = true; - valueInEvent = e.detail.value; - }); - - const sliderBar = slider.$.sliderBar; - const sliderBarOrigin = { - x: sliderBar.getBoundingClientRect().x, - y: sliderBar.getBoundingClientRect().y - }; - - let oldIndex = slider.index; - MockInteractions.down(sliderBar, sliderBarOrigin); - - // Mouse down on the left end of the slider bar should move the knob there. - expectEquals(0, slider.index); - expectEquals(0, Math.round(parseFloat(slider.$.sliderKnob.style.left))); - - // Mouse down must trigger a drag event since we are essentially dragging - // the knob. - assertTrue(dragEventReceived); - expectEquals(ticks[slider.index].value, valueInEvent); - dragEventReceived = false; - - // However the pref value should not update until the mouse is released. - expectEquals(ticks[oldIndex].value, slider.pref.value); - - // Release mouse to update pref value. - MockInteractions.up(sliderBar); - expectEquals(ticks[slider.index].value, slider.pref.value); - - const tickWidth = - sliderBar.getBoundingClientRect().width / (ticks.length - 1); - let expectedIndex = 3; - // The knob position for the 3rd index. - let sliderBarPos = { - x: sliderBarOrigin.x + tickWidth * expectedIndex, - y: sliderBarOrigin.y - }; - - // The slider has not yet started dragging. - assertFalse(slider.dragging); - - oldIndex = slider.index; - // Clicking at the 3rd index position on the slider bar should update the - // knob. - MockInteractions.down(sliderBar, sliderBarPos); - let expectedLeftPercentage = - (tickWidth * expectedIndex * 100) / sliderBar.offsetWidth; - expectEquals( - Math.round(expectedLeftPercentage), - Math.round(parseFloat(slider.$.sliderKnob.style.left))); - expectEquals(expectedIndex, slider.index); - expectEquals(ticks[oldIndex].value, slider.pref.value); - - - expectedIndex = 5; - const nextSliderBarPos = { - x: sliderBarPos.x + tickWidth * (expectedIndex - slider.index), - y: sliderBarPos.y - }; - MockInteractions.move(sliderBar, sliderBarPos, nextSliderBarPos); - expectEquals(expectedIndex, slider.index); - expectedLeftPercentage = - (tickWidth * expectedIndex * 100) / sliderBar.offsetWidth; - expectEquals( - Math.round(expectedLeftPercentage), - Math.round(parseFloat(slider.$.sliderKnob.style.left))); - - expectEquals(ticks[oldIndex].value, slider.pref.value); - - assertTrue(dragEventReceived); - expectEquals(ticks[slider.index].value, valueInEvent); - - MockInteractions.up(sliderBar); - expectEquals(ticks[expectedIndex].value, slider.pref.value); - }); -});
diff --git a/chrome/test/data/webui/settings/settings_slider_tests.js b/chrome/test/data/webui/settings/settings_slider_tests.js index 1512b521..4eb7adc 100644 --- a/chrome/test/data/webui/settings/settings_slider_tests.js +++ b/chrome/test/data/webui/settings/settings_slider_tests.js
@@ -13,7 +13,7 @@ */ let crSlider; - const tickValues = [2, 4, 8, 16, 32, 64, 128]; + const ticks = [2, 4, 8, 16, 32, 64, 128]; setup(function() { PolymerTest.clearBody(); @@ -26,6 +26,38 @@ crSlider = slider.$$('cr-slider'); }); + function pressArrowRight() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 39, [], 'ArrowRight'); + } + + function pressArrowLeft() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 37, [], 'ArrowLeft'); + } + + function pressPageUp() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 33, [], 'PageUp'); + } + + function pressPageDown() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 34, [], 'PageDown'); + } + + function pressArrowUp() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 38, [], 'ArrowUp'); + } + + function pressArrowDown() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 40, [], 'ArrowDown'); + } + + function pressHome() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 36, [], 'Home'); + } + + function pressEnd() { + MockInteractions.pressAndReleaseKeyOn(crSlider, 35, [], 'End'); + } + test('enforce value', function() { // Test that the indicator is not present until after the pref is // enforced. @@ -43,85 +75,106 @@ }); test('set value', function() { - slider.tickValues = tickValues; + slider.ticks = ticks; slider.set('pref.value', 16); + Polymer.dom.flush(); expectEquals(6, crSlider.max); expectEquals(3, crSlider.value); - expectEquals(3, crSlider.immediateValue); // settings-slider only supports snapping to a range of tick values. // Setting to an in-between value should snap to an indexed value. slider.set('pref.value', 70); expectEquals(5, crSlider.value); - expectEquals(5, crSlider.immediateValue); expectEquals(64, slider.pref.value); // Setting the value out-of-range should clamp the slider. slider.set('pref.value', -100); expectEquals(0, crSlider.value); - expectEquals(0, crSlider.immediateValue); expectEquals(2, slider.pref.value); }); test('move slider', function() { - slider.tickValues = tickValues; + slider.ticks = ticks; slider.set('pref.value', 30); expectEquals(4, crSlider.value); - MockInteractions.pressAndReleaseKeyOn(crSlider.$.slider, 39 /* right */); + pressArrowRight(); expectEquals(5, crSlider.value); expectEquals(64, slider.pref.value); - MockInteractions.pressAndReleaseKeyOn(crSlider.$.slider, 39 /* right */); + pressArrowRight(); expectEquals(6, crSlider.value); expectEquals(128, slider.pref.value); - MockInteractions.pressAndReleaseKeyOn(crSlider.$.slider, 39 /* right */); + pressArrowRight(); expectEquals(6, crSlider.value); expectEquals(128, slider.pref.value); - MockInteractions.pressAndReleaseKeyOn(crSlider.$.slider, 37 /* left */); + pressArrowLeft(); expectEquals(5, crSlider.value); expectEquals(64, slider.pref.value); - }); - test('findNearestIndex_', function() { - const slider = document.createElement('settings-slider'); - const testArray = [80, 20, 350, 1000, 200, 100]; - const testFindNearestIndex = function(expectedIndex, value) { - expectEquals(expectedIndex, slider.findNearestIndex_(testArray, value)); - }; - testFindNearestIndex(0, 51); - testFindNearestIndex(0, 80); - testFindNearestIndex(0, 89); - testFindNearestIndex(1, -100); - testFindNearestIndex(1, 20); - testFindNearestIndex(1, 49); - testFindNearestIndex(2, 400); - testFindNearestIndex(2, 350); - testFindNearestIndex(2, 300); - testFindNearestIndex(3, 200000); - testFindNearestIndex(3, 1000); - testFindNearestIndex(3, 700); - testFindNearestIndex(4, 220); - testFindNearestIndex(4, 200); - testFindNearestIndex(4, 151); - testFindNearestIndex(5, 149); - testFindNearestIndex(5, 100); - testFindNearestIndex(5, 91); + pressPageUp(); + expectEquals(6, crSlider.value); + expectEquals(128, slider.pref.value); + + pressPageDown(); + expectEquals(5, crSlider.value); + expectEquals(64, slider.pref.value); + + pressHome(); + expectEquals(0, crSlider.value); + expectEquals(2, slider.pref.value); + + pressArrowDown(); + expectEquals(0, crSlider.value); + expectEquals(2, slider.pref.value); + + pressArrowUp(); + expectEquals(1, crSlider.value); + expectEquals(4, slider.pref.value); + + pressEnd(); + expectEquals(6, crSlider.value); + expectEquals(128, slider.pref.value); }); test('scaled slider', function() { - slider.scale = 10; slider.set('pref.value', 2); - expectEquals(20, crSlider.value); + expectEquals(2, crSlider.value); - MockInteractions.pressAndReleaseKeyOn(crSlider.$.slider, 39 /* right */); - expectEquals(21, crSlider.value); - expectEquals(2.1, slider.pref.value); + slider.scale = 10; + slider.max = 4; + pressArrowRight(); + expectEquals(3, crSlider.value); + expectEquals(.3, slider.pref.value); - MockInteractions.pressAndReleaseKeyOn(crSlider.$.slider, 39 /* right */); - expectEquals(22, crSlider.value); - expectEquals(2.2, slider.pref.value); + pressArrowRight(); + expectEquals(4, crSlider.value); + expectEquals(.4, slider.pref.value); + + pressArrowRight(); + expectEquals(4, crSlider.value); + expectEquals(.4, slider.pref.value); + + pressHome(); + expectEquals(0, crSlider.value); + expectEquals(0, slider.pref.value); + + pressEnd(); + expectEquals(4, crSlider.value); + expectEquals(.4, slider.pref.value); + + slider.set('pref.value', .25); + expectEquals(2.5, crSlider.value); + expectEquals(.25, slider.pref.value); + + pressPageUp(); + expectEquals(3.5, crSlider.value); + expectEquals(.35, slider.pref.value); + + pressPageUp(); + expectEquals(4, crSlider.value); + expectEquals(.4, slider.pref.value); }); });
diff --git a/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc b/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc index 716db2a..25ef92eb 100644 --- a/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc +++ b/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -250,8 +250,8 @@ std::unique_ptr<Params> params(Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); - content::RenderFrameHost* rfh = - content::RenderFrameHost::FromAXTreeID(params->tree_id); + content::RenderFrameHost* rfh = content::RenderFrameHost::FromAXTreeID( + ui::AXTreeID::FromString(params->tree_id)); if (!rfh) return RespondNow(Error("unable to load tab")); @@ -271,7 +271,7 @@ AutomationInternalPerformActionFunction::ConvertToAXActionData( api::automation_internal::PerformAction::Params* params, ui::AXActionData* action) { - action->target_tree_id = params->args.tree_id; + action->target_tree_id = ui::AXTreeID::FromString(params->args.tree_id); action->source_extension_id = extension_id(); action->target_node_id = params->args.automation_node_id; int* request_id = params->args.request_id.get(); @@ -424,7 +424,7 @@ EXTENSION_FUNCTION_VALIDATE(params.get()); ui::AXTreeIDRegistry* registry = ui::AXTreeIDRegistry::GetInstance(); ui::AXHostDelegate* delegate = - registry->GetHostDelegate(params->args.tree_id); + registry->GetHostDelegate(ui::AXTreeID::FromString(params->args.tree_id)); if (delegate) { #if defined(USE_AURA) ui::AXActionData data; @@ -439,8 +439,8 @@ " platform does not support desktop automation")); #endif // defined(USE_AURA) } - content::RenderFrameHost* rfh = - content::RenderFrameHost::FromAXTreeID(params->args.tree_id); + content::RenderFrameHost* rfh = content::RenderFrameHost::FromAXTreeID( + ui::AXTreeID::FromString(params->args.tree_id)); if (!rfh) return RespondNow(Error("Ignoring action on destroyed node")); @@ -507,8 +507,8 @@ std::unique_ptr<Params> params(Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); - content::RenderFrameHost* rfh = - content::RenderFrameHost::FromAXTreeID(params->args.tree_id); + content::RenderFrameHost* rfh = content::RenderFrameHost::FromAXTreeID( + ui::AXTreeID::FromString(params->args.tree_id)); if (!rfh) { return RespondNow( Error("domQuerySelector query sent on non-web or destroyed tree."));
diff --git a/chromecast/browser/extensions/api/tabs/tabs_constants.cc b/chromecast/browser/extensions/api/tabs/tabs_constants.cc index df10b0b..eeabb9e8 100644 --- a/chromecast/browser/extensions/api/tabs/tabs_constants.cc +++ b/chromecast/browser/extensions/api/tabs/tabs_constants.cc
@@ -110,8 +110,6 @@ const char kInvalidWindowTypeError[] = "Invalid value for type"; const char kInvalidWindowStateError[] = "Invalid value for state"; const char kScreenshotsDisabled[] = "Taking screenshots has been disabled"; -const char kCannotUpdateMuteDisabled[] = - "Failed to update mute state for tab *, --* must be enabled"; const char kCannotUpdateMuteCaptured[] = "Cannot update mute state for tab *, tab has audio or video currently " "being captured";
diff --git a/chromecast/browser/extensions/api/tabs/tabs_constants.h b/chromecast/browser/extensions/api/tabs/tabs_constants.h index 33d0a01..468fb93 100644 --- a/chromecast/browser/extensions/api/tabs/tabs_constants.h +++ b/chromecast/browser/extensions/api/tabs/tabs_constants.h
@@ -102,7 +102,6 @@ extern const char kInvalidWindowTypeError[]; extern const char kInvalidWindowStateError[]; extern const char kScreenshotsDisabled[]; -extern const char kCannotUpdateMuteDisabled[]; extern const char kCannotUpdateMuteCaptured[]; extern const char kCannotDetermineLanguageOfUnloadedTab[]; extern const char kMissingLockWindowFullscreenPrivatePermission[];
diff --git a/chromecast/common/extensions_api/cast_extension_messages.h b/chromecast/common/extensions_api/cast_extension_messages.h index d49c2c6..9a851da1 100644 --- a/chromecast/common/extensions_api/cast_extension_messages.h +++ b/chromecast/common/extensions_api/cast_extension_messages.h
@@ -79,7 +79,7 @@ IPC_STRUCT_BEGIN(ExtensionMsg_AccessibilityEventBundleParams) // ID of the accessibility tree that this event applies to. - IPC_STRUCT_MEMBER(std::string, tree_id) + IPC_STRUCT_MEMBER(ui::AXTreeID, tree_id) // Zero or more updates to the accessibility tree to apply first. IPC_STRUCT_MEMBER(std::vector<ui::AXTreeUpdate>, updates) @@ -93,7 +93,7 @@ IPC_STRUCT_BEGIN(ExtensionMsg_AccessibilityLocationChangeParams) // ID of the accessibility tree that this event applies to. - IPC_STRUCT_MEMBER(std::string, tree_id) + IPC_STRUCT_MEMBER(ui::AXTreeID, tree_id) // ID of the object whose location is changing. IPC_STRUCT_MEMBER(int, id)
diff --git a/chromecast/media/cma/backend/BUILD.gn b/chromecast/media/cma/backend/BUILD.gn index 7cfad18e..2155e12 100644 --- a/chromecast/media/cma/backend/BUILD.gn +++ b/chromecast/media/cma/backend/BUILD.gn
@@ -206,6 +206,8 @@ "media_pipeline_backend_for_mixer.h", "mixer_input.cc", "mixer_input.h", + "mixer_pipeline.cc", + "mixer_pipeline.h", "post_processing_pipeline.h", "post_processing_pipeline_impl.cc", "post_processing_pipeline_impl.h",
diff --git a/chromecast/media/cma/backend/cast_media_shlib_mixer_audio.cc b/chromecast/media/cma/backend/cast_media_shlib_mixer_audio.cc index 42563d5..dd6dd5f7 100644 --- a/chromecast/media/cma/backend/cast_media_shlib_mixer_audio.cc +++ b/chromecast/media/cma/backend/cast_media_shlib_mixer_audio.cc
@@ -7,6 +7,7 @@ #include "chromecast/public/cast_media_shlib.h" #include <string> +#include <utility> #include "chromecast/media/cma/backend/stream_mixer.h" @@ -22,8 +23,8 @@ StreamMixer::Get()->RemoveLoopbackAudioObserver(observer); } -void CastMediaShlib::ResetPostProcessors() { - StreamMixer::Get()->ResetPostProcessors(); +void CastMediaShlib::ResetPostProcessors(CastMediaShlib::ResultCallback cb) { + StreamMixer::Get()->ResetPostProcessors(std::move(cb)); } void CastMediaShlib::SetPostProcessorConfig(const std::string& name,
diff --git a/chromecast/media/cma/backend/filter_group.cc b/chromecast/media/cma/backend/filter_group.cc index a4be583a..c86c59c5 100644 --- a/chromecast/media/cma/backend/filter_group.cc +++ b/chromecast/media/cma/backend/filter_group.cc
@@ -20,14 +20,13 @@ FilterGroup::FilterGroup(int num_channels, GroupType type, - bool mix_to_mono, const std::string& name, std::unique_ptr<PostProcessingPipeline> pipeline, - const std::unordered_set<std::string>& device_ids, + const base::flat_set<std::string>& device_ids, const std::vector<FilterGroup*>& mixed_inputs) : num_channels_(num_channels), type_(type), - mix_to_mono_(mix_to_mono), + mix_to_mono_(false), playout_channel_(kChannelAll), name_(name), device_ids_(device_ids), @@ -41,10 +40,6 @@ for (auto* const m : mixed_inputs) { DCHECK_EQ(m->GetOutputChannelCount(), num_channels); } - // Don't need mono mixer if input is single channel. - if (num_channels == 1) { - mix_to_mono_ = false; - } } FilterGroup::~FilterGroup() = default; @@ -82,6 +77,7 @@ AudioContentType content_type = static_cast<AudioContentType>(-1); rendering_delay.delay_microseconds += GetRenderingDelayMicroseconds(); + rendering_delay_to_output_ = rendering_delay; // Recursively mix inputs. for (auto* filter_group : mixed_inputs_) { @@ -205,6 +201,11 @@ output_samples_per_second_; } +MediaPipelineBackend::AudioDecoder::RenderingDelay +FilterGroup::GetRenderingDelayToOutput() { + return rendering_delay_to_output_; +} + int FilterGroup::GetOutputChannelCount() { return post_processing_pipeline_->NumOutputChannels(); }
diff --git a/chromecast/media/cma/backend/filter_group.h b/chromecast/media/cma/backend/filter_group.h index 0ce8dff..bc90f35 100644 --- a/chromecast/media/cma/backend/filter_group.h +++ b/chromecast/media/cma/backend/filter_group.h
@@ -9,7 +9,6 @@ #include <memory> #include <string> -#include <unordered_set> #include <vector> #include "base/containers/flat_set.h" @@ -43,9 +42,6 @@ // some features are specific to certain locations: // - mono mixer takes place at the end of kFinalMix. // - channel selection occurs before post-processing in kLinearize. - // |mix_to_mono| enables mono mixing in the pipeline. The number of audio - // output channels will be 1 if it is set to true, otherwise it remains - // same as |num_channels|. // |name| is used for debug printing // |pipeline| - processing pipeline. // |device_ids| is a set of strings that is used as a filter to determine @@ -58,10 +54,9 @@ FilterGroup(int num_channels, GroupType type, - bool mix_to_mono, const std::string& name, std::unique_ptr<PostProcessingPipeline> pipeline, - const std::unordered_set<std::string>& device_ids, + const base::flat_set<std::string>& device_ids, const std::vector<FilterGroup*>& mixed_inputs); ~FilterGroup(); @@ -89,6 +84,11 @@ // (Not recursive). int64_t GetRenderingDelayMicroseconds(); + // Gets the delay of this FilterGroup and all downstream FilterGroups. + // Computed recursively when MixAndFilter() is called. + MediaPipelineBackend::AudioDecoder::RenderingDelay + GetRenderingDelayToOutput(); + // Retrieves a pointer to the output buffer. This will crash if called before // MixAndFilter(), and the data & memory location may change each time // MixAndFilter() is called. @@ -127,7 +127,7 @@ bool mix_to_mono_; int playout_channel_; const std::string name_; - const std::unordered_set<std::string> device_ids_; + const base::flat_set<std::string> device_ids_; std::vector<FilterGroup*> mixed_inputs_; base::flat_set<MixerInput*> active_inputs_; @@ -135,6 +135,7 @@ int frames_zeroed_; float last_volume_; int64_t delay_frames_; + MediaPipelineBackend::AudioDecoder::RenderingDelay rendering_delay_to_output_; AudioContentType content_type_; // Buffers that hold audio data while it is mixed.
diff --git a/chromecast/media/cma/backend/filter_group_unittest.cc b/chromecast/media/cma/backend/filter_group_unittest.cc index e9378cf..9ad6560 100644 --- a/chromecast/media/cma/backend/filter_group_unittest.cc +++ b/chromecast/media/cma/backend/filter_group_unittest.cc
@@ -4,6 +4,7 @@ #include "chromecast/media/cma/backend/filter_group.h" +#include "base/containers/flat_set.h" #include "base/memory/ptr_util.h" #include "chromecast/media/cma/backend/mixer_input.h" #include "chromecast/media/cma/backend/mock_mixer_source.h" @@ -170,10 +171,10 @@ EXPECT_CALL(*post_processor_, SetContentType(kDefaultContentType)); EXPECT_CALL(*post_processor_, UpdatePlayoutChannel(kDefaultPlayoutChannel)); filter_group_ = std::make_unique<FilterGroup>( - kNumInputChannels, type, mix_to_mono, "test_filter", - std::move(post_processor), - std::unordered_set<std::string>() /* device_ids */, + kNumInputChannels, type, "test_filter", std::move(post_processor), + base::flat_set<std::string>() /* device_ids */, std::vector<FilterGroup*>()); + filter_group_->SetMixToMono(mix_to_mono); filter_group_->Initialize(kInputSampleRate); filter_group_->AddInput(&input_); filter_group_->UpdatePlayoutChannel(kChannelAll);
diff --git a/chromecast/media/cma/backend/mixer_pipeline.cc b/chromecast/media/cma/backend/mixer_pipeline.cc new file mode 100644 index 0000000..1cc02eb6 --- /dev/null +++ b/chromecast/media/cma/backend/mixer_pipeline.cc
@@ -0,0 +1,220 @@ +// 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 "chromecast/media/cma/backend/mixer_pipeline.h" + +#include <utility> + +#include "base/containers/flat_set.h" +#include "base/logging.h" +#include "chromecast/media/base/audio_device_ids.h" +#include "chromecast/media/cma/backend/filter_group.h" +#include "chromecast/media/cma/backend/post_processing_pipeline_impl.h" +#include "chromecast/media/cma/backend/post_processing_pipeline_parser.h" +#include "media/audio/audio_device_description.h" + +namespace chromecast { +namespace media { + +namespace { + +const int kNumInputChannels = 2; + +bool IsOutputDeviceId(const std::string& device) { + return device == ::media::AudioDeviceDescription::kDefaultDeviceId || + device == ::media::AudioDeviceDescription::kCommunicationsDeviceId || + device == kLocalAudioDeviceId || device == kAlarmAudioDeviceId || + device == kPlatformAudioDeviceId /* e.g. bluetooth and aux */ || + device == kTtsAudioDeviceId || device == kBypassAudioDeviceId; +} + +std::unique_ptr<FilterGroup> CreateFilterGroup( + FilterGroup::GroupType type, + int input_channels, + const std::string& name, + const base::ListValue* filter_list, + const base::flat_set<std::string>& device_ids, + const std::vector<FilterGroup*>& mixed_inputs, + PostProcessingPipelineFactory* ppp_factory) { + DCHECK(ppp_factory); + auto pipeline = + ppp_factory->CreatePipeline(name, filter_list, input_channels); + return std::make_unique<FilterGroup>(input_channels, type, name, + std::move(pipeline), device_ids, + mixed_inputs); +} + +} // namespace + +// static +std::unique_ptr<MixerPipeline> MixerPipeline::CreateMixerPipeline( + PostProcessingPipelineParser* config, + PostProcessingPipelineFactory* factory) { + std::unique_ptr<MixerPipeline> mixer_pipeline(new MixerPipeline); + + if (mixer_pipeline->BuildPipeline(config, factory)) { + return mixer_pipeline; + } + return nullptr; +} + +MixerPipeline::MixerPipeline() = default; +MixerPipeline::~MixerPipeline() = default; + +bool MixerPipeline::BuildPipeline(PostProcessingPipelineParser* config, + PostProcessingPipelineFactory* factory) { + DCHECK(config); + DCHECK(factory); + base::flat_set<std::string> used_streams; + for (auto& stream_pipeline : config->GetStreamPipelines()) { + const auto& device_ids = stream_pipeline.stream_types; + for (const std::string& stream_type : device_ids) { + if (!IsOutputDeviceId(stream_type)) { + LOG(ERROR) << stream_type + << " is not a stream type. Stream types are listed " + << "in chromecast/media/base/audio_device_ids.cc and " + << "media/audio/audio_device_description.cc"; + return false; + } + if (!used_streams.insert(stream_type).second) { + LOG(ERROR) << "Multiple instances of stream type '" << stream_type + << "' in " << config->GetFilePath() << "."; + return false; + } + filter_groups_.push_back(CreateFilterGroup( + FilterGroup::GroupType::kStream, kNumInputChannels, + *device_ids.begin() /* name */, stream_pipeline.pipeline, device_ids, + std::vector<FilterGroup*>() /* mixed_inputs */, factory)); + if (device_ids.find(::media::AudioDeviceDescription::kDefaultDeviceId) != + device_ids.end()) { + default_stream_group_ = filter_groups_.back().get(); + } + } + } + + if (!filter_groups_.empty()) { + std::vector<FilterGroup*> filter_group_ptrs(filter_groups_.size()); + int mix_group_input_channels = filter_groups_[0]->GetOutputChannelCount(); + for (size_t i = 0; i < filter_groups_.size(); ++i) { + if (mix_group_input_channels != + filter_groups_[i]->GetOutputChannelCount()) { + LOG(ERROR) + << "All output stream mixers must have the same number of channels" + << filter_groups_[i]->name() << " has " + << filter_groups_[i]->GetOutputChannelCount() << " but others have " + << mix_group_input_channels; + return false; + } + filter_group_ptrs[i] = filter_groups_[i].get(); + } + + filter_groups_.push_back(CreateFilterGroup( + FilterGroup::GroupType::kFinalMix, mix_group_input_channels, "mix", + config->GetMixPipeline(), + base::flat_set<std::string>() /* device_ids */, filter_group_ptrs, + factory)); + } else { + // Mix group directly mixes all inputs. + std::string kDefaultDeviceId = + ::media::AudioDeviceDescription::kDefaultDeviceId; + filter_groups_.push_back(CreateFilterGroup( + FilterGroup::GroupType::kFinalMix, kNumInputChannels, "mix", + config->GetMixPipeline(), + base::flat_set<std::string>({kDefaultDeviceId}), + std::vector<FilterGroup*>() /* mixed_inputs */, factory)); + default_stream_group_ = filter_groups_.back().get(); + } + + loopback_output_group_ = filter_groups_.back().get(); + + filter_groups_.push_back(CreateFilterGroup( + FilterGroup::GroupType::kLinearize, + loopback_output_group_->GetOutputChannelCount(), "linearize", + config->GetLinearizePipeline(), + base::flat_set<std::string>() /* device_ids */, + std::vector<FilterGroup*>({loopback_output_group_}), factory)); + output_group_ = filter_groups_.back().get(); + + LOG(INFO) << "PostProcessor configuration:"; + if (default_stream_group_ == loopback_output_group_) { + LOG(INFO) << "Stream layer: none"; + } else { + LOG(INFO) << "Stream layer: " + << default_stream_group_->GetOutputChannelCount() << " channels"; + } + LOG(INFO) << "Mix filter: " << loopback_output_group_->GetOutputChannelCount() + << " channels"; + LOG(INFO) << "Linearize filter: " << output_group_->GetOutputChannelCount() + << " channels"; + + return true; +} + +void MixerPipeline::Initialize(int output_samples_per_second_) { + for (auto&& filter_group : filter_groups_) { + filter_group->Initialize(output_samples_per_second_); + } +} + +FilterGroup* MixerPipeline::GetInputGroup(const std::string& device_id) { + for (auto&& filter_group : filter_groups_) { + if (filter_group->CanProcessInput(device_id)) { + return filter_group.get(); + break; + } + } + + if (default_stream_group_) { + return default_stream_group_; + } + + NOTREACHED() << "Could not find a filter group to re-attach " << device_id; + return nullptr; +} + +void MixerPipeline::MixAndFilter( + int frames_per_write, + MediaPipelineBackend::AudioDecoder::RenderingDelay rendering_delay) { + output_group_->MixAndFilter(frames_per_write, rendering_delay); +} + +float* MixerPipeline::GetLoopbackOutput() { + return loopback_output_group_->GetOutputBuffer(); +} + +float* MixerPipeline::GetOutput() { + return output_group_->GetOutputBuffer(); +} + +int MixerPipeline::GetLoopbackChannelCount() const { + return loopback_output_group_->GetOutputChannelCount(); +} + +int MixerPipeline::GetOutputChannelCount() const { + return output_group_->GetOutputChannelCount(); +} + +int64_t MixerPipeline::GetPostLoopbackRenderingDelayMicroseconds() const { + return output_group_->GetRenderingDelayMicroseconds(); +} + +void MixerPipeline::SetPostProcessorConfig(const std::string& name, + const std::string& config) { + for (auto&& filter_group : filter_groups_) { + filter_group->SetPostProcessorConfig(name, config); + } +} + +void MixerPipeline::SetMixToMono(bool mix_to_mono) { + loopback_output_group_->SetMixToMono(mix_to_mono); +} + +void MixerPipeline::SetPlayoutChannel(int playout_channel) { + for (auto& filter_group : filter_groups_) { + filter_group->UpdatePlayoutChannel(playout_channel); + } +} + +} // namespace media +} // namespace chromecast
diff --git a/chromecast/media/cma/backend/mixer_pipeline.h b/chromecast/media/cma/backend/mixer_pipeline.h new file mode 100644 index 0000000..086949aa --- /dev/null +++ b/chromecast/media/cma/backend/mixer_pipeline.h
@@ -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. + +#ifndef CHROMECAST_MEDIA_CMA_BACKEND_MIXER_PIPELINE_H_ +#define CHROMECAST_MEDIA_CMA_BACKEND_MIXER_PIPELINE_H_ + +#include <cstdint> +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "chromecast/public/media/audio_post_processor_shlib.h" +#include "chromecast/public/media/media_pipeline_backend.h" + +namespace chromecast { +namespace media { + +class FilterGroup; +class PostProcessingPipelineParser; +class PostProcessingPipelineFactory; + +// Provides mixer and post-processing functionality for StreamMixer. +// Internally, MixerPipeline is a tree of post processors with two taps - +// LoopbackOutput and Output. Calling MixAndFilter causes the pipeline to pull +// data from inputs, mixing and filtering as described in cast_audio.json. +class MixerPipeline { + public: + // Attempts to create a pipeline from |config|. + // Returns nullptr if config fails to parse. + static std::unique_ptr<MixerPipeline> CreateMixerPipeline( + PostProcessingPipelineParser* parser, + PostProcessingPipelineFactory* factory); + + ~MixerPipeline(); + + // Sets the sample rate of all processors. + void Initialize(int samples_per_second); + + // Returns the FilterGroup that should process a stream with |device_id| or + // |nullptr| if no matching FilterGroup is found. + FilterGroup* GetInputGroup(const std::string& device_id); + + // Polls |MixerInput|s for |frames_per_write| frames of audio data, mixes the + // inputs, and applies PostProcessors. + // |rendering_delay| is the rendering delay of the output device, and is used + // to calculate the delay from various points in the pipeline. + void MixAndFilter( + int frames_per_write, + MediaPipelineBackend::AudioDecoder::RenderingDelay rendering_delay); + + // Returns the output data from the "mix" group. + float* GetLoopbackOutput(); + + // Returns the output data from the "linearize" group. + float* GetOutput(); + + // Returns the number of channels that will be present in GetLoopbackOutput(). + int GetLoopbackChannelCount() const; + + // Returns the number of channels that will be present in GetOutput(). + int GetOutputChannelCount() const; + + // Attempts to send |config| to PostProcessors with |name|. + void SetPostProcessorConfig(const std::string& name, + const std::string& config); + + // Returns the rendering delay between audio coming from GetLoopbackOutput() + // and GetOutput(), i.e. the group delay of PostProcessors in "linearize" + int64_t GetPostLoopbackRenderingDelayMicroseconds() const; + + // Informs FilterGroups that the output should be mixed to mono. + void SetMixToMono(bool mix_to_mono); + + // Informs FilterGroups and PostProcessors which channel will be played out. + // |playout_channel| may be |-1| to signal all channels will be played out. + void SetPlayoutChannel(int playout_channel); + + private: + // External classes should call CreateMixerPipeline. + MixerPipeline(); + + // Attempts to build a pipeline using |config|. Returns |true| IFF successful. + bool BuildPipeline(PostProcessingPipelineParser* config, + PostProcessingPipelineFactory* factory); + + std::vector<std::unique_ptr<FilterGroup>> filter_groups_; + FilterGroup* default_stream_group_ = nullptr; + FilterGroup* loopback_output_group_ = nullptr; + FilterGroup* output_group_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(MixerPipeline); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_MIXER_PIPELINE_H_
diff --git a/chromecast/media/cma/backend/post_processing_pipeline_parser.cc b/chromecast/media/cma/backend/post_processing_pipeline_parser.cc index 7bc3fa61..deac7d19 100644 --- a/chromecast/media/cma/backend/post_processing_pipeline_parser.cc +++ b/chromecast/media/cma/backend/post_processing_pipeline_parser.cc
@@ -4,13 +4,11 @@ #include "chromecast/media/cma/backend/post_processing_pipeline_parser.h" -#include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/logging.h" #include "base/values.h" #include "chromecast/base/serializers.h" #include "chromecast/media/base/audio_device_ids.h" -#include "chromecast/media/cma/backend/cast_audio_json.h" #include "media/audio/audio_device_description.h" namespace chromecast { @@ -29,7 +27,7 @@ StreamPipelineDescriptor::StreamPipelineDescriptor( const base::ListValue* pipeline_in, - const std::unordered_set<std::string>& stream_types_in) + const base::flat_set<std::string>& stream_types_in) : pipeline(pipeline_in), stream_types(stream_types_in) {} StreamPipelineDescriptor::~StreamPipelineDescriptor() = default; @@ -39,21 +37,27 @@ : StreamPipelineDescriptor(other.pipeline, other.stream_types) {} PostProcessingPipelineParser::PostProcessingPipelineParser( - const std::string& json) - : postprocessor_config_(nullptr) { - base::FilePath path = CastAudioJson::GetFilePath(); - if (json.empty() && !base::PathExists(path)) { - LOG(WARNING) << "Could not open post-processing config in " << path << "."; + std::unique_ptr<base::DictionaryValue> config_dict) + : file_path_(""), config_dict_(std::move(config_dict)) { + CHECK(config_dict_) << "Invalid JSON"; + if (!config_dict_->GetDictionary(kPostProcessorsKey, + &postprocessor_config_)) { + LOG(WARNING) << "No post-processor config found."; + } +} + +PostProcessingPipelineParser::PostProcessingPipelineParser( + const base::FilePath& file_path) + : file_path_(file_path) { + if (!base::PathExists(file_path_)) { + LOG(WARNING) << "No post-processing config found at " << file_path_ << "."; return; } - if (json.empty()) { - config_dict_ = base::DictionaryValue::From(DeserializeJsonFromFile(path)); - } else { - config_dict_ = base::DictionaryValue::From(DeserializeFromJson(json)); - } + config_dict_ = + base::DictionaryValue::From(DeserializeJsonFromFile(file_path_)); + CHECK(config_dict_) << "Invalid JSON in " << file_path_; - CHECK(config_dict_) << "Invalid JSON in " << path; if (!config_dict_->GetDictionary(kPostProcessorsKey, &postprocessor_config_)) { LOG(WARNING) << "No post-processor config found."; @@ -82,7 +86,7 @@ const base::ListValue* streams_list; CHECK(pipeline_description_dict->GetList(kStreamsKey, &streams_list)); - std::unordered_set<std::string> streams_set; + base::flat_set<std::string> streams_set; for (size_t stream = 0; stream < streams_list->GetSize(); ++stream) { std::string stream_name; CHECK(streams_list->GetString(stream, &stream_name)); @@ -109,8 +113,7 @@ if (!postprocessor_config_ || !postprocessor_config_->GetDictionary(key, &stream_dict)) { LOG(WARNING) << "No post-processor description found for \"" << key - << "\" in " << CastAudioJson::GetFilePath() - << ". Using passthrough."; + << "\" in " << file_path_ << ". Using passthrough."; return nullptr; } const base::ListValue* out_list; @@ -119,5 +122,9 @@ return out_list; } +base::FilePath PostProcessingPipelineParser::GetFilePath() const { + return file_path_; +} + } // namespace media } // namespace chromecast
diff --git a/chromecast/media/cma/backend/post_processing_pipeline_parser.h b/chromecast/media/cma/backend/post_processing_pipeline_parser.h index b66f237..b5aadea 100644 --- a/chromecast/media/cma/backend/post_processing_pipeline_parser.h +++ b/chromecast/media/cma/backend/post_processing_pipeline_parser.h
@@ -7,9 +7,10 @@ #include <memory> #include <string> -#include <unordered_set> #include <vector> +#include "base/containers/flat_set.h" +#include "base/files/file_path.h" #include "base/macros.h" namespace base { @@ -29,11 +30,10 @@ // "config": "CONFIGURATION_STRING"}, // ... ] const base::ListValue* pipeline; - std::unordered_set<std::string> stream_types; + base::flat_set<std::string> stream_types; - StreamPipelineDescriptor( - const base::ListValue* pipeline_in, - const std::unordered_set<std::string>& stream_types_in); + StreamPipelineDescriptor(const base::ListValue* pipeline_in, + const base::flat_set<std::string>& stream_types_in); ~StreamPipelineDescriptor(); StreamPipelineDescriptor(const StreamPipelineDescriptor& other); StreamPipelineDescriptor operator=(const StreamPipelineDescriptor& other) = @@ -43,9 +43,12 @@ // Helper class to parse post-processing pipeline descriptor file. class PostProcessingPipelineParser { public: - // |json|, if provided, is used instead of reading from file. - // |json| should be provided in tests only. - explicit PostProcessingPipelineParser(const std::string& json = ""); + PostProcessingPipelineParser(const base::FilePath& path); + + // For testing only: + PostProcessingPipelineParser( + std::unique_ptr<base::DictionaryValue> config_dict); + ~PostProcessingPipelineParser(); std::vector<StreamPipelineDescriptor> GetStreamPipelines(); @@ -55,11 +58,15 @@ const base::ListValue* GetMixPipeline(); const base::ListValue* GetLinearizePipeline(); + // Returns the file path used to load this object. + base::FilePath GetFilePath() const; + private: const base::ListValue* GetPipelineByKey(const std::string& key); + const base::FilePath file_path_; std::unique_ptr<base::DictionaryValue> config_dict_; - const base::DictionaryValue* postprocessor_config_; + const base::DictionaryValue* postprocessor_config_ = nullptr; DISALLOW_COPY_AND_ASSIGN(PostProcessingPipelineParser); };
diff --git a/chromecast/media/cma/backend/stream_mixer.cc b/chromecast/media/cma/backend/stream_mixer.cc index 8c1aef84..c4ee0c29 100644 --- a/chromecast/media/cma/backend/stream_mixer.cc +++ b/chromecast/media/cma/backend/stream_mixer.cc
@@ -19,13 +19,13 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "chromecast/base/chromecast_switches.h" +#include "chromecast/base/serializers.h" #include "chromecast/media/base/audio_device_ids.h" #include "chromecast/media/cma/backend/audio_output_redirector.h" #include "chromecast/media/cma/backend/cast_audio_json.h" #include "chromecast/media/cma/backend/filter_group.h" #include "chromecast/media/cma/backend/post_processing_pipeline_impl.h" #include "chromecast/media/cma/backend/post_processing_pipeline_parser.h" -#include "chromecast/public/media/audio_post_processor_shlib.h" #include "chromecast/public/media/mixer_output_stream.h" #include "media/audio/audio_device_description.h" @@ -118,31 +118,6 @@ task_runner->PostTask(FROM_HERE, std::move(task)); } -bool IsOutputDeviceId(const std::string& device) { - return device == ::media::AudioDeviceDescription::kDefaultDeviceId || - device == ::media::AudioDeviceDescription::kCommunicationsDeviceId || - device == kLocalAudioDeviceId || device == kAlarmAudioDeviceId || - device == kPlatformAudioDeviceId /* e.g. bluetooth and aux */ || - device == kTtsAudioDeviceId || device == kBypassAudioDeviceId; -} - -std::unique_ptr<FilterGroup> CreateFilterGroup( - FilterGroup::GroupType type, - int input_channels, - bool mix_to_mono, - const std::string& name, - const base::ListValue* filter_list, - const std::unordered_set<std::string>& device_ids, - const std::vector<FilterGroup*>& mixed_inputs, - std::unique_ptr<PostProcessingPipelineFactory>& ppp_factory) { - DCHECK(ppp_factory); - auto pipeline = - ppp_factory->CreatePipeline(name, filter_list, input_channels); - return std::make_unique<FilterGroup>(input_channels, type, mix_to_mono, name, - std::move(pipeline), device_ids, - mixed_inputs); -} - int GetFixedSampleRate() { int fixed_sample_rate = GetSwitchValueNonNegativeInt( switches::kAudioOutputSampleRate, MixerOutputStream::kInvalidSampleRate); @@ -253,9 +228,8 @@ LOG(INFO) << "Setting fixed sample rate to " << fixed_sample_rate_; } - // Read post-processing configuration file. - PostProcessingPipelineParser pipeline_parser; - CreatePostProcessors(&pipeline_parser); + CreatePostProcessors([](bool, const std::string&) {}, + "" /* override_config */); // TODO(jyw): command line flag for filter frame alignment. DCHECK_EQ(filter_frame_alignment_ & (filter_frame_alignment_ - 1), 0) @@ -273,11 +247,14 @@ } } -void StreamMixer::ResetPostProcessors() { - POST_THROUGH_INPUT_THREAD(&StreamMixer::ResetPostProcessorsOnThread); +void StreamMixer::ResetPostProcessors(CastMediaShlib::ResultCallback callback) { + POST_THROUGH_INPUT_THREAD(&StreamMixer::ResetPostProcessorsOnThread, + std::move(callback), ""); } -void StreamMixer::ResetPostProcessorsOnThread() { +void StreamMixer::ResetPostProcessorsOnThread( + CastMediaShlib::ResultCallback callback, + const std::string& override_config) { DCHECK(mixer_task_runner_->BelongsToCurrentThread()); // Detach inputs. @@ -285,42 +262,61 @@ input.second->SetFilterGroup(nullptr); } - // Re-create post processors. - filter_groups_.clear(); - default_filter_ = nullptr; - - PostProcessingPipelineParser parser; - CreatePostProcessors(&parser); - - if (state_ == kStateRunning) { - for (auto&& filter_group : filter_groups_) { - filter_group->Initialize(output_samples_per_second_); - } - } + CreatePostProcessors(std::move(callback), override_config); // Re-attach inputs. for (const auto& input : inputs_) { - MixerInput::Source* input_source = input.first; + FilterGroup* input_group = + mixer_pipeline_->GetInputGroup(input.first->device_id()); + DCHECK(input_group) << "No input group for input.first->device_id()"; + input.second->SetFilterGroup(input_group); + } + UpdatePlayoutChannel(); +} - FilterGroup* input_filter_group = default_filter_; - for (auto&& filter_group : filter_groups_) { - if (filter_group->CanProcessInput(input_source->device_id())) { - input_filter_group = filter_group.get(); - break; - } - } +// May be called on mixer_task_runner_ or from ctor +void StreamMixer::CreatePostProcessors(CastMediaShlib::ResultCallback callback, + const std::string& override_config) { + // (Re)-create post processors. + mixer_pipeline_.reset(); - if (input_filter_group) { - LOG(INFO) << "Re-attach input of type " << input_source->device_id() - << " to " << input_filter_group->name(); - input.second->SetFilterGroup(input_filter_group); - } else { - NOTREACHED() << "Could not find a filter group to re-attach " - << input_source->device_id(); - } + if (!override_config.empty()) { + PostProcessingPipelineParser parser( + base::DictionaryValue::From(DeserializeFromJson(override_config))); + mixer_pipeline_ = MixerPipeline::CreateMixerPipeline( + &parser, post_processing_pipeline_factory_.get()); + } else { + PostProcessingPipelineParser parser(CastAudioJson::GetFilePath()); + mixer_pipeline_ = MixerPipeline::CreateMixerPipeline( + &parser, post_processing_pipeline_factory_.get()); } - UpdatePlayoutChannel(); + // Attempt to fall back to built-in cast_audio.json, unless we were reset with + // an override config. + if ((!mixer_pipeline_ || !PostProcessorsHaveCorrectNumOutputs()) && + override_config.empty()) { + LOG(WARNING) << "Invalid cast_audio.json config loaded. Retrying with " + "read-only config"; + callback(false, + "Unable to build pipeline."); // TODO(bshaya): Send more specific + // error message. + callback = nullptr; + PostProcessingPipelineParser parser(CastAudioJson::GetReadOnlyFilePath()); + mixer_pipeline_.reset(); + mixer_pipeline_ = MixerPipeline::CreateMixerPipeline( + &parser, post_processing_pipeline_factory_.get()); + } + + CHECK(mixer_pipeline_) << "Unable to load post processor config!"; + CHECK(PostProcessorsHaveCorrectNumOutputs()); + + if (state_ == kStateRunning) { + mixer_pipeline_->Initialize(output_samples_per_second_); + } + + if (callback) { + callback(true, ""); + } } void StreamMixer::ResetPostProcessorsForTest( @@ -328,11 +324,9 @@ const std::string& pipeline_json) { DCHECK(mixer_task_runner_->BelongsToCurrentThread()); LOG(INFO) << __FUNCTION__ << " disregard previous PostProcessor messages."; - filter_groups_.clear(); - default_filter_ = nullptr; + mixer_pipeline_.reset(); post_processing_pipeline_factory_ = std::move(pipeline_factory); - PostProcessingPipelineParser parser(pipeline_json); - CreatePostProcessors(&parser); + ResetPostProcessorsOnThread([](bool, const std::string&) {}, pipeline_json); } void StreamMixer::SetNumOutputChannelsForTest(int num_output_channels) { @@ -340,86 +334,6 @@ num_output_channels_ = num_output_channels; } -void StreamMixer::CreatePostProcessors( - PostProcessingPipelineParser* pipeline_parser) { - std::unordered_set<std::string> used_streams; - for (auto& stream_pipeline : pipeline_parser->GetStreamPipelines()) { - const auto& device_ids = stream_pipeline.stream_types; - for (const std::string& stream_type : device_ids) { - CHECK(IsOutputDeviceId(stream_type)) - << stream_type << " is not a stream type. Stream types are listed " - << "in chromecast/media/base/audio_device_ids.cc and " - << "media/audio/audio_device_description.cc"; - CHECK(used_streams.insert(stream_type).second) - << "Multiple instances of stream type '" << stream_type << "' in " - << CastAudioJson::GetFilePath() << "."; - } - filter_groups_.push_back(CreateFilterGroup( - FilterGroup::GroupType::kStream, kNumInputChannels, - false /* mono_mixer */, *device_ids.begin() /* name */, - stream_pipeline.pipeline, device_ids, - std::vector<FilterGroup*>() /* mixed_inputs */, - post_processing_pipeline_factory_)); - if (device_ids.find(::media::AudioDeviceDescription::kDefaultDeviceId) != - device_ids.end()) { - default_filter_ = filter_groups_.back().get(); - } - } - - bool enabled_mono_mixer = (num_output_channels_ == 1); - if (!filter_groups_.empty()) { - std::vector<FilterGroup*> filter_group_ptrs(filter_groups_.size()); - int mix_group_input_channels = filter_groups_[0]->GetOutputChannelCount(); - for (size_t i = 0; i < filter_groups_.size(); ++i) { - DCHECK_EQ(mix_group_input_channels, - filter_groups_[i]->GetOutputChannelCount()) - << "All output stream mixers must have the same number of channels"; - filter_group_ptrs[i] = filter_groups_[i].get(); - } - - // Enable Mono mixer in |mix_filter_| if necessary. - filter_groups_.push_back(CreateFilterGroup( - FilterGroup::GroupType::kFinalMix, mix_group_input_channels, - enabled_mono_mixer, "mix", pipeline_parser->GetMixPipeline(), - std::unordered_set<std::string>() /* device_ids */, filter_group_ptrs, - post_processing_pipeline_factory_)); - } else { - // Mix group directly mixes all inputs. - std::string kDefaultDeviceId = - ::media::AudioDeviceDescription::kDefaultDeviceId; - filter_groups_.push_back(CreateFilterGroup( - FilterGroup::GroupType::kFinalMix, kNumInputChannels, - enabled_mono_mixer, "mix", pipeline_parser->GetMixPipeline(), - std::unordered_set<std::string>({kDefaultDeviceId}), - std::vector<FilterGroup*>() /* mixed_inputs */, - post_processing_pipeline_factory_)); - default_filter_ = filter_groups_.back().get(); - } - - mix_filter_ = filter_groups_.back().get(); - - filter_groups_.push_back(CreateFilterGroup( - FilterGroup::GroupType::kLinearize, mix_filter_->GetOutputChannelCount(), - false /* mono_mixer */, "linearize", - pipeline_parser->GetLinearizePipeline(), - std::unordered_set<std::string>() /* device_ids */, - std::vector<FilterGroup*>({mix_filter_}), - post_processing_pipeline_factory_)); - linearize_filter_ = filter_groups_.back().get(); - - LOG(INFO) << "PostProcessor configuration:"; - if (default_filter_ == mix_filter_) { - LOG(INFO) << "Stream layer: none"; - } else { - LOG(INFO) << "Stream layer: " << default_filter_->GetOutputChannelCount() - << " channels"; - } - LOG(INFO) << "Mix filter: " << mix_filter_->GetOutputChannelCount() - << " channels"; - LOG(INFO) << "Linearize filter: " - << linearize_filter_->GetOutputChannelCount() << " channels"; -} - StreamMixer::~StreamMixer() { VLOG(1) << __func__; if (shim_thread_) { @@ -489,12 +403,8 @@ output_->OptimalWriteFramesCount() & ~(filter_frame_alignment_ - 1); CHECK_GT(frames_per_write_, 0); - ValidatePostProcessors(); - // Initialize filters. - for (auto&& filter_group : filter_groups_) { - filter_group->Initialize(output_samples_per_second_); - } + mixer_pipeline_->Initialize(output_samples_per_second_); for (auto& redirector : audio_output_redirectors_) { redirector.second->Start(output_samples_per_second_); @@ -590,25 +500,14 @@ Start(); } - FilterGroup* input_filter_group = default_filter_; - for (auto&& filter_group : filter_groups_) { - if (filter_group->CanProcessInput(input_source->device_id())) { - input_filter_group = filter_group.get(); - break; - } - } - if (input_filter_group) { - LOG(INFO) << "Added input of type " << input_source->device_id() << " to " - << input_filter_group->name(); - } else { - NOTREACHED() << "Could not find a filter group for " - << input_source->device_id() << "\n" - << "(consider adding a 'default' processor)"; - } + FilterGroup* input_group = + mixer_pipeline_->GetInputGroup(input_source->device_id()); + DCHECK(input_group) << "Could not find a processor for " + << input_source->device_id(); auto input = std::make_unique<MixerInput>( input_source, output_samples_per_second_, frames_per_write_, - GetTotalRenderingDelay(input_filter_group), input_filter_group); + GetTotalRenderingDelay(input_group), input_group); if (state_ != kStateRunning) { // Mixer error occurred, signal error. MixerInput* input_ptr = input.get(); @@ -670,8 +569,6 @@ void StreamMixer::UpdatePlayoutChannel() { DCHECK(mixer_task_runner_->BelongsToCurrentThread()); - DCHECK(mix_filter_); - DCHECK(linearize_filter_); int playout_channel; if (inputs_.empty()) { @@ -688,11 +585,9 @@ playout_channel >= 0 && playout_channel < kNumInputChannels); LOG(INFO) << "Update playout channel: " << playout_channel; - mix_filter_->SetMixToMono(num_output_channels_ == 1 && - playout_channel == kChannelAll); - for (auto& filter_group : filter_groups_) { - filter_group->UpdatePlayoutChannel(playout_channel); - } + mixer_pipeline_->SetMixToMono(num_output_channels_ == 1 && + playout_channel == kChannelAll); + mixer_pipeline_->SetPlayoutChannel(playout_channel); } MediaPipelineBackend::AudioDecoder::RenderingDelay @@ -701,20 +596,12 @@ if (!output_) { return MediaPipelineBackend::AudioDecoder::RenderingDelay(); } - MediaPipelineBackend::AudioDecoder::RenderingDelay delay = - output_->GetRenderingDelay(); if (!filter_group) { - return delay; + return output_->GetRenderingDelay(); } - if (filter_group != mix_filter_) { - delay.delay_microseconds += filter_group->GetRenderingDelayMicroseconds(); - } - delay.delay_microseconds += mix_filter_->GetRenderingDelayMicroseconds(); - delay.delay_microseconds += - linearize_filter_->GetRenderingDelayMicroseconds(); - - return delay; + // Includes |output_->GetRenderingDelay()|. + return filter_group->GetRenderingDelayToOutput(); } void StreamMixer::PlaybackLoop() { @@ -740,15 +627,16 @@ // Recursively mix and filter each group. MediaPipelineBackend::AudioDecoder::RenderingDelay rendering_delay = output_->GetRenderingDelay(); - linearize_filter_->MixAndFilter(frames_per_write_, rendering_delay); + mixer_pipeline_->MixAndFilter(frames_per_write_, rendering_delay); int64_t expected_playback_time; if (rendering_delay.timestamp_microseconds == kNoTimestamp) { expected_playback_time = kNoTimestamp; } else { - expected_playback_time = rendering_delay.timestamp_microseconds + - rendering_delay.delay_microseconds + - linearize_filter_->GetRenderingDelayMicroseconds(); + expected_playback_time = + rendering_delay.timestamp_microseconds + + rendering_delay.delay_microseconds + + mixer_pipeline_->GetPostLoopbackRenderingDelayMicroseconds(); } for (auto& redirector : audio_output_redirectors_) { @@ -762,10 +650,10 @@ DCHECK(mixer_task_runner_->BelongsToCurrentThread()); // Downmix reference signal to mono to reduce CPU load. - int mix_channel_count = mix_filter_->GetOutputChannelCount(); + int mix_channel_count = mixer_pipeline_->GetLoopbackChannelCount(); int loopback_channel_count = mix_channel_count; - float* mixed_data = mix_filter_->GetOutputBuffer(); + float* mixed_data = mixer_pipeline_->GetLoopbackOutput(); if (num_output_channels_ == 1 && mix_channel_count != 1) { for (int i = 0; i < frames; ++i) { float sum = 0; @@ -779,6 +667,7 @@ // Hard limit to [1.0, -1.0] for (int i = 0; i < frames * loopback_channel_count; ++i) { + // TODO(bshaya): Warn about clipping here. mixed_data[i] = std::min(1.0f, std::max(-1.0f, mixed_data[i])); } @@ -793,8 +682,8 @@ } // Drop extra channels from linearize filter if necessary. - float* linearized_data = linearize_filter_->GetOutputBuffer(); - int linearize_channel_count = linearize_filter_->GetOutputChannelCount(); + float* linearized_data = mixer_pipeline_->GetOutput(); + int linearize_channel_count = mixer_pipeline_->GetOutputChannelCount(); if (num_output_channels_ == 1 && linearize_channel_count != 1) { for (int i = 0; i < frames; ++i) { linearized_data[i] = linearized_data[i * linearize_channel_count]; @@ -1012,28 +901,34 @@ void StreamMixer::SetPostProcessorConfigOnThread(const std::string& name, const std::string& config) { DCHECK(mixer_task_runner_->BelongsToCurrentThread()); - for (auto&& filter_group : filter_groups_) { - filter_group->SetPostProcessorConfig(name, config); - } + mixer_pipeline_->SetPostProcessorConfig(name, config); } void StreamMixer::ValidatePostProcessorsForTest() { - ValidatePostProcessors(); + CHECK(PostProcessorsHaveCorrectNumOutputs()); } -void StreamMixer::ValidatePostProcessors() { - // Ensure filter configuration is viable. - // This can't be done in CreatePostProcessors() because it breaks tests. - CHECK(num_output_channels_ == 1 || - num_output_channels_ == linearize_filter_->GetOutputChannelCount()) - << "PostProcessor configuration channel count does not match command line" - << " flag: " << linearize_filter_->GetOutputChannelCount() << " vs " - << num_output_channels_; - int loopback_channel_count = - num_output_channels_ == 1 ? 1 : mix_filter_->GetOutputChannelCount(); - CHECK_LE(loopback_channel_count, 2) - << "PostProcessor configuration has " << loopback_channel_count - << " channels after 'mix' group, but only 1 or 2 are allowed."; +bool StreamMixer::PostProcessorsHaveCorrectNumOutputs() { + bool correct_num_outputs = + num_output_channels_ == 1 || + num_output_channels_ == mixer_pipeline_->GetOutputChannelCount(); + if (!correct_num_outputs) { + LOG(WARNING) << "PostProcessor configuration channel count does not match " + << "command line flag: " + << mixer_pipeline_->GetOutputChannelCount() << " vs " + << num_output_channels_; + return false; + } + int loopback_channel_count = num_output_channels_ == 1 + ? 1 + : mixer_pipeline_->GetLoopbackChannelCount(); + if (loopback_channel_count > 2) { + LOG(WARNING) << "PostProcessor configuration has " << loopback_channel_count + << " channels after 'mix' group, but only 1 or 2 are allowed."; + return false; + } + return true; } + } // namespace media } // namespace chromecast
diff --git a/chromecast/media/cma/backend/stream_mixer.h b/chromecast/media/cma/backend/stream_mixer.h index 02683651..efad3e8 100644 --- a/chromecast/media/cma/backend/stream_mixer.h +++ b/chromecast/media/cma/backend/stream_mixer.h
@@ -20,6 +20,7 @@ #include "base/threading/thread.h" #include "base/time/time.h" #include "chromecast/media/cma/backend/mixer_input.h" +#include "chromecast/media/cma/backend/mixer_pipeline.h" #include "chromecast/public/cast_media_shlib.h" #include "chromecast/public/media/external_audio_pipeline_shlib.h" #include "chromecast/public/media/media_pipeline_backend.h" @@ -29,9 +30,7 @@ namespace media { class AudioOutputRedirector; -class FilterGroup; class MixerOutputStream; -class PostProcessingPipelineParser; class PostProcessingPipelineFactory; // Mixer implementation. The mixer has zero or more inputs; these can be added @@ -118,7 +117,7 @@ void SetPostProcessorConfig(const std::string& name, const std::string& config); - void ResetPostProcessors(); + void ResetPostProcessors(CastMediaShlib::ResultCallback callback); // Test-only methods. StreamMixer(std::unique_ptr<MixerOutputStream> output, @@ -159,9 +158,11 @@ bool muted = false; }; - void CreatePostProcessors(PostProcessingPipelineParser* pipeline_parser); - void ResetPostProcessorsOnThread(); - void ValidatePostProcessors(); + void ResetPostProcessorsOnThread(CastMediaShlib::ResultCallback callback, + const std::string& override_config); + void CreatePostProcessors(CastMediaShlib::ResultCallback callback, + const std::string& override_config); + bool PostProcessorsHaveCorrectNumOutputs(); void FinalizeOnMixerThread(); void Start(); void Stop(); @@ -171,8 +172,6 @@ void RemoveInputOnThread(MixerInput::Source* input_source); void SetCloseTimeout(); void UpdatePlayoutChannel(); - MediaPipelineBackend::AudioDecoder::RenderingDelay GetTotalRenderingDelay( - FilterGroup* filter_group); void PlaybackLoop(); void WriteOneBuffer(); @@ -211,9 +210,13 @@ int length); void LoopbackInterrupted(); + MediaPipelineBackend::AudioDecoder::RenderingDelay GetTotalRenderingDelay( + FilterGroup* filter_group); + std::unique_ptr<MixerOutputStream> output_; std::unique_ptr<PostProcessingPipelineFactory> post_processing_pipeline_factory_; + std::unique_ptr<MixerPipeline> mixer_pipeline_; std::unique_ptr<base::Thread> mixer_thread_; scoped_refptr<base::SingleThreadTaskRunner> mixer_task_runner_; @@ -239,11 +242,6 @@ State state_; base::TimeTicks close_timestamp_; - std::vector<std::unique_ptr<FilterGroup>> filter_groups_; - FilterGroup* default_filter_ = nullptr; - FilterGroup* mix_filter_ = nullptr; - FilterGroup* linearize_filter_ = nullptr; - base::flat_map<MixerInput::Source*, std::unique_ptr<MixerInput>> inputs_; base::flat_map<MixerInput::Source*, std::unique_ptr<MixerInput>> ignored_inputs_;
diff --git a/chromecast/media/cma/backend/stream_mixer_unittest.cc b/chromecast/media/cma/backend/stream_mixer_unittest.cc index 87e2bbf..e3ed597e 100644 --- a/chromecast/media/cma/backend/stream_mixer_unittest.cc +++ b/chromecast/media/cma/backend/stream_mixer_unittest.cc
@@ -1482,12 +1482,9 @@ ::testing::FLAGS_gtest_death_test_style = "threadsafe"; mixer_->SetNumOutputChannelsForTest(kNumOutputChannels); - mixer_->ResetPostProcessorsForTest( - std::make_unique<MockPostProcessorFactory>(), config); - - ASSERT_DEATH(mixer_->ValidatePostProcessorsForTest(), - DeathRegex("PostProcessor configuration channel count does not " - "match command line flag")); + ASSERT_DEATH(mixer_->ResetPostProcessorsForTest( + std::make_unique<MockPostProcessorFactory>(), config), + DeathRegex("PostProcessorsHaveCorrectNumOutputs")); } TEST_F(StreamMixerDeathTest, CrashesIfMoreThan2LoopbackChannels) { @@ -1514,11 +1511,9 @@ ::testing::FLAGS_gtest_death_test_style = "threadsafe"; mixer_->SetNumOutputChannelsForTest(kNumOutputChannels); - mixer_->ResetPostProcessorsForTest( - std::make_unique<MockPostProcessorFactory>(), config); - - ASSERT_DEATH(mixer_->ValidatePostProcessorsForTest(), - DeathRegex("loopback_channel_count <= 2")); + ASSERT_DEATH(mixer_->ResetPostProcessorsForTest( + std::make_unique<MockPostProcessorFactory>(), config), + DeathRegex("PostProcessorsHaveCorrectNumOutputs")); } #endif // GTEST_HAS_DEATH_TEST
diff --git a/chromecast/public/cast_media_shlib.h b/chromecast/public/cast_media_shlib.h index 6a3439e..fc38d8a 100644 --- a/chromecast/public/cast_media_shlib.h +++ b/chromecast/public/cast_media_shlib.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include <functional> #include <memory> #include <string> #include <vector> @@ -38,6 +39,8 @@ // from other tests. class CHROMECAST_EXPORT CastMediaShlib { public: + using ResultCallback = + std::function<void(bool success, const std::string& message)>; // Observer for audio loopback data. class LoopbackAudioObserver { public: @@ -126,8 +129,10 @@ static void RemoveLoopbackAudioObserver(LoopbackAudioObserver* observer) __attribute__((__weak__)); - // Reset the post processing pipeline. - static void ResetPostProcessors() __attribute__((__weak__)); + // Reset the post processing pipeline. |callback| will be called with + // |success| = |true| if the new config loads without error. + static void ResetPostProcessors(ResultCallback callback) + __attribute__((__weak__)); // Updates all postprocessors with the given |name| to have new configuration // |config|.
diff --git a/chromecast/renderer/extensions/automation_internal_custom_bindings.cc b/chromecast/renderer/extensions/automation_internal_custom_bindings.cc index aff6347..bcd13ef 100644 --- a/chromecast/renderer/extensions/automation_internal_custom_bindings.cc +++ b/chromecast/renderer/extensions/automation_internal_custom_bindings.cc
@@ -107,8 +107,8 @@ ui::AXNode* FindNodeWithChildTreeId(ui::AXNode* node, ui::AXTreeID child_tree_id) { - if (child_tree_id == - node->data().GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId)) + if (child_tree_id == ui::AXTreeID::FromString(node->data().GetStringAttribute( + ax::mojom::StringAttribute::kChildTreeId))) return node; for (int i = 0; i < node->child_count(); ++i) { @@ -143,7 +143,8 @@ if (args.Length() != 1 || !args[0]->IsString()) ThrowInvalidArgumentsException(automation_bindings_); - ui::AXTreeID tree_id = *v8::String::Utf8Value(isolate, args[0]); + ui::AXTreeID tree_id = + ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0])); AutomationAXTreeWrapper* tree_wrapper = automation_bindings_->GetAutomationAXTreeWrapperFromTreeID(tree_id); if (!tree_wrapper) @@ -190,7 +191,8 @@ v8::Local<v8::Context> context = automation_bindings_->context()->v8_context(); - ui::AXTreeID tree_id = *v8::String::Utf8Value(isolate, args[0]); + ui::AXTreeID tree_id = + ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0])); int node_id = args[1]->Int32Value(context).FromMaybe(0); AutomationAXTreeWrapper* tree_wrapper = @@ -244,7 +246,8 @@ v8::Local<v8::Context> context = automation_bindings_->context()->v8_context(); - ui::AXTreeID tree_id = *v8::String::Utf8Value(isolate, args[0]); + ui::AXTreeID tree_id = + ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0])); int node_id = args[1]->Int32Value(context).FromMaybe(0); std::string attribute = *v8::String::Utf8Value(isolate, args[2]); @@ -300,7 +303,8 @@ v8::Local<v8::Context> context = automation_bindings_->context()->v8_context(); - ui::AXTreeID tree_id = *v8::String::Utf8Value(isolate, args[0]); + ui::AXTreeID tree_id = + ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0])); int node_id = args[1]->Int32Value(context).FromMaybe(0); int start = args[2]->Int32Value(context).FromMaybe(0); int end = args[3]->Int32Value(context).FromMaybe(0); @@ -1032,7 +1036,8 @@ return; } - ui::AXTreeID tree_id = *v8::String::Utf8Value(args.GetIsolate(), args[0]); + ui::AXTreeID tree_id = ui::AXTreeID::FromString( + *v8::String::Utf8Value(args.GetIsolate(), args[0])); auto iter = tree_id_to_tree_wrapper_map_.find(tree_id); if (iter == tree_id_to_tree_wrapper_map_.end()) return; @@ -1096,8 +1101,9 @@ // Try to keep following focus recursively, by letting |tree_id| be the // new subtree to search in, while keeping |focus_tree_id| set to the tree // where we know we found a focused node. - ui::AXTreeID child_tree_id = focus->data().GetStringAttribute( - ax::mojom::StringAttribute::kChildTreeId); + ui::AXTreeID child_tree_id = + ui::AXTreeID::FromString(focus->data().GetStringAttribute( + ax::mojom::StringAttribute::kChildTreeId)); AutomationAXTreeWrapper* child_tree_wrapper = GetAutomationAXTreeWrapperFromTreeID(child_tree_id); @@ -1139,7 +1145,8 @@ return; } - ui::AXTreeID tree_id = *v8::String::Utf8Value(args.GetIsolate(), args[0]); + ui::AXTreeID tree_id = ui::AXTreeID::FromString( + *v8::String::Utf8Value(args.GetIsolate(), args[0])); AutomationAXTreeWrapper* tree_wrapper = GetAutomationAXTreeWrapperFromTreeID(tree_id); if (!tree_wrapper) @@ -1150,10 +1157,11 @@ if (!GetFocusInternal(tree_wrapper, &focused_tree_wrapper, &focused_node)) return; - args.GetReturnValue().Set(gin::DataObjectBuilder(GetIsolate()) - .Set("treeId", focused_tree_wrapper->tree_id()) - .Set("nodeId", focused_node->id()) - .Build()); + args.GetReturnValue().Set( + gin::DataObjectBuilder(GetIsolate()) + .Set("treeId", focused_tree_wrapper->tree_id().ToString()) + .Set("nodeId", focused_node->id()) + .Build()); } void AutomationInternalCustomBindings::GetHtmlAttributes( @@ -1162,7 +1170,8 @@ if (args.Length() < 2 || !args[0]->IsString() || !args[1]->IsNumber()) ThrowInvalidArgumentsException(this); - ui::AXTreeID tree_id = *v8::String::Utf8Value(isolate, args[0]); + ui::AXTreeID tree_id = + ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0])); int node_id = args[1]->Int32Value(context()->v8_context()).FromMaybe(0); AutomationAXTreeWrapper* tree_wrapper = @@ -1186,7 +1195,8 @@ if (args.Length() < 2 || !args[0]->IsString() || !args[1]->IsNumber()) ThrowInvalidArgumentsException(this); - ui::AXTreeID tree_id = *v8::String::Utf8Value(isolate, args[0]); + ui::AXTreeID tree_id = + ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0])); int node_id = args[1]->Int32Value(context()->v8_context()).FromMaybe(0); AutomationAXTreeWrapper* tree_wrapper = @@ -1208,7 +1218,7 @@ } AutomationAXTreeWrapper* top_tree_wrapper = - GetAutomationAXTreeWrapperFromTreeID(0); + GetAutomationAXTreeWrapperFromTreeID(ui::DesktopAXTreeID()); if (!top_tree_wrapper) top_tree_wrapper = tree_wrapper; AutomationAXTreeWrapper* focused_tree_wrapper = nullptr; @@ -1263,8 +1273,9 @@ ui::AXNode* parent = parent_tree_wrapper->tree()->GetFromId( (*in_out_tree_wrapper)->host_node_id()); if (parent) { - ui::AXTreeID parent_child_tree_id = parent->data().GetStringAttribute( - ax::mojom::StringAttribute::kChildTreeId); + ui::AXTreeID parent_child_tree_id = + ui::AXTreeID::FromString(parent->data().GetStringAttribute( + ax::mojom::StringAttribute::kChildTreeId)); if (parent_child_tree_id == (*in_out_tree_wrapper)->tree_id()) { *in_out_tree_wrapper = parent_tree_wrapper; return parent; @@ -1326,7 +1337,8 @@ return; } - ui::AXTreeID tree_id = *v8::String::Utf8Value(args.GetIsolate(), args[0]); + ui::AXTreeID tree_id = ui::AXTreeID::FromString( + *v8::String::Utf8Value(args.GetIsolate(), args[0])); int node_id = args[1]->Int32Value(context()->v8_context()).FromMaybe(0); const auto iter = tree_id_to_tree_wrapper_map_.find(tree_id); @@ -1370,7 +1382,7 @@ if (!tree_wrapper->OnAccessibilityEvents(event_bundle, is_active_profile)) { LOG(ERROR) << tree_wrapper->tree()->error(); base::ListValue args; - args.AppendString(tree_id); + args.AppendString(tree_id.ToString()); bindings_system_->DispatchEventInContext( "automationInternal.onAccessibilityTreeSerializationError", &args, nullptr, context()); @@ -1460,7 +1472,7 @@ base::ListValue args; args.AppendInteger(observer.id); - args.AppendString(tree_id); + args.AppendString(tree_id.ToString()); args.AppendInteger(node->id()); args.AppendString(ToString(change_type)); bindings_system_->DispatchEventInContext("automationInternal.onTreeChange", @@ -1474,7 +1486,7 @@ ui::AXEvent& event, api::automation::EventType event_type) { auto event_params = std::make_unique<base::DictionaryValue>(); - event_params->SetString("treeID", tree_id); + event_params->SetString("treeID", tree_id.ToString()); event_params->SetInteger("targetID", event.id); event_params->SetString("eventType", api::automation::ToString(event_type)); event_params->SetString("eventFrom", ui::ToString(event.event_from)); @@ -1496,7 +1508,7 @@ ui::AXTreeID tree_id = iter->second->tree_id(); base::ListValue args; - args.AppendString(tree_id); + args.AppendString(tree_id.ToString()); args.AppendInteger(node->id()); bindings_system_->DispatchEventInContext("automationInternal.onChildTreeID", &args, nullptr, context()); @@ -1512,7 +1524,7 @@ ui::AXTreeID tree_id = iter->second->tree_id(); base::ListValue args; - args.AppendString(tree_id); + args.AppendString(tree_id.ToString()); { auto nodes = std::make_unique<base::ListValue>(); for (auto id : ids)
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 022b672b..0c6a0ba4 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -11107.0.0 \ No newline at end of file +11108.0.0 \ No newline at end of file
diff --git a/chromeos/components/proximity_auth/proximity_auth_system.cc b/chromeos/components/proximity_auth/proximity_auth_system.cc index ea9c61f..a61b2d4 100644 --- a/chromeos/components/proximity_auth/proximity_auth_system.cc +++ b/chromeos/components/proximity_auth/proximity_auth_system.cc
@@ -190,9 +190,12 @@ << account_id.Serialize(); remote_device_life_cycle_ = CreateRemoteDeviceLifeCycle(remote_device, local_device); - unlock_manager_->SetRemoteDeviceLifeCycle(remote_device_life_cycle_.get()); remote_device_life_cycle_->AddObserver(this); - remote_device_life_cycle_->Start(); + + // UnlockManager listens for Bluetooth power change events, and is therefore + // responsible for starting RemoteDeviceLifeCycle when Bluetooth becomes + // powered. + unlock_manager_->SetRemoteDeviceLifeCycle(remote_device_life_cycle_.get()); } }
diff --git a/chromeos/components/proximity_auth/proximity_auth_system_unittest.cc b/chromeos/components/proximity_auth/proximity_auth_system_unittest.cc index 92fed9e..ac13b34 100644 --- a/chromeos/components/proximity_auth/proximity_auth_system_unittest.cc +++ b/chromeos/components/proximity_auth/proximity_auth_system_unittest.cc
@@ -274,7 +274,7 @@ EXPECT_EQ(life_cycle(), unlock_manager_life_cycle); EXPECT_TRUE(life_cycle()); - EXPECT_TRUE(life_cycle()->started()); + EXPECT_FALSE(life_cycle()->started()); EXPECT_EQ(kUser1, life_cycle()->GetRemoteDevice().user_id()); EXPECT_CALL(*unlock_manager_, SetRemoteDeviceLifeCycle(nullptr))
diff --git a/chromeos/components/proximity_auth/remote_device_life_cycle_impl.cc b/chromeos/components/proximity_auth/remote_device_life_cycle_impl.cc index a931dfd..97b932d 100644 --- a/chromeos/components/proximity_auth/remote_device_life_cycle_impl.cc +++ b/chromeos/components/proximity_auth/remote_device_life_cycle_impl.cc
@@ -203,11 +203,24 @@ chromeos::secure_channel::mojom::ConnectionAttemptFailureReason reason) { DCHECK(base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)); - PA_LOG(ERROR) << "Failed to create connection to remote device: " - << remote_device_.GetTruncatedDeviceIdForLogs() - << ", for reason: " << reason << ". Giving up."; connection_attempt_.reset(); - TransitionToState(RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED); + + if (reason == chromeos::secure_channel::mojom:: + ConnectionAttemptFailureReason::ADAPTER_DISABLED || + reason == chromeos::secure_channel::mojom:: + ConnectionAttemptFailureReason::ADAPTER_NOT_PRESENT) { + // Transition to state STOPPED, and wait for Bluetooth to become powered. + // If it does, UnlockManager will start RemoteDeviceLifeCycle again. + PA_LOG(WARNING) << "Life cycle for " + << remote_device_.GetTruncatedDeviceIdForLogs() + << " stopped because Bluetooth is not available."; + TransitionToState(RemoteDeviceLifeCycle::State::STOPPED); + } else { + PA_LOG(ERROR) << "Failed to authenticate with remote device: " + << remote_device_.GetTruncatedDeviceIdForLogs() + << ", for reason: " << reason << ". Giving up."; + TransitionToState(RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED); + } } void RemoteDeviceLifeCycleImpl::OnConnection(
diff --git a/chromeos/components/proximity_auth/remote_device_life_cycle_impl_unittest.cc b/chromeos/components/proximity_auth/remote_device_life_cycle_impl_unittest.cc index c8ce875..ea0fdbb9 100644 --- a/chromeos/components/proximity_auth/remote_device_life_cycle_impl_unittest.cc +++ b/chromeos/components/proximity_auth/remote_device_life_cycle_impl_unittest.cc
@@ -249,24 +249,23 @@ life_cycle_.GetMessenger()->GetChannel()); } - void SimulateFailureToAuthenticateConnection() { + void SimulateFailureToAuthenticateConnection( + chromeos::secure_channel::mojom::ConnectionAttemptFailureReason + failure_reason, + RemoteDeviceLifeCycle::State expected_life_cycle_state) { EXPECT_EQ(RemoteDeviceLifeCycle::State::FINDING_CONNECTION, life_cycle_.GetState()); - EXPECT_CALL(*this, - OnLifeCycleStateChanged( - RemoteDeviceLifeCycle::State::FINDING_CONNECTION, - RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED)); + EXPECT_CALL(*this, OnLifeCycleStateChanged( + RemoteDeviceLifeCycle::State::FINDING_CONNECTION, + expected_life_cycle_state)); - fake_connection_attempt_->NotifyConnectionAttemptFailure( - chromeos::secure_channel::mojom::ConnectionAttemptFailureReason:: - AUTHENTICATION_ERROR); + fake_connection_attempt_->NotifyConnectionAttemptFailure(failure_reason); EXPECT_EQ(nullptr, life_cycle_.GetChannel()); EXPECT_EQ(nullptr, life_cycle_.GetMessenger()); - EXPECT_EQ(RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED, - life_cycle_.GetState()); + EXPECT_EQ(expected_life_cycle_state, life_cycle_.GetState()); } cryptauth::FakeConnection* OnConnectionFound() { @@ -340,7 +339,35 @@ CreateFakeConnectionAttempt(); StartLifeCycle(); - SimulateFailureToAuthenticateConnection(); + SimulateFailureToAuthenticateConnection( + chromeos::secure_channel::mojom::ConnectionAttemptFailureReason:: + AUTHENTICATION_ERROR /* failure_reason */, + RemoteDeviceLifeCycle::State:: + AUTHENTICATION_FAILED /* expected_life_cycle_state */); +} + +TEST_F(ProximityAuthRemoteDeviceLifeCycleImplTest, + MultiDeviceApiEnabled_Failure_BluetoothNotPresent) { + SetMultiDeviceApiEnabled(); + CreateFakeConnectionAttempt(); + + StartLifeCycle(); + SimulateFailureToAuthenticateConnection( + chromeos::secure_channel::mojom::ConnectionAttemptFailureReason:: + ADAPTER_NOT_PRESENT /* failure_reason */, + RemoteDeviceLifeCycle::State::STOPPED /* expected_life_cycle_state */); +} + +TEST_F(ProximityAuthRemoteDeviceLifeCycleImplTest, + MultiDeviceApiEnabled_Failure_BluetoothNotPowered) { + SetMultiDeviceApiEnabled(); + CreateFakeConnectionAttempt(); + + StartLifeCycle(); + SimulateFailureToAuthenticateConnection( + chromeos::secure_channel::mojom::ConnectionAttemptFailureReason:: + ADAPTER_DISABLED /* failure_reason */, + RemoteDeviceLifeCycle::State::STOPPED /* expected_life_cycle_state */); } TEST_F(ProximityAuthRemoteDeviceLifeCycleImplTest, AuthenticateAndDisconnect) {
diff --git a/chromeos/components/proximity_auth/unlock_manager_impl.cc b/chromeos/components/proximity_auth/unlock_manager_impl.cc index ac0549f..56b94e2 100644 --- a/chromeos/components/proximity_auth/unlock_manager_impl.cc +++ b/chromeos/components/proximity_auth/unlock_manager_impl.cc
@@ -103,7 +103,7 @@ DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this); - SetWakingUpState(true); + SetWakingUpState(true /* is_waking_up */); if (device::BluetoothAdapterFactory::IsBluetoothSupported()) { device::BluetoothAdapterFactory::GetAdapter( @@ -142,7 +142,8 @@ life_cycle_ = life_cycle; if (life_cycle_) { - SetWakingUpState(true); + AttemptToStartRemoteDeviceLifecycle(); + SetWakingUpState(true /* is_waking_up */); } else { proximity_monitor_.reset(); } @@ -162,7 +163,7 @@ } if (state == RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED) - SetWakingUpState(false); + SetWakingUpState(false /* is_waking_up */); UpdateLockScreen(); } @@ -190,13 +191,12 @@ GetScreenlockStateFromRemoteUpdate(status_update))); // This also calls |UpdateLockScreen()| - SetWakingUpState(false); + SetWakingUpState(false /* is_waking_up */); } void UnlockManagerImpl::OnDecryptResponse(const std::string& decrypted_bytes) { if (!is_attempting_auth_) { - PA_LOG(ERROR) << "Decrypt response received but not attempting " - << "auth."; + PA_LOG(ERROR) << "Decrypt response received but not attempting auth."; return; } @@ -212,8 +212,7 @@ void UnlockManagerImpl::OnUnlockResponse(bool success) { if (!is_attempting_auth_) { - PA_LOG(ERROR) << "Unlock response received but not attempting " - << "auth."; + PA_LOG(ERROR) << "Unlock response received but not attempting auth."; return; } @@ -248,12 +247,8 @@ void UnlockManagerImpl::OnFocusedUserChanged(const AccountId& account_id) {} void UnlockManagerImpl::OnScreenLockedOrUnlocked(bool is_locked) { - if (is_locked && bluetooth_adapter_ && bluetooth_adapter_->IsPowered() && - life_cycle_ && - life_cycle_->GetState() == - RemoteDeviceLifeCycle::State::FINDING_CONNECTION) { - SetWakingUpState(true); - } + if (is_locked && IsBluetoothPresentAndPowered() && life_cycle_) + SetWakingUpState(true /* is_waking_up */); is_locked_ = is_locked; UpdateProximityMonitorState(); @@ -276,7 +271,22 @@ } void UnlockManagerImpl::SuspendDone(const base::TimeDelta& sleep_duration) { - SetWakingUpState(true); + SetWakingUpState(true /* is_waking_up */); +} + +bool UnlockManagerImpl::IsBluetoothPresentAndPowered() const { + return bluetooth_adapter_ && bluetooth_adapter_->IsPresent() && + bluetooth_adapter_->IsPowered(); +} + +void UnlockManagerImpl::AttemptToStartRemoteDeviceLifecycle() { + if (IsBluetoothPresentAndPowered() && life_cycle_ && + life_cycle_->GetState() == RemoteDeviceLifeCycle::State::STOPPED) { + // If Bluetooth is disabled after this, |life_cycle_| will be notified by + // SecureChannel that the connection attempt failed. From that point on, + // |life_cycle_| will wait to be started again by UnlockManager. + life_cycle_->Start(); + } } void UnlockManagerImpl::OnAuthAttempted(mojom::AuthType auth_type) { @@ -388,16 +398,13 @@ if (!life_cycle_) return ScreenlockState::INACTIVE; - RemoteDeviceLifeCycle::State life_cycle_state = life_cycle_->GetState(); - if (life_cycle_state == RemoteDeviceLifeCycle::State::STOPPED) - return ScreenlockState::INACTIVE; - - if (!bluetooth_adapter_ || !bluetooth_adapter_->IsPowered()) + if (!IsBluetoothPresentAndPowered()) return ScreenlockState::NO_BLUETOOTH; if (IsUnlockAllowed()) return ScreenlockState::AUTHENTICATED; + RemoteDeviceLifeCycle::State life_cycle_state = life_cycle_->GetState(); if (life_cycle_state == RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED) return ScreenlockState::PHONE_NOT_AUTHENTICATED; @@ -448,6 +455,8 @@ } void UnlockManagerImpl::UpdateLockScreen() { + AttemptToStartRemoteDeviceLifecycle(); + UpdateProximityMonitorState(); ScreenlockState new_state = GetScreenlockState();
diff --git a/chromeos/components/proximity_auth/unlock_manager_impl.h b/chromeos/components/proximity_auth/unlock_manager_impl.h index ebc674b..ace4ff8 100644 --- a/chromeos/components/proximity_auth/unlock_manager_impl.h +++ b/chromeos/components/proximity_auth/unlock_manager_impl.h
@@ -99,6 +99,13 @@ // chromeos::PowerManagerClient::Observer: void SuspendDone(const base::TimeDelta& sleep_duration) override; + // Returns true if the BluetoothAdapter is present and powered. + bool IsBluetoothPresentAndPowered() const; + + // If the RemoteDeviceLifeCycle is available, ensure it is started (but only + // if Bluetooth is available). + void AttemptToStartRemoteDeviceLifecycle(); + // Called when auth is attempted to send the sign-in challenge to the remote // device for decryption. void SendSignInChallenge();
diff --git a/chromeos/components/proximity_auth/unlock_manager_impl_unittest.cc b/chromeos/components/proximity_auth/unlock_manager_impl_unittest.cc index 57fd8e3..c4067a5 100644 --- a/chromeos/components/proximity_auth/unlock_manager_impl_unittest.cc +++ b/chromeos/components/proximity_auth/unlock_manager_impl_unittest.cc
@@ -164,6 +164,7 @@ bluetooth_adapter_(CreateAndRegisterMockBluetoothAdapter()), task_runner_(new base::TestSimpleTaskRunner()), thread_task_runner_handle_(task_runner_) { + ON_CALL(*bluetooth_adapter_, IsPresent()).WillByDefault(Return(true)); ON_CALL(*bluetooth_adapter_, IsPowered()).WillByDefault(Return(true)); ON_CALL(messenger_, SupportsSignIn()).WillByDefault(Return(true)); ON_CALL(messenger_, GetSecureContext()) @@ -477,6 +478,36 @@ EXPECT_TRUE(proximity_monitor()->started()); } +TEST_F(ProximityAuthUnlockManagerImplTest, BluetoothAdapterNotPresent) { + ON_CALL(*bluetooth_adapter_, IsPresent()).WillByDefault(Return(false)); + + CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK); + + EXPECT_CALL(proximity_auth_client_, + UpdateScreenlockState(ScreenlockState::NO_BLUETOOTH)); + + unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_); + EXPECT_FALSE(life_cycle_.started()); +} + +TEST_F(ProximityAuthUnlockManagerImplTest, BluetoothAdapterPowerChanges) { + ON_CALL(*bluetooth_adapter_, IsPowered()).WillByDefault(Return(false)); + + CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK); + + EXPECT_CALL(proximity_auth_client_, + UpdateScreenlockState(ScreenlockState::NO_BLUETOOTH)); + + unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_); + EXPECT_FALSE(life_cycle_.started()); + + EXPECT_CALL(proximity_auth_client_, + UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING)); + ON_CALL(*bluetooth_adapter_, IsPowered()).WillByDefault(Return(true)); + bluetooth_adapter_->NotifyAdapterPoweredChanged(true); + EXPECT_TRUE(life_cycle_.started()); +} + TEST_F(ProximityAuthUnlockManagerImplTest, OnLifeCycleStateChanged_SecureChannelEstablished_RegistersAsObserver) { CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK); @@ -505,17 +536,6 @@ } TEST_F(ProximityAuthUnlockManagerImplTest, - OnLifeCycleStateChanged_Stopped_UpdatesScreenlockState) { - CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK); - SimulateUserPresentState(); - - EXPECT_CALL(proximity_auth_client_, - UpdateScreenlockState(ScreenlockState::INACTIVE)); - life_cycle_.ChangeState(RemoteDeviceLifeCycle::State::STOPPED); - unlock_manager_->OnLifeCycleStateChanged(); -} - -TEST_F(ProximityAuthUnlockManagerImplTest, OnLifeCycleStateChanged_AuthenticationFailed_UpdatesScreenlockState) { CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK); SimulateUserPresentState(); @@ -529,50 +549,24 @@ TEST_F(ProximityAuthUnlockManagerImplTest, OnLifeCycleStateChanged_FindingConnection_UpdatesScreenlockState) { CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK); - unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_); EXPECT_CALL(proximity_auth_client_, UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING)); - life_cycle_.ChangeState(RemoteDeviceLifeCycle::State::FINDING_CONNECTION); - unlock_manager_->OnLifeCycleStateChanged(); -} - -TEST_F(ProximityAuthUnlockManagerImplTest, - OnLifeCycleStateChanged_FindingConnection_BluetoothAdapterOff) { - CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK); unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_); - - EXPECT_CALL(proximity_auth_client_, - UpdateScreenlockState(ScreenlockState::NO_BLUETOOTH)); - ON_CALL(*bluetooth_adapter_, IsPowered()).WillByDefault(Return(false)); - life_cycle_.ChangeState(RemoteDeviceLifeCycle::State::FINDING_CONNECTION); - unlock_manager_->OnLifeCycleStateChanged(); } TEST_F(ProximityAuthUnlockManagerImplTest, OnLifeCycleStateChanged_Authenticating_UpdatesScreenlockState) { CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK); - unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_); - EXPECT_CALL(proximity_auth_client_, UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING)); + unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_); + EXPECT_TRUE(life_cycle_.started()); + life_cycle_.ChangeState(RemoteDeviceLifeCycle::State::AUTHENTICATING); unlock_manager_->OnLifeCycleStateChanged(); } -TEST_F( - ProximityAuthUnlockManagerImplTest, - OnLifeCycleStateChanged_SecureChannelEstablished_UpdatesScreenlockState) { - CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK); - unlock_manager_->SetRemoteDeviceLifeCycle(&life_cycle_); - - EXPECT_CALL(proximity_auth_client_, - UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING)); - life_cycle_.ChangeState( - RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED); - unlock_manager_->OnLifeCycleStateChanged(); -} - TEST_F(ProximityAuthUnlockManagerImplTest, OnDisconnected_UnregistersAsObserver) { CreateUnlockManager(ProximityAuthSystem::SESSION_LOCK);
diff --git a/chromeos/services/multidevice_setup/BUILD.gn b/chromeos/services/multidevice_setup/BUILD.gn index 94cccf7..8e01084a1 100644 --- a/chromeos/services/multidevice_setup/BUILD.gn +++ b/chromeos/services/multidevice_setup/BUILD.gn
@@ -14,6 +14,8 @@ "account_status_change_delegate_notifier.h", "account_status_change_delegate_notifier_impl.cc", "account_status_change_delegate_notifier_impl.h", + "android_sms_app_installing_status_observer.cc", + "android_sms_app_installing_status_observer.h", "device_reenroller.cc", "device_reenroller.h", "eligible_host_devices_provider.h", @@ -118,6 +120,7 @@ sources = [ "account_status_change_delegate_notifier_impl_unittest.cc", + "android_sms_app_installing_status_observer_unittest.cc", "device_reenroller_unittest.cc", "eligible_host_devices_provider_impl_unittest.cc", "feature_state_manager_impl_unittest.cc",
diff --git a/chromeos/services/multidevice_setup/android_sms_app_installing_status_observer.cc b/chromeos/services/multidevice_setup/android_sms_app_installing_status_observer.cc new file mode 100644 index 0000000..d5e6f8c --- /dev/null +++ b/chromeos/services/multidevice_setup/android_sms_app_installing_status_observer.cc
@@ -0,0 +1,77 @@ +// 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 "chromeos/services/multidevice_setup/android_sms_app_installing_status_observer.h" + +#include "base/memory/ptr_util.h" +#include "base/no_destructor.h" +#include "chromeos/services/multidevice_setup/host_status_provider.h" +#include "chromeos/services/multidevice_setup/public/cpp/android_sms_app_helper_delegate.h" +#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h" + +namespace chromeos { + +namespace multidevice_setup { + +// static +AndroidSmsAppInstallingStatusObserver::Factory* + AndroidSmsAppInstallingStatusObserver::Factory::test_factory_ = nullptr; + +// static +AndroidSmsAppInstallingStatusObserver::Factory* +AndroidSmsAppInstallingStatusObserver::Factory::Get() { + if (test_factory_) + return test_factory_; + + static base::NoDestructor<Factory> factory; + return factory.get(); +} + +// static +void AndroidSmsAppInstallingStatusObserver::Factory::SetFactoryForTesting( + Factory* test_factory) { + test_factory_ = test_factory; +} + +AndroidSmsAppInstallingStatusObserver::Factory::~Factory() = default; + +std::unique_ptr<AndroidSmsAppInstallingStatusObserver> +AndroidSmsAppInstallingStatusObserver::Factory::BuildInstance( + HostStatusProvider* host_status_provider, + std::unique_ptr<AndroidSmsAppHelperDelegate> + android_sms_app_helper_delegate) { + return base::WrapUnique(new AndroidSmsAppInstallingStatusObserver( + host_status_provider, std::move(android_sms_app_helper_delegate))); +} + +AndroidSmsAppInstallingStatusObserver:: + ~AndroidSmsAppInstallingStatusObserver() { + host_status_provider_->RemoveObserver(this); +} + +AndroidSmsAppInstallingStatusObserver::AndroidSmsAppInstallingStatusObserver( + HostStatusProvider* host_status_provider, + std::unique_ptr<AndroidSmsAppHelperDelegate> + android_sms_app_helper_delegate) + : host_status_provider_(host_status_provider), + android_sms_app_helper_delegate_( + std::move(android_sms_app_helper_delegate)) { + host_status_provider_->AddObserver(this); +} + +void AndroidSmsAppInstallingStatusObserver::OnHostStatusChange( + const HostStatusProvider::HostStatusWithDevice& host_status_with_device) { + mojom::HostStatus status(host_status_with_device.host_status()); + if (status == + mojom::HostStatus::kHostSetLocallyButWaitingForBackendConfirmation || + status == mojom::HostStatus::kHostVerified) { + // This call is re-entrant. If the app is already installed, it will just + // fail silently, which is fine. + android_sms_app_helper_delegate_->InstallAndroidSmsApp(); + } +} + +} // namespace multidevice_setup + +} // namespace chromeos
diff --git a/chromeos/services/multidevice_setup/android_sms_app_installing_status_observer.h b/chromeos/services/multidevice_setup/android_sms_app_installing_status_observer.h new file mode 100644 index 0000000..b0f35e6 --- /dev/null +++ b/chromeos/services/multidevice_setup/android_sms_app_installing_status_observer.h
@@ -0,0 +1,62 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_SERVICES_MULTIDEVICE_SETUP_ANDROID_SMS_APP_INSTALLING_STATUS_OBSERVER_H_ +#define CHROMEOS_SERVICES_MULTIDEVICE_SETUP_ANDROID_SMS_APP_INSTALLING_STATUS_OBSERVER_H_ + +#include <memory> + +#include "chromeos/services/multidevice_setup/host_status_provider.h" + +namespace chromeos { + +namespace multidevice_setup { + +class AndroidSmsAppHelperDelegate; + +// Listens for status changes in multidevice state and installs the Android +// Messages PWA if needed. +// +// TODO(crbug.com/884290): Also observe FeatureStateManager to make sure +// Messages is supported. +class AndroidSmsAppInstallingStatusObserver + : public HostStatusProvider::Observer { + public: + class Factory { + public: + static Factory* Get(); + static void SetFactoryForTesting(Factory* test_factory); + virtual ~Factory(); + virtual std::unique_ptr<AndroidSmsAppInstallingStatusObserver> + BuildInstance(HostStatusProvider* host_status_provider, + std::unique_ptr<AndroidSmsAppHelperDelegate> + android_sms_app_helper_delegate); + + private: + static Factory* test_factory_; + }; + + ~AndroidSmsAppInstallingStatusObserver() override; + + private: + AndroidSmsAppInstallingStatusObserver( + HostStatusProvider* host_status_provider, + std::unique_ptr<AndroidSmsAppHelperDelegate> + android_sms_app_helper_delegate); + + // HostStatusProvider::Observer: + void OnHostStatusChange(const HostStatusProvider::HostStatusWithDevice& + host_status_with_device) override; + + HostStatusProvider* host_status_provider_; + std::unique_ptr<AndroidSmsAppHelperDelegate> android_sms_app_helper_delegate_; + + DISALLOW_COPY_AND_ASSIGN(AndroidSmsAppInstallingStatusObserver); +}; + +} // namespace multidevice_setup + +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_MULTIDEVICE_SETUP_ANDROID_SMS_APP_INSTALLING_STATUS_OBSERVER_H_
diff --git a/chromeos/services/multidevice_setup/android_sms_app_installing_status_observer_unittest.cc b/chromeos/services/multidevice_setup/android_sms_app_installing_status_observer_unittest.cc new file mode 100644 index 0000000..a443f31c --- /dev/null +++ b/chromeos/services/multidevice_setup/android_sms_app_installing_status_observer_unittest.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 "chromeos/services/multidevice_setup/android_sms_app_installing_status_observer.h" + +#include <string> + +#include "chromeos/services/multidevice_setup/fake_host_status_provider.h" +#include "chromeos/services/multidevice_setup/public/cpp/fake_android_sms_app_helper_delegate.h" +#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h" +#include "components/cryptauth/remote_device_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { + +namespace multidevice_setup { + +namespace { + +const char kFakePhoneKey[] = "fake-phone-key"; +const char kFakePhoneName[] = "Phony Phone"; + +} // namespace + +class MultiDeviceSetupAndroidSmsAppInstallingStatusObserverTest + : public testing::Test { + protected: + MultiDeviceSetupAndroidSmsAppInstallingStatusObserverTest() = default; + + ~MultiDeviceSetupAndroidSmsAppInstallingStatusObserverTest() override = + default; + + void SetUp() override { + auto fake_android_sms_app_helper_delegate = + std::make_unique<FakeAndroidSmsAppHelperDelegate>(); + fake_android_sms_app_helper_delegate_ = + fake_android_sms_app_helper_delegate.get(); + fake_host_status_provider_ = std::make_unique<FakeHostStatusProvider>(); + android_sms_app_installing_status_observer_ = + AndroidSmsAppInstallingStatusObserver::Factory::Get()->BuildInstance( + fake_host_status_provider_.get(), + std::move(fake_android_sms_app_helper_delegate)); + + EXPECT_FALSE(fake_app_helper_delegate()->HasInstalledApp()); + } + + void SetHostWithStatus( + mojom::HostStatus host_status, + const base::Optional<cryptauth::RemoteDeviceRef>& host_device) { + fake_host_status_provider_->SetHostWithStatus(host_status, host_device); + } + + FakeAndroidSmsAppHelperDelegate* fake_app_helper_delegate() { + return fake_android_sms_app_helper_delegate_; + } + + cryptauth::RemoteDeviceRef GetFakePhone() { + return cryptauth::RemoteDeviceRefBuilder() + .SetPublicKey(kFakePhoneKey) + .SetName(kFakePhoneName) + .Build(); + } + + private: + std::unique_ptr<FakeHostStatusProvider> fake_host_status_provider_; + FakeAndroidSmsAppHelperDelegate* fake_android_sms_app_helper_delegate_; + + std::unique_ptr<AndroidSmsAppInstallingStatusObserver> + android_sms_app_installing_status_observer_; + + DISALLOW_COPY_AND_ASSIGN( + MultiDeviceSetupAndroidSmsAppInstallingStatusObserverTest); +}; + +TEST_F(MultiDeviceSetupAndroidSmsAppInstallingStatusObserverTest, + InstallsAfterHostPending) { + SetHostWithStatus(mojom::HostStatus::kEligibleHostExistsButNoHostSet, + base::nullopt /* host_device */); + EXPECT_FALSE(fake_app_helper_delegate()->HasInstalledApp()); + + SetHostWithStatus( + mojom::HostStatus::kHostSetLocallyButWaitingForBackendConfirmation, + GetFakePhone()); + EXPECT_TRUE(fake_app_helper_delegate()->HasInstalledApp()); +} + +TEST_F(MultiDeviceSetupAndroidSmsAppInstallingStatusObserverTest, + InstallsAfterHostVerified) { + SetHostWithStatus(mojom::HostStatus::kNoEligibleHosts, + base::nullopt /* host_device */); + EXPECT_FALSE(fake_app_helper_delegate()->HasInstalledApp()); + + SetHostWithStatus(mojom::HostStatus::kHostVerified, GetFakePhone()); + EXPECT_TRUE(fake_app_helper_delegate()->HasInstalledApp()); +} +} // namespace multidevice_setup + +} // namespace chromeos
diff --git a/chromeos/services/multidevice_setup/multidevice_setup_impl.cc b/chromeos/services/multidevice_setup/multidevice_setup_impl.cc index d77350356..4cb15e5f 100644 --- a/chromeos/services/multidevice_setup/multidevice_setup_impl.cc +++ b/chromeos/services/multidevice_setup/multidevice_setup_impl.cc
@@ -9,6 +9,7 @@ #include "base/time/default_clock.h" #include "chromeos/components/proximity_auth/logging/logging.h" #include "chromeos/services/multidevice_setup/account_status_change_delegate_notifier_impl.h" +#include "chromeos/services/multidevice_setup/android_sms_app_installing_status_observer.h" #include "chromeos/services/multidevice_setup/device_reenroller.h" #include "chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.h" #include "chromeos/services/multidevice_setup/feature_state_manager_impl.h" @@ -74,9 +75,7 @@ std::unique_ptr<AndroidSmsPairingStateTracker> android_sms_pairing_state_tracker, const cryptauth::GcmDeviceInfoProvider* gcm_device_info_provider) - : android_sms_app_helper_delegate_( - std::move(android_sms_app_helper_delegate)), - eligible_host_devices_provider_( + : eligible_host_devices_provider_( EligibleHostDevicesProviderImpl::Factory::Get()->BuildInstance( device_sync_client)), host_backend_delegate_( @@ -113,6 +112,10 @@ device_reenroller_(DeviceReenroller::Factory::Get()->BuildInstance( device_sync_client, gcm_device_info_provider)), + android_sms_app_installing_host_observer_( + AndroidSmsAppInstallingStatusObserver::Factory::Get()->BuildInstance( + host_status_provider_.get(), + std::move(android_sms_app_helper_delegate))), auth_token_validator_(auth_token_validator) { host_status_provider_->AddObserver(this); feature_state_manager_->AddObserver(this); @@ -302,7 +305,6 @@ return false; host_backend_delegate_->AttemptToSetMultiDeviceHostOnBackend(*it); - android_sms_app_helper_delegate_->InstallAndroidSmsApp(); return true; }
diff --git a/chromeos/services/multidevice_setup/multidevice_setup_impl.h b/chromeos/services/multidevice_setup/multidevice_setup_impl.h index da730ea..5a4d76b 100644 --- a/chromeos/services/multidevice_setup/multidevice_setup_impl.h +++ b/chromeos/services/multidevice_setup/multidevice_setup_impl.h
@@ -32,6 +32,7 @@ class AccountStatusChangeDelegateNotifier; class AndroidSmsAppHelperDelegate; +class AndroidSmsAppInstallingStatusObserver; class AndroidSmsPairingStateTracker; class AuthTokenValidator; class DeviceReenroller; @@ -124,7 +125,6 @@ void FlushForTesting(); - std::unique_ptr<AndroidSmsAppHelperDelegate> android_sms_app_helper_delegate_; std::unique_ptr<EligibleHostDevicesProvider> eligible_host_devices_provider_; std::unique_ptr<HostBackendDelegate> host_backend_delegate_; std::unique_ptr<HostVerifier> host_verifier_; @@ -133,6 +133,8 @@ std::unique_ptr<SetupFlowCompletionRecorder> setup_flow_completion_recorder_; std::unique_ptr<AccountStatusChangeDelegateNotifier> delegate_notifier_; std::unique_ptr<DeviceReenroller> device_reenroller_; + std::unique_ptr<AndroidSmsAppInstallingStatusObserver> + android_sms_app_installing_host_observer_; AuthTokenValidator* auth_token_validator_; mojo::InterfacePtrSet<mojom::HostStatusObserver> host_status_observers_;
diff --git a/chromeos/services/multidevice_setup/multidevice_setup_impl_unittest.cc b/chromeos/services/multidevice_setup/multidevice_setup_impl_unittest.cc index 2942e6d65..f6efaff 100644 --- a/chromeos/services/multidevice_setup/multidevice_setup_impl_unittest.cc +++ b/chromeos/services/multidevice_setup/multidevice_setup_impl_unittest.cc
@@ -10,6 +10,7 @@ #include "base/test/scoped_task_environment.h" #include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h" #include "chromeos/services/multidevice_setup/account_status_change_delegate_notifier_impl.h" +#include "chromeos/services/multidevice_setup/android_sms_app_installing_status_observer.h" #include "chromeos/services/multidevice_setup/device_reenroller.h" #include "chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.h" #include "chromeos/services/multidevice_setup/fake_account_status_change_delegate.h" @@ -392,6 +393,39 @@ DISALLOW_COPY_AND_ASSIGN(FakeDeviceReenrollerFactory); }; +class FakeAndroidSmsAppInstallingStatusObserverFactory + : public AndroidSmsAppInstallingStatusObserver::Factory { + public: + FakeAndroidSmsAppInstallingStatusObserverFactory( + FakeHostStatusProviderFactory* fake_host_status_provider_factory, + AndroidSmsAppHelperDelegate* expected_android_sms_app_helper_delegate) + : fake_host_status_provider_factory_(fake_host_status_provider_factory), + expected_android_sms_app_helper_delegate_( + expected_android_sms_app_helper_delegate) {} + + ~FakeAndroidSmsAppInstallingStatusObserverFactory() override = default; + + private: + // AndroidSmsAppInstallingStatusObserver::Factory: + std::unique_ptr<AndroidSmsAppInstallingStatusObserver> BuildInstance( + HostStatusProvider* host_status_provider, + std::unique_ptr<AndroidSmsAppHelperDelegate> + android_sms_app_helper_delegate) override { + EXPECT_EQ(fake_host_status_provider_factory_->instance(), + host_status_provider); + EXPECT_EQ(expected_android_sms_app_helper_delegate_, + android_sms_app_helper_delegate.get()); + // Only check inputs and return nullptr. We do not want to trigger the + // AndroidSmsAppInstallingStatusObserver logic in these unit tests. + return nullptr; + } + + FakeHostStatusProviderFactory* fake_host_status_provider_factory_; + AndroidSmsAppHelperDelegate* expected_android_sms_app_helper_delegate_; + + DISALLOW_COPY_AND_ASSIGN(FakeAndroidSmsAppInstallingStatusObserverFactory); +}; + } // namespace class MultiDeviceSetupImplTest : public testing::Test { @@ -412,8 +446,6 @@ auto fake_android_sms_app_helper_delegate = std::make_unique<FakeAndroidSmsAppHelperDelegate>(); - fake_android_sms_app_helper_delegate_ = - fake_android_sms_app_helper_delegate.get(); auto fake_android_sms_pairing_state_tracker = std::make_unique<FakeAndroidSmsPairingStateTracker>(); @@ -479,6 +511,13 @@ DeviceReenroller::Factory::SetFactoryForTesting( fake_device_reenroller_factory_.get()); + fake_android_sms_app_installing_status_observer_factory_ = + std::make_unique<FakeAndroidSmsAppInstallingStatusObserverFactory>( + fake_host_status_provider_factory_.get(), + fake_android_sms_app_helper_delegate.get()); + AndroidSmsAppInstallingStatusObserver::Factory::SetFactoryForTesting( + fake_android_sms_app_installing_status_observer_factory_.get()); + multidevice_setup_ = MultiDeviceSetupImpl::Factory::Get()->BuildInstance( test_pref_service_.get(), fake_device_sync_client_.get(), fake_auth_token_validator_.get(), @@ -497,6 +536,8 @@ AccountStatusChangeDelegateNotifierImpl::Factory::SetFactoryForTesting( nullptr); DeviceReenroller::Factory::SetFactoryForTesting(nullptr); + AndroidSmsAppInstallingStatusObserver::Factory::SetFactoryForTesting( + nullptr); } void CallSetAccountStatusChangeDelegate() { @@ -689,10 +730,6 @@ return fake_account_status_change_delegate_notifier_factory_->instance(); } - FakeAndroidSmsAppHelperDelegate* fake_android_sms_app_helper_delegate() { - return fake_android_sms_app_helper_delegate_; - } - cryptauth::RemoteDeviceRefList& test_devices() { return test_devices_; } MultiDeviceSetupBase* multidevice_setup() { return multidevice_setup_.get(); } @@ -780,7 +817,8 @@ std::unique_ptr<FakeAccountStatusChangeDelegateNotifierFactory> fake_account_status_change_delegate_notifier_factory_; std::unique_ptr<FakeDeviceReenrollerFactory> fake_device_reenroller_factory_; - FakeAndroidSmsAppHelperDelegate* fake_android_sms_app_helper_delegate_; + std::unique_ptr<FakeAndroidSmsAppInstallingStatusObserverFactory> + fake_android_sms_app_installing_status_observer_factory_; FakeAndroidSmsPairingStateTracker* fake_android_sms_pairing_state_tracker_; std::unique_ptr<FakeAccountStatusChangeDelegate> @@ -1058,9 +1096,6 @@ VerifyCurrentHostStatus(mojom::HostStatus::kHostVerified, test_devices()[0], observer.get(), 3u /* expected_observer_index */); - // Messages App install should have succeeded. - EXPECT_TRUE(fake_android_sms_app_helper_delegate()->HasInstalledApp()); - // Remove the host. multidevice_setup()->RemoveHostDevice(); fake_host_verifier()->set_is_host_verified(false);
diff --git a/chromeos/services/multidevice_setup/public/cpp/fake_android_sms_app_helper_delegate.cc b/chromeos/services/multidevice_setup/public/cpp/fake_android_sms_app_helper_delegate.cc index 8afabd3..290b694c6 100644 --- a/chromeos/services/multidevice_setup/public/cpp/fake_android_sms_app_helper_delegate.cc +++ b/chromeos/services/multidevice_setup/public/cpp/fake_android_sms_app_helper_delegate.cc
@@ -32,6 +32,11 @@ return has_launched_; } +void FakeAndroidSmsAppHelperDelegate::Reset() { + has_installed_ = false; + has_launched_ = false; +} + } // namespace multidevice_setup } // namespace chromeos
diff --git a/chromeos/services/multidevice_setup/public/cpp/fake_android_sms_app_helper_delegate.h b/chromeos/services/multidevice_setup/public/cpp/fake_android_sms_app_helper_delegate.h index b586c5865..1312c8f 100644 --- a/chromeos/services/multidevice_setup/public/cpp/fake_android_sms_app_helper_delegate.h +++ b/chromeos/services/multidevice_setup/public/cpp/fake_android_sms_app_helper_delegate.h
@@ -17,6 +17,7 @@ ~FakeAndroidSmsAppHelperDelegate() override; bool HasInstalledApp(); bool HasLaunchedApp(); + void Reset(); // AndroidSmsAppHelperDelegate: void InstallAndroidSmsApp() override;
diff --git a/components/autofill/content/common/autofill_types.mojom b/components/autofill/content/common/autofill_types.mojom index 99e63e8..fbc07aea 100644 --- a/components/autofill/content/common/autofill_types.mojom +++ b/components/autofill/content/common/autofill_types.mojom
@@ -57,6 +57,7 @@ FRAME_DETACHED, DOM_MUTATION_AFTER_XHR, PROVISIONALLY_SAVED_FORM_ON_START_PROVISIONAL_LOAD, + PROBABLE_FORM_SUBMISSION, SUBMISSION_INDICATOR_EVENT_COUNT }; @@ -70,6 +71,7 @@ // autofill::SubmissionSource enum SubmissionSource { + NONE, SAME_DOCUMENT_NAVIGATION, XHR_SUCCEEDED, FRAME_DETACHED,
diff --git a/components/autofill/content/common/autofill_types_struct_traits.cc b/components/autofill/content/common/autofill_types_struct_traits.cc index 554892b5..0dbc248 100644 --- a/components/autofill/content/common/autofill_types_struct_traits.cc +++ b/components/autofill/content/common/autofill_types_struct_traits.cc
@@ -259,6 +259,10 @@ SUBMISSION_INDICATOR_EVENT_COUNT: return autofill::mojom::PasswordFormSubmissionIndicatorEvent:: SUBMISSION_INDICATOR_EVENT_COUNT; + case autofill::PasswordForm::SubmissionIndicatorEvent:: + PROBABLE_FORM_SUBMISSION: + return autofill::mojom::PasswordFormSubmissionIndicatorEvent:: + PROBABLE_FORM_SUBMISSION; } NOTREACHED(); @@ -302,6 +306,11 @@ PROVISIONALLY_SAVED_FORM_ON_START_PROVISIONAL_LOAD; return true; case autofill::mojom::PasswordFormSubmissionIndicatorEvent:: + PROBABLE_FORM_SUBMISSION: + *output = autofill::PasswordForm::SubmissionIndicatorEvent:: + PROBABLE_FORM_SUBMISSION; + return true; + case autofill::mojom::PasswordFormSubmissionIndicatorEvent:: SUBMISSION_INDICATOR_EVENT_COUNT: *output = autofill::PasswordForm::SubmissionIndicatorEvent:: SUBMISSION_INDICATOR_EVENT_COUNT; @@ -372,6 +381,8 @@ autofill::mojom::SubmissionSource, autofill::SubmissionSource>::ToMojom(autofill::SubmissionSource input) { switch (input) { + case autofill::SubmissionSource::NONE: + return autofill::mojom::SubmissionSource::NONE; case autofill::SubmissionSource::SAME_DOCUMENT_NAVIGATION: return autofill::mojom::SubmissionSource::SAME_DOCUMENT_NAVIGATION; case autofill::SubmissionSource::XHR_SUCCEEDED: @@ -386,7 +397,7 @@ return autofill::mojom::SubmissionSource::FORM_SUBMISSION; } NOTREACHED(); - return autofill::mojom::SubmissionSource::FORM_SUBMISSION; + return autofill::mojom::SubmissionSource::NONE; } // static @@ -394,6 +405,9 @@ FromMojom(autofill::mojom::SubmissionSource input, autofill::SubmissionSource* output) { switch (input) { + case autofill::mojom::SubmissionSource::NONE: + *output = autofill::SubmissionSource::NONE; + return true; case autofill::mojom::SubmissionSource::SAME_DOCUMENT_NAVIGATION: *output = autofill::SubmissionSource::SAME_DOCUMENT_NAVIGATION; return true;
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index f16e702d..89a08030 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -621,22 +621,6 @@ return WebInputElement(); } -PasswordForm::SubmissionIndicatorEvent ToSubmissionIndicatorEvent( - SubmissionSource source) { - switch (source) { - case SubmissionSource::FRAME_DETACHED: - return PasswordForm::SubmissionIndicatorEvent::FRAME_DETACHED; - case SubmissionSource::SAME_DOCUMENT_NAVIGATION: - return PasswordForm::SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION; - case SubmissionSource::XHR_SUCCEEDED: - return PasswordForm::SubmissionIndicatorEvent::XHR_SUCCEEDED; - case SubmissionSource::DOM_MUTATION_AFTER_XHR: - return PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR; - default: - return PasswordForm::SubmissionIndicatorEvent::NONE; - } -} - WebInputElement ConvertToWebInput(const WebFormControlElement& element) { if (element.IsNull()) return WebInputElement();
diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/components/autofill/core/browser/autofill_download_manager.cc index 81e2de0..245ab7a 100644 --- a/components/autofill/core/browser/autofill_download_manager.cc +++ b/components/autofill/core/browser/autofill_download_manager.cc
@@ -18,6 +18,7 @@ #include "base/numerics/safe_conversions.h" #include "base/rand_util.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" @@ -25,9 +26,14 @@ #include "components/autofill/core/browser/autofill_metrics.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/proto/server.pb.h" +#include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_features.h" +#include "components/autofill/core/common/autofill_prefs.h" #include "components/autofill/core/common/autofill_switches.h" +#include "components/autofill/core/common/submission_source.h" #include "components/data_use_measurement/core/data_use_user_data.h" +#include "components/prefs/pref_service.h" +#include "components/prefs/scoped_user_pref_update.h" #include "components/variations/net/variations_http_headers.h" #include "net/base/load_flags.h" #include "net/http/http_request_headers.h" @@ -331,6 +337,52 @@ return out; } +// Check for and returns true if |upload_event| is allowed to trigger an upload +// for |form|. If true, updates |prefs| to track that |upload_event| has been +// recorded for |form|. +bool IsUploadAllowed(const FormStructure& form, PrefService* prefs) { + if (!prefs || + !base::FeatureList::IsEnabled(features::kAutofillUploadThrottling)) { + return true; + } + + // If the upload event pref needs to be reset, clear it now. + static constexpr base::TimeDelta kResetPeriod = base::TimeDelta::FromDays(28); + base::Time now = AutofillClock::Now(); + base::Time last_reset = + prefs->GetTime(prefs::kAutofillUploadEventsLastResetTimestamp); + if ((now - last_reset) > kResetPeriod) { + prefs->ClearPref(prefs::kAutofillUploadEvents); + prefs->SetTime(prefs::kAutofillUploadEventsLastResetTimestamp, now); + } + + // Get the key for the upload bucket and extract the current bitfield value. + static constexpr size_t kNumUploadBuckets = 1021; + std::string key = base::StringPrintf( + "%03X", static_cast<int>(form.form_signature() % kNumUploadBuckets)); + auto* upload_events = prefs->GetDictionary(prefs::kAutofillUploadEvents); + auto* found = upload_events->FindKeyOfType(key, base::Value::Type::INTEGER); + int value = found ? found->GetInt() : 0; + + // Calculate the mask we expect to be set for the form's upload bucket. + const int bit = static_cast<int>(form.submission_source()); + DCHECK_LE(0, bit); + DCHECK_LT(bit, 32); + const int mask = (1 << bit); + + // Check if the upload should be allowed and, if so, update the upload event + // pref to set the appropriate bit. + bool allow_upload = ((value & mask) == 0); + if (allow_upload) { + DictionaryPrefUpdate update(prefs, prefs::kAutofillUploadEvents); + update->SetKey(std::move(key), base::Value(value | mask)); + } + + // Capture metrics and return. + AutofillMetrics::LogUploadEvent(form.submission_source(), allow_upload); + return allow_upload; +} + } // namespace struct AutofillDownloadManager::FormRequestData { @@ -397,8 +449,9 @@ bool form_was_autofilled, const ServerFieldTypeSet& available_field_types, const std::string& login_form_signature, - bool observed_submission) { - if (!IsEnabled()) + bool observed_submission, + PrefService* prefs) { + if (!IsEnabled() || !IsUploadAllowed(form, prefs)) return false; AutofillUploadContents upload;
diff --git a/components/autofill/core/browser/autofill_download_manager.h b/components/autofill/core/browser/autofill_download_manager.h index c1b7b97b..b51e3cc 100644 --- a/components/autofill/core/browser/autofill_download_manager.h +++ b/components/autofill/core/browser/autofill_download_manager.h
@@ -23,6 +23,8 @@ #include "services/network/public/cpp/simple_url_loader.h" #include "url/gurl.h" +class PrefService; + namespace autofill { class AutofillDriver; @@ -86,7 +88,8 @@ bool form_was_autofilled, const ServerFieldTypeSet& available_field_types, const std::string& login_form_signature, - bool observed_submission); + bool observed_submission, + PrefService* pref_service); // Returns true if the autofill server communication is enabled. bool IsEnabled() const { return autofill_server_url_.is_valid(); }
diff --git a/components/autofill/core/browser/autofill_download_manager_unittest.cc b/components/autofill/core/browser/autofill_download_manager_unittest.cc index 4b76b58..a7d2e25b 100644 --- a/components/autofill/core/browser/autofill_download_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -27,12 +27,15 @@ #include "base/threading/thread_task_runner_handle.h" #include "components/autofill/core/browser/autofill_field.h" #include "components/autofill/core/browser/autofill_metrics.h" +#include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/form_structure.h" +#include "components/autofill/core/browser/test_autofill_clock.h" #include "components/autofill/core/browser/test_autofill_driver.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_switches.h" #include "components/autofill/core/common/form_data.h" +#include "components/prefs/pref_service.h" #include "net/http/http_status_code.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" @@ -85,7 +88,8 @@ : test_shared_loader_factory_( base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_)), - download_manager_(&driver_, this) { + download_manager_(&driver_, this), + pref_service_(test::PrefServiceForTesting()) { driver_.SetSharedURLLoaderFactory(test_shared_loader_factory_); } @@ -143,6 +147,7 @@ network::TestURLLoaderFactory test_url_loader_factory_; TestAutofillDriver driver_; AutofillDownloadManager download_manager_; + std::unique_ptr<PrefService> pref_service_; }; TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) { @@ -243,14 +248,17 @@ // Request with id 1. EXPECT_TRUE(download_manager_.StartUploadRequest( - *(form_structures[0]), true, ServerFieldTypeSet(), std::string(), true)); + *(form_structures[0]), true, ServerFieldTypeSet(), std::string(), true, + pref_service_.get())); // Request with id 2. EXPECT_TRUE(download_manager_.StartUploadRequest( - *(form_structures[1]), false, ServerFieldTypeSet(), std::string(), true)); + *(form_structures[1]), false, ServerFieldTypeSet(), std::string(), true, + pref_service_.get())); // Request with id 3. Upload request with a non-empty additional password form // signature. - EXPECT_TRUE(download_manager_.StartUploadRequest( - *(form_structures[2]), false, ServerFieldTypeSet(), "42", true)); + EXPECT_TRUE(download_manager_.StartUploadRequest(*(form_structures[2]), false, + ServerFieldTypeSet(), "42", + true, pref_service_.get())); const char* responses[] = { "<autofillqueryresponse>" @@ -487,10 +495,12 @@ form.fields.push_back(field); auto form_structure = std::make_unique<FormStructure>(form); + form_structure->set_submission_source(SubmissionSource::FORM_SUBMISSION); // Request with id 0. EXPECT_TRUE(download_manager_.StartUploadRequest( - *form_structure, true, ServerFieldTypeSet(), std::string(), true)); + *form_structure, true, ServerFieldTypeSet(), std::string(), true, + pref_service_.get())); auto* request = test_url_loader_factory_.GetPendingRequest(0); @@ -532,9 +542,11 @@ responses_.pop_front(); // Validate no retry on sending a bad request. + form_structure->set_submission_source(SubmissionSource::XHR_SUCCEEDED); base::HistogramTester histogram; EXPECT_TRUE(download_manager_.StartUploadRequest( - *form_structure, true, ServerFieldTypeSet(), std::string(), true)); + *form_structure, true, ServerFieldTypeSet(), std::string(), true, + pref_service_.get())); request = test_url_loader_factory_.GetPendingRequest(2); test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList( request, @@ -755,8 +767,14 @@ void SetUp() override { testing::TestWithParam<ServerCommuncationMode>::SetUp(); - scoped_feature_list_1_.InitAndEnableFeature( - features::kAutofillCacheQueryResponses); + pref_service_ = test::PrefServiceForTesting(); + + scoped_feature_list_1_.InitWithFeatures( + // Enabled + {features::kAutofillCacheQueryResponses, + features::kAutofillUploadThrottling}, + // Disabled + {}); // Setup the server. server_.RegisterRequestHandler( @@ -870,7 +888,7 @@ AutofillDownloadManager download_manager(driver_.get(), this); bool succeeded = download_manager.StartUploadRequest( form, form_was_autofilled, available_field_types, login_form_signature, - observed_submission); + observed_submission, pref_service_.get()); if (succeeded) run_loop_->Run(); run_loop_.reset(); @@ -888,6 +906,7 @@ size_t call_count_ = 0; scoped_refptr<network::TestSharedURLLoaderFactory> shared_url_loader_factory_; std::unique_ptr<TestAutofillDriver> driver_; + std::unique_ptr<PrefService> pref_service_; }; } // namespace @@ -1043,4 +1062,172 @@ AutofillQueryTest, ::testing::Values(FINCHED_URL, COMMAND_LINE_URL)); +using AutofillUploadTest = AutofillServerCommunicationTest; + +TEST_P(AutofillUploadTest, Throttling) { + ASSERT_NE(DISABLED, GetParam()); + + FormData form; + FormFieldData field; + + field.label = ASCIIToUTF16("First Name:"); + field.name = ASCIIToUTF16("firstname"); + field.form_control_type = "text"; + form.fields.push_back(field); + + field.label = ASCIIToUTF16("Last Name:"); + field.name = ASCIIToUTF16("lastname"); + field.form_control_type = "text"; + form.fields.push_back(field); + + field.label = ASCIIToUTF16("Email:"); + field.name = ASCIIToUTF16("email"); + field.form_control_type = "text"; + form.fields.push_back(field); + + AutofillDownloadManager download_manager(driver_.get(), this); + FormStructure form_structure(form); + for (int i = 0; i < 8; ++i) { + SCOPED_TRACE(base::StringPrintf("submission source = %d", i)); + base::HistogramTester histogram_tester; + auto submission_source = static_cast<SubmissionSource>(i); + form_structure.set_submission_source(submission_source); + + // The first attempt should succeed. + EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true)); + + // The second attempt should always fail. + EXPECT_FALSE(SendUploadRequest(form_structure, true, {}, "", true)); + + // One upload was not sent. + histogram_tester.ExpectBucketCount("Autofill.UploadEvent", 0, 1); + histogram_tester.ExpectBucketCount( + AutofillMetrics::SubmissionSourceToUploadEventMetric(submission_source), + 0, 1); + + // One upload was sent. + histogram_tester.ExpectBucketCount("Autofill.UploadEvent", 1, 1); + histogram_tester.ExpectBucketCount( + AutofillMetrics::SubmissionSourceToUploadEventMetric(submission_source), + 1, 1); + } +} + +TEST_P(AutofillUploadTest, ThrottlingDisabled) { + ASSERT_NE(DISABLED, GetParam()); + + FormData form; + FormFieldData field; + + field.label = ASCIIToUTF16("First Name:"); + field.name = ASCIIToUTF16("firstname"); + field.form_control_type = "text"; + form.fields.push_back(field); + + field.label = ASCIIToUTF16("Last Name:"); + field.name = ASCIIToUTF16("lastname"); + field.form_control_type = "text"; + form.fields.push_back(field); + + field.label = ASCIIToUTF16("Email:"); + field.name = ASCIIToUTF16("email"); + field.form_control_type = "text"; + form.fields.push_back(field); + + AutofillDownloadManager download_manager(driver_.get(), this); + FormStructure form_structure(form); + + base::test::ScopedFeatureList local_feature; + local_feature.InitAndDisableFeature(features::kAutofillUploadThrottling); + + for (int i = 0; i < 8; ++i) { + SCOPED_TRACE(base::StringPrintf("submission source = %d", i)); + base::HistogramTester histogram_tester; + auto submission_source = static_cast<SubmissionSource>(i); + form_structure.set_submission_source(submission_source); + + // The first attempt should succeed. + EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true)); + + // The second attempt should also succeed + EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true)); + + // The third attempt should also succeed + EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true)); + + // No throttling metrics should be logged. + EXPECT_TRUE(histogram_tester.GetAllSamples("Autofill.UploadEvent").empty()); + EXPECT_TRUE( + histogram_tester + .GetAllSamples(AutofillMetrics::SubmissionSourceToUploadEventMetric( + submission_source)) + .empty()); + } +} + +TEST_P(AutofillUploadTest, Reset) { + ASSERT_NE(DISABLED, GetParam()); + + FormData form; + FormFieldData field; + + field.label = ASCIIToUTF16("First Name:"); + field.name = ASCIIToUTF16("firstname"); + field.form_control_type = "text"; + form.fields.push_back(field); + + field.label = ASCIIToUTF16("Last Name:"); + field.name = ASCIIToUTF16("lastname"); + field.form_control_type = "text"; + form.fields.push_back(field); + + field.label = ASCIIToUTF16("Email:"); + field.name = ASCIIToUTF16("email"); + field.form_control_type = "text"; + form.fields.push_back(field); + + AutofillDownloadManager download_manager(driver_.get(), this); + SubmissionSource submission_source = SubmissionSource::FORM_SUBMISSION; + + FormStructure form_structure(form); + form_structure.set_submission_source(submission_source); + + base::HistogramTester histogram_tester; + + TestAutofillClock test_clock; + test_clock.SetNow(base::Time::Now()); + + // The first attempt should succeed. + EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true)); + + // Advance the clock, but not past the reset period. The pref won't reset, + // so the upload should never be sent. + test_clock.Advance(base::TimeDelta::FromDays(27)); + EXPECT_FALSE(SendUploadRequest(form_structure, true, {}, "", true)); + + // Advance the clock beyond the reset period. The pref should bfde reset and + // the upload should succeed. + test_clock.Advance(base::TimeDelta::FromDays(2)); // Total = 29 + EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true)); + + // One upload was not sent. + histogram_tester.ExpectBucketCount("Autofill.UploadEvent", 0, 1); + histogram_tester.ExpectBucketCount( + AutofillMetrics::SubmissionSourceToUploadEventMetric(submission_source), + 0, 1); + + // Two uploads were sent. + histogram_tester.ExpectBucketCount("Autofill.UploadEvent", 1, 2); + histogram_tester.ExpectBucketCount( + AutofillMetrics::SubmissionSourceToUploadEventMetric(submission_source), + 1, 2); +} + +// Note that we omit DEFAULT_URL from the test params. We don't actually want +// the tests to hit the production server. We also excluded DISABLED, since +// these tests exercise "enabled" functionality. +INSTANTIATE_TEST_CASE_P(All, + AutofillUploadTest, + ::testing::Values(FINCHED_URL, COMMAND_LINE_URL)); + } // namespace autofill
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index d88f532..aa7aea9 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -303,8 +303,11 @@ SubmissionSource source, base::TimeTicks timestamp) { // TODO(crbug.com/801698): handle PROBABLY_FORM_SUBMITTED. - if (source == SubmissionSource::PROBABLY_FORM_SUBMITTED) + if (source == SubmissionSource::PROBABLY_FORM_SUBMITTED && + !base::FeatureList::IsEnabled( + features::kAutofillSaveOnProbablySubmitted)) { return; + } // We will always give Autocomplete a chance to save the data. std::unique_ptr<FormStructure> submitted_form = ValidateSubmittedForm(form); @@ -329,6 +332,7 @@ if (IsCreditCardAutofillEnabled()) credit_card_form_event_logger_->OnWillSubmitForm(); + submitted_form->set_submission_source(source); MaybeStartVoteUploadProcess(std::move(submitted_form), timestamp, /*observed_submission=*/true); @@ -339,6 +343,8 @@ if (!submitted_form) return; + submitted_form->set_submission_source(source); + CreditCard credit_card = form_data_importer_->ExtractCreditCardFromForm(*submitted_form); AutofillMetrics::CardNumberStatus card_number_status = @@ -1083,7 +1089,8 @@ download_manager_->StartUploadRequest( submitted_form, was_autofilled, non_empty_types, - /*login_form_signature=*/std::string(), observed_submission); + /*login_form_signature=*/std::string(), observed_submission, + client_->GetPrefs()); } void AutofillManager::Reset() {
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc index 84db4fc..6962703 100644 --- a/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -102,12 +102,13 @@ AutofillDownloadManager::Observer* observer) : TestAutofillDownloadManager(driver, observer) {} - MOCK_METHOD5(StartUploadRequest, + MOCK_METHOD6(StartUploadRequest, bool(const FormStructure&, bool, const ServerFieldTypeSet&, const std::string&, - bool)); + bool, + PrefService*)); private: DISALLOW_COPY_AND_ASSIGN(MockAutofillDownloadManager); @@ -6169,7 +6170,7 @@ autofill_manager_->SetExpectedObservedSubmission(true); autofill_manager_->SetCallParentUploadFormData(true); EXPECT_CALL(*download_manager_, - StartUploadRequest(_, false, _, std::string(), true)); + StartUploadRequest(_, false, _, std::string(), true, _)); base::HistogramTester histogram_tester; FormSubmitted(form);
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc index 86b8544..537886bc 100644 --- a/components/autofill/core/browser/autofill_metrics.cc +++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -22,6 +22,7 @@ #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_prefs.h" #include "components/autofill/core/common/form_data.h" +#include "components/autofill/core/common/submission_source.h" #include "services/metrics/public/cpp/ukm_builders.h" namespace autofill { @@ -1562,6 +1563,37 @@ } // static +const char* AutofillMetrics::SubmissionSourceToUploadEventMetric( + SubmissionSource source) { + switch (source) { + case SubmissionSource::NONE: + return "Autofill.UploadEvent.None"; + case SubmissionSource::SAME_DOCUMENT_NAVIGATION: + return "Autofill.UploadEvent.SameDocumentNavigation"; + case SubmissionSource::XHR_SUCCEEDED: + return "Autofill.UploadEvent.XhrSucceeded"; + case SubmissionSource::FRAME_DETACHED: + return "Autofill.UploadEvent.FrameDetached"; + case SubmissionSource::DOM_MUTATION_AFTER_XHR: + return "Autofill.UploadEvent.DomMutationAfterXhr"; + case SubmissionSource::PROBABLY_FORM_SUBMITTED: + return "Autofill.UploadEvent.ProbablyFormSubmitted"; + case SubmissionSource::FORM_SUBMISSION: + return "Autofill.UploadEvent.FormSubmission"; + } + // Unittests exercise this path, so do not put NOTREACHED() here. + return "Autofill.UploadEvent.Unknown"; +} + +// static +void AutofillMetrics::LogUploadEvent(SubmissionSource submission_source, + bool was_sent) { + UMA_HISTOGRAM_BOOLEAN("Autofill.UploadEvent", was_sent); + LogUMAHistogramEnumeration( + SubmissionSourceToUploadEventMetric(submission_source), was_sent, 2); +} + +// static void AutofillMetrics::LogCardUploadDecisionsUkm(ukm::UkmRecorder* ukm_recorder, ukm::SourceId source_id, const GURL& url,
diff --git a/components/autofill/core/browser/autofill_metrics.h b/components/autofill/core/browser/autofill_metrics.h index 20eb82a8..f0c4b7f 100644 --- a/components/autofill/core/browser/autofill_metrics.h +++ b/components/autofill/core/browser/autofill_metrics.h
@@ -27,6 +27,7 @@ class AutofillField; class CreditCard; +enum class SubmissionSource; class AutofillMetrics { public: @@ -1133,6 +1134,15 @@ // Logs if there is any suggestions for an autocomplete query. static void LogAutocompleteSuggestions(bool has_suggestions); + // Returns the UMA metric used to track whether or not an upload was sent + // after being triggered by |submission_source|. This is exposed for testing. + static const char* SubmissionSourceToUploadEventMetric( + SubmissionSource submission_source); + + // Logs whether or not an upload |was_sent| after being triggered by a + // |submission_source| event. + static void LogUploadEvent(SubmissionSource submission_source, bool was_sent); + // Logs the card upload decisions ukm for the specified |url|. // |upload_decision_metrics| is a bitmask of |CardUploadDecisionMetric|. static void LogCardUploadDecisionsUkm(ukm::UkmRecorder* ukm_recorder,
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index 6547e88..bcf37e6 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -438,13 +438,19 @@ upload->set_autofill_used(form_was_autofilled); upload->set_data_present(EncodeFieldTypes(available_field_types)); upload->set_passwords_revealed(passwords_were_revealed_); - if (submission_event_ != PasswordForm::SubmissionIndicatorEvent::NONE) { - DCHECK(submission_event_ != PasswordForm::SubmissionIndicatorEvent:: - SUBMISSION_INDICATOR_EVENT_COUNT); - upload->set_submission_event( - static_cast<AutofillUploadContents_SubmissionIndicatorEvent>( - submission_event_)); - } + + auto triggering_event = + (submission_event_ != PasswordForm::SubmissionIndicatorEvent::NONE) + ? submission_event_ + : ToSubmissionIndicatorEvent(submission_source_); + + DCHECK_LT( + submission_event_, + PasswordForm::SubmissionIndicatorEvent::SUBMISSION_INDICATOR_EVENT_COUNT); + upload->set_submission_event( + static_cast<AutofillUploadContents_SubmissionIndicatorEvent>( + triggering_event)); + if (password_attributes_vote_) { EncodePasswordAttributesVote(*password_attributes_vote_, password_length_vote_, upload);
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h index 098db543..349c2f98e 100644 --- a/components/autofill/core/browser/form_structure.h +++ b/components/autofill/core/browser/form_structure.h
@@ -24,6 +24,7 @@ #include "components/autofill/core/browser/form_types.h" #include "components/autofill/core/browser/proto/server.pb.h" #include "components/autofill/core/common/password_form.h" +#include "components/autofill/core/common/submission_source.h" #include "url/gurl.h" #include "url/origin.h" @@ -292,6 +293,11 @@ } #endif + SubmissionSource submission_source() const { return submission_source_; } + void set_submission_source(SubmissionSource submission_source) { + submission_source_ = submission_source; + } + bool operator==(const FormData& form) const; bool operator!=(const FormData& form) const; @@ -536,6 +542,8 @@ // DetermineHeuristicTypes(). int developer_engagement_metrics_; + SubmissionSource submission_source_ = SubmissionSource::NONE; + DISALLOW_COPY_AND_ASSIGN(FormStructure); };
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc index f895284..d9eef3c0 100644 --- a/components/autofill/core/browser/form_structure_unittest.cc +++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -2407,6 +2407,8 @@ upload.set_password_has_numeric(true); upload.set_password_length(10u); upload.set_action_signature(15724779818122431245U); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_NONE); test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text", nullptr, 3U, 0); @@ -2723,6 +2725,8 @@ upload.set_password_has_numeric(true); upload.set_password_length(10u); upload.set_action_signature(15724779818122431245U); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_NONE); test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text", nullptr, 3U, {0, 2}); @@ -2909,6 +2913,9 @@ // Adjust the expected proto string. upload.set_form_signature(7816485729218079147U); upload.set_autofill_used(false); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_HTML_FORM_SUBMISSION); + // Create an additional 2 fields (total of 7). for (int i = 0; i < 2; ++i) { test::FillUploadField(upload.add_field(), 509334676U, "address", "text", @@ -3037,6 +3044,8 @@ upload.set_action_signature(15724779818122431245U); upload.set_login_form_signature(42); upload.set_passwords_revealed(false); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_NONE); AutofillUploadContents::Field* upload_firstname_field = upload.add_field(); test::FillUploadField(upload_firstname_field, 4224610201U, "firstname", "", @@ -3132,6 +3141,8 @@ upload.set_data_present("1440"); upload.set_action_signature(15724779818122431245U); upload.set_passwords_revealed(false); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_NONE); test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text", "given-name", 3U); @@ -3220,6 +3231,8 @@ upload.set_autofill_used(true); upload.set_data_present("1440"); upload.set_passwords_revealed(false); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_NONE); test::FillUploadField(upload.add_field(), 3763331450U, nullptr, nullptr, nullptr, 3U); @@ -3298,6 +3311,8 @@ upload.set_data_present("1440"); upload.set_action_signature(15724779818122431245U); upload.set_passwords_revealed(false); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_NONE); test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text", nullptr, 3U); @@ -3368,6 +3383,8 @@ upload.set_data_present("1440"); upload.set_action_signature(15724779818122431245U); upload.set_passwords_revealed(false); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_NONE); test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text", nullptr, 3U); @@ -3435,6 +3452,8 @@ upload.set_data_present("1440"); upload.set_action_signature(15724779818122431245U); upload.set_passwords_revealed(false); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_NONE); AutofillUploadContents::Field* firstname_field = upload.add_field(); test::FillUploadField(firstname_field, 1318412689U, nullptr, "text", nullptr, @@ -3486,7 +3505,9 @@ form.fields.push_back(field); test::InitializePossibleTypesAndValidities( possible_field_types, possible_field_types_validities, {EMAIL_ADDRESS}); + form_structure.reset(new FormStructure(form)); + form_structure->set_submission_source(SubmissionSource::FRAME_DETACHED); ASSERT_EQ(form_structure->field_count(), possible_field_types.size()); ASSERT_EQ(form_structure->field_count(), @@ -3513,6 +3534,8 @@ upload.set_action_signature(15724779818122431245U); upload.set_form_name("myform"); upload.set_passwords_revealed(false); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_FRAME_DETACHED); test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text", nullptr, 3U); @@ -3588,6 +3611,8 @@ upload.set_data_present("1440"); upload.set_passwords_revealed(false); upload.set_action_signature(15724779818122431245U); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_NONE); test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text", nullptr, 3U); @@ -3672,6 +3697,8 @@ upload.set_autofill_used(true); upload.set_data_present("1440"); upload.set_passwords_revealed(false); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_NONE); test::FillUploadField(upload.add_field(), 3763331450U, nullptr, nullptr, nullptr, 3U); @@ -3713,6 +3740,7 @@ form.fields.push_back(field); FormStructure form_structure(form); + form_structure.set_submission_source(SubmissionSource::FORM_SUBMISSION); std::vector<ServerFieldTypeSet> possible_field_types; std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; @@ -3739,6 +3767,8 @@ upload.set_data_present(""); upload.set_passwords_revealed(false); upload.set_action_signature(15724779818122431245U); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_HTML_FORM_SUBMISSION); test::FillUploadField(upload.add_field(), 1089846351U, "first", "text", nullptr, 1U); @@ -3997,7 +4027,7 @@ {ADDRESS_HOME_LINE1}); form_structure.reset(new FormStructure(form)); - + form_structure->set_submission_source(SubmissionSource::XHR_SUCCEEDED); for (size_t i = 0; i < form_structure->field_count(); ++i) { form_structure->field(i)->set_possible_types(possible_field_types[i]); form_structure->field(i)->set_possible_types_validities( @@ -4013,6 +4043,8 @@ upload.set_data_present("1440000360000008"); upload.set_passwords_revealed(false); upload.set_action_signature(15724779818122431245U); + upload.set_submission_event( + AutofillUploadContents_SubmissionIndicatorEvent_XHR_SUCCEEDED); test::FillUploadField(upload.add_field(), 420638584U, "email", "text", nullptr, 9U);
diff --git a/components/autofill/core/browser/proto/server.proto b/components/autofill/core/browser/proto/server.proto index 9389048..263fabf 100644 --- a/components/autofill/core/browser/proto/server.proto +++ b/components/autofill/core/browser/proto/server.proto
@@ -342,6 +342,7 @@ PROVISIONALLY_SAVED_FORM_ON_START_PROVISIONAL_LOAD = 7; DEPRECATED_FILLED_FORM_ON_START_PROVISIONAL_LOAD = 8; // unused DEPRECATED_FILLED_INPUT_ELEMENTS_ON_START_PROVISIONAL_LOAD = 9; // unused + PROBABLE_FORM_SUBMISSION = 10; } // The type of the event that was taken as an indication that the form has
diff --git a/components/autofill/core/browser/test_autofill_clock.cc b/components/autofill/core/browser/test_autofill_clock.cc index a43489e..97d50fa3c 100644 --- a/components/autofill/core/browser/test_autofill_clock.cc +++ b/components/autofill/core/browser/test_autofill_clock.cc
@@ -24,4 +24,8 @@ test_clock_.SetNow(now); } +void TestAutofillClock::Advance(base::TimeDelta delta) { + test_clock_.Advance(delta); +} + } // namespace autofill
diff --git a/components/autofill/core/browser/test_autofill_clock.h b/components/autofill/core/browser/test_autofill_clock.h index 71bc882..2b97361 100644 --- a/components/autofill/core/browser/test_autofill_clock.h +++ b/components/autofill/core/browser/test_autofill_clock.h
@@ -28,6 +28,9 @@ // Set the time to be returned from AutofillClock::Now() calls. void SetNow(base::Time now); + // Advances the clock by |delta|. + void Advance(base::TimeDelta delta); + private: base::SimpleTestClock test_clock_;
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index a3eed220..bfe67a7 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -158,6 +158,9 @@ "AutofillRestrictUnownedFieldsToFormlessCheckout", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kAutofillSaveOnProbablySubmitted{ + "AutofillSaveOnProbablySubmitted", base::FEATURE_ENABLED_BY_DEFAULT}; + const base::Feature kAutofillSaveCardDialogUnlabeledExpirationDate{ "AutofillSaveCardDialogUnlabeledExpirationDate", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -223,6 +226,9 @@ const base::Feature kAutofillSuppressDisusedCreditCards{ "AutofillSuppressDisusedCreditCards", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kAutofillUploadThrottling{"AutofillUploadThrottling", + base::FEATURE_ENABLED_BY_DEFAULT}; + const base::Feature kAutofillUpstream{"AutofillUpstream", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 8cb99c0..e0c5658d 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -53,6 +53,7 @@ extern const base::Feature kAutofillRestrictUnownedFieldsToFormlessCheckout; extern const base::Feature kAutofillSaveCardDialogUnlabeledExpirationDate; extern const base::Feature kAutofillSaveCardSignInAfterLocalSave; +extern const base::Feature kAutofillSaveOnProbablySubmitted; extern const base::Feature kAutofillScanCardholderName; extern const base::Feature kAutofillSendExperimentIdsInPaymentsRPCs; extern const base::Feature kAutofillSendOnlyCountryInGetUploadDetails; @@ -64,6 +65,7 @@ extern const base::Feature kAutofillSuggestInvalidProfileData; extern const base::Feature kAutofillSuppressDisusedAddresses; extern const base::Feature kAutofillSuppressDisusedCreditCards; +extern const base::Feature kAutofillUploadThrottling; extern const base::Feature kAutofillUpstream; extern const base::Feature kAutofillUpstreamAllowAllEmailDomains; extern const base::Feature kAutofillUpstreamAlwaysRequestCardholderName;
diff --git a/components/autofill/core/common/autofill_prefs.cc b/components/autofill/core/common/autofill_prefs.cc index 5b9c0dcf..1d1d054 100644 --- a/components/autofill/core/common/autofill_prefs.cc +++ b/components/autofill/core/common/autofill_prefs.cc
@@ -60,6 +60,17 @@ // Boolean that is true if Autofill is enabled and allowed to save profile data. const char kAutofillProfileEnabled[] = "autofill.profile_enabled"; +// Dictionary pref used to track which form signature uploads have been +// performed. Each entry in the dictionary maps a form signature (reduced +// via a 10-bit modulus) to a integer bit-field where each bit denotes whether +// or not a given upload event has occurred. +const char kAutofillUploadEvents[] = "autofill.upload_events"; + +// The timestamp (seconds since the Epoch UTC) for when the the upload event +// pref was last reset. +const char kAutofillUploadEventsLastResetTimestamp[] = + "autofill.upload_events_last_reset_timestamp"; + // Boolean that's true when Wallet card and address import is enabled by the // user. const char kAutofillWalletImportEnabled[] = "autofill.wallet_import_enabled"; @@ -106,6 +117,9 @@ registry->RegisterIntegerPref( prefs::kAutofillLastVersionDisusedCreditCardsDeleted, 0); registry->RegisterBooleanPref(prefs::kAutofillOrphanRowsRemoved, false); + registry->RegisterDictionaryPref(prefs::kAutofillUploadEvents); + registry->RegisterTimePref(prefs::kAutofillUploadEventsLastResetTimestamp, + base::Time()); } void MigrateDeprecatedAutofillPrefs(PrefService* prefs) {
diff --git a/components/autofill/core/common/autofill_prefs.h b/components/autofill/core/common/autofill_prefs.h index 4dc9d14..aee9128 100644 --- a/components/autofill/core/common/autofill_prefs.h +++ b/components/autofill/core/common/autofill_prefs.h
@@ -32,6 +32,8 @@ extern const char kAutofillOrphanRowsRemoved[]; // Do not get/set the value of this pref directly. Use provided getter/setter. extern const char kAutofillProfileEnabled[]; +extern const char kAutofillUploadEvents[]; +extern const char kAutofillUploadEventsLastResetTimestamp[]; extern const char kAutofillWalletImportEnabled[]; extern const char kAutofillWalletImportStorageCheckboxState[]; extern const char kAutofillProfileValidity[];
diff --git a/components/autofill/core/common/password_form.cc b/components/autofill/core/common/password_form.cc index 34a9bec..65f8a2d 100644 --- a/components/autofill/core/common/password_form.cc +++ b/components/autofill/core/common/password_form.cc
@@ -12,6 +12,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "components/autofill/core/common/password_form.h" +#include "components/autofill/core/common/submission_source.h" namespace autofill { @@ -198,6 +199,28 @@ return base::JoinString(pairs, base::ASCIIToUTF16(", ")); } +PasswordForm::SubmissionIndicatorEvent ToSubmissionIndicatorEvent( + SubmissionSource source) { + switch (source) { + case SubmissionSource::NONE: + return PasswordForm::SubmissionIndicatorEvent::NONE; + case SubmissionSource::SAME_DOCUMENT_NAVIGATION: + return PasswordForm::SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION; + case SubmissionSource::XHR_SUCCEEDED: + return PasswordForm::SubmissionIndicatorEvent::XHR_SUCCEEDED; + case SubmissionSource::FRAME_DETACHED: + return PasswordForm::SubmissionIndicatorEvent::FRAME_DETACHED; + case SubmissionSource::DOM_MUTATION_AFTER_XHR: + return PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR; + case SubmissionSource::PROBABLY_FORM_SUBMITTED: + return PasswordForm::SubmissionIndicatorEvent::PROBABLE_FORM_SUBMISSION; + case SubmissionSource::FORM_SUBMISSION: + return PasswordForm::SubmissionIndicatorEvent::HTML_FORM_SUBMISSION; + } + // Unittests exercise this path, so do not put NOTREACHED() here. + return PasswordForm::SubmissionIndicatorEvent::NONE; +} + std::ostream& operator<<(std::ostream& os, const PasswordForm& form) { base::DictionaryValue form_json; PasswordFormToJSON(form, &form_json);
diff --git a/components/autofill/core/common/password_form.h b/components/autofill/core/common/password_form.h index 10253567..3f5f51b 100644 --- a/components/autofill/core/common/password_form.h +++ b/components/autofill/core/common/password_form.h
@@ -18,6 +18,8 @@ namespace autofill { +enum class SubmissionSource; + // Pair of a value and the name of the element that contained this value. using ValueElementPair = std::pair<base::string16, base::string16>; @@ -85,6 +87,7 @@ PROVISIONALLY_SAVED_FORM_ON_START_PROVISIONAL_LOAD, DEPRECATED_FILLED_FORM_ON_START_PROVISIONAL_LOAD, // unused DEPRECATED_FILLED_INPUT_ELEMENTS_ON_START_PROVISIONAL_LOAD, // unused + PROBABLE_FORM_SUBMISSION, SUBMISSION_INDICATOR_EVENT_COUNT }; @@ -361,6 +364,9 @@ base::string16 ValueElementVectorToString( const ValueElementVector& value_element_pairs); +PasswordForm::SubmissionIndicatorEvent ToSubmissionIndicatorEvent( + SubmissionSource source); + // For testing. std::ostream& operator<<(std::ostream& os, const PasswordForm& form); std::ostream& operator<<(std::ostream& os, PasswordForm* form);
diff --git a/components/autofill/core/common/submission_source.h b/components/autofill/core/common/submission_source.h index d6c213b2..5eab05a1 100644 --- a/components/autofill/core/common/submission_source.h +++ b/components/autofill/core/common/submission_source.h
@@ -9,6 +9,7 @@ // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.autofill enum class SubmissionSource { + NONE, // No submission signal was detected. SAME_DOCUMENT_NAVIGATION, // The form was removed in same document // navigation. XHR_SUCCEEDED, // The form was removed whem XHR succeeded.
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp index 9c93add1..040b934 100644 --- a/components/autofill_strings.grdp +++ b/components/autofill_strings.grdp
@@ -252,6 +252,9 @@ <!-- Autofill Local card migration bubble or dialog --> <if expr="not is_ios and not is_android"> + <message name="IDS_AUTOFILL_GOOGLE_PAY_LOGO_ACCESSIBLE_NAME" desc="The accessible name for the Google Pay logo in the local card migration bubble or dialog."> + Google Pay logo + </message> <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_BUBBLE_TITLE" desc="The title text for a bubble that offers users to start the process of migrating local cards to cloud."> Save all your cards in one place? </message>
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java index 0928f3ca..b00f636 100644 --- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java +++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java
@@ -7,6 +7,7 @@ import android.content.Context; import android.os.Build; +import org.chromium.base.CommandLine; import org.chromium.base.Log; import org.chromium.base.ThreadUtils; import org.chromium.base.TraceEvent; @@ -21,6 +22,7 @@ */ class BackgroundTaskSchedulerImpl implements BackgroundTaskScheduler { private static final String TAG = "BkgrdTaskScheduler"; + private static final String SWITCH_IGNORE_BACKGROUND_TASKS = "ignore-background-tasks"; private final BackgroundTaskSchedulerDelegate mSchedulerDelegate; @@ -31,6 +33,12 @@ @Override public boolean schedule(Context context, TaskInfo taskInfo) { + if (CommandLine.getInstance().hasSwitch(SWITCH_IGNORE_BACKGROUND_TASKS)) { + // When background tasks finish executing, they leave a cached process, which + // artificially inflates startup metrics that are based on events near to process + // creation. + return true; + } try (TraceEvent te = TraceEvent.scoped( "BackgroundTaskScheduler.schedule", Integer.toString(taskInfo.getTaskId()))) { ThreadUtils.assertOnUiThread();
diff --git a/components/heap_profiling/test_driver.cc b/components/heap_profiling/test_driver.cc index 592467a..a070690 100644 --- a/components/heap_profiling/test_driver.cc +++ b/components/heap_profiling/test_driver.cc
@@ -901,8 +901,7 @@ if (IsRecordingAllAllocations()) { if (should_validate_dumps) { result = ValidateDump(heaps_v2, kMallocAllocSize * kMallocAllocCount, - kMallocAllocCount, "malloc", - HasPseudoFrames() ? kMallocTypeTag : nullptr, + kMallocAllocCount, "malloc", kMallocTypeTag, HasPseudoFrames() ? kMallocEvent : "", thread_name); if (!result) { LOG(ERROR) << "Failed to validate malloc fixed allocations";
diff --git a/components/image_fetcher/core/DEPS b/components/image_fetcher/core/DEPS index 9b2c814f..ab5ae2fd 100644 --- a/components/image_fetcher/core/DEPS +++ b/components/image_fetcher/core/DEPS
@@ -1,4 +1,7 @@ include_rules = [ "+components/leveldb_proto", "+components/prefs", + "+ui/gfx/codec", + "+ui/gfx/geomtery", + "+ui/gfx/image", ]
diff --git a/components/image_fetcher/core/cached_image_fetcher.cc b/components/image_fetcher/core/cached_image_fetcher.cc index 8c00a300..437b066 100644 --- a/components/image_fetcher/core/cached_image_fetcher.cc +++ b/components/image_fetcher/core/cached_image_fetcher.cc
@@ -10,24 +10,45 @@ #include "components/image_fetcher/core/image_decoder.h" #include "components/image_fetcher/core/request_metadata.h" #include "components/image_fetcher/core/storage/image_cache.h" +#include "ui/gfx/codec/png_codec.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/image/image.h" +#include "ui/gfx/image/image_skia.h" namespace image_fetcher { namespace { -// Wrapper to check if callbacks can be called. -void CallbackIfPresent(ImageDataFetcherCallback data_callback, - ImageFetcherCallback image_callback, - const std::string& id, - const std::string& image_data, - const gfx::Image& image, - const image_fetcher::RequestMetadata& metadata) { - if (!data_callback.is_null()) - std::move(data_callback).Run(image_data, metadata); - if (!image_callback.is_null()) - std::move(image_callback).Run(id, image, metadata); +void DataCallbackIfPresent(ImageDataFetcherCallback data_callback, + const std::string& image_data, + const image_fetcher::RequestMetadata& metadata) { + if (data_callback.is_null()) { + return; + } + std::move(data_callback).Run(image_data, metadata); +} + +void ImageCallbackIfPresent(ImageFetcherCallback image_callback, + const std::string& id, + const gfx::Image& image, + const image_fetcher::RequestMetadata& metadata) { + if (image_callback.is_null()) { + return; + } + std::move(image_callback).Run(id, image, metadata); +} + +bool EncodeSkBitmapToPNG(const SkBitmap& bitmap, + std::vector<unsigned char>* dest) { + if (!bitmap.readyToDraw() || bitmap.isNull()) { + return false; + } + + return gfx::PNGCodec::Encode( + static_cast<const unsigned char*>(bitmap.getPixels()), + gfx::PNGCodec::FORMAT_RGBA, gfx::Size(bitmap.width(), bitmap.height()), + static_cast<int>(bitmap.rowBytes()), /* discard_transparency */ false, + std::vector<gfx::PNGCodec::Comment>(), dest); } } // namespace @@ -51,6 +72,7 @@ void CachedImageFetcher::SetDesiredImageFrameSize(const gfx::Size& size) { image_fetcher_->SetDesiredImageFrameSize(size); + desired_image_frame_size_ = size; } void CachedImageFetcher::SetImageDownloadLimit( @@ -89,8 +111,9 @@ FetchImageFromNetwork(id, image_url, std::move(data_callback), std::move(image_callback), traffic_annotation); } else { + // TODO(wylieb): On Android, do this in-process. GetImageDecoder()->DecodeImage( - image_data, gfx::Size(), + image_data, desired_image_frame_size_, base::BindRepeating(&CachedImageFetcher::OnImageDecodedFromCache, weak_ptr_factory_.GetWeakPtr(), id, image_url, base::Passed(std::move(data_callback)), @@ -110,10 +133,13 @@ if (image.IsEmpty()) { FetchImageFromNetwork(id, image_url, std::move(data_callback), std::move(image_callback), traffic_annotation); + // Decoding error, delete image from cache. image_cache_->DeleteImage(image_url.spec()); } else { - CallbackIfPresent(std::move(data_callback), std::move(image_callback), id, - image_data, image, RequestMetadata()); + DataCallbackIfPresent(std::move(data_callback), image_data, + RequestMetadata()); + ImageCallbackIfPresent(std::move(image_callback), id, image, + RequestMetadata()); } } @@ -123,58 +149,50 @@ ImageDataFetcherCallback data_callback, ImageFetcherCallback image_callback, const net::NetworkTrafficAnnotationTag& traffic_annotation) { - if (!image_url.is_valid()) { - // URL is invalid, return empty image/data. - CallbackIfPresent(std::move(data_callback), std::move(image_callback), id, - std::string(), gfx::Image(), RequestMetadata()); - return; - } - - image_fetcher_->FetchImageData( + // Fetch image data and the image itself. The image data will be stored in + // the image cache, and the image will be returned to the caller. + image_fetcher_->FetchImageAndData( id, image_url, + base::BindOnce(&CachedImageFetcher::OnImageDataFetchedFromNetwork, + weak_ptr_factory_.GetWeakPtr(), std::move(data_callback), + image_url), base::BindOnce(&CachedImageFetcher::OnImageFetchedFromNetwork, - weak_ptr_factory_.GetWeakPtr(), id, image_url, - std::move(data_callback), std::move(image_callback)), + weak_ptr_factory_.GetWeakPtr(), std::move(image_callback)), traffic_annotation); } void CachedImageFetcher::OnImageFetchedFromNetwork( - const std::string& id, - const GURL& image_url, - ImageDataFetcherCallback data_callback, ImageFetcherCallback image_callback, + const std::string& id, + const gfx::Image& image, + const RequestMetadata& request_metadata) { + // The image has been deocded by the fetcher already, return straight to the + // caller. + ImageCallbackIfPresent(std::move(image_callback), id, image, + request_metadata); +} + +void CachedImageFetcher::OnImageDataFetchedFromNetwork( + ImageDataFetcherCallback data_callback, + const GURL& image_url, const std::string& image_data, const RequestMetadata& request_metadata) { - if (image_data.empty()) { - // Fetching image failed, return empty image/data. - CallbackIfPresent(std::move(data_callback), std::move(image_callback), id, - image_data, gfx::Image(), request_metadata); + DataCallbackIfPresent(std::move(data_callback), image_data, request_metadata); + GetImageDecoder()->DecodeImage( + image_data, /* Decoding for cache shouldn't specify size */ gfx::Size(), + base::BindRepeating(&CachedImageFetcher::OnImageDecodedFromNetwork, + weak_ptr_factory_.GetWeakPtr(), image_url)); +} + +void CachedImageFetcher::OnImageDecodedFromNetwork(const GURL& image_url, + const gfx::Image& image) { + std::vector<unsigned char> encoded_data; + if (!EncodeSkBitmapToPNG(*image.ToSkBitmap(), &encoded_data)) { return; } - image_fetcher_->GetImageDecoder()->DecodeImage( - image_data, gfx::Size(), - base::BindRepeating(&CachedImageFetcher::OnImageDecodedFromNetwork, - weak_ptr_factory_.GetWeakPtr(), id, image_url, - base::Passed(std::move(data_callback)), - base::Passed(std::move(image_callback)), image_data, - request_metadata)); -} - -void CachedImageFetcher::OnImageDecodedFromNetwork( - const std::string& id, - const GURL& image_url, - ImageDataFetcherCallback data_callback, - ImageFetcherCallback image_callback, - const std::string& image_data, - const RequestMetadata& request_metadata, - const gfx::Image& image) { - CallbackIfPresent(std::move(data_callback), std::move(image_callback), id, - image_data, image, request_metadata); - - if (!image.IsEmpty()) { - image_cache_->SaveImage(image_url.spec(), image_data); - } + image_cache_->SaveImage( + image_url.spec(), std::string(encoded_data.begin(), encoded_data.end())); } } // namespace image_fetcher
diff --git a/components/image_fetcher/core/cached_image_fetcher.h b/components/image_fetcher/core/cached_image_fetcher.h index 410e98d..1b3ebe0 100644 --- a/components/image_fetcher/core/cached_image_fetcher.h +++ b/components/image_fetcher/core/cached_image_fetcher.h
@@ -20,6 +20,7 @@ namespace gfx { class Image; +class Size; } // namespace gfx namespace image_fetcher { @@ -76,23 +77,23 @@ ImageDataFetcherCallback image_data_callback, ImageFetcherCallback image_callback, const net::NetworkTrafficAnnotationTag& traffic_annotation); - void OnImageFetchedFromNetwork(const std::string& id, - const GURL& image_url, - ImageDataFetcherCallback image_data_callback, - ImageFetcherCallback image_callback, - const std::string& image_data, + void OnImageFetchedFromNetwork(ImageFetcherCallback image_callback, + const std::string& id, + const gfx::Image& image, const RequestMetadata& request_metadata); - void OnImageDecodedFromNetwork(const std::string& id, - const GURL& image_url, - ImageDataFetcherCallback image_data_callback, - ImageFetcherCallback image_callback, - const std::string& image_data, - const RequestMetadata& request_metadata, + void OnImageDataFetchedFromNetwork( + ImageDataFetcherCallback image_data_callback, + const GURL& image_url, + const std::string& image_data, + const RequestMetadata& request_metadata); + void OnImageDecodedFromNetwork(const GURL& image_url, const gfx::Image& image); std::unique_ptr<ImageFetcher> image_fetcher_; std::unique_ptr<ImageCache> image_cache_; + gfx::Size desired_image_frame_size_; + base::WeakPtrFactory<CachedImageFetcher> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(CachedImageFetcher);
diff --git a/components/image_fetcher/core/cached_image_fetcher_unittest.cc b/components/image_fetcher/core/cached_image_fetcher_unittest.cc index 944919e..76bc141 100644 --- a/components/image_fetcher/core/cached_image_fetcher_unittest.cc +++ b/components/image_fetcher/core/cached_image_fetcher_unittest.cc
@@ -137,23 +137,12 @@ return !arg.IsEmpty(); } -// TODO(wylieb): Rename these tests CachedImageFetcherTest* when ntp_snippets/- -// remote/cached_image_fetcher has been migrated. -TEST_F(ComponentizedCachedImageFetcherTest, FetchEmptyUrl) { - base::MockCallback<ImageDataFetcherCallback> data_callback; - base::MockCallback<ImageFetcherCallback> image_callback; - GURL empty_url = GURL(std::string()); - - // Make sure an empty image passed to callback. - EXPECT_CALL(data_callback, Run(std::string(), _)); - EXPECT_CALL(image_callback, Run(std::string(), EmptyImage(), _)); - cached_image_fetcher()->FetchImageAndData( - empty_url.spec(), empty_url, data_callback.Get(), image_callback.Get(), - TRAFFIC_ANNOTATION_FOR_TESTS); - - RunUntilIdle(); +MATCHER(NonEmptyString, "") { + return !arg.empty(); } +// TODO(wylieb): Rename these tests CachedImageFetcherTest* when ntp_snippets/- +// remote/cached_image_fetcher has been migrated. TEST_F(ComponentizedCachedImageFetcherTest, FetchImageFromCache) { // Save the image in the database. image_cache()->SaveImage(kImageUrl.spec(), kImageData); @@ -179,7 +168,7 @@ base::MockCallback<ImageDataFetcherCallback> data_callback; base::MockCallback<ImageFetcherCallback> image_callback; - EXPECT_CALL(data_callback, Run(kImageData, _)); + EXPECT_CALL(data_callback, Run(NonEmptyString(), _)); EXPECT_CALL(image_callback, Run(kImageUrl.spec(), NonEmptyImage(), _)); cached_image_fetcher()->FetchImageAndData( kImageUrl.spec(), kImageUrl, data_callback.Get(), image_callback.Get(), @@ -189,7 +178,7 @@ } // Make sure the image data is in the database. { - EXPECT_CALL(*this, OnImageLoaded(kImageData)); + EXPECT_CALL(*this, OnImageLoaded(NonEmptyString())); image_cache()->LoadImage( kImageUrl.spec(), base::BindOnce(&ComponentizedCachedImageFetcherTest::OnImageLoaded, @@ -203,7 +192,7 @@ base::MockCallback<ImageDataFetcherCallback> data_callback; base::MockCallback<ImageFetcherCallback> image_callback; - EXPECT_CALL(data_callback, Run(kImageData, _)); + EXPECT_CALL(data_callback, Run(NonEmptyString(), _)); EXPECT_CALL(image_callback, Run(kImageUrl.spec(), NonEmptyImage(), _)); cached_image_fetcher()->FetchImageAndData( kImageUrl.spec(), kImageUrl, data_callback.Get(), image_callback.Get(),
diff --git a/components/network_session_configurator/browser/network_session_configurator_unittest.cc b/components/network_session_configurator/browser/network_session_configurator_unittest.cc index 0c8388a5..2fdb96a 100644 --- a/components/network_session_configurator/browser/network_session_configurator_unittest.cc +++ b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -734,13 +734,6 @@ EXPECT_EQ("foo", host_port_pair.host()); } -TEST_F(NetworkSessionConfiguratorTest, TokenBindingDisabled) { - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - ParseCommandLineAndFieldTrials(command_line); - - EXPECT_FALSE(params_.enable_token_binding); -} - TEST_F(NetworkSessionConfiguratorTest, ChannelIDEnabled) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature(features::kChannelID);
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc index 81af9db..c2e9321 100644 --- a/components/omnibox/browser/omnibox_edit_model.cc +++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -235,11 +235,15 @@ if (GetQueryInOmniboxSearchTerms(&display_text_)) { // The search query has been inserted into |display_text_|. DCHECK(!display_text_.empty()); - } else if (OmniboxFieldTrial:: - IsHideSteadyStateUrlSchemeAndSubdomainsEnabled()) { - display_text_ = toolbar_model->GetURLForDisplay(); } else { +#if defined(OS_IOS) + // iOS is unusual in that it uses a separate LocationView to show the + // ToolbarModel's display-only URL. The actual OmniboxViewIOS widget is + // hidden in the defocused state, and always contains the URL for editing. display_text_ = url_for_editing_; +#else + display_text_ = toolbar_model->GetURLForDisplay(); +#endif } // When there's new permanent text, and the user isn't interacting with the
diff --git a/components/omnibox/browser/omnibox_edit_model_unittest.cc b/components/omnibox/browser/omnibox_edit_model_unittest.cc index 864f3ee..5546b1a5 100644 --- a/components/omnibox/browser/omnibox_edit_model_unittest.cc +++ b/components/omnibox/browser/omnibox_edit_model_unittest.cc
@@ -58,7 +58,6 @@ const bool write_url; const char* expected_url; - bool steady_state_elisions_on = false; const char* url_for_display = ""; } input[] = { // Test that http:// is inserted if all text is selected. @@ -103,7 +102,8 @@ "http://a.de/"}, // Makes sure intranet urls get 'http://' prefixed to them. - {"b/foo", 0, "", false, "b/foo", "http://b/foo", true, "http://b/foo"}, + {"b/foo", 0, "", false, "b/foo", "http://b/foo", true, "http://b/foo", + "b/foo"}, // Verifies a search term 'foo' doesn't end up with http. {"www.google.com/search?", 0, "", false, "foo", "foo", false, ""}, @@ -126,19 +126,10 @@ // Steady State Elisions test for re-adding an elided 'https://'. {"https://a.de/b", 0, "", false, "a.de/b", "https://a.de/b", true, - "https://a.de/b", true, "a.de/b"}, + "https://a.de/b", "a.de/b"}, }; for (size_t i = 0; i < arraysize(input); ++i) { - base::test::ScopedFeatureList feature_list; - if (input[i].steady_state_elisions_on) { - feature_list.InitAndEnableFeature( - omnibox::kUIExperimentHideSteadyStateUrlSchemeAndSubdomains); - } else { - feature_list.InitAndDisableFeature( - omnibox::kUIExperimentHideSteadyStateUrlSchemeAndSubdomains); - } - toolbar_model()->set_formatted_full_url( base::ASCIIToUTF16(input[i].url_for_editing)); toolbar_model()->set_url_for_display( @@ -242,41 +233,23 @@ base::ASCIIToUTF16("https://www.example.com/")); toolbar_model()->set_url_for_display(base::ASCIIToUTF16("example.com")); - // Verify the displayed text with Steady State Elisions Enabled. + // Verify we show the display text when there is no Query in Omnibox match. { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndDisableFeature( - omnibox::kUIExperimentHideSteadyStateUrlSchemeAndSubdomains); model()->ResetDisplayTexts(); +#if defined(OS_IOS) + // iOS OmniboxEditModel always provides the full URL as the OmniboxView + // permanent display text. EXPECT_EQ(base::ASCIIToUTF16("https://www.example.com/"), model()->GetPermanentDisplayText()); - - base::string16 search_terms; - EXPECT_FALSE(model()->GetQueryInOmniboxSearchTerms(&search_terms)); - EXPECT_TRUE(search_terms.empty()); - } - -// TODO(tommycli): For now, it's not possible to enable Steady State Elisions -// in the edit model for iOS. -#if !defined(OS_IOS) - // Verify the displayed text with Steady State Elisions Disabled. - { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature( - omnibox::kUIExperimentHideSteadyStateUrlSchemeAndSubdomains); - - ASSERT_TRUE( - OmniboxFieldTrial::IsHideSteadyStateUrlSchemeAndSubdomainsEnabled()); - - model()->ResetDisplayTexts(); +#else EXPECT_EQ(base::ASCIIToUTF16("example.com"), model()->GetPermanentDisplayText()); +#endif base::string16 search_terms; EXPECT_FALSE(model()->GetQueryInOmniboxSearchTerms(&search_terms)); EXPECT_TRUE(search_terms.empty()); } -#endif // !defined(OS_IOS) // Verify the displayed text when there is a Query in Omnibox match. TestOmniboxClient* client =
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc index 675a7a1..45daced6 100644 --- a/components/omnibox/browser/omnibox_field_trial.cc +++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -146,12 +146,6 @@ "OmniboxUIExperimentElideSuggestionUrlAfterHost", base::FEATURE_DISABLED_BY_DEFAULT}; -// Feature used to hide the scheme and trivial subdomains from steady state -// URLs displayed in the Omnibox. Hidden portions are restored during editing. -const base::Feature kUIExperimentHideSteadyStateUrlSchemeAndSubdomains{ - "OmniboxUIExperimentHideSteadyStateUrlSchemeAndSubdomains", - base::FEATURE_DISABLED_BY_DEFAULT}; - // Feature used to jog the Omnibox textfield to align with the dropdown // suggestions text when the popup is opened. When this feature is disabled, the // textfield is always aligned with the suggestions text, and a separator fills @@ -773,12 +767,6 @@ return omnibox::pedal_suggestion_mode.Get(); } -bool OmniboxFieldTrial::IsHideSteadyStateUrlSchemeAndSubdomainsEnabled() { - return base::FeatureList::IsEnabled( - omnibox::kUIExperimentHideSteadyStateUrlSchemeAndSubdomains) || - base::FeatureList::IsEnabled(features::kExperimentalUi); -} - bool OmniboxFieldTrial::IsJogTextfieldOnPopupEnabled() { return ui::MaterialDesignController::IsRefreshUi() && base::FeatureList::IsEnabled(
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h index d0c98da..e24290b 100644 --- a/components/omnibox/browser/omnibox_field_trial.h +++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -39,7 +39,6 @@ extern const base::Feature kDisplayTitleForCurrentUrl; extern const base::Feature kQueryInOmnibox; extern const base::Feature kUIExperimentElideSuggestionUrlAfterHost; -extern const base::Feature kUIExperimentHideSteadyStateUrlSchemeAndSubdomains; extern const base::Feature kUIExperimentJogTextfieldOnPopup; extern const base::Feature kUIExperimentMaxAutocompleteMatches; extern const base::Feature kUIExperimentShowSuggestionFavicons; @@ -439,10 +438,6 @@ // Returns the #omnibox-pedal-suggestions feature's mode parameter as enum. static PedalSuggestionMode GetPedalSuggestionMode(); - // Returns true if either the steady-state elision flag or the - // #upcoming-ui-features flag is enabled. - static bool IsHideSteadyStateUrlSchemeAndSubdomainsEnabled(); - // Returns true if the jog textfield flag and refresh UI are both enabled. static bool IsJogTextfieldOnPopupEnabled();
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc index 9e9534ae..c9872b0 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -210,12 +210,13 @@ autofill::AutofillDownloadManager::Observer* observer) : AutofillDownloadManager(driver, observer) {} - MOCK_METHOD5(StartUploadRequest, + MOCK_METHOD6(StartUploadRequest, bool(const autofill::FormStructure&, bool, const autofill::ServerFieldTypeSet&, const std::string&, - bool)); + bool, + PrefService*)); private: DISALLOW_COPY_AND_ASSIGN(MockAutofillDownloadManager); @@ -466,7 +467,7 @@ Field::CREDENTIALS_REUSED}})), HasPasswordAttributesVote(false)), false, expected_available_field_types, - expected_login_signature, true)); + expected_login_signature, true, nullptr)); } else { EXPECT_CALL( *client()->mock_driver()->mock_autofill_download_manager(), @@ -475,18 +476,18 @@ HasGenerationVote(expect_generation_vote), HasPasswordAttributesVote(false)), false, expected_available_field_types, - expected_login_signature, true)); + expected_login_signature, true, nullptr)); } } else { EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, _, _, _, _)) + StartUploadRequest(_, _, _, _, _, _)) .Times(0); } if (times_used == 0) { // First login vote. - EXPECT_CALL( - *client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(SignatureIsSameAs(form_to_save), _, _, _, _)); + EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), + StartUploadRequest(SignatureIsSameAs(form_to_save), _, _, _, + _, nullptr)); } form_manager.ProvisionallySave(form_to_save); form_manager.Save(); @@ -576,7 +577,7 @@ // An unrelated vote that the credentials were used for the first time. EXPECT_CALL( *client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(SignatureIsSameAs(submitted_form), _, _, _, _)); + StartUploadRequest(SignatureIsSameAs(submitted_form), _, _, _, _, _)); } EXPECT_CALL( *client()->mock_driver()->mock_autofill_download_manager(), @@ -585,7 +586,7 @@ UploadedAutofillTypesAre(expected_types), HasGenerationVote(false), HasPasswordAttributesVote(false)), false, expected_available_field_types, expected_login_signature, - true)); + true, nullptr)); switch (field_type) { case autofill::NEW_PASSWORD: @@ -702,13 +703,13 @@ expected_generation_types; expected_generation_types[generation_element] = expected_generation_type; - EXPECT_CALL( - *client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest( - AllOf(SignatureIsSameAs(submitted_form), - UploadedGenerationTypesAre(expected_generation_types, + EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), + StartUploadRequest(AllOf(SignatureIsSameAs(submitted_form), + UploadedGenerationTypesAre( + expected_generation_types, generated_password_changed)), - false, expected_available_field_types, std::string(), true)); + false, expected_available_field_types, + std::string(), true, nullptr)); base::HistogramTester histogram_tester; form_manager.ProvisionallySave(submitted_form); @@ -811,13 +812,13 @@ expected_generation_types; expected_generation_types[generation_element] = expected_generation_type; - EXPECT_CALL( - *client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest( - AllOf(SignatureIsSameAs(submitted_form), - UploadedGenerationTypesAre(expected_generation_types, + EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), + StartUploadRequest(AllOf(SignatureIsSameAs(submitted_form), + UploadedGenerationTypesAre( + expected_generation_types, generated_password_changed)), - false, expected_available_field_types, std::string(), true)); + false, expected_available_field_types, + std::string(), true, nullptr)); form_manager->ProvisionallySave(submitted_form); switch (interaction) { case SAVE: @@ -926,7 +927,7 @@ form_manager.Init(nullptr); EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, _, _, _, _)) + StartUploadRequest(_, _, _, _, _, _)) .Times(::testing::AnyNumber()); PasswordForm http_stored_form = *saved_match(); @@ -1191,9 +1192,9 @@ autofill::ServerFieldTypeSet expected_available_field_types; expected_available_field_types.insert(autofill::ACCOUNT_CREATION_PASSWORD); expected_available_field_types.insert(autofill::USERNAME); - EXPECT_CALL( - *client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, false, expected_available_field_types, _, true)); + EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), + StartUploadRequest(_, false, expected_available_field_types, _, + true, nullptr)); EXPECT_CALL(MockFormSaver::Get(form_manager()), Save(_, _)) .WillOnce(SaveArg<0>(&actual_saved_form)); form_manager()->Save(); @@ -1430,7 +1431,7 @@ EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _, nullptr)) .WillOnce(SaveArg<0>(&saved_result)); EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, false, _, _, true)); + StartUploadRequest(_, false, _, _, true, nullptr)); form_manager()->Save(); // Should be only one password stored, and should not have @@ -1924,7 +1925,7 @@ .WillOnce(testing::DoAll(SaveArg<0>(&saved_result), SaveArgPointee<2>(&credentials_to_update))); EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, false, _, _, true)); + StartUploadRequest(_, false, _, _, true, nullptr)); form_manager()->Save(); @@ -1958,9 +1959,9 @@ autofill::ServerFieldTypeSet expected_available_field_types; expected_available_field_types.insert(autofill::PASSWORD); - EXPECT_CALL( - *client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, false, expected_available_field_types, _, true)); + EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), + StartUploadRequest(_, false, expected_available_field_types, _, + true, nullptr)); form_manager.ProvisionallySave(form_to_save); form_manager.Save(); } @@ -1978,8 +1979,9 @@ autofill::ServerFieldTypeSet expected_available_field_types; expected_available_field_types.insert(autofill::USERNAME); expected_available_field_types.insert(autofill::PASSWORD); - EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, _, expected_available_field_types, _, true)) + EXPECT_CALL( + *client()->mock_driver()->mock_autofill_download_manager(), + StartUploadRequest(_, _, expected_available_field_types, _, true, _)) .Times(0); blacklist_form_manager.PermanentlyBlacklist(); } @@ -2342,7 +2344,7 @@ AllOf(SignatureIsSameAs(observed), UploadedAutofillTypesAre(expected_types), HasGenerationVote(false), VoteTypesAre(expected_vote_types)), - _, Contains(autofill::USERNAME), _, _)); + _, Contains(autofill::USERNAME), _, _, nullptr)); form_manager.Save(); // Check what is saved. @@ -2418,7 +2420,7 @@ AllOf(SignatureIsSameAs(expected_pending), UploadedAutofillTypesAre(expected_types), HasGenerationVote(false), VoteTypesAre(expected_vote_types)), - _, Contains(autofill::USERNAME), _, _)); + _, Contains(autofill::USERNAME), _, _, nullptr)); form_manager()->Save(); } } @@ -2477,9 +2479,9 @@ Save(_, ElementsAre(Pair(saved_match()->username_value, Pointee(*saved_match()))))) .WillOnce(SaveArg<0>(&actual_saved_form)); - EXPECT_CALL( - *client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, _, Not(Contains(autofill::USERNAME)), _, _)); + EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), + StartUploadRequest(_, _, Not(Contains(autofill::USERNAME)), _, + _, nullptr)); form_manager.Save(); // Can't verify |date_created |, so ignore it in form comparison. @@ -2519,9 +2521,9 @@ PasswordForm saved_result; EXPECT_CALL(MockFormSaver::Get(&form_manager), Save(_, IsEmpty())) .WillOnce(SaveArg<0>(&saved_result)); - EXPECT_CALL( - *client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, _, Not(Contains(autofill::USERNAME)), _, _)); + EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), + StartUploadRequest(_, _, Not(Contains(autofill::USERNAME)), _, _, + nullptr)); form_manager.Save(); EXPECT_TRUE(saved_result.username_value.empty()); @@ -2557,8 +2559,9 @@ Pointee(*psl_saved_match()))))) .WillOnce(SaveArg<0>(&saved_result)); // As the credential is re-used successfully, expect a username vote. - EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, _, Contains(autofill::USERNAME), _, _)); + EXPECT_CALL( + *client()->mock_driver()->mock_autofill_download_manager(), + StartUploadRequest(_, _, Contains(autofill::USERNAME), _, _, nullptr)); form_manager()->Save(); // Check what is saved. @@ -2648,7 +2651,7 @@ UploadedAutofillTypesAre(expected_types), HasGenerationVote(false), PasswordsWereRevealed(has_passwords_revealed)), - _, Contains(autofill::PASSWORD), _, _)); + _, Contains(autofill::PASSWORD), _, _, nullptr)); form_manager.Save(); EXPECT_EQ(ASCIIToUTF16("p4ssword"), saved_result.password_value); @@ -2864,7 +2867,7 @@ .WillOnce(testing::DoAll(SaveArg<0>(&new_credentials), SaveArgPointee<2>(&credentials_to_update))); EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, false, _, _, true)); + StartUploadRequest(_, false, _, _, true, nullptr)); form_manager.Save(); @@ -2916,7 +2919,7 @@ Update(_, _, Pointee(IsEmpty()), nullptr)) .WillOnce(testing::SaveArg<0>(&new_credentials)); EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, false, _, _, true)); + StartUploadRequest(_, false, _, _, true, nullptr)); form_manager.Save(); @@ -2957,7 +2960,7 @@ Update(_, _, Pointee(IsEmpty()), nullptr)) .WillOnce(testing::SaveArg<0>(&new_credentials)); EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, false, _, _, true)); + StartUploadRequest(_, false, _, _, true, nullptr)); form_manager.Save(); @@ -2993,8 +2996,9 @@ EXPECT_CALL(MockFormSaver::Get(&form_manager), Save(_, _)) .WillOnce(testing::SaveArg<0>(&new_credentials)); // As the username is re-used, expect a username vote. - EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, _, Contains(autofill::USERNAME), _, _)); + EXPECT_CALL( + *client()->mock_driver()->mock_autofill_download_manager(), + StartUploadRequest(_, _, Contains(autofill::USERNAME), _, _, nullptr)); form_manager.Save(); EXPECT_EQ(credentials.password_value, new_credentials.password_value); @@ -3168,16 +3172,16 @@ autofill::FormStructure(saved_match()->form_data).FormSignatureAsStr(); // First login vote. - EXPECT_CALL( - *client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(SignatureIsSameAs(submitted_form), _, _, _, _)); + EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), + StartUploadRequest(SignatureIsSameAs(submitted_form), _, _, _, _, + nullptr)); // Password change vote. EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), StartUploadRequest(AllOf(UploadedAutofillTypesAre(expected_types), HasGenerationVote(false), SignatureIsSameAs(*observed_form())), false, expected_available_field_types, - expected_login_signature, true)); + expected_login_signature, true, nullptr)); EXPECT_CALL(MockFormSaver::Get(&form_manager), Update(_, _, _, _)); form_manager.Update(*saved_match()); @@ -3280,7 +3284,7 @@ EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), StartUploadRequest( UploadedFieldPropertiesMasksAre(expected_field_properties), - false, _, _, true)); + false, _, _, true, nullptr)); form_manager.ProvisionallySave(submitted_form); form_manager.Save(); } @@ -3345,7 +3349,7 @@ .WillOnce(testing::DoAll(SaveArg<0>(&new_credentials), SaveArgPointee<2>(&credentials_to_update))); EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, false, _, _, true)); + StartUploadRequest(_, false, _, _, true, nullptr)); form_manager()->Save(); EXPECT_TRUE(new_credentials.skip_zero_click); @@ -3371,7 +3375,7 @@ EXPECT_FALSE(form_manager()->IsNewLogin()); EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, false, _, _, true)); + StartUploadRequest(_, false, _, _, true, nullptr)); base::UserActionTester tester; EXPECT_EQ(0, tester.GetActionCount("PasswordManager_LoginFollowingAutofill")); @@ -3534,9 +3538,9 @@ InSequence s; autofill::ServerFieldTypeSet field_types; field_types.insert(autofill::PASSWORD); - EXPECT_CALL( - *client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, false, field_types, std::string(), true)); + EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), + StartUploadRequest(_, false, field_types, std::string(), true, + nullptr)); EXPECT_CALL( *client()->mock_driver()->mock_autofill_download_manager(), @@ -3545,7 +3549,7 @@ HasGenerationVote(false), VoteTypesAre(expected_vote_types)), false, expected_available_field_types, - expected_login_signature, true)); + expected_login_signature, true, nullptr)); form_manager.Save(); } } @@ -3565,7 +3569,7 @@ // Don't expect any vote uploads. EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, _, _, _, _)) + StartUploadRequest(_, _, _, _, _, _)) .Times(0); form_manager()->Save(); @@ -3610,10 +3614,10 @@ Pointee(*saved_match()))), Pointee(IsEmpty()), nullptr)); EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, _, _, _, _)); - EXPECT_CALL( - *client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, _, Not(Contains(autofill::USERNAME)), _, _)); + StartUploadRequest(_, _, _, _, _, nullptr)); + EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), + StartUploadRequest(_, _, Not(Contains(autofill::USERNAME)), _, + _, nullptr)); form_manager()->Save(); } } @@ -4249,7 +4253,7 @@ EXPECT_CALL( *client()->mock_driver()->mock_autofill_download_manager(), StartUploadRequest(SignatureIsSameAs(*test_case.stored_creds.front()), - _, _, _, _)) + _, _, _, _, _)) .Times(AtMost(1)); // First login vote EXPECT_CALL( @@ -4265,7 +4269,7 @@ _, autofill::ServerFieldTypeSet( {autofill::USERNAME, autofill::PASSWORD}), - _, true)); + _, true, nullptr)); form_manager()->Save(); @@ -4312,7 +4316,7 @@ form_manager()->ProvisionallySave(submitted_form); EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(_, _, _, _, _)) + StartUploadRequest(_, _, _, _, _, _)) .Times(0); form_manager()->Save(); @@ -4357,7 +4361,7 @@ // Unrelated vote EXPECT_CALL( *client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(SignatureIsSameAs(different_password), _, _, _, _)) + StartUploadRequest(SignatureIsSameAs(different_password), _, _, _, _, _)) .Times(AtMost(1)); // First login vote EXPECT_CALL( @@ -4370,7 +4374,8 @@ {ASCIIToUTF16("petname"), autofill::UNKNOWN_TYPE}})), UploadedFieldPropertiesMasksAre(expected_field_properties), VoteTypesAre(expected_vote_types)), - _, autofill::ServerFieldTypeSet({autofill::USERNAME}), _, true)); + _, autofill::ServerFieldTypeSet({autofill::USERNAME}), _, true, + nullptr)); form_manager()->Save(); } @@ -4419,7 +4424,8 @@ // Unrelated vote. EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _)) + StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _, + nullptr)) .Times(1); // First login vote. EXPECT_CALL( @@ -4435,7 +4441,7 @@ _, autofill::ServerFieldTypeSet( {autofill::USERNAME, autofill::PASSWORD}), - _, true)); + _, true, nullptr)); form_manager()->Save(); } @@ -4479,7 +4485,8 @@ // Unrelated vote. EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _)) + StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _, + nullptr)) .Times(1); // First login vote. EXPECT_CALL( @@ -4495,7 +4502,7 @@ _, autofill::ServerFieldTypeSet( {autofill::USERNAME, autofill::PASSWORD}), - _, true)); + _, true, nullptr)); form_manager()->Save(); } @@ -4546,7 +4553,8 @@ // Unrelated vote. EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _)) + StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _, + nullptr)) .Times(1); // First login vote. EXPECT_CALL( @@ -4556,7 +4564,8 @@ UploadedAutofillTypesAre(expected_votes), UploadedFieldPropertiesMasksAre(expected_field_properties), VoteTypesAre(expected_vote_types)), - _, autofill::ServerFieldTypeSet({autofill::PASSWORD}), _, true)); + _, autofill::ServerFieldTypeSet({autofill::PASSWORD}), _, true, + nullptr)); form_manager()->Save(); } @@ -4657,7 +4666,8 @@ // Unrelated vote. EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(), - StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _)) + StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _, + nullptr)) .Times(1); // First login vote. EXPECT_CALL( @@ -4670,7 +4680,7 @@ _, autofill::ServerFieldTypeSet( {autofill::USERNAME, autofill::PASSWORD}), - _, true)); + _, true, nullptr)); form_manager()->Save(); } @@ -4693,7 +4703,7 @@ EXPECT_CALL( *client()->mock_driver()->mock_autofill_download_manager(), StartUploadRequest(HasPasswordAttributesVote(true /* is_vote_expected */), - _, _, _, _)); + _, _, _, _, nullptr)); form_manager.Save(); }
diff --git a/components/password_manager/core/browser/votes_uploader.cc b/components/password_manager/core/browser/votes_uploader.cc index a06414a..b465722 100644 --- a/components/password_manager/core/browser/votes_uploader.cc +++ b/components/password_manager/core/browser/votes_uploader.cc
@@ -306,7 +306,8 @@ bool success = autofill_manager->download_manager()->StartUploadRequest( form_structure, false /* was_autofilled */, available_field_types, - login_form_signature, true /* observed_submission */); + login_form_signature, true /* observed_submission */, + nullptr /* prefs */); UMA_HISTOGRAM_BOOLEAN("PasswordGeneration.UploadStarted", success); return success; @@ -354,7 +355,7 @@ autofill_manager->download_manager()->StartUploadRequest( form_structure, false /* was_autofilled */, available_field_types, - std::string(), true /* observed_submission */); + std::string(), true /* observed_submission */, nullptr /* prefs */); } void VotesUploader::AddGeneratedVote(FormStructure* form_structure) {
diff --git a/components/password_manager/core/browser/votes_uploader_unittest.cc b/components/password_manager/core/browser/votes_uploader_unittest.cc index ccad826d..ac451aa3 100644 --- a/components/password_manager/core/browser/votes_uploader_unittest.cc +++ b/components/password_manager/core/browser/votes_uploader_unittest.cc
@@ -51,12 +51,13 @@ autofill::AutofillDownloadManager::Observer* observer) : AutofillDownloadManager(driver, observer) {} - MOCK_METHOD5(StartUploadRequest, + MOCK_METHOD6(StartUploadRequest, bool(const FormStructure&, bool, const ServerFieldTypeSet&, const std::string&, - bool)); + bool, + PrefService*)); private: DISALLOW_COPY_AND_ASSIGN(MockAutofillDownloadManager); @@ -105,7 +106,8 @@ EXPECT_CALL(client_, GetAutofillManagerForMainFrame()) .WillRepeatedly(Return(&mock_autofill_manager_)); - ON_CALL(*mock_autofill_download_manager_, StartUploadRequest(_, _, _, _, _)) + ON_CALL(*mock_autofill_download_manager_, + StartUploadRequest(_, _, _, _, _, _)) .WillByDefault(Return(true)); // Create |fields| in |form_to_upload_| and |submitted_form_|. Only |name| @@ -156,12 +158,13 @@ PasswordForm::SubmissionIndicatorEvent expected_submission_event = PasswordForm::SubmissionIndicatorEvent::HTML_FORM_SUBMISSION; - EXPECT_CALL(*mock_autofill_download_manager_, - StartUploadRequest( - AllOf(SignatureIsSameAs(form_to_upload_), - UploadedAutofillTypesAre(expected_types), - SubmissionEventIsSameAs(expected_submission_event)), - false, expected_field_types, login_form_signature_, true)); + EXPECT_CALL( + *mock_autofill_download_manager_, + StartUploadRequest( + AllOf(SignatureIsSameAs(form_to_upload_), + UploadedAutofillTypesAre(expected_types), + SubmissionEventIsSameAs(expected_submission_event)), + false, expected_field_types, login_form_signature_, true, nullptr)); EXPECT_TRUE(votes_uploader.UploadPasswordVote( form_to_upload_, submitted_form_, NEW_PASSWORD, login_form_signature_)); @@ -184,7 +187,8 @@ EXPECT_CALL(*mock_autofill_download_manager_, StartUploadRequest( SubmissionEventIsSameAs(expected_submission_event), false, - expected_field_types, login_form_signature_, true)); + expected_field_types, login_form_signature_, true, + /* pref_service= */ nullptr)); EXPECT_TRUE(votes_uploader.UploadPasswordVote( form_to_upload_, submitted_form_, PASSWORD, login_form_signature_));
diff --git a/components/resources/components_resources.grd b/components/resources/components_resources.grd index b1359f5..4623e36e 100644 --- a/components/resources/components_resources.grd +++ b/components/resources/components_resources.grd
@@ -16,11 +16,6 @@ <part file="net_log_resources.grdp" /> <part file="neterror_resources.grdp" /> <part file="ntp_tiles_resources.grdp" /> - <if expr="is_win"> - <part file="nux_email.grdp" /> - <part file="nux_google_apps.grdp" /> - <part file="nux_set_as_default.grdp" /> - </if> <part file="offline_pages_resources.grdp" /> <part file="password_manager_internals_resources.grdp" /> <part file="printing_resources.grdp" />
diff --git a/components/resources/nux_email.grdp b/components/resources/nux_email.grdp deleted file mode 100644 index 437612f..0000000 --- a/components/resources/nux_email.grdp +++ /dev/null
@@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<grit-part> - <include name="IDR_NUX_EMAIL_AOL_1X" file="../nux/email/resources/aol_1x.png" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_AOL_2X" file="../nux/email/resources/aol_2x.png" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_CHOOSER_HTML" file="../nux/email/resources/email_chooser.html" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_CHOOSER_JS" file="../nux/email/resources/email_chooser.js" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_GMAIL_1X" file="../nux/email/resources/gmail_1x.png" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_GMAIL_2X" file="../nux/email/resources/gmail_2x.png" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_HTML" file="../nux/email/resources/nux_email.html" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_ICLOUD_1X" file="../nux/email/resources/icloud_1x.png" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_ICLOUD_2X" file="../nux/email/resources/icloud_2x.png" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_JS" file="../nux/email/resources/nux_email.js" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_OUTLOOK_1X" file="../nux/email/resources/outlook_1x.png" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_OUTLOOK_2X" file="../nux/email/resources/outlook_2x.png" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_PROXY_HTML" file="../nux/email/resources/nux_email_proxy.html" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_PROXY_JS" file="../nux/email/resources/nux_email_proxy.js" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_YAHOO_1X" file="../nux/email/resources/yahoo_1x.png" type="BINDATA" /> - <include name="IDR_NUX_EMAIL_YAHOO_2X" file="../nux/email/resources/yahoo_2x.png" type="BINDATA" /> -</grit-part>
diff --git a/components/resources/nux_google_apps.grdp b/components/resources/nux_google_apps.grdp deleted file mode 100644 index 5e74f85..0000000 --- a/components/resources/nux_google_apps.grdp +++ /dev/null
@@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<grit-part> - <include name="IDR_NUX_GOOGLE_APPS_HTML" file="../nux/google_apps/resources/nux_google_apps.html" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_JS" file="../nux/google_apps/resources/nux_google_apps.js" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_PROXY_HTML" file="../nux/google_apps/resources/nux_google_apps_proxy.html" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_PROXY_JS" file="../nux/google_apps/resources/nux_google_apps_proxy.js" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_CHOOSER_HTML" file="../nux/google_apps/resources/apps_chooser.html" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_CHOOSER_JS" file="../nux/google_apps/resources/apps_chooser.js" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_CHROME_STORE_1X" file="../nux/google_apps/resources/chrome_store_24dp_1x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_CHROME_STORE_2X" file="../nux/google_apps/resources/chrome_store_24dp_2x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_GMAIL_1X" file="../nux/google_apps/resources/gmail_24dp_1x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_GMAIL_2X" file="../nux/google_apps/resources/gmail_24dp_2x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_MAPS_1X" file="../nux/google_apps/resources/maps_24dp_1x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_MAPS_2X" file="../nux/google_apps/resources/maps_24dp_2x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_NEWS_1X" file="../nux/google_apps/resources/news_24dp_1x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_NEWS_2X" file="../nux/google_apps/resources/news_24dp_2x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_TRANSLATE_1X" file="../nux/google_apps/resources/translate_24dp_1x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_TRANSLATE_2X" file="../nux/google_apps/resources/translate_24dp_2x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_YOUTUBE_1X" file="../nux/google_apps/resources/youtube_24dp_1x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_YOUTUBE_2X" file="../nux/google_apps/resources/youtube_24dp_2x.png" type="BINDATA" /> -</grit-part>
diff --git a/components/resources/nux_set_as_default.grdp b/components/resources/nux_set_as_default.grdp deleted file mode 100644 index e37a8fd..0000000 --- a/components/resources/nux_set_as_default.grdp +++ /dev/null
@@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<grit-part> - <include name="IDR_NUX_SET_AS_DEFAULT_HTML" file="../nux/set_as_default/resources/nux_set_as_default.html" type="BINDATA" /> - <include name="IDR_NUX_SET_AS_DEFAULT_JS" file="../nux/set_as_default/resources/nux_set_as_default.js" type="BINDATA" /> - <include name="IDR_NUX_SET_AS_DEFAULT_PROXY_HTML" file="../nux/set_as_default/resources/nux_set_as_default_proxy.html" type="BINDATA" /> - <include name="IDR_NUX_SET_AS_DEFAULT_PROXY_JS" file="../nux/set_as_default/resources/nux_set_as_default_proxy.js" type="BINDATA" /> -</grit-part>
diff --git a/components/safe_browsing/password_protection/password_protection_service.cc b/components/safe_browsing/password_protection/password_protection_service.cc index d899d51..b6b2985f 100644 --- a/components/safe_browsing/password_protection/password_protection_service.cc +++ b/components/safe_browsing/password_protection/password_protection_service.cc
@@ -676,7 +676,7 @@ int* out_verdict_received_time, LoginReputationClientResponse* out_verdict) { std::string serialized_verdict_proto; - if (!verdict_entry || !out_verdict) + if (!verdict_entry || !verdict_entry->is_dict() || !out_verdict) return false; base::Value* cache_creation_time_value = verdict_entry->FindKey(kCacheCreationTime);
diff --git a/components/services/heap_profiling/public/cpp/allocator_shim.cc b/components/services/heap_profiling/public/cpp/allocator_shim.cc index ef76601..7c36719 100644 --- a/components/services/heap_profiling/public/cpp/allocator_shim.cc +++ b/components/services/heap_profiling/public/cpp/allocator_shim.cc
@@ -140,8 +140,7 @@ class ScopedAllowAlloc { public: ScopedAllowAlloc() - : allowed_(LIKELY(CanEnterAllocatorShim()) && - LIKELY(!base::ThreadLocalStorage::HasBeenDestroyed())) { + : allowed_(LIKELY(CanEnterAllocatorShim()) && !HasTLSBeenDestroyed()) { if (allowed_) SetEnteringAllocatorShim(true); } @@ -151,6 +150,10 @@ } explicit operator bool() const { return allowed_; } + static inline bool HasTLSBeenDestroyed() { + return UNLIKELY(base::ThreadLocalStorage::HasBeenDestroyed()); + } + private: const bool allowed_; }; @@ -735,7 +738,8 @@ break; case mojom::StackMode::NATIVE_WITH_THREAD_NAMES: case mojom::StackMode::NATIVE_WITHOUT_THREAD_NAMES: - AllocationContextTracker::SetCaptureMode(CaptureMode::DISABLED); + // This would track task contexts only. + AllocationContextTracker::SetCaptureMode(CaptureMode::NATIVE_STACK); break; } @@ -778,6 +782,9 @@ void SerializeFramesFromAllocationContext(FrameSerializer* serializer, const char** context) { + // Allocation context is tracked in TLS. Return nothing if TLS was destroyed. + if (ScopedAllowAlloc::HasTLSBeenDestroyed()) + return; auto* tracker = AllocationContextTracker::GetInstanceForCurrentThread(); if (!tracker) return; @@ -791,7 +798,8 @@ *context = allocation_context.type_name; } -void SerializeFramesFromBacktrace(FrameSerializer* serializer) { +void SerializeFramesFromBacktrace(FrameSerializer* serializer, + const char** context) { // Skip 3 top frames related to the profiler itself, e.g.: // base::debug::StackTrace::StackTrace // heap_profiling::RecordAndSendAlloc @@ -824,6 +832,13 @@ const char* thread_name = GetOrSetThreadName(); serializer->AddCString(thread_name); } + + if (!*context && !ScopedAllowAlloc::HasTLSBeenDestroyed()) { + const auto* tracker = + AllocationContextTracker::GetInstanceForCurrentThread(); + if (tracker) + *context = tracker->TaskContext(); + } } void AllocatorShimLogAlloc(AllocatorType type, @@ -895,7 +910,7 @@ capture_mode == CaptureMode::MIXED_STACK) { SerializeFramesFromAllocationContext(&serializer, &context); } else { - SerializeFramesFromBacktrace(&serializer); + SerializeFramesFromBacktrace(&serializer, &context); } size_t context_len = context ? strnlen(context, kMaxContextLen) : 0;
diff --git a/components/services/heap_profiling/public/cpp/allocator_shim.h b/components/services/heap_profiling/public/cpp/allocator_shim.h index f4931e4..c7582e4 100644 --- a/components/services/heap_profiling/public/cpp/allocator_shim.h +++ b/components/services/heap_profiling/public/cpp/allocator_shim.h
@@ -60,13 +60,15 @@ mojom::ProfilingParamsPtr params); // Creates allocation info record, populates it with current call stack, -// thread name, allocator type and sends out to the client. +// thread name, allocator type and sends out to the client. Safe to call this +// method after TLS is destroyed. void RecordAndSendAlloc(AllocatorType type, void* address, size_t sz, const char* context); -// Creates the record for free operation and sends it out to the client. +// Creates the record for free operation and sends it out to the client. Safe +// to call this method after TLS is destroyed. void RecordAndSendFree(void* address); // Exists for testing only.
diff --git a/components/signin/core/browser/fake_signin_manager.cc b/components/signin/core/browser/fake_signin_manager.cc index 916756a..022c2a5 100644 --- a/components/signin/core/browser/fake_signin_manager.cc +++ b/components/signin/core/browser/fake_signin_manager.cc
@@ -103,7 +103,7 @@ } void FakeSigninManager::ForceSignOut() { - ProhibitSignout(false); + // SigninClients should always allow sign-out for SIGNOUT_TEST. SignOut(signin_metrics::SIGNOUT_TEST, signin_metrics::SignoutDelete::IGNORE_METRIC); } @@ -113,10 +113,11 @@ observer.GoogleSigninFailed(error); } -void FakeSigninManager::DoSignOut( +void FakeSigninManager::OnSignoutDecisionReached( signin_metrics::ProfileSignout signout_source_metric, signin_metrics::SignoutDelete signout_delete_metric, - RemoveAccountsOption remove_option) { + RemoveAccountsOption remove_option, + SigninClient::SignoutDecision signout_decision) { if (!IsAuthenticated()) { if (AuthInProgress()) { // If the user is in the process of signing in, then treat a call to @@ -133,8 +134,11 @@ return; } - if (IsSignoutProhibited()) + // TODO(crbug.com/887756): Consider moving this higher up, or document why + // the above blocks are exempt from the |signout_decision| early return. + if (signout_decision == SigninClient::SignoutDecision::DISALLOW_SIGNOUT) return; + set_auth_in_progress(std::string()); set_password(std::string()); AccountInfo account_info = GetAuthenticatedAccountInfo();
diff --git a/components/signin/core/browser/fake_signin_manager.h b/components/signin/core/browser/fake_signin_manager.h index 41dc74c..a7314d2 100644 --- a/components/signin/core/browser/fake_signin_manager.h +++ b/components/signin/core/browser/fake_signin_manager.h
@@ -76,9 +76,11 @@ void CompletePendingSignin() override; protected: - void DoSignOut(signin_metrics::ProfileSignout signout_source_metric, - signin_metrics::SignoutDelete signout_delete_metric, - RemoveAccountsOption remove_option) override; + void OnSignoutDecisionReached( + signin_metrics::ProfileSignout signout_source_metric, + signin_metrics::SignoutDelete signout_delete_metric, + RemoveAccountsOption remove_option, + SigninClient::SignoutDecision signout_decision) override; // Username specified in StartSignInWithRefreshToken() call. std::string username_;
diff --git a/components/signin/core/browser/signin_client.cc b/components/signin/core/browser/signin_client.cc index a17afa9..b6741ad 100644 --- a/components/signin/core/browser/signin_client.cc +++ b/components/signin/core/browser/signin_client.cc
@@ -5,9 +5,10 @@ #include "components/signin/core/browser/signin_client.h" void SigninClient::PreSignOut( - const base::Callback<void()>& sign_out, + base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached, signin_metrics::ProfileSignout signout_source_metric) { - sign_out.Run(); + // Allow sign out to continue. + std::move(on_signout_decision_reached).Run(SignoutDecision::ALLOW_SIGNOUT); } void SigninClient::PreGaiaLogout(base::OnceClosure callback) {
diff --git a/components/signin/core/browser/signin_client.h b/components/signin/core/browser/signin_client.h index dec60e6..7ded61b 100644 --- a/components/signin/core/browser/signin_client.h +++ b/components/signin/core/browser/signin_client.h
@@ -36,12 +36,10 @@ // embedder. class SigninClient : public KeyedService { public: - ~SigninClient() override = default; + // Argument to PreSignOut() callback, indicating client decision. + enum class SignoutDecision { ALLOW_SIGNOUT, DISALLOW_SIGNOUT }; - // Called before Google signout started, call |sign_out| to start the sign out - // process. - virtual void PreSignOut(const base::Callback<void()>& sign_out, - signin_metrics::ProfileSignout signout_source_metric); + ~SigninClient() override = default; // Perform Chrome-specific sign out. This happens when user signs out. virtual void OnSignedOut() = 0; @@ -77,6 +75,14 @@ const std::string& username, const std::string& password) {} + // Called before Google sign-out started. Implementers must run the + // |on_signout_decision_reached|, passing a SignoutDecision to allow/disallow + // sign-out to continue. When to disallow sign-out is implementation specific. + // Sign-out is always allowed by default. + virtual void PreSignOut( + base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached, + signin_metrics::ProfileSignout signout_source_metric); + // Called before calling the GAIA logout endpoint. // For iOS, cookies should be cleaned up. virtual void PreGaiaLogout(base::OnceClosure callback);
diff --git a/components/signin/core/browser/signin_manager.cc b/components/signin/core/browser/signin_manager.cc index c27e9797..945a0d7 100644 --- a/components/signin/core/browser/signin_manager.cc +++ b/components/signin/core/browser/signin_manager.cc
@@ -15,7 +15,6 @@ #include "components/prefs/pref_service.h" #include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/gaia_cookie_manager_service.h" -#include "components/signin/core/browser/signin_client.h" #include "components/signin/core/browser/signin_internals_util.h" #include "components/signin/core/browser/signin_metrics.h" #include "components/signin/core/browser/signin_pref_names.h" @@ -37,7 +36,6 @@ : SigninManagerBase(client, account_tracker_service, signin_error_controller), - prohibit_signout_(false), type_(SIGNIN_TYPE_NONE), client_(client), token_service_(token_service), @@ -185,15 +183,17 @@ signin_metrics::SignoutDelete signout_delete_metric, RemoveAccountsOption remove_option) { client_->PreSignOut( - base::Bind(&SigninManager::DoSignOut, base::Unretained(this), - signout_source_metric, signout_delete_metric, remove_option), + base::BindOnce(&SigninManager::OnSignoutDecisionReached, + base::Unretained(this), signout_source_metric, + signout_delete_metric, remove_option), signout_source_metric); } -void SigninManager::DoSignOut( +void SigninManager::OnSignoutDecisionReached( signin_metrics::ProfileSignout signout_source_metric, signin_metrics::SignoutDelete signout_delete_metric, - RemoveAccountsOption remove_option) { + RemoveAccountsOption remove_option, + SigninClient::SignoutDecision signout_decision) { DCHECK(IsInitialized()); signin_metrics::LogSignout(signout_source_metric, signout_delete_metric); @@ -213,8 +213,10 @@ return; } - if (IsSignoutProhibited()) { - DVLOG(1) << "Ignoring attempt to sign out while signout is prohibited"; + // TODO(crbug.com/887756): Consider moving this higher up, or document why + // the above blocks are exempt from the |signout_decision| early return. + if (signout_decision == SigninClient::SignoutDecision::DISALLOW_SIGNOUT) { + DVLOG(1) << "Ignoring attempt to sign out while signout disallowed"; return; } @@ -504,9 +506,3 @@ token_service_->RemoveObserver(this); } } - -void SigninManager::ProhibitSignout(bool prohibit_signout) { - prohibit_signout_ = prohibit_signout; -} - -bool SigninManager::IsSignoutProhibited() const { return prohibit_signout_; }
diff --git a/components/signin/core/browser/signin_manager.h b/components/signin/core/browser/signin_manager.h index 25f7920..0c9559a 100644 --- a/components/signin/core/browser/signin_manager.h +++ b/components/signin/core/browser/signin_manager.h
@@ -38,6 +38,7 @@ #include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/profile_management_switches.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" +#include "components/signin/core/browser/signin_client.h" #include "components/signin/core/browser/signin_internals_util.h" #include "components/signin/core/browser/signin_manager_base.h" #include "components/signin/core/browser/signin_metrics.h" @@ -185,22 +186,13 @@ // a new account). static void DisableOneClickSignIn(PrefService* prefs); - // Tells the SigninManager whether to prohibit signout for this profile. - // If |prohibit_signout| is true, then signout will be prohibited. - void ProhibitSignout(bool prohibit_signout); - - // If true, signout is prohibited for this profile (calls to SignOut() are - // ignored). - bool IsSignoutProhibited() const; - protected: - // Flag saying whether signing out is allowed. - bool prohibit_signout_; - // The sign out process which is started by SigninClient::PreSignOut() - virtual void DoSignOut(signin_metrics::ProfileSignout signout_source_metric, - signin_metrics::SignoutDelete signout_delete_metric, - RemoveAccountsOption remove_option); + virtual void OnSignoutDecisionReached( + signin_metrics::ProfileSignout signout_source_metric, + signin_metrics::SignoutDelete signout_delete_metric, + RemoveAccountsOption remove_option, + SigninClient::SignoutDecision signout_decision); private: enum SigninType {
diff --git a/components/signin/core/browser/signin_manager_unittest.cc b/components/signin/core/browser/signin_manager_unittest.cc index c47fefa..2a2b0b4d 100644 --- a/components/signin/core/browser/signin_manager_unittest.cc +++ b/components/signin/core/browser/signin_manager_unittest.cc
@@ -335,11 +335,11 @@ EXPECT_TRUE(manager_->GetAuthenticatedAccountId().empty()); manager_->SetAuthenticatedAccountInfo("gaia_id", "user@gmail.com"); - manager_->ProhibitSignout(true); + signin_client()->set_is_signout_allowed(false); manager_->SignOut(signin_metrics::SIGNOUT_TEST, signin_metrics::SignoutDelete::IGNORE_METRIC); EXPECT_TRUE(manager_->IsAuthenticated()); - manager_->ProhibitSignout(false); + signin_client()->set_is_signout_allowed(true); manager_->SignOut(signin_metrics::SIGNOUT_TEST, signin_metrics::SignoutDelete::IGNORE_METRIC); EXPECT_FALSE(manager_->IsAuthenticated());
diff --git a/components/signin/core/browser/signin_metrics.h b/components/signin/core/browser/signin_metrics.h index d1649df..a0ca17ba 100644 --- a/components/signin/core/browser/signin_metrics.h +++ b/components/signin/core/browser/signin_metrics.h
@@ -69,7 +69,7 @@ HISTOGRAM_REJECTED, // The user pressed the X button to dismiss the infobar this time. HISTOGRAM_DISMISSED, - // The user completely ignored the infoar. Either they navigated away, or + // The user completely ignored the infobar. Either they navigated away, or // they used the page as is. HISTOGRAM_IGNORED, // The user clicked on the learn more link in the infobar.
diff --git a/components/signin/core/browser/test_signin_client.cc b/components/signin/core/browser/test_signin_client.cc index b52e930..3a0cb77 100644 --- a/components/signin/core/browser/test_signin_client.cc +++ b/components/signin/core/browser/test_signin_client.cc
@@ -49,7 +49,8 @@ &test_url_loader_factory_)), pref_service_(pref_service), are_signin_cookies_allowed_(true), - network_calls_delayed_(false) {} + network_calls_delayed_(false), + is_signout_allowed_(true) {} TestSigninClient::~TestSigninClient() {} @@ -75,6 +76,14 @@ signed_in_password_ = password; } +void TestSigninClient::PreSignOut( + base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached, + signin_metrics::ProfileSignout signout_source_metric) { + std::move(on_signout_decision_reached) + .Run(is_signout_allowed_ ? SignoutDecision::ALLOW_SIGNOUT + : SignoutDecision::DISALLOW_SIGNOUT); +} + scoped_refptr<network::SharedURLLoaderFactory> TestSigninClient::GetURLLoaderFactory() { return shared_factory_;
diff --git a/components/signin/core/browser/test_signin_client.h b/components/signin/core/browser/test_signin_client.h index 5b7ba67c..077588b 100644 --- a/components/signin/core/browser/test_signin_client.h +++ b/components/signin/core/browser/test_signin_client.h
@@ -46,6 +46,12 @@ const std::string& username, const std::string& password) override; + // Allow or disallow continuation of sign-out depending on value of + // |is_signout_allowed_|; + void PreSignOut( + base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached, + signin_metrics::ProfileSignout signout_source_metric) override; + std::string get_signed_in_password() { return signed_in_password_; } // Returns the empty string. @@ -65,6 +71,8 @@ are_signin_cookies_allowed_ = value; } + void set_is_signout_allowed(bool value) { is_signout_allowed_ = value; } + // When |value| is true, network calls posted through DelayNetworkCall() are // delayed indefinitely. // When |value| is false, all pending calls are unblocked, and new calls are @@ -95,6 +103,7 @@ std::unique_ptr<network::mojom::CookieManager> cookie_manager_; bool are_signin_cookies_allowed_; bool network_calls_delayed_; + bool is_signout_allowed_; std::vector<base::OnceClosure> delayed_network_calls_; // Pointer to be filled by PostSignedIn.
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc index 6a03ed5..4eba01d 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc +++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
@@ -29,6 +29,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/common/console_message_level.h" #include "net/base/net_errors.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" namespace subresource_filter { @@ -122,8 +123,10 @@ transferred_ad_frame || base::ContainsKey(ad_frames_, frame_host); DCHECK(!is_ad_subframe || !navigation_handle->IsInMainFrame()); - frame_host->Send(new SubresourceFilterMsg_ActivateForNextCommittedLoad( - frame_host->GetRoutingID(), filter->activation_state(), is_ad_subframe)); + mojom::SubresourceFilterAgentAssociatedPtr agent; + frame_host->GetRemoteAssociatedInterfaces()->GetInterface(&agent); + agent->ActivateForNextCommittedLoad(filter->activation_state().Clone(), + is_ad_subframe); } void ContentSubresourceFilterThrottleManager::DidFinishNavigation( @@ -196,18 +199,6 @@ statistics_->OnDidFinishLoad(); } -bool ContentSubresourceFilterThrottleManager::OnMessageReceived( - const IPC::Message& message, - content::RenderFrameHost* render_frame_host) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(ContentSubresourceFilterThrottleManager, message) - IPC_MESSAGE_HANDLER(SubresourceFilterHostMsg_DocumentLoadStatistics, - OnDocumentLoadStatistics) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - // Sets the desired page-level |activation_state| for the currently ongoing // page load, identified by its main-frame |navigation_handle|. If this method // is not called for a main-frame navigation, the default behavior is no @@ -382,12 +373,6 @@ } } -void ContentSubresourceFilterThrottleManager::OnDocumentLoadStatistics( - const DocumentLoadStatistics& statistics) { - if (statistics_) - statistics_->OnDocumentLoadStatistics(statistics); -} - void ContentSubresourceFilterThrottleManager::OnFrameIsAdSubframe( content::RenderFrameHost* render_frame_host) { DCHECK(render_frame_host); @@ -405,6 +390,12 @@ OnFrameIsAdSubframe(binding_.GetCurrentTargetFrame()); } +void ContentSubresourceFilterThrottleManager::SetDocumentLoadStatistics( + mojom::DocumentLoadStatisticsPtr statistics) { + if (statistics_) + statistics_->OnDocumentLoadStatistics(*statistics); +} + void ContentSubresourceFilterThrottleManager::MaybeActivateSubframeSpecialUrls( content::NavigationHandle* navigation_handle) { if (navigation_handle->IsInMainFrame())
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h index 3d94617..9bb8cf1 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h +++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
@@ -28,10 +28,6 @@ class RenderFrameHost; } // namespace content -namespace IPC { -class Message; -} // namespace IPC - namespace subresource_filter { class AsyncDocumentSubresourceFilter; @@ -39,7 +35,6 @@ class PageLoadStatistics; class SubresourceFilterObserverManager; class SubresourceFilterClient; -struct DocumentLoadStatistics; // The ContentSubresourceFilterThrottleManager manages NavigationThrottles in // order to calculate frame activation states and subframe navigation filtering, @@ -96,8 +91,6 @@ content::NavigationHandle* navigation_handle) override; void DidFinishLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url) override; - bool OnMessageReceived(const IPC::Message& message, - content::RenderFrameHost* render_frame_host) override; // SubresourceFilterObserver: void OnSubresourceFilterGoingAway() override; @@ -137,8 +130,6 @@ VerifiedRuleset::Handle* EnsureRulesetHandle(); void DestroyRulesetHandleIfNoLongerUsed(); - void OnDocumentLoadStatistics(const DocumentLoadStatistics& statistics); - // Registers |render_frame_host| as an ad frame. If the frame later moves to // a new process its RenderHost will be told that it's an ad. void OnFrameIsAdSubframe(content::RenderFrameHost* render_frame_host); @@ -146,6 +137,8 @@ // mojom::SubresourceFilterHost: void DidDisallowFirstSubresource() override; void FrameIsAdSubframe() override; + void SetDocumentLoadStatistics( + mojom::DocumentLoadStatisticsPtr statistics) override; // Adds the navigation's RenderFrameHost to activated_frame_hosts_ if it is a // special navigation which did not go through navigation throttles and its
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc index d994a51d..f6c8551 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc +++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
@@ -34,6 +34,7 @@ #include "content/public/test/test_utils.h" #include "net/base/net_errors.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "url/url_constants.h" namespace subresource_filter { @@ -54,6 +55,44 @@ WILL_PROCESS_RESPONSE, }; +class FakeSubresourceFilterAgent : public mojom::SubresourceFilterAgent { + public: + FakeSubresourceFilterAgent() : binding_(this) {} + ~FakeSubresourceFilterAgent() override = default; + + void OnSubresourceFilterAgentRequest( + mojo::ScopedInterfaceEndpointHandle handle) { + binding_.Bind( + mojo::AssociatedInterfaceRequest<mojom::SubresourceFilterAgent>( + std::move(handle))); + } + + // mojom::SubresourceFilterAgent: + void ActivateForNextCommittedLoad(mojom::ActivationStatePtr activation_state, + bool is_ad_subframe) override { + last_activation_ = std::move(activation_state); + is_ad_subframe_ = is_ad_subframe; + } + + // These methods reset state back to default when they are called. + bool LastAdSubframe() { + bool is_ad_subframe = is_ad_subframe_; + is_ad_subframe_ = false; + return is_ad_subframe; + } + bool LastActivated() { + bool activated = last_activation_ && last_activation_->activation_level != + mojom::ActivationLevel::kDisabled; + last_activation_.reset(); + return activated; + } + + private: + mojom::ActivationStatePtr last_activation_; + bool is_ad_subframe_ = false; + mojo::AssociatedBinding<mojom::SubresourceFilterAgent> binding_; +}; + // Simple throttle that sends page-level activation to the manager for a // specific set of URLs. class MockPageStateActivationThrottle : public content::NavigationThrottle { @@ -124,6 +163,9 @@ // content::RenderViewHostTestHarness: void SetUp() override { content::RenderViewHostTestHarness::SetUp(); + content::WebContents* web_contents = + RenderViewHostTestHarness::web_contents(); + CreateAgentForHost(web_contents->GetMainFrame()); NavigateAndCommit(GURL("https://example.first")); @@ -147,9 +189,8 @@ throttle_manager_ = std::make_unique<ContentSubresourceFilterThrottleManager>( - this, dealer_handle_.get(), - RenderViewHostTestHarness::web_contents()); - Observe(RenderViewHostTestHarness::web_contents()); + this, dealer_handle_.get(), web_contents); + Observe(web_contents); } void TearDown() override { @@ -162,21 +203,13 @@ void ExpectActivationSignalForFrame(content::RenderFrameHost* rfh, bool expect_activation, bool expect_is_ad_subframe = false) { - content::MockRenderProcessHost* render_process_host = - static_cast<content::MockRenderProcessHost*>(rfh->GetProcess()); - const IPC::Message* message = - render_process_host->sink().GetFirstMessageMatching( - SubresourceFilterMsg_ActivateForNextCommittedLoad::ID); - ASSERT_EQ(expect_activation, !!message); - if (expect_activation) { - std::tuple<mojom::ActivationState, bool> args; - SubresourceFilterMsg_ActivateForNextCommittedLoad::Read(message, &args); - mojom::ActivationLevel level = std::get<0>(args).activation_level; - EXPECT_NE(mojom::ActivationLevel::kDisabled, level); - bool is_ad_subframe = std::get<1>(args); - EXPECT_EQ(expect_is_ad_subframe, is_ad_subframe); - } - render_process_host->sink().ClearMessages(); + // In some cases we need to verify that messages were _not_ sent, in which + // case using a Wait() idiom would cause hangs. RunUntilIdle instead to + // ensure mojo calls make it to the fake agent. + base::RunLoop().RunUntilIdle(); + FakeSubresourceFilterAgent* agent = agent_map_[rfh].get(); + EXPECT_EQ(expect_activation, agent->LastActivated()); + EXPECT_EQ(expect_is_ad_subframe, agent->LastAdSubframe()); } // Helper methods: @@ -262,6 +295,14 @@ protected: // content::WebContentsObserver + void RenderFrameCreated(content::RenderFrameHost* new_host) override { + CreateAgentForHost(new_host); + } + + void FrameDeleted(content::RenderFrameHost* host) override { + agent_map_.erase(host); + } + void DidStartNavigation( content::NavigationHandle* navigation_handle) override { if (navigation_handle->IsSameDocument()) @@ -282,6 +323,16 @@ } } + void CreateAgentForHost(content::RenderFrameHost* host) { + auto new_agent = std::make_unique<FakeSubresourceFilterAgent>(); + host->GetRemoteAssociatedInterfaces()->OverrideBinderForTesting( + mojom::SubresourceFilterAgent::Name_, + base::BindRepeating( + &FakeSubresourceFilterAgent::OnSubresourceFilterAgentRequest, + base::Unretained(new_agent.get()))); + agent_map_[host] = std::move(new_agent); + } + // SubresourceFilterClient: void ShowNotification() override { ++disallowed_notification_count_; } mojom::ActivationLevel OnPageActivationComputed( @@ -303,6 +354,10 @@ std::unique_ptr<ContentSubresourceFilterThrottleManager> throttle_manager_; + std::map<content::RenderFrameHost*, + std::unique_ptr<FakeSubresourceFilterAgent>> + agent_map_; + std::unique_ptr<content::NavigationSimulator> navigation_simulator_; // Incremented on every OnFirstSubresourceLoadDisallowed call. @@ -311,7 +366,7 @@ DISALLOW_COPY_AND_ASSIGN(ContentSubresourceFilterThrottleManagerTest); }; -INSTANTIATE_TEST_CASE_P(PageActivationNotificationTiming, +INSTANTIATE_TEST_CASE_P(, ContentSubresourceFilterThrottleManagerTest, ::testing::Values(WILL_START_REQUEST, WILL_PROCESS_RESPONSE)); @@ -739,18 +794,13 @@ false /* is_ad_subframe */); // A disallowed subframe navigation should be successfully filtered. - content::RenderFrameHost* subframe = CreateSubframeWithTestNavigation( + CreateSubframeWithTestNavigation( GURL("https://www.example.com/disallowed.html"), main_rfh()); SimulateStartAndExpectResult( content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE); EXPECT_EQ(1, disallowed_notification_count()); - - // Since the IPC is not actually sent, is_ad_subframe is not really checked - // but adding it here since we do tag even if its not a dryrun scenario. - ExpectActivationSignalForFrame(subframe, false /* expect_activation */, - true /* is_ad_subframe */); } // If the RenderFrame determines that the frame is an ad, then any navigation @@ -848,7 +898,7 @@ SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED); grandchild_frame = SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED); - ExpectActivationSignalForFrame(subframe, true /* expect_activation */, + ExpectActivationSignalForFrame(grandchild_frame, true /* expect_activation */, true /* is_ad_subframe */); EXPECT_TRUE( throttle_manager()->IsFrameTaggedAsAdForTesting(grandchild_frame));
diff --git a/components/subresource_filter/content/browser/page_load_statistics.cc b/components/subresource_filter/content/browser/page_load_statistics.cc index 9f11748..efaf382b 100644 --- a/components/subresource_filter/content/browser/page_load_statistics.cc +++ b/components/subresource_filter/content/browser/page_load_statistics.cc
@@ -16,7 +16,7 @@ PageLoadStatistics::~PageLoadStatistics() {} void PageLoadStatistics::OnDocumentLoadStatistics( - const DocumentLoadStatistics& statistics) { + const mojom::DocumentLoadStatistics& statistics) { // Note: Chances of overflow are negligible. aggregated_document_statistics_.num_loads_total += statistics.num_loads_total; aggregated_document_statistics_.num_loads_evaluated +=
diff --git a/components/subresource_filter/content/browser/page_load_statistics.h b/components/subresource_filter/content/browser/page_load_statistics.h index 33a190d3..d47e6e34 100644 --- a/components/subresource_filter/content/browser/page_load_statistics.h +++ b/components/subresource_filter/content/browser/page_load_statistics.h
@@ -6,7 +6,6 @@ #define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_PAGE_LOAD_STATISTICS_H_ #include "base/macros.h" -#include "components/subresource_filter/core/common/document_load_statistics.h" #include "components/subresource_filter/mojom/subresource_filter.mojom.h" namespace subresource_filter { @@ -19,7 +18,8 @@ PageLoadStatistics(const mojom::ActivationState& state); ~PageLoadStatistics(); - void OnDocumentLoadStatistics(const DocumentLoadStatistics& statistics); + void OnDocumentLoadStatistics( + const mojom::DocumentLoadStatistics& statistics); void OnDidFinishLoad(); private: @@ -27,7 +27,7 @@ // Statistics about subresource loads, aggregated across all frames of the // current page. - DocumentLoadStatistics aggregated_document_statistics_; + mojom::DocumentLoadStatistics aggregated_document_statistics_; DISALLOW_COPY_AND_ASSIGN(PageLoadStatistics); };
diff --git a/components/subresource_filter/content/common/subresource_filter_messages.h b/components/subresource_filter/content/common/subresource_filter_messages.h index ed92407..1e3c36d 100644 --- a/components/subresource_filter/content/common/subresource_filter_messages.h +++ b/components/subresource_filter/content/common/subresource_filter_messages.h
@@ -6,36 +6,13 @@ // no-include-guard-because-multiply-included #include "base/time/time.h" -#include "components/subresource_filter/core/common/document_load_statistics.h" -#include "components/subresource_filter/mojom/subresource_filter.mojom.h" #include "content/public/common/common_param_traits_macros.h" #include "ipc/ipc_message.h" #include "ipc/ipc_message_macros.h" #include "ipc/ipc_platform_file.h" -#include "url/ipc/url_param_traits.h" #define IPC_MESSAGE_START SubresourceFilterMsgStart -IPC_ENUM_TRAITS_MAX_VALUE(subresource_filter::mojom::ActivationLevel, - subresource_filter::mojom::ActivationLevel::kMaxValue) - -IPC_STRUCT_TRAITS_BEGIN(subresource_filter::mojom::ActivationState) - IPC_STRUCT_TRAITS_MEMBER(activation_level) - IPC_STRUCT_TRAITS_MEMBER(filtering_disabled_for_document) - IPC_STRUCT_TRAITS_MEMBER(generic_blocking_rules_disabled) - IPC_STRUCT_TRAITS_MEMBER(measure_performance) - IPC_STRUCT_TRAITS_MEMBER(enable_logging) -IPC_STRUCT_TRAITS_END() - -IPC_STRUCT_TRAITS_BEGIN(subresource_filter::DocumentLoadStatistics) - IPC_STRUCT_TRAITS_MEMBER(num_loads_total) - IPC_STRUCT_TRAITS_MEMBER(num_loads_evaluated) - IPC_STRUCT_TRAITS_MEMBER(num_loads_matching_rules) - IPC_STRUCT_TRAITS_MEMBER(num_loads_disallowed) - IPC_STRUCT_TRAITS_MEMBER(evaluation_total_wall_duration) - IPC_STRUCT_TRAITS_MEMBER(evaluation_total_cpu_duration) -IPC_STRUCT_TRAITS_END() - // ---------------------------------------------------------------------------- // Messages sent from the browser to the renderer. // ---------------------------------------------------------------------------- @@ -45,34 +22,3 @@ // subsequent document loads that have subresource filtering activated. IPC_MESSAGE_CONTROL1(SubresourceFilterMsg_SetRulesetForProcess, IPC::PlatformFileForTransit /* ruleset_file */) - -// Instructs the renderer to activate subresource filtering at the specified -// |activation_state| for the document load committed next in a frame. -// -// Without browser-side navigation, the message must arrive just before the -// provisional load is committed on the renderer side. In practice, it is often -// sent after the provisional load has already started, but this is not a -// requirement. The message will have no effect if the provisional load fails. -// -// With browser-side navigation enabled, the message must arrive just before -// mojom::FrameNavigationControl::CommitNavigation. -// -// If no message arrives, the default behavior is -// mojom::ActivationLevel::kDisabled. -IPC_MESSAGE_ROUTED2( - SubresourceFilterMsg_ActivateForNextCommittedLoad, - subresource_filter::mojom::ActivationState /* activation_state */, - bool /* is_ad_subframe */) - -// ---------------------------------------------------------------------------- -// Messages sent from the renderer to the browser. -// ---------------------------------------------------------------------------- - -// This is sent to a RenderFrameHost in the browser when a document load is -// finished, just before the DidFinishLoad message, and contains statistics -// collected by the DocumentSubresourceFilter up until that point: the number of -// subresources evaluated/disallowed/etc, and total time spent on evaluating -// subresource loads in its allowLoad method. The time metrics are equal to zero -// if performance measurements were disabled for the load. -IPC_MESSAGE_ROUTED1(SubresourceFilterHostMsg_DocumentLoadStatistics, - subresource_filter::DocumentLoadStatistics /* statistics */)
diff --git a/components/subresource_filter/content/renderer/DEPS b/components/subresource_filter/content/renderer/DEPS index 717a382..f1783be 100644 --- a/components/subresource_filter/content/renderer/DEPS +++ b/components/subresource_filter/content/renderer/DEPS
@@ -2,4 +2,5 @@ "+content/public/renderer", "+third_party/blink/public/platform", "+third_party/blink/public/web", + "+mojo/public/cpp", ]
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent.cc b/components/subresource_filter/content/renderer/subresource_filter_agent.cc index 34f768d..233172a 100644 --- a/components/subresource_filter/content/renderer/subresource_filter_agent.cc +++ b/components/subresource_filter/content/renderer/subresource_filter_agent.cc
@@ -16,7 +16,6 @@ #include "components/subresource_filter/content/common/subresource_filter_utils.h" #include "components/subresource_filter/content/renderer/unverified_ruleset_dealer.h" #include "components/subresource_filter/content/renderer/web_document_subresource_filter_impl.h" -#include "components/subresource_filter/core/common/document_load_statistics.h" #include "components/subresource_filter/core/common/document_subresource_filter.h" #include "components/subresource_filter/core/common/memory_mapped_ruleset.h" #include "components/subresource_filter/core/common/scoped_timers.h" @@ -26,6 +25,7 @@ #include "content/public/renderer/render_frame.h" #include "ipc/ipc_message.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" #include "third_party/blink/public/platform/web_worker_fetch_context.h" #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_document_loader.h" @@ -41,8 +41,16 @@ : content::RenderFrameObserver(render_frame), content::RenderFrameObserverTracker<SubresourceFilterAgent>(render_frame), ruleset_dealer_(ruleset_dealer), - ad_resource_tracker_(std::move(ad_resource_tracker)) { + ad_resource_tracker_(std::move(ad_resource_tracker)), + binding_(this) { DCHECK(ruleset_dealer); + // |render_frame| can be nullptr in unit tests. + if (render_frame) { + render_frame->GetAssociatedInterfaceRegistry()->AddInterface( + base::BindRepeating( + &SubresourceFilterAgent::OnSubresourceFilterAgentRequest, + base::Unretained(this))); + } } SubresourceFilterAgent::~SubresourceFilterAgent() { @@ -71,9 +79,8 @@ } void SubresourceFilterAgent::SendDocumentLoadStatistics( - const DocumentLoadStatistics& statistics) { - render_frame()->Send(new SubresourceFilterHostMsg_DocumentLoadStatistics( - render_frame()->GetRoutingID(), statistics)); + const mojom::DocumentLoadStatistics& statistics) { + GetSubresourceFilterHost()->SetDocumentLoadStatistics(statistics.Clone()); } void SubresourceFilterAgent::SendFrameIsAdSubframe() { @@ -102,14 +109,6 @@ return mojom::ActivationState(); } -void SubresourceFilterAgent::OnActivateForNextCommittedLoad( - const mojom::ActivationState& activation_state, - bool is_ad_subframe) { - activation_state_for_next_commit_ = activation_state; - if (is_ad_subframe) - SetIsAdSubframe(); -} - void SubresourceFilterAgent::RecordHistogramsOnLoadCommitted( const mojom::ActivationState& activation_state) { // Note: mojom::ActivationLevel used to be called mojom::ActivationState, the @@ -180,6 +179,19 @@ return subresource_filter_host_; } +void SubresourceFilterAgent::OnSubresourceFilterAgentRequest( + mojom::SubresourceFilterAgentAssociatedRequest request) { + binding_.Bind(std::move(request)); +} + +void SubresourceFilterAgent::ActivateForNextCommittedLoad( + mojom::ActivationStatePtr activation_state, + bool is_ad_subframe) { + activation_state_for_next_commit_ = *activation_state; + if (is_ad_subframe) + SetIsAdSubframe(); +} + void SubresourceFilterAgent::OnDestruct() { delete this; } @@ -257,16 +269,6 @@ RecordHistogramsOnLoadFinished(); } -bool SubresourceFilterAgent::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(SubresourceFilterAgent, message) - IPC_MESSAGE_HANDLER(SubresourceFilterMsg_ActivateForNextCommittedLoad, - OnActivateForNextCommittedLoad) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - void SubresourceFilterAgent::WillCreateWorkerFetchContext( blink::WebWorkerFetchContext* worker_fetch_context) { if (!filter_for_last_committed_load_)
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent.h b/components/subresource_filter/content/renderer/subresource_filter_agent.h index 31c9d1745..7d1c9de8 100644 --- a/components/subresource_filter/content/renderer/subresource_filter_agent.h +++ b/components/subresource_filter/content/renderer/subresource_filter_agent.h
@@ -13,6 +13,7 @@ #include "components/subresource_filter/mojom/subresource_filter.mojom.h" #include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_frame_observer_tracker.h" +#include "mojo/public/cpp/bindings/associated_binding.h" #include "url/gurl.h" namespace blink { @@ -21,7 +22,6 @@ namespace subresource_filter { -struct DocumentLoadStatistics; class UnverifiedRulesetDealer; class WebDocumentSubresourceFilterImpl; @@ -32,6 +32,7 @@ class SubresourceFilterAgent : public content::RenderFrameObserver, public content::RenderFrameObserverTracker<SubresourceFilterAgent>, + public mojom::SubresourceFilterAgent, public base::SupportsWeakPtr<SubresourceFilterAgent> { public: // The |ruleset_dealer| must not be null and must outlive this instance. The @@ -62,7 +63,7 @@ // Sends statistics about the DocumentSubresourceFilter's work to the browser. virtual void SendDocumentLoadStatistics( - const DocumentLoadStatistics& statistics); + const mojom::DocumentLoadStatistics& statistics); // Tells the browser that the frame is an ad subframe. virtual void SendFrameIsAdSubframe(); @@ -71,15 +72,16 @@ virtual bool IsAdSubframe(); virtual void SetIsAdSubframe(); + // mojom::SubresourceFilterAgent: + void ActivateForNextCommittedLoad(mojom::ActivationStatePtr activation_state, + bool is_ad_subframe) override; + private: // Assumes that the parent will be in a local frame relative to this one, upon // construction. static mojom::ActivationState GetParentActivationState( content::RenderFrame* render_frame); - void OnActivateForNextCommittedLoad( - const mojom::ActivationState& activation_state, - bool is_ad_subframe); void RecordHistogramsOnLoadCommitted( const mojom::ActivationState& activation_state); void RecordHistogramsOnLoadFinished(); @@ -87,6 +89,9 @@ const mojom::SubresourceFilterHostAssociatedPtr& GetSubresourceFilterHost(); + void OnSubresourceFilterAgentRequest( + mojom::SubresourceFilterAgentAssociatedRequest request); + // content::RenderFrameObserver: void OnDestruct() override; void DidCreateNewDocument() override; @@ -94,7 +99,6 @@ ui::PageTransition transition) override; void DidFailProvisionalLoad(const blink::WebURLError& error) override; void DidFinishLoad() override; - bool OnMessageReceived(const IPC::Message& message) override; void WillCreateWorkerFetchContext(blink::WebWorkerFetchContext*) override; // Owned by the ChromeContentRendererClient and outlives us. @@ -109,6 +113,8 @@ // to legacy IPC messages. mojom::SubresourceFilterHostAssociatedPtr subresource_filter_host_; + mojo::AssociatedBinding<mojom::SubresourceFilterAgent> binding_; + // If a document has been created for this frame before. The first document // for a new local subframe should be about:blank. bool first_document_ = true;
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc b/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc index 439c08d..24a3f86 100644 --- a/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc +++ b/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc
@@ -14,7 +14,6 @@ #include "base/time/time.h" #include "components/subresource_filter/content/common/subresource_filter_messages.h" #include "components/subresource_filter/content/renderer/unverified_ruleset_dealer.h" -#include "components/subresource_filter/core/common/document_load_statistics.h" #include "components/subresource_filter/core/common/memory_mapped_ruleset.h" #include "components/subresource_filter/core/common/scoped_timers.h" #include "components/subresource_filter/core/common/test_ruleset_creator.h" @@ -52,7 +51,8 @@ MOCK_METHOD0(GetDocumentURL, GURL()); MOCK_METHOD0(OnSetSubresourceFilterForCommittedLoadCalled, void()); MOCK_METHOD0(SignalFirstSubresourceDisallowedForCommittedLoad, void()); - MOCK_METHOD1(SendDocumentLoadStatistics, void(const DocumentLoadStatistics&)); + MOCK_METHOD1(SendDocumentLoadStatistics, + void(const mojom::DocumentLoadStatistics&)); MOCK_METHOD0(SendFrameIsAdSubframe, void()); bool IsMainFrame() override { return true; } @@ -78,6 +78,8 @@ return std::move(last_injected_filter_); } + using SubresourceFilterAgent::ActivateForNextCommittedLoad; + private: std::unique_ptr<blink::WebDocumentSubresourceFilter> last_injected_filter_; bool is_ad_subframe_ = false; @@ -157,9 +159,7 @@ void StartLoadAndSetActivationState(mojom::ActivationState state, bool is_ad_subframe = false) { agent_as_rfo()->DidStartProvisionalLoad(nullptr, true); - EXPECT_TRUE(agent_as_rfo()->OnMessageReceived( - SubresourceFilterMsg_ActivateForNextCommittedLoad(0, state, - is_ad_subframe))); + agent()->ActivateForNextCommittedLoad(state.Clone(), is_ad_subframe); agent_as_rfo()->DidCommitProvisionalLoad( false /* is_same_document_navigation */, ui::PAGE_TRANSITION_LINK); } @@ -462,12 +462,11 @@ SetTestRulesetToDisallowURLsWithPathSuffix(kTestBothURLsPathSuffix)); ExpectNoSubresourceFilterGetsInjected(); agent_as_rfo()->DidStartProvisionalLoad(nullptr, true); - mojom::ActivationState state; - state.activation_level = mojom::ActivationLevel::kEnabled; - state.measure_performance = true; - EXPECT_TRUE(agent_as_rfo()->OnMessageReceived( - SubresourceFilterMsg_ActivateForNextCommittedLoad( - 0, state, false /* is_ad_subframe */))); + mojom::ActivationStatePtr state = mojom::ActivationState::New(); + state->activation_level = mojom::ActivationLevel::kEnabled; + state->measure_performance = true; + agent()->ActivateForNextCommittedLoad(std::move(state), + false /* is_ad_subframe */); agent_as_rfo()->DidFailProvisionalLoad( blink::WebURLError(net::ERR_FAILED, blink::WebURL())); agent_as_rfo()->DidStartProvisionalLoad(nullptr, true);
diff --git a/components/subresource_filter/core/common/BUILD.gn b/components/subresource_filter/core/common/BUILD.gn index 32a20df..6acaad4 100644 --- a/components/subresource_filter/core/common/BUILD.gn +++ b/components/subresource_filter/core/common/BUILD.gn
@@ -13,7 +13,6 @@ "activation_scope.h", "common_features.cc", "common_features.h", - "document_load_statistics.h", "document_subresource_filter.cc", "document_subresource_filter.h", "first_party_origin.cc",
diff --git a/components/subresource_filter/core/common/document_load_statistics.h b/components/subresource_filter/core/common/document_load_statistics.h deleted file mode 100644 index b6857693..0000000 --- a/components/subresource_filter/core/common/document_load_statistics.h +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_DOCUMENT_LOAD_STATISTICS_H_ -#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_DOCUMENT_LOAD_STATISTICS_H_ - -#include <stdint.h> - -#include "base/time/time.h" - -namespace subresource_filter { - -// Contains statistics and performance metrics collected by the -// DocumentSubresourceFilter. -struct DocumentLoadStatistics { - // The number of subresource loads that went through the - // DocumentSubresouceFilter filtering methods. - int32_t num_loads_total = 0; - - // Statistics on the number of subresource loads that were evaluated, were - // matched by filtering rules, and were disallowed, respectively, during the - // lifetime of a DocumentSubresourceFilter. - int32_t num_loads_evaluated = 0; - int32_t num_loads_matching_rules = 0; - int32_t num_loads_disallowed = 0; - - // Total time spent in GetLoadPolicy() calls evaluating subresource loads. - base::TimeDelta evaluation_total_wall_duration; - base::TimeDelta evaluation_total_cpu_duration; -}; - -} // namespace subresource_filter - -#endif // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_DOCUMENT_LOAD_STATISTICS_H_
diff --git a/components/subresource_filter/core/common/document_subresource_filter.h b/components/subresource_filter/core/common/document_subresource_filter.h index 79fdf40..19e2fa0d 100644 --- a/components/subresource_filter/core/common/document_subresource_filter.h +++ b/components/subresource_filter/core/common/document_subresource_filter.h
@@ -12,7 +12,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "components/subresource_filter/core/common/document_load_statistics.h" #include "components/subresource_filter/core/common/indexed_ruleset.h" #include "components/subresource_filter/core/common/load_policy.h" #include "components/subresource_filter/mojom/subresource_filter.mojom.h" @@ -46,12 +45,14 @@ const mojom::ActivationState& activation_state() const { return activation_state_; } - const DocumentLoadStatistics& statistics() const { return statistics_; } + const mojom::DocumentLoadStatistics& statistics() const { + return statistics_; + } // WARNING: This is only to allow DocumentSubresourceFilter's wrappers to // modify the |statistics|. // TODO(pkalinnikov): Find a better way to achieve this. - DocumentLoadStatistics& statistics() { return statistics_; } + mojom::DocumentLoadStatistics& statistics() { return statistics_; } LoadPolicy GetLoadPolicy( const GURL& subresource_url, @@ -77,7 +78,7 @@ // Equals nullptr iff |activation_state_.filtering_disabled_for_document|. std::unique_ptr<FirstPartyOrigin> document_origin_; - DocumentLoadStatistics statistics_; + mojom::DocumentLoadStatistics statistics_; DISALLOW_COPY_AND_ASSIGN(DocumentSubresourceFilter); };
diff --git a/components/subresource_filter/mojom/subresource_filter.mojom b/components/subresource_filter/mojom/subresource_filter.mojom index 3cc02d7..d8753722 100644 --- a/components/subresource_filter/mojom/subresource_filter.mojom +++ b/components/subresource_filter/mojom/subresource_filter.mojom
@@ -4,6 +4,8 @@ module subresource_filter.mojom; +import "mojo/public/mojom/base/time.mojom"; + enum ActivationLevel { kDisabled, kDryRun, @@ -37,6 +39,25 @@ bool enable_logging = false; }; +// Contains statistics and performance metrics collected by the +// DocumentSubresourceFilter. +struct DocumentLoadStatistics { + // The number of subresource loads that went through the + // DocumentSubresouceFilter filtering methods. + int32 num_loads_total = 0; + + // Statistics on the number of subresource loads that were evaluated, were + // matched by filtering rules, and were disallowed, respectively, during the + // lifetime of a DocumentSubresourceFilter. + int32 num_loads_evaluated = 0; + int32 num_loads_matching_rules = 0; + int32 num_loads_disallowed = 0; + + // Total time spent in GetLoadPolicy() calls evaluating subresource loads. + mojo_base.mojom.TimeDelta evaluation_total_wall_duration; + mojo_base.mojom.TimeDelta evaluation_total_cpu_duration; +}; + interface SubresourceFilterHost { // Called the first time a subresource load is disallowed for the most // recently committed document load in a frame. It is used to trigger a UI @@ -49,5 +70,24 @@ // an ad via SubresourceFilterMsg_ActivateForNextCommittedLoad, at // ReadyToCommitNavigation time. FrameIsAdSubframe(); + + // This is sent to a RenderFrameHost in the browser when a document load is + // finished, just before the DidFinishLoad message, and contains statistics + // collected by the DocumentSubresourceFilter up until that point: the number + // of subresources evaluated/disallowed/etc, and total time spent on + // evaluating subresource loads in its allowLoad method. The time metrics are + // equal to zero if performance measurements were disabled for the load. + SetDocumentLoadStatistics(DocumentLoadStatistics statistics); +}; + +interface SubresourceFilterAgent { + // Instructs the renderer to activate subresource filtering at the specified + // |activation_state| for the document load committed next in a frame. + // + // Most be called just before mojom::FrameNavigationControl::CommitNavigation, + // at ReadyToCommitNavigation time. If not called, the default behavior is + // mojom::ActivationLevel::kDisabled. + ActivateForNextCommittedLoad(ActivationState activation_state, + bool is_ad_subframe); };
diff --git a/components/toolbar/BUILD.gn b/components/toolbar/BUILD.gn index 339de16..2492cc25 100644 --- a/components/toolbar/BUILD.gn +++ b/components/toolbar/BUILD.gn
@@ -106,6 +106,7 @@ deps = [ ":toolbar", "//base", + "//base/test:test_support", "//testing/gtest", "//url", ]
diff --git a/components/toolbar/toolbar_field_trial.cc b/components/toolbar/toolbar_field_trial.cc index 4b03ab2..a8c412a 100644 --- a/components/toolbar/toolbar_field_trial.cc +++ b/components/toolbar/toolbar_field_trial.cc
@@ -5,10 +5,40 @@ #include "components/toolbar/toolbar_field_trial.h" #include "base/feature_list.h" +#include "build/build_config.h" +#include "ui/base/ui_base_features.h" namespace toolbar { namespace features { +const base::Feature kHideSteadyStateUrlScheme { + "OmniboxUIExperimentHideSteadyStateUrlScheme", +#if defined(OS_IOS) + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT +#endif +}; + +const base::Feature kHideSteadyStateUrlTrivialSubdomains { + "OmniboxUIExperimentHideSteadyStateUrlTrivialSubdomains", +#if defined(OS_IOS) + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT +#endif +}; + +bool IsHideSteadyStateUrlSchemeEnabled() { + return base::FeatureList::IsEnabled(kHideSteadyStateUrlScheme) || + base::FeatureList::IsEnabled(::features::kExperimentalUi); +} + +bool IsHideSteadyStateUrlTrivialSubdomainsEnabled() { + return base::FeatureList::IsEnabled(kHideSteadyStateUrlTrivialSubdomains) || + base::FeatureList::IsEnabled(::features::kExperimentalUi); +} + // Features used for EV UI removal experiment (https://crbug.com/803501). const base::Feature kSimplifyHttpsIndicator{"SimplifyHttpsIndicator", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/toolbar/toolbar_field_trial.h b/components/toolbar/toolbar_field_trial.h index 4b9dd0a..f0dbf55b 100644 --- a/components/toolbar/toolbar_field_trial.h +++ b/components/toolbar/toolbar_field_trial.h
@@ -10,6 +10,22 @@ namespace toolbar { namespace features { +// Feature used to hide the scheme from steady state URLs displayed in the +// toolbar. It is restored during editing. +extern const base::Feature kHideSteadyStateUrlScheme; + +// Feature used to hide trivial subdomains from steady state URLs displayed in +// the toolbar. It is restored during editing. +extern const base::Feature kHideSteadyStateUrlTrivialSubdomains; + +// Returns true if either the steady-state elision flag for scheme or the +// #upcoming-ui-features flag is enabled. +bool IsHideSteadyStateUrlSchemeEnabled(); + +// Returns true if either the steady-state elision flag for trivial +// subdomains or the #upcoming-ui-features flag is enabled. +bool IsHideSteadyStateUrlTrivialSubdomainsEnabled(); + // This feature simplifies the security indiciator UI for https:// pages. The // exact UI treatment is dependent on the parameter 'treatment' which can have // the following value:
diff --git a/components/toolbar/toolbar_model_impl.cc b/components/toolbar/toolbar_model_impl.cc index f308fbc..4211322 100644 --- a/components/toolbar/toolbar_model_impl.cc +++ b/components/toolbar/toolbar_model_impl.cc
@@ -44,12 +44,18 @@ base::string16 ToolbarModelImpl::GetURLForDisplay() const { url_formatter::FormatUrlTypes format_types = + url_formatter::kFormatUrlOmitDefaults; + #if defined(OS_IOS) - url_formatter::kFormatUrlTrimAfterHost | + format_types |= url_formatter::kFormatUrlTrimAfterHost; #endif - url_formatter::kFormatUrlOmitDefaults | - url_formatter::kFormatUrlOmitHTTPS | - url_formatter::kFormatUrlOmitTrivialSubdomains; + + if (toolbar::features::IsHideSteadyStateUrlSchemeEnabled()) + format_types |= url_formatter::kFormatUrlOmitHTTPS; + + if (toolbar::features::IsHideSteadyStateUrlTrivialSubdomainsEnabled()) + format_types |= url_formatter::kFormatUrlOmitTrivialSubdomains; + return GetFormattedURL(format_types); }
diff --git a/components/toolbar/toolbar_model_impl_unittest.cc b/components/toolbar/toolbar_model_impl_unittest.cc index 4fe8905..443fb464 100644 --- a/components/toolbar/toolbar_model_impl_unittest.cc +++ b/components/toolbar/toolbar_model_impl_unittest.cc
@@ -5,6 +5,8 @@ #include "components/toolbar/toolbar_model_impl.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" +#include "components/toolbar/toolbar_field_trial.h" #include "components/toolbar/toolbar_model_delegate.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -33,6 +35,12 @@ TEST(ToolbarModelImplTest, DisplayUrlAppliesFormattedStringWithEquivalentMeaning) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {toolbar::features::kHideSteadyStateUrlScheme, + toolbar::features::kHideSteadyStateUrlTrivialSubdomains}, + {}); + FakeToolbarModelDelegate delegate; auto model = std::make_unique<ToolbarModelImpl>(&delegate, 1024);
diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc index eb8d2dc..3d74be7 100644 --- a/content/browser/accessibility/accessibility_win_browsertest.cc +++ b/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -76,6 +76,10 @@ void SetUpInputField(Microsoft::WRL::ComPtr<IAccessibleText>* input_text); void SetUpScrollableInputField( Microsoft::WRL::ComPtr<IAccessibleText>* input_text); + void SetUpSingleCharInputField( + Microsoft::WRL::ComPtr<IAccessibleText>* input_text); + void SetUpSingleCharRtlInputField( + Microsoft::WRL::ComPtr<IAccessibleText>* input_text); void SetUpTextareaField( Microsoft::WRL::ComPtr<IAccessibleText>* textarea_text); void SetUpSampleParagraph( @@ -201,6 +205,39 @@ SetUpInputFieldHelper(input_text); } +// Loads a page with an input text field and places a single character in it. +void AccessibilityWinBrowserTest::SetUpSingleCharInputField( + Microsoft::WRL::ComPtr<IAccessibleText>* input_text) { + ASSERT_NE(nullptr, input_text); + LoadInitialAccessibilityTreeFromHtml(std::string( + R"HTML(<!DOCTYPE html> + <html> + <body> + <form> + <input type="text" id="textField" name="name" value="x"> + </form> + </body> + </html>)HTML")); + SetUpInputFieldHelper(input_text); +} + +// Loads a page with a right-to-left input text field and places a single +// character in it. +void AccessibilityWinBrowserTest::SetUpSingleCharRtlInputField( + Microsoft::WRL::ComPtr<IAccessibleText>* input_text) { + ASSERT_NE(nullptr, input_text); + LoadInitialAccessibilityTreeFromHtml(std::string( + R"HTML(<!DOCTYPE html> + <html> + <body> + <form> + <input type="text" id="textField" name="name" dir="rtl" value="x"> + </form> + </body> + </html>)HTML")); + SetUpInputFieldHelper(input_text); +} + void AccessibilityWinBrowserTest::SetUpInputFieldHelper( Microsoft::WRL::ComPtr<IAccessibleText>* input_text) { Microsoft::WRL::ComPtr<IAccessible> document(GetRendererAccessible()); @@ -1245,6 +1282,15 @@ EXPECT_LT(1, width) << "at offset " << offset; EXPECT_EQ(previous_height, height) << "at offset " << offset; } + + // Past end of text. + EXPECT_HRESULT_SUCCEEDED(paragraph_text->get_characterExtents( + n_characters, coordinate_type, &x, &y, &width, &height)); + EXPECT_LT(previous_x, x) << "at final offset " << n_characters; + EXPECT_EQ(previous_y, y) << "at final offset " << n_characters; + // Last character width past end should be 1, the width of a caret. + EXPECT_EQ(1, width) << "at final offset " << n_characters; + EXPECT_EQ(previous_height, height) << "at final offset " << n_characters; } } @@ -1376,6 +1422,111 @@ EXPECT_LT(1, width) << "at offset " << offset; EXPECT_EQ(previous_height, height) << "at offset " << offset; } + // Past end of text. + EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents( + n_characters, coordinate_type, &x, &y, &width, &height)); + EXPECT_LT(previous_x, x) << "at final offset " << n_characters; + EXPECT_EQ(previous_y, y) << "at final offset " << n_characters; + // Last character width past end should be 1, the width of a caret. + EXPECT_EQ(1, width) << "at final offset " << n_characters; + EXPECT_EQ(previous_height, height) << "at final offset " << n_characters; + } +} + +// TODO(accessibility) Support bounds in an empty text field where there are +// no child inline text objects, such that the following test passes. +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, + DISABLED_TestCharacterExtentsInEmptyInputField) { + Microsoft::WRL::ComPtr<IAccessibleText> input_text; + SetUpSingleCharInputField(&input_text); + + LONG n_characters; + ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters)); + ASSERT_EQ(1, n_characters); + + // Get the rect for the only character. + LONG prev_x, prev_y, prev_width, prev_height; + EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents( + 0, IA2_COORDTYPE_SCREEN_RELATIVE, &prev_x, &prev_y, &prev_width, + &prev_height)); + + EXPECT_LT(1, prev_width); + EXPECT_LT(1, prev_height); + + // Delete the character in the input field. + AccessibilityNotificationWaiter waiter( + shell()->web_contents(), ui::kAXModeComplete, + ax::mojom::Event::kTextSelectionChanged); + ExecuteScript(std::wstring(L"document.querySelector('input').value='';")); + waiter.WaitForNotification(); + + ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters)); + ASSERT_EQ(0, n_characters); + LONG caret_offset; + ASSERT_HRESULT_SUCCEEDED(input_text->get_caretOffset(&caret_offset)); + ASSERT_EQ(0, caret_offset); + + // Now that input is completely empty, the position of the caret should be + // returned for character 0. The x,y position and height should be the same as + // it was as when there was single character, but the width should now be 1. + LONG x, y, width, height; + for (int offset = IA2_TEXT_OFFSET_CARET; offset <= 0; ++offset) { + EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents( + offset, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height)); + EXPECT_EQ(prev_x, x); + EXPECT_EQ(prev_y, y); + EXPECT_EQ(1, width); + EXPECT_EQ(prev_height, height); + } +} + +// TODO(accessibility) Support bounds in an empty text field where there are +// no child inline text objects, such that the following test passes. +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, + DISABLED_TestCharacterExtentsInEmptyRtlInputField) { + Microsoft::WRL::ComPtr<IAccessibleText> input_text; + SetUpSingleCharRtlInputField(&input_text); + + LONG n_characters; + ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters)); + ASSERT_EQ(1, n_characters); + + // Get the rect for the only character. + LONG prev_x, prev_y, prev_width, prev_height; + EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents( + 0, IA2_COORDTYPE_SCREEN_RELATIVE, &prev_x, &prev_y, &prev_width, + &prev_height)); + + EXPECT_LT(1, prev_width); + EXPECT_LT(1, prev_height); + + // Delete the character in the input field. + AccessibilityNotificationWaiter waiter( + shell()->web_contents(), ui::kAXModeComplete, + ax::mojom::Event::kTextSelectionChanged); + ExecuteScript( + std::wstring(L"const input = document.querySelector('input');" + "input.value='';")); + waiter.WaitForNotification(); + + ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters)); + ASSERT_EQ(0, n_characters); + LONG caret_offset; + ASSERT_HRESULT_SUCCEEDED(input_text->get_caretOffset(&caret_offset)); + ASSERT_EQ(0, caret_offset); + + // Now that input is completely empty, the position of the caret should be + // returned for character 0. The x,y position and height should be the same as + // it was as when there was single character, but the width should now be 1. + LONG x, y, width, height; + for (int offset = IA2_TEXT_OFFSET_CARET; offset <= 0; ++offset) { + EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents( + offset, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height)); + // TODO(accessibility) Why do results keep changing on each run? + EXPECT_GE(prev_x + prev_width - 1, x); + EXPECT_EQ(prev_y, y); + EXPECT_EQ(1, width); + EXPECT_EQ(prev_height, height); } }
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc index b9fe935..400d970d 100644 --- a/content/browser/accessibility/browser_accessibility.cc +++ b/content/browser/accessibility/browser_accessibility.cc
@@ -75,9 +75,10 @@ uint32_t BrowserAccessibility::PlatformChildCount() const { if (HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId)) { + AXTreeID child_tree_id = AXTreeID::FromString( + GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId)); BrowserAccessibilityManager* child_manager = - BrowserAccessibilityManager::FromID( - GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId)); + BrowserAccessibilityManager::FromID(child_tree_id); if (child_manager && child_manager->GetRoot()->PlatformGetParent() == this) return 1; @@ -128,9 +129,10 @@ if (child_index == 0 && HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId)) { + AXTreeID child_tree_id = AXTreeID::FromString( + GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId)); BrowserAccessibilityManager* child_manager = - BrowserAccessibilityManager::FromID( - GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId)); + BrowserAccessibilityManager::FromID(child_tree_id); if (child_manager && child_manager->GetRoot()->PlatformGetParent() == this) result = child_manager->GetRoot(); } else { @@ -380,7 +382,9 @@ else start = 0; } - return bounds; + // When past the end of text, the area will be 0. + // In this case, use bounds provided for the caret. + return bounds.IsEmpty() ? GetPageBoundsPastEndOfText() : bounds; } int end = start + len; @@ -492,6 +496,54 @@ return bounds; } +// Get a rect for a 1-width character past the end of text. This is what ATs +// expect when getting the character extents past the last character in a line, +// and equals what the caret bounds would be when past the end of the text. +gfx::Rect BrowserAccessibility::GetPageBoundsPastEndOfText() const { + // Step 1: get approximate caret bounds. The thickness may not yet be correct. + gfx::Rect bounds; + if (InternalChildCount() > 0) { + // When past the end of text, use bounds provided by a last child if + // available, and then correct for thickness of caret. + BrowserAccessibility* child = InternalGetChild(InternalChildCount() - 1); + int child_text_len = child->GetText().size(); + bounds = child->GetPageBoundsForRange(child_text_len, child_text_len); + if (bounds.width() == 0 && bounds.height() == 0) + return bounds; // Inline text boxes info not yet available. + } else { + // TODO(accessibility) Support bounds in an empty text field where there are + // no child inline text objects. + return bounds; + } + + // Step 2: correct for the thickness of the caret. + auto text_direction = static_cast<ax::mojom::TextDirection>( + GetIntAttribute(ax::mojom::IntAttribute::kTextDirection)); + constexpr int kCaretThickness = 1; + switch (text_direction) { + case ax::mojom::TextDirection::kNone: + case ax::mojom::TextDirection::kLtr: { + bounds.set_width(kCaretThickness); + break; + } + case ax::mojom::TextDirection::kRtl: { + bounds.set_x(bounds.right() - kCaretThickness); + bounds.set_width(kCaretThickness); + break; + } + case ax::mojom::TextDirection::kTtb: { + bounds.set_height(kCaretThickness); + break; + } + case ax::mojom::TextDirection::kBtt: { + bounds.set_y(bounds.bottom() - kCaretThickness); + bounds.set_height(kCaretThickness); + break; + } + } + return bounds; +} + base::string16 BrowserAccessibility::GetValue() const { base::string16 value = GetString16Attribute(ax::mojom::StringAttribute::kValue); @@ -772,6 +824,24 @@ return name; } +std::string BrowserAccessibility::GetLiveRegionText() const { + if (GetRole() == ax::mojom::Role::kIgnored) + return ""; + + std::string text = GetStringAttribute(ax::mojom::StringAttribute::kName); + if (!text.empty()) + return text; + + for (size_t i = 0; i < InternalChildCount(); ++i) { + BrowserAccessibility* child = InternalGetChild(i); + if (!child) + continue; + + text += child->GetLiveRegionText(); + } + return text; +} + std::vector<int> BrowserAccessibility::GetLineStartOffsets() const { if (!instance_active()) return std::vector<int>();
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h index 494ad2e8..7a4951c 100644 --- a/content/browser/accessibility/browser_accessibility.h +++ b/content/browser/accessibility/browser_accessibility.h
@@ -320,6 +320,9 @@ // to compute a name from its descendants. std::string ComputeAccessibleNameFromDescendants() const; + // Get text to announce for a live region change if AT does not implement. + std::string GetLiveRegionText() const; + // Creates a text position rooted at this object. BrowserAccessibilityPosition::AXPositionInstance CreatePositionAt( int offset, @@ -389,6 +392,8 @@ // text, depending on the platform. base::string16 GetInnerText() const; + gfx::Rect GetPageBoundsPastEndOfText() const; + // A unique ID, since node IDs are frame-local. ui::AXUniqueId unique_id_;
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc index 8c86aa1..5a69a22 100644 --- a/content/browser/accessibility/browser_accessibility_manager.cc +++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -5,6 +5,7 @@ #include "content/browser/accessibility/browser_accessibility_manager.h" #include <stddef.h> +#include <map> #include <utility> #include "base/debug/crash_logging.h" @@ -21,7 +22,7 @@ namespace { // Map from AXTreeID to BrowserAccessibilityManager -using AXTreeIDMap = base::hash_map<ui::AXTreeID, BrowserAccessibilityManager*>; +using AXTreeIDMap = std::map<ui::AXTreeID, BrowserAccessibilityManager*>; base::LazyInstance<AXTreeIDMap>::Leaky g_ax_tree_id_map = LAZY_INSTANCE_INITIALIZER; @@ -49,8 +50,8 @@ ui::AXTreeUpdate update; ui::AXTreeData tree_data; - tree_data.tree_id = 1; - tree_data.focused_tree_id = 1; + tree_data.tree_id = ui::AXTreeID::FromString("1"); + tree_data.focused_tree_id = ui::AXTreeID::FromString("1"); update.tree_data = tree_data; update.has_tree_data = true; update.root_id = node1.id; @@ -273,8 +274,9 @@ for (int32_t host_node_id : host_node_ids) { BrowserAccessibility* parent_node = parent_manager->GetFromID(host_node_id); if (parent_node) { - DCHECK_EQ(ax_tree_id_, parent_node->GetStringAttribute( - ax::mojom::StringAttribute::kChildTreeId)); + DCHECK_EQ(ax_tree_id_, + AXTreeID::FromString(parent_node->GetStringAttribute( + ax::mojom::StringAttribute::kChildTreeId))); return parent_node; } } @@ -520,9 +522,10 @@ return GetRoot(); if (obj->HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId)) { + AXTreeID child_tree_id = AXTreeID::FromString( + obj->GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId)); BrowserAccessibilityManager* child_manager = - BrowserAccessibilityManager::FromID( - obj->GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId)); + BrowserAccessibilityManager::FromID(child_tree_id); if (child_manager) return child_manager->GetFocusFromThisOrDescendantFrame(); }
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm index 584c954..ace4792 100644 --- a/content/browser/accessibility/browser_accessibility_manager_mac.mm +++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -182,6 +182,16 @@ FireNativeMacNotification(mac_notification, node); } +void PostAnnouncementNotification(NSString* announcement) { + NSDictionary* notification_info = @{ + NSAccessibilityAnnouncementKey : announcement, + NSAccessibilityPriorityKey : @(NSAccessibilityPriorityLow) + }; + NSAccessibilityPostNotificationWithUserInfo( + [NSApp mainWindow], NSAccessibilityAnnouncementRequestedNotification, + notification_info); +} + void BrowserAccessibilityManagerMac::FireGeneratedEvent( AXEventGenerator::Event event_type, BrowserAccessibility* node) { @@ -315,6 +325,18 @@ return; } + if (base::mac::IsAtMostOS10_13()) { + // Use the announcement API to get around OS <= 10.13 VoiceOver bug + // where it stops announcing live regions after the first time focus + // leaves any content area. + // Unfortunately this produces an annoying boing sound with each live + // announcement, but the alternative is almost no live region support. + PostAnnouncementNotification( + base::SysUTF8ToNSString(node->GetLiveRegionText())); + return; + } + + // Use native VoiceOver support for live regions. base::scoped_nsobject<BrowserAccessibilityCocoa> retained_node( [native_node retain]); base::PostDelayedTaskWithTraits(
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 8fba1fcf..f95b75a 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -971,6 +971,11 @@ RunAriaTest(FILE_PATH_LITERAL("table-column-hidden.html")); } +IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, + AccessibilityLabelWithSelectedAriaOption) { + RunAriaTest(FILE_PATH_LITERAL("label-with-selected-option.html")); +} + IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityArticle) { RunHtmlTest(FILE_PATH_LITERAL("article.html")); } @@ -1849,6 +1854,11 @@ RunHtmlTest(FILE_PATH_LITERAL("input-image-with-title.html")); } +IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, + AccessibilityLabelWithSelectedOption) { + RunHtmlTest(FILE_PATH_LITERAL("label-with-selected-option.html")); +} + // // Regression tests. These don't test a specific web platform feature, // they test a specific web page that crashed or had some bad behavior
diff --git a/content/browser/appcache/appcache_storage_impl.cc b/content/browser/appcache/appcache_storage_impl.cc index 1aff407..3d0aee2 100644 --- a/content/browser/appcache/appcache_storage_impl.cc +++ b/content/browser/appcache/appcache_storage_impl.cc
@@ -684,7 +684,7 @@ // We have to ask the quota manager for the value. storage_->pending_quota_queries_.insert(this); quota_manager->GetUsageAndQuota( - group_record_.origin.GetURL(), blink::mojom::StorageType::kTemporary, + group_record_.origin, blink::mojom::StorageType::kTemporary, base::BindOnce(&StoreGroupAndCacheTask::OnQuotaCallback, this)); }
diff --git a/content/browser/appcache/appcache_storage_impl_unittest.cc b/content/browser/appcache/appcache_storage_impl_unittest.cc index 03237c2..8fe73464 100644 --- a/content/browser/appcache/appcache_storage_impl_unittest.cc +++ b/content/browser/appcache/appcache_storage_impl_unittest.cc
@@ -254,7 +254,7 @@ storage::GetQuotaSettingsFunc()), async_(false) {} - void GetUsageAndQuota(const GURL& origin, + void GetUsageAndQuota(const url::Origin& /* origin */, StorageType type, UsageAndQuotaCallback callback) override { EXPECT_EQ(StorageType::kTemporary, type);
diff --git a/content/browser/cache_storage/cache_storage_cache_unittest.cc b/content/browser/cache_storage/cache_storage_cache_unittest.cc index 66462353..1246417f 100644 --- a/content/browser/cache_storage/cache_storage_cache_unittest.cc +++ b/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -62,7 +62,8 @@ namespace cache_storage_cache_unittest { const char kTestData[] = "Hello World"; -const char kOrigin[] = "http://example.com"; +// TODO(crbug.com/889590): Use helper for url::Origin creation from string. +const url::Origin kOrigin = url::Origin::Create(GURL("http://example.com")); const char kCacheName[] = "test_cache"; const GURL kBodyUrl("http://example.com/body.html"); const GURL kBodyUrlWithQuery("http://example.com/body.html?query=test"); @@ -387,9 +388,8 @@ mock_quota_manager_ = new MockQuotaManager( is_incognito, temp_dir_path, base::ThreadTaskRunnerHandle::Get().get(), quota_policy_.get()); - mock_quota_manager_->SetQuota(GURL(kOrigin), - blink::mojom::StorageType::kTemporary, - 1024 * 1024 * 100); + mock_quota_manager_->SetQuota( + kOrigin, blink::mojom::StorageType::kTemporary, 1024 * 1024 * 100); quota_manager_proxy_ = new MockQuotaManagerProxy( mock_quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get()); @@ -415,8 +415,7 @@ MakeRequest(&blob_ptr_)); cache_ = std::make_unique<TestCacheStorageCache>( - url::Origin::Create(GURL(kOrigin)), kCacheName, temp_dir_path, - nullptr /* CacheStorage */, + kOrigin, kCacheName, temp_dir_path, nullptr /* CacheStorage */, BrowserContext::GetDefaultStoragePartition(&browser_context_) ->GetURLRequestContext(), quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr()); @@ -1539,8 +1538,7 @@ } TEST_P(CacheStorageCacheTestP, PutWithSideData_QuotaExceeded) { - mock_quota_manager_->SetQuota(GURL(kOrigin), - blink::mojom::StorageType::kTemporary, + mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary, expected_blob_data_.size() - 1); blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse(); const std::string expected_side_data = "SideData"; @@ -1555,8 +1553,7 @@ } TEST_P(CacheStorageCacheTestP, PutWithSideData_QuotaExceededSkipSideData) { - mock_quota_manager_->SetQuota(GURL(kOrigin), - blink::mojom::StorageType::kTemporary, + mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary, expected_blob_data_.size()); blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse(); const std::string expected_side_data = "SideData"; @@ -1638,8 +1635,8 @@ } TEST_P(CacheStorageCacheTestP, WriteSideData_QuotaExceeded) { - mock_quota_manager_->SetQuota( - GURL(kOrigin), blink::mojom::StorageType::kTemporary, 1024 * 1023); + mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary, + 1024 * 1023); base::Time response_time(base::Time::Now()); blink::mojom::FetchAPIResponsePtr response(CreateNoBodyResponse()); response->response_time = response_time; @@ -1746,8 +1743,8 @@ } TEST_P(CacheStorageCacheTestP, PutObeysQuotaLimits) { - mock_quota_manager_->SetQuota(GURL(kOrigin), - blink::mojom::StorageType::kTemporary, 0); + mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary, + 0); EXPECT_FALSE(Put(body_request_, CreateBlobBodyResponse())); EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_); }
diff --git a/content/browser/cache_storage/cache_storage_manager_unittest.cc b/content/browser/cache_storage/cache_storage_manager_unittest.cc index c9aa948..9c9f451 100644 --- a/content/browser/cache_storage/cache_storage_manager_unittest.cc +++ b/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -259,9 +259,9 @@ mock_quota_manager_ = new MockQuotaManager( MemoryOnly(), temp_dir_path, base::ThreadTaskRunnerHandle::Get().get(), quota_policy_.get()); - mock_quota_manager_->SetQuota(origin1_.GetURL(), StorageType::kTemporary, + mock_quota_manager_->SetQuota(origin1_, StorageType::kTemporary, 1024 * 1024 * 100); - mock_quota_manager_->SetQuota(origin2_.GetURL(), StorageType::kTemporary, + mock_quota_manager_->SetQuota(origin2_, StorageType::kTemporary, 1024 * 1024 * 100); quota_manager_proxy_ = new MockCacheStorageQuotaManagerProxy(
diff --git a/content/browser/devtools/devtools_url_loader_interceptor.cc b/content/browser/devtools/devtools_url_loader_interceptor.cc index 95cd368..e7001506e 100644 --- a/content/browser/devtools/devtools_url_loader_interceptor.cc +++ b/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -988,8 +988,8 @@ request.method, request.url, request.site_for_cookies, first_party_url_policy, request.referrer_policy, request.referrer.spec(), &headers, headers.response_code(), - redirect_url, false /* token_binding_negotiated */, - false /* insecure_scheme_was_upgraded */, false /* copy_fragment */)); + redirect_url, false /* insecure_scheme_was_upgraded */, + false /* copy_fragment */)); client_->OnReceiveRedirect(*response_metadata_->redirect_info, response_metadata_->head);
diff --git a/content/browser/devtools/protocol/storage_handler.cc b/content/browser/devtools/protocol/storage_handler.cc index 2af30aad8..436be9b 100644 --- a/content/browser/devtools/protocol/storage_handler.cc +++ b/content/browser/devtools/protocol/storage_handler.cc
@@ -86,11 +86,11 @@ void GetUsageAndQuotaOnIOThread( storage::QuotaManager* manager, - const GURL& url, + const url::Origin& origin, std::unique_ptr<StorageHandler::GetUsageAndQuotaCallback> callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); manager->GetUsageAndQuotaWithBreakdown( - url, blink::mojom::StorageType::kTemporary, + origin, blink::mojom::StorageType::kTemporary, base::BindOnce(&GotUsageAndQuotaDataCallback, std::move(callback))); } } // namespace @@ -335,7 +335,7 @@ base::PostTaskWithTraits( FROM_HERE, {BrowserThread::IO}, base::BindOnce(&GetUsageAndQuotaOnIOThread, base::RetainedRef(manager), - origin_url, std::move(callback))); + url::Origin::Create(origin_url), std::move(callback))); } Response StorageHandler::TrackCacheStorageForOrigin(const std::string& origin) {
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc index 26385de..aa292b7 100644 --- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc +++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -2371,6 +2371,7 @@ EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( shell()->web_contents()->GetMainFrame()->GetProcess()->GetID())); SiteInstance* site_instance1 = shell()->web_contents()->GetSiteInstance(); + int process1_id = site_instance1->GetProcess()->GetID(); // Open a new tab. Initially it gets a render view in the original tab's // current site instance. @@ -2383,9 +2384,14 @@ WebContentsImpl* new_web_contents = static_cast<WebContentsImpl*>( new_shell->web_contents()); SiteInstance* site_instance2 = new_web_contents->GetSiteInstance(); + int process2_id = site_instance2->GetProcess()->GetID(); + // The 2nd WebUI page should swap to a different process (and SiteInstance), + // but should stay in the same BrowsingInstance as the 1st WebUI page. + EXPECT_NE(process1_id, process2_id); EXPECT_NE(site_instance2, site_instance1); EXPECT_TRUE(site_instance2->IsRelatedSiteInstance(site_instance1)); + RenderViewHost* initial_rvh = new_web_contents-> GetRenderManagerForTesting()->GetSwappedOutRenderViewHost(site_instance1); ASSERT_TRUE(initial_rvh);
diff --git a/content/browser/frame_host/webui_navigation_browsertest.cc b/content/browser/frame_host/webui_navigation_browsertest.cc index 7add7719..fbf93aa 100644 --- a/content/browser/frame_host/webui_navigation_browsertest.cc +++ b/content/browser/frame_host/webui_navigation_browsertest.cc
@@ -2,12 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/command_line.h" +#include "base/macros.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/web_contents.h" #include "content/public/common/bindings_policy.h" #include "content/public/common/browser_side_navigation_policy.h" +#include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" @@ -16,6 +19,7 @@ #include "content/shell/browser/shell.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "url/url_constants.h" namespace content { @@ -219,6 +223,11 @@ EXPECT_EQ(chrome_url, webui_rfh->GetLastCommittedURL()); EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( webui_rfh->GetProcess()->GetID())); + EXPECT_EQ( + ChildProcessSecurityPolicyImpl::CheckOriginLockResult::HAS_EQUAL_LOCK, + ChildProcessSecurityPolicyImpl::GetInstance()->CheckOriginLock( + root->current_frame_host()->GetProcess()->GetID(), + webui_site_instance->GetSiteURL())); GURL web_url(embedded_test_server()->GetURL("/title2.html")); std::string script = @@ -233,6 +242,13 @@ EXPECT_NE(webui_site_instance, root->current_frame_host()->GetSiteInstance()); EXPECT_FALSE(webui_site_instance->IsRelatedSiteInstance( root->current_frame_host()->GetSiteInstance())); + EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( + root->current_frame_host()->GetProcess()->GetID())); + EXPECT_NE( + ChildProcessSecurityPolicyImpl::CheckOriginLockResult::HAS_EQUAL_LOCK, + ChildProcessSecurityPolicyImpl::GetInstance()->CheckOriginLock( + root->current_frame_host()->GetProcess()->GetID(), + webui_site_instance->GetSiteURL())); } IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest, @@ -267,4 +283,37 @@ BINDINGS_POLICY_WEB_UI); } +IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest, + WebUIOriginsRequireDedicatedProcess) { + // chrome:// URLs should require a dedicated process. + WebContents* web_contents = shell()->web_contents(); + BrowserContext* browser_context = web_contents->GetBrowserContext(); + GURL chrome_url = GURL(std::string(kChromeUIScheme) + "://" + + std::string(kChromeUIGpuHost)); + EXPECT_TRUE(SiteInstanceImpl::DoesSiteRequireDedicatedProcess(browser_context, + chrome_url)); + + // Navigate to a WebUI page. + EXPECT_TRUE(NavigateToURL(shell(), chrome_url)); + + // Verify that the "hostname" is also part of the site URL. + GURL site_url = web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL(); + EXPECT_EQ(chrome_url, site_url); + + // Ask the page to create a blob URL and return back the blob URL. + const char* kScript = R"( + var blob = new Blob(['foo'], {type : 'text/html'}); + var url = URL.createObjectURL(blob); + url; + )"; + GURL blob_url(EvalJs(shell(), kScript).ExtractString()); + EXPECT_EQ(url::kBlobScheme, blob_url.scheme()); + + // Verify that the blob also requires a dedicated process and that it would + // use the same site url as the original page. + EXPECT_TRUE(SiteInstanceImpl::DoesSiteRequireDedicatedProcess(browser_context, + blob_url)); + EXPECT_EQ(chrome_url, SiteInstance::GetSiteForURL(browser_context, blob_url)); +} + } // namespace content
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc index 7f5000f..7b8ccdc9 100644 --- a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc +++ b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
@@ -58,6 +58,11 @@ namespace content { namespace { +// TODO(crbug.com/889590): Replace with common converter. +url::Origin ToOrigin(const std::string& url) { + return url::Origin::Create(GURL(url)); +} + ACTION_TEMPLATE(MoveArg, HAS_1_TEMPLATE_PARAMS(int, k), AND_1_VALUE_PARAMS(out)) { @@ -174,8 +179,9 @@ {BrowserThread::IO})), context_impl_, ChromeBlobStorageContext::GetFor(&browser_context_))) { - quota_manager_->SetQuota( - GURL(kOrigin), blink::mojom::StorageType::kTemporary, kTemporaryQuota); + quota_manager_->SetQuota(ToOrigin(kOrigin), + blink::mojom::StorageType::kTemporary, + kTemporaryQuota); } void TearDown() override { @@ -240,7 +246,7 @@ const char kObjectStoreName[] = "os"; // Open connection. - TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)), + TestDatabaseConnection connection(ToOrigin(kOrigin), base::UTF8ToUTF16(kDatabaseName), kDBVersion, kTransactionId); @@ -322,9 +328,8 @@ // Open connection 2, but expect that we won't be called back. IDBDatabaseAssociatedPtrInfo database_info2; IndexedDBDatabaseMetadata metadata2; - TestDatabaseConnection connection2(url::Origin::Create(GURL(kOrigin)), - base::UTF8ToUTF16(kDatabaseName), - kDBVersion, 0); + TestDatabaseConnection connection2( + ToOrigin(kOrigin), base::UTF8ToUTF16(kDatabaseName), kDBVersion, 0); connection2.Open(idb_mojo_factory_.get()); // Check that we're called in order and the second connection gets it's @@ -448,7 +453,7 @@ const int64_t kTransactionId = 1; // Open connection. - TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)), + TestDatabaseConnection connection(ToOrigin(kOrigin), base::UTF8ToUTF16(kDatabaseName), kDBVersion, kTransactionId); IndexedDBDatabaseMetadata metadata; @@ -508,7 +513,7 @@ const char kObjectStoreName[] = "os"; // Open connection. - TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)), + TestDatabaseConnection connection(ToOrigin(kOrigin), base::UTF8ToUTF16(kDatabaseName), kDBVersion, kTransactionId); IndexedDBDatabaseMetadata metadata; @@ -573,7 +578,7 @@ const int64_t kTransactionId = 1; // Open connection. - TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)), + TestDatabaseConnection connection(ToOrigin(kOrigin), base::UTF8ToUTF16(kDatabaseName), kDBVersion, kTransactionId); IndexedDBDatabaseMetadata metadata; @@ -636,7 +641,7 @@ const int64_t kTransactionId = 1; // Open connection. - TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)), + TestDatabaseConnection connection(ToOrigin(kOrigin), base::UTF8ToUTF16(kDatabaseName), kDBVersion, kTransactionId); IndexedDBDatabaseMetadata metadata; @@ -699,7 +704,7 @@ const char kObjectStoreName[] = "os"; // Open connection. - TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)), + TestDatabaseConnection connection(ToOrigin(kOrigin), base::UTF8ToUTF16(kDatabaseName), kDBVersion, kTransactionId); IndexedDBDatabaseMetadata metadata; @@ -764,7 +769,7 @@ const int64_t kTransactionId = 1; // Open connection. - TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)), + TestDatabaseConnection connection(ToOrigin(kOrigin), base::UTF8ToUTF16(kDatabaseName), kDBVersion, kTransactionId); IndexedDBDatabaseMetadata metadata; @@ -838,7 +843,7 @@ context_impl_->AddObserver(&observer); // Open connection 1. - TestDatabaseConnection connection1(url::Origin::Create(GURL(kOrigin)), + TestDatabaseConnection connection1(ToOrigin(kOrigin), base::UTF8ToUTF16(kDatabaseName), kDBVersion1, kTransactionId1); IndexedDBDatabaseMetadata metadata1; @@ -943,7 +948,7 @@ connection2.database->Close(); // Open connection 3. - TestDatabaseConnection connection3(url::Origin::Create(GURL(kOrigin)), + TestDatabaseConnection connection3(ToOrigin(kOrigin), base::UTF8ToUTF16(kDatabaseName), kDBVersion3, kTransactionId3); IndexedDBDatabaseMetadata metadata3; @@ -1072,7 +1077,7 @@ connection1.database->Close(); // Open connection 2. - TestDatabaseConnection connection2(url::Origin::Create(GURL(kOrigin)), + TestDatabaseConnection connection2(ToOrigin(kOrigin), base::UTF8ToUTF16(kDatabaseName), kDBVersion2, kTransactionId2); IndexedDBDatabaseMetadata metadata2;
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc index 90543ca5..26f09ff 100644 --- a/content/browser/loader/navigation_url_loader_impl.cc +++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -962,7 +962,6 @@ // there likely remains more to be done. // a. For subframe navigations, the Origin header may need to be modified // differently? - // b. How should redirect_info_.referred_token_binding_host be handled? bool should_clear_upload = false; net::RedirectUtil::UpdateHttpRequest(
diff --git a/content/browser/quota_dispatcher_host.cc b/content/browser/quota_dispatcher_host.cc index dee8d4e..350bdf3b 100644 --- a/content/browser/quota_dispatcher_host.cc +++ b/content/browser/quota_dispatcher_host.cc
@@ -95,7 +95,7 @@ StorageType storage_type, QueryStorageUsageAndQuotaCallback callback) { quota_manager_->GetUsageAndQuotaForWebApps( - origin.GetURL(), storage_type, + origin, storage_type, base::BindOnce(&QuotaDispatcherHost::DidQueryStorageUsageAndQuota, weak_factory_.GetWeakPtr(), std::move(callback))); } @@ -126,13 +126,13 @@ storage_type == StorageType::kPersistent); if (storage_type == StorageType::kPersistent) { quota_manager_->GetUsageAndQuotaForWebApps( - origin.GetURL(), storage_type, + origin, storage_type, base::BindOnce(&QuotaDispatcherHost::DidGetPersistentUsageAndQuota, weak_factory_.GetWeakPtr(), origin, storage_type, requested_size, std::move(callback))); } else { quota_manager_->GetUsageAndQuotaForWebApps( - origin.GetURL(), storage_type, + origin, storage_type, base::BindOnce(&QuotaDispatcherHost::DidGetTemporaryUsageAndQuota, weak_factory_.GetWeakPtr(), requested_size, std::move(callback))); @@ -166,7 +166,7 @@ // TODO(nhiroki): The backend should accept uint64_t values. int64_t requested_quota_signed = base::saturated_cast<int64_t>(requested_quota); - if (quota_manager_->IsStorageUnlimited(origin.GetURL(), storage_type) || + if (quota_manager_->IsStorageUnlimited(origin, storage_type) || requested_quota_signed <= current_quota) { std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk, current_usage, requested_quota);
diff --git a/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc b/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc index d54aa97..c41c809 100644 --- a/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc +++ b/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
@@ -412,7 +412,7 @@ storage::FileSystemType file_system_type = PepperFileSystemTypeToFileSystemType(type_); return !quota_manager_proxy->quota_manager()->IsStorageUnlimited( - root_url_.GetOrigin(), + url::Origin::Create(root_url_), storage::FileSystemTypeToQuotaStorageType(file_system_type)); }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 95444b0..404a1e7 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -568,7 +568,7 @@ return manager->GetRoot()->GetNativeViewAccessible(); #endif - NOTIMPLEMENTED(); + NOTIMPLEMENTED_LOG_ONCE(); return static_cast<gfx::NativeViewAccessible>(nullptr); } @@ -1272,7 +1272,7 @@ } base::i18n::TextDirection RenderWidgetHostViewAura::GetTextDirection() const { - NOTIMPLEMENTED(); + NOTIMPLEMENTED_LOG_ONCE(); return base::i18n::UNKNOWN_DIRECTION; } @@ -1382,7 +1382,7 @@ bool RenderWidgetHostViewAura::GetCompositionTextRange( gfx::Range* range) const { // TODO(suzhe): implement this method when fixing http://crbug.com/55130. - NOTIMPLEMENTED(); + NOTIMPLEMENTED_LOG_ONCE(); return false; } @@ -1402,13 +1402,13 @@ bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) { // TODO(suzhe): implement this method when fixing http://crbug.com/55130. - NOTIMPLEMENTED(); + NOTIMPLEMENTED_LOG_ONCE(); return false; } bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) { // TODO(suzhe): implement this method when fixing http://crbug.com/55130. - NOTIMPLEMENTED(); + NOTIMPLEMENTED_LOG_ONCE(); return false; }
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 0fdcb47..e2b2712b 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -92,7 +92,6 @@ // |delegate| should be set at most once. CONTENT_EXPORT void SetDelegate( NSObject<RenderWidgetHostViewMacDelegate>* delegate); - void SetAllowPauseForResizeOrRepaint(bool allow); // RenderWidgetHostView implementation. void InitAsChild(gfx::NativeView parent_view) override;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index fc8e9dec..d826ceb 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -217,13 +217,9 @@ // startup raciness and decrease latency. needs_begin_frames_ = needs_begin_frames; UpdateNeedsBeginFramesInternal(); - if (features::IsViewsBrowserCocoa()) - ui::CATransactionCoordinator::Get().AddPreCommitObserver(this); } RenderWidgetHostViewMac::~RenderWidgetHostViewMac() { - if (features::IsViewsBrowserCocoa()) - ui::CATransactionCoordinator::Get().RemovePreCommitObserver(this); if (popup_parent_host_view_) { DCHECK(!popup_parent_host_view_->popup_child_host_view_ || popup_parent_host_view_->popup_child_host_view_ == this); @@ -308,11 +304,6 @@ [cocoa_view() setResponderDelegate:delegate]; } -void RenderWidgetHostViewMac::SetAllowPauseForResizeOrRepaint(bool allow) { - // TODO: Remove SetAllowPauseForResizeOrRepaint and SetAllowOtherViews, since - // they aren't used anymore. -} - ui::TextInputType RenderWidgetHostViewMac::GetTextInputType() { if (!GetActiveWidget()) return ui::TEXT_INPUT_TYPE_NONE; @@ -409,9 +400,6 @@ LOG(ERROR) << "Failed to create display link."; } - if (features::IsViewsBrowserCocoa()) - ui::CATransactionCoordinator::Get().Synchronize(); - // During auto-resize it is the responsibility of the caller to ensure that // the NSView and RenderWidgetHostImpl are kept in sync. if (host()->auto_resize_enabled())
diff --git a/content/browser/service_worker/service_worker_navigation_loader.cc b/content/browser/service_worker/service_worker_navigation_loader.cc index 5552d4a..473bd8d 100644 --- a/content/browser/service_worker/service_worker_navigation_loader.cc +++ b/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -464,9 +464,8 @@ // Handle a redirect response. ComputeRedirectInfo returns non-null redirect // info if the given response is a redirect. base::Optional<net::RedirectInfo> redirect_info = - ServiceWorkerLoaderHelpers::ComputeRedirectInfo( - resource_request_, response_head_, - response_head_.ssl_info->token_binding_negotiated); + ServiceWorkerLoaderHelpers::ComputeRedirectInfo(resource_request_, + response_head_); if (redirect_info) { TRACE_EVENT_WITH_FLOW2( "ServiceWorker", "ServiceWorkerNavigationLoader::StartResponse", this,
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc index f09529d..2f27e67 100644 --- a/content/browser/site_instance_impl.cc +++ b/content/browser/site_instance_impl.cc
@@ -569,18 +569,23 @@ if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) return true; - // Error pages in main frames do require isolation, however since this is - // missing the context whether this is for a main frame or not, that part - // is enforced in RenderFrameHostManager. - if (url.SchemeIs(kChromeErrorScheme)) - return true; - // Always require a dedicated process for isolated origins. GURL site_url = SiteInstance::GetSiteForURL(browser_context, url); auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); if (policy->IsIsolatedOrigin(url::Origin::Create(site_url))) return true; + // Error pages in main frames do require isolation, however since this is + // missing the context whether this is for a main frame or not, that part + // is enforced in RenderFrameHostManager. + if (site_url.SchemeIs(kChromeErrorScheme)) + return true; + + // Isolate kChromeUIScheme pages from one another and from other kinds of + // schemes. + if (site_url.SchemeIs(content::kChromeUIScheme)) + return true; + // Let the content embedder enable site isolation for specific URLs. Use the // canonical site url for this check, so that schemes with nested origins // (blob and filesystem) work properly. @@ -611,12 +616,6 @@ if (site_url.SchemeIs(content::kGuestScheme)) return false; - // TODO(creis, nick) https://crbug.com/510588 Chrome UI pages use the same - // site (chrome://chrome), so they can't be locked because the site being - // loaded doesn't match the SiteInstance. - if (site_url.SchemeIs(content::kChromeUIScheme)) - return false; - // TODO(creis, nick): Until we can handle sites with effective URLs at the // call sites of ChildProcessSecurityPolicy::CanAccessDataForOrigin, we // must give the embedder a chance to exempt some sites to avoid process
diff --git a/content/browser/site_instance_impl.h b/content/browser/site_instance_impl.h index 41f75a3b..1fd745d 100644 --- a/content/browser/site_instance_impl.h +++ b/content/browser/site_instance_impl.h
@@ -232,12 +232,12 @@ // true here also implies that |site_url| requires a dedicated process. // However, the converse does not hold: this might still return false for // certain special cases where an origin lock can't be applied even when - // |site_url| requires a dedicated process (e.g., with - // --site-per-process). Examples of those cases include <webview> guests, - // WebUI, single-process mode, or extensions where a process is currently - // allowed to be reused for different extensions. Most of these special - // cases should eventually be removed, and this function should become - // equivalent to DoesSiteRequireDedicatedProcess(). + // |site_url| requires a dedicated process (e.g., with --site-per-process). + // Examples of those cases include <webview> guests, single-process mode, or + // extensions where a process is currently allowed to be reused for different + // extensions. Most of these special cases should eventually be removed, and + // this function should become equivalent to + // DoesSiteRequireDedicatedProcess(). static bool ShouldLockToOrigin(BrowserContext* browser_context, GURL site_url);
diff --git a/content/browser/site_instance_impl_unittest.cc b/content/browser/site_instance_impl_unittest.cc index ec3fa59..412ca32b 100644 --- a/content/browser/site_instance_impl_unittest.cc +++ b/content/browser/site_instance_impl_unittest.cc
@@ -676,79 +676,6 @@ DrainMessageLoop(); } -static scoped_refptr<SiteInstanceImpl> CreateSiteInstance( - BrowserContext* browser_context, - const GURL& url) { - return SiteInstanceImpl::CreateForURL(browser_context, url); -} - -// Test to ensure that pages that require certain privileges are grouped -// in processes with similar pages. -// TODO(nasko): Remove. See https://crbug.com/847127. -TEST_F(SiteInstanceTest, ProcessSharingByType) { - // This test shouldn't run with --site-per-process mode, which prohibits - // the renderer process reuse this test explicitly exercises. - if (AreAllSitesIsolatedForTesting()) - return; - - ChildProcessSecurityPolicyImpl* policy = - ChildProcessSecurityPolicyImpl::GetInstance(); - - // Make a bunch of mock renderers so that we hit the limit. - std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext()); - std::vector<std::unique_ptr<MockRenderProcessHost>> hosts; - for (size_t i = 0; i < kMaxRendererProcessCount; ++i) { - hosts.push_back( - std::make_unique<MockRenderProcessHost>(browser_context.get())); - hosts[i]->SetIsUsed(); - } - - // On Android by default the number of renderer hosts is unlimited and process - // sharing doesn't happen. We set the override so that the test can run - // everywhere. - RenderProcessHost::SetMaxRendererProcessCount(kMaxRendererProcessCount); - - // Create some extension instances and make sure they share a process. - scoped_refptr<SiteInstanceImpl> extension1_instance( - CreateSiteInstance(browser_context.get(), - GURL(kPrivilegedScheme + std::string("://foo/bar")))); - set_privileged_process_id(extension1_instance->GetProcess()->GetID()); - - scoped_refptr<SiteInstanceImpl> extension2_instance( - CreateSiteInstance(browser_context.get(), - GURL(kPrivilegedScheme + std::string("://baz/bar")))); - - std::unique_ptr<RenderProcessHost> extension_host( - extension1_instance->GetProcess()); - EXPECT_EQ(extension1_instance->GetProcess(), - extension2_instance->GetProcess()); - - // Create some WebUI instances and make sure they share a process. - scoped_refptr<SiteInstanceImpl> webui1_instance( - CreateSiteInstance(browser_context.get(), GetWebUIURL(kChromeUIGpuHost))); - policy->GrantWebUIBindings(webui1_instance->GetProcess()->GetID(), - BINDINGS_POLICY_WEB_UI); - - scoped_refptr<SiteInstanceImpl> webui2_instance(CreateSiteInstance( - browser_context.get(), GetWebUIURL(kChromeUIMediaInternalsHost))); - - std::unique_ptr<RenderProcessHost> dom_host(webui1_instance->GetProcess()); - EXPECT_EQ(webui1_instance->GetProcess(), webui2_instance->GetProcess()); - - // Make sure none of differing privilege processes are mixed. - EXPECT_NE(extension1_instance->GetProcess(), webui1_instance->GetProcess()); - - for (size_t i = 0; i < kMaxRendererProcessCount; ++i) { - EXPECT_NE(extension1_instance->GetProcess(), hosts[i].get()); - EXPECT_NE(webui1_instance->GetProcess(), hosts[i].get()); - } - - DrainMessageLoop(); - - // Disable the process limit override. - RenderProcessHost::SetMaxRendererProcessCount(0u); -} - // Test to ensure that HasWrongProcessForURL behaves properly for different // types of URLs. TEST_F(SiteInstanceTest, HasWrongProcessForURL) {
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index ab06c5eb..4887d13 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -16,6 +16,7 @@ #include "base/callback_helpers.h" #include "base/command_line.h" #include "base/location.h" +#include "base/optional.h" #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" #include "base/strings/utf_string_conversions.h" @@ -106,7 +107,7 @@ } } -void OnQuotaManagedOriginDeleted(const GURL& origin, +void OnQuotaManagedOriginDeleted(const url::Origin& origin, blink::mojom::StorageType type, size_t* deletion_task_count, base::OnceClosure callback, @@ -353,15 +354,19 @@ // Most of the operations in this class are done on IO thread. class StoragePartitionImpl::QuotaManagedDataDeletionHelper { public: - QuotaManagedDataDeletionHelper(uint32_t remove_mask, - uint32_t quota_storage_remove_mask, - const GURL& storage_origin, - base::OnceClosure callback) + QuotaManagedDataDeletionHelper( + uint32_t remove_mask, + uint32_t quota_storage_remove_mask, + const base::Optional<url::Origin>& storage_origin, + base::OnceClosure callback) : remove_mask_(remove_mask), quota_storage_remove_mask_(quota_storage_remove_mask), storage_origin_(storage_origin), callback_(std::move(callback)), - task_count_(0) {} + task_count_(0) { + DCHECK(!storage_origin_.has_value() || + !storage_origin_->GetURL().is_empty()); + } void IncrementTaskCountOnIO(); void DecrementTaskCountOnIO(); @@ -379,14 +384,14 @@ special_storage_policy, const StoragePartition::OriginMatcherFunction& origin_matcher, base::OnceClosure callback, - const std::set<GURL>& origins, + const std::set<url::Origin>& origins, blink::mojom::StorageType quota_storage_type); private: // All of these data are accessed on IO thread. uint32_t remove_mask_; uint32_t quota_storage_remove_mask_; - GURL storage_origin_; + base::Optional<url::Origin> storage_origin_; base::OnceClosure callback_; int task_count_; @@ -488,7 +493,10 @@ StoragePartitionImpl::QuotaManagedDataDeletionHelper* helper = new StoragePartitionImpl::QuotaManagedDataDeletionHelper( - remove_mask_, quota_storage_remove_mask_, storage_origin, + remove_mask_, quota_storage_remove_mask_, + storage_origin.is_empty() + ? base::nullopt + : base::make_optional(url::Origin::Create(storage_origin)), std::move(callback)); helper->ClearDataOnIOThread(quota_manager, begin, special_storage_policy, origin_matcher); @@ -1009,7 +1017,7 @@ special_storage_policy, const StoragePartition::OriginMatcherFunction& origin_matcher, base::OnceClosure callback, - const std::set<GURL>& origins, + const std::set<url::Origin>& origins, blink::mojom::StorageType quota_storage_type) { // The QuotaManager manages all storage other than cookies, LocalStorage, // and SessionStorage. This loop wipes out most HTML5 storage for the given @@ -1027,23 +1035,22 @@ size_t* deletion_task_count = new size_t(0u); (*deletion_task_count)++; - for (std::set<GURL>::const_iterator origin = origins.begin(); - origin != origins.end(); ++origin) { + for (const auto& origin : origins) { // TODO(mkwst): Clean this up, it's slow. http://crbug.com/130746 - if (!storage_origin_.is_empty() && origin->GetOrigin() != storage_origin_) + if (storage_origin_.has_value() && origin != *storage_origin_) continue; if (!origin_matcher.is_null() && - !origin_matcher.Run(*origin, special_storage_policy.get())) { + !origin_matcher.Run(origin.GetURL(), special_storage_policy.get())) { continue; } (*deletion_task_count)++; quota_manager->DeleteOriginData( - *origin, quota_storage_type, + origin, quota_storage_type, StoragePartitionImpl::GenerateQuotaClientMask(remove_mask_), - base::BindOnce(&OnQuotaManagedOriginDeleted, origin->GetOrigin(), - quota_storage_type, deletion_task_count, completion)); + base::BindOnce(&OnQuotaManagedOriginDeleted, origin, quota_storage_type, + deletion_task_count, completion)); } (*deletion_task_count)--;
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc index 3f2be88..03a95d8 100644 --- a/content/browser/storage_partition_impl_unittest.cc +++ b/content/browser/storage_partition_impl_unittest.cc
@@ -71,10 +71,12 @@ const char kClearKeyCdmPluginId[] = "application_x-ppapi-clearkey-cdm"; #endif // BUILDFLAG(ENABLE_PLUGINS) -const GURL kOrigin1(kTestOrigin1); -const GURL kOrigin2(kTestOrigin2); -const GURL kOrigin3(kTestOrigin3); -const GURL kOriginDevTools(kTestOriginDevTools); +// TODO(crbug.com/889590): Use helper for url::Origin creation from string. +const url::Origin kOrigin1 = url::Origin::Create(GURL(kTestOrigin1)); +const url::Origin kOrigin2 = url::Origin::Create(GURL(kTestOrigin2)); +const url::Origin kOrigin3 = url::Origin::Create(GURL(kTestOrigin3)); +const url::Origin kOriginDevTools = + url::Origin::Create(GURL(kTestOriginDevTools)); const GURL kResourceURL(kTestURL); const blink::mojom::StorageType kTemporary = @@ -138,7 +140,7 @@ bool ContainsCookie() { get_cookie_success_ = false; cookie_store_->GetCookieListWithOptionsAsync( - kOrigin1, net::CookieOptions(), + kOrigin1.GetURL(), net::CookieOptions(), base::BindOnce(&RemoveCookieTester::GetCookieListCallback, base::Unretained(this))); await_completion_.BlockUntilNotified(); @@ -147,7 +149,7 @@ void AddCookie() { cookie_store_->SetCookieWithOptionsAsync( - kOrigin1, "A=1", net::CookieOptions(), + kOrigin1.GetURL(), "A=1", net::CookieOptions(), base::BindOnce(&RemoveCookieTester::SetCookieCallback, base::Unretained(this))); await_completion_.BlockUntilNotified(); @@ -190,11 +192,11 @@ } // Returns true, if the given origin URL exists. - bool DOMStorageExistsForOrigin(const GURL& origin) { + bool DOMStorageExistsForOrigin(const url::Origin& origin) { GetLocalStorageUsage(); await_completion_.BlockUntilNotified(); for (size_t i = 0; i < infos_.size(); ++i) { - if (origin == infos_[i].origin) + if (origin == url::Origin::Create(infos_[i].origin)) return true; } return false; @@ -215,21 +217,21 @@ base::Time now = base::Time::Now(); data.set_last_modified(now.ToInternalValue()); data.set_size_bytes(16); - mock_data_[CreateMetaDataKey(url::Origin::Create(kOrigin1))] = + mock_data_[CreateMetaDataKey(kOrigin1)] = leveldb::StdStringToUint8Vector(data.SerializeAsString()); - mock_data_[CreateDataKey(url::Origin::Create(kOrigin1))] = {}; + mock_data_[CreateDataKey(kOrigin1)] = {}; base::Time one_day_ago = now - base::TimeDelta::FromDays(1); data.set_last_modified(one_day_ago.ToInternalValue()); - mock_data_[CreateMetaDataKey(url::Origin::Create(kOrigin2))] = + mock_data_[CreateMetaDataKey(kOrigin2)] = leveldb::StdStringToUint8Vector(data.SerializeAsString()); - mock_data_[CreateDataKey(url::Origin::Create(kOrigin2))] = {}; + mock_data_[CreateDataKey(kOrigin2)] = {}; base::Time sixty_days_ago = now - base::TimeDelta::FromDays(60); data.set_last_modified(sixty_days_ago.ToInternalValue()); - mock_data_[CreateMetaDataKey(url::Origin::Create(kOrigin3))] = + mock_data_[CreateMetaDataKey(kOrigin3)] = leveldb::StdStringToUint8Vector(data.SerializeAsString()); - mock_data_[CreateDataKey(url::Origin::Create(kOrigin3))] = {}; + mock_data_[CreateDataKey(kOrigin3)] = {}; } private: @@ -341,18 +343,18 @@ // Create a PluginPrivateFileSystem for ClearKey and add a single file // with a timestamp of 1 day ago. std::string clearkey_fsid = - CreateFileSystem(kClearKeyCdmPluginId, kOrigin1); - clearkey_file_ = CreateFile(kOrigin1, clearkey_fsid, "foo"); + CreateFileSystem(kClearKeyCdmPluginId, kOrigin1.GetURL()); + clearkey_file_ = CreateFile(kOrigin1.GetURL(), clearkey_fsid, "foo"); SetFileTimestamp(clearkey_file_, ten_days_ago); // Create a second PluginPrivateFileSystem for Widevine and add two files // with different times. std::string widevine_fsid = - CreateFileSystem(kWidevineCdmPluginId, kOrigin2); + CreateFileSystem(kWidevineCdmPluginId, kOrigin2.GetURL()); storage::FileSystemURL widevine_file1 = - CreateFile(kOrigin2, widevine_fsid, "bar1"); + CreateFile(kOrigin2.GetURL(), widevine_fsid, "bar1"); storage::FileSystemURL widevine_file2 = - CreateFile(kOrigin2, widevine_fsid, "bar2"); + CreateFile(kOrigin2.GetURL(), widevine_fsid, "bar2"); SetFileTimestamp(widevine_file1, now); SetFileTimestamp(widevine_file2, sixty_days_ago); } @@ -360,7 +362,7 @@ void DeleteClearKeyTestData() { DeleteFile(clearkey_file_); } // Returns true, if the given origin exists in a PluginPrivateFileSystem. - bool DataExistsForOrigin(const GURL& origin) { + bool DataExistsForOrigin(const url::Origin& origin) { AwaitCompletionHelper await_completion; bool data_exists_for_origin = false; filesystem_context_->default_file_task_runner()->PostTask( @@ -508,7 +510,7 @@ // If |origin| exists in the PluginPrivateFileSystem, set // |data_exists_for_origin| to true, false otherwise. void CheckIfDataExistsForOriginOnFileTaskRunner( - const GURL& origin, + const url::Origin& origin, bool* data_exists_for_origin, AwaitCompletionHelper* await_completion) { storage::FileSystemBackend* backend = @@ -520,7 +522,7 @@ std::set<GURL> origins; quota_util->GetOriginsForTypeOnFileTaskRunner( storage::kFileSystemTypePluginPrivate, &origins); - *data_exists_for_origin = origins.find(origin) != origins.end(); + *data_exists_for_origin = origins.find(origin.GetURL()) != origins.end(); // AwaitCompletionHelper and MessageLoop don't work on a // SequencedTaskRunner, so post a task on the IO thread. @@ -800,7 +802,7 @@ void PopulateTestQuotaManagedPersistentData(MockQuotaManager* manager) { manager->AddOrigin(kOrigin2, kPersistent, kClientFile, base::Time()); manager->AddOrigin(kOrigin3, kPersistent, kClientFile, - base::Time::Now() - base::TimeDelta::FromDays(1)); + base::Time::Now() - base::TimeDelta::FromDays(1)); EXPECT_FALSE(manager->OriginHasData(kOrigin1, kPersistent, kClientFile)); EXPECT_TRUE(manager->OriginHasData(kOrigin2, kPersistent, kClientFile)); @@ -810,7 +812,7 @@ void PopulateTestQuotaManagedTemporaryData(MockQuotaManager* manager) { manager->AddOrigin(kOrigin1, kTemporary, kClientFile, base::Time::Now()); manager->AddOrigin(kOrigin3, kTemporary, kClientFile, - base::Time::Now() - base::TimeDelta::FromDays(1)); + base::Time::Now() - base::TimeDelta::FromDays(1)); EXPECT_TRUE(manager->OriginHasData(kOrigin1, kTemporary, kClientFile)); EXPECT_FALSE(manager->OriginHasData(kOrigin2, kTemporary, kClientFile)); @@ -844,18 +846,18 @@ FROM_HERE, base::BindOnce(&ClearQuotaData, partition, &run_loop)); run_loop.Run(); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent, - kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile)); } TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverOnlyTemporary) { @@ -871,18 +873,18 @@ FROM_HERE, base::BindOnce(&ClearQuotaData, partition, &run_loop)); run_loop.Run(); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent, - kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile)); } TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverOnlyPersistent) { @@ -898,18 +900,18 @@ FROM_HERE, base::BindOnce(&ClearQuotaData, partition, &run_loop)); run_loop.Run(); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent, - kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile)); } TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverNeither) { @@ -923,18 +925,18 @@ FROM_HERE, base::BindOnce(&ClearQuotaData, partition, &run_loop)); run_loop.Run(); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent, - kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile)); } TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverSpecificOrigin) { @@ -947,22 +949,22 @@ base::RunLoop run_loop; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&ClearQuotaDataForOrigin, partition, kOrigin1, - base::Time(), &run_loop)); + FROM_HERE, base::BindOnce(&ClearQuotaDataForOrigin, partition, + kOrigin1.GetURL(), base::Time(), &run_loop)); run_loop.Run(); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary, - kClientFile)); - EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent, - kClientFile)); - EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin2, kPersistent, - kClientFile)); - EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kPersistent, - kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile)); + EXPECT_TRUE( + GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile)); + EXPECT_TRUE( + GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile)); + EXPECT_TRUE( + GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile)); } TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForLastHour) { @@ -981,18 +983,18 @@ &run_loop)); run_loop.Run(); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary, - kClientFile)); - EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent, - kClientFile)); - EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin2, kPersistent, - kClientFile)); - EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kPersistent, - kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile)); + EXPECT_TRUE( + GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile)); + EXPECT_TRUE( + GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile)); + EXPECT_TRUE( + GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile)); } TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForLastWeek) { @@ -1010,25 +1012,25 @@ &run_loop)); run_loop.Run(); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent, - kClientFile)); - EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin2, kPersistent, - kClientFile)); - EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kPersistent, - kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile)); + EXPECT_TRUE( + GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile)); + EXPECT_TRUE( + GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile)); } TEST_F(StoragePartitionImplTest, RemoveQuotaManagedUnprotectedOrigins) { // Protect kOrigin1. scoped_refptr<MockSpecialStoragePolicy> mock_policy = new MockSpecialStoragePolicy; - mock_policy->AddProtected(kOrigin1.GetOrigin()); + mock_policy->AddProtected(kOrigin1.GetURL()); PopulateTestQuotaManagedData(GetMockManager()); @@ -1042,29 +1044,29 @@ base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&ClearQuotaDataWithOriginMatcher, partition, GURL(), - base::Bind(&DoesOriginMatchForUnprotectedWeb), + base::BindRepeating(&DoesOriginMatchForUnprotectedWeb), base::Time(), &run_loop)); run_loop.Run(); - EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin1, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent, - kClientFile)); + EXPECT_TRUE( + GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile)); } TEST_F(StoragePartitionImplTest, RemoveQuotaManagedProtectedSpecificOrigin) { // Protect kOrigin1. scoped_refptr<MockSpecialStoragePolicy> mock_policy = new MockSpecialStoragePolicy; - mock_policy->AddProtected(kOrigin1.GetOrigin()); + mock_policy->AddProtected(kOrigin1.GetURL()); PopulateTestQuotaManagedData(GetMockManager()); @@ -1078,30 +1080,31 @@ base::RunLoop run_loop; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::BindOnce(&ClearQuotaDataWithOriginMatcher, partition, kOrigin1, - base::Bind(&DoesOriginMatchForUnprotectedWeb), + base::BindOnce(&ClearQuotaDataWithOriginMatcher, partition, + kOrigin1.GetURL(), + base::BindRepeating(&DoesOriginMatchForUnprotectedWeb), base::Time(), &run_loop)); run_loop.Run(); - EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin1, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary, - kClientFile)); - EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent, - kClientFile)); - EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin2, kPersistent, - kClientFile)); - EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kPersistent, - kClientFile)); + EXPECT_TRUE( + GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile)); + EXPECT_TRUE( + GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile)); + EXPECT_TRUE( + GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile)); + EXPECT_TRUE( + GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile)); } TEST_F(StoragePartitionImplTest, RemoveQuotaManagedProtectedOrigins) { // Protect kOrigin1. scoped_refptr<MockSpecialStoragePolicy> mock_policy = new MockSpecialStoragePolicy; - mock_policy->AddProtected(kOrigin1.GetOrigin()); + mock_policy->AddProtected(kOrigin1.GetURL()); PopulateTestQuotaManagedData(GetMockManager()); @@ -1114,24 +1117,24 @@ partition->OverrideSpecialStoragePolicyForTesting(mock_policy.get()); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::BindOnce( - &ClearQuotaDataWithOriginMatcher, partition, GURL(), - base::Bind(&DoesOriginMatchForBothProtectedAndUnprotectedWeb), - base::Time(), &run_loop)); + base::BindOnce(&ClearQuotaDataWithOriginMatcher, partition, GURL(), + base::BindRepeating( + &DoesOriginMatchForBothProtectedAndUnprotectedWeb), + base::Time(), &run_loop)); run_loop.Run(); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent, - kClientFile)); - EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent, - kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile)); + EXPECT_FALSE( + GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile)); } TEST_F(StoragePartitionImplTest, RemoveQuotaManagedIgnoreDevTools) { @@ -1143,16 +1146,17 @@ partition->OverrideQuotaManagerForTesting( GetMockManager()); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&ClearQuotaDataWithOriginMatcher, partition, - GURL(), base::Bind(&DoesOriginMatchUnprotected), - base::Time(), &run_loop)); + FROM_HERE, + base::BindOnce(&ClearQuotaDataWithOriginMatcher, partition, GURL(), + base::BindRepeating(&DoesOriginMatchUnprotected), + base::Time(), &run_loop)); run_loop.Run(); // Check that devtools data isn't removed. EXPECT_TRUE(GetMockManager()->OriginHasData(kOriginDevTools, kTemporary, - kClientFile)); + kClientFile)); EXPECT_TRUE(GetMockManager()->OriginHasData(kOriginDevTools, kPersistent, - kClientFile)); + kClientFile)); } TEST_F(StoragePartitionImplTest, RemoveCookieForever) { @@ -1216,42 +1220,7 @@ // Protect kOrigin1. scoped_refptr<MockSpecialStoragePolicy> mock_policy = new MockSpecialStoragePolicy; - mock_policy->AddProtected(kOrigin1.GetOrigin()); - - RemoveLocalStorageTester tester(browser_context()); - - tester.AddDOMStorageTestData(); - EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin1)); - EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin2)); - EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin3)); - - StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( - BrowserContext::GetDefaultStoragePartition(browser_context())); - partition->OverrideSpecialStoragePolicyForTesting(mock_policy.get()); - - base::RunLoop run_loop; - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&ClearStuff, - StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE, - partition, base::Time(), base::Time::Max(), - base::Bind(&DoesOriginMatchForUnprotectedWeb), &run_loop)); - run_loop.Run(); - // ClearData only guarantees that tasks to delete data are scheduled when its - // callback is invoked. It doesn't guarantee data has actually been cleared. - // So run all scheduled tasks to make sure data is cleared. - base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin1)); - EXPECT_FALSE(tester.DOMStorageExistsForOrigin(kOrigin2)); - EXPECT_FALSE(tester.DOMStorageExistsForOrigin(kOrigin3)); -} - -TEST_F(StoragePartitionImplTest, RemoveProtectedLocalStorageForever) { - // Protect kOrigin1. - scoped_refptr<MockSpecialStoragePolicy> mock_policy = - new MockSpecialStoragePolicy; - mock_policy->AddProtected(kOrigin1.GetOrigin()); + mock_policy->AddProtected(kOrigin1.GetURL()); RemoveLocalStorageTester tester(browser_context()); @@ -1270,8 +1239,44 @@ base::BindOnce( &ClearStuff, StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE, partition, base::Time(), base::Time::Max(), - base::Bind(&DoesOriginMatchForBothProtectedAndUnprotectedWeb), - &run_loop)); + base::BindRepeating(&DoesOriginMatchForUnprotectedWeb), &run_loop)); + run_loop.Run(); + // ClearData only guarantees that tasks to delete data are scheduled when its + // callback is invoked. It doesn't guarantee data has actually been cleared. + // So run all scheduled tasks to make sure data is cleared. + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin1)); + EXPECT_FALSE(tester.DOMStorageExistsForOrigin(kOrigin2)); + EXPECT_FALSE(tester.DOMStorageExistsForOrigin(kOrigin3)); +} + +TEST_F(StoragePartitionImplTest, RemoveProtectedLocalStorageForever) { + // Protect kOrigin1. + scoped_refptr<MockSpecialStoragePolicy> mock_policy = + new MockSpecialStoragePolicy; + mock_policy->AddProtected(kOrigin1.GetURL()); + + RemoveLocalStorageTester tester(browser_context()); + + tester.AddDOMStorageTestData(); + EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin1)); + EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin2)); + EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin3)); + + StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( + BrowserContext::GetDefaultStoragePartition(browser_context())); + partition->OverrideSpecialStoragePolicyForTesting(mock_policy.get()); + + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&ClearStuff, + StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE, + partition, base::Time(), base::Time::Max(), + base::BindRepeating( + &DoesOriginMatchForBothProtectedAndUnprotectedWeb), + &run_loop)); run_loop.Run(); // ClearData only guarantees that tasks to delete data are scheduled when its // callback is invoked. It doesn't guarantee data has actually been cleared. @@ -1300,11 +1305,12 @@ base::RunLoop run_loop; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::BindOnce( - &ClearStuff, StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE, - partition, a_week_ago, base::Time::Max(), - base::Bind(&DoesOriginMatchForBothProtectedAndUnprotectedWeb), - &run_loop)); + base::BindOnce(&ClearStuff, + StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE, + partition, a_week_ago, base::Time::Max(), + base::BindRepeating( + &DoesOriginMatchForBothProtectedAndUnprotectedWeb), + &run_loop)); run_loop.Run(); // ClearData only guarantees that tasks to delete data are scheduled when its // callback is invoked. It doesn't guarantee data has actually been cleared. @@ -1329,7 +1335,7 @@ RemoveCodeCacheTester tester(partition->GetGeneratedCodeCacheContext()); - url::Origin origin = url::Origin::Create(kOrigin1); + url::Origin origin = kOrigin1; std::string data("SomeData"); tester.AddEntry(kResourceURL, origin, data); EXPECT_TRUE(tester.ContainsEntry(kResourceURL, origin)); @@ -1436,8 +1442,9 @@ base::RunLoop run_loop; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&ClearPluginPrivateData, partition, kOrigin1, - base::Time(), base::Time::Max(), &run_loop)); + FROM_HERE, + base::BindOnce(&ClearPluginPrivateData, partition, kOrigin1.GetURL(), + base::Time(), base::Time::Max(), &run_loop)); run_loop.Run(); // Only Origin1 should be deleted.
diff --git a/content/browser/tracing/background_tracing_manager_impl.cc b/content/browser/tracing/background_tracing_manager_impl.cc index e71ddb1..a1990c56 100644 --- a/content/browser/tracing/background_tracing_manager_impl.cc +++ b/content/browser/tracing/background_tracing_manager_impl.cc
@@ -655,7 +655,7 @@ record_mode); case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_GPU: return TraceConfig( - "benchmark,toplevel,gpu,base,mojom," + "benchmark,toplevel,gpu,base,mojom,ipc," "disabled-by-default-system_stats,disabled-by-default-cpu_profiler", record_mode); case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_IPC:
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index d545411..169b1d8 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -6229,16 +6229,6 @@ return java_interfaces_.get(); } -#elif defined(OS_MACOSX) - -void WebContentsImpl::SetAllowOtherViews(bool allow) { - view_->SetAllowOtherViews(allow); -} - -bool WebContentsImpl::GetAllowOtherViews() { - return view_->GetAllowOtherViews(); -} - #endif bool WebContentsImpl::CompletedFirstVisuallyNonEmptyPaint() const {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 511f9db..44f9ba81 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -464,9 +464,6 @@ void ActivateNearestFindResult(float x, float y) override; void RequestFindMatchRects(int current_version) override; service_manager::InterfaceProvider* GetJavaInterfaces() override; -#elif defined(OS_MACOSX) - void SetAllowOtherViews(bool allow) override; - bool GetAllowOtherViews() override; #endif bool HasRecentInteractiveInputEvent() const override;
diff --git a/content/browser/web_contents/web_contents_view.h b/content/browser/web_contents/web_contents_view.h index 281a3d6..5426d60 100644 --- a/content/browser/web_contents/web_contents_view.h +++ b/content/browser/web_contents/web_contents_view.h
@@ -123,13 +123,6 @@ virtual void SetOverscrollControllerEnabled(bool enabled) = 0; #if defined(OS_MACOSX) - // Allowing other views disables optimizations which assume that only a single - // WebContents is present. - virtual void SetAllowOtherViews(bool allow) = 0; - - // Returns true if other views are allowed, false otherwise. - virtual bool GetAllowOtherViews() const = 0; - // If we close the tab while a UI control is in an event-tracking // loop, the control may message freed objects and crash. // WebContents::Close() calls IsEventTracking(), and if it returns
diff --git a/content/browser/web_contents/web_contents_view_child_frame.cc b/content/browser/web_contents/web_contents_view_child_frame.cc index 015812b..7b339bf 100644 --- a/content/browser/web_contents/web_contents_view_child_frame.cc +++ b/content/browser/web_contents/web_contents_view_child_frame.cc
@@ -117,15 +117,6 @@ void WebContentsViewChildFrame::CloseTabAfterEventTracking() { NOTREACHED(); } - -void WebContentsViewChildFrame::SetAllowOtherViews(bool allow) { - NOTREACHED(); -} - -bool WebContentsViewChildFrame::GetAllowOtherViews() const { - NOTREACHED(); - return false; -} #endif void WebContentsViewChildFrame::RestoreFocus() {
diff --git a/content/browser/web_contents/web_contents_view_child_frame.h b/content/browser/web_contents/web_contents_view_child_frame.h index 7f7107e..e82cced 100644 --- a/content/browser/web_contents/web_contents_view_child_frame.h +++ b/content/browser/web_contents/web_contents_view_child_frame.h
@@ -50,8 +50,6 @@ RenderViewHost* new_host) override; void SetOverscrollControllerEnabled(bool enabled) override; #if defined(OS_MACOSX) - void SetAllowOtherViews(bool allow) override; - bool GetAllowOtherViews() const override; bool IsEventTracking() const override; void CloseTabAfterEventTracking() override; #endif
diff --git a/content/browser/web_contents/web_contents_view_guest.cc b/content/browser/web_contents/web_contents_view_guest.cc index 65c709c..5de4d7c 100644 --- a/content/browser/web_contents/web_contents_view_guest.cc +++ b/content/browser/web_contents/web_contents_view_guest.cc
@@ -117,16 +117,6 @@ return gfx::Rect(size_); } -#if defined(OS_MACOSX) -void WebContentsViewGuest::SetAllowOtherViews(bool allow) { - platform_view_->SetAllowOtherViews(allow); -} - -bool WebContentsViewGuest::GetAllowOtherViews() const { - return platform_view_->GetAllowOtherViews(); -} -#endif - void WebContentsViewGuest::CreateView(const gfx::Size& initial_size, gfx::NativeView context) { platform_view_->CreateView(initial_size, context);
diff --git a/content/browser/web_contents/web_contents_view_guest.h b/content/browser/web_contents/web_contents_view_guest.h index b9691d9..1f0e6616 100644 --- a/content/browser/web_contents/web_contents_view_guest.h +++ b/content/browser/web_contents/web_contents_view_guest.h
@@ -68,8 +68,6 @@ RenderViewHost* new_host) override; void SetOverscrollControllerEnabled(bool enabled) override; #if defined(OS_MACOSX) - void SetAllowOtherViews(bool allow) override; - bool GetAllowOtherViews() const override; bool IsEventTracking() const override; void CloseTabAfterEventTracking() override; #endif
diff --git a/content/browser/web_contents/web_contents_view_mac.h b/content/browser/web_contents/web_contents_view_mac.h index 21b40228..0b37270 100644 --- a/content/browser/web_contents/web_contents_view_mac.h +++ b/content/browser/web_contents/web_contents_view_mac.h
@@ -91,8 +91,6 @@ void FocusThroughTabTraversal(bool reverse) override; DropData* GetDropData() const override; gfx::Rect GetViewBounds() const override; - void SetAllowOtherViews(bool allow) override; - bool GetAllowOtherViews() const override; void CreateView(const gfx::Size& initial_size, gfx::NativeView context) override; RenderWidgetHostViewBase* CreateViewForWidget( @@ -165,9 +163,6 @@ // Our optional delegate. std::unique_ptr<WebContentsViewDelegate> delegate_; - // Whether to allow other views. - bool allow_other_views_; - // This contains all RenderWidgetHostViewMacs that have been added as child // NSViews to this NSView. Note that this list may contain RWHVMacs besides // just |web_contents_->GetRenderWidgetHostView()|. The only time that the
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm index cb6b58f..325c9c8 100644 --- a/content/browser/web_contents/web_contents_view_mac.mm +++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -105,10 +105,7 @@ WebContentsViewMac::WebContentsViewMac(WebContentsImpl* web_contents, WebContentsViewDelegate* delegate) - : web_contents_(web_contents), - delegate_(delegate), - allow_other_views_(false) { -} + : web_contents_(web_contents), delegate_(delegate) {} WebContentsViewMac::~WebContentsViewMac() { // This handles the case where a renderer close call was deferred @@ -322,21 +319,6 @@ return gfx::ScreenRectFromNSRect(window_bounds); } -void WebContentsViewMac::SetAllowOtherViews(bool allow) { - if (allow_other_views_ == allow) - return; - - allow_other_views_ = allow; - RenderWidgetHostViewMac* view = static_cast<RenderWidgetHostViewMac*>( - web_contents_->GetRenderWidgetHostView()); - if (view) - view->SetAllowPauseForResizeOrRepaint(!allow_other_views_); -} - -bool WebContentsViewMac::GetAllowOtherViews() const { - return allow_other_views_; -} - void WebContentsViewMac::CreateView( const gfx::Size& initial_size, gfx::NativeView context) { WebContentsViewCocoa* view = @@ -369,7 +351,6 @@ view->SetDelegate(rw_delegate.get()); } - view->SetAllowPauseForResizeOrRepaint(!allow_other_views_); // Add the RenderWidgetHostView to the ui::Layer heirarchy. child_views_.push_back(view->GetWeakPtr());
diff --git a/content/common/common_param_traits_unittest.cc b/content/common/common_param_traits_unittest.cc index 7c395a8..cb95c23f 100644 --- a/content/common/common_param_traits_unittest.cc +++ b/content/common/common_param_traits_unittest.cc
@@ -173,8 +173,6 @@ in.pkp_bypassed = true; in.client_cert_sent = true; in.channel_id_sent = true; - in.token_binding_negotiated = true; - in.token_binding_key_param = net::TB_PARAM_ECDSAP256; in.handshake_type = net::SSLInfo::HANDSHAKE_FULL; const net::SHA256HashValue kCertPublicKeyHashValue = {{0x01, 0x02}}; in.public_key_hashes.push_back(net::HashValue(kCertPublicKeyHashValue)); @@ -218,8 +216,6 @@ ASSERT_EQ(in.pkp_bypassed, out.pkp_bypassed); ASSERT_EQ(in.client_cert_sent, out.client_cert_sent); ASSERT_EQ(in.channel_id_sent, out.channel_id_sent); - ASSERT_EQ(in.token_binding_negotiated, out.token_binding_negotiated); - ASSERT_EQ(in.token_binding_key_param, out.token_binding_key_param); ASSERT_EQ(in.handshake_type, out.handshake_type); ASSERT_EQ(in.public_key_hashes, out.public_key_hashes); ASSERT_EQ(in.pinning_failure_log, out.pinning_failure_log);
diff --git a/content/common/service_worker/service_worker_loader_helpers.cc b/content/common/service_worker/service_worker_loader_helpers.cc index 4b365157..d422ca9 100644 --- a/content/common/service_worker/service_worker_loader_helpers.cc +++ b/content/common/service_worker/service_worker_loader_helpers.cc
@@ -157,8 +157,7 @@ base::Optional<net::RedirectInfo> ServiceWorkerLoaderHelpers::ComputeRedirectInfo( const network::ResourceRequest& original_request, - const network::ResourceResponseHead& response_head, - bool token_binding_negotiated) { + const network::ResourceResponseHead& response_head) { std::string new_location; if (!response_head.headers->IsRedirect(&new_location)) return base::nullopt; @@ -175,8 +174,7 @@ original_request.referrer_policy, network::ComputeReferrer(original_request.referrer), response_head.headers.get(), response_head.headers->response_code(), - original_request.url.Resolve(new_location), false, - token_binding_negotiated); + original_request.url.Resolve(new_location), false); } int ServiceWorkerLoaderHelpers::ReadBlobResponseBody(
diff --git a/content/common/service_worker/service_worker_loader_helpers.h b/content/common/service_worker/service_worker_loader_helpers.h index 3026f7a8..60da247c 100644 --- a/content/common/service_worker/service_worker_loader_helpers.h +++ b/content/common/service_worker/service_worker_loader_helpers.h
@@ -38,8 +38,7 @@ // Otherwise returns base::nullopt. static base::Optional<net::RedirectInfo> ComputeRedirectInfo( const network::ResourceRequest& original_request, - const network::ResourceResponseHead& response_head, - bool token_binding_negotiated); + const network::ResourceResponseHead& response_head); // Reads |blob| using the range in |headers| (if any), writing into // |handle_out|. Calls |on_blob_read_complete| when done or if an error
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h index 1b12b44..f26f7e5 100644 --- a/content/public/browser/web_contents.h +++ b/content/public/browser/web_contents.h
@@ -912,13 +912,6 @@ // scoped to this WebContents. This provides access to interfaces implemented // in Java in the browser process to C++ code in the browser process. virtual service_manager::InterfaceProvider* GetJavaInterfaces() = 0; -#elif defined(OS_MACOSX) - // Allowing other views disables optimizations which assume that only a single - // WebContents is present. - virtual void SetAllowOtherViews(bool allow) = 0; - - // Returns true if other views are allowed, false otherwise. - virtual bool GetAllowOtherViews() = 0; #endif // OS_ANDROID // Returns true if the WebContents has completed its first meaningful paint
diff --git a/content/public/common/common_param_traits.cc b/content/public/common/common_param_traits.cc index 539c53e..1d92adb8 100644 --- a/content/public/common/common_param_traits.cc +++ b/content/public/common/common_param_traits.cc
@@ -36,6 +36,24 @@ l->append(")"); } +void ParamTraits<ui::AXTreeID>::Write(base::Pickle* m, const param_type& p) { + WriteParam(m, p.ToString()); +} + +bool ParamTraits<ui::AXTreeID>::Read(const base::Pickle* m, + base::PickleIterator* iter, + param_type* r) { + std::string value; + if (!ReadParam(m, iter, &value)) + return false; + *r = ui::AXTreeID::FromString(value); + return true; +} + +void ParamTraits<ui::AXTreeID>::Log(const param_type& p, std::string* l) { + l->append("<ui::AXTreeID>"); +} + } // namespace IPC // Generate param traits write methods.
diff --git a/content/public/common/common_param_traits.h b/content/public/common/common_param_traits.h index 366da86..5c9f82f 100644 --- a/content/public/common/common_param_traits.h +++ b/content/public/common/common_param_traits.h
@@ -23,6 +23,7 @@ #include "content/common/content_export.h" #include "content/public/common/common_param_traits_macros.h" #include "ipc/ipc_message_utils.h" +#include "ui/accessibility/ax_tree_id.h" #include "ui/gfx/native_widget_types.h" #include "ui/surface/transport_dib.h" #include "url/ipc/url_param_traits.h" @@ -80,6 +81,16 @@ } }; +template <> +struct CONTENT_EXPORT ParamTraits<ui::AXTreeID> { + typedef ui::AXTreeID param_type; + static void Write(base::Pickle* m, const param_type& p); + static bool Read(const base::Pickle* m, + base::PickleIterator* iter, + param_type* r); + static void Log(const param_type& p, std::string* l); +}; + } // namespace IPC #endif // CONTENT_PUBLIC_COMMON_COMMON_PARAM_TRAITS_H_
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.cc b/content/renderer/service_worker/service_worker_subresource_loader.cc index 0b8cfb84..d3346e3 100644 --- a/content/renderer/service_worker/service_worker_subresource_loader.cc +++ b/content/renderer/service_worker/service_worker_subresource_loader.cc
@@ -438,7 +438,7 @@ // Handle a redirect response. ComputeRedirectInfo returns non-null redirect // info if the given response is a redirect. redirect_info_ = ServiceWorkerLoaderHelpers::ComputeRedirectInfo( - resource_request_, response_head_, false /* token_binding_negotiated */); + resource_request_, response_head_); if (redirect_info_) { if (redirect_limit_-- == 0) { CommitCompleted(net::ERR_TOO_MANY_REDIRECTS);
diff --git a/content/test/data/accessibility/aria/label-with-selected-option-expected-blink.txt b/content/test/data/accessibility/aria/label-with-selected-option-expected-blink.txt new file mode 100644 index 0000000..6af34113 --- /dev/null +++ b/content/test/data/accessibility/aria/label-with-selected-option-expected-blink.txt
@@ -0,0 +1,9 @@ +rootWebArea +++checkBox name='Test 1: Flash the screen 2 times.' checkedState=false +++checkBox name='Test 2: Flash the screen 2 times.' checkedState=false +++textField +++checkBox name='Test 3: Flash the screen two times.' checkedState=false +++checkBox name='Test 4: Flash the screen two times.' checkedState=false +++textField +++checkBox name='Test 5: Flash the screen two times.' checkedState=false +++comboBoxMenuButton name='two'
diff --git a/content/test/data/accessibility/aria/label-with-selected-option.html b/content/test/data/accessibility/aria/label-with-selected-option.html new file mode 100644 index 0000000..638d24c5 --- /dev/null +++ b/content/test/data/accessibility/aria/label-with-selected-option.html
@@ -0,0 +1,67 @@ +<html> +<body> + <div> + <input type="checkbox" id="test1" /> + <label for="test1">Test 1: Flash the screen + <ul role="listbox" style="list-style-type: none;"> + <li role="option" aria-selected="false">1</li> + <li role="option" aria-selected="true">2</li> + <li role="option">3</li> + </ul> + times. + </label> + </div> + <div> + <input type="checkbox" id="test2" /> + <label for="test2">Test 2: Flash the screen + <div role="combobox"> + <div role="textbox"></div> + <ul role="listbox" style="list-style-type: none;"> + <li role="option" aria-selected="false">1</li> + <li role="option" aria-selected="true">2</li> + <li role="option" >3</li> + </ul> + </div> + times. + </label> + </div> + <div> + <input type="checkbox" id="test3" /> + <label for="test3">Test 3: Flash the screen + <ul role="listbox" style="list-style-type: none;"> + <li role="option" aria-selected="false">1</li> + <li role="option" aria-selected="true" aria-label="two">2</li> + <li role="option">3</li> + </ul> + times. + </label> + </div> + <div> + <input type="checkbox" id="test4" /> + <label for="test4">Test 4: Flash the screen + <div role="combobox"> + <div role="textbox"></div> + <ul role="listbox" style="list-style-type: none;"> + <li role="option" aria-selected="false">1</li> + <li role="option" aria-selected="true" aria-label="two">2</li> + <li role="option">3</li> + </ul> + </div> + times. + </label> + </div> + <div> + <input type="checkbox" id="test5" /> + <label for="test5">Test 5: Flash the screen + <div role="combobox" aria-haspopup="true" tabindex="0"> + <ul role="listbox" style="list-style-type: none;"> + <li role="option" aria-selected="false">1</li> + <li role="option" aria-selected="true" aria-label="two">2</li> + <li role="option">3</li> + </ul> + </div> + times. + </label> + </div> +</body> +</html>
diff --git a/content/test/data/accessibility/html/label-with-selected-option-expected-blink.txt b/content/test/data/accessibility/html/label-with-selected-option-expected-blink.txt new file mode 100644 index 0000000..a9906a5b --- /dev/null +++ b/content/test/data/accessibility/html/label-with-selected-option-expected-blink.txt
@@ -0,0 +1,33 @@ +rootWebArea +++genericContainer +++++checkBox name='Test 1: Flash the screen 2 times.' checkedState=false +++++popUpButton collapsed value='2' +++++++menuListPopup invisible +++++++++menuListOption invisible name='1' selected=false +++++++++menuListOption name='2' selected=true +++++++++menuListOption invisible name='3' selected=false +++genericContainer +++++checkBox name='Test 2: Flash the screen 2 times.' checkedState=false +++++listBox activedescendantId=listBoxOption +++++++listBoxOption name='1' selected=false +++++++listBoxOption name='2' selected=true +++++++listBoxOption name='3' selected=false +++genericContainer +++++checkBox name='Test 3: Flash the screen two times.' checkedState=false +++++popUpButton collapsed value='two' +++++++menuListPopup invisible +++++++++menuListOption invisible name='1' selected=false +++++++++menuListOption name='two' selected=true +++++++++menuListOption invisible name='3' selected=false +++genericContainer +++++checkBox name='Test 4: Flash the screen two times.' checkedState=false +++++listBox activedescendantId=listBoxOption +++++++listBoxOption name='1' selected=false +++++++listBoxOption name='two' selected=true +++++++listBoxOption name='3' selected=false +++genericContainer +++++checkBox name='Test 5: Flash the screen two 3 times.' checkedState=false +++++listBox multiselectable activedescendantId=listBoxOption +++++++listBoxOption name='1' selected=false +++++++listBoxOption name='two' selected=true +++++++listBoxOption name='3' selected=true
diff --git a/content/test/data/accessibility/html/label-with-selected-option.html b/content/test/data/accessibility/html/label-with-selected-option.html new file mode 100644 index 0000000..ca3696e9 --- /dev/null +++ b/content/test/data/accessibility/html/label-with-selected-option.html
@@ -0,0 +1,59 @@ +<html> +<body> + <div> + <input type="checkbox" id="test1" /> + <label for="test1" >Test 1: Flash the screen + <select size="1"> + <option>1</option> + <option selected>2</option> + <option>3</option> + </select> + times. + </label> + </div> + <div> + <input type="checkbox" id="test2" /> + <label for="test2">Test 2: Flash the screen + <select size="3"> + <option>1</option> + <option selected>2</option> + <option>3</option> + </select> + times. + </label> + </div> + <div> + <input type="checkbox" id="test3" /> + <label for="test3">Test 3: Flash the screen + <select size="1"> + <option>1</option> + <option selected aria-label="two">2</option> + <option>3</option> + </select> + times. + </label> + </div> + <div> + <input type="checkbox" id="test4" /> + <label for="test4">Test 4: Flash the screen + <select size="3"> + <option>1</option> + <option selected aria-label="two">2</option> + <option>3</option> + </select> + times. + </label> + </div> + <div> + <input type="checkbox" id="test5" /> + <label for="test5">Test 5: Flash the screen + <select size="3" multiple> + <option>1</option> + <option selected aria-label="two">2</option> + <option selected>3</option> + </select> + times. + </label> + </div> +</body> +</html>
diff --git a/extensions/browser/api/alarms/alarms_api_unittest.cc b/extensions/browser/api/alarms/alarms_api_unittest.cc index c15047fe..efe47f5 100644 --- a/extensions/browser/api/alarms/alarms_api_unittest.cc +++ b/extensions/browser/api/alarms/alarms_api_unittest.cc
@@ -642,7 +642,7 @@ // Create a new extension, which is packed, and has a granularity of 1 minute. // CreateAlarm() uses extension_, so keep a ref of the old one around, and // repopulate extension_. - scoped_refptr<Extension> extension2(extension_ref()); + scoped_refptr<const Extension> extension2(extension_ref()); set_extension( utils::CreateEmptyExtensionWithLocation(extensions::Manifest::INTERNAL));
diff --git a/extensions/browser/api/messaging/message_property_provider.cc b/extensions/browser/api/messaging/message_property_provider.cc index e7ce840..d49c7f2 100644 --- a/extensions/browser/api/messaging/message_property_provider.cc +++ b/extensions/browser/api/messaging/message_property_provider.cc
@@ -70,8 +70,7 @@ net::CompletionCallback net_completion_callback = base::Bind(&MessagePropertyProvider::GotChannelID, original_task_runner, base::Owned(output), reply); - if (!network_params->enable_token_binding && - !network_params->enable_channel_id) { + if (!network_params->enable_channel_id) { GotChannelID(original_task_runner, output, reply, net::ERR_FILE_NOT_FOUND); return; }
diff --git a/extensions/browser/api_unittest.h b/extensions/browser/api_unittest.h index 485bf98..72c71f8 100644 --- a/extensions/browser/api_unittest.h +++ b/extensions/browser/api_unittest.h
@@ -39,8 +39,8 @@ content::WebContents* contents() { return contents_.get(); } const Extension* extension() const { return extension_.get(); } - scoped_refptr<Extension> extension_ref() { return extension_; } - void set_extension(scoped_refptr<Extension> extension) { + scoped_refptr<const Extension> extension_ref() { return extension_; } + void set_extension(scoped_refptr<const Extension> extension) { extension_ = extension; } @@ -92,7 +92,7 @@ std::unique_ptr<content::WebContents> contents_; // The Extension used when running API function calls. - scoped_refptr<Extension> extension_; + scoped_refptr<const Extension> extension_; }; } // namespace extensions
diff --git a/headless/test/test_network_interceptor.cc b/headless/test/test_network_interceptor.cc index 4112fdd..e8a23e6 100644 --- a/headless/test/test_network_interceptor.cc +++ b/headless/test/test_network_interceptor.cc
@@ -54,8 +54,7 @@ UPDATE_FIRST_PARTY_URL_ON_REDIRECT, url_request_.referrer_policy, url_request_.referrer.spec(), response_->headers.get(), response_->headers->response_code(), - url_.Resolve(location), false /* token_binding_negotiated */, - false /* insecure_scheme_was_upgraded */, true); + url_.Resolve(location), false /* insecure_scheme_was_upgraded */, true); network::ResourceResponseHead head; head.request_time = base::Time::Now(); head.response_time = base::Time::Now();
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg index 2734cfd..416aedb3 100644 --- a/infra/config/global/cr-buildbucket.cfg +++ b/infra/config/global/cr-buildbucket.cfg
@@ -1592,6 +1592,11 @@ mixins: "linux" } builders { + name: "ToTAndroidOfficial" + mixins: "clang-ci" + mixins: "linux" + } + builders { name: "ToTLinux" mixins: "clang-ci" mixins: "linux"
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg index 68f1c16..576f3c2 100644 --- a/infra/config/global/luci-milo.cfg +++ b/infra/config/global/luci-milo.cfg
@@ -1926,6 +1926,11 @@ short_name: "cfi" } builders { + name: "buildbucket/luci.chromium.ci/ToTAndroidOfficial" + category: "ToT Android" + short_name: "off" + } + builders { name: "buildbot/chromium.clang/ToTMac" name: "buildbucket/luci.chromium.ci/ToTMac" category: "ToT Mac" @@ -2149,6 +2154,11 @@ short_name: "cfi" } builders { + name: "buildbucket/luci.chromium.ci/ToTAndroidOfficial" + category: "ToT Android" + short_name: "off" + } + builders { name: "buildbucket/luci.chromium.ci/ToTMac" category: "ToT Mac" short_name: "rel"
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg index 651cbab9..71ff0cc8 100644 --- a/infra/config/global/luci-scheduler.cfg +++ b/infra/config/global/luci-scheduler.cfg
@@ -214,6 +214,7 @@ triggers: "ToTAndroid64" triggers: "ToTAndroidASan" triggers: "ToTAndroidCFI" + triggers: "ToTAndroidOfficial" triggers: "ToTLinux (dbg)" triggers: "ToTLinux" triggers: "ToTLinuxASan" @@ -4272,6 +4273,16 @@ } job { + id: "ToTAndroidOfficial" + acl_sets: "default" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "ToTAndroidOfficial" + } +} + +job { id: "ToTLinux" acl_sets: "default" buildbucket {
diff --git a/infra/config/global/tricium-prod.cfg b/infra/config/global/tricium-prod.cfg index cde7591..a19cc2e 100644 --- a/infra/config/global/tricium-prod.cfg +++ b/infra/config/global/tricium-prod.cfg
@@ -16,6 +16,19 @@ platform: UBUNTU } +selections { + function: "Pylint" + platform: UBUNTU + configs { + name: "disable" + value: "all" + } + configs { + name: "enable" + value: "syntax-error,unused-variable,undefined-variable,unused-import" + } +} + repos { gerrit_project { host: "chromium-review.googlesource.com"
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn index fe7f78e7..f4e2d23 100644 --- a/ios/chrome/app/BUILD.gn +++ b/ios/chrome/app/BUILD.gn
@@ -286,7 +286,20 @@ bundle_deps = [ "//ios/chrome/app/resources" ] if (!is_chrome_branded || ios_chrome_app_variants == []) { + assert(ios_application_icons_target != "", + "ios_application_icons_target must be defined.") bundle_deps += [ ios_application_icons_target ] + + if (ios_enable_firebase_sdk) { + assert(ios_firebase_resources_target != "", + "ios_firebase_resources_target must be defined if Firebase SDK " + + "is enabled.") + + # Empty list assigned to bundle_deps to indicate that this is an + # intentional override of bundle_deps. + bundle_deps = [] + bundle_deps = [ ios_firebase_resources_target ] + } } else { variants = ios_chrome_app_variants }
diff --git a/ios/third_party/firebase/BUILD.gn b/ios/third_party/firebase/BUILD.gn index e947febe..9fa73ea2 100644 --- a/ios/third_party/firebase/BUILD.gn +++ b/ios/third_party/firebase/BUILD.gn
@@ -2,13 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//ios/third_party/firebase/firebase.gni") - source_set("firebase") { - assert( - ios_firebase_resources_target != "", - "ios_firebase_resources_target must be defined if Firebase SDK is enabled.") - # From gn documentation: # https://chromium.googlesource.com/chromium/src/+/master/tools/gn/docs/reference.md#ldflags # "ldflags are NOT pushed to dependents, so applying ldflags to source sets @@ -19,9 +13,6 @@ # This source_set must be specified as a direct deps of an ios_app_bundle # target for ldflags specified in :firebase_config to be applied. public_configs = [ ":firebase_config" ] - deps = [ - ios_firebase_resources_target, - ] } config("firebase_config") {
diff --git a/ios/web_view/internal/signin/ios_web_view_signin_client.h b/ios/web_view/internal/signin/ios_web_view_signin_client.h index f5fc8bb..6000bc3 100644 --- a/ios/web_view/internal/signin/ios_web_view_signin_client.h +++ b/ios/web_view/internal/signin/ios_web_view_signin_client.h
@@ -49,7 +49,7 @@ void RemoveContentSettingsObserver( content_settings::Observer* observer) override; void PreSignOut( - const base::RepeatingClosure& sign_out, + base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached, signin_metrics::ProfileSignout signout_source_metric) override; void DelayNetworkCall(const base::Closure& callback) override; std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcher(
diff --git a/ios/web_view/internal/signin/ios_web_view_signin_client.mm b/ios/web_view/internal/signin/ios_web_view_signin_client.mm index b0ee3092..2f16af00 100644 --- a/ios/web_view/internal/signin/ios_web_view_signin_client.mm +++ b/ios/web_view/internal/signin/ios_web_view_signin_client.mm
@@ -86,9 +86,9 @@ } void IOSWebViewSigninClient::PreSignOut( - const base::RepeatingClosure& sign_out, + base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached, signin_metrics::ProfileSignout signout_source_metric) { - sign_out.Run(); + std::move(on_signout_decision_reached).Run(SignoutDecision::ALLOW_SIGNOUT); [sync_controller_ didSignoutWithSourceMetric:signout_source_metric]; }
diff --git a/net/BUILD.gn b/net/BUILD.gn index b7a551a..a714def 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -362,8 +362,6 @@ "ssl/ssl_private_key.h", "ssl/ssl_server_config.cc", "ssl/ssl_server_config.h", - "ssl/token_binding.cc", - "ssl/token_binding.h", "third_party/quic/core/quic_error_codes.cc", "third_party/quic/core/quic_error_codes.h", "third_party/uri_template/uri_template.cc",
diff --git a/net/base/mime_sniffer.cc b/net/base/mime_sniffer.cc index 3f60f22..ace836a5 100644 --- a/net/base/mime_sniffer.cc +++ b/net/base/mime_sniffer.cc
@@ -152,7 +152,7 @@ MAGIC_NUMBER("image/tiff", "II*"), MAGIC_NUMBER("image/tiff", "MM\x00*"), MAGIC_NUMBER("audio/mpeg", "ID3"), - MAGIC_NUMBER("image/webp", "RIFF....WEBPVP8 "), + MAGIC_NUMBER("image/webp", "RIFF....WEBPVP"), MAGIC_NUMBER("video/webm", "\x1A\x45\xDF\xA3"), MAGIC_NUMBER("application/zip", "PK\x03\x04"), MAGIC_NUMBER("application/x-rar-compressed", "Rar!\x1A\x07\x00"),
diff --git a/net/base/mime_sniffer_unittest.cc b/net/base/mime_sniffer_unittest.cc index 5c200eb6..dd417c7 100644 --- a/net/base/mime_sniffer_unittest.cc +++ b/net/base/mime_sniffer_unittest.cc
@@ -458,6 +458,27 @@ mime_type.clear(); } +TEST(MimeSnifferTest, ImageTest) { + std::string mime_type; + const char kWebPSimpleFormat[] = "RIFF\xee\x81\x00\x00WEBPVP8 "; + EXPECT_TRUE(SniffMimeTypeFromLocalData( + kWebPSimpleFormat, sizeof(kWebPSimpleFormat) - 1, &mime_type)); + EXPECT_EQ("image/webp", mime_type); + mime_type.clear(); + + const char kWebPLosslessFormat[] = "RIFF\xee\x81\x00\x00WEBPVP8L"; + EXPECT_TRUE(SniffMimeTypeFromLocalData( + kWebPLosslessFormat, sizeof(kWebPLosslessFormat) - 1, &mime_type)); + EXPECT_EQ("image/webp", mime_type); + mime_type.clear(); + + const char kWebPExtendedFormat[] = "RIFF\xee\x81\x00\x00WEBPVP8X"; + EXPECT_TRUE(SniffMimeTypeFromLocalData( + kWebPExtendedFormat, sizeof(kWebPExtendedFormat) - 1, &mime_type)); + EXPECT_EQ("image/webp", mime_type); + mime_type.clear(); +} + // The tests need char parameters, but the ranges to test include 0xFF, and some // platforms have signed chars and are noisy about it. Using an int parameter // and casting it to char inside the test case solves both these problems.
diff --git a/net/http/http_basic_stream.cc b/net/http/http_basic_stream.cc index 2fc34a5..2f677a4 100644 --- a/net/http/http_basic_stream.cc +++ b/net/http/http_basic_stream.cc
@@ -131,12 +131,6 @@ return state_.connection()->socket()->GetPeerAddress(endpoint) == OK; } -Error HttpBasicStream::GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) { - return parser()->GetTokenBindingSignature(key, tb_type, out); -} - void HttpBasicStream::Drain(HttpNetworkSession* session) { HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(this); drainer->Start(session);
diff --git a/net/http/http_basic_stream.h b/net/http/http_basic_stream.h index 48f79725..accecba 100644 --- a/net/http/http_basic_stream.h +++ b/net/http/http_basic_stream.h
@@ -83,10 +83,6 @@ bool GetRemoteEndpoint(IPEndPoint* endpoint) override; - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) override; - void Drain(HttpNetworkSession* session) override; void PopulateNetErrorDetails(NetErrorDetails* details) override;
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 951cad57..5582ea6 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -143,7 +143,6 @@ quic_race_cert_verification(false), quic_estimate_initial_rtt(false), quic_headers_include_h2_stream_dependency(false), - enable_token_binding(false), enable_channel_id(false), http_09_on_non_default_ports_enabled(false), disable_idle_sockets_close_on_memory_pressure(false) { @@ -232,7 +231,6 @@ params.quic_headers_include_h2_stream_dependency, params.quic_connection_options, params.quic_client_connection_options, - params.enable_token_binding, params.enable_channel_id, params.quic_enable_socket_recv_optimization), spdy_session_pool_(context.host_resolver, @@ -462,9 +460,6 @@ } else { server_config->channel_id_enabled = params_.enable_channel_id; proxy_config->channel_id_enabled = params_.enable_channel_id; - if (params_.enable_token_binding && context_.channel_id_service) { - server_config->token_binding_params.push_back(TB_PARAM_ECDSAP256); - } } }
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index fa0596f..c4319af 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h
@@ -226,8 +226,6 @@ // If non-empty, QUIC will only be spoken to hosts in this list. base::flat_set<std::string> quic_host_whitelist; - // Enable support for Token Binding. - bool enable_token_binding; // Enable Channel ID. Channel ID is being deprecated. bool enable_channel_id;
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 2d0718ae..12b8b561 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc
@@ -67,7 +67,6 @@ #include "net/ssl/ssl_connection_status_flags.h" #include "net/ssl/ssl_info.h" #include "net/ssl/ssl_private_key.h" -#include "net/ssl/token_binding.h" #include "url/gurl.h" #include "url/url_canon.h" @@ -636,42 +635,6 @@ return request_->url.SchemeIsCryptographic(); } -bool HttpNetworkTransaction::IsTokenBindingEnabled() const { - if (!IsSecureRequest()) - return false; - SSLInfo ssl_info; - stream_->GetSSLInfo(&ssl_info); - return ssl_info.token_binding_negotiated && - ssl_info.token_binding_key_param == TB_PARAM_ECDSAP256 && - session_->context().channel_id_service; -} - -void HttpNetworkTransaction::RecordTokenBindingSupport() const { - // This enum is used for an UMA histogram - do not change or re-use values. - enum { - DISABLED = 0, - CLIENT_ONLY = 1, - CLIENT_AND_SERVER = 2, - CLIENT_NO_CHANNEL_ID_SERVICE = 3, - TOKEN_BINDING_SUPPORT_MAX - } supported; - if (!IsSecureRequest()) - return; - SSLInfo ssl_info; - stream_->GetSSLInfo(&ssl_info); - if (!session_->params().enable_token_binding) { - supported = DISABLED; - } else if (!session_->context().channel_id_service) { - supported = CLIENT_NO_CHANNEL_ID_SERVICE; - } else if (ssl_info.token_binding_negotiated) { - supported = CLIENT_AND_SERVER; - } else { - supported = CLIENT_ONLY; - } - UMA_HISTOGRAM_ENUMERATION("Net.TokenBinding.Support", supported, - TOKEN_BINDING_SUPPORT_MAX); -} - bool HttpNetworkTransaction::UsingHttpProxyWithoutTunnel() const { return (proxy_info_.is_http() || proxy_info_.is_https() || proxy_info_.is_quic()) && @@ -736,20 +699,6 @@ case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE: rv = DoGenerateServerAuthTokenComplete(rv); break; - case STATE_GET_PROVIDED_TOKEN_BINDING_KEY: - DCHECK_EQ(OK, rv); - rv = DoGetProvidedTokenBindingKey(); - break; - case STATE_GET_PROVIDED_TOKEN_BINDING_KEY_COMPLETE: - rv = DoGetProvidedTokenBindingKeyComplete(rv); - break; - case STATE_GET_REFERRED_TOKEN_BINDING_KEY: - DCHECK_EQ(OK, rv); - rv = DoGetReferredTokenBindingKey(); - break; - case STATE_GET_REFERRED_TOKEN_BINDING_KEY_COMPLETE: - rv = DoGetReferredTokenBindingKeyComplete(rv); - break; case STATE_INIT_REQUEST_BODY: DCHECK_EQ(OK, rv); rv = DoInitRequestBody(); @@ -991,53 +940,6 @@ int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) { DCHECK_NE(ERR_IO_PENDING, rv); if (rv == OK) - next_state_ = STATE_GET_PROVIDED_TOKEN_BINDING_KEY; - return rv; -} - -int HttpNetworkTransaction::DoGetProvidedTokenBindingKey() { - next_state_ = STATE_GET_PROVIDED_TOKEN_BINDING_KEY_COMPLETE; - if (!IsTokenBindingEnabled()) - return OK; - - net_log_.BeginEvent(NetLogEventType::HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY); - ChannelIDService* channel_id_service = session_->context().channel_id_service; - return channel_id_service->GetOrCreateChannelID( - request_->url.host(), &provided_token_binding_key_, io_callback_, - &token_binding_request_); -} - -int HttpNetworkTransaction::DoGetProvidedTokenBindingKeyComplete(int rv) { - DCHECK_NE(ERR_IO_PENDING, rv); - if (IsTokenBindingEnabled()) { - net_log_.EndEventWithNetErrorCode( - NetLogEventType::HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY, rv); - } - - if (rv == OK) - next_state_ = STATE_GET_REFERRED_TOKEN_BINDING_KEY; - return rv; -} - -int HttpNetworkTransaction::DoGetReferredTokenBindingKey() { - next_state_ = STATE_GET_REFERRED_TOKEN_BINDING_KEY_COMPLETE; - if (!IsTokenBindingEnabled() || request_->token_binding_referrer.empty()) - return OK; - - net_log_.BeginEvent(NetLogEventType::HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY); - ChannelIDService* channel_id_service = session_->context().channel_id_service; - return channel_id_service->GetOrCreateChannelID( - request_->token_binding_referrer, &referred_token_binding_key_, - io_callback_, &token_binding_request_); -} - -int HttpNetworkTransaction::DoGetReferredTokenBindingKeyComplete(int rv) { - DCHECK_NE(ERR_IO_PENDING, rv); - if (IsTokenBindingEnabled() && !request_->token_binding_referrer.empty()) { - net_log_.EndEventWithNetErrorCode( - NetLogEventType::HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY, rv); - } - if (rv == OK) next_state_ = STATE_INIT_REQUEST_BODY; return rv; } @@ -1075,16 +977,6 @@ request_headers_.SetHeader(HttpRequestHeaders::kContentLength, "0"); } - RecordTokenBindingSupport(); - if (provided_token_binding_key_) { - std::string token_binding_header; - int rv = BuildTokenBindingHeader(&token_binding_header); - if (rv != OK) - return rv; - request_headers_.SetHeader(HttpRequestHeaders::kTokenBinding, - token_binding_header); - } - // Honor load flags that impact proxy caches. if (request_->load_flags & LOAD_BYPASS_CACHE) { request_headers_.SetHeader(HttpRequestHeaders::kPragma, "no-cache"); @@ -1111,52 +1003,6 @@ return OK; } -int HttpNetworkTransaction::BuildTokenBindingHeader(std::string* out) { - base::TimeTicks start = base::TimeTicks::Now(); - std::vector<uint8_t> signed_ekm; - int rv = stream_->GetTokenBindingSignature(provided_token_binding_key_.get(), - TokenBindingType::PROVIDED, - &signed_ekm); - if (rv != OK) - return rv; - std::string provided_token_binding; - rv = BuildTokenBinding(TokenBindingType::PROVIDED, - provided_token_binding_key_.get(), signed_ekm, - &provided_token_binding); - if (rv != OK) - return rv; - - std::vector<base::StringPiece> token_bindings; - token_bindings.push_back(provided_token_binding); - - std::string referred_token_binding; - if (referred_token_binding_key_) { - std::vector<uint8_t> referred_signed_ekm; - int rv = stream_->GetTokenBindingSignature( - referred_token_binding_key_.get(), TokenBindingType::REFERRED, - &referred_signed_ekm); - if (rv != OK) - return rv; - rv = BuildTokenBinding(TokenBindingType::REFERRED, - referred_token_binding_key_.get(), - referred_signed_ekm, &referred_token_binding); - if (rv != OK) - return rv; - token_bindings.push_back(referred_token_binding); - } - std::string header; - rv = BuildTokenBindingMessageFromTokenBindings(token_bindings, &header); - if (rv != OK) - return rv; - base::Base64UrlEncode(header, base::Base64UrlEncodePolicy::OMIT_PADDING, out); - base::TimeDelta header_creation_time = base::TimeTicks::Now() - start; - UMA_HISTOGRAM_CUSTOM_TIMES("Net.TokenBinding.HeaderCreationTime", - header_creation_time, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(1), 50); - return OK; -} - int HttpNetworkTransaction::DoInitRequestBody() { next_state_ = STATE_INIT_REQUEST_BODY_COMPLETE; int rv = OK; @@ -1680,8 +1526,6 @@ remote_endpoint_ = IPEndPoint(); net_error_details_.quic_broken = false; net_error_details_.quic_connection_error = quic::QUIC_NO_ERROR; - provided_token_binding_key_.reset(); - referred_token_binding_key_.reset(); } void HttpNetworkTransaction::CacheNetErrorDetailsAndResetStream() {
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h index cd95f6ef..e0105d06 100644 --- a/net/http/http_network_transaction.h +++ b/net/http/http_network_transaction.h
@@ -33,10 +33,6 @@ #include "net/ssl/ssl_config_service.h" #include "net/websockets/websocket_handshake_stream_base.h" -namespace crypto { -class ECPrivateKey; -} - namespace net { class BidirectionalStreamImpl; @@ -151,10 +147,6 @@ STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE, STATE_GENERATE_SERVER_AUTH_TOKEN, STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE, - STATE_GET_PROVIDED_TOKEN_BINDING_KEY, - STATE_GET_PROVIDED_TOKEN_BINDING_KEY_COMPLETE, - STATE_GET_REFERRED_TOKEN_BINDING_KEY, - STATE_GET_REFERRED_TOKEN_BINDING_KEY_COMPLETE, STATE_INIT_REQUEST_BODY, STATE_INIT_REQUEST_BODY_COMPLETE, STATE_BUILD_REQUEST, @@ -171,8 +163,6 @@ }; bool IsSecureRequest() const; - bool IsTokenBindingEnabled() const; - void RecordTokenBindingSupport() const; // Returns true if the request is using an HTTP(S) proxy without being // tunneled via the CONNECT method. @@ -197,10 +187,6 @@ int DoGenerateProxyAuthTokenComplete(int result); int DoGenerateServerAuthToken(); int DoGenerateServerAuthTokenComplete(int result); - int DoGetProvidedTokenBindingKey(); - int DoGetProvidedTokenBindingKeyComplete(int result); - int DoGetReferredTokenBindingKey(); - int DoGetReferredTokenBindingKeyComplete(int result); int DoInitRequestBody(); int DoInitRequestBodyComplete(int result); int DoBuildRequest(); @@ -215,7 +201,6 @@ int DoDrainBodyForAuthRestartComplete(int result); int BuildRequestHeaders(bool using_http_proxy_without_tunnel); - int BuildTokenBindingHeader(std::string* out); // Writes a log message to help debugging in the field when we block a proxy // response to a CONNECT request. @@ -351,13 +336,6 @@ SSLConfig server_ssl_config_; SSLConfig proxy_ssl_config_; - // Keys to use for signing message in Token Binding header. - std::unique_ptr<crypto::ECPrivateKey> provided_token_binding_key_; - std::unique_ptr<crypto::ECPrivateKey> referred_token_binding_key_; - // Object to manage lookup of |provided_token_binding_key_| and - // |referred_token_binding_key_|. - ChannelIDService::Request token_binding_request_; - HttpRequestHeaders request_headers_; // The size in bytes of the buffer we use to drain the response body that
diff --git a/net/http/http_network_transaction_ssl_unittest.cc b/net/http/http_network_transaction_ssl_unittest.cc index e4e7e08..837fd089 100644 --- a/net/http/http_network_transaction_ssl_unittest.cc +++ b/net/http/http_network_transaction_ssl_unittest.cc
@@ -39,12 +39,9 @@ namespace { -class TokenBindingSSLConfigService : public SSLConfigService { +class ChannelIDSSLConfigService : public SSLConfigService { public: - TokenBindingSSLConfigService() { - ssl_config_.token_binding_params.push_back(TB_PARAM_ECDSAP256); - } - ~TokenBindingSSLConfigService() override = default; + ~ChannelIDSSLConfigService() override = default; void GetSSLConfig(SSLConfig* config) override { *config = ssl_config_; } @@ -64,7 +61,7 @@ HttpNetworkTransactionSSLTest() = default; void SetUp() override { - ssl_config_service_.reset(new TokenBindingSSLConfigService); + ssl_config_service_.reset(new ChannelIDSSLConfigService); session_context_.ssl_config_service = ssl_config_service_.get(); auth_handler_factory_.reset(new HttpAuthHandlerMock::Factory()); @@ -125,130 +122,4 @@ EXPECT_TRUE(trans.server_ssl_config_.channel_id_enabled); } -#if !defined(OS_IOS) -TEST_F(HttpNetworkTransactionSSLTest, TokenBinding) { - ChannelIDService channel_id_service(new DefaultChannelIDStore(NULL)); - session_context_.channel_id_service = &channel_id_service; - - SSLSocketDataProvider ssl_data(ASYNC, OK); - ssl_data.ssl_info.token_binding_negotiated = true; - ssl_data.ssl_info.token_binding_key_param = TB_PARAM_ECDSAP256; - mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data); - MockRead mock_reads[] = {MockRead("HTTP/1.1 200 OK\r\n\r\n"), - MockRead(SYNCHRONOUS, OK)}; - StaticSocketDataProvider data(mock_reads, base::span<MockWrite>()); - mock_socket_factory_.AddSocketDataProvider(&data); - - HttpNetworkSession session(HttpNetworkSession::Params(), session_context_); - HttpNetworkTransaction trans1(DEFAULT_PRIORITY, &session); - - TestCompletionCallback callback; - int rv = callback.GetResult( - trans1.Start(GetRequestInfo("https://www.example.com/"), - callback.callback(), NetLogWithSource())); - EXPECT_THAT(rv, IsOk()); - - HttpRequestHeaders headers1; - ASSERT_TRUE(trans1.GetFullRequestHeaders(&headers1)); - std::string token_binding_header1; - EXPECT_TRUE(headers1.GetHeader(HttpRequestHeaders::kTokenBinding, - &token_binding_header1)); - - // Send a second request and verify that the token binding header is the same - // as in the first request. - mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data); - StaticSocketDataProvider data2(mock_reads, base::span<MockWrite>()); - mock_socket_factory_.AddSocketDataProvider(&data2); - HttpNetworkTransaction trans2(DEFAULT_PRIORITY, &session); - - rv = callback.GetResult( - trans2.Start(GetRequestInfo("https://www.example.com/"), - callback.callback(), NetLogWithSource())); - EXPECT_THAT(rv, IsOk()); - - HttpRequestHeaders headers2; - ASSERT_TRUE(trans2.GetFullRequestHeaders(&headers2)); - std::string token_binding_header2; - EXPECT_TRUE(headers2.GetHeader(HttpRequestHeaders::kTokenBinding, - &token_binding_header2)); - - EXPECT_EQ(token_binding_header1, token_binding_header2); -} - -TEST_F(HttpNetworkTransactionSSLTest, NoTokenBindingOverHttp) { - ChannelIDService channel_id_service(new DefaultChannelIDStore(NULL)); - session_context_.channel_id_service = &channel_id_service; - - SSLSocketDataProvider ssl_data(ASYNC, OK); - ssl_data.ssl_info.token_binding_negotiated = true; - ssl_data.ssl_info.token_binding_key_param = TB_PARAM_ECDSAP256; - mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data); - MockRead mock_reads[] = {MockRead("HTTP/1.1 200 OK\r\n\r\n"), - MockRead(SYNCHRONOUS, OK)}; - StaticSocketDataProvider data(mock_reads, base::span<MockWrite>()); - mock_socket_factory_.AddSocketDataProvider(&data); - - HttpNetworkSession session(HttpNetworkSession::Params(), session_context_); - HttpNetworkTransaction trans(DEFAULT_PRIORITY, &session); - - TestCompletionCallback callback; - int rv = - callback.GetResult(trans.Start(GetRequestInfo("http://www.example.com/"), - callback.callback(), NetLogWithSource())); - EXPECT_THAT(rv, IsOk()); - - HttpRequestHeaders headers; - ASSERT_TRUE(trans.GetFullRequestHeaders(&headers)); - std::string token_binding_header; - EXPECT_FALSE(headers.GetHeader(HttpRequestHeaders::kTokenBinding, - &token_binding_header)); -} - -// Regression test for https://crbug.com/667683. -TEST_F(HttpNetworkTransactionSSLTest, TokenBindingAsync) { - // Create a separate thread for ChannelIDService - // so that asynchronous Channel ID creation can be delayed. - base::Thread channel_id_thread("ThreadForChannelIDService"); - channel_id_thread.Start(); - scoped_refptr<base::DeferredSequencedTaskRunner> channel_id_runner = - new base::DeferredSequencedTaskRunner(channel_id_thread.task_runner()); - ChannelIDService channel_id_service(new DefaultChannelIDStore(nullptr)); - channel_id_service.set_task_runner_for_testing(channel_id_runner); - session_context_.channel_id_service = &channel_id_service; - - SSLSocketDataProvider ssl_data(ASYNC, OK); - ssl_data.ssl_info.token_binding_negotiated = true; - ssl_data.ssl_info.token_binding_key_param = TB_PARAM_ECDSAP256; - ssl_data.next_proto = kProtoHTTP2; - mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data); - - MockRead reads[] = {MockRead(ASYNC, OK, 0)}; - StaticSocketDataProvider data(reads, base::span<MockWrite>()); - mock_socket_factory_.AddSocketDataProvider(&data); - - HttpRequestInfo request_info; - request_info.url = GURL("https://www.example.com/"); - request_info.method = "GET"; - request_info.token_binding_referrer = "encrypted.example.com"; - request_info.traffic_annotation = - net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); - - HttpNetworkSession session(HttpNetworkSession::Params(), session_context_); - HttpNetworkTransaction trans(DEFAULT_PRIORITY, &session); - - TestCompletionCallback callback; - int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource()); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - - base::RunLoop().RunUntilIdle(); - - // When ChannelIdService calls back to HttpNetworkSession, - // SpdyHttpStream should not crash. - channel_id_runner->Start(); - - rv = callback.WaitForResult(); - EXPECT_THAT(rv, IsError(ERR_CONNECTION_CLOSED)); -} -#endif // !defined(OS_IOS) - } // namespace net
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 1c7ec47..4d3cb523 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -17159,46 +17159,6 @@ EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes()); } -#if !defined(OS_IOS) -TEST_F(HttpNetworkTransactionTest, TokenBindingSpdy) { - const std::string https_url = "https://www.example.com"; - HttpRequestInfo request; - request.url = GURL(https_url); - request.method = "GET"; - request.traffic_annotation = - net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); - - SSLSocketDataProvider ssl(ASYNC, OK); - ssl.ssl_info.token_binding_negotiated = true; - ssl.ssl_info.token_binding_key_param = TB_PARAM_ECDSAP256; - ssl.next_proto = kProtoHTTP2; - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); - spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); - MockRead reads[] = {CreateMockRead(resp), CreateMockRead(body), - MockRead(ASYNC, ERR_IO_PENDING)}; - StaticSocketDataProvider data(reads, base::span<MockWrite>()); - session_deps_.socket_factory->AddSocketDataProvider(&data); - session_deps_.channel_id_service = - std::make_unique<ChannelIDService>(new DefaultChannelIDStore(nullptr)); - std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - - HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); - TestCompletionCallback callback; - EXPECT_EQ(ERR_IO_PENDING, - trans.Start(&request, callback.callback(), NetLogWithSource())); - - RunUntilIdle(); - - EXPECT_TRUE(trans.GetResponseInfo()->was_fetched_via_spdy); - HttpRequestHeaders headers; - ASSERT_TRUE(trans.GetFullRequestHeaders(&headers)); - EXPECT_TRUE(headers.HasHeader(HttpRequestHeaders::kTokenBinding)); -} -#endif // !defined(OS_IOS) - void CheckContentEncodingMatching(SpdySessionDependencies* session_deps, const std::string& accept_encoding, const std::string& content_encoding,
diff --git a/net/http/http_proxy_client_socket_wrapper_unittest.cc b/net/http/http_proxy_client_socket_wrapper_unittest.cc index 18427b1..687ee76 100644 --- a/net/http/http_proxy_client_socket_wrapper_unittest.cc +++ b/net/http/http_proxy_client_socket_wrapper_unittest.cc
@@ -144,8 +144,7 @@ kMaxMigrationsToNonDefaultNetworkOnPathDegrading, allow_server_migration_, race_cert_verification_, estimate_initial_rtt_, client_headers_include_h2_stream_dependency_, connection_options_, - client_connection_options_, /*enable_token_binding=*/false, - /*enable_channel_id=*/false, + client_connection_options_, /*enable_channel_id=*/false, /*enable_socket_recv_optimization=*/false)); }
diff --git a/net/http/http_request_headers.cc b/net/http/http_request_headers.cc index ec77236..d8b9df1 100644 --- a/net/http/http_request_headers.cc +++ b/net/http/http_request_headers.cc
@@ -42,7 +42,6 @@ const char HttpRequestHeaders::kReferer[] = "Referer"; const char HttpRequestHeaders::kSecOriginPolicy[] = "Sec-Origin-Policy"; const char HttpRequestHeaders::kTransferEncoding[] = "Transfer-Encoding"; -const char HttpRequestHeaders::kTokenBinding[] = "Sec-Token-Binding"; const char HttpRequestHeaders::kUserAgent[] = "User-Agent"; HttpRequestHeaders::HeaderKeyValuePair::HeaderKeyValuePair() = default;
diff --git a/net/http/http_request_headers.h b/net/http/http_request_headers.h index acdbc8e..3bb9e43 100644 --- a/net/http/http_request_headers.h +++ b/net/http/http_request_headers.h
@@ -86,7 +86,6 @@ static const char kReferer[]; static const char kSecOriginPolicy[]; static const char kTransferEncoding[]; - static const char kTokenBinding[]; static const char kUserAgent[]; HttpRequestHeaders();
diff --git a/net/http/http_request_info.h b/net/http/http_request_info.h index 987c0e1..a7fbfe43 100644 --- a/net/http/http_request_info.h +++ b/net/http/http_request_info.h
@@ -42,10 +42,6 @@ // tracked by the server (e.g. without channel id). PrivacyMode privacy_mode; - // If present, the host of the referrer whose TokenBindingID should be - // included in a referred TokenBinding. - std::string token_binding_referrer; - // Tag applied to all sockets used to service request. SocketTag socket_tag;
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc index edf7f42..f21ba7d 100644 --- a/net/http/http_response_body_drainer_unittest.cc +++ b/net/http/http_response_body_drainer_unittest.cc
@@ -118,12 +118,6 @@ void GetSSLInfo(SSLInfo* ssl_info) override {} void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {} bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; } - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) override { - ADD_FAILURE(); - return ERR_NOT_IMPLEMENTED; - } // Mocked API int ReadResponseBody(IOBuffer* buf,
diff --git a/net/http/http_stream.h b/net/http/http_stream.h index 581a491..96937af 100644 --- a/net/http/http_stream.h +++ b/net/http/http_stream.h
@@ -23,11 +23,6 @@ #include "net/base/net_export.h" #include "net/base/request_priority.h" #include "net/http/http_raw_request_headers.h" -#include "net/ssl/token_binding.h" - -namespace crypto { -class ECPrivateKey; -} namespace net { @@ -169,13 +164,6 @@ // and does not modify |endpoint| if it is unavailable. virtual bool GetRemoteEndpoint(IPEndPoint* endpoint) = 0; - // Generates the signature used in Token Binding using |*key| and for a Token - // Binding of type |tb_type|, putting the signature in |*out|. Returns OK or - // ERR_FAILED. - virtual Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) = 0; - // In the case of an HTTP error or redirect, flush the response body (usually // a simple error or "this page has moved") so that we can re-use the // underlying connection. This stream is responsible for deleting itself when
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc index 8459add6c..0f23be7 100644 --- a/net/http/http_stream_factory_unittest.cc +++ b/net/http/http_stream_factory_unittest.cc
@@ -146,12 +146,6 @@ void GetSSLInfo(SSLInfo* ssl_info) override {} void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {} bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; } - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) override { - ADD_FAILURE(); - return ERR_NOT_IMPLEMENTED; - } void Drain(HttpNetworkSession* session) override {} void PopulateNetErrorDetails(NetErrorDetails* details) override { return; } void SetPriority(RequestPriority priority) override {}
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index ce23e57..ec6f480e 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc
@@ -25,7 +25,6 @@ #include "net/log/net_log_event_type.h" #include "net/socket/client_socket_handle.h" #include "net/socket/ssl_client_socket.h" -#include "net/ssl/token_binding.h" #include "url/url_canon.h" namespace net { @@ -1138,16 +1137,6 @@ } } -Error HttpStreamParser::GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) { - if (!request_->url.SchemeIsCryptographic() || !connection_->socket()) { - NOTREACHED(); - return ERR_FAILED; - } - return connection_->socket()->GetTokenBindingSignature(key, tb_type, out); -} - int HttpStreamParser::EncodeChunk(const base::StringPiece& payload, char* output, size_t output_size) {
diff --git a/net/http/http_stream_parser.h b/net/http/http_stream_parser.h index 603db77..a70c254 100644 --- a/net/http/http_stream_parser.h +++ b/net/http/http_stream_parser.h
@@ -21,7 +21,6 @@ #include "net/base/net_errors.h" #include "net/base/net_export.h" #include "net/log/net_log_with_source.h" -#include "net/ssl/token_binding.h" #include "net/traffic_annotation/network_traffic_annotation.h" namespace net { @@ -104,10 +103,6 @@ void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info); - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out); - // Encodes the given |payload| in the chunked format to |output|. // Returns the number of bytes written to |output|. |output_size| should // be large enough to store the encoded chunk, which is payload.size() +
diff --git a/net/http/proxy_connect_redirect_http_stream.cc b/net/http/proxy_connect_redirect_http_stream.cc index 565ae55..99b3ba4 100644 --- a/net/http/proxy_connect_redirect_http_stream.cc +++ b/net/http/proxy_connect_redirect_http_stream.cc
@@ -108,14 +108,6 @@ return false; } -Error ProxyConnectRedirectHttpStream::GetTokenBindingSignature( - crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) { - NOTREACHED(); - return ERR_NOT_IMPLEMENTED; -} - void ProxyConnectRedirectHttpStream::Drain(HttpNetworkSession* session) { NOTREACHED(); }
diff --git a/net/http/proxy_connect_redirect_http_stream.h b/net/http/proxy_connect_redirect_http_stream.h index 2a0ae44..67cc6181 100644 --- a/net/http/proxy_connect_redirect_http_stream.h +++ b/net/http/proxy_connect_redirect_http_stream.h
@@ -62,9 +62,6 @@ void GetSSLInfo(SSLInfo* ssl_info) override; void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override; bool GetRemoteEndpoint(IPEndPoint* endpoint) override; - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) override; void Drain(HttpNetworkSession* session) override; void PopulateNetErrorDetails(NetErrorDetails* details) override;
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h index c22bf49..437ec84 100644 --- a/net/log/net_log_event_type_list.h +++ b/net/log/net_log_event_type_list.h
@@ -1227,9 +1227,6 @@ // restarting for authentication, on keep alive connections. EVENT_TYPE(HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART) -// Measures the time taken to look up the key used for Token Binding. -EVENT_TYPE(HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY) - // This event is sent when we try to restart a transaction after an error. // The following parameters are attached: // {
diff --git a/net/nqe/network_quality_estimator_params.cc b/net/nqe/network_quality_estimator_params.cc index 16dda1aa..b0516fd 100644 --- a/net/nqe/network_quality_estimator_params.cc +++ b/net/nqe/network_quality_estimator_params.cc
@@ -238,6 +238,24 @@ } } +// Typical HTTP RTT value corresponding to a given WebEffectiveConnectionType +// value. Taken from +// https://cs.chromium.org/chromium/src/net/nqe/network_quality_estimator_params.cc. +const base::TimeDelta kTypicalHttpRttEffectiveConnectionType + [net::EFFECTIVE_CONNECTION_TYPE_LAST] = { + base::TimeDelta::FromMilliseconds(0), + base::TimeDelta::FromMilliseconds(0), + base::TimeDelta::FromMilliseconds(3600), + base::TimeDelta::FromMilliseconds(1800), + base::TimeDelta::FromMilliseconds(450), + base::TimeDelta::FromMilliseconds(175)}; + +// Typical downlink throughput (in Mbps) value corresponding to a given +// WebEffectiveConnectionType value. Taken from +// https://cs.chromium.org/chromium/src/net/nqe/network_quality_estimator_params.cc. +const int32_t kTypicalDownlinkKbpsEffectiveConnectionType + [net::EFFECTIVE_CONNECTION_TYPE_LAST] = {0, 0, 40, 75, 400, 1600}; + // Sets |typical_network_quality| to typical network quality for different // effective connection types. void ObtainTypicalNetworkQualities( @@ -257,30 +275,39 @@ // Set to the 77.5th percentile of 2G RTT observations on Android. // This corresponds to the median RTT observation when effective // connection type is Slow 2G. - base::TimeDelta::FromMilliseconds(3600), - base::TimeDelta::FromMilliseconds(3000), 40); + kTypicalHttpRttEffectiveConnectionType + [EFFECTIVE_CONNECTION_TYPE_SLOW_2G], + base::TimeDelta::FromMilliseconds(3000), + kTypicalDownlinkKbpsEffectiveConnectionType + [EFFECTIVE_CONNECTION_TYPE_SLOW_2G]); typical_network_quality[EFFECTIVE_CONNECTION_TYPE_2G] = nqe::internal::NetworkQuality( // Set to the 58th percentile of 2G RTT observations on Android. This // corresponds to the median RTT observation when effective connection // type is 2G. - base::TimeDelta::FromMilliseconds(1800), - base::TimeDelta::FromMilliseconds(1500), 75); + kTypicalHttpRttEffectiveConnectionType[EFFECTIVE_CONNECTION_TYPE_2G], + base::TimeDelta::FromMilliseconds(1500), + kTypicalDownlinkKbpsEffectiveConnectionType + [EFFECTIVE_CONNECTION_TYPE_2G]); typical_network_quality[EFFECTIVE_CONNECTION_TYPE_3G] = nqe::internal::NetworkQuality( // Set to the 75th percentile of 3G RTT observations on Android. This // corresponds to the median RTT observation when effective connection // type is 3G. - base::TimeDelta::FromMilliseconds(450), - base::TimeDelta::FromMilliseconds(400), 400); + kTypicalHttpRttEffectiveConnectionType[EFFECTIVE_CONNECTION_TYPE_3G], + base::TimeDelta::FromMilliseconds(400), + kTypicalDownlinkKbpsEffectiveConnectionType + [EFFECTIVE_CONNECTION_TYPE_3G]); // Set to the 25th percentile of 3G RTT observations on Android. typical_network_quality[EFFECTIVE_CONNECTION_TYPE_4G] = - nqe::internal::NetworkQuality(base::TimeDelta::FromMilliseconds(175), - base::TimeDelta::FromMilliseconds(125), - 1600); + nqe::internal::NetworkQuality( + kTypicalHttpRttEffectiveConnectionType[EFFECTIVE_CONNECTION_TYPE_4G], + base::TimeDelta::FromMilliseconds(125), + kTypicalDownlinkKbpsEffectiveConnectionType + [EFFECTIVE_CONNECTION_TYPE_4G]); static_assert( EFFECTIVE_CONNECTION_TYPE_4G + 1 == EFFECTIVE_CONNECTION_TYPE_LAST, @@ -518,6 +545,18 @@ return use_small_responses_; }; +// static +base::TimeDelta NetworkQualityEstimatorParams::GetDefaultTypicalHttpRtt( + EffectiveConnectionType effective_connection_type) { + return kTypicalHttpRttEffectiveConnectionType[effective_connection_type]; +} + +// static +int32_t NetworkQualityEstimatorParams::GetDefaultTypicalDownlinkKbps( + EffectiveConnectionType effective_connection_type) { + return kTypicalDownlinkKbpsEffectiveConnectionType[effective_connection_type]; +} + void NetworkQualityEstimatorParams::SetForcedEffectiveConnectionTypeForTesting( EffectiveConnectionType type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/net/nqe/network_quality_estimator_params.h b/net/nqe/network_quality_estimator_params.h index 6add5a6..f9762e2 100644 --- a/net/nqe/network_quality_estimator_params.h +++ b/net/nqe/network_quality_estimator_params.h
@@ -174,6 +174,18 @@ // network quality. Set to true only for tests. bool use_small_responses() const; + // Returns the typical HTTP RTT that maps to the given + // |effective_connection_type|. May return invalid value if + // |effective_connection_type| is less than Slow2G or faster than 4G, + static base::TimeDelta GetDefaultTypicalHttpRtt( + EffectiveConnectionType effective_connection_type); + + // Returns the typical downslink throughput (in kbps) that maps to the given + // |effective_connection_type|. May return invalid value if + // |effective_connection_type| is less than Slow2G or faster than 4G, + static int32_t GetDefaultTypicalDownlinkKbps( + EffectiveConnectionType effective_connection_type); + // |use_small_responses| should only be true when testing. // Allows the responses smaller than |kMinTransferSizeInBits| to be used for // network quality estimation.
diff --git a/net/nqe/network_quality_estimator_params_unittest.cc b/net/nqe/network_quality_estimator_params_unittest.cc index d9b2ed2..aa6c98bb0 100644 --- a/net/nqe/network_quality_estimator_params_unittest.cc +++ b/net/nqe/network_quality_estimator_params_unittest.cc
@@ -83,6 +83,12 @@ params.TypicalNetworkQuality(ect).downstream_throughput_kbps()); EXPECT_EQ(nqe::internal::INVALID_RTT_THROUGHPUT, params.ConnectionThreshold(ect).downstream_throughput_kbps()); + + EXPECT_EQ(params.TypicalNetworkQuality(ect).http_rtt(), + NetworkQualityEstimatorParams::GetDefaultTypicalHttpRtt(ect)); + EXPECT_EQ( + params.TypicalNetworkQuality(ect).downstream_throughput_kbps(), + NetworkQualityEstimatorParams::GetDefaultTypicalDownlinkKbps(ect)); } // The typical network quality of 4G connection should be at least as fast
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index bb1bcdea..cafdd106 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -38,7 +38,6 @@ #include "net/ssl/channel_id_service.h" #include "net/ssl/ssl_connection_status_flags.h" #include "net/ssl/ssl_info.h" -#include "net/ssl/token_binding.h" #include "net/third_party/quic/core/http/quic_client_promised_info.h" #include "net/third_party/quic/core/http/spdy_utils.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h" @@ -57,12 +56,6 @@ // IP address changes. const size_t kMaxReadersPerQuicSession = 5; -// Size of the MRU cache of Token Binding signatures. Since the material being -// signed is constant and there aren't many keys being used to sign, a fairly -// small number was chosen, somewhat arbitrarily, and to match -// SSLClientSocketImpl. -const size_t kTokenBindingSignatureMapSize = 10; - // Time to wait (in seconds) when no networks are available and // migrating sessions need to wait for a new network to connect. const size_t kWaitTimeForNewNetworkSecs = 10; @@ -333,16 +326,6 @@ return session_->GetConnectTiming(); } -Error QuicChromiumClientSession::Handle::GetTokenBindingSignature( - crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) { - if (!session_) - return ERR_CONNECTION_CLOSED; - - return session_->GetTokenBindingSignature(key, tb_type, out); -} - void QuicChromiumClientSession::Handle::PopulateNetErrorDetails( NetErrorDetails* details) const { if (session_) { @@ -740,7 +723,6 @@ net_log_)), going_away_(false), port_migration_detected_(false), - token_binding_signatures_(kTokenBindingSignatureMapSize), push_delegate_(push_delegate), streams_pushed_count_(0), streams_pushed_and_claimed_count_(0), @@ -1175,40 +1157,9 @@ ssl_info->UpdateCertificateTransparencyInfo(*ct_verify_result_); - if (crypto_stream_->crypto_negotiated_params().token_binding_key_param == - quic::kTB10) { - ssl_info->token_binding_negotiated = true; - ssl_info->token_binding_key_param = TB_PARAM_ECDSAP256; - } - return true; } -Error QuicChromiumClientSession::GetTokenBindingSignature( - crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) { - // The same key will be used across multiple requests to sign the same value, - // so the signature is cached. - std::string raw_public_key; - if (!key->ExportRawPublicKey(&raw_public_key)) - return ERR_FAILED; - TokenBindingSignatureMap::iterator it = - token_binding_signatures_.Get(std::make_pair(tb_type, raw_public_key)); - if (it != token_binding_signatures_.end()) { - *out = it->second; - return OK; - } - - std::string key_material; - if (!crypto_stream_->ExportTokenBindingKeyingMaterial(&key_material)) - return ERR_FAILED; - if (!CreateTokenBindingSignature(key_material, tb_type, key, out)) - return ERR_FAILED; - token_binding_signatures_.Put(std::make_pair(tb_type, raw_public_key), *out); - return OK; -} - int QuicChromiumClientSession::CryptoConnect(CompletionOnceCallback callback) { connect_timing_.connect_start = base::TimeTicks::Now(); RecordHandshakeState(STATE_STARTED);
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h index 1bfd7a8..2a2da167 100644 --- a/net/quic/quic_chromium_client_session.h +++ b/net/quic/quic_chromium_client_session.h
@@ -58,10 +58,6 @@ class SSLInfo; class TransportSecurityState; -using TokenBindingSignatureMap = - base::MRUCache<std::pair<TokenBindingType, std::string>, - std::vector<uint8_t>>; - namespace test { class QuicChromiumClientSessionPeer; } // namespace test @@ -192,12 +188,6 @@ // Returns the connection timing for the handshake of this session. const LoadTimingInfo::ConnectTiming& GetConnectTiming(); - // Signs the exported keying material used for Token Binding using key - // |*key| and puts the signature in |*out|. Returns a net error code. - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out); - // Returns true if |other| is a handle to the same session as this handle. bool SharesSameSession(const Handle& other) const; @@ -514,9 +504,6 @@ // MultiplexedSession methods: bool GetRemoteEndpoint(IPEndPoint* endpoint) override; bool GetSSLInfo(SSLInfo* ssl_info) const override; - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) override; // Performs a crypto handshake with the server. int CryptoConnect(CompletionOnceCallback callback); @@ -783,7 +770,6 @@ bool going_away_; // True when the session receives a go away from server due to port migration. bool port_migration_detected_; - TokenBindingSignatureMap token_binding_signatures_; // Not owned. |push_delegate_| outlives the session and handles server pushes // received by session. ServerPushDelegate* push_delegate_;
diff --git a/net/quic/quic_end_to_end_unittest.cc b/net/quic/quic_end_to_end_unittest.cc index 675c8e7..8478688 100644 --- a/net/quic/quic_end_to_end_unittest.cc +++ b/net/quic/quic_end_to_end_unittest.cc
@@ -179,8 +179,6 @@ quic::test::kInitialStreamFlowControlWindowForTest); server_config_.SetInitialSessionFlowControlWindowToSend( quic::test::kInitialSessionFlowControlWindowForTest); - server_config_options_.token_binding_params = - quic::QuicTagVector{quic::kTB10, quic::kP256}; server_.reset(new QuicSimpleServer( quic::test::crypto_test_utils::ProofSourceForTesting(), server_config_, server_config_options_, quic::AllSupportedVersions(), @@ -282,27 +280,6 @@ CheckResponse(consumer, "HTTP/1.1 200", response); } -TEST_P(QuicEndToEndTest, TokenBinding) { - // Enable token binding and re-initialize the TestTransactionFactory. - session_params_.enable_token_binding = true; - transaction_factory_.reset( - new TestTransactionFactory(session_params_, session_context_)); - - AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody); - - TestTransactionConsumer consumer(DEFAULT_PRIORITY, - transaction_factory_.get()); - consumer.Start(&request_, NetLogWithSource()); - - // Will terminate when the last consumer completes. - base::RunLoop().Run(); - - CheckResponse(consumer, "HTTP/1.1 200", kResponseBody); - HttpRequestHeaders headers; - ASSERT_TRUE(consumer.transaction()->GetFullRequestHeaders(&headers)); - EXPECT_TRUE(headers.HasHeader(HttpRequestHeaders::kTokenBinding)); -} - // crbug.com/559173 #if defined(THREAD_SANITIZER) TEST_P(QuicEndToEndTest, DISABLED_LargePostWithNoPacketLoss) {
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index b79cc201..a24b5a18 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -50,7 +50,6 @@ #include "net/socket/socket_performance_watcher.h" #include "net/socket/socket_performance_watcher_factory.h" #include "net/socket/udp_client_socket.h" -#include "net/ssl/token_binding.h" #include "net/third_party/quic/core/crypto/proof_verifier.h" #include "net/third_party/quic/core/crypto/quic_random.h" #include "net/third_party/quic/core/http/quic_client_promised_info.h" @@ -380,15 +379,27 @@ }; void CloseStaleHostConnection() { + DVLOG(1) << "Closing connection from stale host."; if (session_) { QuicChromiumClientSession* session = session_; session_ = nullptr; - session->CloseSessionOnError( + session->CloseSessionOnErrorLater( ERR_ABORTED, quic::QUIC_CONNECTION_CANCELLED, quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); } } + bool DoesPeerAddressMatchWithFreshAddressList() { + std::vector<net::IPEndPoint> endpoints = address_list_.endpoints(); + IPEndPoint stale_address = session_->peer_address().impl().socket_address(); + + if (std::find(endpoints.begin(), endpoints.end(), stale_address) != + endpoints.end()) { + return true; + } + return false; + } + IoState io_state_; QuicStreamFactory* factory_; quic::QuicTransportVersion quic_version_; @@ -534,11 +545,17 @@ return; } else if (io_state_ != STATE_HOST_VALIDATION) { // Case where host resolution returns successfully, but stale connection - // hasn't finished yet. Host validation will be handled in - // DoValidateHost(). - // TODO(renjietang): In the future, we can also compare IPs here and if - // they don't match, we can close the stale connection early. - return; + // hasn't finished yet. + if (DoesPeerAddressMatchWithFreshAddressList()) { + dns_race_ongoing_ = false; + return; + } + net_log_.AddEvent( + NetLogEventType:: + QUIC_STREAM_FACTORY_JOB_STALE_HOST_RESOLUTION_NO_MATCH); + CloseStaleHostConnection(); + dns_race_ongoing_ = false; + io_state_ = STATE_RESOLVE_HOST_COMPLETE; } } @@ -695,11 +712,7 @@ // This state is reached iff both host resolution and connection from stale dns // have finished successfully. int QuicStreamFactory::Job::DoValidateHost() { - std::vector<net::IPEndPoint> endpoints = address_list_.endpoints(); - IPEndPoint stale_address = session_->peer_address().impl().socket_address(); - - if (std::find(endpoints.begin(), endpoints.end(), stale_address) != - endpoints.end()) { + if (DoesPeerAddressMatchWithFreshAddressList()) { io_state_ = STATE_CONFIRM_CONNECTION; return OK; } @@ -911,7 +924,6 @@ bool headers_include_h2_stream_dependency, const quic::QuicTagVector& connection_options, const quic::QuicTagVector& client_connection_options, - bool enable_token_binding, bool enable_channel_id, bool enable_socket_recv_optimization) : require_confirmation_(true), @@ -993,8 +1005,6 @@ crypto_config_.SetChannelIDSource( new ChannelIDSourceChromium(channel_id_service)); } - if (enable_token_binding && channel_id_service) - crypto_config_.tb_key_params.push_back(quic::kTB10); crypto::EnsureOpenSSLInit(); bool has_aes_hardware_support = !!EVP_has_aes_hardware(); UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.PreferAesGcm",
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h index 1595fb6..e3e7c69 100644 --- a/net/quic/quic_stream_factory.h +++ b/net/quic/quic_stream_factory.h
@@ -261,7 +261,6 @@ bool headers_include_h2_stream_dependency, const quic::QuicTagVector& connection_options, const quic::QuicTagVector& client_connection_options, - bool enable_token_binding, bool enable_channel_id, bool enable_socket_recv_optimization); ~QuicStreamFactory() override;
diff --git a/net/quic/quic_stream_factory_fuzzer.cc b/net/quic/quic_stream_factory_fuzzer.cc index 1b1e7f8d..e82e47b4 100644 --- a/net/quic/quic_stream_factory_fuzzer.cc +++ b/net/quic/quic_stream_factory_fuzzer.cc
@@ -101,7 +101,6 @@ bool race_cert_verification = data_provider.ConsumeBool(); bool estimate_initial_rtt = data_provider.ConsumeBool(); bool headers_include_h2_stream_dependency = data_provider.ConsumeBool(); - bool enable_token_binding = data_provider.ConsumeBool(); bool enable_channel_id = data_provider.ConsumeBool(); bool enable_socket_recv_optimization = data_provider.ConsumeBool(); bool race_stale_dns_on_connection = data_provider.ConsumeBool(); @@ -150,8 +149,8 @@ kMaxMigrationsToNonDefaultNetworkOnPathDegrading, allow_server_migration, race_cert_verification, estimate_initial_rtt, headers_include_h2_stream_dependency, env->connection_options, - env->client_connection_options, enable_token_binding, - enable_channel_id, enable_socket_recv_optimization); + env->client_connection_options, enable_channel_id, + enable_socket_recv_optimization); QuicStreamRequest request(factory.get()); TestCompletionCallback callback;
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index ece11002..810f89a 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -299,7 +299,7 @@ kMaxMigrationsToNonDefaultNetworkOnPathDegrading, allow_server_migration_, race_cert_verification_, estimate_initial_rtt_, client_headers_include_h2_stream_dependency_, connection_options_, - client_connection_options_, /*enable_token_binding*/ false, + client_connection_options_, /*enable_channel_id*/ false, /*enable_socket_recv_optimization*/ false)); } @@ -8690,6 +8690,7 @@ cache->Set(key, entry, base::TimeTicks::Now(), zero); // Expire the cache cache->OnNetworkChange(); + MockQuicData quic_data; quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); @@ -9128,14 +9129,16 @@ MockQuicData quic_data; quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); - quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + client_maker_.SetEncryptionLevel(quic::ENCRYPTION_INITIAL); quic_data.AddWrite( SYNCHRONOUS, client_maker_.MakeConnectionClosePacket( - 2, true, quic::QUIC_CONNECTION_CANCELLED, "net error")); + 1, true, quic::QUIC_CONNECTION_CANCELLED, "net error")); quic_data.AddSocketDataToFactory(socket_factory_.get()); MockQuicData quic_data2; quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE); + quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); quic_data2.AddSocketDataToFactory(socket_factory_.get()); QuicStreamRequest request(factory_.get()); @@ -9147,9 +9150,7 @@ failed_on_default_network_callback_, callback_.callback())); // Finish dns resolution, but need to wait for stale connection. host_resolver_->ResolveAllPending(); - EXPECT_FALSE(callback_.have_result()); - - // Finish stale connection and expect the job to be done. + base::RunLoop().RunUntilIdle(); crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent( quic::QuicSession::HANDSHAKE_CONFIRMED); EXPECT_THAT(callback_.WaitForResult(), IsOk()); @@ -9271,8 +9272,6 @@ host_resolver_->ResolveAllPending(); EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED)); - EXPECT_FALSE(HasLiveSession(host_port_pair_)); - EXPECT_TRUE(quic_data.AllReadDataConsumed()); EXPECT_TRUE(quic_data.AllWriteDataConsumed()); } @@ -9494,82 +9493,6 @@ } // With dns race experiment on, dns resolve async and stale connect async, dns -// resolve returns fine then preconnect fails -TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceResolveAsyncStaleAsyncError) { - race_stale_dns_on_connection_ = true; - host_resolver_ = std::make_unique<MockCachingHostResolver>(); - Initialize(); - ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); - crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); - - // Set asynchronous fresh address in host resolver. - host_resolver_->set_ondemand_mode(true); - factory_->set_require_confirmation(true); - crypto_client_stream_factory_.set_handshake_mode( - MockCryptoClientStream::ZERO_RTT); - host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(), - kNonCachedIPAddress, ""); - - // Set up an address in stale resolver cache. - HostCache::Key key(host_port_pair_.host(), ADDRESS_FAMILY_UNSPECIFIED, 0); - HostCache::Entry entry(OK, - AddressList::CreateFromIPAddress(kCachedIPAddress, 0), - HostCache::Entry::SOURCE_DNS); - base::TimeDelta zero; - HostCache* cache = host_resolver_->GetHostCache(); - cache->Set(key, entry, base::TimeTicks::Now(), zero); - // Expire the cache - cache->OnNetworkChange(); - - MockQuicData quic_data; - quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); - quic_data.AddSocketDataToFactory(socket_factory_.get()); - - MockQuicData quic_data2; - quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); - quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); - quic_data2.AddSocketDataToFactory(socket_factory_.get()); - - QuicStreamRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - - // Host resolution finishes but stale connection is still running. - host_resolver_->ResolveAllPending(); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(callback_.have_result()); - - // Kill the session so that crypto connect will return error. - QuicChromiumClientSession* session = GetPendingSession(host_port_pair_); - session->CloseSessionOnError(ERR_ABORTED, quic::QUIC_INTERNAL_ERROR, - quic::ConnectionCloseBehavior::SILENT_CLOSE); - EXPECT_FALSE(callback_.have_result()); - - // Send crypto handshake for the new connection and check that it finishes. - crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent( - quic::QuicSession::HANDSHAKE_CONFIRMED); - EXPECT_THAT(callback_.WaitForResult(), IsOk()); - - std::unique_ptr<HttpStream> stream = CreateStream(&request); - EXPECT_TRUE(stream.get()); - - QuicChromiumClientSession* session2 = GetActiveSession(host_port_pair_); - - EXPECT_EQ( - session2->peer_address().impl().socket_address().ToStringWithoutPort(), - kNonCachedIPAddress); - - EXPECT_TRUE(quic_data.AllReadDataConsumed()); - EXPECT_TRUE(quic_data.AllWriteDataConsumed()); - EXPECT_TRUE(quic_data2.AllReadDataConsumed()); - EXPECT_TRUE(quic_data2.AllWriteDataConsumed()); -} - -// With dns race experiment on, dns resolve async and stale connect async, dns // resolve returns error and then preconnect fails. TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceResolveAsyncErrorStaleAsyncError) {
diff --git a/net/socket/fuzzed_socket_factory.cc b/net/socket/fuzzed_socket_factory.cc index 65a11fc..504ee2aa 100644 --- a/net/socket/fuzzed_socket_factory.cc +++ b/net/socket/fuzzed_socket_factory.cc
@@ -93,13 +93,6 @@ return nullptr; } - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) override { - NOTREACHED(); - return ERR_UNEXPECTED; - } - crypto::ECPrivateKey* GetChannelIDKey() const override { NOTREACHED(); return nullptr;
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index a8492e01..164b9f3 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc
@@ -1586,13 +1586,6 @@ return data_->channel_id_service; } -Error MockSSLClientSocket::GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) { - out->push_back('A'); - return OK; -} - int MockSSLClientSocket::ExportKeyingMaterial(const base::StringPiece& label, bool has_context, const base::StringPiece& context,
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 7851ad9..b7cabb2 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h
@@ -918,9 +918,6 @@ bool GetSSLInfo(SSLInfo* ssl_info) override; void GetSSLCertRequestInfo( SSLCertRequestInfo* cert_request_info) const override; - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) override; ChannelIDService* GetChannelIDService() const override; crypto::ECPrivateKey* GetChannelIDKey() const override; void ApplySocketTag(const SocketTag& tag) override;
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h index 0221f8b1..f522db3db 100644 --- a/net/socket/ssl_client_socket.h +++ b/net/socket/ssl_client_socket.h
@@ -18,7 +18,6 @@ #include "net/base/net_export.h" #include "net/socket/ssl_socket.h" #include "net/socket/stream_socket.h" -#include "net/ssl/token_binding.h" namespace net {
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index bdcbf4b..4bc70a5f1 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -53,7 +53,6 @@ #include "net/ssl/ssl_info.h" #include "net/ssl/ssl_key_logger.h" #include "net/ssl/ssl_private_key.h" -#include "net/ssl/token_binding.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "third_party/boringssl/src/include/openssl/bio.h" #include "third_party/boringssl/src/include/openssl/bytestring.h" @@ -461,7 +460,6 @@ cert_verifier_(context.cert_verifier), cert_transparency_verifier_(context.cert_transparency_verifier), channel_id_service_(context.channel_id_service), - tb_signature_map_(10), transport_(std::move(transport_socket)), host_and_port_(host_and_port), ssl_config_(ssl_config), @@ -666,10 +664,6 @@ ssl_info->client_cert_sent = ssl_config_.send_client_cert && ssl_config_.client_cert.get(); ssl_info->channel_id_sent = channel_id_sent_; - ssl_info->token_binding_negotiated = - SSL_is_token_binding_negotiated(ssl_.get()); - ssl_info->token_binding_key_param = static_cast<net::TokenBindingParam>( - SSL_get_negotiated_token_binding_param(ssl_.get())); ssl_info->pinning_failure_log = pinning_failure_log_; ssl_info->ocsp_result = server_cert_verify_result_.ocsp_result; ssl_info->is_fatal_cert_error = is_fatal_cert_error_; @@ -748,39 +742,6 @@ return channel_id_service_; } -Error SSLClientSocketImpl::GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) { - // The same key will be used across multiple requests to sign the same value, - // so the signature is cached. - std::string raw_public_key; - if (!key->ExportRawPublicKey(&raw_public_key)) - return ERR_FAILED; - auto it = tb_signature_map_.Get(std::make_pair(tb_type, raw_public_key)); - if (it != tb_signature_map_.end()) { - *out = it->second; - return OK; - } - - uint8_t tb_ekm_buf[32]; - static const char kTokenBindingExporterLabel[] = "EXPORTER-Token-Binding"; - if (!SSL_export_keying_material(ssl_.get(), tb_ekm_buf, sizeof(tb_ekm_buf), - kTokenBindingExporterLabel, - strlen(kTokenBindingExporterLabel), nullptr, - 0, false /* no context */)) { - return ERR_FAILED; - } - - if (!CreateTokenBindingSignature( - base::StringPiece(reinterpret_cast<char*>(tb_ekm_buf), - sizeof(tb_ekm_buf)), - tb_type, key, out)) - return ERR_FAILED; - - tb_signature_map_.Put(std::make_pair(tb_type, raw_public_key), *out); - return OK; -} - crypto::ECPrivateKey* SSLClientSocketImpl::GetChannelIDKey() const { return channel_id_key_.get(); } @@ -976,12 +937,6 @@ SSL_enable_tls_channel_id(ssl_.get()); } - if (!ssl_config_.token_binding_params.empty()) { - std::vector<uint8_t> params(ssl_config_.token_binding_params.begin(), - ssl_config_.token_binding_params.end()); - SSL_set_token_binding_params(ssl_.get(), params.data(), params.size()); - } - if (!ssl_config_.alpn_protos.empty()) { std::vector<uint8_t> wire_protos = SerializeNextProtos(ssl_config_.alpn_protos); @@ -1699,9 +1654,6 @@ } bool SSLClientSocketImpl::IsRenegotiationAllowed() const { - if (SSL_is_token_binding_negotiated(ssl_.get())) - return false; - if (negotiated_protocol_ == kProtoUnknown) return ssl_config_.renego_allowed_default;
diff --git a/net/socket/ssl_client_socket_impl.h b/net/socket/ssl_client_socket_impl.h index 14d3e10..186594c1 100644 --- a/net/socket/ssl_client_socket_impl.h +++ b/net/socket/ssl_client_socket_impl.h
@@ -53,10 +53,6 @@ class SSLInfo; class SSLKeyLogger; -using TokenBindingSignatureMap = - base::MRUCache<std::pair<TokenBindingType, std::string>, - std::vector<uint8_t>>; - class SSLClientSocketImpl : public SSLClientSocket, public SocketBIOAdapter::Delegate { public: @@ -107,9 +103,6 @@ void GetSSLCertRequestInfo( SSLCertRequestInfo* cert_request_info) const override; ChannelIDService* GetChannelIDService() const override; - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) override; crypto::ECPrivateKey* GetChannelIDKey() const override; void ApplySocketTag(const SocketTag& tag) override; @@ -219,13 +212,6 @@ const void* buf, size_t len); - int TokenBindingAdd(const uint8_t** out, - size_t* out_len, - int* out_alert_value); - int TokenBindingParse(const uint8_t* contents, - size_t contents_len, - int* out_alert_value); - void LogConnectEndEvent(int rv); // Record whether ALPN was used, and if so, the negotiated protocol, @@ -287,7 +273,6 @@ // The service for retrieving Channel ID keys. May be NULL. ChannelIDService* channel_id_service_; - TokenBindingSignatureMap tb_signature_map_; // OpenSSL stuff bssl::UniquePtr<SSL> ssl_;
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index 27ed3ee6..7e9a15c 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc
@@ -3066,52 +3066,6 @@ EXPECT_THAT(rv, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH)); } -TEST_F(SSLClientSocketTest, TokenBindingEnabled) { - SpawnedTestServer::SSLOptions ssl_options; - ssl_options.supported_token_binding_params.push_back(TB_PARAM_ECDSAP256); - ASSERT_TRUE(StartTestServer(ssl_options)); - - SSLConfig ssl_config; - ssl_config.token_binding_params.push_back(TB_PARAM_ECDSAP256); - - int rv; - ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); - EXPECT_THAT(rv, IsOk()); - SSLInfo info; - EXPECT_TRUE(sock_->GetSSLInfo(&info)); - EXPECT_TRUE(info.token_binding_negotiated); - EXPECT_EQ(TB_PARAM_ECDSAP256, info.token_binding_key_param); -} - -TEST_F(SSLClientSocketTest, TokenBindingFailsWithEmsDisabled) { - SpawnedTestServer::SSLOptions ssl_options; - ssl_options.supported_token_binding_params.push_back(TB_PARAM_ECDSAP256); - ssl_options.disable_extended_master_secret = true; - ASSERT_TRUE(StartTestServer(ssl_options)); - - SSLConfig ssl_config; - ssl_config.token_binding_params.push_back(TB_PARAM_ECDSAP256); - - int rv; - ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); - EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR)); -} - -TEST_F(SSLClientSocketTest, TokenBindingEnabledWithoutServerSupport) { - SpawnedTestServer::SSLOptions ssl_options; - ASSERT_TRUE(StartTestServer(ssl_options)); - - SSLConfig ssl_config; - ssl_config.token_binding_params.push_back(TB_PARAM_ECDSAP256); - - int rv; - ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); - EXPECT_THAT(rv, IsOk()); - SSLInfo info; - EXPECT_TRUE(sock_->GetSSLInfo(&info)); - EXPECT_FALSE(info.token_binding_negotiated); -} - TEST_F(SSLClientSocketFalseStartTest, FalseStartEnabled) { // False Start requires ALPN, ECDHE, and an AEAD. SpawnedTestServer::SSLOptions server_options;
diff --git a/net/socket/stream_socket.cc b/net/socket/stream_socket.cc index dd83d61..bf698ba 100644 --- a/net/socket/stream_socket.cc +++ b/net/socket/stream_socket.cc
@@ -23,13 +23,6 @@ return nullptr; } -Error StreamSocket::GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) { - NOTREACHED(); - return ERR_NOT_IMPLEMENTED; -} - crypto::ECPrivateKey* StreamSocket::GetChannelIDKey() const { NOTREACHED(); return nullptr;
diff --git a/net/socket/stream_socket.h b/net/socket/stream_socket.h index 1c5a6f06..41bb302f5 100644 --- a/net/socket/stream_socket.h +++ b/net/socket/stream_socket.h
@@ -14,7 +14,6 @@ #include "net/socket/connection_attempts.h" #include "net/socket/next_proto.h" #include "net/socket/socket.h" -#include "net/ssl/token_binding.h" namespace crypto { class ECPrivateKey; @@ -160,13 +159,6 @@ // not support SSL. virtual ChannelIDService* GetChannelIDService() const; - // Generates the signature used in Token Binding using key |*key| and for a - // Token Binding of type |tb_type|, putting the signature in |*out|. Returns a - // net error code. Must not be called on a socket that does not support SSL. - virtual Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out); - // This method is only for debugging https://crbug.com/548423 and will be // removed when that bug is closed. This returns the channel ID key that was // used when establishing the connection (or NULL if no channel ID was used).
diff --git a/net/socket/udp_socket_unittest.cc b/net/socket/udp_socket_unittest.cc index 79c32f7..e51998c 100644 --- a/net/socket/udp_socket_unittest.cc +++ b/net/socket/udp_socket_unittest.cc
@@ -54,18 +54,6 @@ namespace { -// Creates an address from ip address and port and writes it to |*address|. -bool CreateUDPAddress(const std::string& ip_str, - uint16_t port, - IPEndPoint* address) { - IPAddress ip_address; - if (!ip_address.AssignFromIPLiteral(ip_str)) - return false; - - *address = IPEndPoint(ip_address, port); - return true; -} - class UDPSocketTest : public PlatformTest, public WithScopedTaskEnvironment { public: UDPSocketTest() : buffer_(base::MakeRefCounted<IOBufferWithSize>(kMaxRead)) {} @@ -126,15 +114,14 @@ WriteSocket(socket, msg); } - // And again for a bare socket - int SendToSocket(UDPSocket* socket, - std::string msg, - const IPEndPoint& address) { - scoped_refptr<StringIOBuffer> io_buffer = new StringIOBuffer(msg); - TestCompletionCallback callback; - int rv = socket->SendTo(io_buffer.get(), io_buffer->size(), address, - callback.callback()); - return callback.GetResult(rv); + // Creates an address from ip address and port and writes it to |*address|. + void CreateUDPAddress(const std::string& ip_str, + uint16_t port, + IPEndPoint* address) { + IPAddress ip_address; + if (!ip_address.AssignFromIPLiteral(ip_str)) + return; + *address = IPEndPoint(ip_address, port); } // Run unit test for a connection test. @@ -326,9 +313,9 @@ std::string first_message("first message"), second_message("second message"); IPEndPoint broadcast_address; - ASSERT_TRUE(CreateUDPAddress("255.255.255.255", kPort, &broadcast_address)); + CreateUDPAddress("255.255.255.255", kPort, &broadcast_address); IPEndPoint listen_address; - ASSERT_TRUE(CreateUDPAddress("0.0.0.0", kPort, &listen_address)); + CreateUDPAddress("0.0.0.0", kPort, &listen_address); TestNetLog server1_log, server2_log; std::unique_ptr<UDPServerSocket> server1( @@ -597,7 +584,7 @@ TEST_F(UDPSocketTest, ServerSetDoNotFragment) { for (std::string ip : {"127.0.0.1", "::1"}) { IPEndPoint bind_address; - ASSERT_TRUE(CreateUDPAddress(ip, 0, &bind_address)); + CreateUDPAddress(ip, 0, &bind_address); UDPServerSocket server(nullptr, NetLogSource()); int rv = server.Listen(bind_address); // May fail on IPv6 is IPv6 is not configure @@ -646,7 +633,7 @@ const char kGroup[] = "237.132.100.17"; IPEndPoint bind_address; - ASSERT_TRUE(CreateUDPAddress("0.0.0.0", kPort, &bind_address)); + CreateUDPAddress("0.0.0.0", kPort, &bind_address); IPAddress group_ip; EXPECT_TRUE(group_ip.AssignFromIPLiteral(kGroup)); @@ -678,7 +665,7 @@ TEST_F(UDPSocketTest, MulticastOptions) { const uint16_t kPort = 9999; IPEndPoint bind_address; - ASSERT_TRUE(CreateUDPAddress("0.0.0.0", kPort, &bind_address)); + CreateUDPAddress("0.0.0.0", kPort, &bind_address); UDPSocket socket(DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource()); // Before binding. @@ -706,7 +693,7 @@ IPEndPoint bind_address; UDPSocket client(DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource()); // We need a real IP, but we won't actually send anything to it. - ASSERT_TRUE(CreateUDPAddress("8.8.8.8", 9999, &bind_address)); + CreateUDPAddress("8.8.8.8", 9999, &bind_address); int rv = client.Open(bind_address.GetFamily()); EXPECT_THAT(rv, IsOk()); @@ -784,255 +771,120 @@ namespace { const HANDLE kFakeHandle = (HANDLE)19; -const QOS_FLOWID kFakeFlowId1 = (QOS_FLOWID)27; -const QOS_FLOWID kFakeFlowId2 = (QOS_FLOWID)38; +const QOS_FLOWID kFakeFlowId = (QOS_FLOWID)27; -class TestUDPSocketWin : public UDPSocketWin { - public: - TestUDPSocketWin(QwaveAPI& qos, - DatagramSocket::BindType bind_type, - net::NetLog* net_log, - const net::NetLogSource& source) - : UDPSocketWin(bind_type, net_log, source), qos_(qos) {} - - // Overriding GetQwaveAPI causes the test class to use the injected mock - // QwaveAPI instance instead of the singleton. Ensure close is called in the - // child destructor before our mock CloseHandle is uninstalled. - ~TestUDPSocketWin() override { UDPSocketWin::Close(); } - - QwaveAPI& GetQwaveAPI() override { return qos_; } - - private: - QwaveAPI& qos_; - - DISALLOW_COPY_AND_ASSIGN(TestUDPSocketWin); -}; - -class MockQwaveAPI : public QwaveAPI { - public: - MOCK_METHOD2(CreateHandle, BOOL(PQOS_VERSION version, PHANDLE handle)); - MOCK_METHOD1(CloseHandle, BOOL(HANDLE handle)); - - MOCK_METHOD6(AddSocketToFlow, - BOOL(HANDLE handle, - SOCKET socket, - PSOCKADDR addr, - QOS_TRAFFIC_TYPE traffic_type, - DWORD flags, - PQOS_FLOWID flow_id)); - - MOCK_METHOD4( - RemoveSocketFromFlow, - BOOL(HANDLE handle, SOCKET socket, QOS_FLOWID flow_id, DWORD reserved)); - MOCK_METHOD7(SetFlow, - BOOL(HANDLE handle, - QOS_FLOWID flow_id, - QOS_SET_FLOW op, - ULONG size, - PVOID data, - DWORD reserved, - LPOVERLAPPED overlapped)); -}; - -std::unique_ptr<UDPSocket> OpenedDscpTestClient(QwaveAPI& qos, - IPEndPoint bind_address) { - auto client = std::make_unique<TestUDPSocketWin>( - qos, DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource()); - int rv = client->Open(bind_address.GetFamily()); - EXPECT_THAT(rv, IsOk()); - - return client; +BOOL WINAPI FakeQOSCreateHandleFAIL(PQOS_VERSION version, PHANDLE handle) { + EXPECT_EQ(0, version->MinorVersion); + EXPECT_EQ(1, version->MajorVersion); + SetLastError(ERROR_OPEN_FAILED); + return false; } -std::unique_ptr<UDPSocket> ConnectedDscpTestClient(QwaveAPI& qos) { - IPEndPoint bind_address; - // We need a real IP, but we won't actually send anything to it. - EXPECT_TRUE(CreateUDPAddress("8.8.8.8", 9999, &bind_address)); - auto client = OpenedDscpTestClient(qos, bind_address); - EXPECT_THAT(client->Connect(bind_address), IsOk()); - return client; +BOOL WINAPI FakeQOSCreateHandle(PQOS_VERSION version, PHANDLE handle) { + EXPECT_EQ(0, version->MinorVersion); + EXPECT_EQ(1, version->MajorVersion); + *handle = kFakeHandle; + return true; } -std::unique_ptr<UDPSocket> UnconnectedDscpTestClient(QwaveAPI& qos) { - IPEndPoint bind_address; - EXPECT_TRUE(CreateUDPAddress("0.0.0.0", 9999, &bind_address)); - auto client = OpenedDscpTestClient(qos, bind_address); - EXPECT_THAT(client->Bind(bind_address), IsOk()); - return client; +BOOL WINAPI FakeQOSCloseHandle(HANDLE handle) { + EXPECT_EQ(kFakeHandle, handle); + return true; +} + +QOS_TRAFFIC_TYPE g_expected_traffic_type; + +BOOL WINAPI FakeQOSAddSocketToFlow(HANDLE handle, + SOCKET socket, + PSOCKADDR addr, + QOS_TRAFFIC_TYPE traffic_type, + DWORD flags, + PQOS_FLOWID flow_id) { + EXPECT_EQ(kFakeHandle, handle); + EXPECT_EQ(NULL, addr); + EXPECT_EQ(static_cast<DWORD>(QOS_NON_ADAPTIVE_FLOW), flags); + EXPECT_EQ(0u, *flow_id); + *flow_id = kFakeFlowId; + return true; +} + +BOOL WINAPI FakeQOSRemoveSocketFromFlow(HANDLE handle, + SOCKET socket, + QOS_FLOWID flowid, + DWORD reserved) { + EXPECT_EQ(kFakeHandle, handle); + EXPECT_EQ(0u, socket); + EXPECT_EQ(kFakeFlowId, flowid); + EXPECT_EQ(0u, reserved); + return true; +} + +DWORD g_expected_dscp; + +BOOL WINAPI FakeQOSSetFlow(HANDLE handle, + QOS_FLOWID flow_id, + QOS_SET_FLOW op, + ULONG size, + PVOID data, + DWORD reserved, + LPOVERLAPPED overlapped) { + EXPECT_EQ(kFakeHandle, handle); + EXPECT_EQ(QOSSetOutgoingDSCPValue, op); + EXPECT_EQ(sizeof(DWORD), size); + EXPECT_EQ(g_expected_dscp, *reinterpret_cast<DWORD*>(data)); + EXPECT_EQ(kFakeFlowId, flow_id); + EXPECT_EQ(0u, reserved); + EXPECT_EQ(NULL, overlapped); + return true; } } // namespace -using ::testing::_; -using ::testing::Return; -using ::testing::SetArgPointee; +// Mock out the Qwave functions and make sure they are +// called correctly. Must be in net namespace for friendship +// reasons. +TEST_F(UDPSocketTest, SetDSCPFake) { + // Setup the server to listen. + IPEndPoint bind_address; + // We need a real IP, but we won't actually send anything to it. + CreateUDPAddress("8.8.8.8", 9999, &bind_address); + UDPSocket client(DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource()); + int rv = client.SetDiffServCodePoint(DSCP_AF41); + EXPECT_THAT(rv, IsError(ERR_SOCKET_NOT_CONNECTED)); -TEST_F(UDPSocketTest, SetDSCPNoopIfPassedNoChange) { - MockQwaveAPI qos; - std::unique_ptr<UDPSocket> client = ConnectedDscpTestClient(qos); - EXPECT_THAT(client->SetDiffServCodePoint(DSCP_NO_CHANGE), IsOk()); -} + rv = client.Open(bind_address.GetFamily()); + EXPECT_THAT(rv, IsOk()); -TEST_F(UDPSocketTest, SetDSCPFailsIfQOSHandleCanNotBeCreated) { - MockQwaveAPI qos; - std::unique_ptr<UDPSocket> client = ConnectedDscpTestClient(qos); + rv = client.Connect(bind_address); + EXPECT_THAT(rv, IsOk()); - EXPECT_CALL(qos, CreateHandle(_, _)).WillOnce(Return(false)); - EXPECT_EQ(ERROR_NOT_SUPPORTED, client->SetDiffServCodePoint(DSCP_AF41)); -} + QwaveAPI& qos(QwaveAPI::Get()); + qos.create_handle_func_ = FakeQOSCreateHandleFAIL; + qos.close_handle_func_ = FakeQOSCloseHandle; + qos.add_socket_to_flow_func_ = FakeQOSAddSocketToFlow; + qos.remove_socket_from_flow_func_ = FakeQOSRemoveSocketFromFlow; + qos.set_flow_func_ = FakeQOSSetFlow; + qos.qwave_supported_ = true; -MATCHER_P(DscpPointee, dscp, "") { - return *(DWORD*)arg == (DWORD)dscp; -} - -TEST_F(UDPSocketTest, SetDSCPCallsQwaveFunctions) { - MockQwaveAPI qos; - std::unique_ptr<UDPSocket> client = ConnectedDscpTestClient(qos); - - EXPECT_CALL(qos, CreateHandle(_, _)) - .WillOnce(DoAll(SetArgPointee<1>(kFakeHandle), Return(true))); - // AddSocketToFlow also sets flow_id, but we don't use that here - EXPECT_CALL(qos, AddSocketToFlow(_, _, _, QOSTrafficTypeAudioVideo, _, _)) - .WillOnce(Return(true)); - EXPECT_CALL(qos, SetFlow(_, _, QOSSetOutgoingDSCPValue, _, - DscpPointee(DSCP_AF41), _, _)); - EXPECT_THAT(client->SetDiffServCodePoint(DSCP_AF41), IsOk()); - EXPECT_CALL(qos, CloseHandle(kFakeHandle)); -} - -TEST_F(UDPSocketTest, SecondSetDSCPCallsQwaveFunctions) { - MockQwaveAPI qos; - std::unique_ptr<UDPSocket> client = ConnectedDscpTestClient(qos); - - EXPECT_CALL(qos, CreateHandle(_, _)) - .WillOnce(DoAll(SetArgPointee<1>(kFakeHandle), Return(true))); - - EXPECT_CALL(qos, AddSocketToFlow(_, _, _, _, _, _)) - .WillOnce(DoAll(SetArgPointee<5>(kFakeFlowId1), Return(true))); - EXPECT_CALL(qos, SetFlow(_, _, _, _, _, _, _)); - EXPECT_THAT(client->SetDiffServCodePoint(DSCP_AF41), IsOk()); - - // New dscp value should reset the flow. - EXPECT_CALL(qos, RemoveSocketFromFlow(_, _, _, _)); - EXPECT_CALL(qos, AddSocketToFlow(_, _, _, QOSTrafficTypeBestEffort, _, _)) - .WillOnce(DoAll(SetArgPointee<5>(kFakeFlowId2), Return(true))); - EXPECT_CALL(qos, SetFlow(_, _, QOSSetOutgoingDSCPValue, _, - DscpPointee(DSCP_DEFAULT), _, _)); - EXPECT_THAT(client->SetDiffServCodePoint(DSCP_DEFAULT), IsOk()); - - // Called from DscpManager destructor. - EXPECT_CALL(qos, RemoveSocketFromFlow(_, _, _, _)); - EXPECT_CALL(qos, CloseHandle(kFakeHandle)); -} - -// TODO(zstein): Mocking out DscpManager might be simpler here -// (just verify that DscpManager::Set and DscpManager::PrepareForSend are -// called). -TEST_F(UDPSocketTest, SendToCallsQwaveApis) { - MockQwaveAPI qos; - std::unique_ptr<UDPSocket> client = UnconnectedDscpTestClient(qos); - - EXPECT_CALL(qos, CreateHandle(_, _)) - .WillOnce(DoAll(SetArgPointee<1>(kFakeHandle), Return(true))); - EXPECT_THAT(client->SetDiffServCodePoint(DSCP_AF41), IsOk()); - - EXPECT_CALL(qos, AddSocketToFlow(_, _, _, _, _, _)) - .WillOnce(DoAll(SetArgPointee<5>(kFakeFlowId1), Return(true))); - EXPECT_CALL(qos, SetFlow(_, _, _, _, _, _, _)); - - std::string simple_message("hello world"); - IPEndPoint server_address(IPAddress::IPv4Localhost(), 9438); - int rv = SendToSocket(client.get(), simple_message, server_address); - EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv)); - - // TODO(zstein): Move to second test case (Qwave APIs called once per address) - rv = SendToSocket(client.get(), simple_message, server_address); - EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv)); - - // TODO(zstein): Move to third test case (Qwave APIs called for each - // destination address). - EXPECT_CALL(qos, AddSocketToFlow(_, _, _, _, _, _)).WillOnce(Return(true)); - IPEndPoint server_address2(IPAddress::IPv4Localhost(), 9439); - - rv = SendToSocket(client.get(), simple_message, server_address2); - EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv)); - - // Called from DscpManager destructor. - EXPECT_CALL(qos, RemoveSocketFromFlow(_, _, _, _)); - EXPECT_CALL(qos, CloseHandle(kFakeHandle)); -} - -class DscpManagerTest : public testing::Test { - protected: - DscpManagerTest() : dscp_manager_(qos_, INVALID_SOCKET, (HANDLE)0) { - CreateUDPAddress("1.2.3.4", 9001, &address1_); - CreateUDPAddress("1234:5678:90ab:cdef:1234:5678:90ab:cdef", 9002, - &address2_); - } - - MockQwaveAPI qos_; - DscpManager dscp_manager_; - - IPEndPoint address1_; - IPEndPoint address2_; -}; - -TEST_F(DscpManagerTest, PrepareForSendIsNoopIfNoSet) { - dscp_manager_.PrepareForSend(address1_); -} - -TEST_F(DscpManagerTest, PrepareForSendCallsQwaveApisAfterSet) { - dscp_manager_.Set(DSCP_CS2); - - // AddSocketToFlow should be called for each address. - EXPECT_CALL(qos_, AddSocketToFlow(_, _, _, _, _, _)) - .WillOnce(DoAll(SetArgPointee<5>(kFakeFlowId1), Return(true))) - .WillOnce(Return(true)); - // SetFlow should only be called when the flow is first created. - EXPECT_CALL(qos_, SetFlow(_, _, _, _, _, _, _)); - dscp_manager_.PrepareForSend(address1_); - EXPECT_CALL(qos_, SetFlow(_, _, _, _, _, _, _)).Times(0); - dscp_manager_.PrepareForSend(address2_); - - // Called from DscpManager destructor. - EXPECT_CALL(qos_, RemoveSocketFromFlow(_, _, _, _)); -} - -TEST_F(DscpManagerTest, PrepareForSendCallsQwaveApisOncePerAddress) { - dscp_manager_.Set(DSCP_CS2); - - EXPECT_CALL(qos_, AddSocketToFlow(_, _, _, _, _, _)) - .WillOnce(DoAll(SetArgPointee<5>(kFakeFlowId1), Return(true))); - EXPECT_CALL(qos_, SetFlow(_, _, _, _, _, _, _)); - dscp_manager_.PrepareForSend(address1_); - EXPECT_CALL(qos_, AddSocketToFlow(_, _, _, _, _, _)).Times(0); - EXPECT_CALL(qos_, SetFlow(_, _, _, _, _, _, _)).Times(0); - dscp_manager_.PrepareForSend(address1_); - - // Called from DscpManager destructor. - EXPECT_CALL(qos_, RemoveSocketFromFlow(_, _, _, _)); -} - -TEST_F(DscpManagerTest, SetDestroysExistingFlowAndResetsPrepareState) { - dscp_manager_.Set(DSCP_CS2); - EXPECT_CALL(qos_, AddSocketToFlow(_, _, _, _, _, _)) - .WillOnce(DoAll(SetArgPointee<5>(kFakeFlowId1), Return(true))); - EXPECT_CALL(qos_, SetFlow(_, _, _, _, _, _, _)); - dscp_manager_.PrepareForSend(address1_); - - // Calling Set should destroy the existing flow. - // TODO(zstein): Verify that RemoveSocketFromFlow with no address - // destroys the flow for all destinations. - EXPECT_CALL(qos_, RemoveSocketFromFlow(_, NULL, kFakeFlowId1, _)); - dscp_manager_.Set(DSCP_CS5); - - EXPECT_CALL(qos_, AddSocketToFlow(_, _, _, _, _, _)) - .WillOnce(DoAll(SetArgPointee<5>(kFakeFlowId2), Return(true))); - EXPECT_CALL(qos_, SetFlow(_, _, _, _, _, _, _)); - dscp_manager_.PrepareForSend(address1_); - - // Called from DscpManager destructor. - EXPECT_CALL(qos_, RemoveSocketFromFlow(_, _, kFakeFlowId2, _)); + EXPECT_THAT(client.SetDiffServCodePoint(DSCP_NO_CHANGE), IsOk()); + EXPECT_EQ(ERROR_NOT_SUPPORTED, client.SetDiffServCodePoint(DSCP_AF41)); + qos.create_handle_func_ = FakeQOSCreateHandle; + g_expected_dscp = DSCP_AF41; + g_expected_traffic_type = QOSTrafficTypeAudioVideo; + EXPECT_THAT(client.SetDiffServCodePoint(DSCP_AF41), IsOk()); + g_expected_dscp = DSCP_DEFAULT; + g_expected_traffic_type = QOSTrafficTypeBestEffort; + EXPECT_THAT(client.SetDiffServCodePoint(DSCP_DEFAULT), IsOk()); + g_expected_dscp = DSCP_CS2; + g_expected_traffic_type = QOSTrafficTypeExcellentEffort; + EXPECT_THAT(client.SetDiffServCodePoint(DSCP_CS2), IsOk()); + g_expected_dscp = DSCP_CS3; + g_expected_traffic_type = QOSTrafficTypeExcellentEffort; + EXPECT_THAT(client.SetDiffServCodePoint(DSCP_NO_CHANGE), IsOk()); + g_expected_dscp = DSCP_DEFAULT; + g_expected_traffic_type = QOSTrafficTypeBestEffort; + EXPECT_THAT(client.SetDiffServCodePoint(DSCP_DEFAULT), IsOk()); + client.Close(); } #endif
diff --git a/net/socket/udp_socket_win.cc b/net/socket/udp_socket_win.cc index 9f48f4d..945d9e8b 100644 --- a/net/socket/udp_socket_win.cc +++ b/net/socket/udp_socket_win.cc
@@ -56,7 +56,7 @@ void WatchForWrite(); // The UDPSocketWin is going away. - void Detach() { socket_ = nullptr; } + void Detach() { socket_ = NULL; } // The separate OVERLAPPED variables for asynchronous operation. OVERLAPPED read_overlapped_; @@ -260,6 +260,7 @@ recv_from_address_(nullptr), net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::UDP_SOCKET)), qos_handle_(nullptr), + qos_flow_id_(0), event_pending_(this) { EnsureWinsockInit(); net_log_.BeginEvent(NetLogEventType::SOCKET_ALIVE, @@ -295,15 +296,12 @@ if (socket_ == INVALID_SOCKET) return; - if (qos_handle_) { - GetQwaveAPI().CloseHandle(qos_handle_); - dscp_manager_ = nullptr; - qos_handle_ = NULL; - } + if (qos_handle_) + QwaveAPI::Get().CloseHandle(qos_handle_); // Zero out any pending read/write callback state. read_callback_.Reset(); - recv_from_address_ = nullptr; + recv_from_address_ = NULL; write_callback_.Reset(); base::TimeTicks start_time = base::TimeTicks::Now(); @@ -327,7 +325,7 @@ if (core_) { core_->Detach(); - core_ = nullptr; + core_ = NULL; } } @@ -380,7 +378,7 @@ int UDPSocketWin::Read(IOBuffer* buf, int buf_len, CompletionOnceCallback callback) { - return RecvFrom(buf, buf_len, nullptr, std::move(callback)); + return RecvFrom(buf, buf_len, NULL, std::move(callback)); } int UDPSocketWin::RecvFrom(IOBuffer* buf, @@ -417,13 +415,6 @@ int buf_len, const IPEndPoint& address, CompletionOnceCallback callback) { - if (dscp_manager_) { - // Alert DscpManager in case this is a new remote address. Failure to - // apply Dscp code is never fatal. - int rv = dscp_manager_->PrepareForSend(address); - if (rv != OK) - net_log_.AddEventWithNetErrorCode(NetLogEventType::UDP_SEND_ERROR, rv); - } return SendToOrWrite(buf, buf_len, &address, std::move(callback)); } @@ -490,10 +481,6 @@ return MapSystemError(WSAGetLastError()); remote_address_.reset(new IPEndPoint(address)); - - if (dscp_manager_) - dscp_manager_->PrepareForSend(*remote_address_.get()); - return rv; } @@ -624,7 +611,7 @@ int result = ok ? num_bytes : MapSystemError(WSAGetLastError()); // Convert address. IPEndPoint address; - IPEndPoint* address_to_log = nullptr; + IPEndPoint* address_to_log = NULL; if (result >= 0) { if (address.FromSockAddr(core_->recv_addr_storage_.addr, core_->recv_addr_storage_.addr_len)) { @@ -636,8 +623,8 @@ } } LogRead(result, core_->read_iobuffer_->data(), address_to_log); - core_->read_iobuffer_ = nullptr; - recv_from_address_ = nullptr; + core_->read_iobuffer_ = NULL; + recv_from_address_ = NULL; DoReadCallback(result); } @@ -650,7 +637,7 @@ LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get()); send_to_address_.reset(); - core_->write_iobuffer_ = nullptr; + core_->write_iobuffer_ = NULL; DoWriteCallback(result); } @@ -704,9 +691,9 @@ recv_from_address_); if (rv == ERR_IO_PENDING) return; - read_iobuffer_ = nullptr; + read_iobuffer_ = NULL; read_iobuffer_len_ = 0; - recv_from_address_ = nullptr; + recv_from_address_ = NULL; DoReadCallback(rv); } @@ -715,7 +702,7 @@ send_to_address_.get()); if (rv == ERR_IO_PENDING) return; - write_iobuffer_ = nullptr; + write_iobuffer_ = NULL; write_iobuffer_len_ = 0; send_to_address_.reset(); DoWriteCallback(rv); @@ -780,13 +767,13 @@ CHECK_NE(INVALID_SOCKET, socket_); AssertEventNotSignaled(core_->read_overlapped_.hEvent); int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr, - &storage.addr_len, &core_->read_overlapped_, nullptr); + &storage.addr_len, &core_->read_overlapped_, NULL); if (rv == 0) { if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { int result = num; // Convert address. IPEndPoint address_storage; - IPEndPoint* address_to_log = nullptr; + IPEndPoint* address_to_log = NULL; if (result >= 0) { if (address_storage.FromSockAddr(core_->recv_addr_storage_.addr, core_->recv_addr_storage_.addr_len)) { @@ -804,7 +791,7 @@ int os_error = WSAGetLastError(); if (os_error != WSA_IO_PENDING) { int result = MapSystemError(os_error); - LogRead(result, nullptr, nullptr); + LogRead(result, NULL, NULL); return result; } } @@ -821,12 +808,12 @@ struct sockaddr* addr = storage.addr; // Convert address. if (!address) { - addr = nullptr; + addr = NULL; storage.addr_len = 0; } else { if (!address->ToSockAddr(addr, &storage.addr_len)) { int result = ERR_ADDRESS_INVALID; - LogWrite(result, nullptr, nullptr); + LogWrite(result, NULL, NULL); return result; } } @@ -838,8 +825,8 @@ DWORD flags = 0; DWORD num; AssertEventNotSignaled(core_->write_overlapped_.hEvent); - int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags, addr, - storage.addr_len, &core_->write_overlapped_, nullptr); + int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags, + addr, storage.addr_len, &core_->write_overlapped_, NULL); if (rv == 0) { if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { int result = num; @@ -850,7 +837,7 @@ int os_error = WSAGetLastError(); if (os_error != WSA_IO_PENDING) { int result = MapSystemError(os_error); - LogWrite(result, nullptr, nullptr); + LogWrite(result, NULL, NULL); return result; } } @@ -879,11 +866,11 @@ return ERR_IO_PENDING; } rv = MapSystemError(os_error); - LogRead(rv, nullptr, nullptr); + LogRead(rv, NULL, NULL); return rv; } IPEndPoint address_storage; - IPEndPoint* address_to_log = nullptr; + IPEndPoint* address_to_log = NULL; if (rv >= 0) { if (address_storage.FromSockAddr(storage.addr, storage.addr_len)) { if (address) @@ -907,11 +894,11 @@ if (address) { if (!address->ToSockAddr(addr, &storage.addr_len)) { int result = ERR_ADDRESS_INVALID; - LogWrite(result, nullptr, nullptr); + LogWrite(result, NULL, NULL); return result; } } else { - addr = nullptr; + addr = NULL; storage.addr_len = 0; } @@ -925,7 +912,7 @@ return ERR_IO_PENDING; } rv = MapSystemError(os_error); - LogWrite(rv, nullptr, nullptr); + LogWrite(rv, NULL, NULL); return rv; } LogWrite(rv, buf->data(), address); @@ -1015,10 +1002,6 @@ return DoBind(IPEndPoint(address, 0)); } -QwaveAPI& UDPSocketWin::GetQwaveAPI() { - return QwaveAPI::Get(); -} - int UDPSocketWin::JoinGroup(const IPAddress& group_address) const { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (!is_connected()) @@ -1128,7 +1111,28 @@ return OK; } -QOS_TRAFFIC_TYPE DscpToTrafficType(DiffServCodePoint dscp) { +int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) { + if (dscp == DSCP_NO_CHANGE) { + return OK; + } + + if (!is_connected()) + return ERR_SOCKET_NOT_CONNECTED; + + QwaveAPI& qos(QwaveAPI::Get()); + + if (!qos.qwave_supported()) + return ERROR_NOT_SUPPORTED; + + if (qos_handle_ == NULL) { + QOS_VERSION version; + version.MajorVersion = 1; + version.MinorVersion = 0; + qos.CreateHandle(&version, &qos_handle_); + if (qos_handle_ == NULL) + return ERROR_NOT_SUPPORTED; + } + QOS_TRAFFIC_TYPE traffic_type = QOSTrafficTypeBestEffort; switch (dscp) { case DSCP_CS0: @@ -1168,36 +1172,34 @@ NOTREACHED(); break; } - return traffic_type; -} - -int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) { - if (dscp == DSCP_NO_CHANGE) - return OK; - - if (!is_connected()) - return ERR_SOCKET_NOT_CONNECTED; - - QwaveAPI& qos(GetQwaveAPI()); - - if (!qos.qwave_supported()) - return ERROR_NOT_SUPPORTED; - - if (!qos_handle_) { - QOS_VERSION version; - version.MajorVersion = 1; - version.MinorVersion = 0; - qos.CreateHandle(&version, &qos_handle_); - if (!qos_handle_) - return ERROR_NOT_SUPPORTED; + if (qos_flow_id_ != 0) { + qos.RemoveSocketFromFlow(qos_handle_, NULL, qos_flow_id_, 0); + qos_flow_id_ = 0; } - - if (!dscp_manager_) - dscp_manager_ = std::make_unique<DscpManager>(qos, socket_, qos_handle_); - - dscp_manager_->Set(dscp); - if (remote_address_) - return dscp_manager_->PrepareForSend(*remote_address_.get()); + if (!qos.AddSocketToFlow(qos_handle_, + socket_, + NULL, + traffic_type, + QOS_NON_ADAPTIVE_FLOW, + &qos_flow_id_)) { + DWORD err = GetLastError(); + if (err == ERROR_DEVICE_REINITIALIZATION_NEEDED) { + qos.CloseHandle(qos_handle_); + qos_flow_id_ = 0; + qos_handle_ = 0; + } + return MapSystemError(err); + } + // This requires admin rights, and may fail, if so we ignore it + // as AddSocketToFlow should still do *approximately* the right thing. + DWORD buf = dscp; + qos.SetFlow(qos_handle_, + qos_flow_id_, + QOSSetOutgoingDSCPValue, + sizeof(buf), + &buf, + 0, + NULL); return OK; } @@ -1248,70 +1250,5 @@ NOTIMPLEMENTED(); return result; } -DscpManager::DscpManager(QwaveAPI& qos, SOCKET socket, HANDLE qos_handle) - : qos_(qos), socket_(socket), qos_handle_(qos_handle) {} - -DscpManager::~DscpManager() { - if (flow_id_ != 0) - qos_.RemoveSocketFromFlow(qos_handle_, NULL, flow_id_, 0); -} - -void DscpManager::Set(DiffServCodePoint dscp) { - if (dscp == DSCP_NO_CHANGE || dscp == dscp_value_) - return; - - dscp_value_ = dscp; - // TODO(zstein): We could reuse the flow when the value changes - // by calling QOSSetFlow with the new traffic type and dscp value. - if (flow_id_ != 0) { - qos_.RemoveSocketFromFlow(qos_handle_, NULL, flow_id_, 0); - configured_.clear(); - flow_id_ = 0; - } -} - -int DscpManager::PrepareForSend(const IPEndPoint& remote_address) { - if (dscp_value_ == DSCP_NO_CHANGE) { - // No DSCP value has been set. - return OK; - } - - if (configured_.find(remote_address) != configured_.end()) - return OK; - - SockaddrStorage storage; - if (!remote_address.ToSockAddr(storage.addr, &storage.addr_len)) - return ERR_ADDRESS_INVALID; - - // We won't try again if we get an error. - configured_.emplace(remote_address); - - // We don't need to call SetFlow if we already have a qos flow. - bool new_flow = flow_id_ == 0; - - const QOS_TRAFFIC_TYPE traffic_type = DscpToTrafficType(dscp_value_); - - if (!qos_.AddSocketToFlow(qos_handle_, socket_, storage.addr, traffic_type, - QOS_NON_ADAPTIVE_FLOW, &flow_id_)) { - DWORD err = GetLastError(); - if (err == ERROR_DEVICE_REINITIALIZATION_NEEDED) { - qos_.CloseHandle(qos_handle_); - flow_id_ = 0; - qos_handle_ = 0; - dscp_value_ = DSCP_NO_CHANGE; - } - return MapSystemError(err); - } - - if (new_flow) { - DWORD buf = dscp_value_; - // This requires admin rights, and may fail, if so we ignore it - // as AddSocketToFlow should still do *approximately* the right thing. - qos_.SetFlow(qos_handle_, flow_id_, QOSSetOutgoingDSCPValue, sizeof(buf), - &buf, 0, nullptr); - } - - return OK; -} } // namespace net
diff --git a/net/socket/udp_socket_win.h b/net/socket/udp_socket_win.h index 8240fc86..81cd245f 100644 --- a/net/socket/udp_socket_win.h +++ b/net/socket/udp_socket_win.h
@@ -37,110 +37,6 @@ struct NetLogSource; class SocketTag; -// QWAVE (Quality Windows Audio/Video Experience) is the latest windows -// library for setting packet priorities (and other things). Unfortunately, -// Microsoft has decided that setting the DSCP bits with setsockopt() no -// longer works, so we have to use this API instead. -// This class is meant to be used as a singleton. It exposes a few dynamically -// loaded functions and a bool called "qwave_supported". -class NET_EXPORT QwaveAPI { - typedef BOOL(WINAPI* CreateHandleFn)(PQOS_VERSION, PHANDLE); - typedef BOOL(WINAPI* CloseHandleFn)(HANDLE); - typedef BOOL(WINAPI* AddSocketToFlowFn)(HANDLE, - SOCKET, - PSOCKADDR, - QOS_TRAFFIC_TYPE, - DWORD, - PQOS_FLOWID); - typedef BOOL(WINAPI* RemoveSocketFromFlowFn)(HANDLE, - SOCKET, - QOS_FLOWID, - DWORD); - typedef BOOL(WINAPI* SetFlowFn)(HANDLE, - QOS_FLOWID, - QOS_SET_FLOW, - ULONG, - PVOID, - DWORD, - LPOVERLAPPED); - - public: - QwaveAPI(); - virtual ~QwaveAPI() = default; - - static QwaveAPI& Get(); - - virtual bool qwave_supported() const; - virtual BOOL CreateHandle(PQOS_VERSION version, PHANDLE handle); - virtual BOOL CloseHandle(HANDLE handle); - virtual BOOL AddSocketToFlow(HANDLE handle, - SOCKET socket, - PSOCKADDR addr, - QOS_TRAFFIC_TYPE traffic_type, - DWORD flags, - PQOS_FLOWID flow_id); - virtual BOOL RemoveSocketFromFlow(HANDLE handle, - SOCKET socket, - QOS_FLOWID flow_id, - DWORD reserved); - virtual BOOL SetFlow(HANDLE handle, - QOS_FLOWID flow_id, - QOS_SET_FLOW op, - ULONG size, - PVOID data, - DWORD reserved, - LPOVERLAPPED overlapped); - - private: - FRIEND_TEST_ALL_PREFIXES(UDPSocketTest, SetDSCPFake); - - bool qwave_supported_; - CreateHandleFn create_handle_func_; - CloseHandleFn close_handle_func_; - AddSocketToFlowFn add_socket_to_flow_func_; - RemoveSocketFromFlowFn remove_socket_from_flow_func_; - SetFlowFn set_flow_func_; - - DISALLOW_COPY_AND_ASSIGN(QwaveAPI); -}; - -//----------------------------------------------------------------------------- - -// Helper for maintaining the state that (unlike a blanket socket option), DSCP -// values are set per-remote endpoint instead of just per-socket on Windows. -// The implementation creates a single QWAVE 'flow' for the socket, and adds -// all encountered remote addresses to that flow. Flows are the minimum -// manageable unit within the QWAVE API. See -// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/qos2/ -// for Microsoft's documentation. -class NET_EXPORT DscpManager { - public: - DscpManager(QwaveAPI& qos, SOCKET socket, HANDLE qos_handle); - ~DscpManager(); - - // Remembers the latest |dscp| so PrepareToSend can add remote addresses to - // the qos flow. Destroys the old flow if it exists and |dscp| changes. - void Set(DiffServCodePoint dscp); - - // Constructs a qos flow for the latest set DSCP value if we don't already - // have one. Adds |remote_address| to the qos flow if it hasn't been added - // already. Does nothing if no DSCP value has been Set. - int PrepareForSend(const IPEndPoint& remote_address); - - private: - QwaveAPI& qos_; - SOCKET socket_; - HANDLE qos_handle_; - - DiffServCodePoint dscp_value_ = DSCP_NO_CHANGE; - // The remote addresses currently in the flow. - std::set<IPEndPoint> configured_; - // 0 means no flow has been constructed. - QOS_FLOWID flow_id_ = 0; -}; - -//----------------------------------------------------------------------------- - class NET_EXPORT UDPSocketWin : public base::win::ObjectWatcher::Delegate { public: UDPSocketWin(DatagramSocket::BindType bind_type, @@ -389,11 +285,6 @@ // Binds to a random port on |address|. int RandomBind(const IPAddress& address); - // This is provided to allow QwaveAPI mocking in tests. |UDPSocketWin| method - // implementations should call |GetQwaveAPI()| instead of |QwaveAPI::Get()| - // directly. - virtual QwaveAPI& GetQwaveAPI(); - SOCKET socket_; int addr_family_; bool is_connected_; @@ -455,9 +346,7 @@ // QWAVE data. Used to set DSCP bits on outgoing packets. HANDLE qos_handle_; - - // Maintains remote addresses for QWAVE qos management. - std::unique_ptr<DscpManager> dscp_manager_; + QOS_FLOWID qos_flow_id_; THREAD_CHECKER(thread_checker_); @@ -470,6 +359,60 @@ //----------------------------------------------------------------------------- +// QWAVE (Quality Windows Audio/Video Experience) is the latest windows +// library for setting packet priorities (and other things). Unfortunately, +// Microsoft has decided that setting the DSCP bits with setsockopt() no +// longer works, so we have to use this API instead. +// This class is meant to be used as a singleton. It exposes a few dynamically +// loaded functions and a bool called "qwave_supported". +class NET_EXPORT QwaveAPI { + typedef BOOL (WINAPI *CreateHandleFn)(PQOS_VERSION, PHANDLE); + typedef BOOL (WINAPI *CloseHandleFn)(HANDLE); + typedef BOOL (WINAPI *AddSocketToFlowFn)( + HANDLE, SOCKET, PSOCKADDR, QOS_TRAFFIC_TYPE, DWORD, PQOS_FLOWID); + typedef BOOL (WINAPI *RemoveSocketFromFlowFn)( + HANDLE, SOCKET, QOS_FLOWID, DWORD); + typedef BOOL (WINAPI *SetFlowFn)( + HANDLE, QOS_FLOWID, QOS_SET_FLOW, ULONG, PVOID, DWORD, LPOVERLAPPED); + + public: + QwaveAPI(); + + static QwaveAPI& Get(); + + bool qwave_supported() const; + BOOL CreateHandle(PQOS_VERSION version, PHANDLE handle); + BOOL CloseHandle(HANDLE handle); + BOOL AddSocketToFlow(HANDLE handle, + SOCKET socket, + PSOCKADDR addr, + QOS_TRAFFIC_TYPE traffic_type, + DWORD flags, + PQOS_FLOWID flow_id); + BOOL RemoveSocketFromFlow(HANDLE handle, + SOCKET socket, + QOS_FLOWID flow_id, + DWORD reserved); + BOOL SetFlow(HANDLE handle, + QOS_FLOWID flow_id, + QOS_SET_FLOW op, + ULONG size, + PVOID data, + DWORD reserved, + LPOVERLAPPED overlapped); + + private: + FRIEND_TEST_ALL_PREFIXES(UDPSocketTest, SetDSCPFake); + + bool qwave_supported_; + CreateHandleFn create_handle_func_; + CloseHandleFn close_handle_func_; + AddSocketToFlowFn add_socket_to_flow_func_; + RemoveSocketFromFlowFn remove_socket_from_flow_func_; + SetFlowFn set_flow_func_; + + DISALLOW_COPY_AND_ASSIGN(QwaveAPI); +}; } // namespace net
diff --git a/net/spdy/multiplexed_http_stream.cc b/net/spdy/multiplexed_http_stream.cc index a11ef9b6f..cdfb865 100644 --- a/net/spdy/multiplexed_http_stream.cc +++ b/net/spdy/multiplexed_http_stream.cc
@@ -37,13 +37,6 @@ NOTREACHED(); } -Error MultiplexedHttpStream::GetTokenBindingSignature( - crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) { - return session_->GetTokenBindingSignature(key, tb_type, out); -} - void MultiplexedHttpStream::Drain(HttpNetworkSession* session) { NOTREACHED(); Close(false);
diff --git a/net/spdy/multiplexed_http_stream.h b/net/spdy/multiplexed_http_stream.h index f731ff8..f2c34fb7 100644 --- a/net/spdy/multiplexed_http_stream.h +++ b/net/spdy/multiplexed_http_stream.h
@@ -26,9 +26,6 @@ bool GetRemoteEndpoint(IPEndPoint* endpoint) override; void GetSSLInfo(SSLInfo* ssl_info) override; void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override; - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) override; void Drain(HttpNetworkSession* session) override; HttpStream* RenewStreamForAuth() override; void SetConnectionReused() override;
diff --git a/net/spdy/multiplexed_session.cc b/net/spdy/multiplexed_session.cc index 6429cfc..61086319 100644 --- a/net/spdy/multiplexed_session.cc +++ b/net/spdy/multiplexed_session.cc
@@ -33,13 +33,4 @@ has_ssl_info_ = session_->GetSSLInfo(&ssl_info_); } -Error MultiplexedSessionHandle::GetTokenBindingSignature( - crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) { - if (!session_) - return ERR_CONNECTION_CLOSED; - return session_->GetTokenBindingSignature(key, tb_type, out); -} - } // namespace net
diff --git a/net/spdy/multiplexed_session.h b/net/spdy/multiplexed_session.h index aaeb292..79ac978 100644 --- a/net/spdy/multiplexed_session.h +++ b/net/spdy/multiplexed_session.h
@@ -11,11 +11,6 @@ #include "net/base/net_errors.h" #include "net/http/http_stream.h" #include "net/ssl/ssl_info.h" -#include "net/ssl/token_binding.h" - -namespace crypto { -class ECPrivateKey; -} // namespace crypto namespace net { @@ -31,13 +26,6 @@ // any. Returns true and fills in |endpoint| if it is available; returns false // and does not modify |endpoint| if it is unavailable. virtual bool GetRemoteEndpoint(IPEndPoint* endpoint) = 0; - - // Generates the signature used in Token Binding using key |*key| and for a - // Token Binding of type |tb_type|, putting the signature in |*out|. Returns a - // net error code. - virtual Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) = 0; }; // A handle to a multiplexed session which will be valid even after the @@ -58,13 +46,6 @@ // Caches SSL info from the underlying session. void SaveSSLInfo(); - // Generates the signature used in Token Binding using key |*key| and for a - // Token Binding of type |tb_type|, putting the signature in |*out|. Returns a - // net error code. - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out); - private: base::WeakPtr<MultiplexedSession> session_; SSLInfo ssl_info_;
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index b8d54afa..5f38d336 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc
@@ -1275,12 +1275,6 @@ return connection_->socket()->GetSSLInfo(ssl_info); } -Error SpdySession::GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) { - return connection_->socket()->GetTokenBindingSignature(key, tb_type, out); -} - bool SpdySession::WasAlpnNegotiated() const { return connection_->socket()->WasAlpnNegotiated(); }
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index b4bae19..97f7f58 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h
@@ -54,10 +54,6 @@ #include "url/gurl.h" #include "url/scheme_host_port.h" -namespace crypto { -class ECPrivateKey; -} - namespace net { namespace test { @@ -428,9 +424,6 @@ // MultiplexedSession methods: bool GetRemoteEndpoint(IPEndPoint* endpoint) override; bool GetSSLInfo(SSLInfo* ssl_info) const override; - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) override; // Returns true if ALPN was negotiated for the underlying socket. bool WasAlpnNegotiated() const;
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc index edfada1e..ca4b101 100644 --- a/net/spdy/spdy_stream.cc +++ b/net/spdy/spdy_stream.cc
@@ -754,12 +754,6 @@ return session_->GetSSLInfo(ssl_info); } -Error SpdyStream::GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) const { - return session_->GetTokenBindingSignature(key, tb_type, out); -} - bool SpdyStream::WasAlpnNegotiated() const { return session_->WasAlpnNegotiated(); }
diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h index 29abeaac..9718976 100644 --- a/net/spdy/spdy_stream.h +++ b/net/spdy/spdy_stream.h
@@ -25,17 +25,12 @@ #include "net/socket/ssl_client_socket.h" #include "net/spdy/spdy_buffer.h" #include "net/ssl/ssl_client_cert_type.h" -#include "net/ssl/token_binding.h" #include "net/third_party/spdy/core/spdy_framer.h" #include "net/third_party/spdy/core/spdy_header_block.h" #include "net/third_party/spdy/core/spdy_protocol.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "url/gurl.h" -namespace crypto { -class ECPrivateKey; -} - namespace net { class IPEndPoint; @@ -339,13 +334,6 @@ // Fills SSL info in |ssl_info| and returns true when SSL is in use. bool GetSSLInfo(SSLInfo* ssl_info) const; - // Generates the signature used in Token Binding using |*key| and for a Token - // Binding of type |tb_type|, putting the signature in |*out|. Returns OK or - // ERR_FAILED. - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) const; - // Returns true if ALPN was negotiated for the underlying socket. bool WasAlpnNegotiated() const;
diff --git a/net/ssl/ssl_config.h b/net/ssl/ssl_config.h index 7dab7ea..4c84056 100644 --- a/net/ssl/ssl_config.h +++ b/net/ssl/ssl_config.h
@@ -29,12 +29,6 @@ SSL_PROTOCOL_VERSION_TLS1_3 = 0x0304, }; -enum TokenBindingParam { - TB_PARAM_RSA2048_PKCS15 = 0, - TB_PARAM_RSA2048_PSS = 1, - TB_PARAM_ECDSAP256 = 2, -}; - enum TLS13Variant { kTLS13VariantDraft23, kTLS13VariantFinal, @@ -109,10 +103,6 @@ bool channel_id_enabled; // True if TLS channel ID extension is enabled. - // List of Token Binding key parameters supported by the client. If empty, - // Token Binding will be disabled, even if token_binding_enabled is true. - std::vector<TokenBindingParam> token_binding_params; - bool false_start_enabled; // True if we'll use TLS False Start. // If true, causes only ECDHE cipher suites to be enabled.
diff --git a/net/ssl/ssl_info.h b/net/ssl/ssl_info.h index 1d0a90ce..696e921 100644 --- a/net/ssl/ssl_info.h +++ b/net/ssl/ssl_info.h
@@ -99,15 +99,6 @@ // True if a channel ID was sent to the server. bool channel_id_sent = false; - // True if Token Binding was negotiated with the server and we agreed on a - // version and key params. - bool token_binding_negotiated = false; - - // Only valid if |token_binding_negotiated| is true. Contains the key param - // negotiated by the client and server in the Token Binding Negotiation TLS - // extension. - TokenBindingParam token_binding_key_param = TB_PARAM_ECDSAP256; - // True if data was received over early data on the server. This field is only // set for server sockets. bool early_data_received = false;
diff --git a/net/ssl/token_binding.cc b/net/ssl/token_binding.cc deleted file mode 100644 index d7f0ae7..0000000 --- a/net/ssl/token_binding.cc +++ /dev/null
@@ -1,223 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/ssl/token_binding.h" - -#include "base/stl_util.h" -#include "crypto/ec_private_key.h" -#include "net/base/net_errors.h" -#include "net/ssl/ssl_config.h" -#include "third_party/boringssl/src/include/openssl/bn.h" -#include "third_party/boringssl/src/include/openssl/bytestring.h" -#include "third_party/boringssl/src/include/openssl/ec.h" -#include "third_party/boringssl/src/include/openssl/ec_key.h" -#include "third_party/boringssl/src/include/openssl/ecdsa.h" -#include "third_party/boringssl/src/include/openssl/evp.h" -#include "third_party/boringssl/src/include/openssl/mem.h" - -namespace net { - -namespace { - -const size_t kUncompressedPointLen = 65; - -bool BuildTokenBindingID(crypto::ECPrivateKey* key, CBB* out) { - EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key->key()); - DCHECK(ec_key); - - uint8_t point_buf[kUncompressedPointLen]; - if (EC_POINT_point2oct( - EC_KEY_get0_group(ec_key), EC_KEY_get0_public_key(ec_key), - POINT_CONVERSION_UNCOMPRESSED, point_buf, kUncompressedPointLen, - NULL) != kUncompressedPointLen) { - return false; - } - CBB public_key, ec_point; - return CBB_add_u8(out, TB_PARAM_ECDSAP256) && - CBB_add_u16_length_prefixed(out, &public_key) && - CBB_add_u8_length_prefixed(&public_key, &ec_point) && - CBB_add_bytes(&ec_point, point_buf + 1, kUncompressedPointLen - 1) && - CBB_flush(out); -} - -bool ECDSA_SIGToRaw(ECDSA_SIG* ec_sig, EC_KEY* ec, std::vector<uint8_t>* out) { - const EC_GROUP* group = EC_KEY_get0_group(ec); - const BIGNUM* order = EC_GROUP_get0_order(group); - size_t len = BN_num_bytes(order); - out->resize(2 * len); - if (!BN_bn2bin_padded(out->data(), len, ec_sig->r) || - !BN_bn2bin_padded(out->data() + len, len, ec_sig->s)) { - return false; - } - return true; -} - -ECDSA_SIG* RawToECDSA_SIG(EC_KEY* ec, base::StringPiece sig) { - bssl::UniquePtr<ECDSA_SIG> raw_sig(ECDSA_SIG_new()); - const EC_GROUP* group = EC_KEY_get0_group(ec); - const BIGNUM* order = EC_GROUP_get0_order(group); - size_t group_size = BN_num_bytes(order); - if (sig.size() != group_size * 2) - return nullptr; - const uint8_t* sigp = reinterpret_cast<const uint8_t*>(sig.data()); - if (!BN_bin2bn(sigp, group_size, raw_sig->r) || - !BN_bin2bn(sigp + group_size, group_size, raw_sig->s)) { - return nullptr; - } - return raw_sig.release(); -} - -} // namespace - -bool CreateTokenBindingSignature(base::StringPiece ekm, - TokenBindingType type, - crypto::ECPrivateKey* key, - std::vector<uint8_t>* out) { - bssl::ScopedEVP_MD_CTX digest_ctx; - uint8_t tb_type = static_cast<uint8_t>(type); - uint8_t key_type = static_cast<uint8_t>(TB_PARAM_ECDSAP256); - uint8_t digest[EVP_MAX_MD_SIZE]; - unsigned int digest_len; - if (!EVP_DigestInit(digest_ctx.get(), EVP_sha256()) || - !EVP_DigestUpdate(digest_ctx.get(), &tb_type, 1) || - !EVP_DigestUpdate(digest_ctx.get(), &key_type, 1) || - !EVP_DigestUpdate(digest_ctx.get(), ekm.data(), ekm.size()) || - !EVP_DigestFinal_ex(digest_ctx.get(), digest, &digest_len)) { - return false; - } - EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key->key()); - if (!ec_key) - return false; - bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_do_sign(digest, digest_len, ec_key)); - if (!sig) - return false; - return ECDSA_SIGToRaw(sig.get(), ec_key, out); -} - -Error BuildTokenBindingMessageFromTokenBindings( - const std::vector<base::StringPiece>& token_bindings, - std::string* out) { - CBB tb_message, child; - if (!CBB_init(&tb_message, 0) || - !CBB_add_u16_length_prefixed(&tb_message, &child)) { - CBB_cleanup(&tb_message); - return ERR_FAILED; - } - for (const base::StringPiece& token_binding : token_bindings) { - if (!CBB_add_bytes(&child, - reinterpret_cast<const uint8_t*>(token_binding.data()), - token_binding.size())) { - CBB_cleanup(&tb_message); - return ERR_FAILED; - } - } - - uint8_t* out_data; - size_t out_len; - if (!CBB_finish(&tb_message, &out_data, &out_len)) { - CBB_cleanup(&tb_message); - return ERR_FAILED; - } - out->assign(reinterpret_cast<char*>(out_data), out_len); - OPENSSL_free(out_data); - return OK; -} - -Error BuildTokenBinding(TokenBindingType type, - crypto::ECPrivateKey* key, - const std::vector<uint8_t>& signed_ekm, - std::string* out) { - uint8_t* out_data; - size_t out_len; - CBB token_binding; - if (!CBB_init(&token_binding, 0) || - !CBB_add_u8(&token_binding, static_cast<uint8_t>(type)) || - !BuildTokenBindingID(key, &token_binding) || - !CBB_add_u16(&token_binding, signed_ekm.size()) || - !CBB_add_bytes(&token_binding, signed_ekm.data(), signed_ekm.size()) || - // 0-length extensions - !CBB_add_u16(&token_binding, 0) || - !CBB_finish(&token_binding, &out_data, &out_len)) { - CBB_cleanup(&token_binding); - return ERR_FAILED; - } - out->assign(reinterpret_cast<char*>(out_data), out_len); - OPENSSL_free(out_data); - return OK; -} - -TokenBinding::TokenBinding() = default; - -bool ParseTokenBindingMessage(base::StringPiece token_binding_message, - std::vector<TokenBinding>* token_bindings) { - CBS tb_message, tb, public_key, ec_point, signature, extensions; - uint8_t tb_type, tb_param; - CBS_init(&tb_message, - reinterpret_cast<const uint8_t*>(token_binding_message.data()), - token_binding_message.size()); - if (!CBS_get_u16_length_prefixed(&tb_message, &tb)) - return false; - while (CBS_len(&tb)) { - if (!CBS_get_u8(&tb, &tb_type) || !CBS_get_u8(&tb, &tb_param) || - !CBS_get_u16_length_prefixed(&tb, &public_key) || - !CBS_get_u8_length_prefixed(&public_key, &ec_point) || - CBS_len(&public_key) != 0 || - !CBS_get_u16_length_prefixed(&tb, &signature) || - !CBS_get_u16_length_prefixed(&tb, &extensions) || - tb_param != TB_PARAM_ECDSAP256 || - (TokenBindingType(tb_type) != TokenBindingType::PROVIDED && - TokenBindingType(tb_type) != TokenBindingType::REFERRED)) { - return false; - } - - TokenBinding token_binding; - token_binding.type = TokenBindingType(tb_type); - token_binding.ec_point = std::string( - reinterpret_cast<const char*>(CBS_data(&ec_point)), CBS_len(&ec_point)); - token_binding.signature = - std::string(reinterpret_cast<const char*>(CBS_data(&signature)), - CBS_len(&signature)); - token_bindings->push_back(token_binding); - } - return true; -} - -bool VerifyTokenBindingSignature(base::StringPiece ec_point, - base::StringPiece signature, - TokenBindingType type, - base::StringPiece ekm) { - if (ec_point.size() != kUncompressedPointLen - 1) - return false; - uint8_t x9_62_ec_point[kUncompressedPointLen]; - x9_62_ec_point[0] = 4; - memcpy(x9_62_ec_point + 1, ec_point.data(), kUncompressedPointLen - 1); - bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); - EC_KEY* keyp = key.get(); - bssl::UniquePtr<EC_POINT> pub_key(EC_POINT_new(EC_KEY_get0_group(keyp))); - if (!EC_POINT_oct2point(EC_KEY_get0_group(keyp), pub_key.get(), - x9_62_ec_point, kUncompressedPointLen, nullptr) || - !EC_KEY_set_public_key(keyp, pub_key.get())) { - return false; - } - - bssl::ScopedEVP_MD_CTX digest_ctx; - uint8_t tb_type = static_cast<uint8_t>(type); - uint8_t key_type = static_cast<uint8_t>(TB_PARAM_ECDSAP256); - uint8_t digest[EVP_MAX_MD_SIZE]; - unsigned int digest_len; - if (!EVP_DigestInit(digest_ctx.get(), EVP_sha256()) || - !EVP_DigestUpdate(digest_ctx.get(), &tb_type, 1) || - !EVP_DigestUpdate(digest_ctx.get(), &key_type, 1) || - !EVP_DigestUpdate(digest_ctx.get(), ekm.data(), ekm.size()) || - !EVP_DigestFinal_ex(digest_ctx.get(), digest, &digest_len)) { - return false; - } - - bssl::UniquePtr<ECDSA_SIG> sig(RawToECDSA_SIG(keyp, signature)); - if (!sig) - return false; - return !!ECDSA_do_verify(digest, digest_len, sig.get(), keyp); -} - -} // namespace net
diff --git a/net/ssl/token_binding.h b/net/ssl/token_binding.h deleted file mode 100644 index 445e4d6f..0000000 --- a/net/ssl/token_binding.h +++ /dev/null
@@ -1,121 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_SSL_TOKEN_BINDING_H_ -#define NET_SSL_TOKEN_BINDING_H_ - -#include <string> -#include <vector> - -#include "base/strings/string_piece.h" -#include "net/base/net_errors.h" -#include "net/base/net_export.h" - -namespace crypto { -class ECPrivateKey; -} - -namespace net { - -enum class TokenBindingType { - PROVIDED = 0, - REFERRED = 1, -}; - -// Takes an exported keying material value |ekm| from the TLS layer, the type of -// Token Binding |type|, and a token binding key |key| and concatenates the -// Token Binding type, key type, and ekm. This concatenation is signed with -// |key| in accordance with section 3.3 of draft-ietf-tokbind-protocol-10, with -// the signature written to |*out|. Returns true on success or false if there's -// an error in the signing operations. -bool CreateTokenBindingSignature(base::StringPiece ekm, - TokenBindingType type, - crypto::ECPrivateKey* key, - std::vector<uint8_t>* out); - -// Given a vector of serialized TokenBinding structs (as defined in -// draft-ietf-tokbind-protocol-04), this function combines them to form the -// serialized TokenBindingMessage struct in |*out|. This function returns a net -// error. -// -// struct { -// TokenBinding tokenbindings<0..2^16-1>; -// } TokenBindingMessage; -Error BuildTokenBindingMessageFromTokenBindings( - const std::vector<base::StringPiece>& token_bindings, - std::string* out); - -// Builds a TokenBinding struct of type |type| with a TokenBindingID created -// from |*key| and a signature of |ekm| using |*key| to sign. -// -// enum { -// rsa2048_pkcs1.5(0), rsa2048_pss(1), ecdsap256(2), (255) -// } TokenBindingKeyParameters; -// -// struct { -// opaque modulus<1..2^16-1>; -// opaque publicexponent<1..2^8-1>; -// } RSAPublicKey; -// -// struct { -// opaque point <1..2^8-1>; -// } ECPoint; -// -// enum { -// provided_token_binding(0), referred_token_binding(1), (255) -// } TokenBindingType; -// -// struct { -// TokenBindingType tokenbinding_type; -// TokenBindingKeyParameters key_parameters; -// select (key_parameters) { -// case rsa2048_pkcs1.5: -// case rsa2048_pss: -// RSAPublicKey rsapubkey; -// case ecdsap256: -// ECPoint point; -// } -// } TokenBindingID; -// -// struct { -// TokenBindingID tokenbindingid; -// opaque signature<0..2^16-1>;// Signature over the exported keying -// // material value -// Extension extensions<0..2^16-1>; -// } TokenBinding; -Error BuildTokenBinding(TokenBindingType type, - crypto::ECPrivateKey* key, - const std::vector<uint8_t>& ekm, - std::string* out); - -// Represents a parsed TokenBinding from a TokenBindingMessage. -struct TokenBinding { - TokenBinding(); - - TokenBindingType type; - std::string ec_point; - std::string signature; -}; - -// Given a TokenBindingMessage, parses the TokenBinding structs from it, putting -// them into |*token_bindings|. If there is an error parsing the -// TokenBindingMessage or the key parameter for any TokenBinding in the -// TokenBindingMessage is not ecdsap256, then this function returns false. -NET_EXPORT_PRIVATE bool ParseTokenBindingMessage( - base::StringPiece token_binding_message, - std::vector<TokenBinding>* token_bindings); - -// Takes an ECPoint |ec_point| from a TokenBindingID, |signature| from a -// TokenBinding, and a Token Binding type |type| and verifies that |signature| -// is the signature of |ekm| using |ec_point| as the public key. Returns true if -// the signature verifies and false if it doesn't or some other error occurs in -// verification. This function is only provided for testing. -NET_EXPORT_PRIVATE bool VerifyTokenBindingSignature(base::StringPiece ec_point, - base::StringPiece signature, - TokenBindingType type, - base::StringPiece ekm); - -} // namespace net - -#endif // NET_SSL_TOKEN_BINDING_H_
diff --git a/net/test/spawned_test_server/base_test_server.cc b/net/test/spawned_test_server/base_test_server.cc index fb1163e..3797c91 100644 --- a/net/test/spawned_test_server/base_test_server.cc +++ b/net/test/spawned_test_server/base_test_server.cc
@@ -114,15 +114,6 @@ return true; } -std::unique_ptr<base::ListValue> GetTokenBindingParams( - std::vector<int> params) { - std::unique_ptr<base::ListValue> values(new base::ListValue()); - for (int param : params) { - values->AppendInteger(param); - } - return values; -} - std::string OCSPStatusToString( const BaseTestServer::SSLOptions::OCSPStatus& ocsp_status) { switch (ocsp_status) { @@ -719,13 +710,6 @@ arguments->Set("disable-extended-master-secret", std::make_unique<base::Value>()); } - if (!ssl_options_.supported_token_binding_params.empty()) { - std::unique_ptr<base::ListValue> token_binding_params( - new base::ListValue()); - arguments->Set( - "token-binding-params", - GetTokenBindingParams(ssl_options_.supported_token_binding_params)); - } } return GenerateAdditionalArguments(arguments);
diff --git a/net/test/spawned_test_server/base_test_server.h b/net/test/spawned_test_server/base_test_server.h index c5b71a5..da11ca28ba 100644 --- a/net/test/spawned_test_server/base_test_server.h +++ b/net/test/spawned_test_server/base_test_server.h
@@ -342,9 +342,6 @@ // If true, disables extended master secret tls extension. bool disable_extended_master_secret = false; - - // List of token binding params that the server supports and will negotiate. - std::vector<int> supported_token_binding_params; }; // Initialize a TestServer.
diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py index cf55990..648082e 100755 --- a/net/tools/testserver/testserver.py +++ b/net/tools/testserver/testserver.py
@@ -161,8 +161,7 @@ npn_protocols, record_resume_info, tls_intolerant, tls_intolerance_type, signed_cert_timestamps, fallback_scsv_enabled, ocsp_response, - alert_after_handshake, disable_channel_id, disable_ems, - token_binding_params): + alert_after_handshake, disable_channel_id, disable_ems): self.cert_chain = tlslite.api.X509CertChain() self.cert_chain.parsePemList(pem_cert_and_key) # Force using only python implementation - otherwise behavior is different @@ -209,8 +208,6 @@ self.ssl_handshake_settings.enableChannelID = False if disable_ems: self.ssl_handshake_settings.enableExtendedMasterSecret = False - self.ssl_handshake_settings.supportedTokenBindingParams = \ - token_binding_params self.ssl_handshake_settings.alpnProtos=alpn_protocols; if record_resume_info: @@ -344,8 +341,6 @@ self.GetSSLSessionCacheHandler, self.SSLManySmallRecords, self.GetChannelID, - self.GetTokenBindingEKM, - self.ForwardTokenBindingHeader, self.GetClientCert, self.ClientCipherListHandler, self.CloseSocketHandler, @@ -1522,41 +1517,6 @@ self.wfile.write(hashlib.sha256(channel_id).digest().encode('base64')) return True - def GetTokenBindingEKM(self): - """Send a reply containing the EKM value for token binding from the TLS - layer.""" - - if not self._ShouldHandleRequest('/tokbind-ekm'): - return False - - ekm = self.server.tlsConnection.exportKeyingMaterial( - "EXPORTER-Token-Binding", "", False, 32) - self.send_response(200) - self.send_header('Content-Type', 'application/octet-stream') - self.end_headers() - self.wfile.write(ekm) - return True - - def ForwardTokenBindingHeader(self): - """Send a redirect that sets the Include-Referred-Token-Binding-ID - header.""" - - test_name = '/forward-tokbind' - if not self._ShouldHandleRequest(test_name): - return False - - query_char = self.path.find('?') - if query_char < 0 or len(self.path) <= query_char + 1: - self.sendRedirectHelp(test_name) - return True - dest = urllib.unquote(self.path[query_char + 1:]) - - self.send_response(302) - self.send_header('Location', dest) - self.send_header('Include-Referred-Token-Binding-ID', 'true') - self.end_headers() - return True - def GetClientCert(self): """Send a reply whether a client certificate was provided.""" @@ -2118,8 +2078,7 @@ stapled_ocsp_response, self.options.alert_after_handshake, self.options.disable_channel_id, - self.options.disable_extended_master_secret, - self.options.token_binding_params) + self.options.disable_extended_master_secret) print 'HTTPS server started on https://%s:%d...' % \ (host, server.server_port) else: @@ -2419,8 +2378,6 @@ self.option_parser.add_option('--disable-channel-id', action='store_true') self.option_parser.add_option('--disable-extended-master-secret', action='store_true') - self.option_parser.add_option('--token-binding-params', action='append', - default=[], type='int') self.option_parser.add_option('--redirect-connect-to-localhost', dest='redirect_connect_to_localhost', default=False, action='store_true',
diff --git a/net/url_request/redirect_info.cc b/net/url_request/redirect_info.cc index 0287bb4..f7075073 100644 --- a/net/url_request/redirect_info.cc +++ b/net/url_request/redirect_info.cc
@@ -124,7 +124,6 @@ int http_status_code, const GURL& new_location, bool insecure_scheme_was_upgraded, - bool token_binding_negotiated, bool copy_fragment) { DCHECK(!response_headers || response_headers->response_code() == http_status_code); @@ -171,15 +170,6 @@ redirect_info.new_url) .spec(); - if (response_headers) { - std::string include_referer; - response_headers->GetNormalizedHeader("include-referred-token-binding-id", - &include_referer); - include_referer = base::ToLowerASCII(include_referer); - if (include_referer == "true" && token_binding_negotiated) - redirect_info.referred_token_binding_host = original_url.host(); - } - return redirect_info; }
diff --git a/net/url_request/redirect_info.h b/net/url_request/redirect_info.h index 57d1ec13..d461115 100644 --- a/net/url_request/redirect_info.h +++ b/net/url_request/redirect_info.h
@@ -42,8 +42,6 @@ const GURL& new_location, // Whether the URL was upgraded to HTTPS due to upgrade-insecure-requests. bool insecure_scheme_was_upgraded, - // Whether Token Binding of TLS was negotiated. - bool token_binding_negotiated, // This method copies the URL fragment of the original URL to the new URL // by default. Set false only when the network delegate has set the // desired redirect URL (with or without fragment), so it must not be @@ -75,11 +73,6 @@ // The new referrer policy that should be obeyed if there are // subsequent redirects. URLRequest::ReferrerPolicy new_referrer_policy; - - // The hostname of the referrer if it asked the client to include a referred - // Token Binding when following the redirect; otherwise this is the empty - // string. - std::string referred_token_binding_host; }; } // namespace net
diff --git a/net/url_request/redirect_info_unittest.cc b/net/url_request/redirect_info_unittest.cc index e5edd55..01a307e6 100644 --- a/net/url_request/redirect_info_unittest.cc +++ b/net/url_request/redirect_info_unittest.cc
@@ -37,7 +37,6 @@ const std::string kOriginalReferrer = ""; const GURL kNewLocation = GURL("https://foo.test/redirected"); const bool kInsecureSchemeWasUpgraded = false; - const bool kTokenBindingNegotiated = false; const bool kCopyFragment = true; for (const auto& test : kTests) { @@ -50,7 +49,7 @@ kOriginalFirstPartyUrlPolicy, kOriginalReferrerPolicy, kOriginalReferrer, nullptr /* response_headers */, test.http_status_code, kNewLocation, kInsecureSchemeWasUpgraded, - kTokenBindingNegotiated, kCopyFragment); + kCopyFragment); EXPECT_EQ(test.expected_new_method, redirect_info.new_method); EXPECT_EQ(test.http_status_code, redirect_info.status_code); @@ -89,7 +88,6 @@ const std::string kOriginalReferrer = ""; const int kHttpStatusCode = 301; const bool kInsecureSchemeWasUpgraded = false; - const bool kTokenBindingNegotiated = false; for (const auto& test : kTests) { SCOPED_TRACE(::testing::Message() @@ -102,7 +100,7 @@ kOriginalFirstPartyUrlPolicy, kOriginalReferrerPolicy, kOriginalReferrer, nullptr /* response_headers */, kHttpStatusCode, GURL(test.new_location), kInsecureSchemeWasUpgraded, - kTokenBindingNegotiated, test.copy_fragment); + test.copy_fragment); EXPECT_EQ(GURL(test.expected_new_url), redirect_info.new_url); } @@ -128,7 +126,6 @@ const GURL kNewLocation = GURL("https://foo.test/redirected"); const bool kInsecureSchemeWasUpgraded = false; const int kHttpStatusCode = 301; - const bool kTokenBindingNegotiated = false; const bool kCopyFragment = true; for (const auto& test : kTests) { @@ -140,8 +137,7 @@ KOriginalMethod, kOriginalUrl, kOriginalSiteForCookies, test.original_first_party_url_policy, kOriginalReferrerPolicy, kOriginalReferrer, nullptr /* response_headers */, kHttpStatusCode, - kNewLocation, kInsecureSchemeWasUpgraded, kTokenBindingNegotiated, - kCopyFragment); + kNewLocation, kInsecureSchemeWasUpgraded, kCopyFragment); EXPECT_EQ(GURL(test.expected_new_site_for_cookies), redirect_info.new_site_for_cookies); @@ -426,7 +422,6 @@ const URLRequest::FirstPartyURLPolicy kOriginalFirstPartyUrlPolicy = net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL; const bool kInsecureSchemeWasUpgraded = false; - const bool kTokenBindingNegotiated = false; const bool kCopyFragment = true; for (const auto& test : kTests) { @@ -456,7 +451,7 @@ kOriginalFirstPartyUrlPolicy, test.original_referrer_policy, test.original_referrer, response_headers.get(), response_headers->response_code(), new_location, - kInsecureSchemeWasUpgraded, kTokenBindingNegotiated, kCopyFragment); + kInsecureSchemeWasUpgraded, kCopyFragment); EXPECT_EQ(test.expected_new_referrer_policy, redirect_info.new_referrer_policy); @@ -464,61 +459,5 @@ } } -TEST(RedirectInfoTest, ReferredTokenBinding) { - struct TestCase { - bool token_binding_negotiated; - const char* response_headers; - const char* expected_referred_token_binding_host; - }; - const TestCase kTests[] = { - {true, "", ""}, - {true, "Include-Referred-Token-Binding-ID: true", "foo.test"}, - {true, "Include-Referred-Token-Binding-ID: bar", ""}, - {false, "", ""}, - {false, "Include-Referred-Token-Binding-ID: true", ""}, - {false, "Include-Referred-Token-Binding-ID: bar", ""}, - }; - - const std::string KOriginalMethod = "GET"; - const GURL kriginalUrl = GURL("https://foo.test/"); - const GURL kOriginalSiteForCookies = GURL("https://foo.test/"); - const URLRequest::FirstPartyURLPolicy kOriginalFirstPartyUrlPolicy = - net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL; - const URLRequest::ReferrerPolicy kOriginalReferrerPolicy = - net::URLRequest::NEVER_CLEAR_REFERRER; - const std::string kOriginalReferrer = ""; - const GURL kNewLocation = GURL("https://bar.test/redirected"); - const bool kInsecureSchemeWasUpgraded = false; - const bool kCopyFragment = true; - - for (const auto& test : kTests) { - SCOPED_TRACE(::testing::Message() - << "token_binding_negotiated: " - << test.token_binding_negotiated - << " response_headers:" << test.response_headers); - - std::string response_header_text = - "HTTP/1.1 302 Redirect\nLocation: " + kNewLocation.spec() + "\n" + - std::string(test.response_headers); - std::string raw_headers = HttpUtil::AssembleRawHeaders( - response_header_text.c_str(), - static_cast<int>(response_header_text.length())); - auto response_headers = - base::MakeRefCounted<HttpResponseHeaders>(raw_headers); - EXPECT_EQ(302, response_headers->response_code()); - - RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo( - KOriginalMethod, kriginalUrl, kOriginalSiteForCookies, - kOriginalFirstPartyUrlPolicy, kOriginalReferrerPolicy, - kOriginalReferrer, response_headers.get(), - response_headers->response_code(), kNewLocation, - kInsecureSchemeWasUpgraded, test.token_binding_negotiated, - kCopyFragment); - - EXPECT_EQ(test.expected_referred_token_binding_host, - redirect_info.referred_token_binding_host); - } -} - } // namespace } // namespace net
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 825a96b3..ef2c226 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -963,7 +963,6 @@ referrer_ = redirect_info.new_referrer; referrer_policy_ = redirect_info.new_referrer_policy; site_for_cookies_ = redirect_info.new_site_for_cookies; - token_binding_referrer_ = redirect_info.referred_token_binding_host; url_chain_.push_back(redirect_info.new_url); --redirect_limit_;
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index a64498d..e6efafc6 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h
@@ -351,13 +351,6 @@ ReferrerPolicy referrer_policy() const { return referrer_policy_; } void set_referrer_policy(ReferrerPolicy referrer_policy); - // If this request should include a referred Token Binding, this returns the - // hostname of the referrer that indicated this request should include a - // referred Token Binding. Otherwise, this returns the empty string. - const std::string& token_binding_referrer() const { - return token_binding_referrer_; - } - // Sets the delegate of the request. This is only to allow creating a request // before creating its delegate. |delegate| must be non-NULL and the request // must not yet have a Delegate set. @@ -860,7 +853,6 @@ std::string method_; // "GET", "POST", etc. Should be all uppercase. std::string referrer_; ReferrerPolicy referrer_policy_; - std::string token_binding_referrer_; FirstPartyURLPolicy first_party_url_policy_; HttpRequestHeaders extra_request_headers_; int load_flags_; // Flags indicating the request type for the load;
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 729775e..7c98db2 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -441,8 +441,6 @@ referrer.spec()); } - request_info_.token_binding_referrer = request_->token_binding_referrer(); - // This should be kept in sync with the corresponding code in // URLRequest::GetUserAgent. request_info_.extra_headers.SetHeaderIfMissing(
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index 5b27df0e..f30efb45 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc
@@ -430,7 +430,6 @@ request_->first_party_url_policy(), request_->referrer_policy(), request_->referrer(), request_->response_headers(), http_status_code, new_location, insecure_scheme_was_upgraded, - request_->ssl_info().token_binding_negotiated, CopyFragmentOnRedirect(new_location)); bool defer_redirect = false; request_->NotifyReceivedRedirect(redirect_info, &defer_redirect);
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 19b71c4..ac22382 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -102,7 +102,6 @@ #include "net/ssl/ssl_connection_status_flags.h" #include "net/ssl/ssl_private_key.h" #include "net/ssl/ssl_server_config.h" -#include "net/ssl/token_binding.h" #include "net/test/cert_test_util.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" @@ -4151,9 +4150,8 @@ class TestSSLConfigService : public SSLConfigService { public: - explicit TestSSLConfigService(bool token_binding_enabled) - : token_binding_enabled_(token_binding_enabled), - min_version_(kDefaultSSLVersionMin), + TestSSLConfigService() + : min_version_(kDefaultSSLVersionMin), max_version_(kDefaultSSLVersionMax) {} ~TestSSLConfigService() override = default; @@ -4165,9 +4163,6 @@ *config = SSLConfig(); config->version_min = min_version_; config->version_max = max_version_; - if (token_binding_enabled_) { - config->token_binding_params.push_back(TB_PARAM_ECDSAP256); - } } bool CanShareConnectionWithClientCerts( @@ -4176,213 +4171,12 @@ } private: - const bool token_binding_enabled_; uint16_t min_version_; uint16_t max_version_; }; } // namespace -// TODO(svaldez): Update tests to use EmbeddedTestServer. -#if !defined(OS_IOS) -class TokenBindingURLRequestTest : public URLRequestTestHTTP { - public: - TokenBindingURLRequestTest() = default; - - void SetUp() override { - ssl_config_service_ = std::make_unique<TestSSLConfigService>( - true /* token_binding_enabled */); - default_context().set_ssl_config_service(ssl_config_service_.get()); - channel_id_service_ = - std::make_unique<ChannelIDService>(new DefaultChannelIDStore(NULL)); - default_context().set_channel_id_service(channel_id_service_.get()); - URLRequestTestHTTP::SetUp(); - } - - protected: - std::unique_ptr<TestSSLConfigService> ssl_config_service_; - std::unique_ptr<ChannelIDService> channel_id_service_; -}; - -TEST_F(TokenBindingURLRequestTest, TokenBindingTest) { - SpawnedTestServer::SSLOptions ssl_options; - ssl_options.supported_token_binding_params.push_back(TB_PARAM_ECDSAP256); - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(kTestFilePath)); - ASSERT_TRUE(https_test_server.Start()); - - TestDelegate d; - { - std::unique_ptr<URLRequest> r(default_context().CreateRequest( - https_test_server.GetURL("tokbind-ekm"), DEFAULT_PRIORITY, &d, - TRAFFIC_ANNOTATION_FOR_TESTS)); - r->Start(); - EXPECT_TRUE(r->is_pending()); - - d.RunUntilComplete(); - - EXPECT_EQ(OK, d.request_status()); - - HttpRequestHeaders headers; - std::string token_binding_header, token_binding_message; - EXPECT_TRUE(r->GetFullRequestHeaders(&headers)); - EXPECT_TRUE(headers.GetHeader(HttpRequestHeaders::kTokenBinding, - &token_binding_header)); - EXPECT_TRUE(base::Base64UrlDecode( - token_binding_header, base::Base64UrlDecodePolicy::DISALLOW_PADDING, - &token_binding_message)); - std::vector<TokenBinding> token_bindings; - ASSERT_TRUE( - ParseTokenBindingMessage(token_binding_message, &token_bindings)); - ASSERT_EQ(1ull, token_bindings.size()); - - EXPECT_GT(d.bytes_received(), 0); - std::string ekm = d.data_received(); - - EXPECT_EQ(TokenBindingType::PROVIDED, token_bindings[0].type); - EXPECT_TRUE(VerifyTokenBindingSignature(token_bindings[0].ec_point, - token_bindings[0].signature, - TokenBindingType::PROVIDED, ekm)); - } -} - -TEST_F(TokenBindingURLRequestTest, ForwardTokenBinding) { - SpawnedTestServer::SSLOptions ssl_options; - ssl_options.supported_token_binding_params.push_back(TB_PARAM_ECDSAP256); - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(kTestFilePath)); - ASSERT_TRUE(https_test_server.Start()); - - TestDelegate d; - { - GURL redirect_url = - https_test_server.GetURL("forward-tokbind?/tokbind-ekm"); - std::unique_ptr<URLRequest> r(default_context().CreateRequest( - redirect_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); - r->Start(); - EXPECT_TRUE(r->is_pending()); - - d.RunUntilComplete(); - - EXPECT_EQ(OK, d.request_status()); - - HttpRequestHeaders headers; - std::string token_binding_header, token_binding_message; - EXPECT_TRUE(r->GetFullRequestHeaders(&headers)); - EXPECT_TRUE(headers.GetHeader(HttpRequestHeaders::kTokenBinding, - &token_binding_header)); - EXPECT_TRUE(base::Base64UrlDecode( - token_binding_header, base::Base64UrlDecodePolicy::DISALLOW_PADDING, - &token_binding_message)); - std::vector<TokenBinding> token_bindings; - ASSERT_TRUE( - ParseTokenBindingMessage(token_binding_message, &token_bindings)); - ASSERT_EQ(2ull, token_bindings.size()); - - EXPECT_GT(d.bytes_received(), 0); - std::string ekm = d.data_received(); - - EXPECT_EQ(TokenBindingType::PROVIDED, token_bindings[0].type); - EXPECT_TRUE(VerifyTokenBindingSignature(token_bindings[0].ec_point, - token_bindings[0].signature, - TokenBindingType::PROVIDED, ekm)); - EXPECT_EQ(TokenBindingType::REFERRED, token_bindings[1].type); - EXPECT_TRUE(VerifyTokenBindingSignature(token_bindings[1].ec_point, - token_bindings[1].signature, - TokenBindingType::REFERRED, ekm)); - } -} - -// TODO(nharper): Remove this #ifdef and replace SpawnedTestServer with -// EmbeddedTestServer once crbug.com/599187 is resolved. -#if !defined(OS_ANDROID) -TEST_F(TokenBindingURLRequestTest, DontForwardHeaderFromHttp) { - SpawnedTestServer http_server(SpawnedTestServer::TYPE_HTTP, base::FilePath()); - ASSERT_TRUE(http_server.Start()); - SpawnedTestServer::SSLOptions ssl_options; - ssl_options.supported_token_binding_params.push_back(TB_PARAM_ECDSAP256); - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(kTestFilePath)); - ASSERT_TRUE(https_test_server.Start()); - - TestDelegate d; - { - GURL redirect_url = http_server.GetURL( - "forward-tokbind?" + https_test_server.GetURL("tokbind-ekm").spec()); - std::unique_ptr<URLRequest> r(default_context().CreateRequest( - redirect_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); - r->Start(); - EXPECT_TRUE(r->is_pending()); - - d.RunUntilComplete(); - - EXPECT_EQ(OK, d.request_status()); - - HttpRequestHeaders headers; - std::string token_binding_header, token_binding_message; - EXPECT_TRUE(r->GetFullRequestHeaders(&headers)); - EXPECT_TRUE(headers.GetHeader(HttpRequestHeaders::kTokenBinding, - &token_binding_header)); - EXPECT_TRUE(base::Base64UrlDecode( - token_binding_header, base::Base64UrlDecodePolicy::DISALLOW_PADDING, - &token_binding_message)); - std::vector<TokenBinding> token_bindings; - ASSERT_TRUE( - ParseTokenBindingMessage(token_binding_message, &token_bindings)); - ASSERT_EQ(1ull, token_bindings.size()); - - EXPECT_GT(d.bytes_received(), 0); - std::string ekm = d.data_received(); - - EXPECT_EQ(TokenBindingType::PROVIDED, token_bindings[0].type); - EXPECT_TRUE(VerifyTokenBindingSignature(token_bindings[0].ec_point, - token_bindings[0].signature, - TokenBindingType::PROVIDED, ekm)); - } -} - -// Test that if a server supporting Token Binding redirects (with -// Include-Referred-Token-Binding-ID) to an https url on a server that does not -// support Token Binding, then we do not send a Sec-Token-Binding when following -// the redirect. -TEST_F(TokenBindingURLRequestTest, ForwardWithoutTokenBinding) { - SpawnedTestServer::SSLOptions ssl_options; - SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(kTestFilePath)); - ASSERT_TRUE(https_test_server.Start()); - ssl_options.supported_token_binding_params.push_back(TB_PARAM_ECDSAP256); - SpawnedTestServer token_binding_test_server(SpawnedTestServer::TYPE_HTTPS, - ssl_options, - base::FilePath(kTestFilePath)); - ASSERT_TRUE(token_binding_test_server.Start()); - - TestDelegate d; - { - GURL redirect_url = token_binding_test_server.GetURL( - "forward-tokbind?" + https_test_server.GetURL("tokbind-ekm").spec()); - std::unique_ptr<URLRequest> r(default_context().CreateRequest( - redirect_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); - r->Start(); - EXPECT_TRUE(r->is_pending()); - - d.RunUntilComplete(); - - EXPECT_EQ(OK, d.request_status()); - - HttpRequestHeaders headers; - std::string token_binding_header, token_binding_message; - EXPECT_TRUE(r->GetFullRequestHeaders(&headers)); - EXPECT_FALSE(headers.GetHeader(HttpRequestHeaders::kTokenBinding, - &token_binding_header)); - } -} -#endif // !defined(OS_ANDROID) -#endif // !defined(OS_IOS) - // In this unit test, we're using the HTTPTestServer as a proxy server and // issuing a CONNECT request with the magic host name "www.redirect.com". // The EmbeddedTestServer will return a 302 response, which we should not @@ -10828,8 +10622,7 @@ class HTTPSFallbackTest : public TestWithScopedTaskEnvironment { public: HTTPSFallbackTest() : context_(true) { - ssl_config_service_ = std::make_unique<TestSSLConfigService>( - false /* token binding enabled */); + ssl_config_service_ = std::make_unique<TestSSLConfigService>(); context_.set_ssl_config_service(ssl_config_service_.get()); } ~HTTPSFallbackTest() override = default;
diff --git a/net/websockets/websocket_basic_handshake_stream.cc b/net/websockets/websocket_basic_handshake_stream.cc index 3fcdf38..266f6aa 100644 --- a/net/websockets/websocket_basic_handshake_stream.cc +++ b/net/websockets/websocket_basic_handshake_stream.cc
@@ -344,16 +344,6 @@ return; } -Error WebSocketBasicHandshakeStream::GetTokenBindingSignature( - crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) { - DCHECK(url_.SchemeIsCryptographic()); - - return state_.connection()->socket()->GetTokenBindingSignature(key, tb_type, - out); -} - void WebSocketBasicHandshakeStream::Drain(HttpNetworkSession* session) { HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(this); drainer->Start(session);
diff --git a/net/websockets/websocket_basic_handshake_stream.h b/net/websockets/websocket_basic_handshake_stream.h index 27e6f035..ccd371b 100644 --- a/net/websockets/websocket_basic_handshake_stream.h +++ b/net/websockets/websocket_basic_handshake_stream.h
@@ -74,9 +74,6 @@ void GetSSLInfo(SSLInfo* ssl_info) override; void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override; bool GetRemoteEndpoint(IPEndPoint* endpoint) override; - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) override; void Drain(HttpNetworkSession* session) override; void SetPriority(RequestPriority priority) override; void PopulateNetErrorDetails(NetErrorDetails* details) override;
diff --git a/net/websockets/websocket_http2_handshake_stream.cc b/net/websockets/websocket_http2_handshake_stream.cc index 73f0a3a8..9bea1903 100644 --- a/net/websockets/websocket_http2_handshake_stream.cc +++ b/net/websockets/websocket_http2_handshake_stream.cc
@@ -216,13 +216,6 @@ return; } -Error WebSocketHttp2HandshakeStream::GetTokenBindingSignature( - crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) { - return stream_->GetTokenBindingSignature(key, tb_type, out); -} - void WebSocketHttp2HandshakeStream::Drain(HttpNetworkSession* session) { Close(true /* not_reusable */); }
diff --git a/net/websockets/websocket_http2_handshake_stream.h b/net/websockets/websocket_http2_handshake_stream.h index f576f43..cef1642 100644 --- a/net/websockets/websocket_http2_handshake_stream.h +++ b/net/websockets/websocket_http2_handshake_stream.h
@@ -18,18 +18,11 @@ #include "net/base/net_export.h" #include "net/base/request_priority.h" #include "net/log/net_log_with_source.h" -#include "net/ssl/token_binding.h" #include "net/third_party/spdy/core/spdy_header_block.h" #include "net/websockets/websocket_basic_stream_adapters.h" #include "net/websockets/websocket_handshake_stream_base.h" #include "net/websockets/websocket_stream.h" -namespace crypto { - -class ECPrivateKey; - -} // namespace crypto - namespace net { struct LoadTimingInfo; @@ -88,9 +81,6 @@ void GetSSLInfo(SSLInfo* ssl_info) override; void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override; bool GetRemoteEndpoint(IPEndPoint* endpoint) override; - Error GetTokenBindingSignature(crypto::ECPrivateKey* key, - TokenBindingType tb_type, - std::vector<uint8_t>* out) override; void Drain(HttpNetworkSession* session) override; void SetPriority(RequestPriority priority) override; void PopulateNetErrorDetails(NetErrorDetails* details) override;
diff --git a/services/network/public/cpp/net_ipc_param_traits.cc b/services/network/public/cpp/net_ipc_param_traits.cc index 8ca5e2e..79912a5 100644 --- a/services/network/public/cpp/net_ipc_param_traits.cc +++ b/services/network/public/cpp/net_ipc_param_traits.cc
@@ -290,8 +290,6 @@ WriteParam(m, p.pkp_bypassed); WriteParam(m, p.client_cert_sent); WriteParam(m, p.channel_id_sent); - WriteParam(m, p.token_binding_negotiated); - WriteParam(m, p.token_binding_key_param); WriteParam(m, p.handshake_type); WriteParam(m, p.public_key_hashes); WriteParam(m, p.pinning_failure_log); @@ -319,8 +317,6 @@ ReadParam(m, iter, &r->pkp_bypassed) && ReadParam(m, iter, &r->client_cert_sent) && ReadParam(m, iter, &r->channel_id_sent) && - ReadParam(m, iter, &r->token_binding_negotiated) && - ReadParam(m, iter, &r->token_binding_key_param) && ReadParam(m, iter, &r->handshake_type) && ReadParam(m, iter, &r->public_key_hashes) && ReadParam(m, iter, &r->pinning_failure_log) &&
diff --git a/services/network/public/cpp/net_ipc_param_traits.h b/services/network/public/cpp/net_ipc_param_traits.h index 3beeb69..26b492c 100644 --- a/services/network/public/cpp/net_ipc_param_traits.h +++ b/services/network/public/cpp/net_ipc_param_traits.h
@@ -216,7 +216,6 @@ IPC_ENUM_TRAITS_MAX_VALUE(net::SSLInfo::HandshakeType, net::SSLInfo::HANDSHAKE_FULL) -IPC_ENUM_TRAITS_MAX_VALUE(net::TokenBindingParam, net::TB_PARAM_ECDSAP256) IPC_ENUM_TRAITS_MAX_VALUE(net::URLRequest::ReferrerPolicy, net::URLRequest::MAX_REFERRER_POLICY - 1) @@ -243,7 +242,6 @@ IPC_STRUCT_TRAITS_MEMBER(new_referrer) IPC_STRUCT_TRAITS_MEMBER(insecure_scheme_was_upgraded) IPC_STRUCT_TRAITS_MEMBER(new_referrer_policy) - IPC_STRUCT_TRAITS_MEMBER(referred_token_binding_host) IPC_STRUCT_TRAITS_END() IPC_ENUM_TRAITS_MAX_VALUE(net::HttpResponseInfo::ConnectionInfo,
diff --git a/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc index 48684f6..7b43d21 100644 --- a/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc +++ b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
@@ -241,13 +241,11 @@ // Grant relatively big quota initially. quota_manager_->SetQuota( - origin_, - storage::FileSystemTypeToQuotaStorageType(src_type_), - 1024 * 1024); + url::Origin::Create(origin_), + storage::FileSystemTypeToQuotaStorageType(src_type_), 1024 * 1024); quota_manager_->SetQuota( - origin_, - storage::FileSystemTypeToQuotaStorageType(dest_type_), - 1024 * 1024); + url::Origin::Create(origin_), + storage::FileSystemTypeToQuotaStorageType(dest_type_), 1024 * 1024); } int64_t GetSourceUsage() { @@ -391,7 +389,8 @@ int64_t* usage, int64_t* quota) { blink::mojom::QuotaStatusCode status = - AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(), origin_, + AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(), + url::Origin::Create(origin_), type, usage, quota); ASSERT_EQ(blink::mojom::QuotaStatusCode::kOk, status); }
diff --git a/storage/browser/fileapi/file_system_operation_impl.cc b/storage/browser/fileapi/file_system_operation_impl.cc index a7bc400..87454ac 100644 --- a/storage/browser/fileapi/file_system_operation_impl.cc +++ b/storage/browser/fileapi/file_system_operation_impl.cc
@@ -407,7 +407,8 @@ DCHECK(quota_manager_proxy); DCHECK(quota_manager_proxy->quota_manager()); quota_manager_proxy->quota_manager()->GetUsageAndQuota( - url.origin(), FileSystemTypeToQuotaStorageType(url.type()), + url::Origin::Create(url.origin()), + FileSystemTypeToQuotaStorageType(url.type()), base::BindOnce(&FileSystemOperationImpl::DidGetUsageAndQuotaAndRunTask, weak_ptr_, task, error_callback)); }
diff --git a/storage/browser/fileapi/file_system_operation_impl_unittest.cc b/storage/browser/fileapi/file_system_operation_impl_unittest.cc index bc6eb31..8636aa75 100644 --- a/storage/browser/fileapi/file_system_operation_impl_unittest.cc +++ b/storage/browser/fileapi/file_system_operation_impl_unittest.cc
@@ -255,7 +255,8 @@ void GetUsageAndQuota(int64_t* usage, int64_t* quota) { blink::mojom::QuotaStatusCode status = AsyncFileTestHelper::GetUsageAndQuota( - quota_manager_.get(), sandbox_file_system_.origin(), + quota_manager_.get(), + url::Origin::Create(sandbox_file_system_.origin()), sandbox_file_system_.type(), usage, quota); scoped_task_environment_.RunUntilIdle(); ASSERT_EQ(blink::mojom::QuotaStatusCode::kOk, status); @@ -279,9 +280,9 @@ void GrantQuotaForCurrentUsage() { int64_t usage; GetUsageAndQuota(&usage, nullptr); - quota_manager()->SetQuota(sandbox_file_system_.origin(), - sandbox_file_system_.storage_type(), - usage); + quota_manager()->SetQuota( + url::Origin::Create(sandbox_file_system_.origin()), + sandbox_file_system_.storage_type(), usage); } int64_t GetUsage() { @@ -293,9 +294,9 @@ void AddQuota(int64_t quota_delta) { int64_t quota; GetUsageAndQuota(nullptr, "a); - quota_manager()->SetQuota(sandbox_file_system_.origin(), - sandbox_file_system_.storage_type(), - quota + quota_delta); + quota_manager()->SetQuota( + url::Origin::Create(sandbox_file_system_.origin()), + sandbox_file_system_.storage_type(), quota + quota_delta); } base::File::Error Move(
diff --git a/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc b/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc index 70b2bfb5..59ac2a9 100644 --- a/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc +++ b/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc
@@ -259,8 +259,9 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteFailureByQuota) { ScopedTextBlob blob(url_request_context(), "blob:success", "Hello, world!\n"); - quota_manager_->SetQuota( - kOrigin, FileSystemTypeToQuotaStorageType(kFileSystemType), 10); + quota_manager_->SetQuota(url::Origin::Create(kOrigin), + FileSystemTypeToQuotaStorageType(kFileSystemType), + 10); file_system_context_->operation_runner()->Write(URLForPath(virtual_path_), blob.GetBlobDataHandle(), 0, RecordWriteCallback());
diff --git a/storage/browser/fileapi/obfuscated_file_util_unittest.cc b/storage/browser/fileapi/obfuscated_file_util_unittest.cc index 1fecb7a3..fcf0117a 100644 --- a/storage/browser/fileapi/obfuscated_file_util_unittest.cc +++ b/storage/browser/fileapi/obfuscated_file_util_unittest.cc
@@ -274,12 +274,9 @@ void GetUsageFromQuotaManager() { int64_t quota = -1; - quota_status_ = - AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(), - origin(), - sandbox_file_system_.type(), - &usage_, - "a); + quota_status_ = AsyncFileTestHelper::GetUsageAndQuota( + quota_manager_.get(), url::Origin::Create(origin()), + sandbox_file_system_.type(), &usage_, "a); EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, quota_status_); }
diff --git a/storage/browser/fileapi/sandbox_file_stream_writer.cc b/storage/browser/fileapi/sandbox_file_stream_writer.cc index c1b2fff..f6fcd9a 100644 --- a/storage/browser/fileapi/sandbox_file_stream_writer.cc +++ b/storage/browser/fileapi/sandbox_file_stream_writer.cc
@@ -161,7 +161,8 @@ DCHECK(quota_manager_proxy->quota_manager()); quota_manager_proxy->quota_manager()->GetUsageAndQuota( - url_.origin(), FileSystemTypeToQuotaStorageType(url_.type()), + url::Origin::Create(url_.origin()), + FileSystemTypeToQuotaStorageType(url_.type()), base::BindOnce(&SandboxFileStreamWriter::DidGetUsageAndQuota, weak_factory_.GetWeakPtr(), std::move(callback))); }
diff --git a/storage/browser/quota/client_usage_tracker.cc b/storage/browser/quota/client_usage_tracker.cc index 732fe4a..3aa30e6 100644 --- a/storage/browser/quota/client_usage_tracker.cc +++ b/storage/browser/quota/client_usage_tracker.cc
@@ -29,7 +29,7 @@ bool EraseOriginFromOriginSet(OriginSetByHost* origins_by_host, const std::string& host, - const GURL& origin) { + const url::Origin& origin) { OriginSetByHost::iterator found = origins_by_host->find(host); if (found == origins_by_host->end()) return false; @@ -44,7 +44,7 @@ bool OriginSetContainsOrigin(const OriginSetByHost& origins, const std::string& host, - const GURL& origin) { + const url::Origin& origin) { OriginSetByHost::const_iterator itr = origins.find(host); return itr != origins.end() && base::ContainsKey(itr->second, origin); } @@ -105,7 +105,7 @@ for (const auto& host_and_origins : non_cached_limited_origins_by_host_) { for (const auto& origin : host_and_origins.second) - client_->GetOriginUsage(url::Origin::Create(origin), type_, accumulator); + client_->GetOriginUsage(origin, type_, accumulator); } accumulator.Run(global_limited_usage_); @@ -144,8 +144,9 @@ AsWeakPtr(), host)); } -void ClientUsageTracker::UpdateUsageCache(const GURL& origin, int64_t delta) { - std::string host = net::GetHostOrSpecFromURL(origin); +void ClientUsageTracker::UpdateUsageCache(const url::Origin& origin, + int64_t delta) { + std::string host = net::GetHostOrSpecFromURL(origin.GetURL()); if (base::ContainsKey(cached_hosts_, host)) { if (!IsUsageCacheEnabledForOrigin(origin)) return; @@ -192,7 +193,7 @@ } void ClientUsageTracker::GetCachedOriginsUsage( - std::map<GURL, int64_t>* origin_usage) const { + std::map<url::Origin, int64_t>* origin_usage) const { DCHECK(origin_usage); for (const auto& host_and_usage_map : cached_usage_by_host_) { for (const auto& origin_and_usage : host_and_usage_map.second) @@ -200,7 +201,8 @@ } } -void ClientUsageTracker::GetCachedOrigins(std::set<GURL>* origins) const { +void ClientUsageTracker::GetCachedOrigins( + std::set<url::Origin>* origins) const { DCHECK(origins); for (const auto& host_and_usage_map : cached_usage_by_host_) { for (const auto& origin_and_usage : host_and_usage_map.second) @@ -208,9 +210,9 @@ } } -void ClientUsageTracker::SetUsageCacheEnabled(const GURL& origin, +void ClientUsageTracker::SetUsageCacheEnabled(const url::Origin& origin, bool enabled) { - std::string host = net::GetHostOrSpecFromURL(origin); + std::string host = net::GetHostOrSpecFromURL(origin.GetURL()); if (!enabled) { // Erase |origin| from cache and subtract its usage. HostUsageMap::iterator found_host = cached_usage_by_host_.find(host); @@ -262,7 +264,7 @@ OriginSetByHost origins_by_host; for (const auto& origin : origins) { GURL origin_url = origin.GetURL(); - origins_by_host[net::GetHostOrSpecFromURL(origin_url)].insert(origin_url); + origins_by_host[net::GetHostOrSpecFromURL(origin_url)].insert(origin); } AccumulateInfo* info = new AccumulateInfo; @@ -278,10 +280,7 @@ for (const auto& host_and_origins : origins_by_host) { const std::string& host = host_and_origins.first; - const std::set<GURL>& origin_urls = host_and_origins.second; - std::set<url::Origin> origins; - for (const auto& origin_url : origin_urls) - origins.insert(url::Origin::Create(origin_url)); + const std::set<url::Origin>& origins = host_and_origins.second; if (host_usage_accumulators_.Add(host, accumulator)) GetUsageForOrigins(host, origins); } @@ -328,36 +327,37 @@ AsWeakPtr(), base::Owned(info), host); for (const auto& origin : origins) { - GURL origin_url = origin.GetURL(); - DCHECK_EQ(host, net::GetHostOrSpecFromURL(origin_url)); + DCHECK_EQ(host, net::GetHostOrSpecFromURL(origin.GetURL())); int64_t origin_usage = 0; - if (GetCachedOriginUsage(origin_url, &origin_usage)) { - accumulator.Run(origin_url, origin_usage); + if (GetCachedOriginUsage(origin, &origin_usage)) { + accumulator.Run(origin, origin_usage); } else { client_->GetOriginUsage(origin, type_, - base::BindOnce(accumulator, origin_url)); + base::BindOnce(accumulator, origin)); } } // Fire the sentinel as we've now called GetOriginUsage for all clients. - accumulator.Run(GURL(), 0); + accumulator.Run(base::nullopt, 0); } -void ClientUsageTracker::AccumulateOriginUsage(AccumulateInfo* info, - const std::string& host, - const GURL& origin, - int64_t usage) { - if (!origin.is_empty()) { +void ClientUsageTracker::AccumulateOriginUsage( + AccumulateInfo* info, + const std::string& host, + const base::Optional<url::Origin>& origin, + int64_t usage) { + if (origin.has_value()) { + DCHECK(!origin->GetURL().is_empty()); if (usage < 0) usage = 0; - if (IsStorageUnlimited(origin)) + if (IsStorageUnlimited(*origin)) info->unlimited_usage += usage; else info->limited_usage += usage; - if (IsUsageCacheEnabledForOrigin(origin)) - AddCachedOrigin(origin, usage); + if (IsUsageCacheEnabledForOrigin(*origin)) + AddCachedOrigin(*origin, usage); } if (--info->pending_jobs) return; @@ -367,7 +367,7 @@ host, info->limited_usage, info->unlimited_usage); } -void ClientUsageTracker::DidGetHostUsageAfterUpdate(const GURL& origin, +void ClientUsageTracker::DidGetHostUsageAfterUpdate(const url::Origin& origin, int64_t usage) { if (!storage_monitor_) return; @@ -376,11 +376,11 @@ storage_monitor_->NotifyUsageChange(filter, 0); } -void ClientUsageTracker::AddCachedOrigin(const GURL& origin, +void ClientUsageTracker::AddCachedOrigin(const url::Origin& origin, int64_t new_usage) { DCHECK(IsUsageCacheEnabledForOrigin(origin)); - std::string host = net::GetHostOrSpecFromURL(origin); + std::string host = net::GetHostOrSpecFromURL(origin.GetURL()); int64_t* usage = &cached_usage_by_host_[host][origin]; int64_t delta = new_usage - *usage; *usage = new_usage; @@ -407,9 +407,9 @@ return usage; } -bool ClientUsageTracker::GetCachedOriginUsage(const GURL& origin, +bool ClientUsageTracker::GetCachedOriginUsage(const url::Origin& origin, int64_t* usage) const { - std::string host = net::GetHostOrSpecFromURL(origin); + std::string host = net::GetHostOrSpecFromURL(origin.GetURL()); HostUsageMap::const_iterator found_host = cached_usage_by_host_.find(host); if (found_host == cached_usage_by_host_.end()) return false; @@ -424,42 +424,42 @@ } bool ClientUsageTracker::IsUsageCacheEnabledForOrigin( - const GURL& origin) const { - std::string host = net::GetHostOrSpecFromURL(origin); + const url::Origin& origin) const { + std::string host = net::GetHostOrSpecFromURL(origin.GetURL()); return !OriginSetContainsOrigin(non_cached_limited_origins_by_host_, host, origin) && !OriginSetContainsOrigin(non_cached_unlimited_origins_by_host_, host, origin); } -void ClientUsageTracker::OnGranted(const GURL& origin, - int change_flags) { +void ClientUsageTracker::OnGranted(const GURL& origin_url, int change_flags) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) { + url::Origin origin = url::Origin::Create(origin_url); int64_t usage = 0; if (GetCachedOriginUsage(origin, &usage)) { global_unlimited_usage_ += usage; global_limited_usage_ -= usage; } - std::string host = net::GetHostOrSpecFromURL(origin); + std::string host = net::GetHostOrSpecFromURL(origin_url); if (EraseOriginFromOriginSet(&non_cached_limited_origins_by_host_, host, origin)) non_cached_unlimited_origins_by_host_[host].insert(origin); } } -void ClientUsageTracker::OnRevoked(const GURL& origin, - int change_flags) { +void ClientUsageTracker::OnRevoked(const GURL& origin_url, int change_flags) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (change_flags & SpecialStoragePolicy::STORAGE_UNLIMITED) { + url::Origin origin = url::Origin::Create(origin_url); int64_t usage = 0; if (GetCachedOriginUsage(origin, &usage)) { global_unlimited_usage_ -= usage; global_limited_usage_ += usage; } - std::string host = net::GetHostOrSpecFromURL(origin); + std::string host = net::GetHostOrSpecFromURL(origin_url); if (EraseOriginFromOriginSet(&non_cached_unlimited_origins_by_host_, host, origin)) non_cached_limited_origins_by_host_[host].insert(origin); @@ -499,11 +499,11 @@ } } -bool ClientUsageTracker::IsStorageUnlimited(const GURL& origin) const { +bool ClientUsageTracker::IsStorageUnlimited(const url::Origin& origin) const { if (type_ == blink::mojom::StorageType::kSyncable) return false; return special_storage_policy_.get() && - special_storage_policy_->IsStorageUnlimited(origin); + special_storage_policy_->IsStorageUnlimited(origin.GetURL()); } } // namespace storage
diff --git a/storage/browser/quota/client_usage_tracker.h b/storage/browser/quota/client_usage_tracker.h index 72460d2..5bac56f2 100644 --- a/storage/browser/quota/client_usage_tracker.h +++ b/storage/browser/quota/client_usage_tracker.h
@@ -39,9 +39,10 @@ base::RepeatingCallback<void(int64_t limited_usage, int64_t unlimited_usage)>; using OriginUsageAccumulator = - base::RepeatingCallback<void(const GURL& origin, int64_t usage)>; + base::RepeatingCallback<void(const base::Optional<url::Origin>& origin, + int64_t usage)>; using UsageAccumulator = base::RepeatingCallback<void(int64_t usage)>; - using OriginSetByHost = std::map<std::string, std::set<GURL>>; + using OriginSetByHost = std::map<std::string, std::set<url::Origin>>; using HostUsageCallback = base::OnceCallback<void(int64_t limited_usage, int64_t unlimited_usage)>; @@ -56,20 +57,21 @@ void GetGlobalLimitedUsage(UsageCallback callback); void GetGlobalUsage(GlobalUsageCallback callback); void GetHostUsage(const std::string& host, UsageCallback callback); - void UpdateUsageCache(const GURL& origin, int64_t delta); + void UpdateUsageCache(const url::Origin& origin, int64_t delta); int64_t GetCachedUsage() const; void GetCachedHostsUsage(std::map<std::string, int64_t>* host_usage) const; - void GetCachedOriginsUsage(std::map<GURL, int64_t>* origin_usage) const; - void GetCachedOrigins(std::set<GURL>* origins) const; - bool IsUsageCacheEnabledForOrigin(const GURL& origin) const; - void SetUsageCacheEnabled(const GURL& origin, bool enabled); + void GetCachedOriginsUsage( + std::map<url::Origin, int64_t>* origin_usage) const; + void GetCachedOrigins(std::set<url::Origin>* origins) const; + bool IsUsageCacheEnabledForOrigin(const url::Origin& origin) const; + void SetUsageCacheEnabled(const url::Origin& origin, bool enabled); private: using HostUsageAccumulatorMap = CallbackQueueMap<HostUsageCallback, std::string, int64_t, int64_t>; using HostSet = std::set<std::string>; - using UsageMap = std::map<GURL, int64_t>; + using UsageMap = std::map<url::Origin, int64_t>; using HostUsageMap = std::map<std::string, UsageMap>; struct AccumulateInfo { @@ -95,28 +97,28 @@ const std::set<url::Origin>& origins); void AccumulateOriginUsage(AccumulateInfo* info, const std::string& host, - const GURL& origin, + const base::Optional<url::Origin>& origin, int64_t usage); - void DidGetHostUsageAfterUpdate(const GURL& origin, int64_t usage); + void DidGetHostUsageAfterUpdate(const url::Origin& origin, int64_t usage); // Methods used by our GatherUsage tasks, as a task makes progress // origins and hosts are added incrementally to the cache. - void AddCachedOrigin(const GURL& origin, int64_t usage); + void AddCachedOrigin(const url::Origin& origin, int64_t usage); void AddCachedHost(const std::string& host); int64_t GetCachedHostUsage(const std::string& host) const; int64_t GetCachedGlobalUnlimitedUsage(); - bool GetCachedOriginUsage(const GURL& origin, int64_t* usage) const; + bool GetCachedOriginUsage(const url::Origin& origin, int64_t* usage) const; // SpecialStoragePolicy::Observer overrides - void OnGranted(const GURL& origin, int change_flags) override; - void OnRevoked(const GURL& origin, int change_flags) override; + void OnGranted(const GURL& origin_url, int change_flags) override; + void OnRevoked(const GURL& origin_url, int change_flags) override; void OnCleared() override; void UpdateGlobalUsageValue(int64_t* usage_value, int64_t delta); - bool IsStorageUnlimited(const GURL& origin) const; + bool IsStorageUnlimited(const url::Origin& origin) const; UsageTracker* tracker_; QuotaClient* client_;
diff --git a/storage/browser/quota/quota_callbacks.h b/storage/browser/quota/quota_callbacks.h index 7a4a4e53..bcf6402a 100644 --- a/storage/browser/quota/quota_callbacks.h +++ b/storage/browser/quota/quota_callbacks.h
@@ -15,11 +15,14 @@ #include "base/callback.h" #include "base/containers/flat_map.h" +#include "base/optional.h" #include "base/stl_util.h" #include "storage/browser/quota/quota_client.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -class GURL; +namespace url { +class Origin; +} namespace storage { @@ -40,10 +43,11 @@ base::OnceCallback<void(blink::mojom::QuotaStatusCode, int64_t)>; using StatusCallback = base::OnceCallback<void(blink::mojom::QuotaStatusCode)>; using GetOriginsCallback = - base::OnceCallback<void(const std::set<GURL>& origins, + base::OnceCallback<void(const std::set<url::Origin>& origins, blink::mojom::StorageType type)>; using GetUsageInfoCallback = base::OnceCallback<void(const UsageInfoEntries&)>; -using GetOriginCallback = base::OnceCallback<void(const GURL&)>; +using GetOriginCallback = + base::OnceCallback<void(const base::Optional<url::Origin>&)>; // Simple template wrapper for a callback queue. template <typename CallbackType, typename... Args>
diff --git a/storage/browser/quota/quota_database.cc b/storage/browser/quota/quota_database.cc index 46c0522..0bcc0bc 100644 --- a/storage/browser/quota/quota_database.cc +++ b/storage/browser/quota/quota_database.cc
@@ -20,6 +20,7 @@ #include "sql/statement.h" #include "sql/transaction.h" #include "storage/browser/quota/special_storage_policy.h" +#include "url/gurl.h" using blink::mojom::StorageType; @@ -120,7 +121,7 @@ : type(StorageType::kUnknown), used_count(0) {} QuotaDatabase::OriginInfoTableEntry::OriginInfoTableEntry( - const GURL& origin, + const url::Origin& origin, StorageType type, int used_count, const base::Time& last_access_time, @@ -129,8 +130,7 @@ type(type), used_count(used_count), last_access_time(last_access_time), - last_modified_time(last_modified_time) { -} + last_modified_time(last_modified_time) {} // QuotaDatabase ------------------------------------------------------------ QuotaDatabase::QuotaDatabase(const base::FilePath& path) @@ -187,8 +187,9 @@ return true; } -bool QuotaDatabase::SetOriginLastAccessTime( - const GURL& origin, StorageType type, base::Time last_access_time) { +bool QuotaDatabase::SetOriginLastAccessTime(const url::Origin& origin, + StorageType type, + base::Time last_access_time) { if (!LazyOpen(true)) return false; @@ -214,7 +215,7 @@ } statement.BindInt(0, entry.used_count); statement.BindInt64(1, last_access_time.ToInternalValue()); - statement.BindString(2, origin.spec()); + statement.BindString(2, origin.GetURL().spec()); statement.BindInt(3, static_cast<int>(type)); if (!statement.Run()) @@ -224,8 +225,9 @@ return true; } -bool QuotaDatabase::SetOriginLastModifiedTime( - const GURL& origin, StorageType type, base::Time last_modified_time) { +bool QuotaDatabase::SetOriginLastModifiedTime(const url::Origin& origin, + StorageType type, + base::Time last_modified_time) { if (!LazyOpen(true)) return false; @@ -247,7 +249,7 @@ statement.BindInt64(3, last_modified_time.ToInternalValue()); } statement.BindInt64(0, last_modified_time.ToInternalValue()); - statement.BindString(1, origin.spec()); + statement.BindString(1, origin.GetURL().spec()); statement.BindInt(2, static_cast<int>(type)); if (!statement.Run()) @@ -257,7 +259,7 @@ return true; } -bool QuotaDatabase::GetOriginLastEvictionTime(const GURL& origin, +bool QuotaDatabase::GetOriginLastEvictionTime(const url::Origin& origin, StorageType type, base::Time* last_modified_time) { DCHECK(last_modified_time); @@ -270,7 +272,7 @@ " WHERE origin = ? AND type = ?"; sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, origin.spec()); + statement.BindString(0, origin.GetURL().spec()); statement.BindInt(1, static_cast<int>(type)); if (!statement.Step()) @@ -280,7 +282,7 @@ return true; } -bool QuotaDatabase::SetOriginLastEvictionTime(const GURL& origin, +bool QuotaDatabase::SetOriginLastEvictionTime(const url::Origin& origin, StorageType type, base::Time last_modified_time) { if (!LazyOpen(true)) @@ -292,7 +294,7 @@ " VALUES (?, ?, ?)"; sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindInt64(0, last_modified_time.ToInternalValue()); - statement.BindString(1, origin.spec()); + statement.BindString(1, origin.GetURL().spec()); statement.BindInt(2, static_cast<int>(type)); if (!statement.Run()) @@ -302,7 +304,7 @@ return true; } -bool QuotaDatabase::DeleteOriginLastEvictionTime(const GURL& origin, +bool QuotaDatabase::DeleteOriginLastEvictionTime(const url::Origin& origin, StorageType type) { if (!LazyOpen(false)) return false; @@ -312,7 +314,7 @@ " WHERE origin = ? AND type = ?"; sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, origin.spec()); + statement.BindString(0, origin.GetURL().spec()); statement.BindInt(1, static_cast<int>(type)); if (!statement.Run()) @@ -323,7 +325,8 @@ } bool QuotaDatabase::RegisterInitialOriginInfo( - const std::set<GURL>& origins, StorageType type) { + const std::set<url::Origin>& origins, + StorageType type) { if (!LazyOpen(true)) return false; @@ -332,7 +335,7 @@ "INSERT OR IGNORE INTO OriginInfoTable" " (origin, type) VALUES (?, ?)"; sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, origin.spec()); + statement.BindString(0, origin.GetURL().spec()); statement.BindInt(1, static_cast<int>(type)); if (!statement.Run()) @@ -343,7 +346,7 @@ return true; } -bool QuotaDatabase::GetOriginInfo(const GURL& origin, +bool QuotaDatabase::GetOriginInfo(const url::Origin& origin, StorageType type, QuotaDatabase::OriginInfoTableEntry* entry) { if (!LazyOpen(false)) @@ -353,14 +356,15 @@ "SELECT * FROM OriginInfoTable" " WHERE origin = ? AND type = ?"; sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, origin.spec()); + statement.BindString(0, origin.GetURL().spec()); statement.BindInt(1, static_cast<int>(type)); if (!statement.Step()) return false; + // TODO(crbug.com/889590): Use helper for url::Origin creation from string. *entry = OriginInfoTableEntry( - GURL(statement.ColumnString(0)), + url::Origin::Create(GURL(statement.ColumnString(0))), static_cast<StorageType>(statement.ColumnInt(1)), statement.ColumnInt(2), base::Time::FromInternalValue(statement.ColumnInt64(3)), base::Time::FromInternalValue(statement.ColumnInt64(4))); @@ -388,8 +392,8 @@ return true; } -bool QuotaDatabase::DeleteOriginInfo( - const GURL& origin, StorageType type) { +bool QuotaDatabase::DeleteOriginInfo(const url::Origin& origin, + StorageType type) { if (!LazyOpen(false)) return false; @@ -398,7 +402,7 @@ " WHERE origin = ? AND type = ?"; sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); - statement.BindString(0, origin.spec()); + statement.BindString(0, origin.GetURL().spec()); statement.BindInt(1, static_cast<int>(type)); if (!statement.Run()) @@ -422,11 +426,10 @@ return meta_table_->SetValue(key, value); } -bool QuotaDatabase::GetLRUOrigin( - StorageType type, - const std::set<GURL>& exceptions, - SpecialStoragePolicy* special_storage_policy, - GURL* origin) { +bool QuotaDatabase::GetLRUOrigin(StorageType type, + const std::set<url::Origin>& exceptions, + SpecialStoragePolicy* special_storage_policy, + base::Optional<url::Origin>* origin) { DCHECK(origin); if (!LazyOpen(false)) return false; @@ -440,26 +443,28 @@ statement.BindInt(0, static_cast<int>(type)); while (statement.Step()) { - GURL url(statement.ColumnString(0)); - if (base::ContainsKey(exceptions, url)) + url::Origin read_origin = + url::Origin::Create(GURL(statement.ColumnString(0))); + if (base::ContainsKey(exceptions, read_origin)) continue; - if (special_storage_policy && ( - special_storage_policy->IsStorageDurable(url) || - special_storage_policy->IsStorageUnlimited(url))) { + if (special_storage_policy && + (special_storage_policy->IsStorageDurable(read_origin.GetURL()) || + special_storage_policy->IsStorageUnlimited(read_origin.GetURL()))) { continue; } - *origin = url; + *origin = read_origin; return true; } - *origin = GURL(); + origin->reset(); return statement.Succeeded(); } -bool QuotaDatabase::GetOriginsModifiedSince( - StorageType type, std::set<GURL>* origins, base::Time modified_since) { +bool QuotaDatabase::GetOriginsModifiedSince(StorageType type, + std::set<url::Origin>* origins, + base::Time modified_since) { DCHECK(origins); if (!LazyOpen(false)) return false; @@ -473,7 +478,7 @@ origins->clear(); while (statement.Step()) - origins->insert(GURL(statement.ColumnString(0))); + origins->insert(url::Origin::Create(GURL(statement.ColumnString(0)))); return statement.Succeeded(); } @@ -749,11 +754,11 @@ while (statement.Step()) { OriginInfoTableEntry entry( - GURL(statement.ColumnString(0)), - static_cast<StorageType>(statement.ColumnInt(1)), - statement.ColumnInt(2), - base::Time::FromInternalValue(statement.ColumnInt64(3)), - base::Time::FromInternalValue(statement.ColumnInt64(4))); + url::Origin::Create(GURL(statement.ColumnString(0))), + static_cast<StorageType>(statement.ColumnInt(1)), + statement.ColumnInt(2), + base::Time::FromInternalValue(statement.ColumnInt64(3)), + base::Time::FromInternalValue(statement.ColumnInt64(4))); if (!callback.Run(entry)) return true;
diff --git a/storage/browser/quota/quota_database.h b/storage/browser/quota/quota_database.h index 529387f..e8a1f3ea 100644 --- a/storage/browser/quota/quota_database.h +++ b/storage/browser/quota/quota_database.h
@@ -19,7 +19,7 @@ #include "base/timer/timer.h" #include "storage/browser/storage_browser_export.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -#include "url/gurl.h" +#include "url/origin.h" namespace content { class QuotaDatabaseTest; @@ -30,8 +30,6 @@ class MetaTable; } -class GURL; - namespace storage { class SpecialStoragePolicy; @@ -41,12 +39,12 @@ public: struct STORAGE_EXPORT OriginInfoTableEntry { OriginInfoTableEntry(); - OriginInfoTableEntry(const GURL& origin, + OriginInfoTableEntry(const url::Origin& origin, blink::mojom::StorageType type, int used_count, const base::Time& last_access_time, const base::Time& last_modified_time); - GURL origin; + url::Origin origin; blink::mojom::StorageType type; int used_count; base::Time last_access_time; @@ -74,41 +72,42 @@ int64_t quota); bool DeleteHostQuota(const std::string& host, blink::mojom::StorageType type); - bool SetOriginLastAccessTime(const GURL& origin, + bool SetOriginLastAccessTime(const url::Origin& origin, blink::mojom::StorageType type, base::Time last_access_time); - bool SetOriginLastModifiedTime(const GURL& origin, + bool SetOriginLastModifiedTime(const url::Origin& origin, blink::mojom::StorageType type, base::Time last_modified_time); // Gets the time |origin| was last evicted. Returns whether the record could // be found. - bool GetOriginLastEvictionTime(const GURL& origin, + bool GetOriginLastEvictionTime(const url::Origin& origin, blink::mojom::StorageType type, base::Time* last_eviction_time); // Sets the time the origin was last evicted. Returns whether the operation // succeeded. - bool SetOriginLastEvictionTime(const GURL& origin, + bool SetOriginLastEvictionTime(const url::Origin& origin, blink::mojom::StorageType type, base::Time last_eviction_time); - bool DeleteOriginLastEvictionTime(const GURL& origin, + bool DeleteOriginLastEvictionTime(const url::Origin& origin, blink::mojom::StorageType type); // Register initial |origins| info |type| to the database. // This method is assumed to be called only after the installation or // the database schema reset. - bool RegisterInitialOriginInfo(const std::set<GURL>& origins, + bool RegisterInitialOriginInfo(const std::set<url::Origin>& origins, blink::mojom::StorageType type); // Gets the OriginInfoTableEntry for |origin|. Returns whether the record // could be found. - bool GetOriginInfo(const GURL& origin, + bool GetOriginInfo(const url::Origin& origin, blink::mojom::StorageType type, OriginInfoTableEntry* entry); - bool DeleteOriginInfo(const GURL& origin, blink::mojom::StorageType type); + bool DeleteOriginInfo(const url::Origin& origin, + blink::mojom::StorageType type); bool GetQuotaConfigValue(const char* key, int64_t* value); bool SetQuotaConfigValue(const char* key, int64_t value); @@ -116,16 +115,16 @@ // Sets |origin| to the least recently used origin of origins not included // in |exceptions| and not granted the special unlimited storage right. // It returns false when it failed in accessing the database. - // |origin| is set to empty when there is no matching origin. + // |origin| is set to nullopt when there is no matching origin. bool GetLRUOrigin(blink::mojom::StorageType type, - const std::set<GURL>& exceptions, + const std::set<url::Origin>& exceptions, SpecialStoragePolicy* special_storage_policy, - GURL* origin); + base::Optional<url::Origin>* origin); // Populates |origins| with the ones that have been modified since // the |modified_since|. Returns whether the operation succeeded. bool GetOriginsModifiedSince(blink::mojom::StorageType type, - std::set<GURL>* origins, + std::set<url::Origin>* origins, base::Time modified_since); // Returns false if SetOriginDatabaseBootstrapped has never
diff --git a/storage/browser/quota/quota_database_unittest.cc b/storage/browser/quota/quota_database_unittest.cc index 0e2e5a5..e0de603 100644 --- a/storage/browser/quota/quota_database_unittest.cc +++ b/storage/browser/quota/quota_database_unittest.cc
@@ -152,15 +152,16 @@ QuotaDatabase db(kDbFile); ASSERT_TRUE(db.LazyOpen(true)); - std::set<GURL> exceptions; - GURL origin; + std::set<url::Origin> exceptions; + base::Optional<url::Origin> origin; EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); - EXPECT_TRUE(origin.is_empty()); + EXPECT_FALSE(origin.has_value()); - const GURL kOrigin1("http://a/"); - const GURL kOrigin2("http://b/"); - const GURL kOrigin3("http://c/"); - const GURL kOrigin4("http://p/"); + // TODO(crbug.com/889590): Use helper for url::Origin creation from string. + const url::Origin kOrigin1 = url::Origin::Create(GURL("http://a/")); + const url::Origin kOrigin2 = url::Origin::Create(GURL("http://b/")); + const url::Origin kOrigin3 = url::Origin::Create(GURL("http://c/")); + const url::Origin kOrigin4 = url::Origin::Create(GURL("http://p/")); // Adding three temporary storages, and EXPECT_TRUE(db.SetOriginLastAccessTime(kOrigin1, kTemporary, @@ -175,33 +176,33 @@ base::Time::FromInternalValue(40))); EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); - EXPECT_EQ(kOrigin1.spec(), origin.spec()); + EXPECT_EQ(kOrigin1, origin); // Test that unlimited origins are exluded from eviction, but // protected origins are not excluded. scoped_refptr<MockSpecialStoragePolicy> policy( new MockSpecialStoragePolicy); - policy->AddUnlimited(kOrigin1); - policy->AddProtected(kOrigin2); + policy->AddUnlimited(kOrigin1.GetURL()); + policy->AddProtected(kOrigin2.GetURL()); EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, policy.get(), &origin)); - EXPECT_EQ(kOrigin2.spec(), origin.spec()); + EXPECT_EQ(kOrigin2, origin); // Test that durable origins are excluded from eviction. - policy->AddDurable(kOrigin2); + policy->AddDurable(kOrigin2.GetURL()); EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, policy.get(), &origin)); - EXPECT_EQ(kOrigin3.spec(), origin.spec()); + EXPECT_EQ(kOrigin3, origin); exceptions.insert(kOrigin1); EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); - EXPECT_EQ(kOrigin2.spec(), origin.spec()); + EXPECT_EQ(kOrigin2, origin); exceptions.insert(kOrigin2); EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); - EXPECT_EQ(kOrigin3.spec(), origin.spec()); + EXPECT_EQ(kOrigin3, origin); exceptions.insert(kOrigin3); EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); - EXPECT_TRUE(origin.is_empty()); + EXPECT_FALSE(origin.has_value()); EXPECT_TRUE( db.SetOriginLastAccessTime(kOrigin1, kTemporary, base::Time::Now())); @@ -212,25 +213,25 @@ // Querying again to see if the deletion has worked. exceptions.clear(); EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); - EXPECT_EQ(kOrigin2.spec(), origin.spec()); + EXPECT_EQ(kOrigin2, origin); exceptions.insert(kOrigin1); exceptions.insert(kOrigin2); EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); - EXPECT_TRUE(origin.is_empty()); + EXPECT_FALSE(origin.has_value()); } void OriginLastModifiedSince(const base::FilePath& kDbFile) { QuotaDatabase db(kDbFile); ASSERT_TRUE(db.LazyOpen(true)); - std::set<GURL> origins; + std::set<url::Origin> origins; EXPECT_TRUE(db.GetOriginsModifiedSince(kTemporary, &origins, base::Time())); EXPECT_TRUE(origins.empty()); - const GURL kOrigin1("http://a/"); - const GURL kOrigin2("http://b/"); - const GURL kOrigin3("http://c/"); + const url::Origin kOrigin1 = url::Origin::Create(GURL("http://a/")); + const url::Origin kOrigin2 = url::Origin::Create(GURL("http://b/")); + const url::Origin kOrigin3 = url::Origin::Create(GURL("http://c/")); // Report last mod time for the test origins. EXPECT_TRUE(db.SetOriginLastModifiedTime(kOrigin1, kTemporary, @@ -299,9 +300,9 @@ QuotaDatabase db(kDbFile); ASSERT_TRUE(db.LazyOpen(true)); - const GURL kOrigin1("http://a/"); - const GURL kOrigin2("http://b/"); - const GURL kOrigin3("http://c/"); + const url::Origin kOrigin1 = url::Origin::Create(GURL("http://a/")); + const url::Origin kOrigin2 = url::Origin::Create(GURL("http://b/")); + const url::Origin kOrigin3 = url::Origin::Create(GURL("http://c/")); base::Time last_eviction_time; EXPECT_FALSE(db.GetOriginLastEvictionTime(kOrigin1, kTemporary, @@ -343,36 +344,39 @@ EXPECT_EQ(base::Time(), last_eviction_time); // Deleting an origin that is not present should not fail. - EXPECT_TRUE(db.DeleteOriginLastEvictionTime(GURL("http://notpresent.com"), - kTemporary)); + EXPECT_TRUE(db.DeleteOriginLastEvictionTime( + url::Origin::Create(GURL("http://notpresent.com")), kTemporary)); } void RegisterInitialOriginInfo(const base::FilePath& kDbFile) { QuotaDatabase db(kDbFile); - const GURL kOrigins[] = { - GURL("http://a/"), - GURL("http://b/"), - GURL("http://c/") }; - std::set<GURL> origins(kOrigins, kOrigins + base::size(kOrigins)); + const url::Origin kOrigins[] = {url::Origin::Create(GURL("http://a/")), + url::Origin::Create(GURL("http://b/")), + url::Origin::Create(GURL("http://c/"))}; + std::set<url::Origin> origins(kOrigins, kOrigins + base::size(kOrigins)); EXPECT_TRUE(db.RegisterInitialOriginInfo(origins, kTemporary)); QuotaDatabase::OriginInfoTableEntry info; info.used_count = -1; - EXPECT_TRUE(db.GetOriginInfo(GURL("http://a/"), kTemporary, &info)); + EXPECT_TRUE(db.GetOriginInfo(url::Origin::Create(GURL("http://a/")), + kTemporary, &info)); EXPECT_EQ(0, info.used_count); - EXPECT_TRUE(db.SetOriginLastAccessTime(GURL("http://a/"), kTemporary, - base::Time::FromDoubleT(1.0))); + EXPECT_TRUE( + db.SetOriginLastAccessTime(url::Origin::Create(GURL("http://a/")), + kTemporary, base::Time::FromDoubleT(1.0))); info.used_count = -1; - EXPECT_TRUE(db.GetOriginInfo(GURL("http://a/"), kTemporary, &info)); + EXPECT_TRUE(db.GetOriginInfo(url::Origin::Create(GURL("http://a/")), + kTemporary, &info)); EXPECT_EQ(1, info.used_count); EXPECT_TRUE(db.RegisterInitialOriginInfo(origins, kTemporary)); info.used_count = -1; - EXPECT_TRUE(db.GetOriginInfo(GURL("http://a/"), kTemporary, &info)); + EXPECT_TRUE(db.GetOriginInfo(url::Origin::Create(GURL("http://a/")), + kTemporary, &info)); EXPECT_EQ(1, info.used_count); } @@ -414,9 +418,11 @@ base::Time now(base::Time::Now()); using Entry = QuotaDatabase::OriginInfoTableEntry; Entry kTableEntries[] = { - Entry(GURL("http://go/"), kTemporary, 2147483647, now, now), - Entry(GURL("http://oo/"), kTemporary, 0, now, now), - Entry(GURL("http://gle/"), kTemporary, 1, now, now), + Entry(url::Origin::Create(GURL("http://go/")), kTemporary, 2147483647, + now, now), + Entry(url::Origin::Create(GURL("http://oo/")), kTemporary, 0, now, now), + Entry(url::Origin::Create(GURL("http://gle/")), kTemporary, 1, now, + now), }; Entry* begin = kTableEntries; Entry* end = kTableEntries + base::size(kTableEntries); @@ -434,7 +440,7 @@ } void GetOriginInfo(const base::FilePath& kDbFile) { - const GURL kOrigin = GURL("http://go/"); + const url::Origin kOrigin = url::Origin::Create(GURL("http://go/")); using Entry = QuotaDatabase::OriginInfoTableEntry; Entry kTableEntries[] = { Entry(kOrigin, kTemporary, 100, base::Time(), base::Time())}; @@ -459,7 +465,8 @@ { Entry entry; EXPECT_FALSE( - db.GetOriginInfo(GURL("http://notpresent.org/"), kTemporary, &entry)); + db.GetOriginInfo(url::Origin::Create(GURL("http://notpresent.org/")), + kTemporary, &entry)); } } @@ -495,7 +502,7 @@ statement.Assign(db->GetCachedStatement(SQL_FROM_HERE, kSql)); ASSERT_TRUE(statement.is_valid()); - statement.BindString(0, itr->origin.spec()); + statement.BindString(0, itr->origin.GetURL().spec()); statement.BindInt(1, static_cast<int>(itr->type)); statement.BindInt(2, itr->used_count); statement.BindInt64(3, itr->last_access_time.ToInternalValue());
diff --git a/storage/browser/quota/quota_manager.cc b/storage/browser/quota/quota_manager.cc index 41a92cc..11a057a 100644 --- a/storage/browser/quota/quota_manager.cc +++ b/storage/browser/quota/quota_manager.cc
@@ -87,7 +87,7 @@ return type == StorageType::kTemporary || type == StorageType::kPersistent; } -void CountOriginType(const std::set<GURL>& origins, +void CountOriginType(const std::set<url::Origin>& origins, SpecialStoragePolicy* policy, size_t* protected_origins, size_t* unlimited_origins) { @@ -98,9 +98,10 @@ if (!policy) return; for (const auto& origin : origins) { - if (policy->IsStorageProtected(origin)) + const GURL url = origin.GetURL(); + if (policy->IsStorageProtected(url)) ++*protected_origins; - if (policy->IsStorageUnlimited(origin)) + if (policy->IsStorageUnlimited(url)) ++*unlimited_origins; } } @@ -124,16 +125,16 @@ } bool GetLRUOriginOnDBThread(StorageType type, - const std::set<GURL>& exceptions, + const std::set<url::Origin>& exceptions, SpecialStoragePolicy* policy, - GURL* url, + base::Optional<url::Origin>* origin, QuotaDatabase* database) { DCHECK(database); - database->GetLRUOrigin(type, exceptions, policy, url); + database->GetLRUOrigin(type, exceptions, policy, origin); return true; } -bool DeleteOriginInfoOnDBThread(const GURL& origin, +bool DeleteOriginInfoOnDBThread(const url::Origin& origin, StorageType type, bool is_eviction, QuotaDatabase* database) { @@ -172,7 +173,7 @@ return database->SetOriginLastEvictionTime(origin, type, now); } -bool BootstrapDatabaseOnDBThread(const std::set<GURL>* origins, +bool BootstrapDatabaseOnDBThread(const std::set<url::Origin>* origins, QuotaDatabase* database) { DCHECK(database); if (database->IsOriginDatabaseBootstrapped()) @@ -186,7 +187,7 @@ return false; } -bool UpdateAccessTimeOnDBThread(const GURL& origin, +bool UpdateAccessTimeOnDBThread(const url::Origin& origin, StorageType type, base::Time accessed_time, QuotaDatabase* database) { @@ -194,7 +195,7 @@ return database->SetOriginLastAccessTime(origin, type, accessed_time); } -bool UpdateModifiedTimeOnDBThread(const GURL& origin, +bool UpdateModifiedTimeOnDBThread(const url::Origin& origin, StorageType type, base::Time modified_time, QuotaDatabase* database) { @@ -216,7 +217,7 @@ class QuotaManager::UsageAndQuotaHelper : public QuotaTask { public: UsageAndQuotaHelper(QuotaManager* manager, - const GURL& origin, + const url::Origin& origin, StorageType type, bool is_unlimited, bool is_session_only, @@ -240,7 +241,7 @@ 4, base::BindOnce(&UsageAndQuotaHelper::OnBarrierComplete, weak_factory_.GetWeakPtr())); - std::string host = net::GetHostOrSpecFromURL(origin_); + std::string host = net::GetHostOrSpecFromURL(origin_.GetURL()); manager()->GetQuotaSettings( base::BindOnce(&UsageAndQuotaHelper::OnGotSettings, @@ -344,7 +345,7 @@ void OnBarrierComplete() { CallCompleted(); } - GURL origin_; + url::Origin origin_; QuotaManager::UsageAndQuotaWithBreakdownCallback callback_; StorageType type_; bool is_unlimited_; @@ -534,7 +535,7 @@ class QuotaManager::OriginDataDeleter : public QuotaTask { public: OriginDataDeleter(QuotaManager* manager, - const GURL& origin, + const url::Origin& origin, StorageType type, int quota_client_mask, bool is_eviction, @@ -557,7 +558,7 @@ for (auto* client : manager()->clients_) { if (quota_client_mask_ & client->id()) { client->DeleteOriginData( - url::Origin::Create(origin_), type_, + origin_, type_, base::BindOnce(&OriginDataDeleter::DidDeleteOriginData, weak_factory_.GetWeakPtr())); } else { @@ -607,7 +608,7 @@ return static_cast<QuotaManager*>(observer()); } - GURL origin_; + url::Origin origin_; StorageType type_; int quota_client_mask_; int error_count_; @@ -675,7 +676,7 @@ DCHECK_GT(remaining_clients_, 0); for (const auto& origin : origins) - origins_.insert(origin.GetURL()); + origins_.insert(origin); if (--remaining_clients_ == 0) { if (!origins_.empty()) @@ -713,7 +714,7 @@ std::string host_; StorageType type_; int quota_client_mask_; - std::set<GURL> origins_; + std::set<url::Origin> origins_; int error_count_; int remaining_clients_; int remaining_deleters_; @@ -738,7 +739,7 @@ bool success) { if (!manager) { // The operation was aborted. - std::move(callback).Run(std::set<GURL>(), type); + std::move(callback).Run(std::set<url::Origin>(), type); return; } manager->DidDatabaseWork(success); @@ -746,7 +747,7 @@ } private: - std::set<GURL> origins_; + std::set<url::Origin> origins_; }; class QuotaManager::DumpQuotaTableHelper { @@ -851,7 +852,7 @@ get_usage_info->Start(); } -void QuotaManager::GetUsageAndQuotaForWebApps(const GURL& origin, +void QuotaManager::GetUsageAndQuotaForWebApps(const url::Origin& origin, StorageType type, UsageAndQuotaCallback callback) { GetUsageAndQuotaWithBreakdown( @@ -860,10 +861,9 @@ } void QuotaManager::GetUsageAndQuotaWithBreakdown( - const GURL& origin, + const url::Origin& origin, StorageType type, UsageAndQuotaWithBreakdownCallback callback) { - DCHECK(origin == origin.GetOrigin()); if (!IsSupportedType(type) || (is_incognito_ && !IsSupportedIncognitoType(type))) { std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorNotSupported, @@ -872,20 +872,18 @@ } LazyInitialize(); - bool is_session_only = type == StorageType::kTemporary && - special_storage_policy_ && - special_storage_policy_->IsStorageSessionOnly(origin); + bool is_session_only = + type == StorageType::kTemporary && special_storage_policy_ && + special_storage_policy_->IsStorageSessionOnly(origin.GetURL()); UsageAndQuotaHelper* helper = new UsageAndQuotaHelper( this, origin, type, IsStorageUnlimited(origin, type), is_session_only, is_incognito_, std::move(callback)); helper->Start(); } -void QuotaManager::GetUsageAndQuota(const GURL& origin, +void QuotaManager::GetUsageAndQuota(const url::Origin& origin, StorageType type, UsageAndQuotaCallback callback) { - DCHECK(origin == origin.GetOrigin()); - if (IsStorageUnlimited(origin, type)) { // TODO(michaeln): This seems like a non-obvious odd behavior, probably for // apps/extensions, but it would be good to eliminate this special case. @@ -896,28 +894,26 @@ GetUsageAndQuotaForWebApps(origin, type, std::move(callback)); } -void QuotaManager::NotifyStorageAccessed( - QuotaClient::ID client_id, - const GURL& origin, StorageType type) { - DCHECK(origin == origin.GetOrigin()); +void QuotaManager::NotifyStorageAccessed(QuotaClient::ID client_id, + const url::Origin& origin, + StorageType type) { NotifyStorageAccessedInternal(client_id, origin, type, base::Time::Now()); } void QuotaManager::NotifyStorageModified(QuotaClient::ID client_id, - const GURL& origin, + const url::Origin& origin, StorageType type, int64_t delta) { - DCHECK(origin == origin.GetOrigin()); NotifyStorageModifiedInternal(client_id, origin, type, delta, base::Time::Now()); } -void QuotaManager::NotifyOriginInUse(const GURL& origin) { +void QuotaManager::NotifyOriginInUse(const url::Origin& origin) { DCHECK(io_thread_->BelongsToCurrentThread()); origins_in_use_[origin]++; } -void QuotaManager::NotifyOriginNoLongerInUse(const GURL& origin) { +void QuotaManager::NotifyOriginNoLongerInUse(const url::Origin& origin) { DCHECK(io_thread_->BelongsToCurrentThread()); DCHECK(IsOriginInUse(origin)); int& count = origins_in_use_[origin]; @@ -926,7 +922,7 @@ } void QuotaManager::SetUsageCacheEnabled(QuotaClient::ID client_id, - const GURL& origin, + const url::Origin& origin, StorageType type, bool enabled) { LazyInitialize(); @@ -934,7 +930,7 @@ GetUsageTracker(type)->SetUsageCacheEnabled(client_id, origin, enabled); } -void QuotaManager::DeleteOriginData(const GURL& origin, +void QuotaManager::DeleteOriginData(const url::Origin& origin, StorageType type, int quota_client_mask, StatusCallback callback) { @@ -1074,7 +1070,7 @@ } } -bool QuotaManager::IsStorageUnlimited(const GURL& origin, +bool QuotaManager::IsStorageUnlimited(const url::Origin& origin, StorageType type) const { // For syncable storage we should always enforce quota (since the // quota must be capped by the server limit). @@ -1083,7 +1079,7 @@ if (type == StorageType::kQuotaNotManaged) return true; return special_storage_policy_.get() && - special_storage_policy_->IsStorageUnlimited(origin); + special_storage_policy_->IsStorageUnlimited(origin.GetURL()); } void QuotaManager::GetOriginsModifiedSince(StorageType type, @@ -1196,7 +1192,7 @@ int64_t unlimited_usage) { // The usage cache should be fully populated now so we can // seed the database with origins we know about. - std::set<GURL>* origins = new std::set<GURL>; + std::set<url::Origin>* origins = new std::set<url::Origin>; temporary_usage_tracker_->GetCachedOrigins(origins); PostTaskAndReplyWithResultForDBThread( FROM_HERE, @@ -1235,18 +1231,18 @@ return nullptr; } -void QuotaManager::GetCachedOrigins( - StorageType type, std::set<GURL>* origins) { +void QuotaManager::GetCachedOrigins(StorageType type, + std::set<url::Origin>* origins) { DCHECK(origins); LazyInitialize(); DCHECK(GetUsageTracker(type)); GetUsageTracker(type)->GetCachedOrigins(origins); } -void QuotaManager::NotifyStorageAccessedInternal( - QuotaClient::ID client_id, - const GURL& origin, StorageType type, - base::Time accessed_time) { +void QuotaManager::NotifyStorageAccessedInternal(QuotaClient::ID client_id, + const url::Origin& origin, + StorageType type, + base::Time accessed_time) { LazyInitialize(); if (type == StorageType::kTemporary && is_getting_eviction_origin_) { // Record the accessed origins while GetLRUOrigin task is runing @@ -1264,7 +1260,7 @@ } void QuotaManager::NotifyStorageModifiedInternal(QuotaClient::ID client_id, - const GURL& origin, + const url::Origin& origin, StorageType type, int64_t delta, base::Time modified_time) { @@ -1311,7 +1307,7 @@ temporary_storage_evictor_->Start(); } -void QuotaManager::DeleteOriginFromDatabase(const GURL& origin, +void QuotaManager::DeleteOriginFromDatabase(const url::Origin& origin, StorageType type, bool is_eviction) { LazyInitialize(); @@ -1338,19 +1334,18 @@ std::move(eviction_context_.evict_origin_data_callback).Run(status); } -void QuotaManager::DeleteOriginDataInternal(const GURL& origin, +void QuotaManager::DeleteOriginDataInternal(const url::Origin& origin, StorageType type, int quota_client_mask, bool is_eviction, StatusCallback callback) { LazyInitialize(); - if (origin.is_empty() || clients_.empty()) { + if (clients_.empty()) { std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk); return; } - DCHECK(origin == origin.GetOrigin()); OriginDataDeleter* deleter = new OriginDataDeleter( this, origin, type, quota_client_mask, is_eviction, std::move(callback)); deleter->Start(); @@ -1369,7 +1364,7 @@ int64_t unlimited_usage) { UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfTemporaryStorage", usage); - std::set<GURL> origins; + std::set<url::Origin> origins; GetCachedOrigins(StorageType::kTemporary, &origins); size_t num_origins = origins.size(); @@ -1396,7 +1391,7 @@ int64_t unlimited_usage) { UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfPersistentStorage", usage); - std::set<GURL> origins; + std::set<url::Origin> origins; GetCachedOrigins(StorageType::kPersistent, &origins); size_t num_origins = origins.size(); @@ -1421,7 +1416,7 @@ void QuotaManager::DidDumpOriginInfoTableForHistogram( const OriginInfoTableEntries& entries) { - using UsageMap = std::map<GURL, int64_t>; + using UsageMap = std::map<url::Origin, int64_t>; UsageMap usage_map; GetUsageTracker(StorageType::kTemporary)->GetCachedOriginsUsage(&usage_map); base::Time now = base::Time::Now(); @@ -1448,9 +1443,9 @@ } } -std::set<GURL> QuotaManager::GetEvictionOriginExceptions( - const std::set<GURL>& extra_exceptions) { - std::set<GURL> exceptions = extra_exceptions; +std::set<url::Origin> QuotaManager::GetEvictionOriginExceptions( + const std::set<url::Origin>& extra_exceptions) { + std::set<url::Origin> exceptions = extra_exceptions; for (const auto& p : origins_in_use_) { if (p.second > 0) exceptions.insert(p.first); @@ -1464,13 +1459,16 @@ return exceptions; } -void QuotaManager::DidGetEvictionOrigin(GetOriginCallback callback, - const GURL& origin) { +void QuotaManager::DidGetEvictionOrigin( + GetOriginCallback callback, + const base::Optional<url::Origin>& origin) { // Make sure the returned origin is (still) not in the origin_in_use_ set // and has not been accessed since we posted the task. - if (base::ContainsKey(origins_in_use_, origin) || - base::ContainsKey(access_notified_origins_, origin)) { - std::move(callback).Run(GURL()); + DCHECK(!origin.has_value() || !origin->GetURL().is_empty()); + if (origin.has_value() && + (base::ContainsKey(origins_in_use_, *origin) || + base::ContainsKey(access_notified_origins_, *origin))) { + std::move(callback).Run(base::nullopt); } else { std::move(callback).Run(origin); } @@ -1479,10 +1477,11 @@ is_getting_eviction_origin_ = false; } -void QuotaManager::GetEvictionOrigin(StorageType type, - const std::set<GURL>& extra_exceptions, - int64_t global_quota, - GetOriginCallback callback) { +void QuotaManager::GetEvictionOrigin( + StorageType type, + const std::set<url::Origin>& extra_exceptions, + int64_t global_quota, + GetOriginCallback callback) { LazyInitialize(); // This must not be called while there's an in-flight task. DCHECK(!is_getting_eviction_origin_); @@ -1504,7 +1503,7 @@ GetLRUOrigin(type, std::move(did_get_origin_callback)); } -void QuotaManager::EvictOriginData(const GURL& origin, +void QuotaManager::EvictOriginData(const url::Origin& origin, StorageType type, StatusCallback callback) { DCHECK(io_thread_->BelongsToCurrentThread()); @@ -1533,19 +1532,20 @@ DCHECK(lru_origin_callback_.is_null()); lru_origin_callback_ = std::move(callback); if (db_disabled_) { - std::move(lru_origin_callback_).Run(GURL()); + std::move(lru_origin_callback_).Run(base::nullopt); return; } - GURL* url = new GURL; + auto origin = std::make_unique<base::Optional<url::Origin>>(); + auto* origin_ptr = origin.get(); PostTaskAndReplyWithResultForDBThread( FROM_HERE, base::BindOnce(&GetLRUOriginOnDBThread, type, - GetEvictionOriginExceptions(std::set<GURL>()), + GetEvictionOriginExceptions(std::set<url::Origin>()), base::RetainedRef(special_storage_policy_), - base::Unretained(url)), + base::Unretained(origin_ptr)), base::BindOnce(&QuotaManager::DidGetLRUOrigin, weak_factory_.GetWeakPtr(), - base::Owned(url))); + std::move(origin))); } void QuotaManager::DidGetPersistentHostQuota(const std::string& host, @@ -1568,8 +1568,9 @@ *new_quota); } -void QuotaManager::DidGetLRUOrigin(const GURL* origin, - bool success) { +void QuotaManager::DidGetLRUOrigin( + std::unique_ptr<base::Optional<url::Origin>> origin, + bool success) { DidDatabaseWork(success); std::move(lru_origin_callback_).Run(*origin);
diff --git a/storage/browser/quota/quota_manager.h b/storage/browser/quota/quota_manager.h index 8dc6ffdc..7673368 100644 --- a/storage/browser/quota/quota_manager.h +++ b/storage/browser/quota/quota_manager.h
@@ -79,15 +79,15 @@ // the current settings, capacity, and usage. virtual void GetEvictionRoundInfo(EvictionRoundInfoCallback callback) = 0; - // Returns next origin to evict. It might return an empty GURL when there are - // no evictable origins. + // Returns next origin to evict, or nullopt if there are no evictable + // origins. virtual void GetEvictionOrigin(blink::mojom::StorageType type, - const std::set<GURL>& extra_exceptions, + const std::set<url::Origin>& extra_exceptions, int64_t global_quota, GetOriginCallback callback) = 0; // Called to evict an origin. - virtual void EvictOriginData(const GURL& origin, + virtual void EvictOriginData(const url::Origin& origin, blink::mojom::StorageType type, StatusCallback callback) = 0; @@ -144,14 +144,14 @@ // Called by Web Apps. // This method is declared as virtual to allow test code to override it. - virtual void GetUsageAndQuotaForWebApps(const GURL& origin, + virtual void GetUsageAndQuotaForWebApps(const url::Origin& origin, blink::mojom::StorageType type, UsageAndQuotaCallback callback); // Called by DevTools. // This method is declared as virtual to allow test code to override it. virtual void GetUsageAndQuotaWithBreakdown( - const GURL& origin, + const url::Origin& origin, blink::mojom::StorageType type, UsageAndQuotaWithBreakdownCallback callback); @@ -161,7 +161,7 @@ // For UnlimitedStorage origins, this version skips usage and quota handling // to avoid extra query cost. // Do not call this method for apps/user-facing code. - virtual void GetUsageAndQuota(const GURL& origin, + virtual void GetUsageAndQuota(const url::Origin& origin, blink::mojom::StorageType type, UsageAndQuotaCallback callback); @@ -169,28 +169,28 @@ // Client storage should call this method when storage is accessed. // Used to maintain LRU ordering. void NotifyStorageAccessed(QuotaClient::ID client_id, - const GURL& origin, + const url::Origin& origin, blink::mojom::StorageType type); // Called by clients via proxy. // Client storage must call this method whenever they have made any // modifications that change the amount of data stored in their storage. void NotifyStorageModified(QuotaClient::ID client_id, - const GURL& origin, + const url::Origin& origin, blink::mojom::StorageType type, int64_t delta); // Used to avoid evicting origins with open pages. // A call to NotifyOriginInUse must be balanced by a later call // to NotifyOriginNoLongerInUse. - void NotifyOriginInUse(const GURL& origin); - void NotifyOriginNoLongerInUse(const GURL& origin); - bool IsOriginInUse(const GURL& origin) const { + void NotifyOriginInUse(const url::Origin& origin); + void NotifyOriginNoLongerInUse(const url::Origin& origin); + bool IsOriginInUse(const url::Origin& origin) const { return base::ContainsKey(origins_in_use_, origin); } void SetUsageCacheEnabled(QuotaClient::ID client_id, - const GURL& origin, + const url::Origin& origin, blink::mojom::StorageType type, bool enabled); @@ -201,7 +201,7 @@ // from the origin. This is specified by the caller as a bitmask built from // QuotaClient::IDs. Setting the mask to QuotaClient::kAllClientsMask will // remove all clients from the origin, regardless of type. - virtual void DeleteOriginData(const GURL& origin, + virtual void DeleteOriginData(const url::Origin& origin, blink::mojom::StorageType type, int quota_client_mask, StatusCallback callback); @@ -233,7 +233,7 @@ void GetStatistics(std::map<std::string, std::string>* statistics); - bool IsStorageUnlimited(const GURL& origin, + bool IsStorageUnlimited(const url::Origin& origin, blink::mojom::StorageType type) const; virtual void GetOriginsModifiedSince(blink::mojom::StorageType type, @@ -318,7 +318,7 @@ struct EvictionContext { EvictionContext(); ~EvictionContext(); - GURL evicted_origin; + url::Origin evicted_origin; blink::mojom::StorageType evicted_type; StatusCallback evict_origin_data_callback; }; @@ -345,15 +345,15 @@ // Extract cached origins list from the usage tracker. // (Might return empty list if no origin is tracked by the tracker.) void GetCachedOrigins(blink::mojom::StorageType type, - std::set<GURL>* origins); + std::set<url::Origin>* origins); // These internal methods are separately defined mainly for testing. void NotifyStorageAccessedInternal(QuotaClient::ID client_id, - const GURL& origin, + const url::Origin& origin, blink::mojom::StorageType type, base::Time accessed_time); void NotifyStorageModifiedInternal(QuotaClient::ID client_id, - const GURL& origin, + const url::Origin& origin, blink::mojom::StorageType type, int64_t delta, base::Time modified_time); @@ -361,7 +361,7 @@ void DumpQuotaTable(DumpQuotaTableCallback callback); void DumpOriginInfoTable(DumpOriginInfoTableCallback callback); - void DeleteOriginDataInternal(const GURL& origin, + void DeleteOriginDataInternal(const url::Origin& origin, blink::mojom::StorageType type, int quota_client_mask, bool is_eviction, @@ -369,7 +369,7 @@ // Methods for eviction logic. void StartEviction(); - void DeleteOriginFromDatabase(const GURL& origin, + void DeleteOriginFromDatabase(const url::Origin& origin, blink::mojom::StorageType type, bool is_eviction); @@ -383,16 +383,17 @@ void DidDumpOriginInfoTableForHistogram( const OriginInfoTableEntries& entries); - std::set<GURL> GetEvictionOriginExceptions( - const std::set<GURL>& extra_exceptions); - void DidGetEvictionOrigin(GetOriginCallback callback, const GURL& origin); + std::set<url::Origin> GetEvictionOriginExceptions( + const std::set<url::Origin>& extra_exceptions); + void DidGetEvictionOrigin(GetOriginCallback callback, + const base::Optional<url::Origin>& origin); // QuotaEvictionHandler. void GetEvictionOrigin(blink::mojom::StorageType type, - const std::set<GURL>& extra_exceptions, + const std::set<url::Origin>& extra_exceptions, int64_t global_quota, GetOriginCallback callback) override; - void EvictOriginData(const GURL& origin, + void EvictOriginData(const url::Origin& origin, blink::mojom::StorageType type, StatusCallback callback) override; void GetEvictionRoundInfo(EvictionRoundInfoCallback callback) override; @@ -406,7 +407,7 @@ QuotaCallback callback, const int64_t* new_quota, bool success); - void DidGetLRUOrigin(const GURL* origin, + void DidGetLRUOrigin(std::unique_ptr<base::Optional<url::Origin>> origin, bool success); void GetQuotaSettings(QuotaSettingsCallback callback); void DidGetSettings(base::TimeTicks start_ticks, @@ -449,7 +450,7 @@ StorageCapacityCallbackQueue storage_capacity_callbacks_; GetOriginCallback lru_origin_callback_; - std::set<GURL> access_notified_origins_; + std::set<url::Origin> access_notified_origins_; QuotaClientList clients_; @@ -466,9 +467,9 @@ HostQuotaCallbackMap persistent_host_quota_callbacks_; // Map from origin to count. - std::map<GURL, int> origins_in_use_; + std::map<url::Origin, int> origins_in_use_; // Map from origin to error count. - std::map<GURL, int> origins_in_error_; + std::map<url::Origin, int> origins_in_error_; scoped_refptr<SpecialStoragePolicy> special_storage_policy_;
diff --git a/storage/browser/quota/quota_manager_proxy.cc b/storage/browser/quota/quota_manager_proxy.cc index 1a0f110..0125cff 100644 --- a/storage/browser/quota/quota_manager_proxy.cc +++ b/storage/browser/quota/quota_manager_proxy.cc
@@ -64,7 +64,7 @@ } if (manager_) - manager_->NotifyStorageAccessed(client_id, origin.GetURL(), type); + manager_->NotifyStorageAccessed(client_id, origin, type); } void QuotaManagerProxy::NotifyStorageModified(QuotaClient::ID client_id, @@ -79,7 +79,7 @@ } if (manager_) - manager_->NotifyStorageModified(client_id, origin.GetURL(), type, delta); + manager_->NotifyStorageModified(client_id, origin, type, delta); } void QuotaManagerProxy::NotifyOriginInUse(const url::Origin& origin) { @@ -91,7 +91,7 @@ } if (manager_) - manager_->NotifyOriginInUse(origin.GetURL()); + manager_->NotifyOriginInUse(origin); } void QuotaManagerProxy::NotifyOriginNoLongerInUse(const url::Origin& origin) { @@ -102,7 +102,7 @@ return; } if (manager_) - manager_->NotifyOriginNoLongerInUse(origin.GetURL()); + manager_->NotifyOriginNoLongerInUse(origin); } void QuotaManagerProxy::SetUsageCacheEnabled(QuotaClient::ID client_id, @@ -116,7 +116,7 @@ return; } if (manager_) - manager_->SetUsageCacheEnabled(client_id, origin.GetURL(), type, enabled); + manager_->SetUsageCacheEnabled(client_id, origin, type, enabled); } void QuotaManagerProxy::GetUsageAndQuota( @@ -141,7 +141,7 @@ TRACE_EVENT0("io", "QuotaManagerProxy::GetUsageAndQuota"); manager_->GetUsageAndQuota( - origin.GetURL(), type, + origin, type, base::BindOnce(&DidGetUsageAndQuota, base::RetainedRef(original_task_runner), std::move(callback)));
diff --git a/storage/browser/quota/quota_manager_unittest.cc b/storage/browser/quota/quota_manager_unittest.cc index d5e4f22..b5f4ebfe 100644 --- a/storage/browser/quota/quota_manager_unittest.cc +++ b/storage/browser/quota/quota_manager_unittest.cc
@@ -72,6 +72,7 @@ return std::make_tuple(total, available); } +// TODO(crbug.com/889590): Replace with common converter. url::Origin ToOrigin(const std::string& url) { return url::Origin::Create(GURL(url)); } @@ -136,8 +137,7 @@ &QuotaManagerTest::DidGetUsageInfo, weak_factory_.GetWeakPtr())); } - void GetUsageAndQuotaForWebApps(const GURL& origin, - StorageType type) { + void GetUsageAndQuotaForWebApps(const url::Origin& origin, StorageType type) { quota_status_ = QuotaStatusCode::kUnknown; usage_ = -1; quota_ = -1; @@ -147,7 +147,8 @@ weak_factory_.GetWeakPtr())); } - void GetUsageAndQuotaWithBreakdown(const GURL& origin, StorageType type) { + void GetUsageAndQuotaWithBreakdown(const url::Origin& origin, + StorageType type) { quota_status_ = QuotaStatusCode::kUnknown; usage_ = -1; quota_ = -1; @@ -158,7 +159,7 @@ weak_factory_.GetWeakPtr())); } - void GetUsageAndQuotaForStorageClient(const GURL& origin, + void GetUsageAndQuotaForStorageClient(const url::Origin& origin, StorageType type) { quota_status_ = QuotaStatusCode::kUnknown; usage_ = -1; @@ -223,7 +224,8 @@ weak_factory_.GetWeakPtr())); } - void RunAdditionalUsageAndQuotaTask(const GURL& origin, StorageType type) { + void RunAdditionalUsageAndQuotaTask(const url::Origin& origin, + StorageType type) { quota_manager_->GetUsageAndQuota( origin, type, base::BindOnce(&QuotaManagerTest::DidGetUsageAndQuotaAdditional, @@ -231,17 +233,16 @@ } void DeleteClientOriginData(QuotaClient* client, - const GURL& origin, + const url::Origin& origin, StorageType type) { DCHECK(client); quota_status_ = QuotaStatusCode::kUnknown; - client->DeleteOriginData(url::Origin::Create(origin), type, + client->DeleteOriginData(origin, type, base::BindOnce(&QuotaManagerTest::StatusCallback, weak_factory_.GetWeakPtr())); } - void EvictOriginData(const GURL& origin, - StorageType type) { + void EvictOriginData(const url::Origin& origin, StorageType type) { quota_status_ = QuotaStatusCode::kUnknown; quota_manager_->EvictOriginData( origin, type, @@ -249,7 +250,7 @@ weak_factory_.GetWeakPtr())); } - void DeleteOriginData(const GURL& origin, + void DeleteOriginData(const url::Origin& origin, StorageType type, int quota_client_mask) { quota_status_ = QuotaStatusCode::kUnknown; @@ -287,39 +288,39 @@ weak_factory_.GetWeakPtr())); } - void GetCachedOrigins(StorageType type, std::set<GURL>* origins) { + void GetCachedOrigins(StorageType type, std::set<url::Origin>* origins) { ASSERT_TRUE(origins != nullptr); origins->clear(); quota_manager_->GetCachedOrigins(type, origins); } void NotifyStorageAccessed(QuotaClient* client, - const GURL& origin, + const url::Origin& origin, StorageType type) { DCHECK(client); quota_manager_->NotifyStorageAccessedInternal( client->id(), origin, type, IncrementMockTime()); } - void DeleteOriginFromDatabase(const GURL& origin, StorageType type) { + void DeleteOriginFromDatabase(const url::Origin& origin, StorageType type) { quota_manager_->DeleteOriginFromDatabase(origin, type, false); } void GetEvictionOrigin(StorageType type) { - eviction_origin_ = GURL(); + eviction_origin_.reset(); // The quota manager's default eviction policy is to use an LRU eviction // policy. quota_manager_->GetEvictionOrigin( - type, std::set<GURL>(), 0, + type, std::set<url::Origin>(), 0, base::BindOnce(&QuotaManagerTest::DidGetEvictionOrigin, weak_factory_.GetWeakPtr())); } - void NotifyOriginInUse(const GURL& origin) { + void NotifyOriginInUse(const url::Origin& origin) { quota_manager_->NotifyOriginInUse(origin); } - void NotifyOriginNoLongerInUse(const GURL& origin) { + void NotifyOriginNoLongerInUse(const url::Origin& origin) { quota_manager_->NotifyOriginNoLongerInUse(origin); } @@ -414,11 +415,13 @@ usage_ = global_usage; } - void DidGetEvictionOrigin(const GURL& origin) { + void DidGetEvictionOrigin(const base::Optional<url::Origin>& origin) { eviction_origin_ = origin; + DCHECK(!origin.has_value() || !origin->GetURL().is_empty()); } - void DidGetModifiedOrigins(const std::set<GURL>& origins, StorageType type) { + void DidGetModifiedOrigins(const std::set<url::Origin>& origins, + StorageType type) { modified_origins_ = origins; modified_origins_type_ = type; } @@ -461,8 +464,12 @@ int64_t quota() const { return quota_; } int64_t total_space() const { return total_space_; } int64_t available_space() const { return available_space_; } - const GURL& eviction_origin() const { return eviction_origin_; } - const std::set<GURL>& modified_origins() const { return modified_origins_; } + const base::Optional<url::Origin>& eviction_origin() const { + return eviction_origin_; + } + const std::set<url::Origin>& modified_origins() const { + return modified_origins_; + } StorageType modified_origins_type() const { return modified_origins_type_; } const QuotaTableEntries& quota_entries() const { return quota_entries_; } const OriginInfoTableEntries& origin_info_entries() const { @@ -496,8 +503,8 @@ int64_t quota_; int64_t total_space_; int64_t available_space_; - GURL eviction_origin_; - std::set<GURL> modified_origins_; + base::Optional<url::Origin> eviction_origin_; + std::set<url::Origin> modified_origins_; StorageType modified_origins_type_; QuotaTableEntries quota_entries_; OriginInfoTableEntries origin_info_entries_; @@ -560,20 +567,20 @@ RegisterClient( CreateClient(kData, base::size(kData), QuotaClient::kFileSystem)); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(80, usage()); EXPECT_EQ(0, quota()); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); EXPECT_LE(0, quota()); int64_t quota_returned_for_foo = quota(); - GetUsageAndQuotaForWebApps(GURL("http://bar.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://bar.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -581,12 +588,12 @@ } TEST_F(QuotaManagerTest, GetUsage_NoClient) { - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -612,12 +619,12 @@ TEST_F(QuotaManagerTest, GetUsage_EmptyClient) { RegisterClient(CreateClient(nullptr, 0, QuotaClient::kFileSystem)); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -658,7 +665,7 @@ const int kPerHostQuota = 20; SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); @@ -667,7 +674,7 @@ // since there's plenty of diskspace. EXPECT_EQ(kPerHostQuota, quota()); - GetUsageAndQuotaForWebApps(GURL("http://bar.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://bar.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(5 + 7, usage()); @@ -696,25 +703,25 @@ const int64_t kPerHostQuota = kPoolSize / 5; SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(1 + 128, usage()); EXPECT_EQ(kPerHostQuota, quota()); - GetUsageAndQuotaForWebApps(GURL("http://bar.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://bar.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4, usage()); EXPECT_EQ(0, quota()); - GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(512, usage()); EXPECT_EQ(kAvailableSpaceForApp + usage(), quota()); - GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(8, usage()); @@ -754,7 +761,7 @@ RegisterClient(client2); RegisterClient(client3); - GetUsageAndQuotaWithBreakdown(GURL("http://foo.com/"), kPerm); + GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(80, usage()); @@ -763,7 +770,7 @@ usage_breakdown_expected[QuotaClient::kAppcache] = 0; EXPECT_EQ(usage_breakdown_expected, usage_breakdown()); - GetUsageAndQuotaWithBreakdown(GURL("http://foo.com/"), kTemp); + GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(1 + 4 + 8, usage()); @@ -772,7 +779,7 @@ usage_breakdown_expected[QuotaClient::kAppcache] = 8; EXPECT_EQ(usage_breakdown_expected, usage_breakdown()); - GetUsageAndQuotaWithBreakdown(GURL("http://bar.com/"), kTemp); + GetUsageAndQuotaWithBreakdown(ToOrigin("http://bar.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -785,13 +792,13 @@ TEST_F(QuotaManagerTest, GetUsageWithBreakdown_NoClient) { base::flat_map<QuotaClient::ID, int64_t> usage_breakdown_expected; - GetUsageAndQuotaWithBreakdown(GURL("http://foo.com/"), kTemp); + GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); EXPECT_EQ(usage_breakdown_expected, usage_breakdown()); - GetUsageAndQuotaWithBreakdown(GURL("http://foo.com/"), kPerm); + GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -818,14 +825,14 @@ RegisterClient( CreateClient(kData, base::size(kData), QuotaClient::kFileSystem)); - GetUsageAndQuotaWithBreakdown(GURL("http://foo.com/"), kTemp); + GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); usage_breakdown_expected[QuotaClient::kFileSystem] = 10 + 20; EXPECT_EQ(usage_breakdown_expected, usage_breakdown()); - GetUsageAndQuotaWithBreakdown(GURL("http://bar.com/"), kTemp); + GetUsageAndQuotaWithBreakdown(ToOrigin("http://bar.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(5 + 7, usage()); @@ -852,7 +859,7 @@ RegisterClient( CreateClient(kData2, base::size(kData2), QuotaClient::kDatabase)); - GetUsageAndQuotaWithBreakdown(GURL("http://foo.com/"), kTemp); + GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(1 + 128, usage()); @@ -860,7 +867,7 @@ usage_breakdown_expected[QuotaClient::kDatabase] = 128; EXPECT_EQ(usage_breakdown_expected, usage_breakdown()); - GetUsageAndQuotaWithBreakdown(GURL("http://bar.com/"), kPerm); + GetUsageAndQuotaWithBreakdown(ToOrigin("http://bar.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4, usage()); @@ -868,7 +875,7 @@ usage_breakdown_expected[QuotaClient::kDatabase] = 0; EXPECT_EQ(usage_breakdown_expected, usage_breakdown()); - GetUsageAndQuotaWithBreakdown(GURL("http://unlimited/"), kTemp); + GetUsageAndQuotaWithBreakdown(ToOrigin("http://unlimited/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(512, usage()); @@ -876,7 +883,7 @@ usage_breakdown_expected[QuotaClient::kDatabase] = 512; EXPECT_EQ(usage_breakdown_expected, usage_breakdown()); - GetUsageAndQuotaWithBreakdown(GURL("http://unlimited/"), kPerm); + GetUsageAndQuotaWithBreakdown(ToOrigin("http://unlimited/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(8, usage()); @@ -894,7 +901,7 @@ CreateClient(data, base::size(data), QuotaClient::kFileSystem); RegisterClient(client); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), type); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), type); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); @@ -903,14 +910,14 @@ client->ModifyOriginAndNotify(ToOrigin("http://foo.com:1/"), type, -5); client->AddOriginAndNotify(ToOrigin("https://foo.com/"), type, 1); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), type); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), type); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20 + 30 - 5 + 1, usage()); int foo_usage = usage(); client->AddOriginAndNotify(ToOrigin("http://bar.com/"), type, 40); - GetUsageAndQuotaForWebApps(GURL("http://bar.com/"), type); + GetUsageAndQuotaForWebApps(ToOrigin("http://bar.com/"), type); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(40, usage()); @@ -939,19 +946,18 @@ const int kPerHostQuota = 20; SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); EXPECT_EQ(kPerHostQuota, quota()); set_additional_callback_count(0); - RunAdditionalUsageAndQuotaTask(GURL("http://foo.com/"), - kTemp); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); - RunAdditionalUsageAndQuotaTask(GURL("http://bar.com/"), kTemp); + RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); + RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); @@ -973,14 +979,12 @@ SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem); set_additional_callback_count(0); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); - RunAdditionalUsageAndQuotaTask(GURL("http://foo.com/"), - kTemp); - RunAdditionalUsageAndQuotaTask(GURL("http://bar.com/"), - kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); + RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kTemp); + RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kTemp); - DeleteOriginData(GURL("http://foo.com/"), kTemp, kAllClients); - DeleteOriginData(GURL("http://bar.com/"), kTemp, kAllClients); + DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, kAllClients); + DeleteOriginData(ToOrigin("http://bar.com/"), kTemp, kAllClients); // Nuke before waiting for callbacks. set_quota_manager(nullptr); @@ -1007,19 +1011,19 @@ scoped_task_environment_.RunUntilIdle(); EXPECT_LE(kMustRemainAvailableForSystem, available_space()); - GetUsageAndQuotaForWebApps(GURL("http://usage1/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://usage1/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(1, usage()); EXPECT_EQ(kPerHostQuota, quota()); - GetUsageAndQuotaForWebApps(GURL("http://usage10/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://usage10/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); EXPECT_EQ(kPerHostQuota, quota()); - GetUsageAndQuotaForWebApps(GURL("http://usage200/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://usage200/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(200, usage()); @@ -1046,25 +1050,25 @@ EXPECT_EQ(10 + 50 + 4000, usage()); EXPECT_EQ(4000, unlimited_usage()); - GetUsageAndQuotaForWebApps(GURL("http://usage10/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://usage10/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); EXPECT_EQ(kPerHostQuotaFor1000, quota()); - GetUsageAndQuotaForWebApps(GURL("http://usage50/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://usage50/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(50, usage()); EXPECT_EQ(kPerHostQuotaFor1000, quota()); - GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4000, usage()); EXPECT_EQ(kAvailableSpaceForApp + usage(), quota()); - GetUsageAndQuotaForStorageClient(GURL("http://unlimited/"), kTemp); + GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -1074,25 +1078,25 @@ const int kPerHostQuotaFor100 = 20; SetQuotaSettings(100, kPerHostQuotaFor100, kMustRemainAvailableForSystem); - GetUsageAndQuotaForWebApps(GURL("http://usage10/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://usage10/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); - GetUsageAndQuotaForWebApps(GURL("http://usage50/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://usage50/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(50, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); - GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4000, usage()); EXPECT_EQ(kAvailableSpaceForApp + usage(), quota()); - GetUsageAndQuotaForStorageClient(GURL("http://unlimited/"), kTemp); + GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -1107,25 +1111,25 @@ EXPECT_EQ(10 + 50 + 4000, usage()); EXPECT_EQ(0, unlimited_usage()); - GetUsageAndQuotaForWebApps(GURL("http://usage10/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://usage10/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); - GetUsageAndQuotaForWebApps(GURL("http://usage50/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://usage50/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(50, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); - GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4000, usage()); EXPECT_EQ(kPerHostQuotaFor100, quota()); - GetUsageAndQuotaForStorageClient(GURL("http://unlimited/"), kTemp); + GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(4000, usage()); @@ -1133,8 +1137,8 @@ } TEST_F(QuotaManagerTest, OriginInUse) { - const GURL kFooOrigin("http://foo.com/"); - const GURL kBarOrigin("http://bar.com/"); + const url::Origin kFooOrigin = ToOrigin("http://foo.com/"); + const url::Origin kBarOrigin = ToOrigin("http://bar.com/"); EXPECT_FALSE(quota_manager()->IsOriginInUse(kFooOrigin)); quota_manager()->NotifyOriginInUse(kFooOrigin); // count of 1 @@ -1184,14 +1188,14 @@ TEST_F(QuotaManagerTest, GetAndSetPersistentUsageAndQuota) { RegisterClient(CreateClient(nullptr, 0, QuotaClient::kFileSystem)); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); EXPECT_EQ(0, quota()); SetPersistentHostQuota("foo.com", 100); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -1199,13 +1203,13 @@ // The actual space avaialble is given to 'unlimited' origins as their quota. mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); - GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(kAvailableSpaceForApp, quota()); // GetUsageAndQuotaForStorageClient should just return 0 usage and // kNoLimit quota. - GetUsageAndQuotaForStorageClient(GURL("http://unlimited/"), kPerm); + GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(0, usage()); EXPECT_EQ(QuotaManager::kNoLimit, quota()); @@ -1222,7 +1226,7 @@ // For unlimited origins the quota manager should return // kAvailableSpaceForApp as syncable quota (because of the pre-condition). mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/")); - GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kSync); + GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kSync); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(0, usage()); @@ -1244,7 +1248,7 @@ CreateClient(kData, base::size(kData), QuotaClient::kFileSystem)); SetPersistentHostQuota("foo.com", 100); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20 + 13 + 19, usage()); @@ -1266,19 +1270,18 @@ CreateClient(kData, base::size(kData), QuotaClient::kFileSystem)); SetPersistentHostQuota("foo.com", 100); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); EXPECT_EQ(100, quota()); set_additional_callback_count(0); - RunAdditionalUsageAndQuotaTask(GURL("http://foo.com/"), - kPerm); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); - RunAdditionalUsageAndQuotaTask(GURL("http://bar.com/"), kPerm); + RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); + RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10 + 20, usage()); @@ -1297,9 +1300,9 @@ SetPersistentHostQuota("foo.com", 100); set_additional_callback_count(0); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); - RunAdditionalUsageAndQuotaTask(GURL("http://foo.com/"), kPerm); - RunAdditionalUsageAndQuotaTask(GURL("http://bar.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); + RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kPerm); + RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kPerm); // Nuke before waiting for callbacks. set_quota_manager(nullptr); @@ -1412,8 +1415,7 @@ scoped_task_environment_.RunUntilIdle(); int64_t predelete_host_pers = usage(); - DeleteClientOriginData(client, GURL("http://foo.com/"), - kTemp); + DeleteClientOriginData(client, ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); @@ -1471,14 +1473,16 @@ int64_t predelete_host_pers = usage(); for (size_t i = 0; i < base::size(kData1); ++i) - quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown, - GURL(kData1[i].origin), kData1[i].type); + quota_manager()->NotifyStorageAccessed( + QuotaClient::kUnknown, url::Origin::Create(GURL(kData1[i].origin)), + kData1[i].type); for (size_t i = 0; i < base::size(kData2); ++i) - quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown, - GURL(kData2[i].origin), kData2[i].type); + quota_manager()->NotifyStorageAccessed( + QuotaClient::kUnknown, url::Origin::Create(GURL(kData2[i].origin)), + kData2[i].type); scoped_task_environment_.RunUntilIdle(); - EvictOriginData(GURL("http://foo.com/"), kTemp); + EvictOriginData(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); DumpOriginInfoTable(); @@ -1486,7 +1490,7 @@ for (const auto& entry : origin_info_entries()) { if (entry.type == kTemp) - EXPECT_NE(std::string("http://foo.com/"), entry.origin.spec()); + EXPECT_NE(std::string("http://foo.com/"), entry.origin.GetURL().spec()); } GetGlobalUsage(kTemp); @@ -1503,7 +1507,7 @@ } TEST_F(QuotaManagerTest, EvictOriginDataHistogram) { - const GURL kOrigin = GURL("http://foo.com/"); + const url::Origin kOrigin = ToOrigin("http://foo.com/"); static const MockOriginData kData[] = { {"http://foo.com/", kTemp, 1}, }; @@ -1531,11 +1535,10 @@ histograms.ExpectTotalCount( QuotaManager::kDaysBetweenRepeatedOriginEvictionsHistogram, 0); - client->AddOriginAndNotify(url::Origin::Create(kOrigin), kTemp, 100); + client->AddOriginAndNotify(kOrigin, kTemp, 100); // Change the used count of the origin. - quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown, GURL(kOrigin), - kTemp); + quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown, kOrigin, kTemp); scoped_task_environment_.RunUntilIdle(); GetGlobalUsage(kTemp); @@ -1556,7 +1559,7 @@ histograms.ExpectTotalCount( QuotaManager::kDaysBetweenRepeatedOriginEvictionsHistogram, 1); - client->AddOriginAndNotify(url::Origin::Create(kOrigin), kTemp, 100); + client->AddOriginAndNotify(kOrigin, kTemp, 100); GetGlobalUsage(kTemp); scoped_task_environment_.RunUntilIdle(); @@ -1593,7 +1596,8 @@ int64_t predelete_host_pers = usage(); for (size_t i = 0; i < base::size(kData); ++i) - NotifyStorageAccessed(client, GURL(kData[i].origin), kData[i].type); + NotifyStorageAccessed(client, url::Origin::Create(GURL(kData[i].origin)), + kData[i].type); scoped_task_environment_.RunUntilIdle(); client->AddOriginToErrorSet(ToOrigin("http://foo.com/"), kTemp); @@ -1601,7 +1605,7 @@ for (int i = 0; i < QuotaManager::kThresholdOfErrorsToBeBlacklisted + 1; ++i) { - EvictOriginData(GURL("http://foo.com/"), kTemp); + EvictOriginData(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kErrorInvalidModification, status()); } @@ -1611,7 +1615,7 @@ bool found_origin_in_database = false; for (const auto& entry : origin_info_entries()) { - if (entry.type == kTemp && entry.origin == "http://foo.com/") { + if (entry.type == kTemp && entry.origin == ToOrigin("http://foo.com/")) { found_origin_in_database = true; break; } @@ -1622,17 +1626,18 @@ for (size_t i = 0; i < kNumberOfTemporaryOrigins - 1; ++i) { GetEvictionOrigin(kTemp); scoped_task_environment_.RunUntilIdle(); - EXPECT_FALSE(eviction_origin().is_empty()); + EXPECT_TRUE(eviction_origin().has_value()); // The origin "http://foo.com/" should not be in the LRU list. - EXPECT_NE(std::string("http://foo.com/"), eviction_origin().spec()); - DeleteOriginFromDatabase(eviction_origin(), kTemp); + EXPECT_NE(std::string("http://foo.com/"), + eviction_origin()->GetURL().spec()); + DeleteOriginFromDatabase(*eviction_origin(), kTemp); scoped_task_environment_.RunUntilIdle(); } // Now the LRU list must be empty. GetEvictionOrigin(kTemp); scoped_task_environment_.RunUntilIdle(); - EXPECT_TRUE(eviction_origin().is_empty()); + EXPECT_FALSE(eviction_origin().has_value()); // Deleting origins from the database should not affect the results of the // following checks. @@ -1783,10 +1788,10 @@ if (entry.type != kTemp) continue; - EXPECT_NE(std::string("http://foo.com/"), entry.origin.spec()); - EXPECT_NE(std::string("http://foo.com:1/"), entry.origin.spec()); - EXPECT_NE(std::string("https://foo.com/"), entry.origin.spec()); - EXPECT_NE(std::string("http://bar.com/"), entry.origin.spec()); + EXPECT_NE(std::string("http://foo.com/"), entry.origin.GetURL().spec()); + EXPECT_NE(std::string("http://foo.com:1/"), entry.origin.GetURL().spec()); + EXPECT_NE(std::string("https://foo.com/"), entry.origin.GetURL().spec()); + EXPECT_NE(std::string("http://bar.com/"), entry.origin.GetURL().spec()); } GetGlobalUsage(kTemp); @@ -1854,18 +1859,22 @@ scoped_task_environment_.RunUntilIdle(); const int64_t predelete_bar_pers = usage(); - for (size_t i = 0; i < base::size(kData1); ++i) - quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown, - GURL(kData1[i].origin), kData1[i].type); - for (size_t i = 0; i < base::size(kData2); ++i) - quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown, - GURL(kData2[i].origin), kData2[i].type); + for (size_t i = 0; i < base::size(kData1); ++i) { + quota_manager()->NotifyStorageAccessed( + QuotaClient::kUnknown, url::Origin::Create(GURL(kData1[i].origin)), + kData1[i].type); + } + for (size_t i = 0; i < base::size(kData2); ++i) { + quota_manager()->NotifyStorageAccessed( + QuotaClient::kUnknown, url::Origin::Create(GURL(kData2[i].origin)), + kData2[i].type); + } scoped_task_environment_.RunUntilIdle(); reset_status_callback_count(); - DeleteOriginData(GURL("http://foo.com/"), kTemp, kAllClients); - DeleteOriginData(GURL("http://bar.com/"), kTemp, kAllClients); - DeleteOriginData(GURL("http://foo.com/"), kTemp, kAllClients); + DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, kAllClients); + DeleteOriginData(ToOrigin("http://bar.com/"), kTemp, kAllClients); + DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, kAllClients); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(3, status_callback_count()); @@ -1877,8 +1886,8 @@ if (entry.type != kTemp) continue; - EXPECT_NE(std::string("http://foo.com/"), entry.origin.spec()); - EXPECT_NE(std::string("http://bar.com/"), entry.origin.spec()); + EXPECT_NE(std::string("http://foo.com/"), entry.origin.GetURL().spec()); + EXPECT_NE(std::string("http://bar.com/"), entry.origin.GetURL().spec()); } GetGlobalUsage(kTemp); @@ -1915,7 +1924,7 @@ // TODO(kinuko): Be careful when we add cache pruner. - std::set<GURL> origins; + std::set<url::Origin> origins; GetCachedOrigins(kTemp, &origins); EXPECT_TRUE(origins.empty()); @@ -1944,7 +1953,7 @@ for (size_t i = 0; i < base::size(kData); ++i) { if (kData[i].type == kTemp) - EXPECT_TRUE(base::ContainsKey(origins, GURL(kData[i].origin))); + EXPECT_TRUE(base::ContainsKey(origins, ToOrigin(kData[i].origin))); } } @@ -1963,29 +1972,29 @@ GURL origin; GetEvictionOrigin(kTemp); scoped_task_environment_.RunUntilIdle(); - EXPECT_TRUE(eviction_origin().is_empty()); + EXPECT_FALSE(eviction_origin().has_value()); - NotifyStorageAccessed(client, GURL("http://a.com/"), kTemp); + NotifyStorageAccessed(client, ToOrigin("http://a.com/"), kTemp); GetEvictionOrigin(kTemp); scoped_task_environment_.RunUntilIdle(); - EXPECT_EQ("http://a.com/", eviction_origin().spec()); + EXPECT_EQ("http://a.com/", eviction_origin()->GetURL().spec()); - NotifyStorageAccessed(client, GURL("http://b.com/"), kPerm); - NotifyStorageAccessed(client, GURL("https://a.com/"), kTemp); - NotifyStorageAccessed(client, GURL("http://c.com/"), kTemp); + NotifyStorageAccessed(client, ToOrigin("http://b.com/"), kPerm); + NotifyStorageAccessed(client, ToOrigin("https://a.com/"), kTemp); + NotifyStorageAccessed(client, ToOrigin("http://c.com/"), kTemp); GetEvictionOrigin(kTemp); scoped_task_environment_.RunUntilIdle(); - EXPECT_EQ("http://a.com/", eviction_origin().spec()); + EXPECT_EQ("http://a.com/", eviction_origin()->GetURL().spec()); - DeleteOriginFromDatabase(eviction_origin(), kTemp); + DeleteOriginFromDatabase(*eviction_origin(), kTemp); GetEvictionOrigin(kTemp); scoped_task_environment_.RunUntilIdle(); - EXPECT_EQ("https://a.com/", eviction_origin().spec()); + EXPECT_EQ("https://a.com/", eviction_origin()->GetURL().spec()); - DeleteOriginFromDatabase(eviction_origin(), kTemp); + DeleteOriginFromDatabase(*eviction_origin(), kTemp); GetEvictionOrigin(kTemp); scoped_task_environment_.RunUntilIdle(); - EXPECT_EQ("http://c.com/", eviction_origin().spec()); + EXPECT_EQ("http://c.com/", eviction_origin()->GetURL().spec()); } TEST_F(QuotaManagerTest, GetLRUOriginWithOriginInUse) { @@ -2003,44 +2012,44 @@ GURL origin; GetEvictionOrigin(kTemp); scoped_task_environment_.RunUntilIdle(); - EXPECT_TRUE(eviction_origin().is_empty()); + EXPECT_FALSE(eviction_origin().has_value()); - NotifyStorageAccessed(client, GURL("http://a.com/"), kTemp); - NotifyStorageAccessed(client, GURL("http://b.com/"), kPerm); - NotifyStorageAccessed(client, GURL("https://a.com/"), kTemp); - NotifyStorageAccessed(client, GURL("http://c.com/"), kTemp); + NotifyStorageAccessed(client, ToOrigin("http://a.com/"), kTemp); + NotifyStorageAccessed(client, ToOrigin("http://b.com/"), kPerm); + NotifyStorageAccessed(client, ToOrigin("https://a.com/"), kTemp); + NotifyStorageAccessed(client, ToOrigin("http://c.com/"), kTemp); GetEvictionOrigin(kTemp); scoped_task_environment_.RunUntilIdle(); - EXPECT_EQ("http://a.com/", eviction_origin().spec()); + EXPECT_EQ(ToOrigin("http://a.com/"), *eviction_origin()); // Notify origin http://a.com is in use. - NotifyOriginInUse(GURL("http://a.com/")); + NotifyOriginInUse(ToOrigin("http://a.com/")); GetEvictionOrigin(kTemp); scoped_task_environment_.RunUntilIdle(); - EXPECT_EQ("https://a.com/", eviction_origin().spec()); + EXPECT_EQ(ToOrigin("https://a.com/"), *eviction_origin()); // Notify origin https://a.com is in use while GetEvictionOrigin is running. GetEvictionOrigin(kTemp); - NotifyOriginInUse(GURL("https://a.com/")); + NotifyOriginInUse(ToOrigin("https://a.com/")); scoped_task_environment_.RunUntilIdle(); // Post-filtering must have excluded the returned origin, so we will // see empty result here. - EXPECT_TRUE(eviction_origin().is_empty()); + EXPECT_FALSE(eviction_origin().has_value()); // Notify access for http://c.com while GetEvictionOrigin is running. GetEvictionOrigin(kTemp); - NotifyStorageAccessed(client, GURL("http://c.com/"), kTemp); + NotifyStorageAccessed(client, ToOrigin("http://c.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); // Post-filtering must have excluded the returned origin, so we will // see empty result here. - EXPECT_TRUE(eviction_origin().is_empty()); + EXPECT_FALSE(eviction_origin().has_value()); - NotifyOriginNoLongerInUse(GURL("http://a.com/")); - NotifyOriginNoLongerInUse(GURL("https://a.com/")); + NotifyOriginNoLongerInUse(ToOrigin("http://a.com/")); + NotifyOriginNoLongerInUse(ToOrigin("https://a.com/")); GetEvictionOrigin(kTemp); scoped_task_environment_.RunUntilIdle(); - EXPECT_EQ("http://a.com/", eviction_origin().spec()); + EXPECT_EQ(ToOrigin("http://a.com/"), *eviction_origin()); } TEST_F(QuotaManagerTest, GetOriginsModifiedSince) { @@ -2075,7 +2084,7 @@ EXPECT_EQ(modified_origins_type(), kTemp); for (size_t i = 0; i < base::size(kData); ++i) { if (kData[i].type == kTemp) - EXPECT_EQ(1U, modified_origins().count(GURL(kData[i].origin))); + EXPECT_EQ(1U, modified_origins().count(ToOrigin(kData[i].origin))); } GetOriginsModifiedSince(kTemp, time2); @@ -2092,7 +2101,7 @@ GetOriginsModifiedSince(kTemp, time3); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(1U, modified_origins().size()); - EXPECT_EQ(1U, modified_origins().count(GURL("http://a.com/"))); + EXPECT_EQ(1U, modified_origins().count(ToOrigin("http://a.com/"))); EXPECT_EQ(modified_origins_type(), kTemp); } @@ -2124,17 +2133,11 @@ using std::make_pair; quota_manager()->NotifyStorageAccessed( - QuotaClient::kUnknown, - GURL("http://example.com/"), - kTemp); + QuotaClient::kUnknown, ToOrigin("http://example.com/"), kTemp); quota_manager()->NotifyStorageAccessed( - QuotaClient::kUnknown, - GURL("http://example.com/"), - kPerm); + QuotaClient::kUnknown, ToOrigin("http://example.com/"), kPerm); quota_manager()->NotifyStorageAccessed( - QuotaClient::kUnknown, - GURL("http://example.com/"), - kPerm); + QuotaClient::kUnknown, ToOrigin("http://example.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); DumpOriginInfoTable(); @@ -2153,9 +2156,9 @@ << "host = " << origin_info.origin << ", " << "type = " << static_cast<int>(origin_info.type) << ", " << "used_count = " << origin_info.used_count); - EXPECT_EQ(1u, entries.erase( - make_pair(make_pair(origin_info.origin, origin_info.type), - origin_info.used_count))); + EXPECT_EQ(1u, entries.erase(make_pair( + make_pair(origin_info.origin.GetURL(), origin_info.type), + origin_info.used_count))); } EXPECT_TRUE(entries.empty()); } @@ -2201,26 +2204,27 @@ scoped_task_environment_.RunUntilIdle(); const int64_t predelete_foo_tmp = usage(); - DeleteOriginData(GURL("http://foo.com/"), kTemp, QuotaClient::kFileSystem); + DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, + QuotaClient::kFileSystem); scoped_task_environment_.RunUntilIdle(); GetHostUsage("foo.com", kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 1, usage()); - DeleteOriginData(GURL("http://foo.com/"), kTemp, QuotaClient::kAppcache); + DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, QuotaClient::kAppcache); scoped_task_environment_.RunUntilIdle(); GetHostUsage("foo.com", kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage()); - DeleteOriginData(GURL("http://foo.com/"), kTemp, QuotaClient::kDatabase); + DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, QuotaClient::kDatabase); scoped_task_environment_.RunUntilIdle(); GetHostUsage("foo.com", kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 4 - 2 - 1, usage()); - DeleteOriginData(GURL("http://foo.com/"), kTemp, - QuotaClient::kIndexedDatabase); + DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, + QuotaClient::kIndexedDatabase); scoped_task_environment_.RunUntilIdle(); GetHostUsage("foo.com", kTemp); scoped_task_environment_.RunUntilIdle(); @@ -2312,15 +2316,15 @@ scoped_task_environment_.RunUntilIdle(); const int64_t predelete_foo_tmp = usage(); - DeleteOriginData(GURL("http://foo.com/"), kTemp, - QuotaClient::kFileSystem | QuotaClient::kDatabase); + DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, + QuotaClient::kFileSystem | QuotaClient::kDatabase); scoped_task_environment_.RunUntilIdle(); GetHostUsage("foo.com", kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(predelete_foo_tmp - 4 - 1, usage()); - DeleteOriginData(GURL("http://foo.com/"), kTemp, - QuotaClient::kAppcache | QuotaClient::kIndexedDatabase); + DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, + QuotaClient::kAppcache | QuotaClient::kIndexedDatabase); scoped_task_environment_.RunUntilIdle(); GetHostUsage("foo.com", kTemp); scoped_task_environment_.RunUntilIdle(); @@ -2387,7 +2391,7 @@ GetGlobalUsage(kPerm); scoped_task_environment_.RunUntilIdle(); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(80, usage()); @@ -2402,20 +2406,20 @@ EXPECT_EQ(kPoolSize, total_space()); EXPECT_EQ(kPoolSize - 80 - 10, available_space()); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); EXPECT_LE(kPerHostQuota, quota()); mock_special_storage_policy()->AddUnlimited(GURL("http://foo.com/")); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(80, usage()); EXPECT_EQ(available_space() + usage(), quota()); - GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); + GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); EXPECT_EQ(10, usage()); @@ -2423,8 +2427,8 @@ } TEST_F(QuotaManagerTest, GetUsageAndQuota_SessionOnly) { - const GURL kEpheremalOrigin("http://ephemeral/"); - mock_special_storage_policy()->AddSessionOnly(kEpheremalOrigin); + const url::Origin kEpheremalOrigin = ToOrigin("http://ephemeral/"); + mock_special_storage_policy()->AddSessionOnly(kEpheremalOrigin.GetURL()); GetUsageAndQuotaForWebApps(kEpheremalOrigin, kTemp); scoped_task_environment_.RunUntilIdle();
diff --git a/storage/browser/quota/quota_temporary_storage_evictor.cc b/storage/browser/quota/quota_temporary_storage_evictor.cc index e933928..fe405c9 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor.cc +++ b/storage/browser/quota/quota_temporary_storage_evictor.cc
@@ -224,19 +224,21 @@ OnEvictionRoundFinished(); } -void QuotaTemporaryStorageEvictor::OnGotEvictionOrigin(const GURL& origin) { +void QuotaTemporaryStorageEvictor::OnGotEvictionOrigin( + const base::Optional<url::Origin>& origin) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (origin.is_empty()) { + if (!origin.has_value()) { StartEvictionTimerWithDelay(interval_ms_); OnEvictionRoundFinished(); return; } - in_progress_eviction_origins_.insert(origin); + DCHECK(!origin->GetURL().is_empty()); + in_progress_eviction_origins_.insert(*origin); quota_eviction_handler_->EvictOriginData( - origin, blink::mojom::StorageType::kTemporary, + *origin, blink::mojom::StorageType::kTemporary, base::BindOnce(&QuotaTemporaryStorageEvictor::OnEvictionComplete, weak_factory_.GetWeakPtr())); }
diff --git a/storage/browser/quota/quota_temporary_storage_evictor.h b/storage/browser/quota/quota_temporary_storage_evictor.h index 1994de8..9761c02b 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor.h +++ b/storage/browser/quota/quota_temporary_storage_evictor.h
@@ -13,17 +13,20 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "base/sequence_checker.h" #include "base/timer/timer.h" #include "storage/browser/storage_browser_export.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -class GURL; - namespace content { class QuotaTemporaryStorageEvictorTest; } +namespace url { +class Origin; +} + namespace storage { class QuotaEvictionHandler; @@ -89,7 +92,7 @@ int64_t total_space, int64_t current_usage, bool current_usage_is_complete); - void OnGotEvictionOrigin(const GURL& origin); + void OnGotEvictionOrigin(const base::Optional<url::Origin>& origin); void OnEvictionComplete(blink::mojom::QuotaStatusCode status); void OnEvictionRoundStarted(); @@ -103,7 +106,7 @@ EvictionRoundStatistics round_statistics_; base::Time time_of_end_of_last_nonskipped_round_; base::Time time_of_end_of_last_round_; - std::set<GURL> in_progress_eviction_origins_; + std::set<url::Origin> in_progress_eviction_origins_; int64_t interval_ms_; bool timer_disabled_for_testing_;
diff --git a/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc b/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc index b4acd69..44801b4 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc +++ b/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc
@@ -30,6 +30,11 @@ namespace { +// TODO(crbug.com/889590): Replace with common converter. +url::Origin ToOrigin(const std::string& url) { + return url::Origin::Create(GURL(url)); +} + class MockQuotaEvictionHandler : public storage::QuotaEvictionHandler { public: explicit MockQuotaEvictionHandler(QuotaTemporaryStorageEvictorTest* test) @@ -37,7 +42,7 @@ error_on_evict_origin_data_(false), error_on_get_usage_and_quota_(false) {} - void EvictOriginData(const GURL& origin, + void EvictOriginData(const url::Origin& origin, StorageType type, storage::StatusCallback callback) override { if (error_on_evict_origin_data_) { @@ -65,13 +70,13 @@ } void GetEvictionOrigin(StorageType type, - const std::set<GURL>& exceptions, + const std::set<url::Origin>& exceptions, int64_t global_quota, storage::GetOriginCallback callback) override { if (origin_order_.empty()) - std::move(callback).Run(GURL()); + std::move(callback).Run(base::nullopt); else - std::move(callback).Run(GURL(origin_order_.front())); + std::move(callback).Run(origin_order_.front()); } int64_t GetUsage() const { @@ -104,7 +109,7 @@ // Simulates an access to |origin|. It reorders the internal LRU list. // It internally uses AddOrigin(). - void AccessOrigin(const GURL& origin) { + void AccessOrigin(const url::Origin& origin) { const auto& found = origins_.find(origin); EXPECT_TRUE(origins_.end() != found); AddOrigin(origin, found->second); @@ -113,14 +118,14 @@ // Simulates adding or overwriting the |origin| to the internal origin set // with the |usage|. It also adds or moves the |origin| to the end of the // LRU list. - void AddOrigin(const GURL& origin, int64_t usage) { + void AddOrigin(const url::Origin& origin, int64_t usage) { EnsureOriginRemoved(origin); origin_order_.push_back(origin); origins_[origin] = usage; } private: - int64_t EnsureOriginRemoved(const GURL& origin) { + int64_t EnsureOriginRemoved(const url::Origin& origin) { int64_t origin_usage; if (!base::ContainsKey(origins_, origin)) return -1; @@ -134,8 +139,8 @@ storage::QuotaSettings settings_; int64_t available_space_; - std::list<GURL> origin_order_; - std::map<GURL, int64_t> origins_; + std::list<url::Origin> origin_order_; + std::map<url::Origin, int64_t> origins_; bool error_on_evict_origin_data_; bool error_on_get_usage_and_quota_; @@ -165,8 +170,8 @@ } void TaskForRepeatedEvictionTest( - const std::pair<GURL, int64_t>& origin_to_be_added, - const GURL& origin_to_be_accessed, + const std::pair<base::Optional<url::Origin>, int64_t>& origin_to_be_added, + const base::Optional<url::Origin>& origin_to_be_accessed, int expected_usage_after_first, int expected_usage_after_second) { EXPECT_GE(4, num_get_usage_and_quota_for_eviction_); @@ -174,11 +179,11 @@ case 2: EXPECT_EQ(expected_usage_after_first, quota_eviction_handler()->GetUsage()); - if (!origin_to_be_added.first.is_empty()) - quota_eviction_handler()->AddOrigin(origin_to_be_added.first, + if (origin_to_be_added.first.has_value()) + quota_eviction_handler()->AddOrigin(*origin_to_be_added.first, origin_to_be_added.second); - if (!origin_to_be_accessed.is_empty()) - quota_eviction_handler()->AccessOrigin(origin_to_be_accessed); + if (origin_to_be_accessed.has_value()) + quota_eviction_handler()->AccessOrigin(*origin_to_be_accessed); break; case 3: EXPECT_EQ(expected_usage_after_second, @@ -220,9 +225,9 @@ }; TEST_F(QuotaTemporaryStorageEvictorTest, SimpleEvictionTest) { - quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 3000); - quota_eviction_handler()->AddOrigin(GURL("http://www.y.com"), 200); - quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 500); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.z.com"), 3000); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.y.com"), 200); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.x.com"), 500); quota_eviction_handler()->SetPoolSize(4000); quota_eviction_handler()->set_available_space(1000000000); EXPECT_EQ(3000 + 200 + 500, quota_eviction_handler()->GetUsage()); @@ -239,10 +244,10 @@ } TEST_F(QuotaTemporaryStorageEvictorTest, MultipleEvictionTest) { - quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 20); - quota_eviction_handler()->AddOrigin(GURL("http://www.y.com"), 2900); - quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 450); - quota_eviction_handler()->AddOrigin(GURL("http://www.w.com"), 400); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.z.com"), 20); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.y.com"), 2900); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.x.com"), 450); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.w.com"), 400); quota_eviction_handler()->SetPoolSize(4000); quota_eviction_handler()->set_available_space(1000000000); EXPECT_EQ(20 + 2900 + 450 + 400, quota_eviction_handler()->GetUsage()); @@ -266,17 +271,17 @@ const int64_t initial_total_size = a_size + b_size + c_size + d_size; const int64_t e_size = 275; - quota_eviction_handler()->AddOrigin(GURL("http://www.d.com"), d_size); - quota_eviction_handler()->AddOrigin(GURL("http://www.c.com"), c_size); - quota_eviction_handler()->AddOrigin(GURL("http://www.b.com"), b_size); - quota_eviction_handler()->AddOrigin(GURL("http://www.a.com"), a_size); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.d.com"), d_size); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.c.com"), c_size); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.b.com"), b_size); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.a.com"), a_size); quota_eviction_handler()->SetPoolSize(1000); quota_eviction_handler()->set_available_space(1000000000); quota_eviction_handler()->set_task_for_get_usage_and_quota( base::BindRepeating( &QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest, weak_factory_.GetWeakPtr(), - std::make_pair(GURL("http://www.e.com"), e_size), GURL(), + std::make_pair(ToOrigin("http://www.e.com"), e_size), base::nullopt, initial_total_size - d_size, initial_total_size - d_size + e_size - c_size)); EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage()); @@ -300,17 +305,18 @@ const int64_t d_size = 292; const int64_t initial_total_size = a_size + b_size + c_size + d_size; - quota_eviction_handler()->AddOrigin(GURL("http://www.d.com"), d_size); - quota_eviction_handler()->AddOrigin(GURL("http://www.c.com"), c_size); - quota_eviction_handler()->AddOrigin(GURL("http://www.b.com"), b_size); - quota_eviction_handler()->AddOrigin(GURL("http://www.a.com"), a_size); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.d.com"), d_size); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.c.com"), c_size); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.b.com"), b_size); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.a.com"), a_size); quota_eviction_handler()->SetPoolSize(1000); quota_eviction_handler()->set_available_space(1000000000); quota_eviction_handler()->set_task_for_get_usage_and_quota( base::BindRepeating( &QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest, - weak_factory_.GetWeakPtr(), std::make_pair(GURL(), 0), GURL(), - initial_total_size - d_size, initial_total_size - d_size)); + weak_factory_.GetWeakPtr(), std::make_pair(base::nullopt, 0), + base::nullopt, initial_total_size - d_size, + initial_total_size - d_size)); EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage()); // disable_timer_for_testing(); temporary_storage_evictor()->Start(); @@ -333,18 +339,18 @@ const int64_t initial_total_size = a_size + b_size + c_size + d_size; const int64_t e_size = 275; - quota_eviction_handler()->AddOrigin(GURL("http://www.d.com"), d_size); - quota_eviction_handler()->AddOrigin(GURL("http://www.c.com"), c_size); - quota_eviction_handler()->AddOrigin(GURL("http://www.b.com"), b_size); - quota_eviction_handler()->AddOrigin(GURL("http://www.a.com"), a_size); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.d.com"), d_size); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.c.com"), c_size); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.b.com"), b_size); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.a.com"), a_size); quota_eviction_handler()->SetPoolSize(1000); quota_eviction_handler()->set_available_space(1000000000); quota_eviction_handler()->set_task_for_get_usage_and_quota( base::BindRepeating( &QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest, weak_factory_.GetWeakPtr(), - std::make_pair(GURL("http://www.e.com"), e_size), - GURL("http://www.c.com"), initial_total_size - d_size, + std::make_pair(ToOrigin("http://www.e.com"), e_size), + ToOrigin("http://www.c.com"), initial_total_size - d_size, initial_total_size - d_size + e_size - b_size)); EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage()); temporary_storage_evictor()->Start(); @@ -363,8 +369,8 @@ TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceNonEvictionTest) { // If we're using so little that evicting all of it wouldn't // do enough to alleviate a diskspace shortage, we don't evict. - quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 10); - quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 20); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.z.com"), 10); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.x.com"), 20); quota_eviction_handler()->SetPoolSize(10000); quota_eviction_handler()->set_available_space( quota_eviction_handler()->settings().should_remain_available - 350); @@ -382,10 +388,10 @@ } TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceEvictionTest) { - quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 294); - quota_eviction_handler()->AddOrigin(GURL("http://www.y.com"), 120); - quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 150); - quota_eviction_handler()->AddOrigin(GURL("http://www.w.com"), 300); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.z.com"), 294); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.y.com"), 120); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.x.com"), 150); + quota_eviction_handler()->AddOrigin(ToOrigin("http://www.w.com"), 300); quota_eviction_handler()->SetPoolSize(10000); quota_eviction_handler()->set_available_space( quota_eviction_handler()->settings().should_remain_available - 350);
diff --git a/storage/browser/quota/storage_monitor.cc b/storage/browser/quota/storage_monitor.cc index 3a16d1b..7b83851 100644 --- a/storage/browser/quota/storage_monitor.cc +++ b/storage/browser/quota/storage_monitor.cc
@@ -246,7 +246,7 @@ void StorageTypeObservers::AddObserver( StorageObserver* observer, const StorageObserver::MonitorParams& params) { - std::string host = net::GetHostOrSpecFromURL(params.filter.origin); + std::string host = net::GetHostOrSpecFromURL(params.filter.origin.GetURL()); if (host.empty()) return; @@ -284,7 +284,7 @@ void StorageTypeObservers::NotifyUsageChange( const StorageObserver::Filter& filter, int64_t delta) { - std::string host = net::GetHostOrSpecFromURL(filter.origin); + std::string host = net::GetHostOrSpecFromURL(filter.origin.GetURL()); auto it = host_observers_map_.find(host); if (it == host_observers_map_.end()) return; @@ -308,8 +308,7 @@ // Check preconditions. if (params.filter.storage_type == blink::mojom::StorageType::kUnknown || params.filter.storage_type == - blink::mojom::StorageType::kQuotaNotManaged || - params.filter.origin.is_empty()) { + blink::mojom::StorageType::kQuotaNotManaged) { NOTREACHED(); return; } @@ -340,8 +339,7 @@ int64_t delta) { // Check preconditions. if (filter.storage_type == blink::mojom::StorageType::kUnknown || - filter.storage_type == blink::mojom::StorageType::kQuotaNotManaged || - filter.origin.is_empty()) { + filter.storage_type == blink::mojom::StorageType::kQuotaNotManaged) { NOTREACHED(); return; }
diff --git a/storage/browser/quota/storage_monitor.h b/storage/browser/quota/storage_monitor.h index c17b249..fbf1c0d 100644 --- a/storage/browser/quota/storage_monitor.h +++ b/storage/browser/quota/storage_monitor.h
@@ -16,6 +16,7 @@ #include "base/timer/timer.h" #include "storage/browser/quota/storage_observer.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" +#include "url/origin.h" namespace content { class StorageMonitorTestBase; @@ -53,7 +54,7 @@ private: struct STORAGE_EXPORT ObserverState { - GURL origin; + url::Origin origin; base::TimeTicks last_notification_time; base::TimeDelta rate; bool requires_update;
diff --git a/storage/browser/quota/storage_monitor_unittest.cc b/storage/browser/quota/storage_monitor_unittest.cc index e633d22..ce306e5 100644 --- a/storage/browser/quota/storage_monitor_unittest.cc +++ b/storage/browser/quota/storage_monitor_unittest.cc
@@ -37,8 +37,11 @@ namespace { -const char kDefaultOrigin[] = "http://www.foo.com/"; -const char kAlternativeOrigin[] = "http://www.bar.com/"; +// TODO(crbug.com/889590): Use helper for url::Origin creation from string. +const url::Origin kDefaultOrigin = + url::Origin::Create(GURL("http://www.foo.com/")); +const url::Origin kAlternativeOrigin = + url::Origin::Create(GURL("http://www.bar.com/")); class MockObserver : public StorageObserver { public: @@ -86,7 +89,7 @@ .Run(callback_status_, callback_usage_, callback_quota_); } - void GetUsageAndQuotaForWebApps(const GURL& origin, + void GetUsageAndQuotaForWebApps(const url::Origin& origin, StorageType type, UsageAndQuotaCallback callback) override { if (initialized_) @@ -186,7 +189,7 @@ // Test dispatching events to one observer. TEST_F(StorageObserverListTest, DispatchEventToSingleObserver) { StorageObserver::MonitorParams params(StorageType::kPersistent, - GURL(kDefaultOrigin), + kDefaultOrigin, base::TimeDelta::FromHours(1), false); MockObserver mock_observer; StorageObserverList observer_list; @@ -237,8 +240,7 @@ MockObserver mock_observer1; MockObserver mock_observer2; StorageObserverList observer_list; - StorageObserver::Filter filter(StorageType::kPersistent, - GURL(kDefaultOrigin)); + StorageObserver::Filter filter(StorageType::kPersistent, kDefaultOrigin); observer_list.AddObserver( &mock_observer1, StorageObserver::MonitorParams( @@ -290,7 +292,7 @@ // observer on registration. TEST_F(StorageObserverListTest, ReplaceEventOrigin) { StorageObserver::MonitorParams params(StorageType::kPersistent, - GURL(kDefaultOrigin), + kDefaultOrigin, base::TimeDelta::FromHours(1), false); MockObserver mock_observer; StorageObserverList observer_list; @@ -298,7 +300,8 @@ StorageObserver::Event dispatched_event; dispatched_event.filter = params.filter; - dispatched_event.filter.origin = GURL("https://www.foo.com/bar"); + dispatched_event.filter.origin = + url::Origin::Create(GURL("https://www.foo.com/bar")); observer_list.OnStorageChange(dispatched_event); EXPECT_EQ(params.filter.origin, mock_observer.LastEvent().filter.origin); @@ -311,7 +314,7 @@ // Verify that HostStorageObservers is initialized after the first usage change. TEST_F(HostStorageObserversTest, InitializeOnUsageChange) { StorageObserver::MonitorParams params(StorageType::kPersistent, - GURL(kDefaultOrigin), + kDefaultOrigin, base::TimeDelta::FromHours(1), false); const int64_t kUsage = 324554; const int64_t kQuota = 234354354; @@ -349,7 +352,7 @@ // |host_observers| should not be initialized after the first observer is // added because it did not elect to receive the initial state. StorageObserver::MonitorParams params(StorageType::kPersistent, - GURL(kDefaultOrigin), + kDefaultOrigin, base::TimeDelta::FromHours(1), false); MockObserver mock_observer1; host_observers.AddObserver(&mock_observer1, params); @@ -395,7 +398,7 @@ // Verify that negative usage and quota is changed to zero. TEST_F(HostStorageObserversTest, NegativeUsageAndQuota) { StorageObserver::MonitorParams params(StorageType::kPersistent, - GURL(kDefaultOrigin), + kDefaultOrigin, base::TimeDelta::FromHours(1), false); const int64_t kUsage = -324554; const int64_t kQuota = -234354354; @@ -413,7 +416,7 @@ // Verify that HostStorageObservers can recover from a bad initialization. TEST_F(HostStorageObserversTest, RecoverFromBadUsageInit) { StorageObserver::MonitorParams params(StorageType::kPersistent, - GURL(kDefaultOrigin), + kDefaultOrigin, base::TimeDelta::FromHours(1), false); MockObserver mock_observer; HostStorageObservers host_observers(quota_manager_.get()); @@ -446,7 +449,7 @@ // and quota correctly. TEST_F(HostStorageObserversTest, AsyncInitialization) { StorageObserver::MonitorParams params(StorageType::kPersistent, - GURL(kDefaultOrigin), + kDefaultOrigin, base::TimeDelta::FromHours(1), false); MockObserver mock_observer; HostStorageObservers host_observers(quota_manager_.get()); @@ -491,13 +494,13 @@ StorageTypeObservers type_observers(quota_manager_.get()); StorageObserver::MonitorParams params1(StorageType::kPersistent, - GURL(kDefaultOrigin), + kDefaultOrigin, base::TimeDelta::FromHours(1), false); StorageObserver::MonitorParams params2(StorageType::kPersistent, - GURL(kAlternativeOrigin), + kAlternativeOrigin, base::TimeDelta::FromHours(1), false); - std::string host1 = net::GetHostOrSpecFromURL(params1.filter.origin); - std::string host2 = net::GetHostOrSpecFromURL(params2.filter.origin); + std::string host1 = net::GetHostOrSpecFromURL(params1.filter.origin.GetURL()); + std::string host2 = net::GetHostOrSpecFromURL(params2.filter.origin.GetURL()); MockObserver mock_observer1; MockObserver mock_observer2; @@ -537,11 +540,11 @@ StorageMonitorTest() : storage_monitor_(nullptr), params1_(StorageType::kTemporary, - GURL(kDefaultOrigin), + kDefaultOrigin, base::TimeDelta::FromHours(1), false), params2_(StorageType::kPersistent, - GURL(kDefaultOrigin), + kDefaultOrigin, base::TimeDelta::FromHours(1), false) {} @@ -550,7 +553,7 @@ StorageTestWithManagerBase::SetUp(); storage_monitor_ = quota_manager_->storage_monitor_.get(); - host_ = net::GetHostOrSpecFromURL(params1_.filter.origin); + host_ = net::GetHostOrSpecFromURL(params1_.filter.origin.GetURL()); storage_monitor_->AddObserver(&mock_observer1_, params1_); storage_monitor_->AddObserver(&mock_observer2_, params1_); @@ -658,16 +661,13 @@ const int64_t kTestUsage = 234743; // Register the observer. - StorageObserver::MonitorParams params(kTestStorageType, - GURL(kDefaultOrigin), - base::TimeDelta::FromHours(1), - false); + StorageObserver::MonitorParams params(kTestStorageType, kDefaultOrigin, + base::TimeDelta::FromHours(1), false); MockObserver mock_observer; quota_manager_->AddStorageObserver(&mock_observer, params); // Fire a usage change. - client_->AddOriginAndNotify(url::Origin::Create(GURL(kDefaultOrigin)), - kTestStorageType, kTestUsage); + client_->AddOriginAndNotify(kDefaultOrigin, kTestStorageType, kTestUsage); scoped_task_environment_.RunUntilIdle(); // Verify that the observer receives it.
diff --git a/storage/browser/quota/storage_observer.cc b/storage/browser/quota/storage_observer.cc index b582a629..37aece7 100644 --- a/storage/browser/quota/storage_observer.cc +++ b/storage/browser/quota/storage_observer.cc
@@ -14,7 +14,7 @@ : storage_type(blink::mojom::StorageType::kUnknown) {} StorageObserver::Filter::Filter(blink::mojom::StorageType storage_type, - const GURL& origin) + const url::Origin& origin) : storage_type(storage_type), origin(origin) {} bool StorageObserver::Filter::operator==(const Filter& other) const { @@ -30,7 +30,7 @@ StorageObserver::MonitorParams::MonitorParams( blink::mojom::StorageType storage_type, - const GURL& origin, + const url::Origin& origin, const base::TimeDelta& rate, bool get_initial_state) : filter(storage_type, origin),
diff --git a/storage/browser/quota/storage_observer.h b/storage/browser/quota/storage_observer.h index e47ed09..68292e2 100644 --- a/storage/browser/quota/storage_observer.h +++ b/storage/browser/quota/storage_observer.h
@@ -10,7 +10,7 @@ #include "base/time/time.h" #include "storage/browser/quota/quota_client.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -#include "url/gurl.h" +#include "url/origin.h" namespace storage { @@ -24,10 +24,10 @@ blink::mojom::StorageType storage_type; // The origin to monitor usage for. Must be specified. - GURL origin; + url::Origin origin; Filter(); - Filter(blink::mojom::StorageType storage_type, const GURL& origin); + Filter(blink::mojom::StorageType storage_type, const url::Origin& origin); bool operator==(const Filter& other) const; }; @@ -45,7 +45,7 @@ MonitorParams(); MonitorParams(blink::mojom::StorageType storage_type, - const GURL& origin, + const url::Origin& origin, const base::TimeDelta& rate, bool get_initial_state); MonitorParams(const Filter& filter,
diff --git a/storage/browser/quota/usage_tracker.cc b/storage/browser/quota/usage_tracker.cc index bac0940..6362317 100644 --- a/storage/browser/quota/usage_tracker.cc +++ b/storage/browser/quota/usage_tracker.cc
@@ -142,7 +142,7 @@ } void UsageTracker::UpdateUsageCache(QuotaClient::ID client_id, - const GURL& origin, + const url::Origin& origin, int64_t delta) { ClientUsageTracker* client_tracker = GetClientTracker(client_id); DCHECK(client_tracker); @@ -165,14 +165,14 @@ } void UsageTracker::GetCachedOriginsUsage( - std::map<GURL, int64_t>* origin_usage) const { + std::map<url::Origin, int64_t>* origin_usage) const { DCHECK(origin_usage); origin_usage->clear(); for (const auto& client_id_and_tracker : client_tracker_map_) client_id_and_tracker.second->GetCachedOriginsUsage(origin_usage); } -void UsageTracker::GetCachedOrigins(std::set<GURL>* origins) const { +void UsageTracker::GetCachedOrigins(std::set<url::Origin>* origins) const { DCHECK(origins); origins->clear(); for (const auto& client_id_and_tracker : client_tracker_map_) @@ -180,7 +180,7 @@ } void UsageTracker::SetUsageCacheEnabled(QuotaClient::ID client_id, - const GURL& origin, + const url::Origin& origin, bool enabled) { ClientUsageTracker* client_tracker = GetClientTracker(client_id); DCHECK(client_tracker);
diff --git a/storage/browser/quota/usage_tracker.h b/storage/browser/quota/usage_tracker.h index e7f81a784..d03bffd 100644 --- a/storage/browser/quota/usage_tracker.h +++ b/storage/browser/quota/usage_tracker.h
@@ -21,7 +21,7 @@ #include "storage/browser/quota/special_storage_policy.h" #include "storage/browser/storage_browser_export.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -#include "url/gurl.h" +#include "url/origin.h" namespace storage { @@ -48,19 +48,20 @@ void GetHostUsageWithBreakdown(const std::string& host, UsageWithBreakdownCallback callback); void UpdateUsageCache(QuotaClient::ID client_id, - const GURL& origin, + const url::Origin& origin, int64_t delta); int64_t GetCachedUsage() const; void GetCachedHostsUsage(std::map<std::string, int64_t>* host_usage) const; - void GetCachedOriginsUsage(std::map<GURL, int64_t>* origin_usage) const; - void GetCachedOrigins(std::set<GURL>* origins) const; + void GetCachedOriginsUsage( + std::map<url::Origin, int64_t>* origin_usage) const; + void GetCachedOrigins(std::set<url::Origin>* origins) const; bool IsWorking() const { return global_usage_callbacks_.HasCallbacks() || host_usage_callbacks_.HasAnyCallbacks(); } void SetUsageCacheEnabled(QuotaClient::ID client_id, - const GURL& origin, + const url::Origin& origin, bool enabled); private:
diff --git a/storage/browser/quota/usage_tracker_unittest.cc b/storage/browser/quota/usage_tracker_unittest.cc index 48ea323..ace109a 100644 --- a/storage/browser/quota/usage_tracker_unittest.cc +++ b/storage/browser/quota/usage_tracker_unittest.cc
@@ -71,7 +71,7 @@ StorageType type, GetUsageCallback callback) override { EXPECT_EQ(StorageType::kTemporary, type); - int64_t usage = GetUsage(origin.GetURL()); + int64_t usage = GetUsage(origin); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), usage)); } @@ -81,7 +81,7 @@ EXPECT_EQ(StorageType::kTemporary, type); std::set<url::Origin> origins; for (const auto& origin_usage_pair : origin_usage_map_) - origins.insert(url::Origin::Create(origin_usage_pair.first)); + origins.insert(origin_usage_pair.first); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), origins)); } @@ -92,8 +92,8 @@ EXPECT_EQ(StorageType::kTemporary, type); std::set<url::Origin> origins; for (const auto& origin_usage_pair : origin_usage_map_) { - if (net::GetHostOrSpecFromURL(origin_usage_pair.first) == host) - origins.insert(url::Origin::Create(origin_usage_pair.first)); + if (net::GetHostOrSpecFromURL(origin_usage_pair.first.GetURL()) == host) + origins.insert(origin_usage_pair.first); } base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), origins)); @@ -103,7 +103,7 @@ StorageType type, DeletionCallback callback) override { EXPECT_EQ(StorageType::kTemporary, type); - origin_usage_map_.erase(origin.GetURL()); + origin_usage_map_.erase(origin); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), QuotaStatusCode::kOk)); } @@ -112,23 +112,23 @@ return type == StorageType::kTemporary; } - int64_t GetUsage(const GURL& origin) { + int64_t GetUsage(const url::Origin& origin) { auto found = origin_usage_map_.find(origin); if (found == origin_usage_map_.end()) return 0; return found->second; } - void SetUsage(const GURL& origin, int64_t usage) { + void SetUsage(const url::Origin& origin, int64_t usage) { origin_usage_map_[origin] = usage; } - int64_t UpdateUsage(const GURL& origin, int64_t delta) { + int64_t UpdateUsage(const url::Origin& origin, int64_t delta) { return origin_usage_map_[origin] += delta; } private: - std::map<GURL, int64_t> origin_usage_map_; + std::map<url::Origin, int64_t> origin_usage_map_; DISALLOW_COPY_AND_ASSIGN(MockQuotaClient); }; @@ -148,13 +148,14 @@ return &usage_tracker_; } - void UpdateUsage(const GURL& origin, int64_t delta) { + void UpdateUsage(const url::Origin& origin, int64_t delta) { quota_client_.UpdateUsage(origin, delta); usage_tracker_.UpdateUsageCache(quota_client_.id(), origin, delta); base::RunLoop().RunUntilIdle(); } - void UpdateUsageWithoutNotification(const GURL& origin, int64_t delta) { + void UpdateUsageWithoutNotification(const url::Origin& origin, + int64_t delta) { quota_client_.UpdateUsage(origin, delta); } @@ -198,23 +199,23 @@ EXPECT_TRUE(done); } - void GrantUnlimitedStoragePolicy(const GURL& origin) { - if (!storage_policy_->IsStorageUnlimited(origin)) { - storage_policy_->AddUnlimited(origin); - storage_policy_->NotifyGranted( - origin, SpecialStoragePolicy::STORAGE_UNLIMITED); + void GrantUnlimitedStoragePolicy(const url::Origin& origin) { + if (!storage_policy_->IsStorageUnlimited(origin.GetURL())) { + storage_policy_->AddUnlimited(origin.GetURL()); + storage_policy_->NotifyGranted(origin.GetURL(), + SpecialStoragePolicy::STORAGE_UNLIMITED); } } - void RevokeUnlimitedStoragePolicy(const GURL& origin) { - if (storage_policy_->IsStorageUnlimited(origin)) { - storage_policy_->RemoveUnlimited(origin); - storage_policy_->NotifyRevoked( - origin, SpecialStoragePolicy::STORAGE_UNLIMITED); + void RevokeUnlimitedStoragePolicy(const url::Origin& origin) { + if (storage_policy_->IsStorageUnlimited(origin.GetURL())) { + storage_policy_->RemoveUnlimited(origin.GetURL()); + storage_policy_->NotifyRevoked(origin.GetURL(), + SpecialStoragePolicy::STORAGE_UNLIMITED); } } - void SetUsageCacheEnabled(const GURL& origin, bool enabled) { + void SetUsageCacheEnabled(const url::Origin& origin, bool enabled) { usage_tracker_.SetUsageCacheEnabled( quota_client_.id(), origin, enabled); } @@ -245,8 +246,9 @@ EXPECT_EQ(0, usage); EXPECT_EQ(0, unlimited_usage); - const GURL origin("http://example.com"); - const std::string host(net::GetHostOrSpecFromURL(origin)); + // TODO(crbug.com/889590): Use helper for url::Origin creation from string. + const url::Origin origin = url::Origin::Create(GURL("http://example.com")); + const std::string host(net::GetHostOrSpecFromURL(origin.GetURL())); UpdateUsage(origin, 100); GetGlobalUsage(&usage, &unlimited_usage); @@ -284,8 +286,8 @@ base::flat_map<QuotaClient::ID, int64_t> host_usage_breakdown; base::flat_map<QuotaClient::ID, int64_t> host_usage_breakdown_expected; - const GURL origin("http://example.com"); - const std::string host(net::GetHostOrSpecFromURL(origin)); + const url::Origin origin = url::Origin::Create(GURL("http://example.com")); + const std::string host(net::GetHostOrSpecFromURL(origin.GetURL())); UpdateUsage(origin, 100); GetGlobalUsage(&usage, &unlimited_usage); @@ -343,10 +345,11 @@ } TEST_F(UsageTrackerTest, LimitedGlobalUsageTest) { - const GURL kNormal("http://normal"); - const GURL kUnlimited("http://unlimited"); - const GURL kNonCached("http://non_cached"); - const GURL kNonCachedUnlimited("http://non_cached-unlimited"); + const url::Origin kNormal = url::Origin::Create(GURL("http://normal")); + const url::Origin kUnlimited = url::Origin::Create(GURL("http://unlimited")); + const url::Origin kNonCached = url::Origin::Create(GURL("http://non_cached")); + const url::Origin kNonCachedUnlimited = + url::Origin::Create(GURL("http://non_cached-unlimited")); GrantUnlimitedStoragePolicy(kUnlimited); GrantUnlimitedStoragePolicy(kNonCachedUnlimited);
diff --git a/storage/browser/test/async_file_test_helper.cc b/storage/browser/test/async_file_test_helper.cc index a741d833..540547b 100644 --- a/storage/browser/test/async_file_test_helper.cc +++ b/storage/browser/test/async_file_test_helper.cc
@@ -258,7 +258,7 @@ blink::mojom::QuotaStatusCode AsyncFileTestHelper::GetUsageAndQuota( storage::QuotaManager* quota_manager, - const GURL& origin, + const url::Origin& origin, storage::FileSystemType type, int64_t* usage, int64_t* quota) {
diff --git a/storage/browser/test/async_file_test_helper.h b/storage/browser/test/async_file_test_helper.h index fcdc0856..711fffd 100644 --- a/storage/browser/test/async_file_test_helper.h +++ b/storage/browser/test/async_file_test_helper.h
@@ -12,14 +12,16 @@ #include "storage/common/fileapi/file_system_types.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -class GURL; - namespace storage { class FileSystemContext; class FileSystemURL; class QuotaManager; } +namespace url { +class Origin; +} + namespace content { // A helper class to perform async file operations in a synchronous way. @@ -103,7 +105,7 @@ // |quota|. static blink::mojom::QuotaStatusCode GetUsageAndQuota( storage::QuotaManager* quota_manager, - const GURL& origin, + const url::Origin& origin, storage::FileSystemType type, int64_t* usage, int64_t* quota);
diff --git a/storage/browser/test/mock_quota_manager.cc b/storage/browser/test/mock_quota_manager.cc index 419cd85..276ef66 100644 --- a/storage/browser/test/mock_quota_manager.cc +++ b/storage/browser/test/mock_quota_manager.cc
@@ -15,16 +15,14 @@ namespace content { -MockQuotaManager::OriginInfo::OriginInfo( - const GURL& origin, - StorageType type, - int quota_client_mask, - base::Time modified) +MockQuotaManager::OriginInfo::OriginInfo(const url::Origin& origin, + StorageType type, + int quota_client_mask, + base::Time modified) : origin(origin), type(type), quota_client_mask(quota_client_mask), - modified(modified) { -} + modified(modified) {} MockQuotaManager::OriginInfo::~OriginInfo() = default; @@ -44,7 +42,7 @@ storage::GetQuotaSettingsFunc()), weak_factory_(this) {} -void MockQuotaManager::GetUsageAndQuota(const GURL& origin, +void MockQuotaManager::GetUsageAndQuota(const url::Origin& origin, StorageType type, UsageAndQuotaCallback callback) { StorageInfo& info = usage_and_quota_map_[std::make_pair(origin, type)]; @@ -52,25 +50,23 @@ info.quota); } -void MockQuotaManager::SetQuota(const GURL& origin, +void MockQuotaManager::SetQuota(const url::Origin& origin, StorageType type, int64_t quota) { usage_and_quota_map_[std::make_pair(origin, type)].quota = quota; } -bool MockQuotaManager::AddOrigin( - const GURL& origin, - StorageType type, - int quota_client_mask, - base::Time modified) { +bool MockQuotaManager::AddOrigin(const url::Origin& origin, + StorageType type, + int quota_client_mask, + base::Time modified) { origins_.push_back(OriginInfo(origin, type, quota_client_mask, modified)); return true; } -bool MockQuotaManager::OriginHasData( - const GURL& origin, - StorageType type, - QuotaClient::ID quota_client) const { +bool MockQuotaManager::OriginHasData(const url::Origin& origin, + StorageType type, + QuotaClient::ID quota_client) const { for (std::vector<OriginInfo>::const_iterator current = origins_.begin(); current != origins_.end(); ++current) { @@ -85,7 +81,7 @@ void MockQuotaManager::GetOriginsModifiedSince(StorageType type, base::Time modified_since, GetOriginsCallback callback) { - std::set<GURL>* origins_to_return = new std::set<GURL>(); + std::set<url::Origin>* origins_to_return = new std::set<url::Origin>(); for (std::vector<OriginInfo>::const_iterator current = origins_.begin(); current != origins_.end(); ++current) { @@ -99,7 +95,7 @@ base::Owned(origins_to_return), type)); } -void MockQuotaManager::DeleteOriginData(const GURL& origin, +void MockQuotaManager::DeleteOriginData(const url::Origin& origin, StorageType type, int quota_client_mask, StatusCallback callback) { @@ -123,14 +119,14 @@ MockQuotaManager::~MockQuotaManager() = default; -void MockQuotaManager::UpdateUsage(const GURL& origin, +void MockQuotaManager::UpdateUsage(const url::Origin& origin, StorageType type, int64_t delta) { usage_and_quota_map_[std::make_pair(origin, type)].usage += delta; } void MockQuotaManager::DidGetModifiedSince(GetOriginsCallback callback, - std::set<GURL>* origins, + std::set<url::Origin>* origins, StorageType storage_type) { std::move(callback).Run(*origins, storage_type); }
diff --git a/storage/browser/test/mock_quota_manager.h b/storage/browser/test/mock_quota_manager.h index 96a19c1..129cb5d 100644 --- a/storage/browser/test/mock_quota_manager.h +++ b/storage/browser/test/mock_quota_manager.h
@@ -18,7 +18,7 @@ #include "storage/browser/quota/quota_manager.h" #include "storage/browser/quota/quota_task.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -#include "url/gurl.h" +#include "url/origin.h" using blink::mojom::StorageType; using storage::GetOriginsCallback; @@ -52,7 +52,7 @@ // updated when MockQuotaManagerProxy::NotifyStorageModified() is // called. The internal quota value can be updated by calling // a helper method MockQuotaManagerProxy::SetQuota(). - void GetUsageAndQuota(const GURL& origin, + void GetUsageAndQuota(const url::Origin& origin, StorageType type, UsageAndQuotaCallback callback) override; @@ -69,20 +69,20 @@ // origin as a bitmask built from QuotaClient::IDs. Setting the mask to // QuotaClient::kAllClientsMask will remove all clients from the origin, // regardless of type. - void DeleteOriginData(const GURL& origin, + void DeleteOriginData(const url::Origin& origin, StorageType type, int quota_client_mask, StatusCallback callback) override; // Helper method for updating internal quota info. - void SetQuota(const GURL& origin, StorageType type, int64_t quota); + void SetQuota(const url::Origin& origin, StorageType type, int64_t quota); // Helper methods for timed-deletion testing: // Adds an origin to the canned list that will be searched through via // GetOriginsModifiedSince. The caller must provide |quota_client_mask| // which specifies the types of QuotaClients this canned origin contains // as a bitmask built from QuotaClient::IDs. - bool AddOrigin(const GURL& origin, + bool AddOrigin(const url::Origin& origin, StorageType type, int quota_client_mask, base::Time modified); @@ -91,7 +91,7 @@ // Checks an origin and type against the origins that have been added via // AddOrigin and removed via DeleteOriginData. If the origin exists in the // canned list with the proper StorageType and client, returns true. - bool OriginHasData(const GURL& origin, + bool OriginHasData(const url::Origin& origin, StorageType type, QuotaClient::ID quota_client) const; @@ -105,13 +105,13 @@ // MockQuotaManager needs to understand for time-based deletion: // the origin itself, the StorageType and its modification time. struct OriginInfo { - OriginInfo(const GURL& origin, + OriginInfo(const url::Origin& origin, StorageType type, int quota_client_mask, base::Time modified); ~OriginInfo(); - GURL origin; + url::Origin origin; StorageType type; int quota_client_mask; base::Time modified; @@ -128,13 +128,13 @@ int64_t quota; }; - typedef std::pair<GURL, StorageType> OriginAndType; + typedef std::pair<url::Origin, StorageType> OriginAndType; typedef std::map<OriginAndType, StorageInfo> UsageAndQuotaMap; // This must be called via MockQuotaManagerProxy. - void UpdateUsage(const GURL& origin, StorageType type, int64_t delta); + void UpdateUsage(const url::Origin& origin, StorageType type, int64_t delta); void DidGetModifiedSince(GetOriginsCallback callback, - std::set<GURL>* origins, + std::set<url::Origin>* origins, StorageType storage_type); void DidDeleteOriginData(StatusCallback callback, blink::mojom::QuotaStatusCode status);
diff --git a/storage/browser/test/mock_quota_manager_proxy.cc b/storage/browser/test/mock_quota_manager_proxy.cc index 048b2afd..b521e3c 100644 --- a/storage/browser/test/mock_quota_manager_proxy.cc +++ b/storage/browser/test/mock_quota_manager_proxy.cc
@@ -38,8 +38,7 @@ blink::mojom::StorageType type, QuotaManager::UsageAndQuotaCallback callback) { if (mock_manager()) { - mock_manager()->GetUsageAndQuota(origin.GetURL(), type, - std::move(callback)); + mock_manager()->GetUsageAndQuota(origin, type, std::move(callback)); } } @@ -62,7 +61,7 @@ last_notified_type_ = type; last_notified_delta_ = delta; if (mock_manager()) - mock_manager()->UpdateUsage(origin.GetURL(), type, delta); + mock_manager()->UpdateUsage(origin, type, delta); } MockQuotaManagerProxy::~MockQuotaManagerProxy() {
diff --git a/storage/browser/test/mock_quota_manager_unittest.cc b/storage/browser/test/mock_quota_manager_unittest.cc index 4ffb207..d1e4d37c 100644 --- a/storage/browser/test/mock_quota_manager_unittest.cc +++ b/storage/browser/test/mock_quota_manager_unittest.cc
@@ -26,9 +26,10 @@ const char kTestOrigin2[] = "http://host2:1/"; const char kTestOrigin3[] = "http://host3:1/"; -const GURL kOrigin1(kTestOrigin1); -const GURL kOrigin2(kTestOrigin2); -const GURL kOrigin3(kTestOrigin3); +// TODO(crbug.com/889590): Use helper for url::Origin creation from string. +const url::Origin kOrigin1 = url::Origin::Create(GURL(kTestOrigin1)); +const url::Origin kOrigin2 = url::Origin::Create(GURL(kTestOrigin2)); +const url::Origin kOrigin3 = url::Origin::Create(GURL(kTestOrigin3)); const StorageType kTemporary = StorageType::kTemporary; const StorageType kPersistent = StorageType::kPersistent; @@ -64,13 +65,15 @@ weak_factory_.GetWeakPtr())); } - void GotModifiedOrigins(const std::set<GURL>& origins, StorageType type) { + void GotModifiedOrigins(const std::set<url::Origin>& origins, + StorageType type) { origins_ = origins; type_ = type; } - void DeleteOriginData(const GURL& origin, StorageType type, - int quota_client_mask) { + void DeleteOriginData(const url::Origin& origin, + StorageType type, + int quota_client_mask) { manager_->DeleteOriginData( origin, type, quota_client_mask, base::BindOnce(&MockQuotaManagerTest::DeletedOriginData, @@ -90,9 +93,7 @@ return manager_.get(); } - const std::set<GURL>& origins() const { - return origins_; - } + const std::set<url::Origin>& origins() const { return origins_; } const StorageType& type() const { return type_; @@ -106,7 +107,7 @@ int deletion_callback_count_; - std::set<GURL> origins_; + std::set<url::Origin> origins_; StorageType type_; base::WeakPtrFactory<MockQuotaManagerTest> weak_factory_;
diff --git a/storage/browser/test/mock_storage_client.cc b/storage/browser/test/mock_storage_client.cc index 38e06a9..287042c0 100644 --- a/storage/browser/test/mock_storage_client.cc +++ b/storage/browser/test/mock_storage_client.cc
@@ -34,6 +34,7 @@ const MockOriginData* mock_data, size_t mock_data_size) { for (size_t i = 0; i < mock_data_size; ++i) { + // TODO(crbug.com/889590): Use helper for url::Origin creation from string. origin_data_[make_pair(url::Origin::Create(GURL(mock_data[i].origin)), mock_data[i].type)] = mock_data[i].usage; } @@ -48,7 +49,7 @@ DCHECK_GE(size, 0); origin_data_[make_pair(origin, type)] = size; quota_manager_proxy_->quota_manager()->NotifyStorageModifiedInternal( - id(), origin.GetURL(), type, size, IncrementMockTime()); + id(), origin, type, size, IncrementMockTime()); } void MockStorageClient::ModifyOriginAndNotify(const url::Origin& origin, @@ -61,7 +62,7 @@ // TODO(tzik): Check quota to prevent usage exceed quota_manager_proxy_->quota_manager()->NotifyStorageModifiedInternal( - id(), origin.GetURL(), type, delta, IncrementMockTime()); + id(), origin, type, delta, IncrementMockTime()); } void MockStorageClient::TouchAllOriginsAndNotify() { @@ -69,8 +70,7 @@ itr != origin_data_.end(); ++itr) { quota_manager_proxy_->quota_manager()->NotifyStorageModifiedInternal( - id(), itr->first.first.GetURL(), itr->first.second, 0, - IncrementMockTime()); + id(), itr->first.first, itr->first.second, 0, IncrementMockTime()); } }
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index 8246f58..e0913e9 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -10011,6 +10011,11 @@ } ] }, + "ToTAndroidOfficial": { + "additional_compile_targets": [ + "all" + ] + }, "ToTLinux": { "gtest_tests": [ {
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 642a9683..cf41416 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -12563,23 +12563,14 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "shards": 4 }, - "test": "angle_end2end_tests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "angle_end2end_tests" }, { "args": [ @@ -12589,22 +12580,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "angle_gles1_conformance_tests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "angle_gles1_conformance_tests" }, { "args": [ @@ -12614,22 +12596,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "angle_white_box_tests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "angle_white_box_tests" }, { "args": [ @@ -12645,22 +12618,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "browser_tests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "browser_tests" }, { "args": [ @@ -12672,22 +12636,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "gl_tests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "gl_tests" }, { "args": [ @@ -12697,22 +12652,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "gles2_conform_test", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "gles2_conform_test" }, { "args": [ @@ -12724,22 +12670,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "gles2_conform_test", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "gles2_conform_test" }, { "args": [ @@ -12752,66 +12689,39 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "gles2_conform_test", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "gles2_conform_test" }, { "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "gpu_unittests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "gpu_unittests" }, { "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "swiftshader_unittests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "swiftshader_unittests" }, { "args": [ @@ -12824,22 +12734,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "video_decode_accelerator_unittest", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "video_decode_accelerator_unittest" } ], "isolated_scripts": [ @@ -12862,21 +12763,12 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -12896,22 +12788,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false, "shards": 20 - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -12929,22 +12812,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false, "shards": 2 - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -12962,22 +12836,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false, "shards": 2 - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -12995,22 +12860,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false, "shards": 2 - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -13028,22 +12884,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false, "shards": 2 - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } } ] @@ -15044,23 +14891,14 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "shards": 4 }, - "test": "angle_end2end_tests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "angle_end2end_tests" }, { "args": [ @@ -15070,22 +14908,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "angle_gles1_conformance_tests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "angle_gles1_conformance_tests" }, { "args": [ @@ -15096,22 +14925,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "angle_unittests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "angle_unittests" }, { "args": [ @@ -15121,22 +14941,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "angle_white_box_tests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "angle_white_box_tests" }, { "args": [ @@ -15150,22 +14961,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "browser_tests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "browser_tests" }, { "args": [ @@ -15181,22 +14983,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "browser_tests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "browser_tests" }, { "args": [ @@ -15207,22 +15000,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "gl_tests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "gl_tests" }, { "args": [ @@ -15234,22 +15018,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "gl_tests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "gl_tests" }, { "args": [ @@ -15259,22 +15034,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "gl_unittests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "gl_unittests" }, { "args": [ @@ -15284,22 +15050,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "gles2_conform_test", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "gles2_conform_test" }, { "args": [ @@ -15311,22 +15068,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "gles2_conform_test", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "gles2_conform_test" }, { "args": [ @@ -15339,66 +15087,39 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "gles2_conform_test", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "gles2_conform_test" }, { "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "gpu_unittests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "gpu_unittests" }, { "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "swiftshader_unittests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "swiftshader_unittests" }, { "args": [ @@ -15411,22 +15132,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "video_decode_accelerator_unittest", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "video_decode_accelerator_unittest" }, { "args": [ @@ -15439,22 +15151,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ] }, - "test": "video_decode_accelerator_unittest", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "video_decode_accelerator_unittest" } ], "isolated_scripts": [ @@ -15473,21 +15176,12 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15505,21 +15199,12 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15537,21 +15222,12 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15569,21 +15245,12 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15605,21 +15272,12 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15644,21 +15302,12 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15691,21 +15340,12 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15724,21 +15364,12 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15756,21 +15387,12 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15790,22 +15412,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false, "shards": 20 - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15825,22 +15438,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false, "shards": 20 - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15860,22 +15464,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false, "shards": 20 - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15893,22 +15488,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false, "shards": 2 - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15926,22 +15512,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false, "shards": 2 - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15959,22 +15536,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false, "shards": 2 - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -15992,22 +15560,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false, "shards": 2 - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } }, { @@ -16025,22 +15584,13 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "idempotent": false, "shards": 2 - }, - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" } } ] @@ -17180,23 +16730,14 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:5912-23.20.16.4877", + "gpu": "8086:5912-23.20.100.6286", "os": "Windows-10", "pool": "Chrome-GPU" } ], "shards": 4 }, - "test": "angle_deqp_gles2_tests", - "trigger_script": { - "args": [ - "--multiple-trigger-configs", - "[{\"gpu\": \"8086:5912-23.20.16.4877\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}, {\"gpu\": \"8086:5912-24.20.100.6286\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]", - "--multiple-dimension-script-verbose", - "True" - ], - "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" - } + "test": "angle_deqp_gles2_tests" } ] },
diff --git a/testing/buildbot/filters/mojo.fyi.chromeos.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.chromeos.network_browser_tests.filter index 65dd820..92beb72 100644 --- a/testing/buildbot/filters/mojo.fyi.chromeos.network_browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.chromeos.network_browser_tests.filter
@@ -9,18 +9,13 @@ # Uncategorized timeouts or test failures. -AffiliationCheck/EnterpriseDeviceAttributesTest.Success/Affiliated -AffiliationCheck/EnterpriseDeviceAttributesTest.Success/NotAffiliated --ArcRobotAccountAuthServiceTest.GetOfflineDemoAccount --ArcSessionManagerTest.ConsumerAccount --ArcSessionManagerTest.ManagedAndroidAccount --ArcSessionManagerTest.ManagedChromeAccount --ArcSessionManagerTest.WellKnownConsumerAccount +-BackgroundFetchBrowserTest.FetchCanBePausedAndResumed -CheckSystemTokenAvailability/EnterprisePlatformKeysTest.Basic/0 -CheckSystemTokenAvailability/EnterprisePlatformKeysTest.Basic/1 -CheckSystemTokenAvailability/EnterprisePlatformKeysTest.Basic/2 -CheckSystemTokenAvailability/EnterprisePlatformKeysTest.Basic/3 -ChromeNewWindowClientBrowserTest.NewWindowForActiveWindowProfileTest -ChromeSessionManagerTest.OobeNewUser --DeclarativeContentApiTest.RemoveAllRulesAfterExtensionUninstall -DeviceIDTest.LegacyUsers -DeviceIDTest.Migration -DeviceIDTest.NewUsers @@ -31,19 +26,6 @@ -HostedAppNonClientFrameViewAshTest.FocusableViews/material_refresh -HostedAppNonClientFrameViewAshTest.FocusableViews/material_refresh_touch_optimized -HostedAppNonClientFrameViewAshTest.FocusableViews/material_touch_optimized --KeyboardEndToEndFocusTest.TriggerAsyncInputFocusFromUserGestureAfterBlurShowsKeyboard --KeyboardEndToEndFocusTest.TriggerAsyncInputFocusFromUserGestureAfterBlurTimeoutDoesNotShowKeyboard --KeyboardEndToEndFocusTest.TriggerAsyncInputFocusFromUserGestureDoesNotShowKeyboard --KeyboardEndToEndFocusTest.TriggerInputFocusFromUserGestureShowsKeyboard --KeyboardEndToEndFocusTest.TriggerInputFocusWithoutUserGestureDoesNotShowKeyboard --KeyboardEndToEndFormTest.ChangeInputModeToNoneHidesKeyboard --KeyboardEndToEndFormTest.ChangeInputModeToNumericDoesNotHideKeyboard --KeyboardEndToEndFormTest.ChangeInputToReadOnlyHidesKeyboard --KeyboardEndToEndFormTest.ChangeInputTypeToNonTextHidesKeyboard --KeyboardEndToEndFormTest.ChangeInputTypeToTextDoesNotHideKeyboard --KeyboardEndToEndFormTest.ClickBodyHidesKeyboard --KeyboardEndToEndFormTest.ClickTextFieldShowsKeyboard --KeyboardEndToEndFormTest.DeleteInputHidesKeyboard -KioskUpdateTest.LaunchCachedOfflineEnabledAppNoNetwork -LoginPolicyTestBase.AllowedInputMethods -LoginPolicyTestBase.AllowedUILocales @@ -53,8 +35,6 @@ -OAuth2Test.TerminateOnBadMergeSessionAfterOnlineAuth -OAuth2Test.VerifyInAdvancedProtectionAfterOnlineAuth -OAuth2Test.VerifyNotInAdvancedProtectionAfterOnlineAuth --OutOfProcessPPAPITest.UDPSocket_DropReceiverPipeOnReceiveMore --OutOfProcessPPAPITest.UDPSocket_ReadError -PolicyProvidedTrustAnchorsOnUserSessionInitTest.TrustAnchorsAvailableImmediatelyAfterSessionStart -PolicyProvidedTrustAnchorsRegularUserTest.AllowedForRegularUser -SAMLPolicyTest.NoSAML @@ -68,7 +48,6 @@ -SamlTest.ScrapedNone -SamlTest.ScrapedSingle -SamlTest.UseAutenticatedUserEmailAddress --ServiceWorkerTestWithNativeBindings/ServiceWorkerTest.EventsToStoppedWorker/0 -SigninProfileAppsPolicyPerChannelTest.ExtensionInstallation/0 -SigninProfileAppsPolicyPerChannelTest.ExtensionInstallation/1 -SigninProfileAppsPolicyPerChannelTest.ExtensionInstallation/2 @@ -110,16 +89,6 @@ -WizardControllerDeviceStateExplicitRequirement/WizardControllerDeviceStateExplicitRequirementTest.ControlFlowForcedReEnrollment/1 -WizardControllerDeviceStateTest.ControlFlowDeviceDisabled -WizardControllerDeviceStateWithInitialEnrollmentTest.ControlFlowInitialEnrollment --ZipFiles/FilesAppBrowserTest.Test/zipCreateFileDownloads --ZipFiles/FilesAppBrowserTest.Test/zipCreateFileDownloads_GuestMode --ZipFiles/FilesAppBrowserTest.Test/zipCreateFileDrive --ZipFiles/FilesAppBrowserTest.Test/zipCreateFileDrive_DriveFs --ZipFiles/FilesAppBrowserTest.Test/zipCreateFileUsb --ZipFiles/FilesAppBrowserTest.Test/zipFileOpenDownloads --ZipFiles/FilesAppBrowserTest.Test/zipFileOpenDownloads_GuestMode --ZipFiles/FilesAppBrowserTest.Test/zipFileOpenDrive --ZipFiles/FilesAppBrowserTest.Test/zipFileOpenDrive_DriveFs --ZipFiles/FilesAppBrowserTest.Test/zipFileOpenUsb # NetworkChangeNotifier() Not implemented. # https://crbug.com/882610 @@ -150,6 +119,9 @@ # Flaky with error: `Check failed: (sequence_checker_).CalledOnValidSequence()`. -DevToolsSanityTest.DisposeEmptyBrowserContext +# Flaky with error: `picture_in_picture_window_controller_impl.cc(167)] Check failed: media_player_id_.has_value()`. +-PictureInPictureWindowControllerBrowserTest.TabIconUpdated + # NOTE: if adding an exclusion for an existing failure (e.g. additional test for # feature X that is already not working), please add it beside the existing # failures. Otherwise please reach out to network-service-dev@.
diff --git a/testing/buildbot/filters/webui_polymer2_browser_tests.filter b/testing/buildbot/filters/webui_polymer2_browser_tests.filter index 37338943..c959b96 100644 --- a/testing/buildbot/filters/webui_polymer2_browser_tests.filter +++ b/testing/buildbot/filters/webui_polymer2_browser_tests.filter
@@ -140,7 +140,6 @@ CrSettingsDevicePageTest.DevicePageTest CrSettingsDevicePageTest.PointersTest CrSettingsDevicePageTest.StylusTest -CrSettingsDisplaySizeSliderTest.* CrSettingsDownloadsPageTest.* CrSettingsDropdownMenuTest.* CrSettingsEditDictionaryPageTest.*
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index e805d246..93eccdae 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -767,6 +767,11 @@ 'gtest_tests': 'chromium_android_gtests', }, }, + 'ToTAndroidOfficial': { + 'additional_compile_targets': [ + 'all', + ], + }, 'ToTLinux': { 'test_suites': { 'gtest_tests': 'chromium_linux_gtests', @@ -2623,7 +2628,7 @@ 'dimension_sets': [ { # WIN10_INTEL_HD_630_STABLE_DRIVER - 'gpu': '8086:5912-23.20.16.4877', + 'gpu': '8086:5912-23.20.100.6286', 'os': 'Windows-10', 'pool': 'Chrome-GPU', }, @@ -2633,15 +2638,6 @@ 'gtest_tests': 'gpu_fyi_win_optional_gtests', 'gpu_telemetry_tests': 'gpu_optional_win_telemetry_tests', }, - 'use_multi_dimension_trigger_script': True, - 'alternate_swarming_dimensions': [ - { - # WIN10_INTEL_HD_630_EXPERIMENTAL_DRIVER - 'gpu': '8086:5912-24.20.100.6286', - 'os': 'Windows-10', - 'pool': 'Chrome-GPU', - }, - ], }, 'Optional Win10 Release (NVIDIA)': { 'os_type': 'win', @@ -2732,7 +2728,7 @@ 'dimension_sets': [ { # WIN10_INTEL_HD_630_STABLE_DRIVER - 'gpu': '8086:5912-23.20.16.4877', + 'gpu': '8086:5912-23.20.100.6286', 'os': 'Windows-10', 'pool': 'Chrome-GPU', }, @@ -2742,15 +2738,6 @@ 'gtest_tests': 'gpu_fyi_win_gtests', 'gpu_telemetry_tests': 'gpu_fyi_win_release_telemetry_tests', }, - 'use_multi_dimension_trigger_script': True, - 'alternate_swarming_dimensions': [ - { - # WIN10_INTEL_HD_630_EXPERIMENTAL_DRIVER - 'gpu': '8086:5912-24.20.100.6286', - 'os': 'Windows-10', - 'pool': 'Chrome-GPU', - }, - ], }, 'Win10 FYI Release (NVIDIA)': { 'os_type': 'win', @@ -2779,7 +2766,7 @@ 'dimension_sets': [ { # WIN10_INTEL_HD_630_STABLE_DRIVER - 'gpu': '8086:5912-23.20.16.4877', + 'gpu': '8086:5912-23.20.100.6286', 'os': 'Windows-10', 'pool': 'Chrome-GPU', }, @@ -2788,15 +2775,6 @@ 'test_suites': { 'gtest_tests': 'gpu_angle_deqp_gles2_d3d11_tests', }, - 'use_multi_dimension_trigger_script': True, - 'alternate_swarming_dimensions': [ - { - # WIN10_INTEL_HD_630_EXPERIMENTAL_DRIVER - 'gpu': '8086:5912-24.20.100.6286', - 'os': 'Windows-10', - 'pool': 'Chrome-GPU', - }, - ], }, 'Win10 FYI dEQP Release (NVIDIA)': { 'os_type': 'win',
diff --git a/testing/libfuzzer/gen_fuzzer_owners.py b/testing/libfuzzer/gen_fuzzer_owners.py index c9590a3d..7b8fd2f5 100755 --- a/testing/libfuzzer/gen_fuzzer_owners.py +++ b/testing/libfuzzer/gen_fuzzer_owners.py
@@ -32,6 +32,13 @@ return None +def GetGitCommand(): + """Returns a git command that does not need to be executed using shell=True. + On non-Windows platforms: 'git'. On Windows: 'git.bat'. + """ + return 'git.bat' if sys.platform == 'win32' else 'git' + + def GetOwnersIfThirdParty(source): """Return owners using OWNERS file if in third_party.""" match_index = source.find(THIRD_PARTY_SEARCH_STRING) @@ -72,8 +79,9 @@ # Found the fuzzer source (and not dependency of fuzzer). git_dir = os.path.join(CHROMIUM_SRC_DIR, '.git') + git_command = GetGitCommand() is_git_file = bool(subprocess.check_output( - ['git', '--git-dir', git_dir, 'ls-files', source], + [git_command, '--git-dir', git_dir, 'ls-files', source], cwd=CHROMIUM_SRC_DIR)) if not is_git_file: # File is not in working tree. Return owners for third_party. @@ -84,9 +92,8 @@ # the original author has authored line 1 which is usually the # copyright line and does not change even with file rename / move. blame_output = subprocess.check_output( - ['git', '--git-dir', git_dir, - 'blame', '--porcelain', '-L1,1', source], - cwd=CHROMIUM_SRC_DIR) + [git_command, '--git-dir', git_dir, 'blame', '--porcelain', '-L1,1', + source], cwd=CHROMIUM_SRC_DIR) return GetAuthorFromGitBlame(blame_output) return None
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 3873cd8..7fb72945 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1787,6 +1787,21 @@ ] } ], + "ExtendedShellExtensionsEnumeration": [ + { + "platforms": [ + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "ExtendedShellExtensionsEnumeration" + ] + } + ] + } + ], "ExtensionContentVerification": [ { "platforms": [ @@ -2996,7 +3011,8 @@ "OmniboxNewAnswerLayout", "OmniboxRichEntitySuggestions", "OmniboxTailSuggestions", - "OmniboxUIExperimentHideSteadyStateUrlSchemeAndSubdomains", + "OmniboxUIExperimentHideSteadyStateUrlScheme", + "OmniboxUIExperimentHideSteadyStateUrlTrivialSubdomains", "ZeroSuggestRedirectToChrome", "ZeroSuggestSwapTitleAndUrl" ] @@ -3013,7 +3029,8 @@ "enable_features": [ "OmniboxBreakWordsAtUnderscores", "OmniboxDisplayTitleForCurrentUrl", - "OmniboxUIExperimentHideSteadyStateUrlSchemeAndSubdomains" + "OmniboxUIExperimentHideSteadyStateUrlScheme", + "OmniboxUIExperimentHideSteadyStateUrlTrivialSubdomains" ] } ]
diff --git a/third_party/.gitignore b/third_party/.gitignore index 0575724..fa6da6a 100644 --- a/third_party/.gitignore +++ b/third_party/.gitignore
@@ -211,7 +211,6 @@ /usrsctp/usrsctplib /v8-i18n /valgrind -/vulkan-validation-layers/src /visualmetrics /wayland/src /wayland-protocols/src
diff --git a/third_party/WebKit/LayoutTests/NeverFixTests b/third_party/WebKit/LayoutTests/NeverFixTests index d70ae81..07a21c3 100644 --- a/third_party/WebKit/LayoutTests/NeverFixTests +++ b/third_party/WebKit/LayoutTests/NeverFixTests
@@ -1003,6 +1003,10 @@ external/wpt/speech-api/SpeechRecognition-onerror-manual.https.html [ WontFix ] external/wpt/speech-api/SpeechRecognition-onresult-manual.https.html [ WontFix ] external/wpt/speech-api/SpeechRecognition-stop-manual.https.html [ WontFix ] +virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechRecognition-abort-manual.https.html [ WontFix ] +virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechRecognition-onerror-manual.https.html [ WontFix ] +virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechRecognition-onresult-manual.https.html [ WontFix ] +virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechRecognition-stop-manual.https.html [ WontFix ] external/wpt/uievents/interface/click-event-manual.htm [ WontFix ] external/wpt/uievents/interface/dblclick-event-manual.htm [ WontFix ] external/wpt/uievents/keyboard/key-101en-us-manual.html [ WontFix ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index d98c073..6ab23f222 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1398,7 +1398,6 @@ crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline.html [ Skip ] crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/negative-flex-rounding-assert.html [ Skip ] crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/negative-overflow.html [ Skip ] -crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/nested-flexbox-min-size-auto.html [ Skip ] crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/nested-orthogonal-flexbox-relayout.html [ Skip ] crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/nested-stretch.html [ Skip ] crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/order-painting.html [ Failure ] @@ -1518,6 +1517,7 @@ crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-006.xht [ Skip ] crbug.com/249112 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-007.xht [ Skip ] crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-008.xht [ Skip ] +crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-009.html [ Skip ] crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-width-flex-items-001.xht [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-width-flex-items-002.xht [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-width-flex-items-003.xht [ Failure ] @@ -2830,6 +2830,7 @@ crbug.com/875249 external/wpt/infrastructure/testdriver/bless.html [ Timeout Pass ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/css/css-backgrounds/border-image-width-008.html [ Failure ] crbug.com/626703 external/wpt/content-security-policy/generic/only-valid-whitespaces-are-allowed.html [ Timeout ] crbug.com/626703 virtual/outofblink-cors-ns/external/wpt/referrer-policy/css-integration/svg/internal-stylesheet.html [ Timeout ] crbug.com/367760 external/wpt/svg/pservers/reftests/meshgradient-basic-004.svg [ Failure ] @@ -2860,6 +2861,8 @@ crbug.com/626703 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-tall.html [ Failure ] crbug.com/626703 external/wpt/speech-api/SpeechSynthesis-speak-events.html [ Timeout ] crbug.com/626703 external/wpt/speech-api/SpeechSynthesis-pause-resume.tentative.html [ Timeout ] +crbug.com/626703 virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechSynthesis-pause-resume.tentative.html [ Timeout ] +crbug.com/626703 virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechSynthesis-speak-events.html [ Timeout ] crbug.com/626703 external/wpt/presentation-api/controlling-ua/reconnectToPresentation_notfound_error-manual.https.html [ Skip ] crbug.com/626703 external/wpt/presentation-api/controlling-ua/reconnectToMultiplePresentations_success-manual.https.html [ Skip ] crbug.com/626703 external/wpt/presentation-api/controlling-ua/startMultiplePresentations_success-manual.https.html [ Skip ] @@ -2933,7 +2936,9 @@ crbug.com/626703 external/wpt/payment-request/PaymentValidationErrors/retry-shows-error-member-manual.https.html [ Skip ] crbug.com/626703 external/wpt/payment-request/payment-response/retry-method-manual.https.html [ Skip ] crbug.com/626703 external/wpt/payment-request/payment-response/rejects_if_not_active-manual.https.html [ Skip ] +crbug.com/626703 external/wpt/speech-api/SpeechSynthesis-speak-twice.html [ Timeout ] crbug.com/626703 external/wpt/speech-api/SpeechSynthesis-speak-without-activation-fails.tentative.html [ Timeout ] +crbug.com/626703 virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechSynthesis-speak-twice.html [ Timeout ] crbug.com/366553 external/wpt/svg/text/reftests/text-inline-size-007.svg [ Failure ] crbug.com/366553 external/wpt/svg/text/reftests/text-inline-size-005.svg [ Failure ] crbug.com/366558 external/wpt/svg/text/reftests/text-multiline-002.svg [ Failure ] @@ -3489,7 +3494,6 @@ crbug.com/626703 virtual/outofblink-cors/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] crbug.com/626703 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] crbug.com/648295 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] -crbug.com/626703 external/wpt/speech-api/SpeechSynthesis-speak-twice.html [ Timeout ] crbug.com/626703 external/wpt/svg/linking/reftests/href-filter-element.html [ Failure ] crbug.com/626703 external/wpt/webrtc/RTCPeerConnection-setRemoteDescription.html [ Pass Failure ] crbug.com/626703 virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites index 5a23630..52ca328 100644 --- a/third_party/WebKit/LayoutTests/VirtualTestSuites +++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -623,6 +623,11 @@ "args": ["--enable-blink-features=FractionalMouseEvent"] }, { + "prefix": "speech-with-unified-autoplay", + "base": "external/wpt/speech-api", + "args": ["--autoplay-policy=document-user-activation-required"] + }, + { "prefix": "unified-autoplay", "base": "external/wpt/feature-policy", "args": ["--autoplay-policy=document-user-activation-required"]
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/nested-flexbox-min-size-auto.html b/third_party/WebKit/LayoutTests/css3/flexbox/nested-flexbox-min-size-auto.html deleted file mode 100644 index 1c9297d..0000000 --- a/third_party/WebKit/LayoutTests/css3/flexbox/nested-flexbox-min-size-auto.html +++ /dev/null
@@ -1,41 +0,0 @@ -<!DOCTYPE html> -<link href="resources/flexbox.css" rel="stylesheet"> -<script src="../../resources/testharness.js"></script> -<script src="../../resources/testharnessreport.js"></script> -<script src="../../resources/check-layout-th.js"></script> -<style> -#container { - height: 300px; - outline: 2px solid black; -} - -.inner -{ - width: 400px; - flex: 1; - background-color: green; -} -</style> -<script> -function change() { - var container = document.getElementById('container'); - container.offsetHeight; - container.style.height = '80px'; - checkLayout('#container'); -} -</script> -<body onload="change()"> -<p>Green rectangle should be entirely within the black rectangle</p> -<div id="log"></div> -<div id="container"> - <div class="flexbox column" style="height: 100%;"> - <div class="flexbox flex-one"> - <div class="flexbox column"> - <div class="flexbox column flex-one"> - <div class="inner" data-expected-height="80"> - </div> - </div> - </div> - </div> - </div> -</div>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json index 558b5ad..c4295aa 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
@@ -33215,6 +33215,18 @@ {} ] ], + "css/css-backgrounds/border-image-width-008.html": [ + [ + "/css/css-backgrounds/border-image-width-008.html", + [ + [ + "/css/css-backgrounds/border-image-width-008-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-backgrounds/border-radius-001.xht": [ [ "/css/css-backgrounds/border-radius-001.xht", @@ -36767,6 +36779,18 @@ {} ] ], + "css/css-contain/contain-paint-clip-019.html": [ + [ + "/css/css-contain/contain-paint-clip-019.html", + [ + [ + "/css/css-contain/reference/contain-paint-clip-019-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-contain/contain-paint-ifc-011.html": [ [ "/css/css-contain/contain-paint-ifc-011.html", @@ -118592,6 +118616,11 @@ {} ] ], + "css/css-backgrounds/border-image-width-008-ref.html": [ + [ + {} + ] + ], "css/css-backgrounds/border-radius-001-ref.xht": [ [ {} @@ -119862,6 +119891,11 @@ {} ] ], + "css/css-contain/reference/contain-paint-clip-019-ref.html": [ + [ + {} + ] + ], "css/css-contain/reference/contain-paint-ifc-011-ref.html": [ [ {} @@ -177587,6 +177621,11 @@ {} ] ], + "webrtc/RTCIceTransport-extension-helper.js": [ + [ + {} + ] + ], "webrtc/RTCPeerConnection-addIceCandidate-expected.txt": [ [ {} @@ -196986,6 +197025,12 @@ {} ] ], + "css/css-flexbox/flex-minimum-height-flex-items-009.html": [ + [ + "/css/css-flexbox/flex-minimum-height-flex-items-009.html", + {} + ] + ], "css/css-flexbox/flexbox_first-letter.html": [ [ "/css/css-flexbox/flexbox_first-letter.html", @@ -199592,9 +199637,9 @@ {} ] ], - "css/css-masking/inheritance.html": [ + "css/css-masking/inheritance.sub.html": [ [ - "/css/css-masking/inheritance.html", + "/css/css-masking/inheritance.sub.html", {} ] ], @@ -261298,6 +261343,18 @@ {} ] ], + "speech-api/SpeechSynthesisErrorEvent-constructor.html": [ + [ + "/speech-api/SpeechSynthesisErrorEvent-constructor.html", + {} + ] + ], + "speech-api/SpeechSynthesisEvent-constructor.html": [ + [ + "/speech-api/SpeechSynthesisEvent-constructor.html", + {} + ] + ], "speech-api/SpeechSynthesisUtterance-basics.https.html": [ [ "/speech-api/SpeechSynthesisUtterance-basics.https.html", @@ -312459,6 +312516,14 @@ "61726c00873739c076812f72645d8324494ff44c", "reftest" ], + "css/css-backgrounds/border-image-width-008-ref.html": [ + "9a066443920726b79d69a0301d814b5211b7df0a", + "support" + ], + "css/css-backgrounds/border-image-width-008.html": [ + "3158cdb5717b873065bc70537075234492796501", + "reftest" + ], "css/css-backgrounds/border-images.html": [ "930a1df3b7fda4098f36cc9691a544f46e2311d5", "visual" @@ -315259,6 +315324,10 @@ "17bcccdeff538ea869a51d703acb80e9acc4b0ca", "reftest" ], + "css/css-contain/contain-paint-clip-019.html": [ + "bd761b8a523bd9fa05dd88f57b6b1317b5c4c40b", + "reftest" + ], "css/css-contain/contain-paint-ifc-011.html": [ "b8a03936cbcc3ddcc88dc1237fab0af56f4bd72b", "reftest" @@ -315587,6 +315656,10 @@ "781a6d2f2f4e8810690ab321f7ff7bf3539044f3", "support" ], + "css/css-contain/reference/contain-paint-clip-019-ref.html": [ + "2a529c12c48e630cc7df146fe3e685afd85a42f0", + "support" + ], "css/css-contain/reference/contain-paint-ifc-011-ref.html": [ "229c8c2d74ba3f2b5cede6824091575835807092", "support" @@ -316891,6 +316964,10 @@ "ead7a424b374fddb247046d2a36a37a11669baae", "reftest" ], + "css/css-flexbox/flex-minimum-height-flex-items-009.html": [ + "718386af02069fa1a3fff0ee5aaa10415ef4b23a", + "testharness" + ], "css/css-flexbox/flex-minimum-width-flex-items-001.xht": [ "b8e2866edaa46af46900c287238894cd8ddef24c", "reftest" @@ -331459,8 +331536,8 @@ "c415eaaa67a2bc9a4b621700049eb0c0b60ec0a3", "testharness" ], - "css/css-masking/inheritance.html": [ - "34f75859ee88833ed39a56bb6c443cd60586e1b5", + "css/css-masking/inheritance.sub.html": [ + "95424204d5094bb1cbcd49e32f5e38c28d86d76f", "testharness" ], "css/css-masking/mask-image/mask-image-url-image-hash.html": [ @@ -395376,7 +395453,7 @@ "support" ], "interfaces/speech-api.idl": [ - "8e998df5bc3fa41d728b5c79d592746701bc3754", + "0b5c866b35c28d8e10261205fb6cbaa6962e480a", "support" ], "interfaces/storage.idl": [ @@ -395500,7 +395577,7 @@ "support" ], "intersection-observer/bounding-box.html": [ - "69052b11ce6c40c6a56fe2b723c70c49ddc36dd9", + "50f33f0443bb70e64bec2e2fcc930fa2b4118ed6", "testharness" ], "intersection-observer/client-rect.html": [ @@ -421772,7 +421849,15 @@ "testharness" ], "speech-api/SpeechSynthesis-speak-without-activation-fails.tentative.html": [ - "acf0d7d575b5dc7f9b348d82b056aa90089b6639", + "1b86552a1cbd8dabaf8b50f928823e743e4b46cb", + "testharness" + ], + "speech-api/SpeechSynthesisErrorEvent-constructor.html": [ + "61e179cca47b70d001e5e081e87166ec1363714a", + "testharness" + ], + "speech-api/SpeechSynthesisEvent-constructor.html": [ + "47a37d25d9723cadcb9da2d778481fd9561c37aa", "testharness" ], "speech-api/SpeechSynthesisUtterance-basics.https-expected.txt": [ @@ -421792,7 +421877,7 @@ "testharness" ], "speech-api/idlharness.window-expected.txt": [ - "12eedafdd950022cc0b2dbd638ee108842ddac06", + "e913d754fb7115c56329bbefe1f0d22d09e5c4b4", "support" ], "speech-api/idlharness.window.js": [ @@ -426808,7 +426893,7 @@ "support" ], "webaudio/idlharness.https.window-expected.txt": [ - "ebd89e3f1de980e2c1195db2c22395fca07e0b3f", + "c1e94f9344adda65b09912eb1fe20a9d26386edc", "support" ], "webaudio/idlharness.https.window.js": [ @@ -428539,8 +428624,12 @@ "8fcf2e214bb23a9f5f023c4d69398c918ca8e49d", "support" ], + "webrtc/RTCIceTransport-extension-helper.js": [ + "659ec59b8df2847e7e2a3c513d3d6fd01027f16d", + "support" + ], "webrtc/RTCIceTransport-extension.https.html": [ - "9c6cec7e1e4994ee58f6822d77048eca8e8af569", + "5adee9fbe61eb9a8f7235b7faa6670eaea45cc89", "testharness" ], "webrtc/RTCIceTransport.html": [ @@ -428848,15 +428937,15 @@ "testharness" ], "webrtc/RTCQuicStream.https.html": [ - "1e08016d75af57307d922b9876605e8152f92768", + "33025451b252e1bdf2491fa118e072f4b8711d12", "testharness" ], "webrtc/RTCQuicTransport-helper.js": [ - "50d9e6666a2d3bf8b3128f94b3c902579fabc0f5", + "3ea19d7a78e4a3788e97d0fa537d51d4b9e6b4fc", "support" ], "webrtc/RTCQuicTransport.https.html": [ - "703f424a63851996b3708fe66caff63c7e0f5502", + "ec79bc228ad21de3a9ce3c2ee812a7d50e57571b", "testharness" ], "webrtc/RTCRtpCapabilities-helper.js": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-backgrounds/border-image-width-008-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-backgrounds/border-image-width-008-ref.html new file mode 100644 index 0000000..9a06644 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-backgrounds/border-image-width-008-ref.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>border-image with different widths</title> +<style> + #ref { + width: 360px; + height: 240px; + border-style: solid; + border-width: 40px 40px 20px 0px; + border-image-source: url("support/border.png"); + border-image-slice: 27; + } +</style> +<body> + <div id="ref"></div> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-backgrounds/border-image-width-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-backgrounds/border-image-width-008.html new file mode 100644 index 0000000..3158cdb --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-backgrounds/border-image-width-008.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>border-image-width has the same effect as a border-width and the image is displayed even if border-width is zero</title> +<link rel="match" href="border-image-width-008-ref.html"> +<link rel="help" href="https://drafts.csswg.org/css-backgrounds-3/#propdef-border-image-width"> +<style> + #test { + width: 400px; + height: 300px; + border-style: solid; + /* Note: Chrome does not display an image if border-width is 0 */ + border-width: 0px; + border-image-source: url("support/border.png"); + border-image-width: 40px 40px 20px 0px; + border-image-slice: 27; + } +</style> +<body> + <div id="test"></div> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-clip-019.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-clip-019.html new file mode 100644 index 0000000..bd761b8a5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-clip-019.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> + +<meta charset="UTF-8"> + +<title>CSS Containment Test: 'contain: paint' and clipping prevents scrollbars</title> + +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/css-contain-1/#containment-paint"> +<link rel="match" href="reference/contain-paint-clip-019-ref.html"> + +<meta content="This test checks that the paint containment of an element clips contents. + It should also prevent layout overflow from being propagated to ancestors." name="assert"> +<meta content="" name="flags"> + +<style> + #container { + contain: paint; + width: 100px; + height: 100px; + } + #green { + background-color: green; + width: 100px; + height: 100px; + } + #red { + background-color: red; + width: 100px; + height: 10000px; + } +</style> + +<p>Test passes if there there is a green square. No red and no scrollbars should be visible.</p> + +<div id="container"> + <div id="green"></div> + <div id="red"></div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-paint-clip-019-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-paint-clip-019-ref.html new file mode 100644 index 0000000..2a529c1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-paint-clip-019-ref.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> + +<meta charset="UTF-8"> + +<title>CSS Reference Test</title> + +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> + +<style> + #green { + background-color: green; + width: 100px; + height: 100px; + } +</style> + +<p>Test passes if there there is a green square. No red and no scrollbars should be visible.</p> + +<div id="green"></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-009.html new file mode 100644 index 0000000..718386a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-009.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<title>Tests correct handling of min-height: auto with dynamic changes</title> +<link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#min-size-auto" title="4.5. Implied Minimum Size of Flex Items" /> +<link rel="author" title="Google Inc." href="http://www.google.com/"> +<link href="support/flexbox.css" rel="stylesheet"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> +<style> +.container { + height: 300px; + outline: 2px solid black; +} + +.inner +{ + width: 400px; + flex: 1; + background-color: green; +} +#container2 .flexbox > * { flex-basis: 0; } +#container2 .column > * { flex-basis: auto; } +</style> +<script> +function change() { + var container = document.getElementById('container'); + container.offsetHeight; + container.style.height = '80px'; + container = document.getElementById('container2'); + container.offsetHeight; + container.style.height = '80px'; + checkLayout('.container'); +} +</script> +<body onload="change()"> +<p>Green rectangle should be entirely within the black rectangle</p> +<div id="log"></div> +<div id="container" class="container"> + <div class="flexbox column" style="height: 100%;"> + <div class="flexbox flex-one"> + <div class="flexbox column"> + <div class="flexbox column flex-one"> + <div class="inner" data-expected-height="80"> + </div> + </div> + </div> + </div> + </div> +</div> + +<div id="container2" class="container"> + <div class="flexbox column" style="height: 100%;"> + <div class="flexbox flex-one"> + <div class="flexbox column"> + <div class="flexbox column flex-one"> + <div class="inner" data-expected-height="80"> + </div> + </div> + </div> + </div> + </div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/inheritance.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/inheritance.sub.html similarity index 86% rename from third_party/WebKit/LayoutTests/external/wpt/css/css-masking/inheritance.html rename to third_party/WebKit/LayoutTests/external/wpt/css/css-masking/inheritance.sub.html index 34f7585..9542420 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/inheritance.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/inheritance.sub.html
@@ -16,17 +16,17 @@ </div> <script> assert_not_inherited('clip', 'auto', 'rect(10px, 20px, 30px, 40px)'); -assert_not_inherited('clip-path', 'none', 'url("https://example.com/")'); +assert_not_inherited('clip-path', 'none', 'url("http://{{host}}/")'); assert_inherited('clip-rule', 'nonzero', 'evenodd'); assert_not_inherited('mask-border-mode', 'alpha', 'luminance'); assert_not_inherited('mask-border-outset', '0', '10px 20px 30px 40px'); assert_not_inherited('mask-border-repeat', 'stretch', 'round space'); assert_not_inherited('mask-border-slice', '0', '1 2 3 4 fill'); -assert_not_inherited('mask-border-source', 'none', 'url("https://example.com/")'); +assert_not_inherited('mask-border-source', 'none', 'url("http://{{host}}/")'); assert_not_inherited('mask-border-width', 'auto', '10px 20px 30px 40px'); assert_not_inherited('mask-clip', 'border-box', 'no-clip'); assert_not_inherited('mask-composite', 'add', 'exclude'); -assert_not_inherited('mask-image', 'none', 'url("https://example.com/")'); +assert_not_inherited('mask-image', 'none', 'url("http://{{host}}/")'); assert_not_inherited('mask-mode', 'match-source', 'luminance'); assert_not_inherited('mask-origin', 'border-box', 'padding-box'); assert_not_inherited('mask-position', '0% 0%', '10px 20px');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/bounding-box.html b/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/bounding-box.html index 69052b1..50f33f04 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/bounding-box.html +++ b/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/bounding-box.html
@@ -13,7 +13,7 @@ overflow: visible; height: 200px; width: 160px; - border: 7px solid black; + border: 8px solid black; } #target { margin: 10px; @@ -50,12 +50,35 @@ var targetBounds = clientBounds(target); target.style.transform = "translateY(195px)"; runTestCycle(step1, "target.style.transform = 'translateY(195px)'"); - checkLastEntry(entries, 0, targetBounds.concat(0, 0, 0, 0, 8, 182, 8, 222, false)); + checkLastEntry(entries, 0, targetBounds.concat(0, 0, 0, 0, 8, 184, 8, 224, false)); } function step1() { var targetBounds = clientBounds(target); - target.style.transform = ""; - checkLastEntry(entries, 1, targetBounds.concat(25, 145, 220, 222, 8, 182, 8, 222, true)); + target.style.transform = "translateY(300px)"; + runTestCycle(step2, "target.style.transform = 'translateY(300px)'"); + checkLastEntry(entries, 1, targetBounds.concat(26, 146, 221, 224, 8, 184, 8, 224, true)); } + +function step2() { + var targetBounds = clientBounds(target); + target.style.transform = ""; + target.style.zoom = "2"; + runTestCycle(step3, "target.style.zoom = 2"); + checkLastEntry(entries, 2, targetBounds.concat(0, 0, 0, 0, 8, 184, 8, 224, false)); +} + +function step3() { + var targetBounds = clientBounds(target); + var intersectionWidth = ( + 176 // root width including border + -8 // root left border + -20 // target left margin * target zoom + ) / 2; // convert to target's zoom factor. + var intersectionHeight = (216 - 8 - 20) / 2; + var intersectionRect = [targetBounds[0], targetBounds[0] + intersectionWidth, + targetBounds[2], targetBounds[2] + intersectionHeight]; + checkLastEntry(entries, 3, targetBounds.concat(intersectionRect).concat(8, 184, 8, 224, true)); +} + </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https-expected.txt index 10b1fd1..28a5b78 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https-expected.txt
@@ -11,6 +11,7 @@ PASS SW-fallbacked redirect to same-origin other-scope. PASS SW-fallbacked redirect to other-origin out-scope. PASS SW-fallbacked redirect to other-origin in-scope. +PASS SW-fallbacked redirect to other-origin and back to same-origin. PASS SW-generated redirect to same-origin out-scope. FAIL SW-generated redirect to same-origin out-scope with a hash fragment. assert_object_equals: Intercepted URLs should match. property "0" expected ["https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F#ref"] got ["https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F"] FAIL SW-generated redirect to same-origin out-scope with different hash fragments. assert_object_equals: Intercepted URLs should match. property "0" expected ["https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F%23ref2#ref"] got ["https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F%23ref2"]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https.html index b6281b9..6f03fd8 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https.html
@@ -1,6 +1,11 @@ <!DOCTYPE html> <title>Service Worker: Navigation redirection</title> <meta name="timeout" content="long"> +<!-- empty variant tests document.location and intercepted URLs --> +<meta name="variant" content=""> +<!-- client variant tests the Clients API (resultingClientId and Client.url) --> +<meta name="variant" content="?client"> + <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/common/get-host-info.sub.js"></script> @@ -76,36 +81,208 @@ assert_object_equals(urls, expected_urls, 'Intercepted URLs should match.'); } +// Checks |clients| returned from a worker. Only the client matching +// |expected_final_client_tag| should be found. Returns true if a client was +// found. Note that the final client is not necessarily found by this worker, +// if the client is cross-origin. +// +// |clients| is an object like: +// {x: {found: true, id: id1, url: url1}, b: {found: false}} +function check_clients(clients, + expected_id, + expected_url, + expected_final_client_tag, + worker_name) { + let found = false; + Object.keys(clients).forEach(key => { + const info = clients[key]; + if (info.found) { + assert_true(expected_final_client_tag, + `${worker_name} client tag exists`); + assert_equals(key, expected_final_client_tag, + `${worker_name} client tag matches`); + assert_equals(info.id, expected_id, `${worker_name} client id`); + assert_equals(info.url, expected_url, `${worker_name} client url`); + found = true; + } + }); + return found; +} + +function check_resulting_client_ids(infos, expected_infos, actual_ids, worker) { + assert_equals(infos.length, expected_infos.length, + `request length for ${worker}`); + for (var i = 0; i < infos.length; i++) { + const tag = expected_infos[i].resultingClientIdTag; + const url = expected_infos[i].url; + const actual_id = infos[i].resultingClientId; + const expected_id = actual_ids[tag]; + assert_equals(typeof(actual_id), 'string', + `resultingClientId for ${url} request to ${worker}`); + if (expected_id) { + assert_equals(requestInfos[0], expected_id, + `resultingClientId for ${url} request to ${worker}`); + } else { + actual_ids[key] = actual_id; + } + } +} + // Creates an iframe and navigates to |url|, which is expected to start a chain // of redirects. // - |expected_last_url| is the expected window.location after the // navigation. +// // - |expected_request_infos| is the expected requests that the service workers // were dispatched fetch events for. The format is: // [ -// [{url: url1}, {url: url2}], // requests from workers[0], -// [{url: url1}, // requests from workers[1], -// [{url: url1}, {url: url2}] // requests from cross-origin worker +// [ +// // Requests received by workers[0]. +// {url: url1, resultingClientIdTag: 'a'}, +// {url: url2, resultingClientIdTag: 'a'} +// ], +// [ +// // Requests received by workers[1]. +// {url: url3, resultingClientIdTag: 'a'} +// ], +// [ +// // Requests received by the cross-origin worker. +// {url: url4, resultingClientIdTag: 'x'} +// {url: url5, resultingClientIdTag: 'x'} +// ] // ] +// Here, |url| is |event.request.url| and |resultingClientIdTag| represents +// |event.resultingClientId|. Since the actual client ids are not known +// beforehand, the expectation isn't the literal expected value, but all equal +// tags must map to the same actual id. +// +// - |expected_final_client_tag| is the resultingClientIdTag that is +// expected to map to the created client's id. This is null if there +// is no such tag, which can happen when the final request was a cross-origin +// redirect to out-scope, so no worker received a fetch event whose +// resultingClientId is the id of the resulting client. +// +// In the example above: +// - workers[0] receives two requests with the same resultingClientId. +// - workers[1] receives one request also with that resultingClientId. +// - The cross-origin worker receives two requests with the same +// resultingClientId which differs from the previous one. +// - Assuming |expected_final_client_tag| is 'x', then the created +// client has the id seen by the cross-origin worker above. function redirect_test(url, expected_last_url, expected_request_infos, + expected_final_client_tag, test_name) { promise_test(async t => { const frame = await with_iframe(url); t.add_cleanup(() => { frame.remove(); }); - const expected_intercepted_urls = expected_request_infos.map(requests => { - return requests.map(info => { - return info.url; - }); - }); - await check_all_intercepted_urls(expected_intercepted_urls); - const last_url = await send_to_iframe(frame, 'getLocation'); - assert_equals(last_url, expected_last_url, 'Last URL should match.'); + // Switch on variant. + if (document.location.search == '?client') { + return client_variant_test(url, expected_last_url, expected_request_infos, + expected_final_client_tag, test_name); + } + + return default_variant_test(url, expected_last_url, expected_request_infos, + frame, test_name); }, test_name); } +// The default variant tests the request interception chain and +// resulting document.location. +async function default_variant_test(url, + expected_last_url, + expected_request_infos, + frame, + test_name) { + const expected_intercepted_urls = expected_request_infos.map( + requests_for_worker => { + return requests_for_worker.map(info => { + return info.url; + }); + }); + await check_all_intercepted_urls(expected_intercepted_urls); + const last_url = await send_to_iframe(frame, 'getLocation'); + assert_equals(last_url, expected_last_url, 'Last URL should match.'); +} + +// The "client" variant tests the Clients API using resultingClientId. +async function client_variant_test(url, + expected_last_url, + expected_request_infos, + expected_final_client_tag, + test_name) { + // Request infos is an array like: + // [ + // [{url: url1, resultingClientIdTag: tag1}], + // [{url: url2, resultingClientIdTag: tag2}], + // [{url: url3: resultingClientIdTag: tag3}] + // ] + const requestInfos = await get_all_request_infos(); + + // We check the actual infos against the expected ones, and learn the + // actual ids as we go. + const actual_ids = {}; + check_resulting_client_ids(requestInfos[0], + expected_request_infos[0], + actual_ids, + 'worker0'); + check_resulting_client_ids(requestInfos[1], + expected_request_infos[1], + actual_ids, + 'worker1'); + check_resulting_client_ids(requestInfos[2], + expected_request_infos[2], + actual_ids, + 'crossOriginWorker'); + + // Now |actual_ids| maps tag to actual id: + // {x: id1, b: id2, c: id3} + // Ask each worker to try to resolve the actual ids to clients. + // Only |expected_final_client_tag| should resolve to a client. + const client_infos = await get_all_clients(actual_ids); + + // Client infos is an object like: + // { + // worker0: {x: {found: true, id: id1, url: url1}, b: {found: false}}, + // worker1: {x: {found: true, id: id1, url: url1}}, + // crossOriginWorker: {x: {found: false}}, {b: {found: false}} + // } + // + // Now check each client info. check_clients() verifies each info: only + // |expected_final_client_tag| should ever be found and the found client + // should have the expected url and id. A wrinkle is that not all workers + // will find the client, if they are cross-origin to the client. This + // means check_clients() trivially passes if no clients are found. So + // additionally check that at least one worker found the client (|found|), + // if that was expected (|expect_found|). + let found = false; + const expect_found = !!expected_final_client_tag; + const expected_id = actual_ids[expected_final_client_tag]; + found = check_clients(client_infos.worker0, + expected_id, + expected_last_url, + expected_final_client_tag, + 'worker0'); + found = check_clients(client_infos.worker1, + expected_id, + expected_last_url, + expected_final_client_tag, + 'worker1') || found; + found = check_clients(client_infos.crossOriginWorker, + expected_id, + expected_last_url, + expected_final_client_tag, + 'crossOriginWorker') || found; + assert_equals(found, expect_found, 'client found'); + + if (!expect_found) { + // TODO(falken): Ask the other origin frame if it has a client of the + // expected URL. + } +} + window.addEventListener('message', on_message, false); function on_message(e) { @@ -129,6 +306,27 @@ }); } +async function get_all_clients(actual_ids) { + const client_infos = {}; + client_infos['worker0'] = await get_clients(workers[0], actual_ids); + client_infos['worker1'] = await get_clients(workers[1], actual_ids); + client_infos['crossOriginWorker'] = + await send_to_iframe(other_origin_frame, + {command: 'get_clients', actual_ids}); + return client_infos; +} + +function get_clients(worker, actual_ids) { + return new Promise(resolve => { + var channel = new MessageChannel(); + channel.port1.onmessage = (msg) => { + resolve(msg.data.clients); + }; + worker.postMessage({command: 'getClients', actual_ids, port: channel.port2}, + [channel.port2]); + }); +} + // Returns an array of the URLs that |worker| received fetch events for: // [url1, url2] async function get_intercepted_urls(worker) { @@ -138,7 +336,10 @@ // Returns the requests that |worker| received fetch events for. The return // value is an array of format: -// [{url: url1}, {url: url2}] +// [ +// {url: url1, resultingClientId: id}, +// {url: url2, resultingClientId: id} +// ] function get_request_infos(worker) { return new Promise(resolve => { var channel = new MessageChannel(); @@ -150,6 +351,29 @@ }); } +// Returns an array of the requests the workers received fetch events for: +// [ +// // Requests from workers[0]. +// [ +// {url: url1, resultingClientIdTag: tag1}, +// {url: url2, resultingClientIdTag: tag1} +// ], +// +// // Requests from workers[1]. +// [{url: url3, resultingClientIdTag: tag2}], +// +// // Requests from the cross-origin worker. +// [] +// ] +async function get_all_request_infos() { + const request_infos = []; + request_infos.push(await get_request_infos(workers[0])); + request_infos.push(await get_request_infos(workers[1])); + request_infos.push(await send_to_iframe(other_origin_frame, + {command: 'get_request_infos'})); + return request_infos; +} + let url; let url1; let url2; @@ -159,7 +383,8 @@ redirect_test( OUT_SCOPE + 'url=' + encodeURIComponent(url), url, - [[{url}], [], []], + [[{url, resultingClientIdTag: 'x'}], [], []], + 'x', 'Normal redirect to same-origin scope.'); @@ -167,30 +392,33 @@ redirect_test( OUT_SCOPE + 'url=' + encodeURIComponent(SCOPE1) + '#ref', url, - [[{url}], [], []], + [[{url, resultingClientIdTag: 'x'}], [], []], + 'x', 'Normal redirect to same-origin scope with a hash fragment.'); url = SCOPE1 + '#ref2'; redirect_test( OUT_SCOPE + 'url=' + encodeURIComponent(url) + '#ref', url, - [[{url}], [], []], + [[{url, resultingClientIdTag: 'x'}], [], []], + 'x', 'Normal redirect to same-origin scope with different hash fragments.'); url = OTHER_ORIGIN_SCOPE; redirect_test( OUT_SCOPE + 'url=' + encodeURIComponent(url), url, - [[], [], [{url}]], + [[], [], [{url, resultingClientIdTag: 'x'}]], + 'x', 'Normal redirect to other-origin scope.'); - // SW fallbacked redirect. SW doesn't handle the fetch request. url = SCOPE1 + 'url=' + encodeURIComponent(OUT_SCOPE); redirect_test( url, OUT_SCOPE, - [[{url}], [], []], + [[{url, resultingClientIdTag: 'x'}], [], []], + 'x', 'SW-fallbacked redirect to same-origin out-scope.'); url1 = SCOPE1 + 'url=' + encodeURIComponent(SCOPE1); @@ -198,7 +426,15 @@ redirect_test( url1, url2, - [[{url: url1}, {url: url2}], [], []], + [ + [ + {url: url1, resultingClientIdTag: 'x'}, + {url: url2, resultingClientIdTag: 'x'} + ], + [], + [] + ], + 'x', 'SW-fallbacked redirect to same-origin same-scope.'); url1 = SCOPE1 + 'url=' + encodeURIComponent(SCOPE1) + '#ref'; @@ -206,7 +442,15 @@ redirect_test( url1, url2, - [[{url: url1}, {url: url2}], [], []], + [ + [ + {url: url1, resultingClientIdTag: 'x'}, + {url: url2, resultingClientIdTag: 'x'} + ], + [], + [] + ], + 'x', 'SW-fallbacked redirect to same-origin same-scope with a hash fragment.'); url1 = SCOPE1 + 'url=' + encodeURIComponent(SCOPE1 + '#ref2') + '#ref'; @@ -214,7 +458,15 @@ redirect_test( url1, url2, - [[{url: url1}, {url: url2}], [], []], + [ + [ + {url: url1, resultingClientIdTag: 'x'}, + {url: url2, resultingClientIdTag: 'x'} + ], + [], + [] + ], + 'x', 'SW-fallbacked redirect to same-origin same-scope with different hash ' + 'fragments.'); @@ -223,7 +475,12 @@ redirect_test( url1, url2, - [[{url: url1}], [{url: url2}], []], + [ + [{url: url1, resultingClientIdTag: 'x'}], + [{url: url2, resultingClientIdTag: 'x'}], + [] + ], + 'x', 'SW-fallbacked redirect to same-origin other-scope.'); url1 = SCOPE1 + 'url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE); @@ -231,7 +488,8 @@ redirect_test( url1, url2, - [[{url: url1}], [], []], + [[{url: url1, resultingClientIdTag: 'a'}], [], []], + 'x', 'SW-fallbacked redirect to other-origin out-scope.'); url1 = SCOPE1 + 'url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE); @@ -239,10 +497,32 @@ redirect_test( url1, url2, - [[{url: url1}], [], [{url: url2}]], + [ + [{url: url1, resultingClientIdTag: 'a'}], + [], + [{url: url2, resultingClientIdTag: 'x'}] + ], + 'x', 'SW-fallbacked redirect to other-origin in-scope.'); +url3 = SCOPE1; +url2 = OTHER_ORIGIN_SCOPE + 'url=' + encodeURIComponent(url3); +url1 = SCOPE1 + 'url=' + encodeURIComponent(url2); +redirect_test( + url1, + url3, + [ + [ + {url: url1, resultingClientIdTag: 'a'}, + {url: url3, resultingClientIdTag: 'x'} + ], + [], + [{url: url2, resultingClientIdTag: 'b'}] + ], + 'x', + 'SW-fallbacked redirect to other-origin and back to same-origin.'); + // SW generated redirect. // SW: event.respondWith(Response.redirect(params['url'])); url1 = SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE); @@ -250,7 +530,8 @@ redirect_test( url1, url2, - [[{url: url1}], [], []], + [[{url: url1, resultingClientIdTag: 'a'}], [], []], + null, 'SW-generated redirect to same-origin out-scope.'); url1 = SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE) + '#ref'; @@ -258,7 +539,8 @@ redirect_test( url1, url2, - [[{url: url1}], [], []], + [[{url: url1, resultingClientIdTag: 'x'}], [], []], + 'x', 'SW-generated redirect to same-origin out-scope with a hash fragment.'); url1 = SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE + '#ref2') + '#ref'; @@ -266,7 +548,8 @@ redirect_test( url1, url2, - [[{url: url1}], [], []], + [[{url: url1, resultingClientIdTag: 'x'}], [], []], + 'x', 'SW-generated redirect to same-origin out-scope with different hash ' + 'fragments.'); @@ -275,7 +558,15 @@ redirect_test( url1, url2, - [[{url: url1}, {url: url2}], [], []], + [ + [ + {url: url1, resultingClientIdTag: 'x'}, + {url: url2, resultingClientIdTag: 'x'} + ], + [], + [] + ], + 'x', 'SW-generated redirect to same-origin same-scope.'); url1 = SCOPE1 + 'sw=gen&url=' + encodeURIComponent(SCOPE2); @@ -283,7 +574,12 @@ redirect_test( url1, url2, - [[{url: url1}], [{url: url2}], []], + [ + [{url: url1, resultingClientIdTag: 'x'}], + [{url: url2, resultingClientIdTag: 'x'}], + [] + ], + 'x', 'SW-generated redirect to same-origin other-scope.'); url1 = SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE); @@ -291,7 +587,8 @@ redirect_test( url1, url2, - [[{url: url1}], [], []], + [[{url: url1, resultingClientIdTag: 'a'}], [], []], + null, 'SW-generated redirect to other-origin out-scope.'); url1 = SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE); @@ -300,10 +597,11 @@ url1, url2, [ - [{url: url1}], + [{url: url1, resultingClientIdTag: 'a'}], [], - [{url: url2}] + [{url: url2, resultingClientIdTag: 'x'}] ], + 'x', 'SW-generated redirect to other-origin in-scope.'); @@ -314,7 +612,8 @@ redirect_test( url1, url2, - [[{url: url1}], [], []], + [[{url: url1, resultingClientIdTag: 'x'}], [], []], + 'x', 'SW-fetched redirect to same-origin out-scope.'); url1 = SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(SCOPE1); @@ -322,7 +621,15 @@ redirect_test( url1, url2, - [[{url: url1}, {url: url2}], [], []], + [ + [ + {url: url1, resultingClientIdTag: 'x'}, + {url: url2, resultingClientIdTag: 'x'} + ], + [], + [] + ], + 'x', 'SW-fetched redirect to same-origin same-scope.'); url1 = SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(SCOPE2); @@ -331,10 +638,11 @@ url1, url2, [ - [{url: url1}], - [{url: url2}], + [{url: url1, resultingClientIdTag: 'x'}], + [{url: url2, resultingClientIdTag: 'x'}], [] ], + 'x', 'SW-fetched redirect to same-origin other-scope.'); url1 = SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE); @@ -342,7 +650,8 @@ redirect_test( url1, url2, - [[{url: url1}], [], []], + [[{url: url1, resultingClientIdTag: 'a'}], [], []], + null, 'SW-fetched redirect to other-origin out-scope.'); url1 = SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE); @@ -351,10 +660,11 @@ url1, url2, [ - [{url: url1}], + [{url: url1, resultingClientIdTag: 'a'}], [], - [{url: url2}] + [{url: url2, resultingClientIdTag: 'x'}] ], + 'x', 'SW-fetched redirect to other-origin in-scope.'); @@ -366,7 +676,8 @@ redirect_test( url1, url2, - [[{url: url1}], [], []], + [[{url: url1, resultingClientIdTag: 'x'}], [], []], + 'x', 'Redirect to same-origin out-scope with opaque redirect response.'); url1 = SCOPE1 + 'sw=manual&url=' + encodeURIComponent(SCOPE1); @@ -374,7 +685,15 @@ redirect_test( url1, url2, - [[{url: url1}, {url: url2}], [], []], + [ + [ + {url: url1, resultingClientIdTag: 'x'}, + {url: url2, resultingClientIdTag: 'x'} + ], + [], + [] + ], + 'x', 'Redirect to same-origin same-scope with opaque redirect response.'); url1 = SCOPE1 + 'sw=manual&url=' + encodeURIComponent(SCOPE2); @@ -382,7 +701,12 @@ redirect_test( url1, url2, - [[{url: url1}], [{url: url2}], []], + [ + [{url: url1, resultingClientIdTag: 'x'}], + [{url: url2, resultingClientIdTag: 'x'}], + [] + ], + 'x', 'Redirect to same-origin other-scope with opaque redirect response.'); url1 = SCOPE1 + 'sw=manual&url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE); @@ -390,7 +714,8 @@ redirect_test( url1, url2, - [[{url: url1}], [], []], + [[{url: url1, resultingClientIdTag: 'a'}], [], []], + null, 'Redirect to other-origin out-scope with opaque redirect response.'); url1 = SCOPE1 + 'sw=manual&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE); @@ -398,12 +723,18 @@ redirect_test( url1, url2, - [[{url: url1}], [], [{url: url2}]], + [ + [{url: url1, resultingClientIdTag: 'a'}], + [], + [{url: url2, resultingClientIdTag: 'x'}] + ], + 'x', 'Redirect to other-origin in-scope with opaque redirect response.'); url= SCOPE1 + 'sw=manual&noLocationRedirect'; redirect_test( - url, url, [[{url}], [], []], + url, url, [[{url, resultingClientIdTag: 'x'}], [], []], + 'x', 'No location redirect response.'); @@ -414,7 +745,8 @@ redirect_test( url1, url2, - [[{url: url1}], [], []], + [[{url: url1, resultingClientIdTag: 'x'}], [], []], + 'x', 'Redirect to same-origin out-scope with opaque redirect response which ' + 'is passed through Cache.'); @@ -424,10 +756,14 @@ url1, url2, [ - [{url: url1}, {url: url2}], + [ + {url: url1, resultingClientIdTag: 'x'}, + {url: url2, resultingClientIdTag: 'x'} + ], [], [] ], + 'x', 'Redirect to same-origin same-scope with opaque redirect response which ' + 'is passed through Cache.'); @@ -437,10 +773,11 @@ url1, url2, [ - [{url: url1}], - [{url: url2}], + [{url: url1, resultingClientIdTag: 'x'}], + [{url: url2, resultingClientIdTag: 'x'}], [] ], + 'x', 'Redirect to same-origin other-scope with opaque redirect response which ' + 'is passed through Cache.'); @@ -450,7 +787,8 @@ redirect_test( url1, url2, - [[{url: url1}], [], []], + [[{url: url1, resultingClientIdTag: 'a'}], [], []], + null, 'Redirect to other-origin out-scope with opaque redirect response which ' + 'is passed through Cache.'); @@ -461,10 +799,11 @@ url1, url2, [ - [{url: url1}], + [{url: url1, resultingClientIdTag: 'a'}], [], - [{url: url2}], + [{url: url2, resultingClientIdTag: 'x'}], ], + 'x', 'Redirect to other-origin in-scope with opaque redirect response which ' + 'is passed through Cache.'); @@ -472,7 +811,8 @@ redirect_test( url, url, - [[{url}], [], []], + [[{url, resultingClientIdTag: 'x'}], [], []], + 'x', 'No location redirect response via Cache.'); // Clean up the test environment. This promise_test() needs to be the last one.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https_client-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https_client-expected.txt new file mode 100644 index 0000000..8856e57f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https_client-expected.txt
@@ -0,0 +1,41 @@ +This is a testharness.js-based test. +PASS initialize global state +FAIL Normal redirect to same-origin scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py? request to worker0 expected "string" but got "undefined" +FAIL Normal redirect to same-origin scope with a hash fragment. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?#ref request to worker0 expected "string" but got "undefined" +FAIL Normal redirect to same-origin scope with different hash fragments. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?#ref2 request to worker0 expected "string" but got "undefined" +FAIL Normal redirect to other-origin scope. assert_equals: resultingClientId for https://www1.web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py? request to crossOriginWorker expected "string" but got "undefined" +FAIL SW-fallbacked redirect to same-origin out-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-fallbacked redirect to same-origin same-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-fallbacked redirect to same-origin same-scope with a hash fragment. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F#ref request to worker0 expected "string" but got "undefined" +FAIL SW-fallbacked redirect to same-origin same-scope with different hash fragments. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F%23ref2#ref request to worker0 expected "string" but got "undefined" +FAIL SW-fallbacked redirect to same-origin other-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope2.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-fallbacked redirect to other-origin out-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-fallbacked redirect to other-origin in-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-fallbacked redirect to other-origin and back to same-origin. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3Furl%3Dhttps%253A%252F%252Fweb-platform.test%253A8444%252Fservice-workers%252Fservice-worker%252Fresources%252Fnavigation-redirect-scope1.py%253F request to worker0 expected "string" but got "undefined" +FAIL SW-generated redirect to same-origin out-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-generated redirect to same-origin out-scope with a hash fragment. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F#ref request to worker0 expected "string" but got "undefined" +FAIL SW-generated redirect to same-origin out-scope with different hash fragments. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F%23ref2#ref request to worker0 expected "string" but got "undefined" +FAIL SW-generated redirect to same-origin same-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-generated redirect to same-origin other-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope2.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-generated redirect to other-origin out-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-generated redirect to other-origin in-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-fetched redirect to same-origin out-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=fetch&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-fetched redirect to same-origin same-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=fetch&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-fetched redirect to same-origin other-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=fetch&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope2.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-fetched redirect to other-origin out-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=fetch&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined" +FAIL SW-fetched redirect to other-origin in-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=fetch&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined" +FAIL Redirect to same-origin out-scope with opaque redirect response. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manual&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined" +FAIL Redirect to same-origin same-scope with opaque redirect response. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manual&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined" +FAIL Redirect to same-origin other-scope with opaque redirect response. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manual&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope2.py%3F request to worker0 expected "string" but got "undefined" +FAIL Redirect to other-origin out-scope with opaque redirect response. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manual&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined" +FAIL Redirect to other-origin in-scope with opaque redirect response. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manual&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined" +FAIL No location redirect response. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manual&noLocationRedirect request to worker0 expected "string" but got "undefined" +FAIL Redirect to same-origin out-scope with opaque redirect response which is passed through Cache. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manualThroughCache&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined" +FAIL Redirect to same-origin same-scope with opaque redirect response which is passed through Cache. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manualThroughCache&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined" +FAIL Redirect to same-origin other-scope with opaque redirect response which is passed through Cache. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manualThroughCache&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope2.py%3F request to worker0 expected "string" but got "undefined" +FAIL Redirect to other-origin out-scope with opaque redirect response which is passed through Cache. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manualThroughCache&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined" +FAIL Redirect to other-origin in-scope with opaque redirect response which is passed through Cache. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manualThroughCache&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined" +FAIL No location redirect response via Cache. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manualThroughCache&noLocationRedirect request to worker0 expected "string" but got "undefined" +PASS clean up global state +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/navigation-redirect-other-origin.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/navigation-redirect-other-origin.html index 0d2825f..d82571d1a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/navigation-redirect-other-origin.html +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/navigation-redirect-other-origin.html
@@ -44,6 +44,20 @@ }); } +function get_clients(worker, actual_ids) { + return new Promise(function(resolve) { + var channel = new MessageChannel(); + channel.port1.onmessage = (msg) => { + resolve(msg.data.clients); + }; + worker.postMessage({ + command: 'getClients', + actual_ids, + port: channel.port2 + }, [channel.port2]); + }); +} + window.addEventListener('message', on_message, false); function on_message(e) { @@ -59,6 +73,11 @@ .then(function(data) { send_result(e.data.id, data); }); + } else if (command == 'get_clients') { + get_clients(worker, e.data.message.actual_ids) + .then(function(data) { + send_result(e.data.id, data); + }); } else if (command == 'unregister') { registration.unregister() .then(function() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/redirect-worker.js b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/redirect-worker.js index bf0a3a8..0c5bc3bd 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/redirect-worker.js +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/redirect-worker.js
@@ -5,6 +5,13 @@ var waitUntilPromiseList = []; +// Sends the requests seen by this worker. The output is: +// { +// requestInfos: [ +// {url: url1, resultingClientId: id1}, +// {url: url2, resultingClientId: id2}, +// ] +// } async function getRequestInfos(event) { // Wait for fetch events to finish. await Promise.all(waitUntilPromiseList); @@ -15,8 +22,11 @@ const requestList = await cache.keys(); const requestInfos = []; for (let i = 0; i < requestList.length; i++) { + const response = await cache.match(requestList[i]); + const body = await response.json(); requestInfos[i] = { url: requestList[i].url, + resultingClientId: body.resultingClientId }; } await caches.delete(cacheName); @@ -24,13 +34,50 @@ event.data.port.postMessage({requestInfos}); } +// Sends the results of clients.get(id) from this worker. The +// input is: +// { +// actual_ids: {a: id1, b: id2, x: id3} +// } +// +// The output is: +// { +// clients: { +// a: {found: false}, +// b: {found: false}, +// x: { +// id: id3, +// url: url1, +// found: true +// } +// } +// } +async function getClients(event) { + // |actual_ids| is like: + // {a: id1, b: id2, x: id3} + const actual_ids = event.data.actual_ids; + const result = {} + for (let key of Object.keys(actual_ids)) { + const id = actual_ids[key]; + const client = await self.clients.get(id); + if (client === undefined) + result[key] = {found: false}; + else + result[key] = {found: true, url: client.url, id: client.id}; + } + event.data.port.postMessage({clients: result}); +} + self.addEventListener('message', async function(event) { if (event.data.command == 'getRequestInfos') { event.waitUntil(getRequestInfos(event)); return; } - // TODO(falken): Add a getClientInfos command to test Clients API. + if (event.data.command == 'getClients') { + event.waitUntil(getClients(event)); + return; + } }); function get_query_params(url) { @@ -49,7 +96,11 @@ self.addEventListener('fetch', function(event) { var waitUntilPromise = caches.open(cacheName).then(function(cache) { - return cache.put(event.request, new Response()); + const responseBody = {}; + responseBody['resultingClientId'] = event.resultingClientId; + const headers = new Headers({'Content-Type': 'application/json'}); + const response = new Response(JSON.stringify(responseBody), {headers}); + return cache.put(event.request, response); }); event.waitUntil(waitUntilPromise);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window-expected.txt index ebd89e3..c1e94f9 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window-expected.txt
@@ -41,7 +41,7 @@ PASS AudioContext interface: attribute baseLatency FAIL AudioContext interface: attribute outputLatency assert_true: The prototype object must have a property "outputLatency" expected true got false PASS AudioContext interface: operation getOutputTimestamp() -FAIL AudioContext interface: operation resume() assert_own_property: interface prototype object missing non-static operation expected property "resume" missing +PASS AudioContext interface: operation resume() PASS AudioContext interface: operation suspend() PASS AudioContext interface: operation close() FAIL AudioContext interface: operation createMediaElementSource(HTMLMediaElement) assert_own_property: interface prototype object missing non-static operation expected property "createMediaElementSource" missing @@ -104,7 +104,7 @@ PASS OfflineAudioContext interface: existence and properties of interface prototype object's "constructor" property PASS OfflineAudioContext interface: existence and properties of interface prototype object's @@unscopables property PASS OfflineAudioContext interface: operation startRendering() -FAIL OfflineAudioContext interface: operation resume() assert_own_property: interface prototype object missing non-static operation expected property "resume" missing +PASS OfflineAudioContext interface: operation resume() PASS OfflineAudioContext interface: operation suspend(double) PASS OfflineAudioContext interface: attribute length PASS OfflineAudioContext interface: attribute oncomplete
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension-helper.js b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension-helper.js new file mode 100644 index 0000000..659ec59 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension-helper.js
@@ -0,0 +1,42 @@ +'use strict'; + +// Construct an RTCIceTransport instance. The instance will automatically be +// cleaned up when the test finishes. +function makeIceTransport(t) { + const iceTransport = new RTCIceTransport(); + t.add_cleanup(() => iceTransport.stop()); + return iceTransport; +} + +// Construct two RTCIceTransport instances, configure them to exchange +// candidates, then gather() them. +// Returns a 2-list: [ RTCIceTransport, RTCIceTransport ] +function makeAndGatherTwoIceTransports(t) { + const localTransport = makeIceTransport(t); + const remoteTransport = makeIceTransport(t); + localTransport.onicecandidate = e => { + if (e.candidate) { + remoteTransport.addRemoteCandidate(e.candidate); + } + }; + remoteTransport.onicecandidate = e => { + if (e.candidate) { + localTransport.addRemoteCandidate(e.candidate); + } + }; + localTransport.gather({}); + remoteTransport.gather({}); + return [ localTransport, remoteTransport ]; +} + +// Construct two RTCIceTransport instances, configure them to exchange +// candidates and parameters, then gather() and start() them. +// Returns a 2-list: +// [ controlling RTCIceTransport, +// controlled RTCIceTransport ] +function makeGatherAndStartTwoIceTransports(t) { + const [ localTransport, remoteTransport ] = makeAndGatherTwoIceTransports(t); + localTransport.start(remoteTransport.getLocalParameters(), 'controlling'); + remoteTransport.start(localTransport.getLocalParameters(), 'controlled'); + return [ localTransport, remoteTransport ]; +}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension.https.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension.https.html index 9c6cec7..5adee9f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension.https.html
@@ -3,12 +3,18 @@ <title>RTCIceTransport-extensions.https.html</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="RTCIceTransport-extension-helper.js"></script> <script> 'use strict'; // These tests are based on the following extension specification: // https://w3c.github.io/webrtc-ice/ +// The following helper functions are called from +// RTCIceTransport-extension-helper.js: +// makeIceTransport +// makeGatherAndStartTwoIceTransports + function makeIceTransport(t) { const iceTransport = new RTCIceTransport(); t.add_cleanup(() => iceTransport.stop()); @@ -240,22 +246,8 @@ 'later called with different remote parameters'); promise_test(async t => { - const localTransport = makeIceTransport(t); - const remoteTransport = makeIceTransport(t); - localTransport.onicecandidate = e => { - if (e.candidate) { - remoteTransport.addRemoteCandidate(e.candidate); - } - }; - remoteTransport.onicecandidate = e => { - if (e.candidate) { - localTransport.addRemoteCandidate(e.candidate); - } - }; - localTransport.gather({}); - remoteTransport.gather({}); - localTransport.start(remoteTransport.getLocalParameters(), 'controlling'); - remoteTransport.start(localTransport.getLocalParameters(), 'controlled'); + const [ localTransport, remoteTransport ] = + makeGatherAndStartTwoIceTransports(t); const localWatcher = new EventWatcher(t, localTransport, 'statechange'); const remoteWatcher = new EventWatcher(t, remoteTransport, 'statechange'); await Promise.all([
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicStream.https.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicStream.https.html index 1e08016d..33025451 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicStream.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicStream.https.html
@@ -3,6 +3,7 @@ <title>RTCQuicStream.https.html</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="RTCIceTransport-extension-helper.js"></script> <script src="RTCQuicTransport-helper.js"></script> <script> 'use strict'; @@ -11,10 +12,10 @@ // https://w3c.github.io/webrtc-quic/ // The following helper functions are called from RTCQuicTransport-helper.js: -// makeQuicTransport +// makeStandaloneQuicTransport -test(t => { - const quicTransport = makeQuicTransport(t, []); +promise_test(async t => { + const quicTransport = await makeStandaloneQuicTransport(t); const quicStream = quicTransport.createStream(); assert_equals(quicStream.transport, quicTransport, 'Expect transport to be set to the creating RTCQuicTransport.'); @@ -25,14 +26,14 @@ 'Expect write buffered amount to be 0.'); }, 'createStream() returns an RTCQuicStream with initial properties set.'); -test(t => { - const quicTransport = makeQuicTransport(t, []); +promise_test(async t => { + const quicTransport = await makeStandaloneQuicTransport(t); quicTransport.stop(); assert_throws('InvalidStateError', () => quicTransport.createStream()); }, 'createStream() throws if the transport is closed.'); -test(t => { - const quicTransport = makeQuicTransport(t, []); +promise_test(async t => { + const quicTransport = await makeStandaloneQuicTransport(t); const firstQuicStream = quicTransport.createStream(); const secondQuicStream = quicTransport.createStream(); quicTransport.stop();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport-helper.js b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport-helper.js index 50d9e66..3ea19d7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport-helper.js +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport-helper.js
@@ -1,10 +1,82 @@ 'use strict'; -function makeQuicTransport(t, certificates) { - const iceTransport = new RTCIceTransport(); - t.add_cleanup(() => iceTransport.stop()); +// This file depends on RTCIceTransport-extension-helper.js which should be +// loaded from the main HTML file. +// The following helper functions are called from +// RTCIceTransport-extension-helper.js: +// makeIceTransport +// makeGatherAndStartTwoIceTransports + +// Return a promise to generate an RTCCertificate with the given keygen +// algorithm or a default one if none provided. +function generateCertificate(keygenAlgorithm) { + return RTCPeerConnection.generateCertificate({ + name: 'ECDSA', + namedCurve: 'P-256', + ...keygenAlgorithm, + }); +} + +// Construct an RTCQuicTransport instance with the given RTCIceTransport +// instance and the given certificates. The RTCQuicTransport instance will be +// automatically cleaned up when the test finishes. +function makeQuicTransport(t, iceTransport, certificates) { const quicTransport = new RTCQuicTransport(iceTransport, certificates); t.add_cleanup(() => quicTransport.stop()); return quicTransport; } +// Construct an RTCQuicTransport instance with a new RTCIceTransport instance +// and a single, newly-generated certificate. The RTCQuicTransport and +// RTCIceTransport instances will be automatically cleaned up when the test +// finishes. +async function makeStandaloneQuicTransport(t) { + const certificate = await generateCertificate(); + return makeQuicTransport(t, makeIceTransport(t), [ certificate ]); +} + +// Construct two RTCQuicTransport instances and each call start() with the other +// transport's local parameters. +// Returns a 2-list: +// [ server RTCQuicTransport, +// client RTCQuicTransport ] +async function makeAndStartTwoQuicTransports(t) { + const [ localCertificate, remoteCertificate ] = + await Promise.all([ generateCertificate(), generateCertificate() ]); + const [ localIceTransport, remoteIceTransport ] = + makeGatherAndStartTwoIceTransports(t); + const localQuicTransport = + makeQuicTransport(t, localIceTransport, [ localCertificate ]); + const remoteQuicTransport = + makeQuicTransport(t, remoteIceTransport, [ remoteCertificate ]); + localQuicTransport.start(remoteQuicTransport.getLocalParameters()); + remoteQuicTransport.start(localQuicTransport.getLocalParameters()); + return [ localQuicTransport, remoteQuicTransport ]; +} + +// Construct two RTCQuicTransport instances and wait for them to connect. +// Returns a 2-list: +// [ server RTCQuicTransport, +// client RTCQuicTransport ] +async function makeTwoConnectedQuicTransports(t) { + // Returns a promise that resolves when the transport fires a 'statechange' + // event to 'connected'. + function waitForConnected(transport) { + return new Promise((resolve, reject) => { + const eventHandler = t.step_func(() => { + assert_equals(transport.state, 'connected'); + transport.removeEventListener('statechange', eventHandler, false); + resolve(); + }); + transport.addEventListener('statechange', eventHandler, false); + }); + } + const [ localQuicTransport, remoteQuicTransport ] = + await makeAndStartTwoQuicTransports(t); + await Promise.all([ + waitForConnected(localQuicTransport), + waitForConnected(remoteQuicTransport), + ]); + return [ localQuicTransport, remoteQuicTransport ]; +} +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport.https.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport.https.html index 703f424a..ec79bc22 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport.https.html
@@ -3,6 +3,7 @@ <title>RTCQuicTransport.https.html</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="RTCIceTransport-extension-helper.js"></script> <script src="RTCQuicTransport-helper.js"></script> <script> 'use strict'; @@ -10,36 +11,31 @@ // These tests are based on the following specification: // https://w3c.github.io/webrtc-quic/ +// The following helper functions are called from +// RTCIceTransport-extension-helper.js: +// makeIceTransport +// makeAndGatherTwoIceTransports + // The following helper functions are called from RTCQuicTransport-helper.js: // makeQuicTransport +// makeStandaloneQuicTransport +// makeAndStartTwoQuicTransports +// makeTwoConnectedQuicTransports -function generateCertificate(keygenAlgorithm) { - return RTCPeerConnection.generateCertificate({ - name: 'ECDSA', - namedCurve: 'P-256', - ...keygenAlgorithm, - }); -} - -test(t => { - // Don't use the makeQuicTransport helper so that the transport property can - // be verified. - const iceTransport = new RTCIceTransport(); - const quicTransport = new RTCQuicTransport(iceTransport, []); - t.add_cleanup(() => { - quicTransport.stop(); - iceTransport.stop(); - }); +promise_test(async t => { + const certificate = await generateCertificate(); + const iceTransport = makeIceTransport(t); + const quicTransport = makeQuicTransport(t, iceTransport, [ certificate ]); assert_equals(quicTransport.transport, iceTransport, 'Expect transport to be the same as the one passed in the constructor.'); assert_equals(quicTransport.state, 'new', `Expect state to be 'new'.`); assert_object_equals(quicTransport.getLocalParameters(), - { role: 'auto', fingerprints: [] }, + { role: 'auto', fingerprints: certificate.getFingerprints() }, 'Expect local parameters to be initialized.'); assert_equals(quicTransport.getRemoteParameters(), null, 'Expect no remote parameters.'); - assert_array_equals(quicTransport.getCertificates(), [], - 'Expect not certificates.'); + assert_array_equals(quicTransport.getCertificates(), [ certificate ], + 'Expect one certificate.'); assert_array_equals(quicTransport.getRemoteCertificates(), [], 'Expect no remote certificates.'); }, 'RTCQuicTransport initial properties are set.'); @@ -48,7 +44,8 @@ const [ firstCertificate, secondCertificate ] = await Promise.all([ generateCertificate(), generateCertificate() ]); const quicTransport = - makeQuicTransport(t, [ firstCertificate, secondCertificate ]); + makeQuicTransport(t, makeIceTransport(t), + [ firstCertificate, secondCertificate ]); assert_array_equals(quicTransport.getCertificates(), [ firstCertificate, secondCertificate ]); }, 'getCertificates() returns the certificates passed in the constructor.'); @@ -57,11 +54,13 @@ const [ firstCertificate, secondCertificate ] = await Promise.all([ generateCertificate(), generateCertificate() ]); const quicTransport = - makeQuicTransport(t, [ firstCertificate, secondCertificate ]); + makeQuicTransport(t, makeIceTransport(t), + [ firstCertificate, secondCertificate ]); assert_object_equals(quicTransport.getLocalParameters(), { role: 'auto', - fingerprints: [ firstCertificate.getFingerprints()[0], - secondCertificate.getFingerprints()[0] ], + fingerprints: + [ firstCertificate.getFingerprints()[0], + secondCertificate.getFingerprints()[0] ], }); assert_array_equals(quicTransport.getCertificates(), [ firstCertificate, secondCertificate ]); @@ -71,21 +70,119 @@ promise_test(async t => { const expiredCertificate = await generateCertificate({ expires: 0 }); assert_throws(new TypeError(), - () => makeQuicTransport(t, [ expiredCertificate ])); + () => makeQuicTransport(t, makeIceTransport(t), [ expiredCertificate ])); }, 'RTCQuicTransport constructor throws if passed an expired certificate.'); -test(t => { - const iceTransport = new RTCIceTransport(); +promise_test(async t => { + const certificate = await generateCertificate(); + const iceTransport = makeIceTransport(t); iceTransport.stop(); assert_throws('InvalidStateError', - () => new RTCQuicTransport(iceTransport, [])); + () => makeQuicTransport(t, iceTransport, [ certificate ])); }, 'RTCQuicTransport constructor throws if passed a closed RTCIceTransport.'); -test(t => { - const quicTransport = makeQuicTransport(t, []); +promise_test(async t => { + const certificate = await generateCertificate(); + const iceTransport = makeIceTransport(t); + const firstQuicTransport = + makeQuicTransport(t, iceTransport, [ certificate ]); + assert_throws('InvalidStateError', + () => makeQuicTransport(t, iceTransport, [ certificate ])); +}, 'RTCQuicTransport constructor throws if passed an RTCIceTransport that ' + + 'already has an active RTCQuicTransport.'); + +promise_test(async t => { + const quicTransport = await makeStandaloneQuicTransport(t); quicTransport.stop(); assert_equals(quicTransport.state, 'closed'); }, `stop() changes state to 'closed'.`); +promise_test(async t => { + const quicTransport = await makeStandaloneQuicTransport(t); + quicTransport.transport.stop(); + assert_equals(quicTransport.state, 'closed'); +}, `RTCIceTransport.stop() changes RTCQuicTransport.state to 'closed'.`); + +promise_test(async t => { + const quicTransport = await makeStandaloneQuicTransport(t); + quicTransport.start(quicTransport.getLocalParameters()); + assert_equals(quicTransport.state, 'new'); +}, 'start() with a non-started RTCIceTransport does not change state.'); + +promise_test(async t => { + const certificate = await generateCertificate(); + const [ localIceTransport, remoteIceTransport ] = + makeAndGatherTwoIceTransports(t); + const quicTransport = + makeQuicTransport(t, localIceTransport, [ certificate ]); + quicTransport.start(quicTransport.getLocalParameters()); + const iceTransportWatcher = + new EventWatcher(t, remoteIceTransport, 'icecandidate'); + await iceTransportWatcher.wait_for('icecandidate'); + localIceTransport.start(remoteIceTransport.getLocalParameters(), + 'controlling'); + assert_equals(quicTransport.state, 'connecting'); +}, 'start() with a non-started RTCIceTransport later changes state to ' + + `'connecting' once the RTCIceTransport.start() is called.`); + +promise_test(async t => { + const certificate = await generateCertificate(); + const [ localIceTransport, remoteIceTransport ] = + makeAndGatherTwoIceTransports(t); + const quicTransport = + makeQuicTransport(t, localIceTransport, [ certificate ]); + const iceTransportWatcher = + new EventWatcher(t, remoteIceTransport, 'icecandidate'); + await iceTransportWatcher.wait_for('icecandidate'); + localIceTransport.start(remoteIceTransport.getLocalParameters()); + quicTransport.start(quicTransport.getLocalParameters()); + assert_equals(quicTransport.state, 'connecting'); +}, `start() with a started RTCIceTransport changes state to 'connecting'.`); + +promise_test(async t => { + const quicTransport = await makeStandaloneQuicTransport(t); + quicTransport.stop(); + assert_throws('InvalidStateError', + () => quicTransport.start(quicTransport.getLocalParameters())); +}, 'start() throws if called after stop().'); + +promise_test(async t => { + const quicTransport = await makeStandaloneQuicTransport(t); + quicTransport.transport.stop(); + assert_throws('InvalidStateError', + () => quicTransport.start(quicTransport.getLocalParameters())); +}, 'start() throws if called after the RTCIceTransport has stopped.'); + +promise_test(async t => { + const quicTransport = await makeStandaloneQuicTransport(t); + quicTransport.start(quicTransport.getLocalParameters()); + assert_throws('InvalidStateError', + () => quicTransport.start(quicTransport.getLocalParameters())); +}, 'start() throws if called twice.'); + +promise_test(async t => { + const [ localQuicTransport, remoteQuicTransport ] = + await makeAndStartTwoQuicTransports(t); + const localWatcher = new EventWatcher(t, localQuicTransport, 'statechange'); + const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'statechange'); + await Promise.all([ + localWatcher.wait_for('statechange').then(() => { + assert_equals(localQuicTransport.state, 'connected'); + }), + remoteWatcher.wait_for('statechange').then(() => { + assert_equals(remoteQuicTransport.state, 'connected'); + }), + ]); +}, 'Two RTCQuicTransports connect to each other.'); + +promise_test(async t => { + const [ localQuicTransport, remoteQuicTransport ] = + await makeTwoConnectedQuicTransports(t); + localQuicTransport.stop(); + const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'statechange'); + await remoteWatcher.wait_for('statechange'); + assert_equals(remoteQuicTransport.state, 'closed'); +}, `stop() fires a statechange event to 'closed' on the remote transport`); + </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-headers-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-headers-expected.txt index 81503474..61921b7 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-headers-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-headers-expected.txt
@@ -75,6 +75,16 @@ serverIPAddress : "" startedDateTime : <string> time : <number> - timings : <object> + timings : { + _blocked_proxy : 0.752 + _blocked_queueing : 0.9689999860711396 + blocked : 3.8059999860711398 + connect : 229.12300000000002 + dns : 84.076 + receive : 6.20800000615418 + send : 0.5549999999999784 + ssl : 98.702 + wait : 568.4820000130125 + } }
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-headers.js b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-headers.js index 13752cb..4d28d75a 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-headers.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-har-headers.js
@@ -26,6 +26,28 @@ request.resourceSize = 1000; request._transferSize = 539; // 39 = header size at the end of the day request.setPriority('VeryHigh'); + + // sample timing values used here are copied from a real request + request.setIssueTime(357904.060558); + request.endTime = 357904.867763; + request.timing = { + 'requestTime': 357904.061527, + 'proxyStart': 1.68, + 'proxyEnd': 2.432, + 'dnsStart': 2.837, + 'dnsEnd': 86.913, + 'connectStart': 86.913, + 'connectEnd': 231.96, + 'sslStart': 133.24, + 'sslEnd': 231.942, + 'workerStart': -1, + 'workerReady': -1, + 'sendStart': 232.218, + 'sendEnd': 232.515, + 'pushStart': 0, + 'pushEnd': 0, + 'receiveHeadersEnd': 800.997 + }; } const fakeInitiator = { @@ -56,7 +78,6 @@ var stillNondeterministic = { 'startedDateTime': 'formatAsTypeName', 'time': 'formatAsTypeName', - 'timings': 'formatAsTypeName', '_transferSize': 'formatAsTypeName', '_error': 'skip' };
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/accessibility/accessibility-nameSources-visiblity-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/accessibility/accessibility-nameSources-visiblity-expected.txt index 49ddf6cb..a651fad 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/accessibility/accessibility-nameSources-visiblity-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/accessibility/accessibility-nameSources-visiblity-expected.txt
@@ -314,7 +314,7 @@ "type": "relatedElement", "value": { "type": "computedString", - "value": "\n 1 \n \n 2 \n \n \n \n \n \n 7 \n " + "value": "\n 1\n \n 2\n \n \n \n \n \n 7\n " }, "attribute": "aria-labelledby", "attributeValue": { @@ -323,7 +323,7 @@ "relatedNodes": [ { "idref": "label4", - "text": "\n 1 \n \n 2 \n \n \n \n \n \n 7 \n ", + "text": "\n 1\n \n 2\n \n \n \n \n \n 7\n ", "nodeResult": "div#label4" } ] @@ -392,7 +392,7 @@ "relatedNodes": [ { "idref": "label4", - "text": "\n 1 \n \n 2 \n \n \n \n \n \n 7 \n ", + "text": "\n 1\n \n 2\n \n \n \n \n \n 7\n ", "nodeResult": "div#label4" } ]
diff --git a/third_party/WebKit/LayoutTests/virtual/speech-with-unified-autoplay/external/wpt/speech-api/README.txt b/third_party/WebKit/LayoutTests/virtual/speech-with-unified-autoplay/external/wpt/speech-api/README.txt new file mode 100644 index 0000000..0d1d1daa --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/speech-with-unified-autoplay/external/wpt/speech-api/README.txt
@@ -0,0 +1 @@ +This suite runs Speech API tests with Unified Autoplay enabled.
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt index 43dbaff5..41106bf4 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -127,6 +127,7 @@ method close method constructor method getOutputTimestamp + method resume method suspend interface AudioDestinationNode : AudioNode attribute @@toStringTag @@ -261,7 +262,6 @@ method createStereoPanner method createWaveShaper method decodeAudioData - method resume setter onstatechange interface BatteryManager : EventTarget attribute @@toStringTag @@ -4223,6 +4223,7 @@ getter length getter oncomplete method constructor + method resume method startRendering method suspend setter oncomplete
diff --git a/third_party/WebKit/LayoutTests/webaudio/AudioContext/audiocontext-properties.html b/third_party/WebKit/LayoutTests/webaudio/AudioContext/audiocontext-properties.html deleted file mode 100644 index 7aa6675..0000000 --- a/third_party/WebKit/LayoutTests/webaudio/AudioContext/audiocontext-properties.html +++ /dev/null
@@ -1,29 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title> - Testing AudioContext properties - </title> - <script src="../../resources/testharness.js"></script> - <script src="../../resources/testharnessreport.js"></script> - <script src="../resources/audit-util.js"></script> - <script src="../resources/audit.js"></script> - <script src="../resources/context-properties.js"></script> - </head> - <body> - <script id="layout-test-code"> - let audit = Audit.createTaskRunner(); - - - // Cross-checking two sets of properties: a programmatically generated set - // and a pre-populated set. - audit.define('crosschecking-properties', (task, should) => { - verifyPrototypeOwnProperties( - AudioContext.prototype, AudioContextOwnProperties, should); - task.done(); - }); - - audit.run(); - </script> - </body> -</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/BaseAudioContext/baseaudiocontext-properties.html b/third_party/WebKit/LayoutTests/webaudio/BaseAudioContext/baseaudiocontext-properties.html deleted file mode 100644 index aec372c..0000000 --- a/third_party/WebKit/LayoutTests/webaudio/BaseAudioContext/baseaudiocontext-properties.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title> - Testing BaseAudioContext properties - </title> - <script src="../../resources/testharness.js"></script> - <script src="../../resources/testharnessreport.js"></script> - <script src="../resources/audit-util.js"></script> - <script src="../resources/audit.js"></script> - <script src="../resources/context-properties.js"></script> - </head> - <body> - <script id="layout-test-code"> - let audit = Audit.createTaskRunner(); - - - // Cross-checking two sets of properties: a programmatically generated set - // and a pre-populated set. - audit.define('crosschecking-properties', (task, should) => { - verifyPrototypeOwnProperties( - BaseAudioContext.prototype, BaseAudioContextOwnProperties, should); - task.done(); - }); - - - audit.run(); - </script> - </body> -</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/OfflineAudioContext/offlineaudiocontext-properties.html b/third_party/WebKit/LayoutTests/webaudio/OfflineAudioContext/offlineaudiocontext-properties.html deleted file mode 100644 index ac328e1..0000000 --- a/third_party/WebKit/LayoutTests/webaudio/OfflineAudioContext/offlineaudiocontext-properties.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title> - Testing OfflineAudioContext properties - </title> - <script src="../../resources/testharness.js"></script> - <script src="../../resources/testharnessreport.js"></script> - <script src="../resources/audit-util.js"></script> - <script src="../resources/audit.js"></script> - <script src="../resources/context-properties.js"></script> - </head> - <body> - <script id="layout-test-code"> - let audit = Audit.createTaskRunner(); - - - // Cross-checking two sets of properties: a programmatically generated set - // and a pre-populated set. - audit.define('crosschecking-properties', (task, should) => { - verifyPrototypeOwnProperties( - OfflineAudioContext.prototype, OfflineAudioContextOwnProperties, - should); - task.done(); - }); - - audit.run(); - </script> - </body> -</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/resources/context-properties.js b/third_party/WebKit/LayoutTests/webaudio/resources/context-properties.js deleted file mode 100644 index 4961bec..0000000 --- a/third_party/WebKit/LayoutTests/webaudio/resources/context-properties.js +++ /dev/null
@@ -1,101 +0,0 @@ -// The list of the 'own' properties in various AudioContexts. These lists were -// populated by running: -// -// Object.getOwnPropertyNames(FooAudioContext.prototype); -// -// https://webaudio.github.io/web-audio-api/#BaseAudioContext - - -let BaseAudioContextOwnProperties = [ - 'audioWorklet', - 'constructor', - 'createAnalyser', - 'createBiquadFilter', - 'createBuffer', - 'createBufferSource', - 'createChannelMerger', - 'createChannelSplitter', - 'createConstantSource', - 'createConvolver', - 'createDelay', - 'createDynamicsCompressor', - 'createGain', - 'createIIRFilter', - 'createOscillator', - 'createPanner', - 'createPeriodicWave', - 'createScriptProcessor', - 'createStereoPanner', - 'createWaveShaper', - 'currentTime', - 'decodeAudioData', - 'destination', - 'listener', - 'onstatechange', - 'resume', - 'sampleRate', - 'state', - - // TODO(hongchan): these belong to AudioContext. - 'createMediaElementSource', - 'createMediaStreamDestination', - 'createMediaStreamSource', -]; - - -let AudioContextOwnProperties = [ - 'close', 'constructor', 'suspend', 'getOutputTimestamp', 'baseLatency', - - // TODO(hongchan): Not implemented yet. - // 'outputLatency', -]; - - -let OfflineAudioContextOwnProperties = [ - 'constructor', - 'length', - 'oncomplete', - 'startRendering', - 'suspend', -]; - - -/** - * Verify properties in the prototype with the pre-populated list. This is a - * 2-way comparison to detect the missing and the unexpected property at the - * same time. - * @param {Object} targetPrototype Target prototype. - * @param {Array} populatedList Property dictionary. - * @param {Function} should |Should| assertion function. - * @return {Map} Verification result map. - */ -function verifyPrototypeOwnProperties(targetPrototype, populatedList, should) { - let propertyMap = new Map(); - let generatedList = Object.getOwnPropertyNames(targetPrototype); - - for (let index in populatedList) { - propertyMap.set(populatedList[index], {actual: false, expected: true}); - } - - for (let index in generatedList) { - if (propertyMap.has(generatedList[index])) { - propertyMap.get(generatedList[index]).actual = true; - } else { - propertyMap.set(generatedList[index], {actual: true, expected: false}); - } - } - - for (let [property, result] of propertyMap) { - let prefix = 'The property "' + property + '"'; - if (result.expected && result.actual) { - // The test meets the expectation. - should(true, prefix).message('was expected and found successfully', ''); - } else if (result.expected && !result.actual) { - // The expected property is missing. - should(false, prefix).message('', 'was expected but not found.'); - } else if (!result.expected && result.actual) { - // Something unexpected was found. - should(false, prefix).message('', 'was not expected but found.'); - } - } -}
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index 13266312..537e5a6 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -297,6 +297,7 @@ method close method constructor method getOutputTimestamp + method resume method suspend interface AudioDestinationNode : AudioNode attribute @@toStringTag @@ -482,7 +483,6 @@ method createStereoPanner method createWaveShaper method decodeAudioData - method resume setter onstatechange interface BatteryManager : EventTarget attribute @@toStringTag @@ -4848,6 +4848,7 @@ getter length getter oncomplete method constructor + method resume method startRendering method suspend setter oncomplete @@ -5561,8 +5562,10 @@ getter transport getter writeBufferedAmount method constructor -interface RTCQuicTransport +interface RTCQuicTransport : EventTarget attribute @@toStringTag + getter onerror + getter onstatechange getter state getter transport method constructor @@ -5571,7 +5574,10 @@ method getLocalParameters method getRemoteCertificates method getRemoteParameters + method start method stop + setter onerror + setter onstatechange interface RTCRtpContributingSource attribute @@toStringTag getter source
diff --git a/third_party/blink/public/web/web_user_gesture_indicator.h b/third_party/blink/public/web/web_user_gesture_indicator.h index 6590b728..dca2e0c8 100644 --- a/third_party/blink/public/web/web_user_gesture_indicator.h +++ b/third_party/blink/public/web/web_user_gesture_indicator.h
@@ -43,17 +43,12 @@ public: // Returns true if a user gesture is currently being processed. Must be called // on the main thread. - // - // TODO(mustaq): remove the default value when all callers have been fixed. - BLINK_EXPORT static bool IsProcessingUserGesture(WebLocalFrame* = nullptr); + BLINK_EXPORT static bool IsProcessingUserGesture(WebLocalFrame*); // Can be called from any thread. Note that this is slower than the non // thread-safe version due to thread id lookups. Prefer the non thread-safe // version for code that will only execute on the main thread. - // - // TODO(mustaq): remove the default value when all callers have been fixed. - BLINK_EXPORT static bool IsProcessingUserGestureThreadSafe( - WebLocalFrame* = nullptr); + BLINK_EXPORT static bool IsProcessingUserGestureThreadSafe(WebLocalFrame*); // Returns true if a consumable gesture exists and has been successfully // consumed.
diff --git a/third_party/blink/renderer/core/frame/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation.cc index 5b6b3dd..b63431b 100644 --- a/third_party/blink/renderer/core/frame/deprecation.cc +++ b/third_party/blink/renderer/core/frame/deprecation.cc
@@ -590,9 +590,13 @@ "6708326821789696 for more details.", MilestoneString(kM70))}; case WebFeature::kTextToSpeech_SpeakDisallowedByAutoplay: - return {"TextToSpeech_DisallowedByAutoplay", kM71, - WillBeRemoved("speechSynthesis.speak() without user activation", - kM71, "5687444770914304")}; + return { + "TextToSpeech_DisallowedByAutoplay", kM71, + String::Format("speechSynthesis.speak() without user activation is" + "no longer allowed since %s. See" + "https://www.chromestatus.com/feature/" + "5687444770914304 for more details", + MilestoneString(kM71))}; case WebFeature::kPPAPIWebSocket: // TODO(ricea): Update once we have an expected release date for M74.
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index 11edc22..e25ac44 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1214,8 +1214,8 @@ auto* local_frame_client = Client(); if (!local_frame_client) return nullptr; - frame_resource_coordinator_.reset(FrameResourceCoordinator::Create( - local_frame_client->GetInterfaceProvider())); + frame_resource_coordinator_ = FrameResourceCoordinator::Create( + local_frame_client->GetInterfaceProvider()); } return frame_resource_coordinator_.get(); }
diff --git a/third_party/blink/renderer/core/inspector/browser_protocol.pdl b/third_party/blink/renderer/core/inspector/browser_protocol.pdl index 4d09e6d..df74b5b 100644 --- a/third_party/blink/renderer/core/inspector/browser_protocol.pdl +++ b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
@@ -5485,6 +5485,18 @@ # Enable collecting and reporting metrics. command enable + # Sets time domain to use for collecting and reporting duration metrics. + # Note that this must be called before enabling metrics collection. Calling + # this method while metrics collection is enabled returns an error. + experimental command setTimeDomain + parameters + # Time domain + enum timeDomain + # Use monotonically increasing abstract time (default). + timeTicks + # Use thread running time. + threadTicks + # Retrieve current values of run-time metrics. command getMetrics returns
diff --git a/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc b/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc index 350f957..e715aa3 100644 --- a/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc
@@ -83,12 +83,40 @@ .setValue(value) .build()); } - -TimeTicks GetTimeTicksNow() { - return base::subtle::TimeTicksNowIgnoringOverride(); -} } // namespace +Response InspectorPerformanceAgent::setTimeDomain(const String& time_domain) { + if (enabled_.Get()) { + return Response::Error( + "Cannot set time domain while performance metrics collection" + " is enabled."); + } + + using namespace protocol::Performance::SetTimeDomain; + + if (time_domain == TimeDomainEnum::TimeTicks) { + use_thread_ticks_ = false; + } else if (time_domain == TimeDomainEnum::ThreadTicks) { + if (!base::ThreadTicks::IsSupported()) { + return Response::Error("Thread time is not supported on this platform."); + } + base::ThreadTicks::WaitUntilInitialized(); + use_thread_ticks_ = true; + } else { + return Response::Error("Invalid time domain specification."); + } + + return Response::OK(); +} + +TimeTicks InspectorPerformanceAgent::GetTimeTicksNow() { + return use_thread_ticks_ + ? base::TimeTicks() + + base::TimeDelta::FromMicroseconds( + base::ThreadTicks::Now().since_origin().InMicroseconds()) + : base::subtle::TimeTicksNowIgnoringOverride(); +} + Response InspectorPerformanceAgent::getMetrics( std::unique_ptr<protocol::Array<protocol::Performance::Metric>>* out_result) {
diff --git a/third_party/blink/renderer/core/inspector/inspector_performance_agent.h b/third_party/blink/renderer/core/inspector/inspector_performance_agent.h index 6fbbd8f4..856bbba 100644 --- a/third_party/blink/renderer/core/inspector/inspector_performance_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_performance_agent.h
@@ -42,6 +42,7 @@ // Performance protocol domain implementation. protocol::Response enable() override; protocol::Response disable() override; + protocol::Response setTimeDomain(const String& time_domain) override; protocol::Response getMetrics( std::unique_ptr<protocol::Array<protocol::Performance::Metric>>* out_result) override; @@ -69,6 +70,7 @@ void ScriptStarts(); void ScriptEnds(); void InnerEnable(); + TimeTicks GetTimeTicksNow(); Member<InspectedFrames> inspected_frames_; TimeDelta layout_duration_; @@ -85,6 +87,7 @@ unsigned long long recalc_style_count_ = 0; int script_call_depth_ = 0; int layout_depth_ = 0; + bool use_thread_ticks_ = false; InspectorAgentState::Boolean enabled_; DISALLOW_COPY_AND_ASSIGN(InspectorPerformanceAgent); };
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc index 375106a..eb52a99 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
@@ -120,12 +120,12 @@ if (last_threshold_index_ != new_threshold_index || last_is_visible_ != is_visible) { - FloatRect snapped_root_bounds(geometry.RootRect()); + FloatRect root_bounds(geometry.UnZoomedRootRect()); FloatRect* root_bounds_pointer = - report_root_bounds ? &snapped_root_bounds : nullptr; + report_root_bounds ? &root_bounds : nullptr; IntersectionObserverEntry* new_entry = new IntersectionObserverEntry( - timestamp, new_visible_ratio, FloatRect(geometry.TargetRect()), - root_bounds_pointer, FloatRect(geometry.IntersectionRect()), + timestamp, new_visible_ratio, FloatRect(geometry.UnZoomedTargetRect()), + root_bounds_pointer, FloatRect(geometry.UnZoomedIntersectionRect()), new_threshold_index > 0, is_visible, Target()); entries_.push_back(new_entry); ToDocument(Observer()->GetExecutionContext())
diff --git a/third_party/blink/renderer/core/layout/intersection_geometry.cc b/third_party/blink/renderer/core/layout/intersection_geometry.cc index 33844bd..2d4fa91 100644 --- a/third_party/blink/renderer/core/layout/intersection_geometry.cc +++ b/third_party/blink/renderer/core/layout/intersection_geometry.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/html/html_frame_owner_element.h" +#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h" #include "third_party/blink/renderer/core/layout/layout_box.h" #include "third_party/blink/renderer/core/layout/layout_inline.h" #include "third_party/blink/renderer/core/layout/layout_view.h" @@ -233,4 +234,28 @@ MapRootRectToRootFrameCoordinates(); } +LayoutRect IntersectionGeometry::UnZoomedTargetRect() const { + if (!target_) + return target_rect_; + FloatRect rect(target_rect_); + AdjustForAbsoluteZoom::AdjustFloatRect(rect, *target_); + return LayoutRect(rect); +} + +LayoutRect IntersectionGeometry::UnZoomedIntersectionRect() const { + if (!target_) + return intersection_rect_; + FloatRect rect(intersection_rect_); + AdjustForAbsoluteZoom::AdjustFloatRect(rect, *target_); + return LayoutRect(rect); +} + +LayoutRect IntersectionGeometry::UnZoomedRootRect() const { + if (!root_) + return root_rect_; + FloatRect rect(root_rect_); + AdjustForAbsoluteZoom::AdjustFloatRect(rect, *root_); + return LayoutRect(rect); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/intersection_geometry.h b/third_party/blink/renderer/core/layout/intersection_geometry.h index cd26479..f08cfdb 100644 --- a/third_party/blink/renderer/core/layout/intersection_geometry.h +++ b/third_party/blink/renderer/core/layout/intersection_geometry.h
@@ -38,12 +38,18 @@ // Client rect in the coordinate system of the frame containing target. LayoutRect TargetRect() const { return target_rect_; } + // Target rect in CSS pixels + LayoutRect UnZoomedTargetRect() const; // Client rect in the coordinate system of the frame containing target. LayoutRect IntersectionRect() const { return intersection_rect_; } + // Intersection rect in CSS pixels + LayoutRect UnZoomedIntersectionRect() const; // Client rect in the coordinate system of the frame containing root. LayoutRect RootRect() const { return root_rect_; } + // Root rect in CSS pixels + LayoutRect UnZoomedRootRect() const; bool DoesIntersect() const { return does_intersect_; }
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index eb627d8..e58ebc7 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -5517,7 +5517,7 @@ : LayoutSize(MarginAfter(container_style), LayoutUnit())); } - if (!HasOverflowClip() && !ShouldApplyLayoutContainment()) + if (!ShouldClipOverflow() && !ShouldApplyLayoutContainment()) rect.Unite(LayoutOverflowRect()); bool has_transform = HasLayer() && Layer()->Transform();
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_flexible_box.cc index 0c7748b..e1def3fb 100644 --- a/third_party/blink/renderer/core/layout/layout_flexible_box.cc +++ b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -437,6 +437,14 @@ return StyleRef().FlexWrap() != EFlexWrap::kNowrap; } +bool LayoutFlexibleBox::ShouldApplyMinSizeAutoForChild( + const LayoutBox& child) const { + Length min = IsHorizontalFlow() ? child.StyleRef().MinWidth() + : child.StyleRef().MinHeight(); + return min.IsAuto() && !child.ShouldApplySizeContainment() && + MainAxisOverflowForChild(child) == EOverflow::kVisible; +} + Length LayoutFlexibleBox::FlexBasisForChild(const LayoutBox& child) const { Length flex_length = child.StyleRef().FlexBasis(); if (flex_length.IsAuto()) { @@ -997,14 +1005,7 @@ // computeMainAxisExtentForChild can return -1 when the child has a // percentage min size, but we have an indefinite size in that axis. sizes.min_size = std::max(LayoutUnit(), sizes.min_size); - } else if (min.IsAuto() && !child.ShouldApplySizeContainment() && - MainAxisOverflowForChild(child) == EOverflow::kVisible && - !(IsColumnFlow() && child.IsFlexibleBox())) { - // TODO(cbiesinger): For now, we do not handle min-height: auto for nested - // column flexboxes. We need to implement - // https://drafts.csswg.org/css-flexbox/#intrinsic-sizes before that - // produces reasonable results. Tracking bug: https://crbug.com/581553 - // css-flexbox section 4.5 + } else if (ShouldApplyMinSizeAutoForChild(child)) { LayoutUnit content_size = ComputeMainAxisExtentForChild(child, kMinSize, Length(kMinContent)); DCHECK_GE(content_size, LayoutUnit()); @@ -1124,6 +1125,14 @@ DISABLE_CFI_PERF FlexItem LayoutFlexibleBox::ConstructFlexItem(LayoutBox& child, ChildLayoutType layout_type) { + if (layout_type == kLayoutIfNeeded && IsColumnFlow() && + child.IsFlexibleBox() && ShouldApplyMinSizeAutoForChild(child)) { + // In this case, we have to force-layout to update the intrinsic height of + // our child; otherwise, it may be too big because it is based on previous + // flexing of a descendant, which would be a problem for applying + // min-size: auto. + layout_type = kForceLayout; + } if (layout_type != kNeverLayout && ChildHasIntrinsicMainAxisSize(child)) { // If this condition is true, then ComputeMainAxisExtentForChild will call // child.IntrinsicContentLogicalHeight() and
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.h b/third_party/blink/renderer/core/layout/layout_flexible_box.h index a2eb5329..156ca0fa 100644 --- a/third_party/blink/renderer/core/layout/layout_flexible_box.h +++ b/third_party/blink/renderer/core/layout/layout_flexible_box.h
@@ -111,6 +111,7 @@ bool IsColumnFlow() const; bool IsLeftToRightFlow() const; bool IsMultiline() const; + bool ShouldApplyMinSizeAutoForChild(const LayoutBox& child) const; Length FlexBasisForChild(const LayoutBox& child) const; LayoutUnit CrossAxisExtentForChild(const LayoutBox& child) const; LayoutUnit CrossAxisIntrinsicExtentForChild(const LayoutBox& child) const;
diff --git a/third_party/blink/renderer/core/paint/README.md b/third_party/blink/renderer/core/paint/README.md index 5402cf6..06c1288 100644 --- a/third_party/blink/renderer/core/paint/README.md +++ b/third_party/blink/renderer/core/paint/README.md
@@ -104,6 +104,13 @@ * Visual rect: the bounding box of all pixels that will be painted by a display item client. +* Isolation nodes/boundary: In certain situations, it is possible to put in + place a barrier that isolates a subtree from being affected by its + ancestors. This barrier is called an isolation boundary and is implemented + in the property trees as isolation nodes that serve as roots for any + descendant property nodes. Currently, the `contain: paint` css property + establishes an isolation boundary. + ## Overview The primary responsibility of this module is to convert the outputs from layout @@ -488,14 +495,14 @@ `InlineBox`es in the first line. ## PrePaint (Slimming paint invalidation/v2 only) -[`PrePaintTreeWalk`](PrePaintTreeWalk.h) +[`PrePaintTreeWalk`](pre_paint_tree_walk.h) During `InPrePaint` document lifecycle state, this class is called to walk the whole layout tree, beginning from the root FrameView, across frame boundaries. We do the following during the tree walk: ### Building paint property trees -[`PaintPropertyTreeBuilder`](PaintPropertyTreeBuilder.h) +[`PaintPropertyTreeBuilder`](paint_property_tree_builder.h) This class is responsible for building property trees (see [the platform paint README file](../../platform/graphics/paint/README.md)). @@ -510,6 +517,92 @@ `DescendantNeedsPaintPropertyUpdate` dirty bits on `LayoutObject` control how much of the layout tree is traversed during each `PrePaintTreeWalk`. +Additionally, some dirty bits are cleared at an isolation boundary. For example +if the paint property tree topology has changed by adding or removing nodes +for an element, we typically force a subtree walk for all descendants since +the descendant nodes may now refer to new parent nodes. However, at an +isolation boundary, we can reason that none of the descendants of an isolation +element would be affected, since the highest node that the paint property nodes +of an isolation element's subtree can reference are the isolation +nodes established at this element itself. + +Implementation note: the isolation boundary is achieved using alias nodes, which +are nodes that are put in place on an isolated element for clip, transform, and +effect trees. These nodes do not themselves contribute to any painted output, +but serve as parents to the subtree nodes. The alias nodes and isolation nodes +are synonymous and are used interchangeably. Also note that these nodes are +placed as children of the regular nodes of the element. This means that the +element itself is not isolated against ancestor mutations; it only isolates the +element's subtree. + +Example tree: ++----------------------+ +| 1. Root LayoutObject | ++----------------------+ + | | + | +-----------------+ + | | + v v ++-----------------+ +-----------------+ +| 2. LayoutObject | | 3. LayoutObject | ++-----------------+ +-----------------+ + | | + v | ++-----------------+ | +| 4. LayoutObject | | ++-----------------+ | + | + +-------------------------+ + | | ++-----------------+ +-----------------+ +| 5. LayoutObject | | 6. LayoutObject | ++-----------------+ +-----------------+ + | | + | +---------------------+ + | | + v v ++-----------------+ +-----------------+ +| 7. LayoutObject | | 8. LayoutObject | ++-----------------+ +-----------------+ + +Suppose that element 3's style changes to include a transform (e.g. +"transform: translateX(10px);"). + +Typically, here is the order of the walk (depth first) and updates: +* Root element 1 is visited since some descendant needs updates +* Element 2 is visited since it is one of the descendants, but it doesn't + need updates. +* Element 4 is skipped since the above step didn't need to recurse. +* Element 3 is visited since it's a descendant of the root element, and its + property trees are updated to include a new transform. This causes a flag + to be flipped that all subtree nodes need an update. +* Elements are then visited in the depth order: 5, 7, 8, 6. Elements 5 and 6 + reparent their transform nodes to point to the transform node of element 3. + Elements 7 and 8 are visited and updated but no changes occur. + +Now suppose that element 5 has "contain: paint" style, which establishes an +isolation boundary. The walk changes in the following way: + +* Root element 1 is visited since some descendant needs updates +* Element 2 is visited since it is one of the descendants, but it doesn't + need updates. +* Element 4 is skipped since the above step didn't need to recurse. +* Element 3 is visited since it's a descendant of the root element, and its + property trees are updated to include a new transform. This causes a flag + to be flipped that all subtree nodes need an update. +* Element 5 is visited and updated by reparenting the transform nodes. + However, now the element is an isolation boundary so elements 7 and 8 are + not visited (i.e. the forced subtree update flag is ignored). +* Element 6 is visited as before and is updated to reparent the transform + node. + +Note that there are subtleties when deciding whether we can skip the subtree +walk. Specifically, not all subtree walks can be stopped at an isolation +boundary. For more information, see +[`PaintPropertyTreeBuilder`](paint_property_tree_builder.h) and its use of +IsolationPiercing vs IsolationBlocked subtree update reasons. + + #### Fragments In the absence of multicolumn/pagination, there is a 1:1 correspondence between @@ -527,15 +620,15 @@ also store a unique `PaintOffset, `PaginationOffset and `LocalBordreBoxProperties` object. -See [`LayoutMultiColumnFlowThread.h`](../layout/LayoutMultiColumnFlowThread.h) +See [`LayoutMultiColumnFlowThread.h`](../layout/layout_multi_column_flow_thread.h) for a much more detail about multicolumn/pagination. ### Paint invalidation -[`PaintInvalidator`](PaintInvalidator.h) +[`PaintInvalidator`](paint_invalidator.h) This class replaces [`PaintInvalidationState`] for SlimmingPaintInvalidation. The main difference is that in PaintInvalidator, visual rects and locations -are computed by `GeometryMapper`(../../platform/graphics/paint/GeometryMapper.h), +are computed by `GeometryMapper`(../../platform/graphics/paint/geometry_mapper.h), based on paint properties produced by `PaintPropertyTreeBuilder`. TODO(wangxianzhu): Combine documentation of PaintInvalidation phase into here.
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 0e203bc..232eec3 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -180,6 +180,7 @@ ALWAYS_INLINE void UpdateReplacedContentTransform(); ALWAYS_INLINE void UpdateScrollAndScrollTranslation(); ALWAYS_INLINE void UpdateOutOfFlowContext(); + // See core/paint/README.md for the description of isolation nodes. ALWAYS_INLINE void UpdateTransformIsolationNode(); ALWAYS_INLINE void UpdateEffectIsolationNode(); ALWAYS_INLINE void UpdateClipIsolationNode();
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/HARLog.js b/third_party/blink/renderer/devtools/front_end/sdk/HARLog.js index be92037c..643d66c 100644 --- a/third_party/blink/renderer/devtools/front_end/sdk/HARLog.js +++ b/third_party/blink/renderer/devtools/front_end/sdk/HARLog.js
@@ -253,7 +253,7 @@ const result = {blocked: -1, dns: -1, ssl: -1, connect: -1, send: 0, wait: 0, receive: 0, _blocked_queueing: -1}; const queuedTime = (issueTime < startTime) ? startTime - issueTime : -1; - result.blocked = queuedTime; + result.blocked = SDK.HARLog.Entry._toMilliseconds(queuedTime); result._blocked_queueing = SDK.HARLog.Entry._toMilliseconds(queuedTime); let highestTime = 0;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc index 1a7eab91..dc9eff99 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -1814,6 +1814,21 @@ return StringValue(); } + // Step 2E from: http://www.w3.org/TR/accname-aam-1.1 + // "If the embedded control has role combobox or listbox, return the text + // alternative of the chosen option." + if (NameFromSelectedOption(recursive)) { + StringBuilder accumulated_text; + AXObjectVector selected_options; + SelectedOptions(selected_options); + for (const auto& child : selected_options) { + if (accumulated_text.length()) + accumulated_text.Append(" "); + accumulated_text.Append(child->ComputedName()); + } + return accumulated_text.ToString(); + } + // Step 2D from: http://www.w3.org/TR/accname-aam-1.1 text_alternative = NativeTextAlternative(visited, name_from, related_objects, name_sources, @@ -1937,9 +1952,11 @@ result = RecursiveTextAlternative(*child, false, visited); if (!result.IsEmpty() && previous && accumulated_text.length() && - !IsHTMLSpace(accumulated_text[accumulated_text.length() - 1])) { - if (ShouldInsertSpaceBetweenObjectsIfNeeded(previous, child)) + !IsHTMLSpace(accumulated_text[accumulated_text.length() - 1]) && + !IsHTMLSpace(result[0])) { + if (ShouldInsertSpaceBetweenObjectsIfNeeded(previous, child)) { accumulated_text.Append(' '); + } } accumulated_text.Append(result); @@ -2475,6 +2492,36 @@ AXObject::UpdateChildrenIfNecessary(); } +void AXNodeObject::SelectedOptions(AXObjectVector& options) const { + if (IsHTMLSelectElement(GetNode())) { + HTMLSelectElement* select = ToHTMLSelectElement(GetNode()); + for (auto* const option : *select->selectedOptions()) { + options.push_back(AXObjectCache().GetOrCreate(option)); + } + return; + } + + // If the combobox or listbox is a descendant of a label element for another + // widget, it may be ignored and Children() won't return all its children. + // As a result, we need to use RawFirstChild and RawNextSibling to iterate + // over the children in search of the selected option(s). + + if (RoleValue() == ax::mojom::Role::kComboBoxGrouping || + RoleValue() == ax::mojom::Role::kComboBoxMenuButton) { + for (AXObject* obj = RawFirstChild(); obj; obj = obj->RawNextSibling()) { + if (obj->RoleValue() == ax::mojom::Role::kListBox) { + obj->SelectedOptions(options); + return; + } + } + } + + for (AXObject* obj = RawFirstChild(); obj; obj = obj->RawNextSibling()) { + if (obj->IsSelected() == kSelectedStateTrue) + options.push_back(obj); + } +} + void AXNodeObject::SelectionChanged() { // Post the selected text changed event on the first ancestor that's // focused (to handle form controls, ARIA text boxes and contentEditable),
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.h b/third_party/blink/renderer/modules/accessibility/ax_node_object.h index bbbd81e..71b6b907 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
@@ -198,6 +198,7 @@ bool NeedsToUpdateChildren() const override { return children_dirty_; } void SetNeedsToUpdateChildren() override { children_dirty_ = true; } void UpdateChildrenIfNecessary() override; + void SelectedOptions(AXObjectVector&) const override; // DOM and Render tree access. Element* ActionElement() const override;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index 8db9fc4..f472ebe 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -3116,6 +3116,19 @@ return role; } +bool AXObject::NameFromSelectedOption(bool recursive) const { + switch (RoleValue()) { + // Step 2E from: http://www.w3.org/TR/accname-aam-1.1 + case ax::mojom::Role::kComboBoxGrouping: + case ax::mojom::Role::kComboBoxMenuButton: + case ax::mojom::Role::kListBox: + case ax::mojom::Role::kPopUpButton: + return recursive; + default: + return false; + } +} + bool AXObject::NameFromContents(bool recursive) const { // ARIA 1.1, section 5.2.7.5. bool result = false;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h index 62d9830..b86749b1 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -855,6 +855,7 @@ virtual void DetachFromParent() { parent_ = nullptr; } virtual AXObject* ScrollBar(AccessibilityOrientation) { return nullptr; } virtual void AddAccessibleNodeChildren(); + virtual void SelectedOptions(AXObjectVector&) const {} // Properties of the object's owning document or page. virtual double EstimatedLoadingProgress() const { return 0; } @@ -1046,6 +1047,7 @@ bool CanReceiveAccessibilityFocus() const; bool NameFromContents(bool recursive) const; + bool NameFromSelectedOption(bool recursive) const; ax::mojom::Role ButtonRoleType() const;
diff --git a/third_party/blink/renderer/modules/event_target_modules_names.json5 b/third_party/blink/renderer/modules/event_target_modules_names.json5 index 433fd83..b1b6e85 100644 --- a/third_party/blink/renderer/modules/event_target_modules_names.json5 +++ b/third_party/blink/renderer/modules/event_target_modules_names.json5
@@ -31,6 +31,7 @@ "modules/notifications/Notification", "modules/payments/PaymentRequest", "modules/peerconnection/RTCIceTransport", + "modules/peerconnection/RTCQuicTransport", "modules/permissions/PermissionStatus", "modules/picture_in_picture/HTMLVideoElementPictureInPicture", "modules/picture_in_picture/PictureInPictureWindow",
diff --git a/third_party/blink/renderer/modules/peerconnection/BUILD.gn b/third_party/blink/renderer/modules/peerconnection/BUILD.gn index e2b32d4..4f543a3 100644 --- a/third_party/blink/renderer/modules/peerconnection/BUILD.gn +++ b/third_party/blink/renderer/modules/peerconnection/BUILD.gn
@@ -24,6 +24,10 @@ "adapters/p2p_quic_transport_factory_impl.h", "adapters/p2p_quic_transport_impl.cc", "adapters/p2p_quic_transport_impl.h", + "adapters/quic_transport_host.cc", + "adapters/quic_transport_host.h", + "adapters/quic_transport_proxy.cc", + "adapters/quic_transport_proxy.h", "adapters/web_rtc_cross_thread_copier.cc", "adapters/web_rtc_cross_thread_copier.h", "rtc_certificate.cc",
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter.h b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter.h index 33dc79d9..a07ea25d 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter.h
@@ -9,6 +9,8 @@ namespace blink { +class P2PQuicPacketTransport; + // Defines the ICE candidate policy the browser uses to surface the permitted // candidates to the application. // https://w3c.github.io/webrtc-pc/#dom-rtcicetransportpolicy @@ -70,6 +72,10 @@ // Adds a remote candidate to potentially start connectivity checks with. // The caller must ensure Start() has already bene called. virtual void AddRemoteCandidate(const cricket::Candidate& candidate) = 0; + + // Gets a P2PQuicPacketTransport that is backed by this ICE connection. The + // returned instance lives the same lifetime as the IceTransportAdapter. + virtual P2PQuicPacketTransport* packet_transport() const = 0; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.cc index 4806d9a..1fc096ec 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.cc +++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.cc
@@ -4,7 +4,80 @@ #include "third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_packet_transport.h" + namespace blink { +namespace { + +// Implementation of P2PQuicPacketTransport backed by a P2PTransportChannel. +class QuicPacketTransportAdapter : public P2PQuicPacketTransport, + public sigslot::has_slots<> { + public: + QuicPacketTransportAdapter( + cricket::P2PTransportChannel* p2p_transport_channel) + : p2p_transport_channel_(p2p_transport_channel) { + DCHECK(p2p_transport_channel_); + p2p_transport_channel_->SignalReadPacket.connect( + this, &QuicPacketTransportAdapter::OnReadPacket); + p2p_transport_channel_->SignalWritableState.connect( + this, &QuicPacketTransportAdapter::OnWritableState); + } + + ~QuicPacketTransportAdapter() override { + // Caller is responsible for unsetting the write observer and receive + // delegate before destroying this. + DCHECK(!write_observer_); + DCHECK(!receive_delegate_); + } + + int WritePacket(const QuicPacket& packet) override { + rtc::PacketOptions options; + options.packet_id = packet.packet_number; + int flags = 0; + return p2p_transport_channel_->SendPacket(packet.buffer, packet.buf_len, + options, flags); + } + + void SetReceiveDelegate(ReceiveDelegate* receive_delegate) override { + receive_delegate_ = receive_delegate; + } + + void SetWriteObserver(WriteObserver* write_observer) override { + write_observer_ = write_observer; + } + + bool Writable() override { return p2p_transport_channel_->writable(); } + + private: + // P2PTransportChannel callbacks. + void OnReadPacket(rtc::PacketTransportInternal* packet_transport, + const char* buffer, + size_t buffer_length, + const rtc::PacketTime& packet_time, + int flags) { + DCHECK_EQ(packet_transport, p2p_transport_channel_); + if (!receive_delegate_) { + // TODO(crbug.com/874296): Consider providing a small buffer. + return; + } + receive_delegate_->OnPacketDataReceived(buffer, buffer_length); + } + void OnWritableState(rtc::PacketTransportInternal* packet_transport) { + DCHECK_EQ(packet_transport, p2p_transport_channel_); + if (!write_observer_) { + return; + } + if (p2p_transport_channel_->writable()) { + write_observer_->OnCanWrite(); + } + } + + cricket::P2PTransportChannel* p2p_transport_channel_; + ReceiveDelegate* receive_delegate_ = nullptr; + WriteObserver* write_observer_ = nullptr; +}; + +} // namespace IceTransportAdapterImpl::IceTransportAdapterImpl( Delegate* delegate, @@ -38,6 +111,8 @@ // generated so that each peer can calculate a.tiebreaker <= b.tiebreaker // consistently. p2p_transport_channel_->SetIceTiebreaker(rtc::CreateRandomId64()); + quic_packet_transport_adapter_ = std::make_unique<QuicPacketTransportAdapter>( + p2p_transport_channel_.get()); } IceTransportAdapterImpl::~IceTransportAdapterImpl() = default; @@ -94,6 +169,10 @@ p2p_transport_channel_->AddRemoteCandidate(candidate); } +P2PQuicPacketTransport* IceTransportAdapterImpl::packet_transport() const { + return quic_packet_transport_adapter_.get(); +} + void IceTransportAdapterImpl::OnGatheringStateChanged( cricket::IceTransportInternal* transport) { DCHECK_EQ(transport, p2p_transport_channel_.get());
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.h b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.h index d022d87..52fed69 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.h
@@ -37,6 +37,7 @@ void HandleRemoteRestart( const cricket::IceParameters& new_remote_parameters) override; void AddRemoteCandidate(const cricket::Candidate& candidate) override; + P2PQuicPacketTransport* packet_transport() const override; private: // Callbacks from P2PTransportChannel. @@ -48,6 +49,7 @@ Delegate* const delegate_; std::unique_ptr<cricket::PortAllocator> port_allocator_; std::unique_ptr<cricket::P2PTransportChannel> p2p_transport_channel_; + std::unique_ptr<P2PQuicPacketTransport> quic_packet_transport_adapter_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.cc b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.cc index dc160b2..5db8163 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.cc +++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.cc
@@ -23,6 +23,7 @@ IceTransportHost::~IceTransportHost() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(!HasConsumer()); } void IceTransportHost::Initialize( @@ -62,6 +63,27 @@ } +bool IceTransportHost::HasConsumer() const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return consumer_host_; +} + +IceTransportAdapter* IceTransportHost::ConnectConsumer( + QuicTransportHost* consumer_host) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(consumer_host); + DCHECK(!consumer_host_); + consumer_host_ = consumer_host; + return transport_.get(); +} + +void IceTransportHost::DisconnectConsumer(QuicTransportHost* consumer_host) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(consumer_host); + DCHECK_EQ(consumer_host, consumer_host_); + consumer_host_ = nullptr; +} + void IceTransportHost::OnGatheringStateChanged( cricket::IceGatheringState new_state) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h index 0214738..08ac5458 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h
@@ -15,6 +15,7 @@ namespace blink { class IceTransportProxy; +class QuicTransportHost; // This class is the host side correspondent to the IceTransportProxy. See the // IceTransportProxy documentation for background. This class lives on the host @@ -58,6 +59,15 @@ void HandleRemoteRestart(const cricket::IceParameters& new_remote_parameters); void AddRemoteCandidate(const cricket::Candidate& candidate); + // A QuicTransportHost can be connected to this IceTransportHost. Only one can + // be connected at a time, and the caller must ensure that the consumer is + // disconnected before destroying the IceTransportHost. + // ConnectConsumer returns an implementation of IceTransportAdapter that + // should only be used on the host thread. + bool HasConsumer() const; + IceTransportAdapter* ConnectConsumer(QuicTransportHost* consumer_host); + void DisconnectConsumer(QuicTransportHost* consumer_host); + private: // IceTransportAdapter::Delegate overrides. void OnGatheringStateChanged(cricket::IceGatheringState new_state) override; @@ -67,6 +77,7 @@ const scoped_refptr<base::SingleThreadTaskRunner> proxy_thread_; std::unique_ptr<IceTransportAdapter> transport_; base::WeakPtr<IceTransportProxy> proxy_; + QuicTransportHost* consumer_host_ = nullptr; THREAD_CHECKER(thread_checker_); };
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.cc b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.cc index e8e9ecb..3ff6fd7 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.cc +++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.cc
@@ -17,7 +17,8 @@ scoped_refptr<base::SingleThreadTaskRunner> host_thread, Delegate* delegate, std::unique_ptr<IceTransportAdapterCrossThreadFactory> adapter_factory) - : host_thread_(std::move(host_thread)), + : proxy_thread_(std::move(proxy_thread)), + host_thread_(std::move(host_thread)), host_(nullptr, base::OnTaskRunnerDeleter(host_thread_)), delegate_(delegate), connection_handle_for_scheduler_( @@ -26,14 +27,14 @@ DCHECK(host_thread_); DCHECK(delegate_); DCHECK(adapter_factory); - DCHECK(proxy_thread->BelongsToCurrentThread()); + DCHECK(proxy_thread_->BelongsToCurrentThread()); adapter_factory->InitializeOnMainThread(); // Wait to initialize the host until the weak_ptr_factory_ is initialized. // The IceTransportHost is constructed on the proxy thread but should only be // interacted with via PostTask to the host thread. The OnTaskRunnerDeleter // (configured above) will ensure it gets deleted on the host thread. - host_.reset(new IceTransportHost(std::move(proxy_thread), - weak_ptr_factory_.GetWeakPtr())); + host_.reset( + new IceTransportHost(proxy_thread_, weak_ptr_factory_.GetWeakPtr())); PostCrossThreadTask(*host_thread_, FROM_HERE, CrossThreadBind(&IceTransportHost::Initialize, CrossThreadUnretained(host_.get()), @@ -42,9 +43,22 @@ IceTransportProxy::~IceTransportProxy() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(!HasConsumer()); // Note: The IceTransportHost will be deleted on the host thread. } +scoped_refptr<base::SingleThreadTaskRunner> IceTransportProxy::proxy_thread() + const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return proxy_thread_; +} + +scoped_refptr<base::SingleThreadTaskRunner> IceTransportProxy::host_thread() + const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return host_thread_; +} + void IceTransportProxy::StartGathering( const cricket::IceParameters& local_parameters, const cricket::ServerAddresses& stun_servers, @@ -88,6 +102,27 @@ CrossThreadUnretained(host_.get()), candidate)); } +bool IceTransportProxy::HasConsumer() const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return consumer_proxy_; +} + +IceTransportHost* IceTransportProxy::ConnectConsumer( + QuicTransportProxy* consumer_proxy) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(consumer_proxy); + DCHECK(!consumer_proxy_); + consumer_proxy_ = consumer_proxy; + return host_.get(); +} + +void IceTransportProxy::DisconnectConsumer(QuicTransportProxy* consumer_proxy) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(consumer_proxy); + DCHECK_EQ(consumer_proxy, consumer_proxy_); + consumer_proxy_ = nullptr; +} + void IceTransportProxy::OnGatheringStateChanged( cricket::IceGatheringState new_state) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.h b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.h index dfcab86..1b90fde 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.h
@@ -21,6 +21,7 @@ namespace blink { class IceTransportHost; +class QuicTransportProxy; // This class allows the ICE implementation (P2PTransportChannel) to run on a // thread different from the thread from which it is controlled. All @@ -63,6 +64,9 @@ std::unique_ptr<IceTransportAdapterCrossThreadFactory> adapter_factory); ~IceTransportProxy(); + scoped_refptr<base::SingleThreadTaskRunner> proxy_thread() const; + scoped_refptr<base::SingleThreadTaskRunner> host_thread() const; + // These methods are proxied to an IceTransportAdapter instance. void StartGathering( const cricket::IceParameters& local_parameters, @@ -75,6 +79,15 @@ void HandleRemoteRestart(const cricket::IceParameters& new_remote_parameters); void AddRemoteCandidate(const cricket::Candidate& candidate); + // A QuicTransportProxy can be connected to this IceTransportProxy. Only one + // can be connected at a time, and the caller must ensure that the consumer + // is disconnected before destroying the IceTransportProxy. + // ConnectConsumer returns an IceTransportHost that can be used to connect + // a QuicTransportHost. + bool HasConsumer() const; + IceTransportHost* ConnectConsumer(QuicTransportProxy* consumer_proxy); + void DisconnectConsumer(QuicTransportProxy* consumer_proxy); + private: // Callbacks from RTCIceTransportHost. friend class IceTransportHost; @@ -82,11 +95,13 @@ void OnCandidateGathered(const cricket::Candidate& candidate); void OnStateChanged(cricket::IceTransportState new_state); + const scoped_refptr<base::SingleThreadTaskRunner> proxy_thread_; const scoped_refptr<base::SingleThreadTaskRunner> host_thread_; // Since the Host is deleted on the host thread (via OnTaskRunnerDeleter), as // long as this is alive it is safe to post tasks to it (using unretained). std::unique_ptr<IceTransportHost, base::OnTaskRunnerDeleter> host_; Delegate* const delegate_; + QuicTransportProxy* consumer_proxy_ = nullptr; // This handle notifies scheduler about an active connection associated // with a frame. Handle should be destroyed when connection is closed.
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.cc index 0f1a76c..73e4c3a6 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.cc +++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.cc
@@ -37,8 +37,7 @@ // to get the packet numbers of QUIC packets we write. The QuicConnection // is created with a quic::QuicPacketWriter, so we can't set the connection // in the constructor. - void InitializeWithQuicConnection( - const quic::QuicConnection* const connection) { + void InitializeWithQuicConnection(quic::QuicConnection* connection) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(connection); if (packet_transport_->Writable()) { @@ -122,6 +121,7 @@ void OnCanWrite() override { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); SetWritable(); + connection_->OnCanWrite(); } private: @@ -129,7 +129,7 @@ // BlinkPacketWriter. P2PQuicPacketTransport* packet_transport_; // The QuicConnection owns this packet writer and will outlive it. - const quic::QuicConnection* connection_; + quic::QuicConnection* connection_; bool writable_ = false; THREAD_CHECKER(thread_checker_);
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.cc b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.cc new file mode 100644 index 0000000..a875a85 --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.cc
@@ -0,0 +1,91 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h" + +#include "net/quic/quic_chromium_alarm_factory.h" +#include "net/third_party/quic/platform/impl/quic_chromium_clock.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h" +#include "third_party/blink/renderer/platform/cross_thread_functional.h" +#include "third_party/blink/renderer/platform/web_task_runner.h" + +namespace blink { + +QuicTransportHost::QuicTransportHost( + scoped_refptr<base::SingleThreadTaskRunner> proxy_thread, + base::WeakPtr<QuicTransportProxy> proxy) + : proxy_thread_(std::move(proxy_thread)), proxy_(std::move(proxy)) { + DETACH_FROM_THREAD(thread_checker_); + DCHECK(proxy_thread_); + DCHECK(proxy_); +} + +QuicTransportHost::~QuicTransportHost() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + // If the TaskRunner this is getting initialized on is destroyed before + // Initialize is called then |ice_transport_host_| may still be null. + if (ice_transport_host_) { + ice_transport_host_->DisconnectConsumer(this); + } +} + +void QuicTransportHost::Initialize( + IceTransportHost* ice_transport_host, + scoped_refptr<base::SingleThreadTaskRunner> host_thread, + quic::Perspective perspective, + const std::vector<rtc::scoped_refptr<rtc::RTCCertificate>>& certificates) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(ice_transport_host); + DCHECK(!ice_transport_host_); + ice_transport_host_ = ice_transport_host; + quic::QuicClock* clock = quic::QuicChromiumClock::GetInstance(); + auto alarm_factory = + std::make_unique<net::QuicChromiumAlarmFactory>(host_thread.get(), clock); + quic_transport_factory_.reset( + new P2PQuicTransportFactoryImpl(clock, std::move(alarm_factory))); + P2PQuicTransportConfig config( + this, ice_transport_host->ConnectConsumer(this)->packet_transport(), + certificates); + config.is_server = (perspective == quic::Perspective::IS_SERVER); + quic_transport_ = + quic_transport_factory_->CreateQuicTransport(std::move(config)); +} + +void QuicTransportHost::Start( + std::vector<std::unique_ptr<rtc::SSLFingerprint>> remote_fingerprints) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + quic_transport_->Start(std::move(remote_fingerprints)); +} + +void QuicTransportHost::Stop() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + quic_transport_->Stop(); +} + +void QuicTransportHost::OnRemoteStopped() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + PostCrossThreadTask( + *proxy_thread_, FROM_HERE, + CrossThreadBind(&QuicTransportProxy::OnRemoteStopped, proxy_)); +} + +void QuicTransportHost::OnConnectionFailed(const std::string& error_details, + bool from_remote) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + PostCrossThreadTask(*proxy_thread_, FROM_HERE, + CrossThreadBind(&QuicTransportProxy::OnConnectionFailed, + proxy_, error_details, from_remote)); +} + +void QuicTransportHost::OnConnected() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + PostCrossThreadTask( + *proxy_thread_, FROM_HERE, + CrossThreadBind(&QuicTransportProxy::OnConnected, proxy_)); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h new file mode 100644 index 0000000..0558c95 --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h
@@ -0,0 +1,77 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_HOST_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_HOST_H_ + +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_checker.h" +#include "net/third_party/quic/core/quic_types.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" + +namespace blink { + +class IceTransportHost; +class P2PQuicTransportFactory; +class QuicTransportProxy; + +// The host class is the host side correspondent to the QuicTransportProxy. See +// the QuicTransportProxy documentation for background. This class lives on the +// host thread and proxies calls between the QuicTransportProxy and the +// P2PQuicTransport (which is single-threaded). +// +// proxy thread host thread +// +-----------------------+ +-----------------------------------+ +// | | | | +// | <-> ICE Proxy | =========> | ICE Host <-> P2PTransportChannel | +// | ^ | <--------- | ^ ^ | +// | client | | | | | | +// | v | | v v | +// | <-> QUIC Proxy | =========> | QUIC Host <-> P2PQuicTransport | +// | | <--------- | | +// +-----------------------+ +-----------------------------------+ +// +// The QuicTransportHost connects to the underlying IceTransportHost in +// Initialize and disconnects in the destructor. The IceTransportHost must +// outlive the QuicTransportHost. +// +// The Host can be constructed on any thread but after that point all methods +// must be called on the host thread. +class QuicTransportHost final : public P2PQuicTransport::Delegate { + public: + QuicTransportHost(scoped_refptr<base::SingleThreadTaskRunner> proxy_thread, + base::WeakPtr<QuicTransportProxy> transport_proxy); + ~QuicTransportHost() override; + + void Initialize( + IceTransportHost* ice_transport_host, + scoped_refptr<base::SingleThreadTaskRunner> host_thread, + quic::Perspective perspective, + const std::vector<rtc::scoped_refptr<rtc::RTCCertificate>>& certificates); + + void Start( + std::vector<std::unique_ptr<rtc::SSLFingerprint>> remote_fingerprints); + void Stop(); + + private: + // P2PQuicTransport::Delegate overrides. + void OnRemoteStopped() override; + void OnConnectionFailed(const std::string& error_details, + bool from_remote) override; + void OnConnected() override; + + const scoped_refptr<base::SingleThreadTaskRunner> proxy_thread_; + std::unique_ptr<P2PQuicTransportFactory> quic_transport_factory_; + std::unique_ptr<P2PQuicTransport> quic_transport_; + base::WeakPtr<QuicTransportProxy> proxy_; + IceTransportHost* ice_transport_host_ = nullptr; + + THREAD_CHECKER(thread_checker_); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_HOST_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.cc b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.cc new file mode 100644 index 0000000..815129d --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.cc
@@ -0,0 +1,104 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h" + +#include "third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h" +#include "third_party/blink/renderer/platform/cross_thread_functional.h" +#include "third_party/blink/renderer/platform/web_task_runner.h" + +namespace blink { + +QuicTransportProxy::QuicTransportProxy( + Delegate* delegate, + IceTransportProxy* ice_transport_proxy, + quic::Perspective perspective, + const std::vector<rtc::scoped_refptr<rtc::RTCCertificate>>& certificates) + : host_(nullptr, + base::OnTaskRunnerDeleter(ice_transport_proxy->host_thread())), + delegate_(delegate), + ice_transport_proxy_(ice_transport_proxy), + weak_ptr_factory_(this) { + DCHECK(delegate_); + DCHECK(ice_transport_proxy_); + scoped_refptr<base::SingleThreadTaskRunner> proxy_thread = + ice_transport_proxy->proxy_thread(); + DCHECK(proxy_thread->BelongsToCurrentThread()); + // Wait to initialize the host until the weak_ptr_factory_ is initialized. + // The QuicTransportHost is constructed on the proxy thread but should only be + // interacted with via PostTask to the host thread. The OnTaskRunnerDeleter + // (configured above) will ensure it gets deleted on the host thread. + host_.reset( + new QuicTransportHost(proxy_thread, weak_ptr_factory_.GetWeakPtr())); + // Connect to the IceTransportProxy. This gives us a reference to the + // underlying IceTransportHost that should be connected by the + // QuicTransportHost on the host thread. It is safe to post it unretained + // since the IceTransportHost's ownership is determined by the + // IceTransportProxy, and the IceTransportProxy is required to outlive this + // object. + IceTransportHost* ice_transport_host = + ice_transport_proxy->ConnectConsumer(this); + PostCrossThreadTask( + *host_thread(), FROM_HERE, + CrossThreadBind(&QuicTransportHost::Initialize, + CrossThreadUnretained(host_.get()), + CrossThreadUnretained(ice_transport_host), host_thread(), + perspective, certificates)); +} + +QuicTransportProxy::~QuicTransportProxy() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + ice_transport_proxy_->DisconnectConsumer(this); + // Note: The QuicTransportHost will be deleted on the host thread. +} + +scoped_refptr<base::SingleThreadTaskRunner> QuicTransportProxy::proxy_thread() + const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return ice_transport_proxy_->proxy_thread(); +} + +scoped_refptr<base::SingleThreadTaskRunner> QuicTransportProxy::host_thread() + const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return ice_transport_proxy_->host_thread(); +} + +void QuicTransportProxy::Start( + std::vector<std::unique_ptr<rtc::SSLFingerprint>> remote_fingerprints) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + PostCrossThreadTask( + *host_thread(), FROM_HERE, + CrossThreadBind(&QuicTransportHost::Start, + CrossThreadUnretained(host_.get()), + WTF::Passed(std::move(remote_fingerprints)))); +} + +void QuicTransportProxy::Stop() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + PostCrossThreadTask(*host_thread(), FROM_HERE, + CrossThreadBind(&QuicTransportHost::Stop, + CrossThreadUnretained(host_.get()))); +} + +void QuicTransportProxy::OnConnected() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + delegate_->OnConnected(); +} + +void QuicTransportProxy::OnRemoteStopped() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + delegate_->OnRemoteStopped(); +} + +void QuicTransportProxy::OnConnectionFailed(const std::string& error_details, + bool from_remote) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + delegate_->OnConnectionFailed(error_details, from_remote); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h new file mode 100644 index 0000000..3e158944 --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h
@@ -0,0 +1,96 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_PROXY_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_PROXY_H_ + +#include <vector> + +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_checker.h" +#include "net/third_party/quic/core/quic_types.h" +#include "third_party/webrtc/rtc_base/scoped_ref_ptr.h" + +namespace rtc { +class RTCCertificate; +struct SSLFingerprint; +} // namespace rtc + +namespace blink { + +class IceTransportProxy; +class QuicTransportHost; + +// This class allows the QUIC implementation (P2PQuicTransport) to run on a +// thread different from the thread from which it is controlled. All +// interactions with the QUIC implementation happen asynchronously. +// +// The QuicTransportProxy is intended to be used with an IceTransportProxy -- +// see the IceTransportProxy class documentation for background and terms. The +// proxy and host threads used with the QuicTransportProxy should be the same as +// the ones used with the connected IceTransportProxy. +class QuicTransportProxy final { + public: + // Delegate for receiving callbacks from the QUIC implementation. These all + // run on the proxy thread. + class Delegate { + public: + virtual ~Delegate() = default; + + // Called when the QUIC handshake finishes and fingerprints have been + // verified. + virtual void OnConnected() {} + // Called when the remote side has indicated it is closed. + virtual void OnRemoteStopped() {} + // Called when the connection is closed due to a QUIC error. This can happen + // locally by the framer or remotely by the peer. + virtual void OnConnectionFailed(const std::string& error_details, + bool from_remote) {} + }; + + // Construct a Proxy with the underlying QUIC implementation running on the + // same thread as the IceTransportProxy. Callbacks will be serviced by the + // given delegate. + // The delegate and IceTransportProxy must outlive the QuicTransportProxy. + // The QuicTransportProxy will immediately connect to the given + // IceTransportProxy; it can be disconnected by destroying the + // QuicTransportProxy object. + QuicTransportProxy( + Delegate* delegate, + IceTransportProxy* ice_transport_proxy, + quic::Perspective perspective, + const std::vector<rtc::scoped_refptr<rtc::RTCCertificate>>& certificates); + ~QuicTransportProxy(); + + scoped_refptr<base::SingleThreadTaskRunner> proxy_thread() const; + scoped_refptr<base::SingleThreadTaskRunner> host_thread() const; + + void Start( + std::vector<std::unique_ptr<rtc::SSLFingerprint>> remote_fingerprints); + void Stop(); + + private: + // Callbacks from QuicTransportHost. + friend class QuicTransportHost; + void OnConnected(); + void OnRemoteStopped(); + void OnConnectionFailed(const std::string& error_details, bool from_remote); + + // Since the Host is deleted on the host thread (Via OnTaskRunnerDeleter), as + // long as this is alive it is safe to post tasks to it (using unretained). + std::unique_ptr<QuicTransportHost, base::OnTaskRunnerDeleter> host_; + Delegate* const delegate_; + IceTransportProxy* ice_transport_proxy_; + + THREAD_CHECKER(thread_checker_); + + // Must be the last member. + base::WeakPtrFactory<QuicTransportProxy> weak_ptr_factory_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_PROXY_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_ice_transport_adapter.h b/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_ice_transport_adapter.h index 18e9f33a..f8eaaf75 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_ice_transport_adapter.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_ice_transport_adapter.h
@@ -27,6 +27,7 @@ const std::vector<cricket::Candidate>&)); MOCK_METHOD1(HandleRemoteRestart, void(const cricket::IceParameters&)); MOCK_METHOD1(AddRemoteCandidate, void(const cricket::Candidate&)); + MOCK_CONST_METHOD0(packet_transport, P2PQuicPacketTransport*()); }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h b/third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h index 09fe3bc..05b1cd5 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h
@@ -8,10 +8,12 @@ // This file defines specializations for the CrossThreadCopier that allow WebRTC // types to be passed across threads using their copy constructors. +#include <memory> #include <set> #include <vector> #include "third_party/blink/renderer/platform/cross_thread_copier.h" +#include "third_party/webrtc/rtc_base/scoped_ref_ptr.h" namespace cricket { class Candidate; @@ -20,12 +22,26 @@ } // namespace cricket namespace rtc { +class RTCCertificate; class SocketAddress; } namespace blink { template <> +struct CrossThreadCopier<std::string> + : public CrossThreadCopierPassThrough<std::string> { + STATIC_ONLY(CrossThreadCopier); +}; + +template <typename T, typename Allocator> +struct CrossThreadCopier<std::vector<std::unique_ptr<T>, Allocator>> { + STATIC_ONLY(CrossThreadCopier); + using Type = std::vector<std::unique_ptr<T>, Allocator>; + static Type Copy(Type vector) { return std::move(vector); } +}; + +template <> struct CrossThreadCopier<cricket::IceParameters> : public CrossThreadCopierPassThrough<cricket::IceParameters> { STATIC_ONLY(CrossThreadCopier); @@ -56,6 +72,13 @@ STATIC_ONLY(CrossThreadCopier); }; +template <> +struct CrossThreadCopier<std::vector<rtc::scoped_refptr<rtc::RTCCertificate>>> + : public CrossThreadCopierPassThrough< + std::vector<rtc::scoped_refptr<rtc::RTCCertificate>>> { + STATIC_ONLY(CrossThreadCopier); +}; + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_WEB_RTC_CROSS_THREAD_COPIER_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc index ca5ddef..6d9af12a 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc
@@ -20,6 +20,7 @@ #include "third_party/blink/renderer/modules/peerconnection/rtc_ice_server.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_event.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_event_init.h" +#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h" #include "third_party/webrtc/api/jsepicecandidate.h" #include "third_party/webrtc/api/peerconnectioninterface.h" #include "third_party/webrtc/p2p/base/portallocator.h" @@ -123,6 +124,29 @@ DCHECK(!proxy_); } +bool RTCIceTransport::HasConsumer() const { + return consumer_; +} + +IceTransportProxy* RTCIceTransport::ConnectConsumer( + RTCQuicTransport* consumer) { + DCHECK(consumer); + DCHECK(proxy_); + if (!consumer_) { + consumer_ = consumer; + } else { + DCHECK_EQ(consumer_, consumer); + } + return proxy_.get(); +} + +void RTCIceTransport::DisconnectConsumer(RTCQuicTransport* consumer) { + DCHECK(consumer); + DCHECK(proxy_); + DCHECK_EQ(consumer, consumer_); + consumer_ = nullptr; +} + String RTCIceTransport::role() const { switch (role_) { case cricket::ICEROLE_CONTROLLING: @@ -335,6 +359,9 @@ } proxy_->Start(ConvertIceParameters(remote_parameters), role, initial_remote_candidates); + if (consumer_) { + consumer_->OnTransportStarted(); + } } else { remote_candidates_.clear(); state_ = RTCIceTransportState::kNew; @@ -347,6 +374,11 @@ if (IsClosed()) { return; } + if (HasConsumer()) { + consumer_->stop(); + } + // Stopping the consumer should cause it to disconnect. + DCHECK(!HasConsumer()); state_ = RTCIceTransportState::kClosed; proxy_.reset(); } @@ -459,6 +491,7 @@ visitor->Trace(local_candidates_); visitor->Trace(remote_candidates_); visitor->Trace(selected_candidate_pair_); + visitor->Trace(consumer_); EventTargetWithInlineData::Trace(visitor); ContextLifecycleObserver::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h index 15276055..364b120 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h
@@ -20,6 +20,7 @@ class RTCIceCandidate; class RTCIceGatherOptions; class IceTransportAdapterCrossThreadFactory; +class RTCQuicTransport; enum class RTCIceTransportState { kNew, @@ -58,8 +59,26 @@ ~RTCIceTransport() override; + // Returns true if start() has been called. + bool IsStarted() const { return role_ != cricket::ICEROLE_UNKNOWN; } + + // Returns the role specified in start(). + cricket::IceRole GetRole() const { return role_; } + + // Returns true if the RTCIceTransport is in a terminal state. bool IsClosed() const { return state_ == RTCIceTransportState::kClosed; } + // An RTCQuicTransport can be connected to this RTCIceTransport. Only one can + // be connected at a time. The consumer will be automatically disconnected + // if stop() is called on this object. Otherwise, the RTCQuicTransport is + // responsible for disconnecting itself when it is done. + // ConnectConsumer returns an IceTransportProxy that can be used to connect + // a QuicTransportProxy. It may be called repeatedly with the same + // RTCQuicTransport. + bool HasConsumer() const; + IceTransportProxy* ConnectConsumer(RTCQuicTransport* consumer); + void DisconnectConsumer(RTCQuicTransport* consumer); + // rtc_ice_transport.idl String role() const; String state() const; @@ -125,6 +144,8 @@ base::Optional<RTCIceCandidatePair> selected_candidate_pair_; + Member<RTCQuicTransport> consumer_; + // Handle to the WebRTC ICE transport. Created when this binding is // constructed and deleted once network traffic should be stopped. std::unique_ptr<IceTransportProxy> proxy_;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc index 407a8bb..79d0957 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc
@@ -4,15 +4,19 @@ #include "third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h" +#include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/dom/events/event.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_certificate.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_parameters.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h" namespace blink { RTCQuicTransport* RTCQuicTransport::Create( + ExecutionContext* context, RTCIceTransport* transport, const HeapVector<Member<RTCCertificate>>& certificates, ExceptionState& exception_state) { @@ -22,6 +26,13 @@ "Cannot construct an RTCQuicTransport with a closed RTCIceTransport."); return nullptr; } + if (transport->HasConsumer()) { + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + "Cannot construct an RTCQuicTransport " + "with an RTCIceTransport that already " + "has a connected RTCQuicTransport."); + return nullptr; + } for (const auto& certificate : certificates) { if (certificate->expires() < ConvertSecondsToDOMTimeStamp(CurrentTime())) { exception_state.ThrowTypeError( @@ -29,16 +40,36 @@ return nullptr; } } - return new RTCQuicTransport(transport, certificates, exception_state); + return new RTCQuicTransport(context, transport, certificates, + exception_state); } RTCQuicTransport::RTCQuicTransport( + ExecutionContext* context, RTCIceTransport* transport, const HeapVector<Member<RTCCertificate>>& certificates, ExceptionState& exception_state) - : transport_(transport), certificates_(certificates) {} + : ContextLifecycleObserver(context), + transport_(transport), + certificates_(certificates) { + transport->ConnectConsumer(this); +} -RTCQuicTransport::~RTCQuicTransport() = default; +RTCQuicTransport::~RTCQuicTransport() { + DCHECK(!proxy_); +} + +void RTCQuicTransport::Close(RTCQuicTransportState new_state) { + DCHECK(!IsClosed()); + for (RTCQuicStream* stream : streams_) { + stream->Stop(); + } + streams_.clear(); + transport_->DisconnectConsumer(this); + proxy_.reset(); + state_ = new_state; + DCHECK(IsClosed()); +} RTCIceTransport* RTCQuicTransport::transport() const { return transport_; @@ -76,7 +107,7 @@ void RTCQuicTransport::getRemoteParameters( base::Optional<RTCQuicParameters>& result) const { - result = base::nullopt; + result = remote_parameters_; } const HeapVector<Member<RTCCertificate>>& RTCQuicTransport::getCertificates() @@ -89,12 +120,82 @@ return remote_certificates_; } -void RTCQuicTransport::stop() { - for (RTCQuicStream* stream : streams_) { - stream->Stop(); +static quic::Perspective QuicPerspectiveFromIceRole(cricket::IceRole ice_role) { + switch (ice_role) { + case cricket::ICEROLE_CONTROLLED: + return quic::Perspective::IS_CLIENT; + case cricket::ICEROLE_CONTROLLING: + return quic::Perspective::IS_SERVER; + default: + NOTREACHED(); } - streams_.clear(); - state_ = RTCQuicTransportState::kClosed; + return quic::Perspective::IS_CLIENT; +} + +void RTCQuicTransport::start(const RTCQuicParameters& remote_parameters, + ExceptionState& exception_state) { + if (RaiseExceptionIfClosed(exception_state)) { + return; + } + if (remote_parameters_) { + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + "Cannot start() multiple times."); + return; + } + remote_parameters_ = remote_parameters; + if (transport_->IsStarted()) { + StartConnection(); + } +} + +static std::unique_ptr<rtc::SSLFingerprint> RTCDtlsFingerprintToSSLFingerprint( + const RTCDtlsFingerprint& dtls_fingerprint) { + std::string algorithm = WebString(dtls_fingerprint.algorithm()).Utf8(); + std::string value = WebString(dtls_fingerprint.value()).Utf8(); + std::unique_ptr<rtc::SSLFingerprint> rtc_fingerprint( + rtc::SSLFingerprint::CreateFromRfc4572(algorithm, value)); + DCHECK(rtc_fingerprint); + return rtc_fingerprint; +} + +void RTCQuicTransport::StartConnection() { + DCHECK_EQ(state_, RTCQuicTransportState::kNew); + DCHECK(remote_parameters_); + + state_ = RTCQuicTransportState::kConnecting; + + std::vector<rtc::scoped_refptr<rtc::RTCCertificate>> rtc_certificates; + for (const auto& certificate : certificates_) { + rtc_certificates.push_back(certificate->Certificate()); + } + IceTransportProxy* transport_proxy = transport_->ConnectConsumer(this); + proxy_.reset(new QuicTransportProxy( + this, transport_proxy, QuicPerspectiveFromIceRole(transport_->GetRole()), + rtc_certificates)); + + std::vector<std::unique_ptr<rtc::SSLFingerprint>> rtc_fingerprints; + for (const RTCDtlsFingerprint& fingerprint : + remote_parameters_->fingerprints()) { + rtc_fingerprints.push_back(RTCDtlsFingerprintToSSLFingerprint(fingerprint)); + } + proxy_->Start(std::move(rtc_fingerprints)); +} + +void RTCQuicTransport::OnTransportStarted() { + // The RTCIceTransport has now been started. + if (remote_parameters_) { + StartConnection(); + } +} + +void RTCQuicTransport::stop() { + if (IsClosed()) { + return; + } + if (proxy_) { + proxy_->Stop(); + } + Close(RTCQuicTransportState::kClosed); } RTCQuicStream* RTCQuicTransport::createStream(ExceptionState& exception_state) { @@ -106,6 +207,22 @@ return stream; } +void RTCQuicTransport::OnConnected() { + state_ = RTCQuicTransportState::kConnected; + DispatchEvent(*Event::Create(EventTypeNames::statechange)); +} + +void RTCQuicTransport::OnConnectionFailed(const std::string& error_details, + bool from_remote) { + Close(RTCQuicTransportState::kFailed); + DispatchEvent(*Event::Create(EventTypeNames::statechange)); +} + +void RTCQuicTransport::OnRemoteStopped() { + Close(RTCQuicTransportState::kClosed); + DispatchEvent(*Event::Create(EventTypeNames::statechange)); +} + bool RTCQuicTransport::RaiseExceptionIfClosed( ExceptionState& exception_state) const { if (IsClosed()) { @@ -117,12 +234,30 @@ return false; } +const AtomicString& RTCQuicTransport::InterfaceName() const { + return EventTargetNames::RTCQuicTransport; +} + +ExecutionContext* RTCQuicTransport::GetExecutionContext() const { + return ContextLifecycleObserver::GetExecutionContext(); +} + +void RTCQuicTransport::ContextDestroyed(ExecutionContext*) { + stop(); +} + +bool RTCQuicTransport::HasPendingActivity() const { + return static_cast<bool>(proxy_); +} + void RTCQuicTransport::Trace(blink::Visitor* visitor) { visitor->Trace(transport_); visitor->Trace(certificates_); visitor->Trace(remote_certificates_); + visitor->Trace(remote_parameters_); visitor->Trace(streams_); - ScriptWrappable::Trace(visitor); + EventTargetWithInlineData::Trace(visitor); + ContextLifecycleObserver::Trace(visitor); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h index 161dd63c8..d734457 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h
@@ -5,8 +5,11 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_TRANSPORT_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_TRANSPORT_H_ +#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" +#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h" +#include "third_party/blink/renderer/modules/event_target_modules.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_quic_parameters.h" -#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" namespace blink { @@ -14,7 +17,6 @@ class ExceptionState; class RTCCertificate; class RTCIceTransport; -class RTCQuicParameters; class RTCQuicStream; enum class RTCQuicTransportState { @@ -25,11 +27,17 @@ kFailed }; -class MODULES_EXPORT RTCQuicTransport final : public ScriptWrappable { +class MODULES_EXPORT RTCQuicTransport final + : public EventTargetWithInlineData, + public ActiveScriptWrappable<RTCQuicTransport>, + public ContextLifecycleObserver, + public QuicTransportProxy::Delegate { DEFINE_WRAPPERTYPEINFO(); + USING_GARBAGE_COLLECTED_MIXIN(RTCQuicTransport); public: static RTCQuicTransport* Create( + ExecutionContext* context, RTCIceTransport* transport, const HeapVector<Member<RTCCertificate>>& certificates, ExceptionState& exception_state); @@ -43,24 +51,57 @@ void getRemoteParameters(base::Optional<RTCQuicParameters>& result) const; const HeapVector<Member<RTCCertificate>>& getCertificates() const; const HeapVector<Member<DOMArrayBuffer>>& getRemoteCertificates() const; + void start(const RTCQuicParameters& remote_parameters, + ExceptionState& exception_state); void stop(); RTCQuicStream* createStream(ExceptionState& exception_state); + DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange); + DEFINE_ATTRIBUTE_EVENT_LISTENER(error); + + // Called by the RTCIceTransport when its start() method is called. + void OnTransportStarted(); + + // EventTarget overrides. + const AtomicString& InterfaceName() const override; + ExecutionContext* GetExecutionContext() const override; + + // ContextLifecycleObserver overrides. + void ContextDestroyed(ExecutionContext*) override; + + // ActiveScriptWrappable overrides. + bool HasPendingActivity() const override; // For garbage collection. void Trace(blink::Visitor* visitor) override; private: - RTCQuicTransport(RTCIceTransport* transport, + RTCQuicTransport(ExecutionContext* context, + RTCIceTransport* transport, const HeapVector<Member<RTCCertificate>>& certificates, ExceptionState& exception_state); + // QuicTransportProxy::Delegate overrides; + void OnConnected() override; + void OnConnectionFailed(const std::string& error_details, + bool from_remote) override; + void OnRemoteStopped() override; + bool IsClosed() const { return state_ == RTCQuicTransportState::kClosed; } bool RaiseExceptionIfClosed(ExceptionState& exception_state) const; + // Starts the underlying QUIC connection. + void StartConnection(); + + // Close all streams, delete the underlying QUIC transport, and transition to + // the given state, closed or failed. + void Close(RTCQuicTransportState new_state); + Member<RTCIceTransport> transport_; RTCQuicTransportState state_ = RTCQuicTransportState::kNew; HeapVector<Member<RTCCertificate>> certificates_; HeapVector<Member<DOMArrayBuffer>> remote_certificates_; + base::Optional<RTCQuicParameters> remote_parameters_; + std::unique_ptr<QuicTransportProxy> proxy_; HeapHashSet<Member<RTCQuicStream>> streams_; };
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.idl b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.idl index df34813..6118b67 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.idl
@@ -13,18 +13,23 @@ // https://w3c.github.io/webrtc-quic/#quic-transport* [ + ActiveScriptWrappable, Constructor(RTCIceTransport transport, sequence<RTCCertificate> certificates), + ConstructorCallWith=ExecutionContext, RaisesException=Constructor, Exposed=Window, RuntimeEnabled=RTCQuicTransport -] interface RTCQuicTransport { +] interface RTCQuicTransport : EventTarget { readonly attribute RTCIceTransport transport; readonly attribute RTCQuicTransportState state; RTCQuicParameters getLocalParameters(); RTCQuicParameters? getRemoteParameters(); sequence<RTCCertificate> getCertificates(); sequence<ArrayBuffer> getRemoteCertificates(); + [RaisesException] void start(RTCQuicParameters remoteParameters); void stop(); [RaisesException, RuntimeEnabled=RTCQuicStream] RTCQuicStream createStream(); - // TODO(crbug.com/868068): Implement remaining control methods + events. + attribute EventHandler onstatechange; + attribute EventHandler onerror; + // TODO(crbug.com/868068): Implement onstream. };
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis.cc b/third_party/blink/renderer/modules/speech/speech_synthesis.cc index d07e54d5..31defe4 100644 --- a/third_party/blink/renderer/modules/speech/speech_synthesis.cc +++ b/third_party/blink/renderer/modules/speech/speech_synthesis.cc
@@ -113,10 +113,6 @@ if (!document) return; - // If SpeechSynthesis followed autoplay policy, we could simply fire an error - // here and ignore this utterance. For now, just log some UseCounters to - // evaluate potential breakage. - // // Note: Non-UseCounter based TTS metrics are of the form TextToSpeech.* and // are generally global, whereas these are scoped to a single page load. UseCounter::Count(document, WebFeature::kTextToSpeech_Speak); @@ -125,6 +121,8 @@ if (!IsAllowedToStartByAutoplay()) { Deprecation::CountDeprecation( document, WebFeature::kTextToSpeech_SpeakDisallowedByAutoplay); + FireErrorEvent(utterance, 0 /* char_index */, "not-allowed"); + return; } utterance_queue_.push_back(utterance);
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.h b/third_party/blink/renderer/modules/webaudio/audio_context.h index 4b8f8789..2c93de4 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_context.h +++ b/third_party/blink/renderer/modules/webaudio/audio_context.h
@@ -42,7 +42,7 @@ bool IsContextClosed() const final; ScriptPromise suspendContext(ScriptState*); - ScriptPromise resumeContext(ScriptState*) final; + ScriptPromise resumeContext(ScriptState*); bool HasRealtimeConstraint() final { return true; }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.idl b/third_party/blink/renderer/modules/webaudio/audio_context.idl index 2983635f..cd64c27 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_context.idl +++ b/third_party/blink/renderer/modules/webaudio/audio_context.idl
@@ -40,6 +40,7 @@ ] interface AudioContext : BaseAudioContext { [MeasureAs=AudioContextSuspend, CallWith=ScriptState, ImplementedAs=suspendContext] Promise<void> suspend(); [MeasureAs=AudioContextClose, CallWith=ScriptState, ImplementedAs=closeContext] Promise<void> close(); + [MeasureAs=AudioContextResume, CallWith=ScriptState, ImplementedAs=resumeContext] Promise<void> resume(); // Output timestamp [MeasureAs=AudioContextGetOutputTimestamp, CallWith=ScriptState] AudioTimestamp getOutputTimestamp();
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param.cc b/third_party/blink/renderer/modules/webaudio/audio_param.cc index eb6008313..24f4820 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_param.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_param.cc
@@ -52,7 +52,9 @@ automation_rate_(rate), rate_mode_(rate_mode), min_value_(min_value), - max_value_(max_value) { + max_value_(max_value), + summing_bus_( + AudioBus::Create(1, AudioUtilities::kRenderQuantumFrames, false)) { // The destination MUST exist because we need the destination handler for the // AudioParam. CHECK(context.destination()); @@ -258,23 +260,25 @@ SetIntrinsicValue(value); } - // Now sum all of the audio-rate connections together (unity-gain summing - // junction). Note that connections would normally be mono, but we mix down - // to mono if necessary. - scoped_refptr<AudioBus> summing_bus = - AudioBus::Create(1, number_of_values, false); - summing_bus->SetChannelMemory(0, values, number_of_values); + // If there are any connections, sum all of the audio-rate connections + // together (unity-gain summing junction). Note that connections would + // normally be mono, but we mix down to mono if necessary. + if (NumberOfRenderingConnections() > 0) { + DCHECK_LE(number_of_values, AudioUtilities::kRenderQuantumFrames); - for (unsigned i = 0; i < NumberOfRenderingConnections(); ++i) { - AudioNodeOutput* output = RenderingOutput(i); - DCHECK(output); + summing_bus_->SetChannelMemory(0, values, number_of_values); - // Render audio from this output. - AudioBus* connection_bus = - output->Pull(nullptr, AudioUtilities::kRenderQuantumFrames); + for (unsigned i = 0; i < NumberOfRenderingConnections(); ++i) { + AudioNodeOutput* output = RenderingOutput(i); + DCHECK(output); - // Sum, with unity-gain. - summing_bus->SumFrom(*connection_bus); + // Render audio from this output. + AudioBus* connection_bus = + output->Pull(nullptr, AudioUtilities::kRenderQuantumFrames); + + // Sum, with unity-gain. + summing_bus_->SumFrom(*connection_bus); + } } }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param.h b/third_party/blink/renderer/modules/webaudio/audio_param.h index 1dfb251..eca5b58 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_param.h +++ b/third_party/blink/renderer/modules/webaudio/audio_param.h
@@ -248,6 +248,9 @@ // The destination node used to get necessary information like the smaple rate // and context time. scoped_refptr<AudioDestinationHandler> destination_handler_; + + // Audio bus to sum in any connections to the AudioParam. + scoped_refptr<AudioBus> summing_bus_; }; // AudioParam class represents web-exposed AudioParam interface.
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc index 5a3c163..139b8c5 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
@@ -33,6 +33,7 @@ #include "third_party/blink/renderer/core/frame/deprecation.h" #include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/platform/audio/audio_utilities.h" +#include "third_party/blink/renderer/platform/audio/vector_math.h" #include "third_party/blink/renderer/platform/bindings/exception_messages.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/wtf/cpu.h" @@ -853,8 +854,8 @@ number_of_values, sample_rate, control_rate); // Clamp the values now to the nominal range - for (unsigned k = 0; k < number_of_values; ++k) - values[k] = clampTo(values[k], min_value, max_value); + VectorMath::Vclip(values, 1, &min_value, &max_value, values, 1, + number_of_values); return last_value; }
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.h b/third_party/blink/renderer/modules/webaudio/base_audio_context.h index 33ab9aea0..7ce3971 100644 --- a/third_party/blink/renderer/modules/webaudio/base_audio_context.h +++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.h
@@ -220,9 +220,6 @@ const PeriodicWaveConstraints&, ExceptionState&); - // Resume - virtual ScriptPromise resumeContext(ScriptState*) = 0; - // IIRFilter IIRFilterNode* createIIRFilter(Vector<double> feedforward_coef, Vector<double> feedback_coef,
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.idl b/third_party/blink/renderer/modules/webaudio/base_audio_context.idl index 6bed5699..00b7009 100644 --- a/third_party/blink/renderer/modules/webaudio/base_audio_context.idl +++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.idl
@@ -61,9 +61,6 @@ [RaisesException, MeasureAs=AudioContextCreateChannelSplitter] ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs); [RaisesException, MeasureAs=AudioContextCreateChannelMerger] ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs); - // Pause/resume - [MeasureAs=AudioContextResume, CallWith=ScriptState, ImplementedAs=resumeContext] Promise<void> resume(); - // TODO(rtoy): These really belong to the AudioContext, but we need them // here so we can use an offline audio context to test these. [RaisesException, MeasureAs=AudioContextCreateMediaElementSource] MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement);
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_context.h b/third_party/blink/renderer/modules/webaudio/offline_audio_context.h index 12d81a75..17e4789 100644 --- a/third_party/blink/renderer/modules/webaudio/offline_audio_context.h +++ b/third_party/blink/renderer/modules/webaudio/offline_audio_context.h
@@ -59,7 +59,7 @@ ScriptPromise startOfflineRendering(ScriptState*); ScriptPromise suspendContext(ScriptState*, double); - ScriptPromise resumeContext(ScriptState*) final; + ScriptPromise resumeContext(ScriptState*); void RejectPendingResolvers() override;
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_context.idl b/third_party/blink/renderer/modules/webaudio/offline_audio_context.idl index 92d713d..3c57739 100644 --- a/third_party/blink/renderer/modules/webaudio/offline_audio_context.idl +++ b/third_party/blink/renderer/modules/webaudio/offline_audio_context.idl
@@ -36,4 +36,5 @@ readonly attribute unsigned long length; [CallWith=ScriptState, ImplementedAs=startOfflineRendering, MeasureAs=OfflineAudioContextStartRendering] Promise<AudioBuffer> startRendering(); [CallWith=ScriptState, ImplementedAs=suspendContext, MeasureAs=OfflineAudioContextSuspend] Promise<void> suspend(double suspendTime); + [MeasureAs=OfflineAudioContextResume, CallWith=ScriptState, ImplementedAs=resumeContext] Promise<void> resume(); };
diff --git a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.cc b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.cc index 95c99cf..b0a1d90 100644 --- a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.cc +++ b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.cc
@@ -4,39 +4,35 @@ #include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.h" +#include "base/memory/ptr_util.h" #include "services/service_manager/public/cpp/interface_provider.h" namespace blink { // static -FrameResourceCoordinator* FrameResourceCoordinator::Create( +std::unique_ptr<FrameResourceCoordinator> FrameResourceCoordinator::Create( service_manager::InterfaceProvider* interface_provider) { - return new FrameResourceCoordinator(interface_provider); + return base::WrapUnique(new FrameResourceCoordinator(interface_provider)); } FrameResourceCoordinator::FrameResourceCoordinator( service_manager::InterfaceProvider* interface_provider) { interface_provider->GetInterface(mojo::MakeRequest(&service_)); + DCHECK(service_); } FrameResourceCoordinator::~FrameResourceCoordinator() = default; void FrameResourceCoordinator::SetNetworkAlmostIdle(bool idle) { - if (!service_) - return; service_->SetNetworkAlmostIdle(idle); } void FrameResourceCoordinator::SetLifecycleState( resource_coordinator::mojom::LifecycleState state) { - if (!service_) - return; service_->SetLifecycleState(state); } void FrameResourceCoordinator::OnNonPersistentNotificationCreated() { - if (!service_) - return; service_->OnNonPersistentNotificationCreated(); }
diff --git a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.h b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.h index a801a489..600558ad 100644 --- a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.h +++ b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.h
@@ -19,7 +19,8 @@ WTF_MAKE_NONCOPYABLE(FrameResourceCoordinator); public: - static FrameResourceCoordinator* Create(service_manager::InterfaceProvider*); + static std::unique_ptr<FrameResourceCoordinator> Create( + service_manager::InterfaceProvider*); ~FrameResourceCoordinator(); void SetNetworkAlmostIdle(bool);
diff --git a/third_party/blink/tools/audit_non_blink_usage.py b/third_party/blink/tools/audit_non_blink_usage.py index 5fd0abd3..21957b83 100755 --- a/third_party/blink/tools/audit_non_blink_usage.py +++ b/third_party/blink/tools/audit_non_blink_usage.py
@@ -52,6 +52,7 @@ 'base::Time', 'base::TimeDelta', 'base::TimeTicks', + 'base::ThreadTicks', 'base::UnguessableToken', 'base::UnsafeSharedMemoryRegion', 'base::WeakPtr',
diff --git a/third_party/metrics_proto/README.chromium b/third_party/metrics_proto/README.chromium index 647f8db1..7052708 100644 --- a/third_party/metrics_proto/README.chromium +++ b/third_party/metrics_proto/README.chromium
@@ -1,8 +1,8 @@ Name: Metrics Protos Short Name: metrics_proto URL: This is the canonical public repository -Version: 213863997 -Date: 2018/09/20 UTC +Version: 214990311 +Date: 2018/09/28 UTC License: BSD Security Critical: Yes
diff --git a/third_party/metrics_proto/cast_logs.proto b/third_party/metrics_proto/cast_logs.proto index 646c5d7f4..923f40d7 100644 --- a/third_party/metrics_proto/cast_logs.proto +++ b/third_party/metrics_proto/cast_logs.proto
@@ -163,7 +163,7 @@ repeated CastConnectionInfo cast_connection_info = 2; // Stores Cast-enabled device specific events with a various context data. - // Next tag: 20 + // Next tag: 21 message CastEventProto { // The name of the action, hashed by same logic used to hash user action // event and histogram. @@ -209,7 +209,7 @@ optional string aogh_request_id = 16; - optional int64 aogh_local_agent_id = 18; + optional int64 aogh_local_device_id = 18; // Optional value associated with the event. For example, may be used for // error codes. @@ -224,6 +224,9 @@ // Optional value associated with timezone update event. optional string timezone_id = 17; + + // Optional value to log ui version. + optional string ui_version = 20; } repeated CastEventProto cast_event = 3; @@ -232,7 +235,7 @@ optional fixed32 virtual_release_track = 4; // Cast specific device information which is expected to change over time. - // Next tag: 8 + // Next tag: 9 message CastDeviceMutableInfo { // This is the last type of reboot the device encountered // Next tag: 11 @@ -277,6 +280,8 @@ // Current timezone which the device is using. optional string timezone_id = 7; + // Optional value to log latest ui version. + optional string latest_ui_version = 8; } // The device sends this information at least once per day. optional CastDeviceMutableInfo cast_device_mutable_info = 5;
diff --git a/third_party/node/node_modules.tar.gz.sha1 b/third_party/node/node_modules.tar.gz.sha1 index 1e717c2..d02c819 100644 --- a/third_party/node/node_modules.tar.gz.sha1 +++ b/third_party/node/node_modules.tar.gz.sha1
@@ -1 +1 @@ -5c652ddf2cbeb69d43b46a051108949f13a9644b +dc855853e383fc88c56845f772c259f25a3ed045
diff --git a/third_party/node/package.json b/third_party/node/package.json index bc3c103..5168b61 100644 --- a/third_party/node/package.json +++ b/third_party/node/package.json
@@ -6,7 +6,7 @@ "crisper": "2.1.1", "eslint": "3.19.0", "polymer-bundler": "3.1.1", - "polymer-css-build": "0.3.2", + "polymer-css-build": "0.3.3", "uglify-es": "3.0.15" } }
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 8cc40b9..ccbe47ec 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -124,6 +124,7 @@ 'ToTAndroidASan': 'android_clang_tot_asan', 'ToTAndroid (dbg)': 'android_clang_tot_dbg', 'ToTAndroidCFI': 'android_clang_tot_cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on', + 'ToTAndroidOfficial': 'android_clang_tot_release_minimal_symbols_official', 'ToTAndroid64': 'android_clang_tot_release_arm64', 'ToTAndroid x64': 'android_clang_tot_x64', 'ToTLinux': 'clang_tot_linux_full_symbols_shared_release', @@ -781,6 +782,16 @@ 'android_without_codecs', 'clang_tot', 'release', 'arm64', ], + 'android_clang_tot_release_minimal_symbols': [ + 'android', 'release', 'static', 'minimal_symbols', + 'strip_debug_info', 'clang_tot', + ], + + 'android_clang_tot_release_minimal_symbols_official': [ + 'android', 'release', 'static', 'minimal_symbols', 'official', + 'clang_tot', + ], + 'android_clang_tot_x64': [ 'android_without_codecs', 'clang_tot', 'shared', 'x64', 'release', 'dcheck_always_on', @@ -911,11 +922,6 @@ 'strip_debug_info', ], - 'android_clang_tot_release_minimal_symbols': [ - 'android', 'release', 'static', 'minimal_symbols', - 'strip_debug_info', 'clang_tot', - ], - 'android_release_bot_minimal_symbols_arm64': [ 'android', 'release_bot', 'minimal_symbols', 'arm64', 'strip_debug_info',
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index f6f891d2..35c129a 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -4571,6 +4571,11 @@ <int value="1" label="Has slow paths with non-AA paint"/> </enum> +<enum name="BooleanHasWithheldHosts"> + <int value="0" label="Does not have withheld hosts"/> + <int value="1" label="Has withheld hosts"/> +</enum> + <enum name="BooleanHiddenPresentationalAutofilled"> <int value="0" label="Skipped"/> <int value="1" label="Autofilled"/> @@ -28542,6 +28547,8 @@ <int value="-1937077699" label="http-form-warning"/> <int value="-1934661084" label="ForceUnifiedConsentBump:disabled"/> <int value="-1933425042" label="OfflinePreviews:enabled"/> + <int value="-1932379839" + label="OmniboxUIExperimentHideSteadyStateUrlTrivialSubdomains:enabled"/> <int value="-1930720286" label="nacl-debug-mask"/> <int value="-1928198763" label="enable-async-dns"/> <int value="-1925117279" label="disable-quic-https"/> @@ -28944,6 +28951,8 @@ <int value="-1224962996" label="PwaImprovedSplashScreen:disabled"/> <int value="-1222805155" label="PdfIsolation:enabled"/> <int value="-1218608640" label="disable-offline-load-stale-cache"/> + <int value="-1217462552" + label="OmniboxUIExperimentHideSteadyStateUrlTrivialSubdomains:disabled"/> <int value="-1217425153" label="ChromeHomeClearUrlOnOpen:enabled"/> <int value="-1216837777" label="clear-data-reduction-proxy-data-savings"/> <int value="-1214870820" label="EnableNewStyleLauncher:enabled"/> @@ -29089,6 +29098,8 @@ <int value="-949178861" label="enable-new-avatar-menu"/> <int value="-945806012" label="DownloadsUi:enabled"/> <int value="-938178614" label="enable-suggestions-with-substring-match"/> + <int value="-933377608" + label="OmniboxUIExperimentHideSteadyStateUrlScheme:enabled"/> <int value="-933316841" label="enable-permissions-blacklist"/> <int value="-928138978" label="IPH_DemoMode:disabled"/> <int value="-926422468" label="disable-embedded-shared-worker"/> @@ -29620,6 +29631,8 @@ <int value="125581289" label="WebRtcHWVP8Encoding:disabled"/> <int value="125934378" label="enable-password-link"/> <int value="131881947" label="D3DVsync:enabled"/> + <int value="132560299" + label="OmniboxUIExperimentHideSteadyStateUrlScheme:disabled"/> <int value="133482330" label="AppNotificationStatusMessaging:enabled"/> <int value="143725809" label="DownloadProgressInfoBar:enabled"/> <int value="147342055" label="ChromeHomeClearUrlOnOpen:disabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 1db9907..be7def44 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -7741,6 +7741,16 @@ </summary> </histogram> +<histogram name="Autofill.UploadEvent" enum="BooleanSent"> +<!-- Name completed by histogram_suffixes name="AutofillUploadEvents" --> + + <owner>rogerm@chromium.org</owner> + <summary> + Whether or not an upload was sent after having been triggered by a form + submission or proxy-form-submission. + </summary> +</histogram> + <histogram name="Autofill.UploadOfferedCardOrigin" enum="UploadOfferedCardOrigin"> <owner>jsaul@google.com</owner> @@ -31334,6 +31344,33 @@ </summary> </histogram> +<histogram name="Extensions.RuntimeHostPermissions.ExtensionHasWithheldHosts" + enum="BooleanHasWithheldHosts" expires_after="2019-11-30"> + <owner>rdevlin.cronin@chromium.org</owner> + <owner>karandeepb@chromium.org</owner> + <summary> + Whether an extension had host permissions withheld as a result of the + RuntimeHostPermissions feature. Recorded once per extension at profile + initialization if and only if the RuntimeHostPermissions feature is enabled + and the extension requests any host permissions (i.e., could be affected by + the feature). + </summary> +</histogram> + +<histogram name="Extensions.RuntimeHostPermissions.GrantedHostCount" + units="Granted hosts" expires_after="2019-11-30"> + <owner>rdevlin.cronin@chromium.org</owner> + <owner>karandeepb@chromium.org</owner> + <summary> + The number of hosts an extension has been granted explicit access to that it + also requested (note that if the user granted unrequested hosts, those will + not be included in this count). Recorded once per extension at profile + initialization if and only if the RuntimeHostPermissions feature is enabled + and the extension has had host permissions withheld. See also + Extensions.RuntimeHostPermissions.ExtensionHasWithheldHosts. + </summary> +</histogram> + <histogram name="Extensions.SandboxUnpackFailure"> <owner>asargent@chromium.org</owner> <summary> @@ -48063,6 +48100,16 @@ </summary> </histogram> +<histogram name="MobileDownload.CancelledDownloadRemovedFromHistory" + units="downloads" expires_after="M72"> + <owner>qinmin@chromium.org</owner> + <owner>dtrainor@chromium.org</owner> + <summary> + Android: Records the number of cancelled download that are cleaned up from + the history, after loading all the downloads from the history DB on startup. + </summary> +</histogram> + <histogram name="MobileDownload.CancelReason" enum="MobileDownloadCancelReason"> <owner>qinmin@chromium.org</owner> <summary>Android: Records the reason that a download is canceled.</summary> @@ -71090,6 +71137,16 @@ </summary> </histogram> +<histogram + name="PageLoad.Internal.PaintTiming.NavigationToFirstContentfulPaint.InitiatingProcess" + enum="ProcessType2" expires_after="2018-12-31"> + <owner>sullivan@chromium.org</owner> + <summary> + Breakdown of NavigationToFirstContentfulPaint counts by process that + initiated the navigation (this will only be renderer or browser). + </summary> +</histogram> + <histogram name="PageLoad.Internal.Prerender" enum="BooleanHit"> <owner>bmcquade@chromium.org</owner> <summary> @@ -121099,6 +121156,18 @@ <affected-histogram name="Autofill.UnmaskPrompt.Duration"/> </histogram_suffixes> +<histogram_suffixes name="AutofillUploadEvents" separator="."> + <suffix name="DomMutationAfterXhr" label="DOM Mutation After XHR"/> + <suffix name="FormSubmission" label="Form Submission"/> + <suffix name="FrameDetached" label="Frame Detached"/> + <suffix name="None" label="None"/> + <suffix name="ProbablyFormSubmitted" label="Probable Form Submission"/> + <suffix name="SameDocumentNavigation" label="Same Document Navigation"/> + <suffix name="Unknown" label="Unknown"/> + <suffix name="XhrSucceeded" label="XHR Succeeded"/> + <affected-histogram name="Autofill.UploadEvent"/> +</histogram_suffixes> + <histogram_suffixes name="BackgroundFetchDatabaseStorageErrors" separator="."> <suffix name="CleanupTask" label="CleanupTask"/> <suffix name="CreateMetadataTask" label="CreateMetadata DatabaseTask"/>
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn index 782b7e7..085e5d6 100644 --- a/ui/accessibility/BUILD.gn +++ b/ui/accessibility/BUILD.gn
@@ -206,6 +206,7 @@ "mojom/ax_event_mojom_traits_unittest.cc", "mojom/ax_node_data_mojom_traits_unittest.cc", "mojom/ax_tree_data_mojom_traits_unittest.cc", + "mojom/ax_tree_id_mojom_traits_unittest.cc", "mojom/ax_tree_update_mojom_traits_unittest.cc", "platform/ax_platform_node_unittest.cc", "platform/ax_platform_node_unittest.h",
diff --git a/ui/accessibility/ax_node_position_unittest.cc b/ui/accessibility/ax_node_position_unittest.cc index ba32352..55c0753 100644 --- a/ui/accessibility/ax_node_position_unittest.cc +++ b/ui/accessibility/ax_node_position_unittest.cc
@@ -201,7 +201,7 @@ initial_state.nodes.push_back(static_text2_); initial_state.nodes.push_back(inline_box2_); initial_state.has_tree_data = true; - initial_state.tree_data.tree_id = "0"; + initial_state.tree_data.tree_id = AXTreeID::FromString("0"); initial_state.tree_data.title = "Dialog title"; AXSerializableTree src_tree(initial_state);
diff --git a/ui/accessibility/ax_position.h b/ui/accessibility/ax_position.h index 06e18d2e..0f3e6296 100644 --- a/ui/accessibility/ax_position.h +++ b/ui/accessibility/ax_position.h
@@ -140,7 +140,7 @@ } else { str_child_index = base::IntToString(child_index_); } - str = "TreePosition tree_id=" + tree_id_ + + str = "TreePosition tree_id=" + tree_id_.ToString() + " anchor_id=" + base::IntToString(anchor_id_) + " child_index=" + str_child_index; break; @@ -152,7 +152,7 @@ } else { str_text_offset = base::IntToString(text_offset_); } - str = "TextPosition tree_id=" + tree_id_ + + str = "TextPosition tree_id=" + tree_id_.ToString() + " anchor_id=" + base::IntToString(anchor_id_) + " text_offset=" + str_text_offset + " affinity=" + ui::ToString(static_cast<ax::mojom::TextAffinity>(affinity_));
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc index ad7b835..648a3f3 100644 --- a/ui/accessibility/ax_tree.cc +++ b/ui/accessibility/ax_tree.cc
@@ -722,17 +722,20 @@ if (attr == ax::mojom::StringAttribute::kChildTreeId) { // Remove old_string -> id from the map, and clear map keys if // their values are now empty. - if (child_tree_id_reverse_map_.find(old_string) != + AXTreeID old_ax_tree_id = AXTreeID::FromString(old_string); + if (child_tree_id_reverse_map_.find(old_ax_tree_id) != child_tree_id_reverse_map_.end()) { - child_tree_id_reverse_map_[old_string].erase(id); - if (child_tree_id_reverse_map_[old_string].empty()) - child_tree_id_reverse_map_.erase(old_string); + child_tree_id_reverse_map_[old_ax_tree_id].erase(id); + if (child_tree_id_reverse_map_[old_ax_tree_id].empty()) + child_tree_id_reverse_map_.erase(old_ax_tree_id); } // Add new_string -> id to the map, unless new_id is zero indicating that // we're only removing a relation. - if (!new_string.empty()) - child_tree_id_reverse_map_[new_string].insert(id); + if (!new_string.empty()) { + AXTreeID new_ax_tree_id = AXTreeID::FromString(new_string); + child_tree_id_reverse_map_[new_ax_tree_id].insert(id); + } } };
diff --git a/ui/accessibility/ax_tree_combiner.cc b/ui/accessibility/ax_tree_combiner.cc index 00ea20fd..b0ab36fa 100644 --- a/ui/accessibility/ax_tree_combiner.cc +++ b/ui/accessibility/ax_tree_combiner.cc
@@ -17,7 +17,7 @@ void AXTreeCombiner::AddTree(const AXTreeUpdate& tree, bool is_root) { trees_.push_back(tree); if (is_root) { - DCHECK_EQ(root_tree_id_, ""); + DCHECK_EQ(root_tree_id_, AXTreeIDUnknown()); root_tree_id_ = tree.tree_data.tree_id; } } @@ -80,8 +80,8 @@ AXTreeID tree_id = tree->tree_data.tree_id; for (size_t i = 0; i < tree->nodes.size(); ++i) { AXNodeData node = tree->nodes[i]; - AXTreeID child_tree_id = - node.GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId); + AXTreeID child_tree_id = AXTreeID::FromString( + node.GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId)); // Map the node's ID. node.id = MapId(tree_id, node.id);
diff --git a/ui/accessibility/ax_tree_combiner_unittest.cc b/ui/accessibility/ax_tree_combiner_unittest.cc index 8272ce27..5e8d1dc 100644 --- a/ui/accessibility/ax_tree_combiner_unittest.cc +++ b/ui/accessibility/ax_tree_combiner_unittest.cc
@@ -10,7 +10,7 @@ TEST(CombineAXTreesTest, RenumberOneTree) { AXTreeUpdate tree; tree.has_tree_data = true; - tree.tree_data.tree_id = "1"; + tree.tree_data.tree_id = ui::AXTreeID::FromString("1"); tree.root_id = 2; tree.nodes.resize(3); tree.nodes[0].id = 2; @@ -39,7 +39,7 @@ AXTreeUpdate parent_tree; parent_tree.root_id = 1; parent_tree.has_tree_data = true; - parent_tree.tree_data.tree_id = "1"; + parent_tree.tree_data.tree_id = ui::AXTreeID::FromString("1"); parent_tree.nodes.resize(3); parent_tree.nodes[0].id = 1; parent_tree.nodes[0].child_ids.push_back(2); @@ -54,8 +54,8 @@ AXTreeUpdate child_tree; child_tree.root_id = 1; child_tree.has_tree_data = true; - child_tree.tree_data.parent_tree_id = "1"; - child_tree.tree_data.tree_id = "2"; + child_tree.tree_data.parent_tree_id = ui::AXTreeID::FromString("1"); + child_tree.tree_data.tree_id = ui::AXTreeID::FromString("2"); child_tree.nodes.resize(3); child_tree.nodes[0].id = 1; child_tree.nodes[0].child_ids.push_back(2); @@ -97,7 +97,7 @@ AXTreeUpdate tree; tree.has_tree_data = true; - tree.tree_data.tree_id = "1"; + tree.tree_data.tree_id = ui::AXTreeID::FromString("1"); tree.root_id = 11; tree.nodes.resize(2); tree.nodes[0].id = 11; @@ -157,8 +157,8 @@ TEST(CombineAXTreesTest, FocusedTree) { AXTreeUpdate parent_tree; parent_tree.has_tree_data = true; - parent_tree.tree_data.tree_id = "1"; - parent_tree.tree_data.focused_tree_id = "2"; + parent_tree.tree_data.tree_id = ui::AXTreeID::FromString("1"); + parent_tree.tree_data.focused_tree_id = ui::AXTreeID::FromString("2"); parent_tree.tree_data.focus_id = 2; parent_tree.root_id = 1; parent_tree.nodes.resize(3); @@ -174,8 +174,8 @@ AXTreeUpdate child_tree; child_tree.has_tree_data = true; - child_tree.tree_data.parent_tree_id = "1"; - child_tree.tree_data.tree_id = "2"; + child_tree.tree_data.parent_tree_id = ui::AXTreeID::FromString("1"); + child_tree.tree_data.tree_id = ui::AXTreeID::FromString("2"); child_tree.tree_data.focus_id = 3; child_tree.root_id = 1; child_tree.nodes.resize(3);
diff --git a/ui/accessibility/ax_tree_data.cc b/ui/accessibility/ax_tree_data.cc index 1e69b36b..ec452ba 100644 --- a/ui/accessibility/ax_tree_data.cc +++ b/ui/accessibility/ax_tree_data.cc
@@ -23,12 +23,12 @@ std::string AXTreeData::ToString() const { std::string result; - if (!tree_id.empty()) - result += " tree_id=" + tree_id; - if (!parent_tree_id.empty()) - result += " parent_tree_id=" + parent_tree_id; - if (!focused_tree_id.empty()) - result += " focused_tree_id=" + focused_tree_id; + if (tree_id != AXTreeIDUnknown()) + result += " tree_id=" + tree_id.ToString(); + if (parent_tree_id != AXTreeIDUnknown()) + result += " parent_tree_id=" + parent_tree_id.ToString(); + if (focused_tree_id != AXTreeIDUnknown()) + result += " focused_tree_id=" + focused_tree_id.ToString(); if (!doctype.empty()) result += " doctype=" + doctype;
diff --git a/ui/accessibility/ax_tree_id.cc b/ui/accessibility/ax_tree_id.cc index bdd900e..6076f11 100644 --- a/ui/accessibility/ax_tree_id.cc +++ b/ui/accessibility/ax_tree_id.cc
@@ -4,17 +4,58 @@ #include "ui/accessibility/ax_tree_id.h" +#include <iostream> + #include "base/no_destructor.h" namespace ui { +AXTreeID::AXTreeID() : id_("") {} + +AXTreeID::AXTreeID(const std::string& string) : id_(string) {} + +// static +AXTreeID AXTreeID::FromString(const std::string& string) { + return AXTreeID(string); +} + +bool AXTreeID::operator==(const AXTreeID& rhs) const { + return id_ == rhs.id_; +} + +bool AXTreeID::operator!=(const AXTreeID& rhs) const { + return id_ != rhs.id_; +} + +bool AXTreeID::operator<(const AXTreeID& rhs) const { + return id_ < rhs.id_; +} + +bool AXTreeID::operator<=(const AXTreeID& rhs) const { + return id_ <= rhs.id_; +} + +bool AXTreeID::operator>(const AXTreeID& rhs) const { + return id_ > rhs.id_; +} + +bool AXTreeID::operator>=(const AXTreeID& rhs) const { + return id_ >= rhs.id_; +} + +std::ostream& operator<<(std::ostream& stream, const AXTreeID& value) { + return stream << 0; +} + const AXTreeID& AXTreeIDUnknown() { - static const base::NoDestructor<AXTreeID> ax_tree_id_unknown(""); + static const base::NoDestructor<AXTreeID> ax_tree_id_unknown( + AXTreeID::FromString("")); return *ax_tree_id_unknown; } const AXTreeID& DesktopAXTreeID() { - static const base::NoDestructor<AXTreeID> desktop_ax_tree_id("0"); + static const base::NoDestructor<AXTreeID> desktop_ax_tree_id( + AXTreeID::FromString("0")); return *desktop_ax_tree_id; }
diff --git a/ui/accessibility/ax_tree_id.h b/ui/accessibility/ax_tree_id.h index 29f8545..946181b 100644 --- a/ui/accessibility/ax_tree_id.h +++ b/ui/accessibility/ax_tree_id.h
@@ -9,11 +9,43 @@ #include "ui/accessibility/ax_export.h" +namespace mojo { +template <typename DataViewType, typename T> +struct StructTraits; +} + +namespace ax { +namespace mojom { +class AXTreeIDDataView; +} +} // namespace ax + namespace ui { -// Note: Originally AXTreeID was an integer. Temporarily we're making it a -// string with the plan to eventually make it a base::UnguessableToken. -using AXTreeID = std::string; +// A unique ID representing an accessibility tree. +class AX_EXPORT AXTreeID { + public: + AXTreeID(); + static AXTreeID FromString(const std::string& string); + const std::string& ToString() const { return id_; } + operator std::string() const { return id_; } + + bool operator==(const AXTreeID& rhs) const; + bool operator!=(const AXTreeID& rhs) const; + bool operator<(const AXTreeID& rhs) const; + bool operator<=(const AXTreeID& rhs) const; + bool operator>(const AXTreeID& rhs) const; + bool operator>=(const AXTreeID& rhs) const; + + private: + explicit AXTreeID(const std::string& string); + + friend struct mojo::StructTraits<ax::mojom::AXTreeIDDataView, ui::AXTreeID>; + + std::string id_; +}; + +AX_EXPORT std::ostream& operator<<(std::ostream& stream, const AXTreeID& value); // The value to use when an AXTreeID is unknown. AX_EXPORT extern const AXTreeID& AXTreeIDUnknown();
diff --git a/ui/accessibility/ax_tree_id_registry.cc b/ui/accessibility/ax_tree_id_registry.cc index 5fdf873..f0a47078 100644 --- a/ui/accessibility/ax_tree_id_registry.cc +++ b/ui/accessibility/ax_tree_id_registry.cc
@@ -21,7 +21,8 @@ if (it != frame_to_ax_tree_id_map_.end()) return it->second; - AXTreeID new_id = base::IntToString(++ax_tree_id_counter_); + AXTreeID new_id = + AXTreeID::FromString(base::IntToString(++ax_tree_id_counter_)); frame_to_ax_tree_id_map_[frame_id] = new_id; ax_tree_to_frame_id_map_[new_id] = frame_id; @@ -41,7 +42,8 @@ if (it.second == delegate) return it.first; } - AXTreeID new_id = base::IntToString(++ax_tree_id_counter_); + AXTreeID new_id = + AXTreeID::FromString(base::IntToString(++ax_tree_id_counter_)); id_to_host_delegate_[new_id] = delegate; return new_id; }
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc index 3b27d19..42d660a 100644 --- a/ui/accessibility/ax_tree_unittest.cc +++ b/ui/accessibility/ax_tree_unittest.cc
@@ -1435,14 +1435,17 @@ ax::mojom::StringAttribute::kChildTreeId, "93"); AXTree tree(initial_state); - auto child_tree_91_nodes = tree.GetNodeIdsForChildTreeId("91"); + auto child_tree_91_nodes = + tree.GetNodeIdsForChildTreeId(AXTreeID::FromString("91")); EXPECT_EQ(0U, child_tree_91_nodes.size()); - auto child_tree_92_nodes = tree.GetNodeIdsForChildTreeId("92"); + auto child_tree_92_nodes = + tree.GetNodeIdsForChildTreeId(AXTreeID::FromString("92")); EXPECT_EQ(1U, child_tree_92_nodes.size()); EXPECT_TRUE(base::ContainsKey(child_tree_92_nodes, 2)); - auto child_tree_93_nodes = tree.GetNodeIdsForChildTreeId("93"); + auto child_tree_93_nodes = + tree.GetNodeIdsForChildTreeId(AXTreeID::FromString("93")); EXPECT_EQ(2U, child_tree_93_nodes.size()); EXPECT_TRUE(base::ContainsKey(child_tree_93_nodes, 3)); EXPECT_TRUE(base::ContainsKey(child_tree_93_nodes, 4)); @@ -1455,12 +1458,14 @@ EXPECT_TRUE(tree.Unserialize(update)); - child_tree_92_nodes = tree.GetNodeIdsForChildTreeId("92"); + child_tree_92_nodes = + tree.GetNodeIdsForChildTreeId(AXTreeID::FromString("92")); EXPECT_EQ(2U, child_tree_92_nodes.size()); EXPECT_TRUE(base::ContainsKey(child_tree_92_nodes, 2)); EXPECT_TRUE(base::ContainsKey(child_tree_92_nodes, 3)); - child_tree_93_nodes = tree.GetNodeIdsForChildTreeId("93"); + child_tree_93_nodes = + tree.GetNodeIdsForChildTreeId(AXTreeID::FromString("93")); EXPECT_EQ(0U, child_tree_93_nodes.size()); }
diff --git a/ui/accessibility/mojom/BUILD.gn b/ui/accessibility/mojom/BUILD.gn index d41dbd6..ac10ca3 100644 --- a/ui/accessibility/mojom/BUILD.gn +++ b/ui/accessibility/mojom/BUILD.gn
@@ -12,6 +12,7 @@ "ax_host.mojom", "ax_node_data.mojom", "ax_tree_data.mojom", + "ax_tree_id.mojom", "ax_tree_update.mojom", ]
diff --git a/ui/accessibility/mojom/ax_action_data.mojom b/ui/accessibility/mojom/ax_action_data.mojom index 60de3978..f7e3238 100644 --- a/ui/accessibility/mojom/ax_action_data.mojom +++ b/ui/accessibility/mojom/ax_action_data.mojom
@@ -5,13 +5,14 @@ module ax.mojom; import "ui/accessibility/ax_enums.mojom"; +import "ui/accessibility/mojom/ax_tree_id.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; // A compact representation of an accessibility action and the arguments // associated with that action. See ui::AXActionData for full documentation. struct AXActionData { Action action; - string target_tree_id; + ax.mojom.AXTreeID target_tree_id; string source_extension_id; int32 target_node_id; int32 request_id;
diff --git a/ui/accessibility/mojom/ax_action_data_mojom_traits.h b/ui/accessibility/mojom/ax_action_data_mojom_traits.h index 933a73e..3a0b573 100644 --- a/ui/accessibility/mojom/ax_action_data_mojom_traits.h +++ b/ui/accessibility/mojom/ax_action_data_mojom_traits.h
@@ -7,6 +7,7 @@ #include "ui/accessibility/ax_action_data.h" #include "ui/accessibility/mojom/ax_action_data.mojom-shared.h" +#include "ui/accessibility/mojom/ax_tree_id_mojom_traits.h" #include "ui/gfx/geometry/mojo/geometry_struct_traits.h" namespace mojo { @@ -16,7 +17,7 @@ static ax::mojom::Action action(const ui::AXActionData& a) { return a.action; } - static const std::string& target_tree_id(const ui::AXActionData& a) { + static const ui::AXTreeID& target_tree_id(const ui::AXActionData& a) { return a.target_tree_id; } static const std::string& source_extension_id(const ui::AXActionData& a) {
diff --git a/ui/accessibility/mojom/ax_action_data_mojom_traits_unittest.cc b/ui/accessibility/mojom/ax_action_data_mojom_traits_unittest.cc index 120159a..68603e3 100644 --- a/ui/accessibility/mojom/ax_action_data_mojom_traits_unittest.cc +++ b/ui/accessibility/mojom/ax_action_data_mojom_traits_unittest.cc
@@ -17,7 +17,7 @@ TEST(AXActionDataMojomTraitsTest, RoundTrip) { ui::AXActionData input; input.action = ax::mojom::Action::kBlur; - input.target_tree_id = "1"; + input.target_tree_id = ui::AXTreeID::FromString("1"); input.source_extension_id = "extension_id"; input.target_node_id = 2; input.request_id = 3; @@ -37,7 +37,7 @@ SerializeAndDeserialize<ax::mojom::AXActionData>(&input, &output)); EXPECT_EQ(output.action, ax::mojom::Action::kBlur); - EXPECT_EQ(output.target_tree_id, "1"); + EXPECT_EQ(output.target_tree_id.ToString(), "1"); EXPECT_EQ(output.source_extension_id, "extension_id"); EXPECT_EQ(output.target_node_id, 2); EXPECT_EQ(output.request_id, 3);
diff --git a/ui/accessibility/mojom/ax_host.mojom b/ui/accessibility/mojom/ax_host.mojom index 23826d3..fde8570 100644 --- a/ui/accessibility/mojom/ax_host.mojom +++ b/ui/accessibility/mojom/ax_host.mojom
@@ -7,6 +7,7 @@ import "ui/accessibility/ax_enums.mojom"; import "ui/accessibility/mojom/ax_action_data.mojom"; import "ui/accessibility/mojom/ax_event.mojom"; +import "ui/accessibility/mojom/ax_tree_id.mojom"; import "ui/accessibility/mojom/ax_tree_update.mojom"; const string kAXHostServiceName = "ax_host_service"; @@ -23,12 +24,12 @@ // process must send its initial AX node tree immediately (because a feature // like ChromeVox is enabled). SetRemoteHost(AXRemoteHost remote) => - (string tree_id, bool automation_enabled); + (ax.mojom.AXTreeID tree_id, bool automation_enabled); // Handles an accessibility |event| (e.g. focus change) for |tree_id| in the // remote process. Includes |updates| to child nodes. HandleAccessibilityEvent( - string tree_id, array<AXTreeUpdate> updates, AXEvent event); + ax.mojom.AXTreeID tree_id, array<AXTreeUpdate> updates, AXEvent event); }; // Remote hosts run outside the browser process, for example in a mojo app like
diff --git a/ui/accessibility/mojom/ax_tree_data.mojom b/ui/accessibility/mojom/ax_tree_data.mojom index b02571f..c2fabbf2 100644 --- a/ui/accessibility/mojom/ax_tree_data.mojom +++ b/ui/accessibility/mojom/ax_tree_data.mojom
@@ -5,12 +5,13 @@ module ax.mojom; import "ui/accessibility/ax_enums.mojom"; +import "ui/accessibility/mojom/ax_tree_id.mojom"; // See ui::AXTreeData for comments / explanations of these fields. struct AXTreeData { - string tree_id; - string parent_tree_id; - string focused_tree_id; + ax.mojom.AXTreeID tree_id; + ax.mojom.AXTreeID parent_tree_id; + ax.mojom.AXTreeID focused_tree_id; string doctype; bool loaded; float loading_progress;
diff --git a/ui/accessibility/mojom/ax_tree_data_mojom_traits.h b/ui/accessibility/mojom/ax_tree_data_mojom_traits.h index 04b5a67..6beea97 100644 --- a/ui/accessibility/mojom/ax_tree_data_mojom_traits.h +++ b/ui/accessibility/mojom/ax_tree_data_mojom_traits.h
@@ -7,18 +7,19 @@ #include "ui/accessibility/ax_tree_data.h" #include "ui/accessibility/mojom/ax_tree_data.mojom-shared.h" +#include "ui/accessibility/mojom/ax_tree_id_mojom_traits.h" namespace mojo { template <> struct StructTraits<ax::mojom::AXTreeDataDataView, ui::AXTreeData> { - static const std::string& tree_id(const ui::AXTreeData& p) { + static const ui::AXTreeID& tree_id(const ui::AXTreeData& p) { return p.tree_id; } - static const std::string& parent_tree_id(const ui::AXTreeData& p) { + static const ui::AXTreeID& parent_tree_id(const ui::AXTreeData& p) { return p.parent_tree_id; } - static const std::string& focused_tree_id(const ui::AXTreeData& p) { + static const ui::AXTreeID& focused_tree_id(const ui::AXTreeData& p) { return p.focused_tree_id; } static const std::string& doctype(const ui::AXTreeData& p) {
diff --git a/ui/accessibility/mojom/ax_tree_data_mojom_traits_unittest.cc b/ui/accessibility/mojom/ax_tree_data_mojom_traits_unittest.cc index c9b134dc..d64ff2c 100644 --- a/ui/accessibility/mojom/ax_tree_data_mojom_traits_unittest.cc +++ b/ui/accessibility/mojom/ax_tree_data_mojom_traits_unittest.cc
@@ -12,9 +12,9 @@ TEST(AXTreeDataMojomTraitsTest, TestSerializeAndDeserializeAXTreeData) { ui::AXTreeData input, output; - input.tree_id = "1"; - input.parent_tree_id = "2"; - input.focused_tree_id = "3"; + input.tree_id = ui::AXTreeID::FromString("1"); + input.parent_tree_id = ui::AXTreeID::FromString("2"); + input.focused_tree_id = ui::AXTreeID::FromString("3"); input.doctype = "4"; input.loaded = true; input.loading_progress = 5; @@ -31,9 +31,9 @@ EXPECT_TRUE(SerializeAndDeserialize<ax::mojom::AXTreeData>(&input, &output)); - EXPECT_EQ("1", output.tree_id); - EXPECT_EQ("2", output.parent_tree_id); - EXPECT_EQ("3", output.focused_tree_id); + EXPECT_EQ("1", output.tree_id.ToString()); + EXPECT_EQ("2", output.parent_tree_id.ToString()); + EXPECT_EQ("3", output.focused_tree_id.ToString()); EXPECT_EQ("4", output.doctype); EXPECT_EQ(true, output.loaded); EXPECT_EQ(5, output.loading_progress);
diff --git a/ui/accessibility/mojom/ax_tree_id.mojom b/ui/accessibility/mojom/ax_tree_id.mojom new file mode 100644 index 0000000..6cc327b4 --- /dev/null +++ b/ui/accessibility/mojom/ax_tree_id.mojom
@@ -0,0 +1,10 @@ +// 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. + +module ax.mojom; + +struct AXTreeID { + // Eventually this may become a base::UnguessableToken. + string id; +};
diff --git a/ui/accessibility/mojom/ax_tree_id.typemap b/ui/accessibility/mojom/ax_tree_id.typemap new file mode 100644 index 0000000..034ddbe0 --- /dev/null +++ b/ui/accessibility/mojom/ax_tree_id.typemap
@@ -0,0 +1,15 @@ +# 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. + +mojom = "//ui/accessibility/mojom/ax_tree_id.mojom" +public_headers = [ "//ui/accessibility/ax_tree_id.h" ] +traits_headers = [ "//ui/accessibility/mojom/ax_tree_id_mojom_traits.h" ] +sources = [ + "ax_tree_id_mojom_traits.cc", + "ax_tree_id_mojom_traits.h", +] +public_deps = [ + "//ui/accessibility", +] +type_mappings = [ "ax.mojom.AXTreeID=ui::AXTreeID" ]
diff --git a/ui/accessibility/mojom/ax_tree_id_mojom_traits.cc b/ui/accessibility/mojom/ax_tree_id_mojom_traits.cc new file mode 100644 index 0000000..949b7db --- /dev/null +++ b/ui/accessibility/mojom/ax_tree_id_mojom_traits.cc
@@ -0,0 +1,18 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/accessibility/mojom/ax_tree_id_mojom_traits.h" + +namespace mojo { + +// static +bool StructTraits<ax::mojom::AXTreeIDDataView, ui::AXTreeID>::Read( + ax::mojom::AXTreeIDDataView data, + ui::AXTreeID* out) { + if (!data.ReadId(&out->id_)) + return false; + return true; +} + +} // namespace mojo
diff --git a/ui/accessibility/mojom/ax_tree_id_mojom_traits.h b/ui/accessibility/mojom/ax_tree_id_mojom_traits.h new file mode 100644 index 0000000..df481aa --- /dev/null +++ b/ui/accessibility/mojom/ax_tree_id_mojom_traits.h
@@ -0,0 +1,22 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_ACCESSIBILITY_MOJOM_AX_TREE_ID_MOJOM_TRAITS_H_ +#define UI_ACCESSIBILITY_MOJOM_AX_TREE_ID_MOJOM_TRAITS_H_ + +#include "ui/accessibility/ax_tree_id.h" +#include "ui/accessibility/mojom/ax_tree_id.mojom-shared.h" + +namespace mojo { + +template <> +struct StructTraits<ax::mojom::AXTreeIDDataView, ui::AXTreeID> { + static const std::string& id(const ui::AXTreeID& p) { return p.ToString(); } + + static bool Read(ax::mojom::AXTreeIDDataView data, ui::AXTreeID* out); +}; + +} // namespace mojo + +#endif // UI_ACCESSIBILITY_MOJOM_AX_TREE_ID_MOJOM_TRAITS_H_
diff --git a/ui/accessibility/mojom/ax_tree_id_mojom_traits_unittest.cc b/ui/accessibility/mojom/ax_tree_id_mojom_traits_unittest.cc new file mode 100644 index 0000000..3f0f4837 --- /dev/null +++ b/ui/accessibility/mojom/ax_tree_id_mojom_traits_unittest.cc
@@ -0,0 +1,18 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/accessibility/mojom/ax_tree_id_mojom_traits.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/accessibility/ax_tree_id.h" +#include "ui/accessibility/mojom/ax_tree_id.mojom.h" + +using mojo::test::SerializeAndDeserialize; + +TEST(AXTreeIDMojomTraitsTest, TestSerializeAndDeserializeAXTreeID) { + ui::AXTreeID input = ui::AXTreeID::FromString("abc"); + ui::AXTreeID output; + EXPECT_TRUE(SerializeAndDeserialize<ax::mojom::AXTreeID>(&input, &output)); + EXPECT_EQ("abc", output.ToString()); +}
diff --git a/ui/accessibility/mojom/typemaps.gni b/ui/accessibility/mojom/typemaps.gni index 0ed9a30f..ba8b1e1 100644 --- a/ui/accessibility/mojom/typemaps.gni +++ b/ui/accessibility/mojom/typemaps.gni
@@ -8,5 +8,6 @@ "//ui/accessibility/mojom/ax_event.typemap", "//ui/accessibility/mojom/ax_node_data.typemap", "//ui/accessibility/mojom/ax_tree_data.typemap", + "//ui/accessibility/mojom/ax_tree_id.typemap", "//ui/accessibility/mojom/ax_tree_update.typemap", ]
diff --git a/ui/accessibility/platform/aura_window_properties.cc b/ui/accessibility/platform/aura_window_properties.cc index efde64b..812b4c9 100644 --- a/ui/accessibility/platform/aura_window_properties.cc +++ b/ui/accessibility/platform/aura_window_properties.cc
@@ -9,6 +9,8 @@ DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AX_EXPORT, ax::mojom::Role) +DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AX_EXPORT, ui::AXTreeID*) + namespace ui { DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(ui::AXTreeID, kChildAXTreeID, nullptr);
diff --git a/ui/aura/window_targeter.cc b/ui/aura/window_targeter.cc index 997f66f5..4586197 100644 --- a/ui/aura/window_targeter.cc +++ b/ui/aura/window_targeter.cc
@@ -137,9 +137,12 @@ // This is used for bezel gesture events (eg. swiping in from screen edge). display::Display display = display::Screen::GetScreen()->GetDisplayNearestWindow(root_window); - const gfx::Point screen_location = - event.target() ? event.target()->GetScreenLocation(event) - : event.root_location(); + // The window target may be null, so use the root's ScreenPositionClient. + gfx::Point screen_location = event.root_location(); + if (client::GetScreenPositionClient(root_window)) { + client::GetScreenPositionClient(root_window) + ->ConvertPointToScreen(root_window, &screen_location); + } if (!display.bounds().Contains(screen_location)) return root_window; }
diff --git a/ui/base/material_design/material_design_controller.cc b/ui/base/material_design/material_design_controller.cc index fb2cd53..03a88a7 100644 --- a/ui/base/material_design/material_design_controller.cc +++ b/ui/base/material_design/material_design_controller.cc
@@ -42,13 +42,6 @@ namespace ui { namespace { -base::ObserverList<MaterialDesignControllerObserver>* GetObservers() { - static base::NoDestructor< - base::ObserverList<MaterialDesignControllerObserver>> - observers; - return observers.get(); -} - #if defined(OS_CHROMEOS) // Whether to use touchable UI. @@ -174,18 +167,6 @@ } // static -void MaterialDesignController::AddObserver( - MaterialDesignControllerObserver* observer) { - GetObservers()->AddObserver(observer); -} - -// static -void MaterialDesignController::RemoveObserver( - MaterialDesignControllerObserver* observer) { - GetObservers()->RemoveObserver(observer); -} - -// static bool MaterialDesignController::IsTouchOptimizedUiEnabled() { return GetMode() == MATERIAL_TOUCH_OPTIMIZED || GetMode() == MATERIAL_TOUCH_REFRESH; @@ -227,6 +208,24 @@ } // static +MaterialDesignController* MaterialDesignController::GetInstance() { + static base::NoDestructor<MaterialDesignController> instance; + return instance.get(); +} + +void MaterialDesignController::AddObserver( + MaterialDesignControllerObserver* observer) { + observers_.AddObserver(observer); +} + +void MaterialDesignController::RemoveObserver( + MaterialDesignControllerObserver* observer) { + observers_.RemoveObserver(observer); +} + +MaterialDesignController::MaterialDesignController() = default; + +// static void MaterialDesignController::Uninitialize() { is_mode_initialized_ = false; } @@ -236,8 +235,8 @@ if (!is_mode_initialized_ || mode_ != mode) { is_mode_initialized_ = true; mode_ = mode; - for (auto& observer : *GetObservers()) - observer.OnModeChanged(); + for (auto& observer : GetInstance()->observers_) + observer.OnMdModeChanged(); } }
diff --git a/ui/base/material_design/material_design_controller.h b/ui/base/material_design/material_design_controller.h index 6a9086d..5986738 100644 --- a/ui/base/material_design/material_design_controller.h +++ b/ui/base/material_design/material_design_controller.h
@@ -6,8 +6,14 @@ #define UI_BASE_MATERIAL_DESIGN_MATERIAL_DESIGN_CONTROLLER_H_ #include "base/macros.h" +#include "base/observer_list.h" #include "ui/base/ui_base_export.h" +namespace base { +template <typename T> +class NoDestructor; +} + namespace ui { class MaterialDesignControllerObserver; @@ -40,10 +46,6 @@ // Get the current Mode that should be used by the system. static Mode GetMode(); - static void AddObserver(MaterialDesignControllerObserver* observer); - - static void RemoveObserver(MaterialDesignControllerObserver* observer); - // Returns true if the touch-optimized UI material design mode is enabled. static bool IsTouchOptimizedUiEnabled(); @@ -61,9 +63,20 @@ static bool is_mode_initialized() { return is_mode_initialized_; } + static MaterialDesignController* GetInstance(); + + void AddObserver(MaterialDesignControllerObserver* observer); + + void RemoveObserver(MaterialDesignControllerObserver* observer); + private: + friend class base::NoDestructor<MaterialDesignController>; friend class test::MaterialDesignControllerTestAPI; + MaterialDesignController(); + + ~MaterialDesignController() = delete; + // Resets the initialization state to uninitialized. To be used by tests to // allow calling Initialize() more than once. static void Uninitialize(); @@ -84,6 +97,8 @@ // MATERIAL_TOUCH_REFRESH depending on the tablet state. static bool is_refresh_dynamic_ui_; + base::ObserverList<MaterialDesignControllerObserver> observers_; + DISALLOW_COPY_AND_ASSIGN(MaterialDesignController); };
diff --git a/ui/base/material_design/material_design_controller_observer.h b/ui/base/material_design/material_design_controller_observer.h index 2341461..5b7eba4 100644 --- a/ui/base/material_design/material_design_controller_observer.h +++ b/ui/base/material_design/material_design_controller_observer.h
@@ -13,7 +13,7 @@ class UI_BASE_EXPORT MaterialDesignControllerObserver : public base::CheckedObserver { public: - virtual void OnModeChanged() = 0; + virtual void OnMdModeChanged() = 0; protected: ~MaterialDesignControllerObserver() override {}
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index 76f70cf..b2e5e4c 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -153,14 +153,6 @@ bool HostWindowsInAppShimProcess() { return base::FeatureList::IsEnabled(kHostWindowsInAppShimProcess); } - -#if BUILDFLAG(MAC_VIEWS_BROWSER) -bool IsViewsBrowserCocoa() { - // TODO(https://crbug.com/832676): Delete all code guarded on this function - // returning true and then remove this function. - return false; -} -#endif // BUILDFLAG(MAC_VIEWS_BROWSER) #endif // defined(OS_MACOSX) const base::Feature kEnableOzoneDrmMojo = {"OzoneDrmMojo",
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h index 45936e1..a6e11f37 100644 --- a/ui/base/ui_base_features.h +++ b/ui/base/ui_base_features.h
@@ -73,14 +73,6 @@ // Returns true if the NSWindows for apps will be created in the app's process, // and will forward input to the browser process. UI_BASE_EXPORT bool HostWindowsInAppShimProcess(); - -#if BUILDFLAG(MAC_VIEWS_BROWSER) -// Returns whether a Views-capable browser build should use the Cocoa browser -// UI. Always returns false. -// TODO(https://crbug.com/832676): Delete all code guarded on this function -// returning true and then remove this function. -UI_BASE_EXPORT bool IsViewsBrowserCocoa(); -#endif // BUILDFLAG(MAC_VIEWS_BROWSER) #endif // defined(OS_MACOSX) // Use mojo communication in the drm platform instead of paramtraits. Remove
diff --git a/ui/gfx/codec/chromeos/jpeg_codec_robust_slow.cc b/ui/gfx/codec/chromeos/jpeg_codec_robust_slow.cc index 1ab3208d..9ffc036 100644 --- a/ui/gfx/codec/chromeos/jpeg_codec_robust_slow.cc +++ b/ui/gfx/codec/chromeos/jpeg_codec_robust_slow.cc
@@ -139,26 +139,12 @@ } #endif // !defined(JCS_EXTENSIONS) -// This class destroys the given jpeg_decompress object when it goes out of -// scope. It simplifies the error handling in Decode (and even applies to the -// success case). -class IjgDecompressDestroyer { - public: - IjgDecompressDestroyer() : cinfo_(NULL) {} - ~IjgDecompressDestroyer() { DestroyManagedObject(); } - void SetManagedObject(jpeg_decompress_struct* ci) { - DestroyManagedObject(); - cinfo_ = ci; +// jpeg_decompress_struct Deleter. +struct JpegDecompressStructDeleter { + void operator()(jpeg_decompress_struct* ptr) { + jpeg_destroy_decompress(ptr); + delete ptr; } - void DestroyManagedObject() { - if (cinfo_) { - jpeg_destroy_decompress(cinfo_); - cinfo_ = NULL; - } - } - - private: - jpeg_decompress_struct* cinfo_; }; } // namespace @@ -169,28 +155,26 @@ std::vector<unsigned char>* output, int* w, int* h) { - jpeg_decompress_struct cinfo; - IjgDecompressDestroyer destroyer; - destroyer.SetManagedObject(&cinfo); + std::unique_ptr<jpeg_decompress_struct, JpegDecompressStructDeleter> cinfo( + new jpeg_decompress_struct); output->clear(); // We set up the normal JPEG error routines, then override error_exit. // This must be done before the call to create_decompress. IjgCoderErrorMgr errmgr; - cinfo.err = jpeg_std_error(&errmgr.pub); + cinfo->err = jpeg_std_error(&errmgr.pub); errmgr.pub.error_exit = IjgErrorExit; // Establish the setjmp return context for IjgErrorExit to use. if (setjmp(errmgr.setjmp_buffer)) { // If we get here, the JPEG code has signaled an error. - // See note in JPEGCodec::Encode() for why we need to destroy the cinfo - // manually here. - destroyer.DestroyManagedObject(); + // Release |cinfo| by hand to avoid use-after-free of |errmgr|. + cinfo.reset(); return false; } // The destroyer will destroy() cinfo on exit. We don't want to set the // destroyer's object until cinfo is initialized. - jpeg_create_decompress(&cinfo); + jpeg_create_decompress(cinfo.get()); // set up the source manager jpeg_source_mgr srcmgr; @@ -199,17 +183,17 @@ srcmgr.skip_input_data = IjgSkipInputData; srcmgr.resync_to_restart = jpeg_resync_to_restart; // use default routine srcmgr.term_source = IjgTermSource; - cinfo.src = &srcmgr; + cinfo->src = &srcmgr; IjgJpegDecoderState state(input, input_size); - cinfo.client_data = &state; + cinfo->client_data = &state; // fill the file metadata into our buffer - if (jpeg_read_header(&cinfo, true) != JPEG_HEADER_OK) + if (jpeg_read_header(cinfo.get(), true) != JPEG_HEADER_OK) return false; // we want to always get RGB data out - switch (cinfo.jpeg_color_space) { + switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: case JCS_RGB: case JCS_YCbCr: @@ -219,24 +203,22 @@ // used by Chromium (i.e. RGB, RGBA, and BGRA) and we just map the input // parameters to a colorspace. if (format == FORMAT_RGB) { - cinfo.out_color_space = JCS_RGB; - cinfo.output_components = 3; + cinfo->out_color_space = JCS_RGB; + cinfo->output_components = 3; } else if (format == FORMAT_RGBA || (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) { - cinfo.out_color_space = JCS_EXT_RGBX; - cinfo.output_components = 4; + cinfo->out_color_space = JCS_EXT_RGBX; + cinfo->output_components = 4; } else if (format == FORMAT_BGRA || (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) { - cinfo.out_color_space = JCS_EXT_BGRX; - cinfo.output_components = 4; + cinfo->out_color_space = JCS_EXT_BGRX; + cinfo->output_components = 4; } else { - // We can exit this function without calling jpeg_destroy_decompress() - // because IjgDecompressDestroyer automaticaly calls it. NOTREACHED() << "Invalid pixel format"; return false; } #else - cinfo.out_color_space = JCS_RGB; + cinfo->out_color_space = JCS_RGB; #endif break; case JCS_CMYK: @@ -248,39 +230,39 @@ return false; } #ifndef JCS_EXTENSIONS - cinfo.output_components = 3; + cinfo->output_components = 3; #endif - jpeg_calc_output_dimensions(&cinfo); - *w = cinfo.output_width; - *h = cinfo.output_height; + jpeg_calc_output_dimensions(cinfo.get()); + *w = cinfo->output_width; + *h = cinfo->output_height; - jpeg_start_decompress(&cinfo); + jpeg_start_decompress(cinfo.get()); // FIXME(brettw) we may want to allow the capability for callers to request // how to align row lengths as we do for the compressor. - int row_read_stride = cinfo.output_width * cinfo.output_components; + int row_read_stride = cinfo->output_width * cinfo->output_components; #ifdef JCS_EXTENSIONS // Create memory for a decoded image and write decoded lines to the memory // without conversions same as JPEGCodec::Encode(). int row_write_stride = row_read_stride; - output->resize(row_write_stride * cinfo.output_height); + output->resize(row_write_stride * cinfo->output_height); - for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) { + for (int row = 0; row < static_cast<int>(cinfo->output_height); row++) { unsigned char* rowptr = &(*output)[row * row_write_stride]; - if (!jpeg_read_scanlines(&cinfo, &rowptr, 1)) + if (!jpeg_read_scanlines(cinfo.get(), &rowptr, 1)) return false; } #else if (format == FORMAT_RGB) { // easy case, row needs no conversion int row_write_stride = row_read_stride; - output->resize(row_write_stride * cinfo.output_height); + output->resize(row_write_stride * cinfo->output_height); - for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) { + for (int row = 0; row < static_cast<int>(cinfo->output_height); row++) { unsigned char* rowptr = &(*output)[row * row_write_stride]; - if (!jpeg_read_scanlines(&cinfo, &rowptr, 1)) + if (!jpeg_read_scanlines(cinfo.get(), &rowptr, 1)) return false; } } else { @@ -291,33 +273,32 @@ void (*converter)(const unsigned char* rgb, int w, unsigned char* out); if (format == FORMAT_RGBA || (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) { - row_write_stride = cinfo.output_width * 4; + row_write_stride = cinfo->output_width * 4; converter = AddAlpha; } else if (format == FORMAT_BGRA || (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) { - row_write_stride = cinfo.output_width * 4; + row_write_stride = cinfo->output_width * 4; converter = RGBtoBGRA; } else { NOTREACHED() << "Invalid pixel format"; - jpeg_destroy_decompress(&cinfo); + jpeg_destroy_decompress(cinfo.get()); return false; } - output->resize(row_write_stride * cinfo.output_height); + output->resize(row_write_stride * cinfo->output_height); std::unique_ptr<unsigned char[]> row_data( new unsigned char[row_read_stride]); unsigned char* rowptr = row_data.get(); - for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) { - if (!jpeg_read_scanlines(&cinfo, &rowptr, 1)) + for (int row = 0; row < static_cast<int>(cinfo->output_height); row++) { + if (!jpeg_read_scanlines(cinfo.get(), &rowptr, 1)) return false; converter(rowptr, *w, &(*output)[row * row_write_stride]); } } #endif - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); + jpeg_finish_decompress(cinfo.get()); return true; }
diff --git a/ui/gfx/codec/jpeg_codec.cc b/ui/gfx/codec/jpeg_codec.cc index 28a8262..b03dc8f9 100644 --- a/ui/gfx/codec/jpeg_codec.cc +++ b/ui/gfx/codec/jpeg_codec.cc
@@ -150,31 +150,14 @@ // "Terminate source --- called by jpeg_finish_decompress() after all data has // been read to clean up JPEG source manager. NOT called by jpeg_abort() or // jpeg_destroy()." -void TermSource(j_decompress_ptr cinfo) { -} +void TermSource(j_decompress_ptr cinfo) {} -// This class destroys the given jpeg_decompress object when it goes out of -// scope. It simplifies the error handling in Decode (and even applies to the -// success case). -class DecompressDestroyer { - public: - DecompressDestroyer() : cinfo_(NULL) { +// jpeg_decompress_struct Deleter. +struct JpegDecompressStructDeleter { + void operator()(jpeg_decompress_struct* ptr) { + jpeg_destroy_decompress(ptr); + delete ptr; } - ~DecompressDestroyer() { - DestroyManagedObject(); - } - void SetManagedObject(jpeg_decompress_struct* ci) { - DestroyManagedObject(); - cinfo_ = ci; - } - void DestroyManagedObject() { - if (cinfo_) { - jpeg_destroy_decompress(cinfo_); - cinfo_ = NULL; - } - } - private: - jpeg_decompress_struct* cinfo_; }; } // namespace @@ -182,28 +165,26 @@ bool JPEGCodec::Decode(const unsigned char* input, size_t input_size, ColorFormat format, std::vector<unsigned char>* output, int* w, int* h) { - jpeg_decompress_struct cinfo; - DecompressDestroyer destroyer; - destroyer.SetManagedObject(&cinfo); + std::unique_ptr<jpeg_decompress_struct, JpegDecompressStructDeleter> cinfo( + new jpeg_decompress_struct); output->clear(); // We set up the normal JPEG error routines, then override error_exit. - // This must be done before the call to create_decompress. + // This must be done before the call to jpeg_create_decompress. CoderErrorMgr errmgr; - cinfo.err = jpeg_std_error(&errmgr.pub); + cinfo->err = jpeg_std_error(&errmgr.pub); errmgr.pub.error_exit = ErrorExit; // Establish the setjmp return context for ErrorExit to use. if (setjmp(errmgr.setjmp_buffer)) { // If we get here, the JPEG code has signaled an error. - // See note in JPEGCodec::Encode() for why we need to destroy the cinfo - // manually here. - destroyer.DestroyManagedObject(); + // Release |cinfo| by hand to avoid use-after-free of |errmgr|. + cinfo.reset(); return false; } // The destroyer will destroy() cinfo on exit. We don't want to set the // destroyer's object until cinfo is initialized. - jpeg_create_decompress(&cinfo); + jpeg_create_decompress(cinfo.get()); // set up the source manager jpeg_source_mgr srcmgr; @@ -212,17 +193,17 @@ srcmgr.skip_input_data = SkipInputData; srcmgr.resync_to_restart = jpeg_resync_to_restart; // use default routine srcmgr.term_source = TermSource; - cinfo.src = &srcmgr; + cinfo->src = &srcmgr; JpegDecoderState state(input, input_size); - cinfo.client_data = &state; + cinfo->client_data = &state; // fill the file metadata into our buffer - if (jpeg_read_header(&cinfo, true) != JPEG_HEADER_OK) + if (jpeg_read_header(cinfo.get(), true) != JPEG_HEADER_OK) return false; // we want to always get RGB data out - switch (cinfo.jpeg_color_space) { + switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: case JCS_RGB: case JCS_YCbCr: @@ -232,15 +213,13 @@ // parameters to a colorspace. if (format == FORMAT_RGBA || (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) { - cinfo.out_color_space = JCS_EXT_RGBX; - cinfo.output_components = 4; + cinfo->out_color_space = JCS_EXT_RGBX; + cinfo->output_components = 4; } else if (format == FORMAT_BGRA || (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) { - cinfo.out_color_space = JCS_EXT_BGRX; - cinfo.output_components = 4; + cinfo->out_color_space = JCS_EXT_BGRX; + cinfo->output_components = 4; } else { - // We can exit this function without calling jpeg_destroy_decompress() - // because DecompressDestroyer automaticaly calls it. NOTREACHED() << "Invalid pixel format"; return false; } @@ -254,29 +233,28 @@ return false; } - jpeg_calc_output_dimensions(&cinfo); - *w = cinfo.output_width; - *h = cinfo.output_height; + jpeg_calc_output_dimensions(cinfo.get()); + *w = cinfo->output_width; + *h = cinfo->output_height; - jpeg_start_decompress(&cinfo); + jpeg_start_decompress(cinfo.get()); // FIXME(brettw) we may want to allow the capability for callers to request // how to align row lengths as we do for the compressor. - int row_read_stride = cinfo.output_width * cinfo.output_components; + int row_read_stride = cinfo->output_width * cinfo->output_components; // Create memory for a decoded image and write decoded lines to the memory // without conversions same as JPEGCodec::Encode(). int row_write_stride = row_read_stride; - output->resize(row_write_stride * cinfo.output_height); + output->resize(row_write_stride * cinfo->output_height); - for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) { + for (int row = 0; row < static_cast<int>(cinfo->output_height); row++) { unsigned char* rowptr = &(*output)[row * row_write_stride]; - if (!jpeg_read_scanlines(&cinfo, &rowptr, 1)) + if (!jpeg_read_scanlines(cinfo.get(), &rowptr, 1)) return false; } - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); + jpeg_finish_decompress(cinfo.get()); return true; }
diff --git a/ui/views/controls/image_view.cc b/ui/views/controls/image_view.cc index b1abacf..0c185578 100644 --- a/ui/views/controls/image_view.cc +++ b/ui/views/controls/image_view.cc
@@ -138,9 +138,17 @@ OnPaintImage(canvas); } +void ImageView::SetAccessibleName(const base::string16& accessible_name) { + accessible_name_ = accessible_name; +} + +base::string16 ImageView::GetAccessibleName() const { + return accessible_name_; +} + void ImageView::GetAccessibleNodeData(ui::AXNodeData* node_data) { node_data->role = ax::mojom::Role::kImage; - node_data->SetName(tooltip_text_); + node_data->SetName(accessible_name_); } const char* ImageView::GetClassName() const { @@ -169,8 +177,11 @@ return vertical_alignment_; } +// TODO(crbug.com/890465): Update the duplicate code here and in views::Button. void ImageView::SetTooltipText(const base::string16& tooltip) { tooltip_text_ = tooltip; + if (accessible_name_.empty()) + accessible_name_ = tooltip_text_; } base::string16 ImageView::GetTooltipText() const {
diff --git a/ui/views/controls/image_view.h b/ui/views/controls/image_view.h index c3adf65..b13e494 100644 --- a/ui/views/controls/image_view.h +++ b/ui/views/controls/image_view.h
@@ -73,6 +73,10 @@ void SetTooltipText(const base::string16& tooltip); base::string16 GetTooltipText() const; + // Set / Get the accessible name text. + void SetAccessibleName(const base::string16& name); + base::string16 GetAccessibleName() const; + // Overriden from View: void OnPaint(gfx::Canvas* canvas) override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; @@ -120,6 +124,9 @@ // The current tooltip text. base::string16 tooltip_text_; + // The current accessible name text. + base::string16 accessible_name_; + // Scale last painted at. float last_paint_scale_;
diff --git a/ui/views/mus/ax_remote_host_unittest.cc b/ui/views/mus/ax_remote_host_unittest.cc index dbdde9d..0ed0034 100644 --- a/ui/views/mus/ax_remote_host_unittest.cc +++ b/ui/views/mus/ax_remote_host_unittest.cc
@@ -46,15 +46,15 @@ void SetRemoteHost(ax::mojom::AXRemoteHostPtr client, SetRemoteHostCallback cb) override { ++add_client_count_; - const ui::AXTreeID tree_id("123"); + const ui::AXTreeID tree_id = ui::AXTreeID::FromString("123"); std::move(cb).Run(tree_id, automation_enabled_); client.FlushForTesting(); } - void HandleAccessibilityEvent(const std::string& tree_id, + void HandleAccessibilityEvent(const ui::AXTreeID& tree_id, const std::vector<ui::AXTreeUpdate>& updates, const ui::AXEvent& event) override { ++event_count_; - last_tree_id_ = ui::AXTreeID(tree_id); + last_tree_id_ = ui::AXTreeID::FromString(tree_id); last_updates_ = updates; last_event_ = event; }
diff --git a/ui/views/mus/ax_tree_source_mus.cc b/ui/views/mus/ax_tree_source_mus.cc index c84c1801..6199fb3c 100644 --- a/ui/views/mus/ax_tree_source_mus.cc +++ b/ui/views/mus/ax_tree_source_mus.cc
@@ -15,7 +15,7 @@ const ui::AXTreeID& tree_id) : root_(root), tree_id_(tree_id) { DCHECK(root_); - DCHECK(!tree_id_.empty()); + DCHECK_NE(tree_id_, ui::AXTreeIDUnknown()); } AXTreeSourceMus::~AXTreeSourceMus() = default;
diff --git a/ui/views/mus/ax_tree_source_mus_unittest.cc b/ui/views/mus/ax_tree_source_mus_unittest.cc index 9fbf307..b4fbdd5 100644 --- a/ui/views/mus/ax_tree_source_mus_unittest.cc +++ b/ui/views/mus/ax_tree_source_mus_unittest.cc
@@ -51,7 +51,7 @@ std::unique_ptr<Widget> widget_; Label* label_ = nullptr; // Owned by views hierarchy. - const ui::AXTreeID ax_tree_id_{"123"}; + const ui::AXTreeID ax_tree_id_ = ui::AXTreeID::FromString("123"); private: DISALLOW_COPY_AND_ASSIGN(AXTreeSourceMusTest);
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn b/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn index f59a915..9a329756 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn
@@ -13,20 +13,14 @@ ":mojo_api", ":multidevice_setup", ":multidevice_setup_browser_proxy", + ":multidevice_setup_delegate", ":setup_failed_page", ":setup_succeeded_page", ":start_setup_page", - ":ui_mode", ":ui_page_container_behavior", ] } -js_library("multidevice_setup_browser_proxy") { - deps = [ - "//ui/webui/resources/js:cr", - ] -} - js_library("button_bar") { } @@ -50,6 +44,9 @@ } js_library("mojo_api") { + deps = [ + "//ui/webui/resources/js:cr", + ] } js_library("multidevice_setup") { @@ -57,11 +54,11 @@ ":button_bar", ":fake_mojo_service", ":mojo_api", + ":multidevice_setup_delegate", ":password_page", ":setup_failed_page", ":setup_succeeded_page", ":start_setup_page", - ":ui_mode", "//ui/webui/resources/js:cr", ] @@ -79,6 +76,18 @@ ] } +js_library("multidevice_setup_browser_proxy") { + deps = [ + "//ui/webui/resources/js:cr", + ] +} + +js_library("multidevice_setup_delegate") { + deps = [ + "//ui/webui/resources/js:cr", + ] +} + js_library("password_page") { deps = [ ":multidevice_setup_browser_proxy", @@ -109,12 +118,6 @@ ] } -js_library("ui_mode") { - deps = [ - "//ui/webui/resources/js:cr", - ] -} - js_library("ui_page_container_behavior") { deps = [ "//ui/webui/resources/js:cr",
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.html b/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.html index e107dd2..b94fb43 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.html +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.html
@@ -1,36 +1,25 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<!-- TODO(jordynass): Implement OOBE style and make the visible style dependent -on the MultiDeviceSetup.uiMode property. --> <dom-module id="button-bar"> <template> <style include="multidevice-setup-shared"> :host { - @apply --layout-end-justified; - @apply --layout-horizontal; - } - - paper-button { - @apply --layout-center-center; - text-transform: none; + display: flex; + justify-content: flex-end; } </style> <div class="flex"></div> - <paper-button id="backward" + <div id="backward" on-click="onBackwardButtonClicked_" - class="cancel-button" - hidden$="[[!backwardButtonText]]"> - [[backwardButtonText]] - </paper-button> - <paper-button id="forward" + hidden$="[[backwardButtonHidden]]"> + <slot name="backward-button"></slot> + </div> + <div id="forward" on-click="onForwardButtonClicked_" - class="action-button" - disabled$="[[forwardButtonDisabled]]" - hidden$="[[!forwardButtonText]]"> - [[forwardButtonText]] + hidden$="[[forwardButtonHidden]]"> + <slot name="forward-button"></slot> </paper-button> </template> <script src="chrome://resources/cr_components/chromeos/multidevice_setup/button_bar.js">
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.js b/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.js index 455643b..536edae 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.js +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.js
@@ -10,30 +10,16 @@ is: 'button-bar', properties: { - /** - * Translated text to display on the forward-naviation button. Undefined if - * the visible page has no forward-navigation button. - * @type {string|undefined} - */ - forwardButtonText: { - type: String, - value: '', + /** Whether the forward button should be hidden. */ + forwardButtonHidden: { + type: Boolean, + value: false, }, - /** - * Whether the forward button should be disabled. - * @type {boolean} - */ - forwardButtonDisabled: {type: Boolean, value: false}, - - /** - * Translated text to display on the backward-naviation button. undefined if - * the visible page has no backward-navigation button. - * @type {string|undefined} - */ - backwardButtonText: { - type: String, - value: '', + /** Whether the backward button should be hidden. */ + backwardButtonHidden: { + type: Boolean, + value: false, }, },
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html index bf8f4c1..d45766b 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html
@@ -3,12 +3,12 @@ <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/button_bar.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/mojo_api.html"> +<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/password_page.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/setup_failed_page.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/setup_succeeded_page.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/start_setup_page.html"> -<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/ui_mode.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html"> @@ -35,22 +35,28 @@ <iron-pages attr-for-selected="is" selected="[[visiblePageName_]]" selected-item="{{visiblePage_}}"> - <password-page id="passwordPage" - auth-token="{{authToken_}}" - forward-button-disabled="{{passwordPageForwardButtonDisabled_}}" - password-field-valid="{{passwordFieldValid}}" - on-user-submitted-password="onUserSubmittedPassword_"> - </password-page> + <template is="dom-if" if="[[shouldPasswordPageBeIncluded_(delegate)]]" + restamp> + <password-page auth-token="{{authToken_}}" + forward-button-disabled="{{passwordPageForwardButtonDisabled_}}" + password-field-valid="{{passwordFieldValid}}" + on-user-submitted-password="onUserSubmittedPassword_"> + </password-page> + </template> <setup-failed-page></setup-failed-page> - <setup-succeeded-page></setup-succeeded-page> + <template is="dom-if" + if="[[shouldSetupSucceededPageBeIncluded_(delegate)]]" restamp> + <setup-succeeded-page></setup-succeeded-page> + </template> <start-setup-page devices="[[devices_]]" selected-device-id="{{selectedDeviceId_}}"> </start-setup-page> </iron-pages> <div class="flex"></div> - <button-bar forward-button-text="[[visiblePage_.forwardButtonText]]" - forward-button-disabled="[[forwardButtonDisabled_]]" - backward-button-text="[[visiblePage_.backwardButtonText]]"> + <button-bar forward-button-hidden="[[!forwardButtonText]]" + backward-button-hidden="[[!backwardButtonText]]"> + <slot name="backward-button" slot="backward-button"></slot> + <slot name="forward-button" slot="backward-button"></slot> </button-bar> </template> <script src="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js">
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js index ca9bd40..2b3a13e 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js
@@ -20,11 +20,38 @@ properties: { /** - * Indicates whether UI was opened during OOBE flow or afterward. - * - * @type {!multidevice_setup.UiMode} + * Delegate object which performs differently in OOBE vs. non-OOBE mode. + * @type {!multidevice_setup.MultiDeviceSetupDelegate} */ - uiMode: Number, + delegate: Object, + + /** + * Text to be shown on the forward navigation button. + * @type {string|undefined} + */ + forwardButtonText: { + type: String, + computed: 'getForwardButtonText_(visiblePage_)', + notify: true, + }, + + /** Whether the forward button should be disabled. */ + forwardButtonDisabled: { + type: Boolean, + computed: 'shouldForwardButtonBeDisabled_(' + + 'passwordPageForwardButtonDisabled_, visiblePageName_)', + notify: true + }, + + /** + * Text to be shown on the backward navigation button. + * @type {string|undefined} + */ + backwardButtonText: { + type: String, + computed: 'getBackwardButtonText_(visiblePage_)', + notify: true, + }, /** * Element name of the currently visible page. @@ -34,8 +61,7 @@ visiblePageName_: { type: String, value: PageName.START, - // For testing purporses only - notify: true, + notify: true, // For testing purporses only. }, /** @@ -80,16 +106,6 @@ passwordPageForwardButtonDisabled_: Boolean, /** - * Whether the forward button should be disabled. - * @private {boolean} - */ - forwardButtonDisabled_: { - type: Boolean, - computed: 'shouldForwardButtonBeDisabled_(' + - 'passwordPageForwardButtonDisabled_, visiblePageName_)', - }, - - /** * Interface to the MultiDeviceSetup Mojo service. * @private {!chromeos.multideviceSetup.mojom.MultiDeviceSetupImpl} */ @@ -145,45 +161,63 @@ this.visiblePageName_ = PageName.START; return; case PageName.PASSWORD: - this.$.passwordPage.clearPasswordTextInput(); - let deviceId = /** @type {string} */ (this.selectedDeviceId_); - this.multideviceSetup_.setHostDevice(deviceId, this.authToken_) - .then((responseParams) => { - if (!responseParams.success) { - console.warn( - 'Failure setting device with device ID: ' + - this.selectedDeviceId_); - return; - } - - switch (this.uiMode) { - case multidevice_setup.UiMode.OOBE: - this.exitSetupFlow_(); - return; - case multidevice_setup.UiMode.POST_OOBE: - this.visiblePageName_ = PageName.SUCCESS; - return; - } - }) - .catch((error) => { - console.warn('Mojo service failure: ' + error); - }); + this.$$('password-page').clearPasswordTextInput(); + this.setHostDevice_(); return; case PageName.SUCCESS: this.exitSetupFlow_(); return; case PageName.START: - this.visiblePageName_ = PageName.PASSWORD; + if (this.delegate.isPasswordRequiredToSetHost()) + this.visiblePageName_ = PageName.PASSWORD; + else + this.setHostDevice_(); return; } }, /** @private */ + setHostDevice_: function() { + // An authentication token must be set if a password is required. + assert(this.delegate.isPasswordRequiredToSetHost() == !!this.authToken_); + + let deviceId = /** @type {string} */ (this.selectedDeviceId_); + this.delegate.setHostDevice(deviceId, this.authToken_) + .then((responseParams) => { + if (!responseParams.success) { + console.warn('Failure setting host with device ID: ' + deviceId); + return; + } + + if (this.delegate.shouldExitSetupFlowAfterSettingHost()) { + this.exitSetupFlow_(); + return; + } + + this.visiblePageName_ = PageName.SUCCESS; + }) + .catch((error) => { + console.warn('Mojo service failure: ' + error); + }); + }, + + /** @private */ onUserSubmittedPassword_: function() { this.onForwardNavigationRequested_(); }, /** + * @return {string|undefined} The forward button text, which is undefined + * if no button should be displayed. + * @private + */ + getForwardButtonText_: function() { + if (!this.visiblePage_) + return undefined; + return this.visiblePage_.forwardButtonText; + }, + + /** * @return {boolean} Whether the forward button should be disabled. * @private */ @@ -193,12 +227,39 @@ }, /** + * @return {string|undefined} The backward button text, which is undefined + * if no button should be displayed. + * @private + */ + getBackwardButtonText_: function() { + if (!this.visiblePage_) + return undefined; + return this.visiblePage_.backwardButtonText; + + }, + + /** + * @return {boolean} + * @private + */ + shouldPasswordPageBeIncluded_: function() { + return this.delegate.isPasswordRequiredToSetHost(); + }, + + /** + * @return {boolean} + * @private + */ + shouldSetupSucceededPageBeIncluded_: function() { + return !this.delegate.shouldExitSetupFlowAfterSettingHost(); + }, + + /** * Notifies observers that the setup flow has completed. * * @private */ exitSetupFlow_: function() { - console.log('Exiting Setup Flow'); this.fire('setup-exited'); }, });
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_mode.html b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.html similarity index 76% rename from ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_mode.html rename to ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.html index 327e5a82..46ce0b9 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_mode.html +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.html
@@ -1,4 +1,4 @@ <link rel="import" href="chrome://resources/html/cr.html"> - -<script src="chrome://resources/cr_components/chromeos/multidevice_setup/ui_mode.js"> +<script src="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.js"> </script> +
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.js b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.js new file mode 100644 index 0000000..ee281f9 --- /dev/null +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.js
@@ -0,0 +1,30 @@ +// 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. + +cr.define('multidevice_setup', function() { + /** + * Interface which provides the ability to set the host device and perform + * related logic. + * @interface + */ + class MultiDeviceSetupDelegate { + /** @return {boolean} */ + isPasswordRequiredToSetHost() {} + + /** + * @param {string} hostDeviceId The ID of the host to set. + * @param {string=} opt_authToken An auth token to authenticate the request; + * only necessary if isPasswordRequiredToSetHost() returns true. + * @return {!Promise<{success: boolean}>} + */ + setHostDevice(hostDeviceId, opt_authToken) {} + + /** @return {boolean} */ + shouldExitSetupFlowAfterSettingHost() {} + } + + return { + MultiDeviceSetupDelegate: MultiDeviceSetupDelegate, + }; +});
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.html b/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.html index 388eeb25..b5c52c0 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.html +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.html
@@ -40,7 +40,7 @@ error-message="[[i18n('wrongPassword')]]" value="{{inputValue_}}" aria-disabled="false" - on-change="onUserPressedEnter_" + on-keypress="onInputKeypress_" autofocus> </cr-input> </div>
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.js b/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.js index 87c58da..fd84cd1 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.js +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.js
@@ -138,8 +138,15 @@ this.passwordInvalid_ = false; }, - /** @private */ - onUserPressedEnter_: function() { + /** + * @param {!Event} e + * @private + */ + onInputKeypress_: function(e) { + // We are only listening for the user trying to enter their password. + if (e.key != 'Enter') + return; + this.fire('user-submitted-password'); },
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_mode.js b/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_mode.js deleted file mode 100644 index 90b0abf..0000000 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_mode.js +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -cr.define('multidevice_setup', function() { - /** @enum {number} */ - const UiMode = { - OOBE: 1, - POST_OOBE: 2, - }; - - return { - UiMode: UiMode, - }; -});
diff --git a/ui/webui/resources/cr_components/cr_components_resources.grdp b/ui/webui/resources/cr_components/cr_components_resources.grdp index 25851f9..3bf1f1c 100644 --- a/ui/webui/resources/cr_components/cr_components_resources.grdp +++ b/ui/webui/resources/cr_components/cr_components_resources.grdp
@@ -280,6 +280,14 @@ file="cr_components/chromeos/multidevice_setup/multidevice_setup.js" type="chrome_html" compress="gzip" /> + <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_DELEGATE_HTML" + file="cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.html" + type="chrome_html" + compress="gzip" /> + <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_DELEGATE_JS" + file="cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.js" + type="chrome_html" + compress="gzip" /> <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_SHARED_CSS_HTML" file="cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html" type="chrome_html" @@ -316,14 +324,6 @@ file="cr_components/chromeos/multidevice_setup/start_setup_page.js" type="chrome_html" compress="gzip" /> - <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_UI_MODE_HTML" - file="cr_components/chromeos/multidevice_setup/ui_mode.html" - type="chrome_html" - compress="gzip" /> - <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_UI_MODE_JS" - file="cr_components/chromeos/multidevice_setup/ui_mode.js" - type="chrome_html" - compress="gzip" /> <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_UI_PAGE_CONTAINER_BEHAVIOR_HTML" file="cr_components/chromeos/multidevice_setup/ui_page_container_behavior.html" type="chrome_html"
diff --git a/ui/webui/resources/cr_elements/cr_slider/BUILD.gn b/ui/webui/resources/cr_elements/cr_slider/BUILD.gn index 78d6d47b..ad5d8f6 100644 --- a/ui/webui/resources/cr_elements/cr_slider/BUILD.gn +++ b/ui/webui/resources/cr_elements/cr_slider/BUILD.gn
@@ -12,6 +12,8 @@ js_library("cr_slider") { deps = [ - "//third_party/polymer/v1_0/components-chromium/paper-slider:paper-slider-extracted", + "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-ripple-behavior-extracted", + "//ui/webui/resources/js:cr", + "//ui/webui/resources/js:event_tracker", ] }
diff --git a/ui/webui/resources/cr_elements/cr_slider/cr_slider.html b/ui/webui/resources/cr_elements/cr_slider/cr_slider.html index 05adf45..a0a5253 100644 --- a/ui/webui/resources/cr_elements/cr_slider/cr_slider.html +++ b/ui/webui/resources/cr_elements/cr_slider/cr_slider.html
@@ -1,52 +1,199 @@ <link rel="import" href="../../html/polymer.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-behaviors/paper-ripple-behavior.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html"> +<link rel="import" href="../../html/cr.html"> +<link rel="import" href="../../html/event_tracker.html"> +<link rel="import" href="../hidden_style_css.html"> <link rel="import" href="../shared_vars_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-slider/paper-slider.html"> <dom-module id="cr-slider"> <template> - <style> - paper-slider { - --paper-slider-active-color: var(--google-blue-600); - --paper-slider-container-color: var(--google-blue-600-opacity-24); - --paper-slider-knob-color: var(--google-blue-600); - --paper-slider-knob-start-color: var(--google-blue-600); - --paper-slider-knob-start-border-color: var(--google-blue-600); - --paper-slider-pin-color: var(--google-blue-600); - --paper-slider-pin-start-color: var(--google-blue-600); - --paper-slider-markers-color: rgba(255, 255, 255, 0.54); - --paper-slider-disabled-active-color: var(--google-grey-600); - --paper-slider-disabled-knob-color: var(--google-grey-600); - width: 100%; - - --paper-slider-pin-text: { - font-family: Roboto; - font-size: 12px; - font-weight: 500; - line-height: 14px; - }; + <style include="cr-hidden-style"> + :host { + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + cursor: default; + user-select: none; } - :host-context([dir=rtl]) paper-slider { - --paper-slider-pin-text: { - font-family: Roboto; - font-size: 12px; - font-weight: 500; - line-height: 14px; - transform: scale(-1, 1) translate(0, -17px); - }; + :host([dragging]) { + touch-action: none; } - paper-slider[disabled] { - --paper-slider-container-color: var(--google-grey-600-opacity-24); + #container { + height: 32px; + position: relative; + } + + #barContainer { + background-color: var(--google-blue-600-opacity-24); + border-radius: 1px; + height: 2px; + margin: 0 16px; + position: absolute; + top: 15px; + width: calc(100% - 32px); + } + + #bar { + background-color: var(--google-blue-600); + border-radius: 1px; + height: 2px; + left: 0; + position: absolute; + transition: width 80ms ease; + width: 0; + } + + :host-context([dir=rtl]) #bar { + left: initial; + right: 0; + } + + #knobContainer { + margin-inline-start: 12px; + position: absolute; + top: 11px; + width: calc(100% - 32px); + } + + #knob { + background-color: var(--google-blue-600); + border: 0; + border-radius: 50%; + box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.4); + height: 10px; + margin-inline-start: 0; + outline: none; + position: absolute; + transition: margin-inline-start 80ms ease; + width: 10px; + } + + paper-ripple { + color: var(--google-blue-600); + height: 32px; + left: -11px; + pointer-events: none; + top: -11px; + transition: color linear 80ms; + width: 32px; + } + + :host-context([dir=rtl]) paper-ripple { + left: auto; + right: -11px; + } + + #markers { + left: 0; + pointer-events: none; + position: absolute; + right: 0; + top: 0; + @apply --layout-horizontal; + } + + .active-marker, + .inactive-marker { + @apply --layout-flex; + } + #markers::before, + #markers::after, + .active-marker::after, + .inactive-marker::after { + border-radius: 50%; + content: ''; + display: block; + height: 2px; + margin-left: -1px; + width: 2px; + } + + #markers::before, + .active-marker::after { + background-color: rgba(255, 255, 255, 0.54); + } + + #markers::after, + .inactive-marker::after { + background-color: rgba(26, 115, 232, 0.54); + } + + #labelContainer { + cursor: default; + margin-inline-start: 1px; + opacity: 0; + transition: opacity 80ms ease-in-out; + user-select: none; + width: calc(100% - 32px); + } + + #container:hover #labelContainer, + .hover #labelContainer, + :host([hold-down_]) #labelContainer { + opacity: 1; + } + + .label { + background: var(--google-blue-600); + border-radius: 14px; + bottom: 28px; + color: white; + font-size: 12px; + line-height: 1.5em; + padding: 0 8px; + position: absolute; + transition: margin-inline-start 80ms ease; + white-space: nowrap; + } + + :host([disabled]) { + pointer-events: none; + } + + :host([disabled]) #barContainer { + background-color: var(--google-grey-600-opacity-24); + } + + :host([disabled]) #bar { + background-color: var(--google-grey-600); + } + + :host([disabled]) inactive-marker::after, + :host([disabled]) #markers::after { + background-color: rgba(255, 255, 255, 0.54); + } + + :host([disabled]) #knobContainer { + margin-inline-start: 9px; + top: 9px; + } + :host([disabled]) #knob { + background-color: var(--google-grey-600); + border: 2px solid white; + box-shadow: unset; } </style> - <paper-slider id="slider" - disabled$="[[disabled]]" snaps="[[snaps]]" on-change="onChange_" - max="[[max]]" min="[[min]]" on-up="resetTrackLock_" value="{{value}}" - max-markers="[[maxMarkers]]" immediate-value="{{immediateValue}}" - dragging="{{dragging}}"> - </paper-slider> + <div id="container"> + <div id="barContainer"> + <div id="bar"></div> + <div id="markers" hidden$="[[!markerCount]]"> + <template is="dom-repeat" items="[[getMarkers_(markerCount)]]"> + <div class$="[[getMarkerClass_(index, value, min, max, + markerCount)]]"></div> + </template> + </div> + </div> + <div id="knobContainer"> + <div id="knob" tabindex="0"></div> + </div> + <div id="labelContainer" aria-label="[[label_]]"> + <div id="label" class="label"> + <div id="labelText">[[label_]]</div> + </div> + </div> + </div> </template> <script src="cr_slider.js"></script> </dom-module>
diff --git a/ui/webui/resources/cr_elements/cr_slider/cr_slider.js b/ui/webui/resources/cr_elements/cr_slider/cr_slider.js index 16180c12..609b8ed 100644 --- a/ui/webui/resources/cr_elements/cr_slider/cr_slider.js +++ b/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
@@ -3,148 +3,374 @@ // found in the LICENSE file. /** - * @fileoverview 'cr-slider' is a wrapper around paper-slider to alter the - * styling. The behavior of the slider remains the same. + * @fileoverview 'cr-slider' is a slider component used to select a number from + * a continuous or discrete range of numbers. */ -Polymer({ - is: 'cr-slider', - properties: { - min: Number, +cr.exportPath('cr_slider'); - max: Number, +/** + * The |value| is the corresponding value that the current slider tick is + * associated with. The string |label| is shown in the UI as the label for the + * current slider value. The |ariaValue| number is used for aria-valuemin, + * aria-valuemax, and aria-valuenow, and is optional. If missing, |value| will + * be used instead. + * @typedef {{ + * value: number, + * label: string, + * ariaValue: (number|undefined), + * }} + */ +cr_slider.SliderTick; - snaps: { - type: Boolean, - value: true, +(() => { + /** + * @param {number} min + * @param {number} max + * @param {number} value + * @return {number} + */ + function clamp(min, max, value) { + return Math.min(max, Math.max(min, value)); + } + + Polymer({ + is: 'cr-slider', + + behaviors: [ + Polymer.PaperRippleBehavior, + ], + + properties: { + disabled: { + type: Boolean, + value: false, + reflectToAttribute: true, + }, + + dragging: { + type: Boolean, + value: false, + reflectToAttribute: true, + }, + + markerCount: { + type: Number, + value: 0, + }, + + max: { + type: Number, + value: 100, + }, + + min: { + type: Number, + value: 0, + }, + + snaps: { + type: Boolean, + value: false, + }, + + /** + * The data associated with each tick on the slider. Each element in the + * array contains a value and the label corresponding to that value. + * @type {!Array<cr_slider.SliderTick>|!Array<number>} + */ + ticks: { + type: Array, + value: () => [], + observer: 'onTicksChanged_', + }, + + value: { + type: Number, + value: 0, + notify: true, + }, + + /** @private */ + holdDown_: { + type: Boolean, + value: false, + observer: 'onHoldDownChanged_', + reflectToAttribute: true, + }, + + /** @private */ + label_: { + type: String, + value: '', + }, }, - disabled: { - type: Boolean, - observer: 'onDisabledChanged_', + hostAttributes: { + role: 'slider', }, - value: Number, - maxMarkers: Number, + observers: [ + 'updateLabelAndAria_(value, min, max, ticks.*)', + 'updateKnobAndBar_(value, min, max)', + ], - immediateValue: { - type: Number, - observer: 'onImmediateValueChanged_', + listeners: { + focus: 'onFocus_', + blur: 'onBlur_', + keydown: 'onKeyDown_', + pointerdown: 'onPointerDown_', }, - dragging: Boolean, - }, + /** @private {Map<string, number>} */ + deltaKeyMap_: null, - listeners: { - 'focus': 'onFocus_', - 'blur': 'onBlur_', - 'keydown': 'onKeyDown_', - 'pointerdown': 'onPointerDown_', - 'pointerup': 'onPointerUp_', - }, + /** @private {boolean} */ + isRtl_: false, - /** @private {boolean} */ - usedMouse_: false, + /** @private {EventTracker} */ + draggingEventTracker_: null, - /** @override */ - attached: function() { - this.onDisabledChanged_(); - }, + /** @override */ + attached: function() { + this.isRtl_ = this.matches(':host-context([dir=rtl]) cr-slider'); + this.deltaKeyMap_ = new Map([ + ['ArrowDown', -1], + ['ArrowUp', 1], + ['PageDown', -1], + ['PageUp', 1], + ['ArrowLeft', this.isRtl_ ? 1 : -1], + ['ArrowRight', this.isRtl_ ? -1 : 1], + ]); + this.draggingEventTracker_ = new EventTracker(); + }, - /** @private */ - onFocus_: function() { - this.$.slider.getRipple().holdDown = true; - this.$.slider._expandKnob(); - }, + /** + * When markers are displayed on the slider, they are evenly spaced across + * the entire slider bar container and are rendered on top of the bar and + * bar container. The location of the marks correspond to the discrete + * values that the slider can have. + * @return {!Array} The array items have no type since this is used to + * create |markerCount| number of markers. + * @private + */ + getMarkers_: function() { + return new Array(Math.max(0, this.markerCount - 1)); + }, - /** @private */ - onBlur_: function() { - this.$.slider.getRipple().holdDown = false; - this.$.slider._resetKnob(); - }, + /** + * @param {number} index + * @return {string} + * @private + */ + getMarkerClass_: function(index) { + const currentStep = (this.markerCount - 1) * this.getRatio_(); + return index < currentStep ? 'active-marker' : 'inactive-marker'; + }, - /** @private */ - onChange_: function() { - this.$.slider._setExpand(!this.usedMouse_); - this.$.slider.getRipple().holdDown = !this.usedMouse_; - this.usedMouse_ = false; - }, + /** + * The ratio is a value from 0 to 1.0 corresponding to a location along the + * slider bar where 0 is the minimum value and 1.0 is the maximum value. + * This is a helper function used to calculate the bar width, knob location + * and label location. + * @return {number} + * @private + */ + getRatio_: function() { + const clamped = clamp(this.min, this.max, this.value); + this.value = this.snaps ? Math.round(clamped) : clamped; + return (this.value - this.min) / (this.max - this.min); + }, - /** @private */ - onKeyDown_: function() { - this.usedMouse_ = false; - if (!this.disabled) - this.onFocus_(); - }, + /** + * Removes all event listeners related to dragging, and cancels ripple. + * @param {number} pointerId + * @private + */ + stopDragging_: function(pointerId) { + this.dragging = false; + this.draggingEventTracker_.removeAll(); + // If there is a ripple animation in progress, setTimeout will hold off + // on updating |holdDown_|. + setTimeout(() => { + this.holdDown_ = false; + }); + this.releasePointerCapture(pointerId); + }, - /** - * @param {!MouseEvent} event - * @private - */ - onPointerDown_: function(event) { - if (this.disabled || event.button != 0) { - event.preventDefault(); - return; - } - this.usedMouse_ = true; - setTimeout(() => { - this.$.slider.getRipple().holdDown = true; - }); - }, + /** @private */ + onBlur_: function() { + this.holdDown_ = false; + }, - /** - * @param {!MouseEvent} event - * @private - */ - onPointerUp_: function(event) { - if (event.button != 0) - return; - this.$.slider.getRipple().holdDown = false; - }, + /** @private */ + onFocus_: function() { + this.holdDown_ = true; + }, - /** - * The style is being set in this way to keep the knob size the same - * regardless of the state or properties set in the paper-slider. paper-slider - * styles alter the size in multiple places making it difficult to introduce - * one or two mixins to override the existing paper-slider knob styling. - * @private - */ - onDisabledChanged_: function() { - const knob = this.$.slider.$$('.slider-knob-inner'); - knob.style.boxSizing = 'content-box'; - knob.style.height = '10px'; - knob.style.transform = 'unset'; - knob.style.transition = 'unset'; - knob.style.width = '10px'; - this.$.slider.$$('.bar-container').style.left = '0'; - if (this.disabled) { - knob.style.backgroundColor = 'var(--google-grey-600)'; - knob.style.border = '2px solid white'; - knob.style.boxShadow = 'unset'; - knob.style.margin = '9px'; - } else { - knob.style.backgroundColor = 'var(--google-blue-600)'; - knob.style.border = '0'; - knob.style.boxShadow = '0 1px 3px 0 rgba(0, 0, 0, 0.4)'; - knob.style.margin = '11px'; - } - }, + /** @private */ + onHoldDownChanged_: function() { + this.getRipple().holdDown = this.holdDown_; + }, - /** @private */ - onImmediateValueChanged_: function() { - // TODO(dpapad): Need to catch and refire the property changed event in - // Polymer 2 only, since it does not bubble by default. Remove the - // condition when migration to Polymer 2 is completed. - if (Polymer.DomIf) - this.fire('immediate-value-changed', this.immediateValue); - }, + /** + * @param {!Event} event + * @private + */ + onKeyDown_: function(event) { + if (this.disabled) + return; - /** - * TODO(scottchen): temporary fix until polymer gesture bug resolved. See: - * https://github.com/PolymerElements/paper-slider/issues/186 - * @private - */ - resetTrackLock_: function() { - Polymer.Gestures.gestures.tap.reset(); - }, -}); + if (event.metaKey || event.shiftKey || event.altKey || event.ctrlKey) + return; + + let handled = true; + if (event.key == 'Home') + this.value = this.min; + else if (event.key == 'End') + this.value = this.max; + else if (this.deltaKeyMap_.has(event.key)) { + const newValue = this.value + this.deltaKeyMap_.get(event.key); + this.value = clamp(this.min, this.max, newValue); + } else + handled = false; + + if (handled) { + event.preventDefault(); + setTimeout(() => { + this.holdDown_ = true; + }); + } + }, + + /** + * When the left-mouse button is pressed, the knob location is updated and + * dragging starts. + * @param {!PointerEvent} event + * @private + */ + onPointerDown_: function(event) { + if (this.disabled || event.buttons != 1 && event.pointerType == 'mouse') + return; + + this.dragging = true; + // If there is a ripple animation in progress, setTimeout will hold off on + // updating |holdDown_|. + setTimeout(() => { + this.$.knob.focus(); + this.holdDown_ = true; + }); + this.updateValueFromClientX_(event.clientX); + + this.setPointerCapture(event.pointerId); + const stopDragging = this.stopDragging_.bind(this, event.pointerId); + + this.draggingEventTracker_.add(this, 'pointermove', e => { + // If the left-button on the mouse is pressed by itself, then update. + // Otherwise stop capturing the mouse events because the drag operation + // is complete. + if (e.buttons != 1 && e.pointerType == 'mouse') { + stopDragging(); + return; + } + this.updateValueFromClientX_(e.clientX); + }); + this.draggingEventTracker_.add(this, 'pointercancel', stopDragging); + this.draggingEventTracker_.add(this, 'pointerdown', stopDragging); + this.draggingEventTracker_.add(this, 'pointerup', stopDragging); + this.draggingEventTracker_.add(this, 'keydown', e => { + if (e.key == 'Escape' || e.key == 'Tab') + stopDragging(); + }); + }, + + /** @private */ + onTicksChanged_: function() { + if (this.ticks.length == 0) { + this.disabled = false; + this.snaps = false; + } else if (this.ticks.length == 1) { + this.disabled = true; + } else { + this.disabled = false; + this.snaps = true; + this.max = this.ticks.length - 1; + this.min = 0; + } + }, + + /** @private */ + updateKnobAndBar_: function() { + const percent = `${this.getRatio_() * 100}%`; + this.$.bar.style.width = percent; + this.$.knob.style.marginInlineStart = percent; + }, + + /** @private */ + updateLabelAndAria_: function() { + const ticks = this.ticks; + const index = this.value; + if (!ticks || ticks.length == 0 || index >= ticks.length || + !Number.isInteger(index) || !this.snaps) { + this.setAttribute('aria-valuetext', this.value); + this.setAttribute('aria-valuemin', this.min); + this.setAttribute('aria-valuemax', this.max); + this.setAttribute('aria-valuenow', this.value); + return; + } + const tick = ticks[index]; + this.label_ = Number.isFinite(tick) ? '' : tick.label; + + // Update label location after it has been rendered. + this.async(() => { + const label = this.$.label; + const parentWidth = label.parentElement.offsetWidth; + const labelWidth = label.offsetWidth; + // The left and right margin are 16px. + const margin = 16; + const knobLocation = parentWidth * this.getRatio_() + margin; + const offsetStart = knobLocation - (labelWidth / 2); + // The label should be centered over the knob. Clamping the offset to a + // min and max value prevents the label from being cutoff. + const max = parentWidth + 2 * margin - labelWidth; + label.style.marginInlineStart = + `${Math.round(clamp(0, max, offsetStart))}px`; + }); + + const ariaValues = [tick, ticks[0], ticks[ticks.length - 1]].map(t => { + if (Number.isFinite(t)) + return t; + return Number.isFinite(t.ariaValue) ? t.ariaValue : t.value; + }); + this.setAttribute( + 'aria-valuetext', + this.label_.length > 0 ? this.label_ : ariaValues[0]); + this.setAttribute('aria-valuenow', ariaValues[0]); + this.setAttribute('aria-valuemin', ariaValues[1]); + this.setAttribute('aria-valuemax', ariaValues[2]); + }, + + /** + * @param {number} clientX + * @private + */ + updateValueFromClientX_: function(clientX) { + const rect = this.$.barContainer.getBoundingClientRect(); + let ratio = (clientX - rect.left) / rect.width; + if (this.isRtl_) + ratio = 1 - ratio; + const newValue = ratio * (this.max - this.min) + this.min; + const clamped = clamp(this.min, this.max, newValue); + this.value = this.snaps ? Math.round(clamped) : clamped; + }, + + _createRipple: function() { + this._rippleContainer = this.$.knob; + const ripple = Polymer.PaperRippleBehavior._createRipple(); + ripple.id = 'ink'; + ripple.setAttribute('recenters', ''); + ripple.classList.add('circle', 'toggle-ink'); + return ripple; + }, + }); +})();